From cd5ce661e2a8f9694933358ccb5b916fbed089c2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Aug 2009 21:49:39 -0600 Subject: add support for building Debian package --- .gbp.conf | 46 + ChangeLog | 2755 ++++++++++++++++++++++++++++++++++++++++++++ ao-tools/ao-load/ao-load.c | 4 - debian/altos.install | 3 + debian/changelog | 5 + debian/compat | 1 + debian/control | 17 + debian/copyright | 36 + debian/dirs | 3 + debian/docs | 2 + debian/menu | 2 + debian/repository | 2 + debian/rules | 78 ++ src/Makefile | 2 + 14 files changed, 2952 insertions(+), 4 deletions(-) create mode 100644 .gbp.conf create mode 100644 ChangeLog create mode 100644 debian/altos.install create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/menu create mode 100644 debian/repository create mode 100755 debian/rules diff --git a/.gbp.conf b/.gbp.conf new file mode 100644 index 00000000..9561fdfe --- /dev/null +++ b/.gbp.conf @@ -0,0 +1,46 @@ +# Configuration file for git-buildpackage and friends + +[DEFAULT] +# the default build command: +#builder = debuild -i\.git/ -I.git +# the default clean command: +cleaner = debian/rules prebuild && debuild clean +# the default branch for upstream sources: +upstream-branch = upstream +# the default branch for the debian patch: +debian-branch = master +# the default tag formats used: +#upstream-tag = upstream/%(version)s +#debian-tag = debian/%(version)s +# use pristine-tar: +pristine-tar = True + +# Options only affecting git-buildpackage +[git-buildpackage] +#upstream-branch = dfsgclean +# uncomment this to automatically GPG sign tags +#sign-tags = True +# keyid to GPG sign tags with +#keyid = 0xdeadbeef +# push to a remote repository after a successful tag: +posttag = git push --mirror +# use this for more svn-buildpackage like behaviour: +export-dir = ../build-area/altos/ +#tarball-dir = ../tarballs/ + +# Options only affecting git-import-orig +[git-import-orig] +#upstream-branch = newupstream +#debian-branch = dfsgclean +#filter = .svn + +# Options only affecting git-import-dsc +[git-import-dsc] +#upstream-branch = svn-upstream +#filter = [ 'CVS', '.cvsignore' ] + +# Options only affecting git-dch +[git-dch] +#git-log = --no-merges +#snapshot-number = snapshot + 1 + diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..43ce3930 --- /dev/null +++ b/ChangeLog @@ -0,0 +1,2755 @@ +commit ea86b19629001059952f7572fa8564e2263dc9f6 +Author: Bdale Garbee +Date: Tue Aug 18 20:47:41 2009 -0600 + + deliver sources.list.d fragment so updates are closer to automatic + +commit cec78502c06f11880366f6131c0442906c6ed864 +Author: Bdale Garbee +Date: Tue Aug 18 20:17:31 2009 -0600 + + update changelogs for Debian build + +commit 82d24bc65af85231b0d67394b30adfdb7beb6564 +Author: Bdale Garbee +Date: Tue Aug 18 20:17:08 2009 -0600 + + we need ChangeLog in the repo for git-buildpackage to work right + +commit c8e04df1423bfd4e9318d9fccae2cfb4a97983ab +Author: Bdale Garbee +Date: Tue Aug 18 20:12:44 2009 -0600 + + update Debian changelog for build + +commit 2fda90c0f8ab46a83175ed168fcba9b11efcd453 +Author: Bdale Garbee +Date: Tue Aug 18 20:12:22 2009 -0600 + + update Debian changelog for build + +commit a40f45bf4791bced48efb728be8990e41a7e4280 +Author: Bdale Garbee +Date: Tue Aug 18 20:08:10 2009 -0600 + + move the ChangeLog creation to the prebuild target + +commit ae7752210a0e06beacad011c17dbf75bff39eda8 +Author: Bdale Garbee +Date: Tue Aug 18 18:57:56 2009 -0600 + + update Debian changelog for build + +commit c7f7a1ed3494db008b397a613cfcd3ab36c01920 +Author: Bdale Garbee +Date: Tue Aug 18 18:56:20 2009 -0600 + + update Debian changelog for build + +commit ebaf8b0d02d82bce7c7ea78e281377768b996d6d +Merge: 79501a5 d996aa9 +Author: Bdale Garbee +Date: Tue Aug 18 18:56:16 2009 -0600 + + Merge branch 'master' into debian + +commit d996aa9b32fb0eb385bd3d158256c29788a42fe3 +Merge: b3b2d3c 7d4ceb7 +Author: Bdale Garbee +Date: Tue Aug 18 18:56:09 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 7d4ceb75a454e6c9b3fe0bd934fadcb5104dea36 +Author: Keith Packard +Date: Tue Aug 18 17:55:22 2009 -0700 + + Add ao-ejection.1 man page + + Document the input requirements and output format + + Signed-off-by: Keith Packard + +commit 79501a5462ab29d661cf76f63628bd4616b6ae1b +Merge: f48eb20 b3b2d3c +Author: Bdale Garbee +Date: Tue Aug 18 18:37:10 2009 -0600 + + Merge branch 'master' into debian + +commit b3b2d3c475a135084b5628c730fc6fca1ba0817b +Merge: 4685fc5 da12b89 +Author: Bdale Garbee +Date: Tue Aug 18 18:36:03 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit f48eb2033f3685fedd42d307963671a8060604c3 +Author: Bdale Garbee +Date: Tue Aug 18 18:33:53 2009 -0600 + + don't ship a zero-length ChangeLog, when it's easy to make one... + +commit da12b89fb056a68e65ba363fef91d266727cb685 +Author: Keith Packard +Date: Tue Aug 18 17:30:43 2009 -0700 + + Create ChangeLog from git log + +commit 7d69e2b3715faed10ce21ad562fc4d25dfc5f9c1 +Author: Keith Packard +Date: Tue Aug 18 17:29:29 2009 -0700 + + Fix ao-bitbang examples to not have . in the first column + +commit 192b08c28719b5518ed349d9897f9a21add3c615 +Author: Bdale Garbee +Date: Tue Aug 18 18:24:50 2009 -0600 + + update Debian changelog for build + +commit 5969d1d0e3aa554187a5bcc899a2f1347656fd5e +Author: Bdale Garbee +Date: Tue Aug 18 18:24:22 2009 -0600 + + fixing things lintian points out + +commit 9bf7c23f6e8ac7080240b91a28b355e50ecb4c4d +Author: Bdale Garbee +Date: Tue Aug 18 18:14:02 2009 -0600 + + update Debian changelog for build + +commit d861218bc6c2f57816953af3271d93fc48f8afc2 +Author: Bdale Garbee +Date: Tue Aug 18 18:13:48 2009 -0600 + + fix merge conflict + +commit 3f953f56fbfd4e903c09ca1e4309664d38c2c669 +Author: Bdale Garbee +Date: Tue Aug 18 18:10:06 2009 -0600 + + update Debian changelog for build + +commit 7fcbe76ce82ec5a17cf536afa0d1b9061e225aa9 +Merge: 035ba6d 4685fc5 +Author: Bdale Garbee +Date: Tue Aug 18 18:09:59 2009 -0600 + + Merge branch 'master' into debian + +commit 4685fc541466afbeefc151bcb64cd054739c048b +Merge: 1c2a0b6 c29275b +Author: Bdale Garbee +Date: Tue Aug 18 18:09:38 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + + Conflicts: + ao-tools/ao-bitbang/Makefile.am + ao-tools/ao-eeprom/Makefile.am + ao-tools/ao-load/Makefile.am + ao-tools/ao-load/ao-load.c + ao-tools/ao-rawload/Makefile.am + +commit c29275b72438637d46d7a50742882d2736eb176a +Author: Keith Packard +Date: Tue Aug 18 15:21:57 2009 -0700 + + Add manual pages for remaining commands. + + Manuals written for ao-bitbang, ao-eeprom, ao-load, ao-rawload and + ao-view. + + Manual for ao-dbg updated to reflect program name change. + + Signed-off-by: Keith Packard + +commit 9b03d620722dc54630539afba40720c30de69b2d +Author: Keith Packard +Date: Tue Aug 18 12:19:31 2009 -0700 + + Use --tty/-T on command line to specify target device + + Also, use the ALTOS_TTY environment variable in all tools. Note that + the magic value of "BITBANG" switches the library to connecting + through a CP2103 instead. + + Signed-off-by: Keith Packard + +commit 7c790fe859dff062692964338091ffbbcdf63257 +Author: Keith Packard +Date: Tue Aug 18 12:40:24 2009 -0700 + + Rename tools to ao- + + Use a consistent prefix to make it easier to remember which programs + belong to this package + + Signed-off-by: Keith Packard + +commit 035ba6df17f016953351bc77a98623c165b69909 +Author: Bdale Garbee +Date: Tue Aug 18 14:40:58 2009 -0600 + + update Debian changelog for build + +commit 7aa251970cbbb6b9d9678ed0721e28da3df9036b +Merge: 107055e 1c2a0b6 +Author: Bdale Garbee +Date: Tue Aug 18 14:40:54 2009 -0600 + + Merge branch 'master' into debian + +commit 1c2a0b6653623b689d68d7349a6b2dce3e20a4a6 +Author: Keith Packard +Date: Tue Aug 18 13:36:54 2009 -0700 + + re-add debugger sources + +commit 107055e969e89771d1e2f8ac8b1a4c5b4b9e9a48 +Author: Bdale Garbee +Date: Tue Aug 18 14:03:48 2009 -0600 + + update Debian changelog for build + +commit 14915158049918fa2fa5294f325b77dc9b08bab8 +Author: Bdale Garbee +Date: Tue Aug 18 14:03:41 2009 -0600 + + update Debian changelog for build + +commit 0fcc426f96577ebbaf0c2d009cd2708e974de315 +Merge: 91b8592 9789ca5 +Author: Bdale Garbee +Date: Tue Aug 18 14:03:16 2009 -0600 + + Merge branch 'master' into debian + +commit 9a9cce5510b87252f863239ac807b9fb4395b288 +Author: Keith Packard +Date: Tue Aug 18 12:19:31 2009 -0700 + + Start working on using getopt for the tty name + +commit 9789ca5e8caa9a013e804f307b9da380e147bd75 +Author: Keith Packard +Date: Tue Aug 18 12:40:24 2009 -0700 + + Rename tools to ao- + + Use a consistent prefix to make it easier to remember which programs + belong to this package + + Signed-off-by: Keith Packard + +commit 91b85929df6a3464396702fd177a6f74c6f28c7a +Author: Bdale Garbee +Date: Tue Aug 18 12:59:36 2009 -0600 + + update Debian changelog for build + +commit 645cc909a279347aa1665ce883c71090b29935a9 +Author: Bdale Garbee +Date: Tue Aug 18 12:59:28 2009 -0600 + + update Debian changelog for build + +commit f54e075705b3d4d6919494e8cff99141128f0303 +Author: Bdale Garbee +Date: Tue Aug 18 12:59:15 2009 -0600 + + deliver firmware files too + +commit 30fb0e78a464794a11fb8cf4ae385c3123922371 +Author: Bdale Garbee +Date: Tue Aug 18 12:52:39 2009 -0600 + + update Debian changelog for build + +commit 022e77db3416175e9b440828f94fb75b739ec00a +Author: Bdale Garbee +Date: Tue Aug 18 12:49:05 2009 -0600 + + oops, need to force prefix to /usr for Debian policy compliance + +commit a382039ebb91e3bea682b601feef15517290ad3b +Author: Bdale Garbee +Date: Tue Aug 18 12:39:41 2009 -0600 + + update Debian changelog for build + +commit 90347b16e11743e80f85308700e50b1228c2b8e0 +Merge: 06a0e43 a578239 +Author: Bdale Garbee +Date: Tue Aug 18 12:39:17 2009 -0600 + + Merge branch 'master' into debian + +commit a5782398d968e7cb11f7203afada7c216f233b3b +Author: Keith Packard +Date: Tue Aug 18 11:34:28 2009 -0700 + + Remove unused cctools code paths for old libusb and cp2103 ioctls. + + Communication with the CP2103 board has gone through three revisions, + first using ioctls supported by the CP2103 kernel driver, then using + the old synchronous usb library and now using the newer libusb + asynchronous interface. There's no reason to keep shipping the old + stale code now that the new stuff works reliably. + + Signed-off-by: Keith Packard + +commit 06a0e432480efb4e10220b0bdf402282aad32de9 +Author: Bdale Garbee +Date: Tue Aug 18 12:16:23 2009 -0600 + + update Debian changelog for build + +commit f9126a21b6a027e56d3c9d086889375fd7f37f3c +Author: Bdale Garbee +Date: Tue Aug 18 12:06:03 2009 -0600 + + update Debian changelog for build + +commit 4d7c4c69a5e0ab16018c2a9325168e363a10084b +Author: Bdale Garbee +Date: Tue Aug 18 12:05:46 2009 -0600 + + fix the changelog version extraction to work for a native version + +commit fc761cc0117cb5a091b041b73b34d222b56a60f0 +Author: Bdale Garbee +Date: Tue Aug 18 11:58:29 2009 -0600 + + update Debian changelog for build + +commit 9a97abb7b1afc90e8f67ba065583a49107a55f61 +Author: Bdale Garbee +Date: Tue Aug 18 11:58:18 2009 -0600 + + update Debian changelog for build + +commit 24c337de950ac5d4b1d074dc20eb7c6a68338462 +Author: Bdale Garbee +Date: Tue Aug 18 11:58:11 2009 -0600 + + oops, fix syntax + +commit 11c610c0e09d4f175b7e164e071ada361a1e9e2e +Author: Bdale Garbee +Date: Tue Aug 18 11:57:52 2009 -0600 + + update Debian changelog for build + +commit f65fa2b7d810ebae4b6df313de8bfe3687223a16 +Author: Bdale Garbee +Date: Tue Aug 18 11:57:00 2009 -0600 + + call debian/rules prebuild before creating source tarball + +commit dc5679ee90429fe43c6180d1d298183a79334dfc +Author: Bdale Garbee +Date: Tue Aug 18 11:54:11 2009 -0600 + + update Debian changelog for build + +commit cf1fa8b062c05ee995d6befee9088908b2b22473 +Author: Bdale Garbee +Date: Tue Aug 18 11:53:31 2009 -0600 + + add a prebuild target for use from git-buildpackage clean hook, that creates + a new debian/changelog entry based on git-describe output + +commit d7e60e48b6d85274690478223ef3b571a818e228 +Author: Bdale Garbee +Date: Tue Aug 18 11:52:46 2009 -0600 + + update Debian changelog for build + +commit e946fa231a719abfdd3f319b8c3345dfc75ee185 +Author: Bdale Garbee +Date: Tue Aug 18 00:08:30 2009 -0600 + + allow pass-in of VERSION, only call git describe if VERSION not set yet + +commit f762a9dfb3b9c81e443a85cd434154598c737ed8 +Author: Bdale Garbee +Date: Tue Aug 18 00:06:24 2009 -0600 + + see if this works + +commit c6514ac5c47b44456a15d0f627f274eca769122e +Author: Bdale Garbee +Date: Tue Aug 18 00:03:27 2009 -0600 + + undo the post-commit hook stuff + +commit 2d53e72e938086688c81d16750b2c880fee1f4cd +Author: Bdale Garbee +Date: Mon Aug 17 23:55:47 2009 -0600 + + tweak makefile to use version file instead of calling git describe directly + +commit 2732624c67f5397fed5f31b062feb0f27b7f8fbd +Author: Bdale Garbee +Date: Mon Aug 17 23:53:35 2009 -0600 + + add version to the list of ignored files + +commit 08b28a0d4a71ba25ca949fe57bb150a89b401cef +Author: Bdale Garbee +Date: Mon Aug 17 23:39:35 2009 -0600 + + add build dependencies + +commit bc5d65b7e9776c87948edc4bd88fc4125ca20209 +Author: Bdale Garbee +Date: Mon Aug 17 23:32:49 2009 -0600 + + build as a Debian specific package since we have no "upstream" + +commit e4fb67c989e10f626042e3b125ffd900bf477d60 +Author: Bdale Garbee +Date: Mon Aug 17 23:31:52 2009 -0600 + + add a config file for git-buildpackage + +commit 5f59df632f3a82348aefc2b16f2521f6ebd30a50 +Author: Bdale Garbee +Date: Mon Aug 17 23:31:20 2009 -0600 + + don't fail to clean if Makefile not present + +commit 946f2be3f4fdd0e7cf5c9867ff6fa0d348d95ee1 +Author: Bdale Garbee +Date: Mon Aug 17 23:30:20 2009 -0600 + + package for Debian + +commit 7cba411de0780c65e3490ab67186a514f0ea42ec +Author: Keith Packard +Date: Mon Aug 17 20:47:31 2009 -0700 + + test for sdcc, nickle and readline + + Signed-off-by: Keith Packard + +commit f48dcffae761700355a17b59345d55a60703f0c4 +Author: Keith Packard +Date: Sun Aug 9 20:43:10 2009 -0700 + + Sync USB data after each memory write command + + This makes sure we flush the USB link often enough for the other end to keep + up. + + Signed-off-by: Keith Packard + +commit cd5456f18e4b39ad76d5549df91a0e0cfb18a2e9 +Author: Keith Packard +Date: Sun Aug 9 16:08:07 2009 -0700 + + Handle partial ALSA PCM writes + + The ALSA spec says that snd_pcm_writei will not return a partial write, but + at least on the OLPC, that's not true. Deal with this. + + Signed-off-by: Keith Packard + +commit 3056cb8eef5aee0dcd342488386355d8b8f574c8 +Author: Keith Packard +Date: Sun Aug 9 15:55:19 2009 -0700 + + Check more alsa return statuses + +commit 8ddf3345afd8cbf638e81993633f7861d8dbca63 +Author: Keith Packard +Date: Sat Jul 18 01:47:34 2009 -0700 + + Don't report distance to rocket without valid GPS + + When there's no valid GPS data, don't try to report the distance and bearing + to the rocket after landing. + + Signed-off-by: Keith Packard + +commit fbcb7b20fa701a6e534d38e307839466545668e3 +Author: Keith Packard +Date: Sat Jul 18 01:05:33 2009 -0700 + + Add B command to set serial baud rate + + Signed-off-by: Keith Packard + +commit 91b023e7e4eeed838e0320d2ddac0f6aac39e565 +Author: Keith Packard +Date: Sat Jul 18 01:05:13 2009 -0700 + + Get rid of spaces after minus sign in climb value + +commit 28be20cf914fb34dc3c776519708d0f02091764e +Author: Keith Packard +Date: Sat Jul 18 01:04:39 2009 -0700 + + Switch to 57600 baud for GPS data + +commit d3f76ce58b9c0ed2e5a9fe3bbc7fb9cb38247714 +Author: Keith Packard +Date: Sat Jul 18 01:04:17 2009 -0700 + + Drain serial port before changing speed + + Signed-off-by: Keith Packard + +commit d7c2d358ed8a1afc9f0ba2bd830b10f6b56dc7b1 +Author: Keith Packard +Date: Sat Jul 18 00:44:42 2009 -0700 + + Display last known GPS coord while unlocked + + Signed-off-by: Keith Packard + +commit 5195fcfe239e430e1f9f11774c9a245c7b29dae9 +Author: Keith Packard +Date: Sat Jul 18 00:44:01 2009 -0700 + + use g_source_destroy instead of free on serial object + +commit 1e5e98bd8f5ea0bc15592de454e3629383462371 +Author: Keith Packard +Date: Sat Jul 18 00:43:22 2009 -0700 + + Trim aoview_serial_set_callback args down to just port and callback + +commit 08f37056deec25d77062bc411a04033401b033a5 +Author: Keith Packard +Date: Fri Jul 17 22:11:03 2009 -0700 + + Reset GPS at boot time + +commit 1150aa850f5a025b849556e32c4dddb27937d9af +Author: Keith Packard +Date: Fri Jul 17 22:10:43 2009 -0700 + + Fix up serial debug output + +commit 2a7956a64935246475f92d44c08369e0230b676a +Author: Keith Packard +Date: Fri Jul 17 21:34:13 2009 -0700 + + Allow the GPS port to run at 4800 baud if desired + +commit 8d650769c319261c97f5e68eff9138207b95c0f8 +Author: Keith Packard +Date: Fri Jul 17 21:33:53 2009 -0700 + + Initialize the GPS serial protocol state + + Signed-off-by: Keith Packard + +commit ab40d224b39ba6d29c4056e2d2c365e1eb3d3793 +Author: Keith Packard +Date: Fri Jul 17 21:33:18 2009 -0700 + + Use uint8_t for comparisons to avoid int conversions + + Signed-off-by: Keith Packard + +commit d6749bf24792bb41ca700cf4b8e5e1ac1a63cbf0 +Author: Keith Packard +Date: Fri Jul 17 21:30:53 2009 -0700 + + Add AO_GPS_RUNNING state. + + This tracks whether the GPS receiver has ever sent a valid report to the + flight computer, allowing the user to tell whether the GPS receiver is + working at all. + + Signed-off-by: Keith Packard + +commit a1da7e871aee75308bc05ce1b7a0dc402e4c9509 +Author: Keith Packard +Date: Fri Jul 17 21:25:35 2009 -0700 + + Add M command to monitor serial bytes + +commit ddfa2308c0be4c002f982ae9da6032ee7854117d +Author: Keith Packard +Date: Fri Jul 17 21:24:45 2009 -0700 + + Support the not-connected GPS state + +commit 34f148500df427c148188c0ada20bf914a7c74ba +Author: Keith Packard +Date: Fri Jul 17 19:23:10 2009 -0700 + + Use 57600 baud for GPS. Clean up gps init. + + Assume GPS is either in 4800 NMEA or 57600 SiRF mode, send just the sequence + to get from 4800 NMEA to 5760 SiRF. + + Also, eliminate threads from the gps test program. + + Signed-off-by: Keith Packard + +commit 2deca0c52cd6cfb4baceb59c8a5458344bada338 +Author: Keith Packard +Date: Fri Jul 17 17:09:20 2009 -0700 + + Try harder to get the GPS receiver serial link sync'd up. + + We cannot assume that the GPS receiver is in any particular state when it + boots, so we try to send the serial configuration at several rates and hope + that it eventually sees something that it likes. + + Signed-off-by: Keith Packard + +commit 31d5670a9144b943ce9c8cb00deb5fb659af0b1c +Author: Keith Packard +Date: Fri Jul 17 17:06:18 2009 -0700 + + Rolling average for pad location. Say 'GPS ready'. + + Use a rolling average for the pad location, instead of just averaging all + positions. This filters out old (presumably less accurate) values eventually. + + When enough GPS samples have been acquired, say 'GPS ready'. + + Signed-off-by: Keith Packard + +commit bfe1e76c82738baaf65abbc58c3244a07ea8fefe +Author: Keith Packard +Date: Fri Jul 17 16:22:51 2009 -0700 + + Split GPS data into a separate column + + Signed-off-by: Keith Packard + +commit 5f0179652e8bb85add9067e5253e981c60f2c51e +Author: Keith Packard +Date: Fri Jul 17 16:03:35 2009 -0700 + + Fix up SiRF parsing and test code so that it actually works + + Signed-off-by: Keith Packard + +commit 0b35447d05a0c7eaf4fefcbcf0065fe3320bba82 +Author: Keith Packard +Date: Fri Jul 17 13:58:14 2009 -0700 + + Add host-side gps protocol testing program + +commit fef7334bddb9fccfbd6deab7d5d466ab3e76323a +Author: Keith Packard +Date: Sat Jul 11 00:56:13 2009 -0700 + + Hook aoview directly to alsa + + This skips the flite internal audio stuff which opened and closed the audio + device for each phrase. This caused the first part of some phrases to be + missed when using an external audio device. + + Signed-off-by: Keith Packard + +commit 80cadf44f5f1accd6ddfca25c2af8d4d424f26d9 +Author: Keith Packard +Date: Thu Jul 9 20:55:10 2009 -0700 + + Show speed. Format numbers. Timeout and report final status. + + The speed value is now shown in the top label bar. Ascent shows + accelerometer-derived data, otherwise it's baro derived. + + All of the numbers displayed are now given sensible printf formats so they + don't contain way too many digits. + + Instead of doing periodic reporting based on flight tick count, data is + reported every 10 seconds based on wall time. After landing, or when no data + have been received for a while, final flight information is spoken. + + Signed-off-by: Keith Packard + +commit 19630ef084866f4230e68ccf11284b30c68128b1 +Author: Keith Packard +Date: Sun Jul 5 08:35:28 2009 -0700 + + Dont smash aoview_monitor_parse input buffer + +commit e506ed4b6efb86eab50204658fcd433b987e3831 +Author: Keith Packard +Date: Tue Jun 30 15:25:52 2009 -0700 + + Integrate flite into aoview directly. Fix great circle computation. + + Use a separate thread for flite rather than a separate program. + Save voice state to gconf. + Add filters for replay file selection + + Signed-off-by: Keith Packard + +commit 5b988e0146075d57434f8484e1ec9fcf3e183df2 +Author: Keith Packard +Date: Tue Jun 30 15:24:53 2009 -0700 + + Make window taller + +commit 696233b088645bba1aaa6aa6c5358c3ecfa5cd3f +Author: Keith Packard +Date: Tue Jun 30 15:24:31 2009 -0700 + + Use 16kHz voice + +commit 2e06772c8b6fd74f86e640ed97f0d5bc8c095c2f +Author: Keith Packard +Date: Tue Jun 30 11:58:30 2009 -0700 + + Add telem replay and larger labels + + Replays telemetry files in real time + Shows height/state/rssi in big values at the top. + + Signed-off-by: Keith Packard + +commit 566dde161385263700eaae51095eecfa9b5972ee +Author: Keith Packard +Date: Mon Jun 29 23:06:47 2009 -0700 + + Update aoview/.gitignore + + Signed-off-by: Keith Packard + +commit 4ca2d910f3be689fd3c78a4f1be0555d6b1a30c1 +Author: Keith Packard +Date: Mon Jun 29 23:05:27 2009 -0700 + + Use flite to announce flight state + + This uses the flite voice synthesis library from festival to announce + altitude and speed information during the rocket flight. + + Signed-off-by: Keith Packard + +commit 527d7c803ed9597b210634018cb2eb9d048d9846 +Author: Keith Packard +Date: Mon Jun 29 23:03:58 2009 -0700 + + Add GPS speed and error data to telemetry and aoview + + Having switched to the SiRF binary GPS format, the velocity and error data + can now be displayed. + + Signed-off-by: Keith Packard + +commit ee4919dd771b00e2a2dd1083c9528efa7baab50f +Author: Keith Packard +Date: Mon Jun 29 13:54:00 2009 -0700 + + Convert GPS to SiRF binary protocol. + + This switches the GPS unit from NMEA to SiRF protocol at startup and then + parses the binary data. The binary data uses a different encoding of lat/lon + than the NMEA strings, and so the telemetry and eeprom data formats change + with this switch. + + Signed-off-by: Keith Packard + +commit 49bf37767d2453869f2ca2c0832d1124322c66e0 +Author: Keith Packard +Date: Wed Jun 17 23:22:25 2009 -0700 + + Add ejection computation utility + + Signed-off-by: Keith Packard + +commit e59520e343c2573b1b92c0b3c4aaa93e51bc55d3 +Author: Keith Packard +Date: Wed Jun 17 13:55:23 2009 -0700 + + Fix clock initialization to not try to use 32kHz xtal on P2_3/P2_4 + + None of our boards have a 32kHz xtal oscillator, instead we use those pins + (on Telemetrum) for the deployment firing circuits. The old clock + initialization code was switching from the 32kHz RC oscillator to the 32kHz + crystal and overriding our use of those pins. + + Signed-off-by: Keith Packard + +commit 1c3cc12c08ddefbd6456a55c54ef87dd94d4ae9a +Author: Keith Packard +Date: Sun Jun 14 17:25:34 2009 -0700 + + Some kernels reference USB ttys as tty/tty* instead of tty:tty* + + Signed-off-by: Keith Packard + +commit 0f2cbd41332b1b63865c5f1a4e749419b469853a +Author: Keith Packard +Date: Sun Jun 14 16:45:19 2009 -0700 + + Rename state apogee -> coast + +commit 5834a12c1d3d71105c9e3d1ceaf9f3ffac9ff1eb +Author: Keith Packard +Date: Sun Jun 14 16:39:28 2009 -0700 + + rename states. launchpad -> pad, coast -> fast + +commit 8c40f19acd09fe93d492c9355da8a1198c34b1c3 +Author: Keith Packard +Date: Sun Jun 14 16:36:29 2009 -0700 + + Disable monitor mode when communicating via usb + +commit 7adea9c59c73acd52743446c74fb675e0a1d6d05 +Author: Keith Packard +Date: Thu Jun 4 14:38:45 2009 -0700 + + Format GPS seconds as %02d.%04d to avoid spaces in the value + + The aoview GPS parsing code doesn't deal well with spaces in the middle of + the value, so pad the seconds field with a zero as needed. + + Signed-off-by: Keith Packard + +commit a0e6bfee635b64092262936c858542318f6fc6dc +Author: Bdale Garbee +Date: Thu Jun 4 13:11:48 2009 -0600 + + newer INSTALL file pulled in by autogen.sh + +commit cf1e258d52b878df10b51a047709b10ecd51a68e +Author: Bdale Garbee +Date: Thu Jun 4 13:09:29 2009 -0600 + + add a distclean target to src/Makefile + +commit 176052b7c14fcad067835ecb550778faf67cf4da +Author: Bdale Garbee +Date: Thu Jun 4 13:07:10 2009 -0600 + + add lib to the front of the subdir list + +commit 208bc15714c7b4020c017eef19011c4eb9ab51e2 +Author: Keith Packard +Date: Thu Jun 4 11:20:10 2009 -0700 + + Move build and debug tools to 'cctools' directory. + + These tools were merged in from the ccdbg package. + + Signed-off-by: Keith Packard + +commit 17d2432a8b9c15963cd3b821f025ad33972ef477 +Merge: 210dbaa 8a9a3f0 +Author: Keith Packard +Date: Thu Jun 4 11:13:15 2009 -0700 + + Merge ccdbg and altos sources into one giant repository + + Keeping these separate isn't making things any easier. + + Signed-off-by: Keith Packard + +commit 210dbaa23cdacf3a6f2d6e23493e96ee2ac9bca7 +Author: Keith Packard +Date: Thu Jun 4 10:41:34 2009 -0700 + + Use autotools, move altos to src subdir + + Signed-off-by: Keith Packard + +commit 8cce307bb3156584ba17ae5a787f645dfee5fb94 +Author: Keith Packard +Date: Thu Jun 4 10:25:30 2009 -0700 + + Make menu seperator insensitive + +commit 778cae8fc5a4b30e5045e4703316fc61ae18562a +Author: Keith Packard +Date: Wed Jun 3 17:07:34 2009 -0700 + + aoview: Add eeprom data fetching + + Fetches the last flight data from a TM device connected via USB and writes + it to the flight log directory. + + Signed-off-by: Keith Packard + +commit bf140966e9649e75b884c8aa5f25ffbf9eed10ea +Author: Keith Packard +Date: Wed Jun 3 10:57:46 2009 -0700 + + Stop log dumping at flight end. Print 'end' at end of log. + + No reason to continue dumping data past the end of the flight now that the + logging stuff has been demonstrated to work reliably. Also, to make + automated log dumping easier, this prints out 'end' after the log data so + that aoview knows when to stop reading. + + Signed-off-by: Keith Packard + +commit 35ac66969abe24ca23776618306a59fc17770e06 +Author: Keith Packard +Date: Sun May 31 09:22:01 2009 -0700 + + Start adding bi-directional packet link + +commit 3a3bfd471a868d546d83cdc431b53c8f5208edb9 +Author: Keith Packard +Date: Thu May 28 23:17:33 2009 -0700 + + Eliminate RDF tone generation. + + Now that we have a viable telemetry-signal based RDF device via TeleDongle, + there's no reason to continue to waste power and bandwidth with a NFM tone. + + Signed-off-by: Keith Packard + +commit 4d83eef0fe1d24a845ab29a535dfc56e13e7ee20 +Author: Keith Packard +Date: Thu May 28 23:17:25 2009 -0700 + + Change .gitignore to match new aoload procedure + +commit dcfcf3bec6788460b6fe8c239c80bad4526bd15b +Author: Keith Packard +Date: Wed May 27 22:01:37 2009 -0700 + + Leave serial number writing to aoload + + Instead of building per-serial hex files, leave that + process to the new aoload program + + Signed-off-by: Keith Packard + +commit 8a9a3f02b951382573ff74dd6ce5a1c0f335fa86 +Author: Keith Packard +Date: Wed May 27 21:53:15 2009 -0700 + + Add aoload to load serial-numbered altos binaries. + + aoload is a custom version of ccload which edits the data before sending it + to the target machine, writing the target serial number into the data. + + Signed-off-by: Keith Packard + +commit 5a7a63c34b778e40a61ddabd16ec1af9a2be50c3 +Author: Keith Packard +Date: Sat May 23 21:20:12 2009 -0700 + + Fix aoview telemetry GPS parsing code to use correct columns + + This code was trying to pull the GPS data from the wrong columns, causing + aoview to fail to display GPS information. + + Signed-off-by: Keith Packard + +commit 26988c3e7acb2fa832810475e43e08fd2867459c +Author: Keith Packard +Date: Sat May 23 21:18:57 2009 -0700 + + Parse both telemetry or log data ao_flight_test + + Change the way data is fed from files to the flight test rig to handle + either kind of input file. + + Signed-off-by: Keith Packard + +commit d6f5a0689023546464a71561f53fa2c943077c88 +Author: Keith Packard +Date: Sat May 23 21:16:22 2009 -0700 + + Avoid 16-bit overflow in velocity computation. + + Adding two 16 bit integers together can wrap around to negative numbers, + this resulted in velocity values which never decreased, making the switch + from coast to apogee state not occur. + + Signed-off-by: Keith Packard + +commit aa6d87aeb616dd62f0debaded297232022b4f8bd +Author: Keith Packard +Date: Wed May 20 09:44:55 2009 -0700 + + Make file handling more general so it can be reused. + + The log file handling stuff will be useful for saving eeprom data, so pull + it out of the real-time log handling code and make a general interface. + + Signed-off-by: Keith Packard + +commit b730c8bcbce649cdddba935e1112aaae538bc526 +Author: Keith Packard +Date: Sun May 17 23:54:44 2009 -0700 + + Ignore aoview_glade.h + +commit 91b07410122d0eaaf292cdb31c200925d45eaf2c +Author: Keith Packard +Date: Sun May 17 23:36:21 2009 -0700 + + Transmit computed ground pressure and acceleration values + + These are the last two values relevant to figuring out the state of the + flight computer, and as they are computed by averaging 10 seconds of 100Hz + sample data, they're a lot more accurate than anything the receiver could do + on its own. + + Signed-off-by: Keith Packard + +commit 71d1689759829f1bc8550f1a4d8c9f2dc90b2ab4 +Author: Keith Packard +Date: Sun May 17 23:18:09 2009 -0700 + + Provide install target + +commit f301b95e87c8ec1e3b58d595a05d486bede5e0c2 +Author: Keith Packard +Date: Sun May 17 23:13:20 2009 -0700 + + Embed glade file in executable + + This eliminates install issues nicely. + + Signed-off-by: Keith Packard + +commit 26361686d6fc63dc22d22285f0543c5c2c756fb4 +Author: Keith Packard +Date: Sun May 17 23:05:23 2009 -0700 + + Add About dialog to aoview. + + Signed-off-by: Keith Packard + +commit 0f3233c49f43cd4e372e613303919ce4d50255b2 +Author: Keith Packard +Date: Sun May 17 22:44:19 2009 -0700 + + USB device names can contain '.' too + + Depending on the hierarchy of devices, names can contain '.', so allow those + too. + + Signed-off-by: Keith Packard + +commit 33221277690e6ee30387c506c3f2b8237ed48efd +Author: Keith Packard +Date: Sun May 17 22:43:34 2009 -0700 + + scandir returns -1 on error + + In which case, the namelist is invalid, so don't look at it, and don't free + it. + + Signed-off-by: Keith Packard + +commit 7cb9fb675f56bf30ab6bf0bcdc5cb679709ffe3e +Author: Keith Packard +Date: Sun May 17 22:29:54 2009 -0700 + + Send computed accel/vel/pres values over the radio + + These computed values reflect what the flight computer is actually refering + to for state changes, and will be useful in debugging the flight software as + well as provide a filtered view of the data. + + Signed-off-by: Keith Packard + +commit 2c780d67b8a22d75a2da4b2af21fd35f0c6f5236 +Author: Keith Packard +Date: Sun May 17 22:29:06 2009 -0700 + + Handle disappearing serial devices + + Put up a dialog when the serial open fails, and shut down monitoring when + the serial device disappears while running. + + Signed-off-by: Keith Packard + +commit 69616104813fc5ba89fb3128d04fb9328961c59c +Author: Keith Packard +Date: Sun May 17 22:24:53 2009 -0700 + + While on the pad, zero out velocity every second + + We integrate acceleration to get velocity, but that means sitting on the pad + for a long time can add substantial error to the velocity value. Each + second, take the velocity value from a full second ago and subtract that out + of the current velocity. Once we detect boost, this will stop, which means + that as long as we detect boost within a second, we won't have subtracted + out any "real" velocity. + + This keeps the pad velocity hovering around zero, which is pretty useful. + + Signed-off-by: Keith Packard + +commit 1234694eb903b204488ddc7cb30bcfe34bf1e677 +Author: Keith Packard +Date: Sun May 17 01:29:06 2009 -0700 + + Clear table, reset log on disconnect + +commit 4316b6af86b37522038e642235c163fcaad52e96 +Author: Keith Packard +Date: Sun May 17 01:28:16 2009 -0700 + + Add pad lat/lon, max accel, max height + + Signed-off-by: Keith Packard + +commit 4348281bd788a13ea700413537f12da3c00356e4 +Author: Keith Packard +Date: Sun May 17 00:46:09 2009 -0700 + + Clean up GPS display + + Signed-off-by: Keith Packard + +commit ff68e38770351ddac3285ce275cd85adab01fd3d +Author: Keith Packard +Date: Sun May 17 00:45:38 2009 -0700 + + Make aoview window taller + + Signed-off-by: Keith Packard + +commit be3f4fed7b863c8cdaabe32b61b65a8b3cd11355 +Author: Keith Packard +Date: Sun May 17 00:13:45 2009 -0700 + + Add lots more aoview UI bits + + Logs data to files, displays current state in window. + + Signed-off-by: Keith Packard + +commit 93d7ce8e054515ed7b166eb042ae7f47e564d21d +Author: Keith Packard +Date: Sat May 16 20:45:26 2009 -0700 + + When logging starts up, right the whole ring to the log. + + This preserves the data pre boost-detect for later analysis. + + Signed-off-by: Keith Packard + +commit fec4212a59a7b3321536b25707dcabc43c797c33 +Author: Keith Packard +Date: Sat May 16 20:04:31 2009 -0700 + + Abandon use of accelerometer for apogee detect. + + Integrating the accelerometer data to compute velocity worked for one rocket + flight, but additional testing shows that it doesn't work in other + airframes. Until we figure out how this should work, we'll rely on the + altimeter to detect apogee. + + Signed-off-by: Keith Packard + +commit 09771c644de54ae354e8f98af7ba74289b3c0fcc +Author: Keith Packard +Date: Sat May 16 02:25:04 2009 -0700 + + Add preliminary aoview code + + AoView connects with TeleDongle to present telemetry information in a + reasonable form. Right now, it just displays information to stdout, but it + does have fancy dialogs for finding the USB devices. + + Signed-off-by: Keith Packard + +commit 37250b00f6286aee4b3b28604f5d463db3079a89 +Author: Keith Packard +Date: Wed May 13 20:41:54 2009 -0700 + + Discard usb output before connection. Handle USB reset. + + Discarding output before USB is plugged in allows threads that send output + and do other things to work without a USB connection. Unfortuantely, there + doesn't appear to be any way to detect when the USB link is disconnected, + which means that once USB is enabled, future writes will continue to block. + + USB reset causes the USB interrupts to all be reconfigured back to power-on + state. + + Signed-off-by: Keith Packard + +commit 9b974217958b1017e62d6c4f4568f547ccc30c58 +Author: Keith Packard +Date: Wed May 13 20:40:42 2009 -0700 + + Enable radio monitor by default in teleterra, teledongle and tidongle + + These ground loads want to monitor the radio constantly, and not require use + of the 'm' command before listening. + + Signed-off-by: Keith Packard + +commit 25fc03a333b2cfad0a93ebc385fbcf74b63c229e +Author: Keith Packard +Date: Wed May 13 20:39:28 2009 -0700 + + Remove monitor/rssi functions from telemetrum load + + Telemetrum is now a flight-only load, use teleterra or teledongle for ground + boards. + + Signed-off-by: Keith Packard + +commit 05493b98eb1ae4d30cb0b600849d70b03fa33594 +Author: Keith Packard +Date: Wed May 13 20:38:11 2009 -0700 + + Split out ao_state_names to separate file + + Allows state names to be used in programs without monitoring enabled. + + Signed-off-by: Keith Packard + +commit d085d43701e3cdd2119e947a9ae45baa78c80318 +Author: Keith Packard +Date: Wed May 13 14:29:30 2009 -0700 + + Indicate RSSI with a blinking LED + + Blink the red LED at a rate proportional to the RSSI value. + + Signed-off-by: Keith Packard + +commit 055331d5f7d5adc40c348c3efd331a562dcda82a +Author: Keith Packard +Date: Wed May 13 11:19:13 2009 -0700 + + Make ao_flight_test show AGL altitude and positive acceleration under boost + + This makes the output more readable + + Signed-off-by: Keith Packard + +commit d91208fbf5fc7797b93087ef8619454c4bed0130 +Author: Keith Packard +Date: Wed May 13 11:18:24 2009 -0700 + + Make ao_flight_test able to read raw logging data + + Protect ao_flight_test reading functions so that a simple + 'script' output can be fed to the program and have it work correctly. + + Signed-off-by: Keith Packard + +commit d3dbd8949e1102220ad5fd0863f493c819b96e46 +Author: Keith Packard +Date: Wed May 13 11:16:53 2009 -0700 + + Print only RSSI when packet CRC is invalid + + Packets with invalid CRC usually contain bogus data, so don't print that, + just print out the RSSI which may contain useful data. + + Signed-off-by: Keith Packard + +commit 8168820b667cc1deffab64dd81cb4e6e2e6eabe4 +Author: Keith Packard +Date: Wed May 13 11:00:43 2009 -0700 + + Accelerometer-based velocity values are invalid after apogee + + Because the orientation of the flight computer relative to the ground is + unknown after apogee, the accelerometer data cannot be integrated to compute + velocity. Main deploy is now based purely on barometric altitude and landing + detection no longer checks for a low velocity value. + + Signed-off-by: Keith Packard + +commit 24fdda44ff8604e40510b196ead17564d8f8cd3d +Author: Keith Packard +Date: Wed May 13 10:59:04 2009 -0700 + + Add velocity check for boost detect via accelerometer + + Bumping the rocket can cause a brief period of high acceleration, which may + cause a mistaken boost detection. Require both a high acceleration and + reasonable velocity to trigger boost phase. + + Signed-off-by: Keith Packard + +commit 7a1aa3fdbc0d1fae5e7ee027bf8904598c6ebe41 +Author: Keith Packard +Date: Wed May 13 10:58:30 2009 -0700 + + Typo in callsign + +commit 497c89a7d08920630894b2605c3b6a0bdc4c229b +Author: Keith Packard +Date: Sun May 10 23:11:06 2009 -0700 + + Use recorded accelerometer baseline data in ao_flight_test + + With the flight computer recording a long-term average value for the + accelerometer in the flight record, use that to prime the flight test code + when running a log file through the simulator. + + Signed-off-by: Keith Packard + +commit ba3c53636e485450f48093d0a88a6629775f7c3a +Author: Keith Packard +Date: Sun May 10 23:01:16 2009 -0700 + + Don't re-initialize the landing range data at each apogee detect sample + + The landing range values are used only after apogee detect, so we need only + initialize them on the transition from apogee to drogue. + + Signed-off-by: Keith Packard + +commit b623b1098bc7a10d471730259438fb82804221d0 +Author: Keith Packard +Date: Sun May 10 23:00:06 2009 -0700 + + Initialize ao_min_vel with |ao_flight_vel| + + As ao_min_vel is stored as an absolute value, it's important to preserve + that invariant, even though we don't expect ao_flight_vel to be negative at + coast. + + Signed-off-by: Keith Packard + +commit e9584e846b9bd7926d61451d32ba5d7a30416f7b +Author: Keith Packard +Date: Sun May 10 22:58:31 2009 -0700 + + Decrease telemetry rate on the pad to 1/sec instead of 20/sec + + Transmitting telemetry through the radio consumes a significant amount of + battery; reducing the rate to 1/sec will reduce power usage while waiting + for launch. + + Signed-off-by: Keith Packard + +commit 97cecb517cd7bf75e1219c76a93bfe6964c07052 +Author: Keith Packard +Date: Sun May 10 22:57:19 2009 -0700 + + Increase the initial accel/baro average to 1000 samples + + To get an accurate baseline of the launchpad state, take a longer average of + the two sensors as the unit boots up. + + Signed-off-by: Keith Packard + +commit 98806b1ff3f41484663d61ff430e9e2764c7b5e6 +Author: Keith Packard +Date: Sun May 10 22:54:14 2009 -0700 + + Record average accelerometer value in flight start log record + + The average accelerometer value cannot be extracted from the log as the + record starts after that is computed. As that drives much of the + accelerometer-based state transition logic, it is an important value to + have, so we log it as part of the flight start record now. + + Signed-off-by: Keith Packard + +commit a12edbfe21fe27a9efbf87bacda9ab4806256e2b +Author: Keith Packard +Date: Sat May 9 10:24:10 2009 -0700 + + Add version command to show product information + +commit e80b87f5e3ccf152d67a2e87bdefda161c455599 +Author: Keith Packard +Date: Sat May 9 10:23:49 2009 -0700 + + Pad callsign with nuls + +commit beae3360828da21eb1a3c4f88e930f242d4e36b7 +Author: Keith Packard +Date: Fri May 1 08:14:57 2009 -0700 + + USB spec limits bulk endpoints to 64 byte payload max. + + For full-speed devices, bulk endpoints may use 8, 16, 32 or 64 bytes, but no + more. + +commit de7814c738488c2c16c6216c93fa78128895e5d5 +Author: Keith Packard +Date: Wed Apr 29 17:46:56 2009 -0700 + + Use 'char' instead of 'uint8_t' for character data + + String and character constants are of char type, so using uint8_t causes + promotion to 16-bit types when comparing the two. + +commit 4ae74fffb939d67424efa3e7f433637f1f920ebc +Author: Keith Packard +Date: Wed Apr 29 17:46:36 2009 -0700 + + Eliminate incorrect cast in printf string argument + + char * is a pointer to a string in the default address space, not a generic pointer + to a string. As such, the compiler (at least 2.9.0) mis-compiles this if the + cast is included. + +commit 39f2a3c6bd501d12a92bfd38434ce67bb5beb70d +Author: Keith Packard +Date: Wed Apr 29 17:44:41 2009 -0700 + + Correct radio frequency shown in config display. + + Radio frequency base is 434.550, not 435.550 + +commit 75ca1751b7cac2f8074d0713ee96d6ab45b54f19 +Author: Keith Packard +Date: Wed Apr 29 17:42:26 2009 -0700 + + Reset landing interval tests at apogee + + This moves all of the interval management into the landing test code and + out of the main loop. The interval is reset at apogee to make sure the + sensors produce a stable reading for at least 20 seconds + +commit 7a1b77c2d7253a681389f32b70e2460aac188807 +Author: Bdale Garbee +Date: Sun Apr 26 17:53:13 2009 -0600 + + clean up host programs, too + +commit 5df80c346d65a9d56a8699b056dc44924acb31fe +Author: Keith Packard +Date: Sun Apr 26 16:04:07 2009 -0700 + + Was missing v_batt in adc dump command + +commit c3fec2c4c65db71e88ef0c05c69463438a7cfc6c +Author: Keith Packard +Date: Sun Apr 26 15:38:28 2009 -0700 + + Add manual ignition and igniter test commands + +commit 819f1de8dd6010fae050bcef930943c7923929f9 +Author: Keith Packard +Date: Sun Apr 26 15:38:03 2009 -0700 + + Clean up commands a bit + +commit 178abb5c8439509926a5507911d7148b84f051b8 +Author: Keith Packard +Date: Sun Apr 26 15:08:58 2009 -0700 + + Clear more files on make clean + +commit 70a69f3acdca27b80cdb2069de59bbc6dba83dbd +Author: Keith Packard +Date: Sun Apr 26 15:05:29 2009 -0700 + + Label binaries with product and serial info + +commit 5ed3b1cb52b573db1fee9655a29a0e6dd72f53fe +Author: Keith Packard +Date: Sun Apr 26 01:37:02 2009 -0700 + + Make sure full log is written and flushed on landing. + + The final state change to landing is recorded in the logging thread, so have + that turn off logging once it has recorded that state. Then make it go to + sleep. + +commit 2e737ad00cad5d893b252d8aa9dbff3d9b800731 +Author: Keith Packard +Date: Sun Apr 26 01:36:53 2009 -0700 + + Clean up monitor output a bit + +commit 38a0b61b0a0b3c00f064c8d562950a17a6ddff4a +Author: Keith Packard +Date: Sun Apr 26 00:11:32 2009 -0700 + + Add configuration support + + Current config variables: + Main deploy altitude above launch (in meters) + Acceleration zero g calibration (manual or automatic) + Radio channel (freq = 435.550MHz + channel * 100kHz) + Callsign (max 8 characters) + + Supporting this involved shuffling code around so that the + non-telemetrum builds could include only the stuff they needed. + +commit c65f1a1acd2ca00758833cec5d3f8056d303d3e2 +Author: Keith Packard +Date: Sat Apr 25 14:44:33 2009 -0700 + + Allow for slower ADC operation. Add power saving code. + + This tries to make the flight computer use less power by disabling USB in + flight mode, lowering the telemetry rate after ascent. It also disables the + RDF beacon during ascent and re-enables it once descent has started. + +commit 8e7b48b5f090be81980ab00fbce814ae1cc253e4 +Author: Keith Packard +Date: Sat Apr 25 14:44:04 2009 -0700 + + Allow ADC to be disabled + +commit 7bc3d9962872850e7b420221cf689db16b4305cc +Author: Keith Packard +Date: Sat Apr 25 14:43:23 2009 -0700 + + Place CPU in P0 state while idle + +commit e45fce7f82d704d677f84c69b0e07588d109d780 +Author: Keith Packard +Date: Sat Apr 25 14:42:20 2009 -0700 + + Add RDF beacon and callsign to telemetry + +commit 61510f98404bca6861b2da98f6cd9ba9deb76968 +Author: Keith Packard +Date: Sat Apr 25 14:40:51 2009 -0700 + + Add radio code to emit a 1kHz tone + +commit 0f07803d84b5ac89500ee33a6818c50583e3ff7f +Author: Keith Packard +Date: Sat Apr 25 13:18:37 2009 -0700 + + Allow the USB system to be disabled/enabled at run-time + +commit 45976af820fc41099928df71ea8304c56eb9fc7c +Author: Keith Packard +Date: Sat Apr 25 13:16:27 2009 -0700 + + Make LED usage depend on target device + +commit 4a050704ad2c497e9f1b0988334228b0bbc4c170 +Author: Keith Packard +Date: Sat Apr 25 13:13:24 2009 -0700 + + Make some functions reentrant to save DSEG space + +commit 6b3d25a6d6d7847765eb03b836913dd5ecef2993 +Author: Keith Packard +Date: Fri Apr 24 19:17:37 2009 -0700 + + Add monitor task to flight software + + Allows the use of telemetrum in teledongle mode. + +commit ad0d2d88a91cbd02c56ea5ff6dab23e16aec6510 +Author: Keith Packard +Date: Fri Apr 24 19:17:19 2009 -0700 + + Report difference from ground to max altitude at landing + +commit f94ab879ff6f97708827c74facd11003a2d8b590 +Author: Keith Packard +Date: Fri Apr 24 19:16:29 2009 -0700 + + Display data with units while running simulation + +commit 6fb26340b150e831a8a9e25e3b68074c29e48dbe +Author: Keith Packard +Date: Fri Apr 24 19:13:31 2009 -0700 + + Enabling apogee detect via speed: < 200m/s && < max_speed - 50m/s + + This change ensures that we actually got going fairly fast, and then slowed + down a bunch before enabling apogee detect. Otherwise, we'll detect apogee + right off the pad as we're not going very fast at that point... + + This also adds the 'f' command to show the current flight status on the USB + port. + +commit 20b9f304ecbddd73a0ee2461b4c5e80f08157f98 +Author: Keith Packard +Date: Fri Apr 24 19:12:28 2009 -0700 + + configure igniter ports, set values to measured ones + +commit 6bf1d91ce0b723abe2bcec89668c13135ec044cf +Author: Keith Packard +Date: Fri Apr 24 19:11:40 2009 -0700 + + Move ao_led_init to end of file to be consistent with other files + +commit b4de7d550ec9a09ccf5f6a72debc6646706e3516 +Author: Keith Packard +Date: Fri Apr 24 19:10:20 2009 -0700 + + Define ao_state_names in ao.h so other people can share + +commit 8e62747b3692d0ac75b08eaf5c3e4b5d766be6ad +Author: Keith Packard +Date: Fri Apr 24 19:09:31 2009 -0700 + + Bump NUM_CMDS to 10 + +commit 2f781beb73ef24ab5fbe2688a83d07ad26c15972 +Author: Keith Packard +Date: Fri Apr 24 19:09:09 2009 -0700 + + Move beep_init to end of file to be consistent with other files + +commit b99315cee4ab796376458a2442cf36806fa4aed3 +Author: Keith Packard +Date: Fri Apr 24 10:19:31 2009 -0700 + + Update flight algorithm based on data collected from SN-1 Flight 1 + + This now correctly sequences through the flight data collected from the + first TeleMetrum test flight. + + This also completes up the flight algorithm test harness (ao_flight_test), + which runs the flight algorithm on the Linux host from a captured data log. + +commit b32f2f0090ff967edac07ae4d7a9895ed0b96d31 +Author: Keith Packard +Date: Thu Apr 23 22:17:44 2009 -0700 + + Add igniters and update flight control algorithm + +commit f155333ae18a25068644792e8940269d9fb28033 +Author: Keith Packard +Date: Fri Apr 24 00:15:09 2009 -0700 + + Avoid ram from 0xfda2 through feff, its funky + +commit f9c1c545c9dc11c3190a6cf7504883131fffce2f +Author: Keith Packard +Date: Thu Apr 23 22:18:33 2009 -0700 + + remove ao_flight_test until its ready + +commit 86e73c009f78dc4664883353124fc891fbb01dce +Author: Keith Packard +Date: Thu Apr 23 20:50:07 2009 -0700 + + Add teledongle module + +commit 204daac71ad56926730f5d6860bd70c645302e19 +Author: Keith Packard +Date: Thu Apr 23 14:26:01 2009 -0700 + + Set telemetry rate to 100ms + +commit 306b28f632e21b42ab165e7944283cf9764b590e +Author: Keith Packard +Date: Thu Apr 23 14:23:26 2009 -0700 + + Wrong license on ao_monitor.c + +commit dca3a6de26d26c0020f3fb2cf5d8ac1552c195b1 +Author: Keith Packard +Date: Thu Apr 23 14:23:00 2009 -0700 + + Crank up radio to 10dBm + +commit fbe3096f7e9a8112dbc79f376eccdaa6872ae520 +Author: Keith Packard +Date: Wed Apr 22 16:03:28 2009 -0700 + + Add COPYING file + +commit 9b7788f18bbaf3c4e5ebbf6c5ebd926468b0e045 +Author: Keith Packard +Date: Wed Apr 22 15:55:01 2009 -0700 + + Clean up TeleTerra files + +commit 61cee50c86e275f9fde875bd317c3e74255394ec +Author: Keith Packard +Date: Wed Apr 22 15:53:55 2009 -0700 + + simplify ao_time function + +commit 3703ecdc9e190f2e0b7ead0e71b78be881c1f3b7 +Author: Keith Packard +Date: Wed Apr 22 15:53:46 2009 -0700 + + One line radio status + +commit 1fbb3c17672a03ea6318fee07f9c2dcd7a8d0b16 +Author: Keith Packard +Date: Wed Apr 22 15:49:16 2009 -0700 + + Add new binaries to .gitignore + +commit 00d5610caff61559eb24c24beaa56629d6bb03be +Author: Keith Packard +Date: Wed Apr 22 15:49:00 2009 -0700 + + Speed up dbg port bit frobbing + +commit c7555eb16876aa8ff9fe7f648d325a1b8fb54d23 +Author: Keith Packard +Date: Wed Apr 22 15:48:28 2009 -0700 + + Use sdcc from path + +commit ada6dea04b94be016598566c4c13e6105aaec353 +Author: Keith Packard +Date: Wed Apr 22 15:48:14 2009 -0700 + + Clean up task list formatting + +commit 0a1b2297ee9f5bbb918bd72f26088a3e0b84839a +Author: Keith Packard +Date: Wed Apr 22 15:47:57 2009 -0700 + + Control radio monitoring with the M command + +commit 837c620f07b63efc171be3ac14c78bc99adf7592 +Author: Keith Packard +Date: Wed Apr 22 14:25:43 2009 -0700 + + Shrink USB output buffers, work around USB packet errors + +commit d87e9c25947d7cc2eba8894a524977f2c55a089a +Author: Keith Packard +Date: Tue Apr 21 02:07:24 2009 -0700 + + Clean up telemetry now that all packets are the same + +commit 1b333def5052d2ed47fdeaef23a897fe326f6340 +Author: Keith Packard +Date: Tue Apr 21 02:07:08 2009 -0700 + + Add longer debug delays to reset/debug_mode entry + +commit d1887ded41a5bfec8e10e9fd736fa9444b9b6222 +Author: Keith Packard +Date: Tue Apr 21 01:17:03 2009 -0700 + + Fix up fancy dbg stuff. Add teleterra initial bits. + + The dbg stuff needed a bit of help to actually walk the tables; it appears + that complex expressions confuse sdcc. + + This also adds primitive teleterra bits, but no UI, etc. + + Signed-off-by: Keith Packard + +commit 43c8f7012102cdb591ace899420c10e4a78385ad +Author: Keith Packard +Date: Mon Apr 20 23:33:41 2009 -0700 + + Add radio support. Build separate executables for TeleMetrum and the TI dongle + + Ok, way too big a patch, but things were in rough shape. + This patch adds support for the radio, both transmit and receive. + Then, because I could no longer run the TeleMetrum code on the TI + dongle, I ended up building a separate image for the TI board, which + involved creating a mechanism for having multiple command sets and splitting + code for different functions into different files. + +commit 5be13b76a2e29b84cd6d1eec065e3354b0dafce5 +Author: Keith Packard +Date: Sat Apr 18 23:19:24 2009 -0700 + + Start using pdata area for less-frequently used data + +commit 3e18b5a0d4c7d84df98b6ed0b7783de1d42d45bf +Author: Keith Packard +Date: Sat Apr 18 23:19:05 2009 -0700 + + Slow down panic presentation + +commit c4e983daa4579896b227fdcb2be43fad75e94307 +Author: Keith Packard +Date: Sat Apr 18 23:17:45 2009 -0700 + + Parse GPS data locally. Add 'g' command to display recent GPS results. + + This parses the GPS GGA message and stores it in a global variable, + protected by a mutex. + +commit ed6f67dc47d750d5ff8bea63ae7cbb560689b9b6 +Author: Keith Packard +Date: Sat Apr 18 23:16:01 2009 -0700 + + Add task names and 'T' command to show task status. + + The T command shows the current wchan and PC for each task in the system. + +commit 3d5a5fc4db5f681e848202c4ee4099d2879677d6 +Author: Keith Packard +Date: Sat Apr 18 19:32:18 2009 -0700 + + Fix GPL version at 2 + + Signed-off-by: Keith Packard + +commit 022f83ca6fd589005d8eb3e25e633950fef69fa7 +Author: Keith Packard +Date: Fri Apr 17 23:38:14 2009 -0700 + + Add gps, debug dongle support and pressure alt tables + + GPS also pulled in serial support. The altitude tables take raw 11-bit + pressure sample numbers and convert them to standard pressure altitude + values. + + Signed-off-by: Keith Packard + +commit 31fce622b1bab7e3f421069d7f6d4d9bdcd825de +Author: Keith Packard +Date: Fri Apr 17 10:32:45 2009 -0700 + + Enable FEC in radio packets + +commit 293a357911090a2f37bdd6f7ea96942079ffdf2e +Author: Keith Packard +Date: Fri Apr 17 10:29:42 2009 -0700 + + Add CRC to radio packets + +commit 20834caf01ddf481e8362b0d2627ef383a82e09d +Author: Keith Packard +Date: Fri Apr 17 10:23:10 2009 -0700 + + Add data whitening + +commit 94e5343a72121a81ab19bf5025e6b6fc9847eb4f +Author: Keith Packard +Date: Fri Apr 17 10:19:25 2009 -0700 + + Add packet status byte defines + +commit 04bc51c170c6f22bb5cc16867ce9a307818a7a00 +Author: Keith Packard +Date: Fri Apr 17 10:11:31 2009 -0700 + + Add separate xmit/recv programs to radio demo + +commit fafe55c3405964e0defdf25b6c00236f9aaefbc5 +Author: Keith Packard +Date: Fri Apr 17 10:11:11 2009 -0700 + + Get env var for debug method selection + +commit 26095fc0511ee0d5213f038986032f7c59964cf0 +Author: Keith Packard +Date: Fri Apr 17 10:10:47 2009 -0700 + + Run-time selection between cp2103 and cc1111 + +commit 543bedde83cbce5145668e72965e02d892187b59 +Author: Keith Packard +Date: Thu Apr 16 20:38:14 2009 -0700 + + Send data + +commit 5e2393eb6b1a6d7b180bd63d5165ee7b7ff5f9e0 +Author: Keith Packard +Date: Wed Apr 15 14:25:26 2009 -0700 + + Move a bunch of variables from __data to __xdata + +commit 4d1091d9bd121f05f5fe0a9c9d2bc0da8c562b9a +Author: Keith Packard +Date: Tue Apr 14 21:25:15 2009 -0700 + + Slow down panic code, disable interrupts + +commit 545478dd02eaeff6a65d318e722b1e4fce5e01b4 +Author: Keith Packard +Date: Tue Apr 14 21:24:25 2009 -0700 + + Keep reporting flight state while it changes + +commit 9605045164882b4ca3d1317ac860b02513a51f30 +Author: Keith Packard +Date: Tue Apr 14 21:23:55 2009 -0700 + + use red LED to indicate system startup + +commit dc844ee7e49a3b6145b3165252a592ed070d600f +Author: Keith Packard +Date: Tue Apr 14 21:23:13 2009 -0700 + + Use ao_ee_flush_internal while holding mutex + +commit 5e45d1c89b00e74d5b2730345843f43aab516af2 +Author: Keith Packard +Date: Tue Apr 14 21:22:56 2009 -0700 + + Leave beeping and lights to the flight code + +commit 902c342289c1d13a4d55b9224acb6d67578b7a60 +Author: Keith Packard +Date: Tue Apr 14 21:22:31 2009 -0700 + + Make mutex functions reentrant + +commit acc4fc635edb70ec1ba2dff9f7ac0c8542c72c47 +Author: Keith Packard +Date: Tue Apr 14 19:08:01 2009 -0700 + + Add in existing flight pieces: flight/report/log + + These pieces come from the old telemetrum firmware. + + Signed-off-by: Keith Packard + +commit ac99982b10fd5772218660137ee21db9b90cd885 +Author: Keith Packard +Date: Tue Apr 14 14:21:56 2009 -0700 + + Add eeprom driver and command loop + + This involved adding dma control and a mutex implementation. + + Signed-off-by: Keith Packard + +commit fbd8f4aff5058f4d371596b04715b7cb6d38e729 +Author: Keith Packard +Date: Tue Apr 14 11:04:09 2009 -0700 + + Switch from --model-large to --model-small + + This shrinks the application quite a bit, and should make it faster as well. + + Signed-off-by: Keith Packard + +commit fb63262699d3a6fbf347d24efda8b01f75b7d0d3 +Author: Keith Packard +Date: Tue Apr 14 10:02:19 2009 -0700 + + Add comments, clean up white space, etc. + + Various clean ups now that the basic code appears to work. + + Signed-off-by: Keith Packard + +commit 7e4abf3a40c39d0ce4f466281bef9a464df85dd4 +Author: Keith Packard +Date: Mon Apr 13 21:58:07 2009 -0700 + + Switch USB to double-buffered + +commit b56a44e48552bc32dbba9ff21770c370219a684a +Author: Keith Packard +Date: Mon Apr 13 21:51:59 2009 -0700 + + Fix USB input/output by reloading packet limits. + + The USB controller is reset during the connection process, which clears the + packet limits set in the controller at initialization time. Reload those + values when the configuration is set. + + Signed-off-by: Keith Packard + +commit cdaf3fc5802acf2ddc7972a15649ab0e1b31b873 +Author: Keith Packard +Date: Mon Apr 13 20:39:46 2009 -0700 + + USB working up through reading strings + +commit c5c1e3fb1c253d387be02c127253ac2a55d577b4 +Author: Keith Packard +Date: Mon Apr 13 13:51:08 2009 -0700 + + Add USB support. + + This offers a single CDC ACM device over USB. + + Signed-off-by: Keith Packard + +commit f3f25a1cec7d2a034aa544569cfd23bea1a996c5 +Author: Keith Packard +Date: Sun Apr 12 23:53:55 2009 -0700 + + Add beep/led support. + + Support our P2_0 connected buzzer, and formalize LED output support. + + Signed-off-by: Keith Packard + +commit e14f07bfdb8824fc7ed6df1129c66ee39ffd6d54 +Author: Keith Packard +Date: Sun Apr 12 23:17:16 2009 -0700 + + Add A/D sampler + + Sample A/D at the timer tick, placing data in a ring + of samples. + + Signed-off-by: Keith Packard + +commit 823f4f92de0c1f8dd7a644a8e56ffe9822bee6e2 +Author: Keith Packard +Date: Sun Apr 12 22:52:47 2009 -0700 + + Add 100Hz timer + + Use Timer 1 to generate a 100Hz timer interrupt + +commit 650a77e209dbb54c8d8fd9824cee430985564973 +Author: Keith Packard +Date: Sun Apr 12 21:58:49 2009 -0700 + + Update README + +commit 870e98334018a66de8a6e4a659d2dc5dee1cbecf +Author: Keith Packard +Date: Sun Apr 12 21:52:56 2009 -0700 + + GPL Version 2 only + +commit 11c526bdcbf4012e18fbfdc29ca8832870ca38f0 +Author: Keith Packard +Date: Sun Apr 12 21:47:32 2009 -0700 + + Add load command to s51 + +commit 55402ba3e87fd699c51079843309f1f0d1534724 +Author: Keith Packard +Date: Sun Apr 12 21:33:55 2009 -0700 + + Make test more complicated + +commit 3d3f849c9af9028f667cef4afedc0798d39a9efc +Author: Keith Packard +Date: Sun Apr 12 21:33:46 2009 -0700 + + SP points at last pushed byte + +commit f72c4cbc8fd9412dd1cce0fc446e7bbd2edc2d34 +Author: Keith Packard +Date: Sun Apr 12 20:27:03 2009 -0700 + + Add .gitignore + +commit 1903a86bf2cc6b685ccc475e62eabe49a4ec5b43 +Author: Keith Packard +Date: Sun Apr 12 20:25:39 2009 -0700 + + Initial AltOS import + +commit 5221dc63cf3a059a32aca2bfa7828c215be814a1 +Author: Keith Packard +Date: Sun Apr 12 12:38:58 2009 -0700 + + Add ccdump + +commit ee110425fb814780476d1d3d8a257af126f41763 +Author: Keith Packard +Date: Mon Apr 6 17:09:23 2009 -0700 + + Bump buffer pointer as data is written to cc-usb + +commit 2d9b8a83a2d9f495199033e43f519d26f27938fe +Author: Keith Packard +Date: Mon Apr 6 11:31:49 2009 -0700 + + Add support for a serial-connected custom debug dongle + + This uses the cc1111 board as a custom debug dongle with faster + methods for communicating with the debug target. + +commit 24edd56155ed0fa02fdd8f66fdc7aa5a1021bf7d +Author: Keith Packard +Date: Wed Apr 1 17:50:47 2009 -0700 + + Reset cc1111 on s51 exit + +commit 5fcfe854d29e1862d9a6adcbef3ef5119eb52fa3 +Author: Keith Packard +Date: Wed Apr 1 00:06:45 2009 -0700 + + Add timer-based beep test + +commit 91607bebdd167ac632aca4b66e22cb0cabdf0d20 +Author: Keith Packard +Date: Thu Mar 26 22:41:47 2009 -0700 + + Add readline support to s51 + +commit 66ee94ed10e3d79b24f45a5c63e58456d4d30343 +Author: Keith Packard +Date: Wed Mar 25 11:37:48 2009 -0700 + + Deal with MSB-outputing DMA engine + +commit d3732fd405af03c3752a84c4b78da7ef5ebd3744 +Author: Keith Packard +Date: Wed Mar 25 11:14:03 2009 -0700 + + Flip ADC bytes around + +commit 50cc8e97e76d9b60c622962e1c74cf422dfb2c0f +Author: Keith Packard +Date: Wed Mar 25 11:01:30 2009 -0700 + + Add spacing for serial adc data + +commit 5577ca3762bfc000b0bc3782c73a8f95996a28a6 +Author: Keith Packard +Date: Wed Mar 25 10:58:57 2009 -0700 + + Inc only one on dest addr + +commit 378227d869a3e8787c532c8c4e1563b44002c4b5 +Author: Keith Packard +Date: Wed Mar 25 10:55:17 2009 -0700 + + Dump remaining inputs + +commit f54a41e37d6897db2e24fbc82880076b78a0ae41 +Author: Keith Packard +Date: Wed Mar 25 10:50:36 2009 -0700 + + Remove poll for ti demo button + +commit 2b93a70fdd9e47e8195855451aa19ecad5d8b068 +Author: Keith Packard +Date: Wed Mar 25 10:50:14 2009 -0700 + + Add adc to serial conversion + +commit d9fd548db15232e3a8823815962b252c7a5e7cba +Author: Keith Packard +Date: Wed Mar 25 10:04:50 2009 -0700 + + Add ADC via DMA example + +commit 61faf2b773300988fe27cfde5bc045be9950a1b0 +Author: Keith Packard +Date: Wed Mar 25 09:45:14 2009 -0700 + + Add DMA example + +commit 7b3fdf5b42c9be9bebc1ceb7a52ff0f5a2a28fcd +Author: Keith Packard +Date: Wed Mar 25 01:05:36 2009 -0700 + + Back to 0dBm + +commit 31d59b88baa2cd96dc6263d1c5877283f2cd8c36 +Author: Keith Packard +Date: Wed Mar 25 01:03:08 2009 -0700 + + Make radio test compile again + +commit 9ce713fdd19bf1a51370dacba3670504356c5c11 +Author: Keith Packard +Date: Wed Mar 25 01:02:07 2009 -0700 + + Wait for xtal to stabilize + +commit ffd43886dc902f3bb7407294018e3d62cac39480 +Author: Keith Packard +Date: Wed Mar 25 00:55:11 2009 -0700 + + Check serial input + +commit 029963cc94fbb47560118b5de73c537e2c14ed7c +Author: Keith Packard +Date: Wed Mar 25 00:50:02 2009 -0700 + + Eliminate array walking + +commit 019456a17d36f8f9f9b72cfbc980492175086d32 +Author: Keith Packard +Date: Wed Mar 25 00:41:49 2009 -0700 + + Add a per-char delay + +commit cfaf187e96ba98eb8dd934409a10bc70273fe68a +Author: Keith Packard +Date: Wed Mar 25 00:36:35 2009 -0700 + + Use UTX1IF to wait for serial TX complete + +commit 006124529b243c7657a94312d2c868a82878d8bb +Author: Keith Packard +Date: Wed Mar 25 00:29:29 2009 -0700 + + Send more interesting text + +commit 5049acd3d1ae42304513f667f55a2ddffa4c685a +Author: Keith Packard +Date: Wed Mar 25 00:24:56 2009 -0700 + + More random serial bit frobbing + +commit 50bdc2407c674a4770912d3a626f36820a7f1527 +Author: Keith Packard +Date: Wed Mar 25 00:13:15 2009 -0700 + + Flip serial TX code around a bit + +commit 7b7617e376afe0df1d505375b76198358330370c +Author: Keith Packard +Date: Wed Mar 25 00:09:47 2009 -0700 + + Try serial polarity high/high + +commit 18edacdb1e6e429cc29a164e22ef2a566096b9d9 +Author: Keith Packard +Date: Wed Mar 25 00:06:32 2009 -0700 + + Make serial test simpler + +commit 62744c186792739c3bf5798c80ff87c69fbe2b65 +Author: Keith Packard +Date: Wed Mar 25 00:03:45 2009 -0700 + + Flip start/stop bits around + +commit 9e96107d5d1a9681b07c36bb5860c748bfe10ec0 +Author: Keith Packard +Date: Tue Mar 24 23:57:12 2009 -0700 + + Stop high + +commit c41ceb9a488b2209d1d3c09967d1473ce608030f +Author: Keith Packard +Date: Tue Mar 24 23:24:01 2009 -0700 + + Change radio to -30dBm + +commit c35de083ca3d4f362063b056a0fd74ffe629d168 +Author: Keith Packard +Date: Tue Mar 24 23:11:48 2009 -0700 + + Add serial test program + +commit 8ecbd8734f0fb5588b2a8eb20720cfc6f43dfb47 +Author: Keith Packard +Date: Tue Mar 24 22:37:38 2009 -0700 + + Wait for xtal to stabilize after changing to 24MHz + +commit e120269fc0f8e14ddf1755337b1d092173e16da2 +Author: Keith Packard +Date: Tue Mar 24 22:21:31 2009 -0700 + + Actually return byte read from SPI + +commit de1ac6f99a1526fa840a52cfc10fa3edc0589bed +Author: Keith Packard +Date: Tue Mar 24 22:12:51 2009 -0700 + + Clear UxCSR_TX_BYTE after transmitting a byte + +commit 3ed3ff63e46767a256d30c5da5c52ae20089a91d +Author: Keith Packard +Date: Tue Mar 24 20:04:58 2009 -0700 + + Led the LED turn on + +commit 91b3a6ae74184692f45702587c4d678b2799ad8c +Author: Keith Packard +Date: Tue Mar 24 19:55:04 2009 -0700 + + actually write and compare SPI test bits + +commit 7de3a43887485c3c6cf52960376ccde33fb33985 +Author: Keith Packard +Date: Tue Mar 24 19:54:02 2009 -0700 + + Add USART-based SPI test code + +commit ef0eef68280e9b6ca5e3bb71062e23054340e1ed +Author: Keith Packard +Date: Tue Mar 24 17:22:36 2009 -0700 + + Change spi test string + +commit 8131389ee5018c05b721146a98367150cf500fdf +Author: Keith Packard +Date: Tue Mar 24 17:15:09 2009 -0700 + + Oops, not merging in the bit read for SPI test + +commit 3429016d1359ec650993d2fb0596184e3f717871 +Author: Keith Packard +Date: Tue Mar 24 17:04:45 2009 -0700 + + Adjust clock/data phase for spi test + +commit fedd18b28ea54e1dabcd2f9e8cab3ae4ee0fd070 +Author: Keith Packard +Date: Tue Mar 24 16:35:13 2009 -0700 + + MISO needs to be an input + +commit f0c233f25a208a636833312b1766825815735304 +Author: Keith Packard +Date: Tue Mar 24 15:41:55 2009 -0700 + + Add bit-banging spi eeprom test program + +commit 6eeee64cf16ccc9218dbdde5426f25bda5e3407f +Author: Bdale Garbee +Date: Wed Mar 18 02:58:33 2009 -0600 + + working beep at around 4khz + +commit 4726317de811c20e8d6754762437b5c9cbb3a48c +Author: Keith Packard +Date: Wed Mar 18 01:54:34 2009 -0700 + + Add simple test program to light up the transmitter at 434.550MHz + + This starts a transmit sequence, but doesn't send any data so the + transmitter just locks on. + +commit a0a27600ee2bf237e74eb83767a8d2e7c91df24f +Author: Keith Packard +Date: Sun Mar 15 18:14:21 2009 -0700 + + Correctly comment which bit the beep program uses + +commit 25b77d236c01258abfc03114c2fc9ea2d69ca6e7 +Author: Keith Packard +Date: Sun Mar 15 18:11:53 2009 -0700 + + Add telemetrum beeper example + +commit 164b4e4749ad64ebbe26e84fd7b4fa1aa733dbe4 +Author: Keith Packard +Date: Sun Mar 15 18:11:20 2009 -0700 + + sdcc gets the lib path correct based on the model + +commit 04a316133af93b79bfbebb91f05eec1015ec2abc +Author: Keith Packard +Date: Sun Mar 15 18:10:43 2009 -0700 + + Bump debug speed back up + +commit 9fd63972758d6d5572f7bcaadec9b1c0e974a2e8 +Author: Keith Packard +Date: Sat Mar 7 21:05:40 2009 -0800 + + Only flip changing bits in async mode + +commit c8fd04e154bcfd65ae1200980bd8163caabd7fe4 +Author: Keith Packard +Date: Sat Mar 7 21:05:06 2009 -0800 + + The debug port only works if reset is higher than clock. weird + +commit ade11f88754b4ab0386ebf86afc5257e59238f62 +Author: Keith Packard +Date: Sat Mar 7 21:04:38 2009 -0800 + + Make manual bit flipping sync after every transaction + +commit e63b5271bb54afc36e4b9891e51e053ff6011092 +Author: Keith Packard +Date: Sat Mar 7 14:49:22 2009 -0800 + + Add ccmanual + +commit 77d754afc2d14aaa4413c13ebe3777ef385f62a9 +Author: Keith Packard +Date: Sat Mar 7 14:48:49 2009 -0800 + + Sync after manual bit reading + +commit 5a338c8a7394d003355f96a8777b6fe83bb8493c +Author: Keith Packard +Date: Sat Mar 7 14:48:35 2009 -0800 + + Flip debug pins around to match telemetrum + +commit cc0495b7028f4b1189a00707d828a68534d1dea2 +Author: Keith Packard +Date: Fri Mar 6 22:52:35 2009 -0800 + + Wait for a while when switching the RESET_N line + + The cc1111 manual suggests placing a 2.7kΩ resister and 1nF capacitor on the + RESET_N line to filter out noise. This increases the time necessary to reset + the chip to several microseconds which is longer than the interval between + two USB packets. Flush the USB packet queue and sleep for a while after + changing the value on the RESET_N line to make sure the chip sees the state + change. + + Signed-off-by: Keith Packard + +commit 41289e6d8f1767547a33fea349866e928e44910f +Author: Bdale Garbee +Date: Mon Mar 2 07:46:20 2009 -0700 + + minor s51.1 formatting fixes + + Signed-off-by: Keith Packard + +commit fdee231ed097a4348aee78fbd4aa92826b80de03 +Author: Keith Packard +Date: Sun Mar 1 23:12:31 2009 -0800 + + Add s51 manual. + + This documents (briefly) the s51 hex debugging interface program, including + some simple commands to test the operation of the system interactively. + + Signed-off-by: Keith Packard + +commit f7d91bd23b8214e09deae0aafb516331e934c49b +Author: Keith Packard +Date: Sun Mar 1 18:43:03 2009 -0800 + + Sometimes the link breaks and the GET_PC command returns garbage + +commit 3cc8d11eb8d5d0b42141dd84a58d461287f59e3a +Author: Keith Packard +Date: Sun Jan 25 08:38:48 2009 -0800 + + Support 'set' command + + The 'set' command modifies target memory and registers + + Signed-off-by: Keith Packard + +commit 60940b4be23962db79b8e914ec943d0636dd68ad +Author: Keith Packard +Date: Mon Jan 5 21:45:21 2009 -0800 + + Expose ccdbg_set_clock API + + This allows applications to change the debug port clock + rate on the fly. + + Signed-off-by: Keith Packard + +commit eb09e61b0682eb2aeac8e1a34d58b897ba6db8e7 +Author: Keith Packard +Date: Mon Jan 5 21:44:44 2009 -0800 + + Use custom sdcc libraries (this needs to be configured...) + + Signed-off-by: Keith Packard + +commit 1ccfe0887c794397131ab1c986c25f66eea86a6c +Author: Keith Packard +Date: Mon Jan 5 21:43:44 2009 -0800 + + Have S51 ignore SIGINT while running under sdcdb. + + This prevents keyboard interrupts from accidentally stopping + s51. + + Signed-off-by: Keith Packard + +commit 7c03937b36aac82b08f4ea0c6da33a994fe15ec7 +Author: Keith Packard +Date: Tue Dec 30 22:40:13 2008 -0800 + + Add simple and timer sample programs + + Signed-off-by: Keith Packard + +commit 6c2a65c743a4ffae96ed27dbc38c1bf9242ed1df +Author: Keith Packard +Date: Tue Dec 30 22:35:53 2008 -0800 + + Save/restore registers to host during memory operations. Cache ROM data. + + Because the debug port uses instructions for most operations, the debug code + will clobber registers used by the running program. Save and restore these + to avoid corrupting application data. + + If the ROM file is known, use that to return data instead of fetching it + from the target to improve performance. + + Signed-off-by: Keith Packard + +commit ea366058aa467a8a7caf17e7014758f3741ea7f7 +Author: Keith Packard +Date: Mon Dec 29 12:35:11 2008 -0800 + + Fix flashing less than a full page of data. Verify page at a time. + + The 8051 flashing code requires special help with counts with non-zero low + byte. Also, instead of verifying the entire flash contents at the end, + verify each page as it goes. + + Signed-off-by: Keith Packard + +commit e0697186a2f9b6139636ff5d5c162879c85caf9c +Author: Keith Packard +Date: Sun Dec 28 00:11:13 2008 -0800 + + Use SFR access funcs. Support 'dump' command. Add -m (monitor) flag. + + Not all SFRs are visible in the unified address space, so the SFR-specific + accessors are required. + + The dump command is the same as the various 'd*' + commands, but also supports dumping program memory. + + The new -m (monitor) flag watches the command stream between s51 and sdcdb. + + Signed-off-by: Keith Packard + +commit 23aca1fcbc169184e32d4ec19f28dd4fd4cfda36 +Author: Keith Packard +Date: Sun Dec 28 00:09:30 2008 -0800 + + Save/restore regs when reading/writing memory. Add SFR access. + + The DPL and ACC registers are used by the memory access code, + so they need to be saved and restored. Stuff them up high in ram for now; + this should probably be fixed to pull them back to the host instead. + + Special SFR access is required as not all SFRs are visible in the unified + address space. + + Signed-off-by: Keith Packard + +commit 1405838160b69e2cda456e21502a1d03b3aa7548 +Author: Keith Packard +Date: Sat Dec 27 11:25:58 2008 -0800 + + s51: get start address from ihx file. re-enable breakpoints after reset. + + Use the start of the ihx file when asked to run from 0x0, this lets + sdcdb run programs from ram. + + The reset command clears all hw breakpoints, so reset them afterwards. + + Signed-off-by: Keith Packard + +commit 1264c3676e95427bba5d01e05c303d036a7f9eca +Author: Keith Packard +Date: Fri Dec 26 23:05:04 2008 -0800 + + Switch to libusb-1.0 and use async interface. + + The async libusb interface offers substantial performance benefits by not + making each command wait for the reply. This makes talking over this + interface almost reasonable. + + Signed-off-by: Keith Packard + +commit d2d9cfd74fd66836c913c02276e09136d83b35dc +Author: Keith Packard +Date: Fri Dec 26 17:58:48 2008 -0800 + + s51: add breakpoints and the ability to block awaiting a breakpoint. + + Signed-off-by: Keith Packard + +commit 4c4093c3fdd309123fdd068c0e1ff4947104492d +Author: Keith Packard +Date: Mon Dec 22 19:11:56 2008 -0800 + + Add more commands to s51 assembly-language debugger + + Signed-off-by: Keith Packard + +commit 55eba4fa08b022197106245d36a70f575a070b0a +Author: Keith Packard +Date: Mon Dec 22 19:10:27 2008 -0800 + + Make read_memory debug output use ccdbg_debug. + + This makes it default to not being presented, which makes s51 much happier + + Signed-off-by: Keith Packard + +commit e75918f3667a5c8ad294bec4acef6fe81682edf6 +Author: Keith Packard +Date: Sun Dec 21 23:33:35 2008 -0800 + + Add preliminary version of s51, a UI clone of the 8051 emulator. + + sdcdb provides source-level debugging using the 8051 emulator, s51. By + emulating that emulator a the UI level, we should be able to get source + debugging right on our target platform. + + This is just the preliminary structure for the program with most commands + not yet implemented. + +commit f7d49868aeae80d515b12a7e339628f1296754a6 +Author: Keith Packard +Date: Sat Dec 20 23:30:06 2008 -0800 + + Cleanup work; separating out the cp interface to be more abstract. + + Signed-off-by: Keith Packard + +commit 30f23f23a6db3d12fdc9c088cf6ab47c5e5077fb +Author: Keith Packard +Date: Fri Dec 19 21:13:04 2008 -0800 + + Clean up autotools stuff. + + Signed-off-by: Keith Packard + +commit 9025eb792861930e6af918d2727c4f5d97a69936 +Author: Keith Packard +Date: Fri Dec 19 21:11:45 2008 -0800 + + Autotools. + + Signed-off-by: Keith Packard + +commit ab909db28307cfbf7ee8d692506bb79d7ffd627a +Author: Keith Packard +Date: Fri Dec 19 19:08:13 2008 -0800 + + Ignore .ihx files + +commit cc8db276bc4f2fd7eb00168a5c0689a8457a5c6f +Author: Keith Packard +Date: Fri Dec 19 19:07:37 2008 -0800 + + Move blink example to subdir + + Signed-off-by: Keith Packard + +commit 82e2d7ebed6682062dc400478c736bd6c91195c9 +Author: Keith Packard +Date: Fri Dec 19 19:04:26 2008 -0800 + + Clean up makefiles, move ihx files to .ihx + +commit 52fb5f795adfd7f62e5b6dbe65877d14361cfdae +Author: Keith Packard +Date: Fri Dec 19 14:39:57 2008 -0800 + + ignore more stuff + +commit 4ecfc33f16aa36b315519e6f279da65374b67aba +Author: Keith Packard +Date: Fri Dec 19 14:37:53 2008 -0800 + + Add cc1111 isr stub example + +commit d32e6658c3e489b62ba3cf6d22e3ab177b9b8a3a +Author: Keith Packard +Date: Fri Dec 19 14:37:29 2008 -0800 + + Add blink-tiny flash and ram versions + +commit b4d1127ef007843c643b778b3b2f6b915b1d5d9a +Author: Keith Packard +Date: Fri Dec 19 14:19:29 2008 -0800 + + Flash multiple pages. Eliminate off-by-one error in hex_image length. + + Signed-off-by: Keith Packard + +commit 55995515b9d4fc1e193039eab697c5d03db417c2 +Author: Keith Packard +Date: Fri Dec 19 11:04:16 2008 -0800 + + Add flash writing code. + + Signed-off-by: Keith Packard + +commit 0bc52385b8f86f9ca1c450ad106e6d8afe3bc153 +Author: Keith Packard +Date: Thu Dec 18 12:37:32 2008 -0800 + + faster + + Signed-off-by: Keith Packard + +commit 3779cc8b32cac3640f42bd0400d4199ddae965a1 +Author: Keith Packard +Date: Thu Dec 18 12:17:41 2008 -0800 + + cq + + Signed-off-by: Keith Packard + +commit dc03adc179669d41e3551d74b3c5a60db41ff217 +Author: Keith Packard +Date: Thu Dec 18 12:07:06 2008 -0800 + + Add ability to load Intel HEX files. Add sample sdcc LED blinker. + + Signed-off-by: Keith Packard + +commit 807e2adacb025af77bb53c03209e9c8e0d7a5f95 +Author: Keith Packard +Date: Thu Dec 18 00:18:50 2008 -0800 + + Add ability to read/write arbitrary memory. Write LED blinker program. + + Signed-off-by: Keith Packard + +commit 8c879bf51c14a5928135d59211facd72f6a32808 +Author: Keith Packard +Date: Wed Dec 17 23:15:47 2008 -0800 + + Move manual bit-banging debug code to separate file + + Signed-off-by: Keith Packard + +commit aec3bbce84a5ceb92060a4b3889379f2af2404ac +Author: Keith Packard +Date: Wed Dec 17 23:15:19 2008 -0800 + + reduce clock to 50us + + Signed-off-by: Keith Packard + +commit fa168f963f8b00144d12aa2770e9c0917cfae123 +Author: Keith Packard +Date: Wed Dec 17 23:12:59 2008 -0800 + + Fill out ccdbg-command to support all debug commands. + + Signed-off-by: Keith Packard + +commit 5df84df7cd6a31527dcfd11030f00ef9d8abf170 +Author: Keith Packard +Date: Wed Dec 17 22:24:59 2008 -0800 + + Clean up bitbanging layer. Add debug printfs. + + Signed-off-by: Keith Packard + +commit 584e28bac8af38de433767e017977ed1adddeb36 +Author: Keith Packard +Date: Wed Dec 17 12:32:15 2008 -0800 + + Clean up sample debug files + + Signed-off-by: Keith Packard + +commit e64b4dbf15e9ee1cb0de002985de7575e83d46e9 +Author: Keith Packard +Date: Mon Dec 8 17:25:28 2008 -0800 + + Add support for input-only lines (-) + +commit 4f38974a9941cddaba27c17c5a46f923db386c94 +Author: Keith Packard +Date: Sat Dec 6 16:32:27 2008 -0800 + + Add another example + +commit 3709ec3205cfb152b6568f3ea505c67fe7504c2a +Author: Keith Packard +Date: Sat Dec 6 16:32:12 2008 -0800 + + Add libusb support and lots more examples + +commit 39801e6e9fb9388072ee414a447f74095a6ac960 +Author: Keith Packard +Date: Fri Nov 28 22:57:07 2008 -0800 + + Random hacking + +commit 01cb2799875e086ee6096627c058ee235bbc33d5 +Author: Keith Packard +Date: Thu Nov 27 17:07:15 2008 -0800 + + Add prototypes, add stub mainline, add .gitignore + +commit 0ffe4ef870b0e564789a1990aeab5b6651868e5b +Author: Keith Packard +Date: Thu Nov 27 12:33:40 2008 -0800 + + cc1111 debug port access through cp2103 serial chip diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 642af2fe..c27fcbe9 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -89,9 +89,6 @@ rewrite(struct hex_image *image, unsigned addr, char *data, int len) memcpy(image->data + addr - image->address, data, len); } -<<<<<<< HEAD:ao-tools/ao-load/ao-load.c -static const struct option -======= static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { 0, 0, 0, 0}, @@ -103,7 +100,6 @@ static void usage(char *program) exit(1); } ->>>>>>> c29275b72438637d46d7a50742882d2736eb176a:ao-tools/ao-load/ao-load.c int main (int argc, char **argv) { diff --git a/debian/altos.install b/debian/altos.install new file mode 100644 index 00000000..aac3544b --- /dev/null +++ b/debian/altos.install @@ -0,0 +1,3 @@ +debian/repository etc/apt/sources.list.d/altos.list +src/*.ihx usr/share/altos +src/*.map usr/share/altos diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 00000000..b92a2284 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +altos (0) unstable; urgency=low + + * Initial packaging + + -- Bdale Garbee Tue, 18 Aug 2009 11:43:43 -0600 diff --git a/debian/compat b/debian/compat new file mode 100644 index 00000000..7f8f011e --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +7 diff --git a/debian/control b/debian/control new file mode 100644 index 00000000..3aa6d5dd --- /dev/null +++ b/debian/control @@ -0,0 +1,17 @@ +Source: altos +Section: otherosfs +Priority: extra +Maintainer: Bdale Garbee +Uploaders: Keith Packard +Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline5-dev, libusb-1.0-0-dev, nickle, sdcc +Standards-Version: 3.8.3 +Homepage: http://altusmetrum.org/ + +Package: altos +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, nickle +Description: Altus Metrum firmware and utilities + Firmware and utilities needed to support the TeleMetrum dual-deploy + recording altimeter for high power model rocketry. + . + See http://altusmetrum.org/ for more information. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 00000000..7d9a469e --- /dev/null +++ b/debian/copyright @@ -0,0 +1,36 @@ +This package was debianized by Bdale Garbee on +Mon, 17 Aug 2009 23:01:22 -0600. + +It was downloaded from git.gag.com. + +Upstream Authors: + + Keith Packard + Bdale Garbee + +Copyright: + + Copyright © 2009 Keith Packard + +License: + + 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., + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + +The Debian packaging is: + + Copyright (C) 2009 Bdale Garbee + +and is also licensed under the GPL version 2. + +For a complete copy of the license, see `/usr/share/common-licenses/GPL-2'. diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 00000000..8b9a4657 --- /dev/null +++ b/debian/dirs @@ -0,0 +1,3 @@ +etc/apt/sources.list.d +usr/bin +usr/share/altos diff --git a/debian/docs b/debian/docs new file mode 100644 index 00000000..50bd824b --- /dev/null +++ b/debian/docs @@ -0,0 +1,2 @@ +NEWS +README diff --git a/debian/menu b/debian/menu new file mode 100644 index 00000000..7e15c9c8 --- /dev/null +++ b/debian/menu @@ -0,0 +1,2 @@ +?package(altos):needs="X11" section="Applications/Viewers"\ + title="aoview" command="/usr/bin/aoview" diff --git a/debian/repository b/debian/repository new file mode 100644 index 00000000..201a4a2f --- /dev/null +++ b/debian/repository @@ -0,0 +1,2 @@ +deb http://altusmetrum.org/apt sid main +deb-src http://altusmetrum.org/apt sid main diff --git a/debian/rules b/debian/rules new file mode 100755 index 00000000..078dac56 --- /dev/null +++ b/debian/rules @@ -0,0 +1,78 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +export DH_VERBOSE=1 +PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') + +# this target invoked by git-buildpackage using a clean hook, see .gbp.conf +prebuild: + dch -v `git describe | tr - +` "build for Debian from git" + git log > ChangeLog + git commit ChangeLog debian/changelog \ + -m "update changelogs for Debian build" + +configure: configure-stamp +configure-stamp: + dh_testdir + ./autogen.sh --prefix=/usr + touch configure-stamp + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + $(MAKE) VERSION=$(PKG_VERSION) + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + [ ! -f Makefile ] || $(MAKE) distclean + dh_clean + +install: build + dh_testdir + dh_testroot + dh_prep + dh_installdirs + + $(MAKE) DESTDIR=$(CURDIR)/debian/altos install + +# Build architecture-independent files here. +binary-indep: install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: install + dh_testdir + dh_testroot + dh_installchangelogs ChangeLog + dh_installdocs + dh_installexamples + dh_install +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_python +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_perl +# dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/src/Makefile b/src/Makefile index 297f676b..5a8afe0b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,9 @@ # CC=sdcc +ifndef VERSION VERSION=$(shell git describe) +endif CFLAGS=--model-small --debug --opt-code-speed -- cgit v1.2.3 From dd09f0bc2b950c00f3b489878cd69ad8a003f46c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Aug 2009 21:57:01 -0600 Subject: update changelogs for Debian build --- ChangeLog | 307 +------------------------------------------------------ debian/changelog | 6 ++ 2 files changed, 9 insertions(+), 304 deletions(-) diff --git a/ChangeLog b/ChangeLog index 43ce3930..8fe3609b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,57 +1,8 @@ -commit ea86b19629001059952f7572fa8564e2263dc9f6 +commit cd5ce661e2a8f9694933358ccb5b916fbed089c2 Author: Bdale Garbee -Date: Tue Aug 18 20:47:41 2009 -0600 +Date: Tue Aug 18 21:49:39 2009 -0600 - deliver sources.list.d fragment so updates are closer to automatic - -commit cec78502c06f11880366f6131c0442906c6ed864 -Author: Bdale Garbee -Date: Tue Aug 18 20:17:31 2009 -0600 - - update changelogs for Debian build - -commit 82d24bc65af85231b0d67394b30adfdb7beb6564 -Author: Bdale Garbee -Date: Tue Aug 18 20:17:08 2009 -0600 - - we need ChangeLog in the repo for git-buildpackage to work right - -commit c8e04df1423bfd4e9318d9fccae2cfb4a97983ab -Author: Bdale Garbee -Date: Tue Aug 18 20:12:44 2009 -0600 - - update Debian changelog for build - -commit 2fda90c0f8ab46a83175ed168fcba9b11efcd453 -Author: Bdale Garbee -Date: Tue Aug 18 20:12:22 2009 -0600 - - update Debian changelog for build - -commit a40f45bf4791bced48efb728be8990e41a7e4280 -Author: Bdale Garbee -Date: Tue Aug 18 20:08:10 2009 -0600 - - move the ChangeLog creation to the prebuild target - -commit ae7752210a0e06beacad011c17dbf75bff39eda8 -Author: Bdale Garbee -Date: Tue Aug 18 18:57:56 2009 -0600 - - update Debian changelog for build - -commit c7f7a1ed3494db008b397a613cfcd3ab36c01920 -Author: Bdale Garbee -Date: Tue Aug 18 18:56:20 2009 -0600 - - update Debian changelog for build - -commit ebaf8b0d02d82bce7c7ea78e281377768b996d6d -Merge: 79501a5 d996aa9 -Author: Bdale Garbee -Date: Tue Aug 18 18:56:16 2009 -0600 - - Merge branch 'master' into debian + add support for building Debian package commit d996aa9b32fb0eb385bd3d158256c29788a42fe3 Merge: b3b2d3c 7d4ceb7 @@ -70,13 +21,6 @@ Date: Tue Aug 18 17:55:22 2009 -0700 Signed-off-by: Keith Packard -commit 79501a5462ab29d661cf76f63628bd4616b6ae1b -Merge: f48eb20 b3b2d3c -Author: Bdale Garbee -Date: Tue Aug 18 18:37:10 2009 -0600 - - Merge branch 'master' into debian - commit b3b2d3c475a135084b5628c730fc6fca1ba0817b Merge: 4685fc5 da12b89 Author: Bdale Garbee @@ -84,12 +28,6 @@ Date: Tue Aug 18 18:36:03 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos -commit f48eb2033f3685fedd42d307963671a8060604c3 -Author: Bdale Garbee -Date: Tue Aug 18 18:33:53 2009 -0600 - - don't ship a zero-length ChangeLog, when it's easy to make one... - commit da12b89fb056a68e65ba363fef91d266727cb685 Author: Keith Packard Date: Tue Aug 18 17:30:43 2009 -0700 @@ -102,43 +40,6 @@ Date: Tue Aug 18 17:29:29 2009 -0700 Fix ao-bitbang examples to not have . in the first column -commit 192b08c28719b5518ed349d9897f9a21add3c615 -Author: Bdale Garbee -Date: Tue Aug 18 18:24:50 2009 -0600 - - update Debian changelog for build - -commit 5969d1d0e3aa554187a5bcc899a2f1347656fd5e -Author: Bdale Garbee -Date: Tue Aug 18 18:24:22 2009 -0600 - - fixing things lintian points out - -commit 9bf7c23f6e8ac7080240b91a28b355e50ecb4c4d -Author: Bdale Garbee -Date: Tue Aug 18 18:14:02 2009 -0600 - - update Debian changelog for build - -commit d861218bc6c2f57816953af3271d93fc48f8afc2 -Author: Bdale Garbee -Date: Tue Aug 18 18:13:48 2009 -0600 - - fix merge conflict - -commit 3f953f56fbfd4e903c09ca1e4309664d38c2c669 -Author: Bdale Garbee -Date: Tue Aug 18 18:10:06 2009 -0600 - - update Debian changelog for build - -commit 7fcbe76ce82ec5a17cf536afa0d1b9061e225aa9 -Merge: 035ba6d 4685fc5 -Author: Bdale Garbee -Date: Tue Aug 18 18:09:59 2009 -0600 - - Merge branch 'master' into debian - commit 4685fc541466afbeefc151bcb64cd054739c048b Merge: 1c2a0b6 c29275b Author: Bdale Garbee @@ -189,44 +90,12 @@ Date: Tue Aug 18 12:40:24 2009 -0700 Signed-off-by: Keith Packard -commit 035ba6df17f016953351bc77a98623c165b69909 -Author: Bdale Garbee -Date: Tue Aug 18 14:40:58 2009 -0600 - - update Debian changelog for build - -commit 7aa251970cbbb6b9d9678ed0721e28da3df9036b -Merge: 107055e 1c2a0b6 -Author: Bdale Garbee -Date: Tue Aug 18 14:40:54 2009 -0600 - - Merge branch 'master' into debian - commit 1c2a0b6653623b689d68d7349a6b2dce3e20a4a6 Author: Keith Packard Date: Tue Aug 18 13:36:54 2009 -0700 re-add debugger sources -commit 107055e969e89771d1e2f8ac8b1a4c5b4b9e9a48 -Author: Bdale Garbee -Date: Tue Aug 18 14:03:48 2009 -0600 - - update Debian changelog for build - -commit 14915158049918fa2fa5294f325b77dc9b08bab8 -Author: Bdale Garbee -Date: Tue Aug 18 14:03:41 2009 -0600 - - update Debian changelog for build - -commit 0fcc426f96577ebbaf0c2d009cd2708e974de315 -Merge: 91b8592 9789ca5 -Author: Bdale Garbee -Date: Tue Aug 18 14:03:16 2009 -0600 - - Merge branch 'master' into debian - commit 9a9cce5510b87252f863239ac807b9fb4395b288 Author: Keith Packard Date: Tue Aug 18 12:19:31 2009 -0700 @@ -244,49 +113,6 @@ Date: Tue Aug 18 12:40:24 2009 -0700 Signed-off-by: Keith Packard -commit 91b85929df6a3464396702fd177a6f74c6f28c7a -Author: Bdale Garbee -Date: Tue Aug 18 12:59:36 2009 -0600 - - update Debian changelog for build - -commit 645cc909a279347aa1665ce883c71090b29935a9 -Author: Bdale Garbee -Date: Tue Aug 18 12:59:28 2009 -0600 - - update Debian changelog for build - -commit f54e075705b3d4d6919494e8cff99141128f0303 -Author: Bdale Garbee -Date: Tue Aug 18 12:59:15 2009 -0600 - - deliver firmware files too - -commit 30fb0e78a464794a11fb8cf4ae385c3123922371 -Author: Bdale Garbee -Date: Tue Aug 18 12:52:39 2009 -0600 - - update Debian changelog for build - -commit 022e77db3416175e9b440828f94fb75b739ec00a -Author: Bdale Garbee -Date: Tue Aug 18 12:49:05 2009 -0600 - - oops, need to force prefix to /usr for Debian policy compliance - -commit a382039ebb91e3bea682b601feef15517290ad3b -Author: Bdale Garbee -Date: Tue Aug 18 12:39:41 2009 -0600 - - update Debian changelog for build - -commit 90347b16e11743e80f85308700e50b1228c2b8e0 -Merge: 06a0e43 a578239 -Author: Bdale Garbee -Date: Tue Aug 18 12:39:17 2009 -0600 - - Merge branch 'master' into debian - commit a5782398d968e7cb11f7203afada7c216f233b3b Author: Keith Packard Date: Tue Aug 18 11:34:28 2009 -0700 @@ -301,133 +127,6 @@ Date: Tue Aug 18 11:34:28 2009 -0700 Signed-off-by: Keith Packard -commit 06a0e432480efb4e10220b0bdf402282aad32de9 -Author: Bdale Garbee -Date: Tue Aug 18 12:16:23 2009 -0600 - - update Debian changelog for build - -commit f9126a21b6a027e56d3c9d086889375fd7f37f3c -Author: Bdale Garbee -Date: Tue Aug 18 12:06:03 2009 -0600 - - update Debian changelog for build - -commit 4d7c4c69a5e0ab16018c2a9325168e363a10084b -Author: Bdale Garbee -Date: Tue Aug 18 12:05:46 2009 -0600 - - fix the changelog version extraction to work for a native version - -commit fc761cc0117cb5a091b041b73b34d222b56a60f0 -Author: Bdale Garbee -Date: Tue Aug 18 11:58:29 2009 -0600 - - update Debian changelog for build - -commit 9a97abb7b1afc90e8f67ba065583a49107a55f61 -Author: Bdale Garbee -Date: Tue Aug 18 11:58:18 2009 -0600 - - update Debian changelog for build - -commit 24c337de950ac5d4b1d074dc20eb7c6a68338462 -Author: Bdale Garbee -Date: Tue Aug 18 11:58:11 2009 -0600 - - oops, fix syntax - -commit 11c610c0e09d4f175b7e164e071ada361a1e9e2e -Author: Bdale Garbee -Date: Tue Aug 18 11:57:52 2009 -0600 - - update Debian changelog for build - -commit f65fa2b7d810ebae4b6df313de8bfe3687223a16 -Author: Bdale Garbee -Date: Tue Aug 18 11:57:00 2009 -0600 - - call debian/rules prebuild before creating source tarball - -commit dc5679ee90429fe43c6180d1d298183a79334dfc -Author: Bdale Garbee -Date: Tue Aug 18 11:54:11 2009 -0600 - - update Debian changelog for build - -commit cf1fa8b062c05ee995d6befee9088908b2b22473 -Author: Bdale Garbee -Date: Tue Aug 18 11:53:31 2009 -0600 - - add a prebuild target for use from git-buildpackage clean hook, that creates - a new debian/changelog entry based on git-describe output - -commit d7e60e48b6d85274690478223ef3b571a818e228 -Author: Bdale Garbee -Date: Tue Aug 18 11:52:46 2009 -0600 - - update Debian changelog for build - -commit e946fa231a719abfdd3f319b8c3345dfc75ee185 -Author: Bdale Garbee -Date: Tue Aug 18 00:08:30 2009 -0600 - - allow pass-in of VERSION, only call git describe if VERSION not set yet - -commit f762a9dfb3b9c81e443a85cd434154598c737ed8 -Author: Bdale Garbee -Date: Tue Aug 18 00:06:24 2009 -0600 - - see if this works - -commit c6514ac5c47b44456a15d0f627f274eca769122e -Author: Bdale Garbee -Date: Tue Aug 18 00:03:27 2009 -0600 - - undo the post-commit hook stuff - -commit 2d53e72e938086688c81d16750b2c880fee1f4cd -Author: Bdale Garbee -Date: Mon Aug 17 23:55:47 2009 -0600 - - tweak makefile to use version file instead of calling git describe directly - -commit 2732624c67f5397fed5f31b062feb0f27b7f8fbd -Author: Bdale Garbee -Date: Mon Aug 17 23:53:35 2009 -0600 - - add version to the list of ignored files - -commit 08b28a0d4a71ba25ca949fe57bb150a89b401cef -Author: Bdale Garbee -Date: Mon Aug 17 23:39:35 2009 -0600 - - add build dependencies - -commit bc5d65b7e9776c87948edc4bd88fc4125ca20209 -Author: Bdale Garbee -Date: Mon Aug 17 23:32:49 2009 -0600 - - build as a Debian specific package since we have no "upstream" - -commit e4fb67c989e10f626042e3b125ffd900bf477d60 -Author: Bdale Garbee -Date: Mon Aug 17 23:31:52 2009 -0600 - - add a config file for git-buildpackage - -commit 5f59df632f3a82348aefc2b16f2521f6ebd30a50 -Author: Bdale Garbee -Date: Mon Aug 17 23:31:20 2009 -0600 - - don't fail to clean if Makefile not present - -commit 946f2be3f4fdd0e7cf5c9867ff6fa0d348d95ee1 -Author: Bdale Garbee -Date: Mon Aug 17 23:30:20 2009 -0600 - - package for Debian - commit 7cba411de0780c65e3490ab67186a514f0ea42ec Author: Keith Packard Date: Mon Aug 17 20:47:31 2009 -0700 diff --git a/debian/changelog b/debian/changelog index b92a2284..e0ee1030 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.4+88+gcd5ce66) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Tue, 18 Aug 2009 21:57:00 -0600 + altos (0) unstable; urgency=low * Initial packaging -- cgit v1.2.3 From 29687cbd462a332d9a36ed87500c5b737dcae3f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Aug 2009 22:35:15 -0700 Subject: Handle GPS satellite tracking data SiRF message #4 includes signal strength and GPS engine state for each of the satellites being tracked. This data is now parsed and sent to eeprom and the radio. Signed-off-by: Keith Packard --- src/Makefile | 4 +- src/ao.h | 32 ++++++++++ src/ao_dbg.c | 2 +- src/ao_gps.c | 126 ++++++++++++++++++++++++++++-------- src/ao_gps_print.c | 37 ++++++++++- src/ao_gps_report.c | 31 +++++++++ src/ao_gps_test.c | 181 +++++++++++++++++++++++++++++++++++++++++++--------- src/ao_host.h | 4 +- src/ao_monitor.c | 3 + src/ao_telemetry.c | 1 + 10 files changed, 358 insertions(+), 63 deletions(-) diff --git a/src/Makefile b/src/Makefile index 297f676b..9cc322a2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -260,8 +260,8 @@ clean: install: -ao_flight_test: ao_flight.c ao_flight_test.c +ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -ao_gps_test: ao_gps.c ao_gps_test.c ao_host.h +ao_gps_test: ao_gps.c ao_gps_test.c ao_gps_print.c ao_host.h cc -g -o $@ ao_gps_test.c diff --git a/src/ao.h b/src/ao.h index 85b7825f..27ec010f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -458,6 +458,7 @@ ao_ee_init(void); #define AO_LOG_GPS_LAT 'N' #define AO_LOG_GPS_LON 'W' #define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' #define AO_LOG_POS_NONE (~0UL) @@ -498,6 +499,12 @@ struct ao_log_record { int16_t altitude; uint16_t unused; } gps_altitude; + struct { + uint16_t svid; + uint8_t state; + uint8_t c_n; + uint8_t unused; + } gps_sat; struct { uint16_t d0; uint16_t d1; @@ -696,8 +703,29 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + extern __xdata uint8_t ao_gps_mutex; extern __xdata struct ao_gps_data ao_gps_data; +extern __xdata struct ao_gps_tracking_data ao_gps_tracking_data; void ao_gps(void); @@ -705,6 +733,9 @@ ao_gps(void); void ao_gps_print(__xdata struct ao_gps_data *gps_data); +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data); + void ao_gps_init(void); @@ -735,6 +766,7 @@ struct ao_telemetry { struct ao_adc adc; struct ao_gps_data gps; char callsign[AO_MAX_CALLSIGN]; + struct ao_gps_tracking_data gps_tracking; }; /* Set delay between telemetry reports (0 to disable) */ diff --git a/src/ao_dbg.c b/src/ao_dbg.c index c8dc6ddc..b218897c 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -26,7 +26,7 @@ #define DBG_RESET_N_PIN (P0_5) static void -ao_dbg_send_bits(uint8_t msk, uint8_t val) +ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { P0 = (P0 & ~msk) | (val & msk); _asm diff --git a/src/ao_gps.c b/src/ao_gps.c index c4c434fd..7d68b325 100644 --- a/src/ao_gps.c +++ b/src/ao_gps.c @@ -21,6 +21,7 @@ __xdata uint8_t ao_gps_mutex; __xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; @@ -105,6 +106,21 @@ struct sirf_geodetic_nav_data { static __xdata struct sirf_geodetic_nav_data ao_sirf_data; +struct sirf_measured_sat_data { + uint8_t svid; + uint16_t state; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + static __pdata uint16_t ao_sirf_cksum; static __pdata uint16_t ao_sirf_len; @@ -118,9 +134,11 @@ static uint8_t data_byte(void) return c; } +static char __xdata *sirf_target; + static void sirf_u16(uint8_t offset) { - uint16_t __xdata *ptr = (uint16_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); uint16_t val; val = data_byte() << 8; @@ -130,16 +148,16 @@ static void sirf_u16(uint8_t offset) static void sirf_u8(uint8_t offset) { - uint8_t __xdata *ptr = (uint8_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); uint8_t val; val = data_byte (); *ptr = val; } -static void sirf_u32(uint8_t offset) +static void sirf_u32(uint8_t offset) __reentrant { - uint32_t __xdata *ptr = (uint32_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); uint32_t val; val = ((uint32_t) data_byte ()) << 24; @@ -160,12 +178,44 @@ static void sirf_discard(uint8_t len) #define SIRF_U8 2 #define SIRF_U16 3 #define SIRF_U32 4 +#define SIRF_U8X10 5 struct sirf_packet_parse { uint8_t type; uint8_t offset; }; +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + static const struct sirf_packet_parse geodetic_nav_data_packet[] = { { SIRF_DISCARD, 2 }, /* 1 nav valid */ { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ @@ -200,29 +250,34 @@ static const struct sirf_packet_parse geodetic_nav_data_packet[] = { }; static void -ao_sirf_parse_41(void) +ao_sirf_parse_41(void) __reentrant { - uint8_t i, offset; + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} - for (i = 0; ; i++) { - offset = geodetic_nav_data_packet[i].offset; - switch (geodetic_nav_data_packet[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - } - } +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ + { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); } static void @@ -267,7 +322,6 @@ ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) static const uint8_t sirf_disable[] = { 2, - 4, 9, 10, 27, @@ -289,6 +343,7 @@ ao_gps(void) __reentrant for (i = 0; i < sizeof (sirf_disable); i++) ao_sirf_set_message_rate(sirf_disable[i], 0); ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); } for (;;) { /* Locate the begining of the next record */ @@ -314,6 +369,11 @@ ao_gps(void) __reentrant break; ao_sirf_parse_41(); break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; } if (ao_sirf_len != 0) continue; @@ -356,6 +416,17 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; } } } @@ -367,6 +438,9 @@ gps_dump(void) __reentrant { ao_mutex_get(&ao_gps_mutex); ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); ao_mutex_put(&ao_gps_mutex); } diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 8cc07c85..ba0ff68a 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -82,14 +82,45 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant gps_data->course * 2, climb / 100, climb % 100); - printf(" %d.%d(hdop) %5u(herr) %5u(verr)\n", + printf(" %d.%d(hdop) %5u(herr) %5u(verr)", gps_data->hdop / 5, (gps_data->hdop * 2) % 10, gps_data->h_error, gps_data->v_error); } else if (gps_data->flags & AO_GPS_RUNNING) { - printf(" unlocked\n"); + printf(" unlocked"); } else { - printf (" not-connected\n"); + printf (" not-connected"); } } + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __reentrant +{ + uint8_t c, n, v; + __xdata struct ao_gps_sat_data *sat; + printf("SAT "); + n = gps_tracking_data->channels; + if (n == 0) { + printf("not-connected\n"); + return; + } + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid && sat->state) + v++; + sat++; + } + printf("%d ", v); + sat = gps_tracking_data->sats; + for (c = 0; c < n; c++) { + if (sat->svid && sat->state) + printf (" %3d %02x %3d", + sat->svid, + sat->state, + sat->c_n_1); + sat++; + } + printf ("\n"); +} diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index dce12adb..acf8bb40 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -52,10 +52,41 @@ ao_gps_report(void) } } +void +ao_gps_tracking_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_gps_tracking_data gps_tracking_data; + uint8_t c, n; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.tick = ao_time(); + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid) && + (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + gps_log.u.gps_sat.unused = 0; + ao_log_data(&gps_log); + } + } +} + __xdata struct ao_task ao_gps_report_task; +__xdata struct ao_task ao_gps_tracking_report_task; void ao_gps_report_init(void) { ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); + ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index fb9b0d10..c94128d9 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -44,6 +44,26 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + void ao_mutex_get(uint8_t *mutex) { @@ -78,6 +98,15 @@ ao_dbg_char(char c) static char input_queue[QUEUE_LEN]; int input_head, input_tail; +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} static void check_sirf_message(char *from, uint8_t *msg, int len) @@ -101,9 +130,11 @@ check_sirf_message(char *from, uint8_t *msg, int len) } encoded_len = (msg[2] << 8) | msg[3]; id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ if (encoded_len != len - 8) { - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); return; } encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; @@ -116,7 +147,8 @@ check_sirf_message(char *from, uint8_t *msg, int len) return; } id = msg[4]; - if (id == 41) { + switch (id) { + case 41:{ int off = 4; uint8_t id; @@ -181,29 +213,83 @@ check_sirf_message(char *from, uint8_t *msg, int len) printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %d\n", week); - printf ("\tTOW %d\n", tow); - printf ("\tyear %d\n", year); - printf ("\tmonth %d\n", month); - printf ("\tday %d\n", day); - printf ("\thour %d\n", hour); - printf ("\tminute %d\n", minute); - printf ("\tsecond %g\n", second / 1000.0); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g\n", lat / 1.0e7); - printf ("\tlon: %g\n", lon / 1.0e7); - printf ("\talt_ell: %g\n", alt_ell / 100.0); - printf ("\talt_msll: %g\n", alt_msl / 100.0); - printf ("\tdatum: %d\n", datum); - printf ("\tground speed: %g\n", sog / 100.0); - printf ("\tcourse: %g\n", cog / 100.0); - printf ("\tclimb: %g\n", climb_rate / 100.0); - printf ("\theading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g\n", h_error / 100.0); - printf ("\tv error: %g\n", v_error / 100.0); - printf ("\tt error: %g\n", t_error / 100.0); - printf ("\th vel error: %g\n", h_v_error / 100.0); - } else { + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: return; printf ("%s %4d:", from, encoded_len); for (i = 4; i < len - 4; i++) { @@ -315,9 +401,16 @@ ao_serial_set_speed(uint8_t speed) #include "ao_gps.c" void -ao_dump_state(void) +ao_dump_state(void *wchan) { double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; printf ("%02d:%02d:%02d", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); @@ -336,6 +429,12 @@ ao_dump_state(void) ao_gps_data.hdop / 5.0, ao_gps_data.h_error, ao_gps_data.v_error); printf("\n"); + printf ("\t"); + for (i = 0; i < 12; i++) + printf (" %2d(%02x)", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].state); + printf ("\n"); } int @@ -358,14 +457,38 @@ ao_gps_open(const char *tty) return fd; } +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + int main (int argc, char **argv) { - char *gps_file = "/dev/ttyUSB0"; + char *tty = "/dev/ttyUSB0"; + int c; - ao_gps_fd = ao_gps_open(gps_file); + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); if (ao_gps_fd < 0) { - perror (gps_file); + perror (tty); exit (1); } ao_gps_setup(); diff --git a/src/ao_host.h b/src/ao_host.h index 38ff84ac..6b42f9f9 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -65,7 +65,7 @@ uint8_t ao_adc_head; #define ao_led_on(l) #define ao_led_off(l) #define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state() +#define ao_wakeup(wchan) ao_dump_state(wchan) #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) @@ -100,7 +100,7 @@ struct ao_adc ao_adc_static; FILE *emulator_in; void -ao_dump_state(void); +ao_dump_state(void *wchan); void ao_sleep(void *wchan); diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 5997d427..e57ea145 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -55,6 +55,9 @@ ao_monitor(void) recv.telemetry.flight_pres, recv.telemetry.ground_pres); ao_gps_print(&recv.telemetry.gps); + putchar(' '); + ao_gps_tracking_print(&recv.telemetry.gps_tracking); + putchar('\n'); ao_rssi_set((int) recv.rssi - 74); } else { printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 463bcd91..9f57f3a9 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -39,6 +39,7 @@ ao_telemetry(void) ao_adc_get(&telemetry.adc); ao_mutex_get(&ao_gps_mutex); memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry); ao_delay(ao_telemetry_interval); -- cgit v1.2.3 From 33edd62992a32b0ec8ca66d879fa300871db5937 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Aug 2009 23:38:16 -0700 Subject: Update ao-view to add GPS satellite tracking data This adds another column to the display to hold per-satellite GPS tracking data and a count of the visible and locked sats. Signed-off-by: Keith Packard --- ao-view/aoview.glade | 25 ++++++++++++++++++------- ao-view/aoview.h | 22 ++++++++++++++++++++++ ao-view/aoview_monitor.c | 34 ++++++++++++++++++++++++++++++++-- ao-view/aoview_state.c | 24 ++++++++++++++++++++++++ ao-view/aoview_table.c | 2 +- src/ao_gps_print.c | 3 +-- 6 files changed, 98 insertions(+), 12 deletions(-) diff --git a/ao-view/aoview.glade b/ao-view/aoview.glade index 3481a779..9a746110 100644 --- a/ao-view/aoview.glade +++ b/ao-view/aoview.glade @@ -3,7 +3,7 @@ - 550 + 900 700 True AltOS View @@ -412,6 +412,17 @@ 1 + + + True + True + False + both + + + 2 + + 2 @@ -453,7 +464,7 @@ end - gtk-cancel + gtk-cancel 1 True True @@ -470,7 +481,7 @@ - gtk-connect + gtk-connect True True True @@ -511,7 +522,7 @@ end - gtk-cancel + gtk-cancel True True True @@ -526,7 +537,7 @@ - gtk-ok + gtk-ok True True True @@ -693,7 +704,7 @@ You should have received a copy of the GNU General Public License along with AoV end - gtk-cancel + gtk-cancel True True True @@ -708,7 +719,7 @@ You should have received a copy of the GNU General Public License along with AoV - gtk-ok + gtk-ok True True True diff --git a/ao-view/aoview.h b/ao-view/aoview.h index e8334e5b..9ca65298 100644 --- a/ao-view/aoview.h +++ b/ao-view/aoview.h @@ -75,6 +75,26 @@ struct aogps { int v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct aogps_sat { + int svid; + int state; + int c_n0; +}; + +struct aogps_tracking { + int channels; + struct aogps_sat sats[12]; +}; + struct aodata { char callsign[16]; int serial; @@ -93,6 +113,7 @@ struct aodata { int flight_pres; int ground_pres; struct aogps gps; + struct aogps_tracking gps_tracking; }; struct aostate { @@ -121,6 +142,7 @@ struct aostate { double max_speed; struct aogps gps; + struct aogps_tracking gps_tracking; int gps_valid; double pad_lat; diff --git a/ao-view/aoview_monitor.c b/ao-view/aoview_monitor.c index 9265a199..1f4c8f72 100644 --- a/ao-view/aoview_monitor.c +++ b/ao-view/aoview_monitor.c @@ -47,6 +47,12 @@ aoview_parse_int(int *target, char *source) *target = strtol(source, NULL, 0); } +static void +aoview_parse_hex(int *target, char *source) +{ + *target = strtol(source, NULL, 16); +} + static void aoview_parse_pos(double *target, char *source) { @@ -65,20 +71,23 @@ aoview_parse_pos(double *target, char *source) *target = r; } +#define PARSE_MAX_WORDS 256 + gboolean aoview_monitor_parse(const char *input_line) { char *saveptr; - char *words[64]; + char *words[PARSE_MAX_WORDS]; int nword; char line_buf[8192], *line; struct aodata data; + int tracking_pos; /* avoid smashing our input parameter */ strncpy (line_buf, input_line, sizeof (line_buf)-1); line_buf[sizeof(line_buf) - 1] = '\0'; line = line_buf; - for (nword = 0; nword < 64; nword++) { + for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; if (words[nword] == NULL) @@ -112,6 +121,7 @@ aoview_monitor_parse(const char *input_line) data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; data.gps.lat = data.gps.lon = 0; data.gps.alt = 0; + tracking_pos = 37; } else if (nword >= 40) { data.gps.gps_locked = 1; data.gps.gps_connected = 1; @@ -119,6 +129,7 @@ aoview_monitor_parse(const char *input_line) aoview_parse_pos(&data.gps.lat, words[37]); aoview_parse_pos(&data.gps.lon, words[38]); sscanf(words[39], "%dm", &data.gps.alt); + tracking_pos = 46; } else { data.gps.gps_connected = 0; data.gps.gps_locked = 0; @@ -143,6 +154,25 @@ aoview_monitor_parse(const char *input_line) data.gps.h_error = 0; data.gps.v_error = 0; } + if (nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { + int c, n, pos; + aoview_parse_int(&n, words[tracking_pos + 1]); + pos = tracking_pos + 2; + if (nword >= pos + n * 3) { + data.gps_tracking.channels = n; + for (c = 0; c < n; c++) { + aoview_parse_int(&data.gps_tracking.sats[c].svid, + words[pos + 0]); + aoview_parse_hex(&data.gps_tracking.sats[c].state, + words[pos + 1]); + aoview_parse_int(&data.gps_tracking.sats[c].c_n0, + words[pos + 2]); + pos += 3; + } + } else { + data.gps_tracking.channels = 0; + } + } aoview_state_notify(&data); return TRUE; } diff --git a/ao-view/aoview_state.c b/ao-view/aoview_state.c index 7efd33b0..f75066dd 100644 --- a/ao-view/aoview_state.c +++ b/ao-view/aoview_state.c @@ -168,6 +168,8 @@ aoview_state_derive(struct aodata *data, struct aostate *state) aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon, &state->distance, &state->bearing); } + if (data->gps_tracking.channels) + state->gps_tracking = data->gps_tracking; if (state->npad) { state->gps_height = state->gps.alt - state->pad_alt; } else { @@ -308,6 +310,7 @@ aoview_state_notify(struct aodata *data) if (state->gps_valid) { aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S'); aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); + aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); aoview_table_add_row(1, "GPS height", "%d", state->gps_height); aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", state->gps.gps_time.hour, @@ -330,6 +333,27 @@ aoview_state_notify(struct aodata *data) aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W'); aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt); } + if (state->gps.gps_connected) { + int nsat_vis = 0; + int nsat_locked = 0; + int c; + + for (c = 0; c < state->gps_tracking.channels; c++) { + if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf) + nsat_locked++; + } + aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels); + aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked); + for (c = 0; c < state->gps_tracking.channels; c++) { + aoview_table_add_row(2, "Satellite id,state,C/N0", + "%3d,%02x,%2d%s", + state->gps_tracking.sats[c].svid, + state->gps_tracking.sats[c].state, + state->gps_tracking.sats[c].c_n0, + (state->gps_tracking.sats[c].state & 0xff) == 0xbf ? + " LOCKED" : ""); + } + } aoview_table_finish(); aoview_label_show(state); aoview_speak_state(state); diff --git a/ao-view/aoview_table.c b/ao-view/aoview_table.c index 93143009..e75ae670 100644 --- a/ao-view/aoview_table.c +++ b/ao-view/aoview_table.c @@ -17,7 +17,7 @@ #include "aoview.h" -#define NCOL 2 +#define NCOL 3 static GtkTreeView *dataview[NCOL]; static GtkListStore *datalist[NCOL]; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index ba0ff68a..cc751337 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -102,7 +102,7 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ printf("SAT "); n = gps_tracking_data->channels; if (n == 0) { - printf("not-connected\n"); + printf("not-connected"); return; } sat = gps_tracking_data->sats; @@ -122,5 +122,4 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ sat->c_n_1); sat++; } - printf ("\n"); } -- cgit v1.2.3 From 0087c1776e0253fc2bd3b86f15bf9d1b32bdc45a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 00:52:57 -0600 Subject: update changelogs for Debian build --- ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8fe3609b..fd3af4d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +commit 4486d9156e19e4280b42bcd422d81d04f2d04a92 +Merge: dd09f0b 33edd62 +Author: Bdale Garbee +Date: Wed Aug 19 00:49:24 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 33edd62992a32b0ec8ca66d879fa300871db5937 +Author: Keith Packard +Date: Tue Aug 18 23:38:16 2009 -0700 + + Update ao-view to add GPS satellite tracking data + + This adds another column to the display to hold per-satellite GPS + tracking data and a count of the visible and locked sats. + + Signed-off-by: Keith Packard + +commit 29687cbd462a332d9a36ed87500c5b737dcae3f4 +Author: Keith Packard +Date: Tue Aug 18 22:35:15 2009 -0700 + + Handle GPS satellite tracking data + + SiRF message #4 includes signal strength and GPS engine state for each + of the satellites being tracked. This data is now parsed and sent to + eeprom and the radio. + + Signed-off-by: Keith Packard + +commit dd09f0bc2b950c00f3b489878cd69ad8a003f46c +Author: Bdale Garbee +Date: Tue Aug 18 21:57:01 2009 -0600 + + update changelogs for Debian build + commit cd5ce661e2a8f9694933358ccb5b916fbed089c2 Author: Bdale Garbee Date: Tue Aug 18 21:49:39 2009 -0600 diff --git a/debian/changelog b/debian/changelog index e0ee1030..c0326367 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.4+92+g4486d91) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Wed, 19 Aug 2009 00:52:57 -0600 + altos (0.4+88+gcd5ce66) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 21e3dd0affac89919e5d0e29c6e9eb1eacb51801 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:06:49 -0600 Subject: enable support for Debian menus --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 078dac56..a2fd3fc7 100755 --- a/debian/rules +++ b/debian/rules @@ -51,7 +51,7 @@ binary-arch: install dh_installdocs dh_installexamples dh_install -# dh_installmenu + dh_installmenu # dh_installdebconf # dh_installlogrotate # dh_installemacsen -- cgit v1.2.3 From b9a97aea65f871fd287bc0bb566d8664766f4afd Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:07:16 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index fd3af4d0..bf0aa255 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 21e3dd0affac89919e5d0e29c6e9eb1eacb51801 +Author: Bdale Garbee +Date: Wed Aug 19 02:06:49 2009 -0600 + + enable support for Debian menus + +commit 0087c1776e0253fc2bd3b86f15bf9d1b32bdc45a +Author: Bdale Garbee +Date: Wed Aug 19 00:52:57 2009 -0600 + + update changelogs for Debian build + commit 4486d9156e19e4280b42bcd422d81d04f2d04a92 Merge: dd09f0b 33edd62 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index c0326367..79cd26d7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.4+94+g21e3dd0) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Wed, 19 Aug 2009 02:07:16 -0600 + altos (0.4+92+g4486d91) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 8d4d6655f1b4c2fbc522fd255bfb75406e5ddaef Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:11:00 -0600 Subject: oops, aoview is now ao-view! --- debian/menu | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/menu b/debian/menu index 7e15c9c8..9bd98c5a 100644 --- a/debian/menu +++ b/debian/menu @@ -1,2 +1,2 @@ ?package(altos):needs="X11" section="Applications/Viewers"\ - title="aoview" command="/usr/bin/aoview" + title="ao-view" command="/usr/bin/ao-view" -- cgit v1.2.3 From 977f5dc0bc7c666dcc1f21db77416efca0d696aa Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:11:11 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index bf0aa255..d49963fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 8d4d6655f1b4c2fbc522fd255bfb75406e5ddaef +Author: Bdale Garbee +Date: Wed Aug 19 02:11:00 2009 -0600 + + oops, aoview is now ao-view! + +commit b9a97aea65f871fd287bc0bb566d8664766f4afd +Author: Bdale Garbee +Date: Wed Aug 19 02:07:16 2009 -0600 + + update changelogs for Debian build + commit 21e3dd0affac89919e5d0e29c6e9eb1eacb51801 Author: Bdale Garbee Date: Wed Aug 19 02:06:49 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 79cd26d7..27049a66 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.4+96+g8d4d665) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Wed, 19 Aug 2009 02:11:11 -0600 + altos (0.4+94+g21e3dd0) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 42ab6d52540d0326ef89e9d57954b08248558468 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:21:06 -0600 Subject: fix location for delivery of sources.list fragment --- debian/altos.install | 2 +- debian/altos.list | 2 ++ debian/repository | 2 -- 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 debian/altos.list delete mode 100644 debian/repository diff --git a/debian/altos.install b/debian/altos.install index aac3544b..57f9b02a 100644 --- a/debian/altos.install +++ b/debian/altos.install @@ -1,3 +1,3 @@ -debian/repository etc/apt/sources.list.d/altos.list +debian/altos.list etc/apt/sources.list.d src/*.ihx usr/share/altos src/*.map usr/share/altos diff --git a/debian/altos.list b/debian/altos.list new file mode 100644 index 00000000..201a4a2f --- /dev/null +++ b/debian/altos.list @@ -0,0 +1,2 @@ +deb http://altusmetrum.org/apt sid main +deb-src http://altusmetrum.org/apt sid main diff --git a/debian/repository b/debian/repository deleted file mode 100644 index 201a4a2f..00000000 --- a/debian/repository +++ /dev/null @@ -1,2 +0,0 @@ -deb http://altusmetrum.org/apt sid main -deb-src http://altusmetrum.org/apt sid main -- cgit v1.2.3 From 8df169791835510d96c11a3b0aa3cc5b79fa7fde Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Aug 2009 02:21:23 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index d49963fe..cd4b4e14 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 42ab6d52540d0326ef89e9d57954b08248558468 +Author: Bdale Garbee +Date: Wed Aug 19 02:21:06 2009 -0600 + + fix location for delivery of sources.list fragment + +commit 977f5dc0bc7c666dcc1f21db77416efca0d696aa +Author: Bdale Garbee +Date: Wed Aug 19 02:11:11 2009 -0600 + + update changelogs for Debian build + commit 8d4d6655f1b4c2fbc522fd255bfb75406e5ddaef Author: Bdale Garbee Date: Wed Aug 19 02:11:00 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 27049a66..318292bf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.4+98+g42ab6d5) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Wed, 19 Aug 2009 02:21:23 -0600 + altos (0.4+96+g8d4d665) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 0d65bff443c17d4d98c18b620ec075ab66b30efd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Aug 2009 10:47:46 -0700 Subject: Turn off GPS tracking data when not present in data stream Signed-off-by: Keith Packard --- ao-view/aoview_monitor.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ao-view/aoview_monitor.c b/ao-view/aoview_monitor.c index 1f4c8f72..8564014b 100644 --- a/ao-view/aoview_monitor.c +++ b/ao-view/aoview_monitor.c @@ -136,6 +136,7 @@ aoview_monitor_parse(const char *input_line) data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; data.gps.lat = data.gps.lon = 0; data.gps.alt = 0; + tracking_pos = -1; } if (nword >= 46) { data.gps.gps_extended = 1; @@ -154,7 +155,7 @@ aoview_monitor_parse(const char *input_line) data.gps.h_error = 0; data.gps.v_error = 0; } - if (nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { + if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { int c, n, pos; aoview_parse_int(&n, words[tracking_pos + 1]); pos = tracking_pos + 2; @@ -172,6 +173,8 @@ aoview_monitor_parse(const char *input_line) } else { data.gps_tracking.channels = 0; } + } else { + data.gps_tracking.channels = 0; } aoview_state_notify(&data); return TRUE; -- cgit v1.2.3 From 6358041f846ba9a20fa650c367d907dc4336e54c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 22 Aug 2009 13:38:56 -0700 Subject: Enable GPS degraded mode, set 10 sec degraded timeout. No reason not to let the GPS report solutions whenever it likes, let's see how this works. Signed-off-by: Keith Packard --- src/ao_gps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_gps.c b/src/ao_gps.c index 7d68b325..2b3a5178 100644 --- a/src/ao_gps.c +++ b/src/ao_gps.c @@ -30,14 +30,14 @@ const char ao_gps_config[] = { 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ 136, /* mode control */ 0, 0, /* reserved */ - 4, /* degraded mode (disabled) */ + 0, /* degraded mode (allow 1-SV navigation) */ 0, 0, /* reserved */ 0, 0, /* user specified altitude */ 2, /* alt hold mode (disabled, require 3d fixes) */ 0, /* alt hold source (use last computed altitude) */ 0, /* reserved */ - 0, /* Degraded time out (disabled) */ - 0, /* Dead Reckoning time out (disabled) */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ 0, /* Track smoothing (disabled) */ 0x00, 0x8e, 0xb0, 0xb3, -- cgit v1.2.3 From 591b99c232e780246fc07841c09c8c4e7835facb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 31 Aug 2009 16:26:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 21 +++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/ChangeLog b/ChangeLog index cd4b4e14..afa99366 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +commit b34474c1f3083e73b7184d519f54d4c8031836fd +Merge: 8df1697 0d65bff +Author: Bdale Garbee +Date: Mon Aug 31 16:25:32 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 0d65bff443c17d4d98c18b620ec075ab66b30efd +Author: Keith Packard +Date: Fri Aug 21 10:47:46 2009 -0700 + + Turn off GPS tracking data when not present in data stream + + Signed-off-by: Keith Packard + +commit 8df169791835510d96c11a3b0aa3cc5b79fa7fde +Author: Bdale Garbee +Date: Wed Aug 19 02:21:23 2009 -0600 + + update changelogs for Debian build + commit 42ab6d52540d0326ef89e9d57954b08248558468 Author: Bdale Garbee Date: Wed Aug 19 02:21:06 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 318292bf..5445a1f5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+9+gb34474c) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 31 Aug 2009 16:26:00 -0600 + altos (0.4+98+g42ab6d5) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From c8c5b7963babe8eb16e2651fba9cd2c8d1cba74e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 31 Aug 2009 16:42:37 -0600 Subject: deliver an icon for the Debian menu system --- debian/altusmetrum.xpm | 175 +++++++++++++++++++++++++++++++++++++++++++++++++ debian/dirs | 1 + debian/menu | 8 ++- debian/rules | 2 + 4 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 debian/altusmetrum.xpm diff --git a/debian/altusmetrum.xpm b/debian/altusmetrum.xpm new file mode 100644 index 00000000..037b42d6 --- /dev/null +++ b/debian/altusmetrum.xpm @@ -0,0 +1,175 @@ +/* XPM */ +static char *icon[] = { +/* columns rows colors chars-per-pixel */ +"26 32 137 2", +" c #BB3D7F", +". c #BC3F7C", +"X c #BC3E7E", +"o c #BF4178", +"O c #BE4179", +"+ c #BD407A", +"@ c #BE407A", +"# c #D95F46", +"$ c #D95F47", +"% c #D55B4B", +"& c #D75D49", +"* c #D65C4B", +"= c #D75C4B", +"- c #D55A4E", +"; c #D85D49", +": c #D85E48", +"> c #D85E49", +", c #CD525B", +"< c #CE525B", +"1 c #CE535B", +"2 c #CF5459", +"3 c #CB505D", +"4 c #CD515D", +"5 c #CC515E", +"6 c #CC505F", +"7 c #D05654", +"8 c #D15655", +"9 c #D05556", +"0 c #D05557", +"q c #D35851", +"w c #D35951", +"e c #D25852", +"r c #D25853", +"t c #D45950", +"y c #D05558", +"u c #DB6241", +"i c #DB6142", +"p c #DC6340", +"a c #D96044", +"s c #DA6044", +"d c #C64B66", +"f c #CB4F60", +"g c #CB4F61", +"h c #C94E63", +"j c #CA4E62", +"k c #C84C65", +"l c #C94D65", +"z c #C84C66", +"x c #C84C67", +"c c #C2466E", +"v c #C3476F", +"b c #C4476E", +"n c #C74B68", +"m c #C74A69", +"M c #C5496B", +"N c #C6496A", +"B c #C6496B", +"V c #C4486D", +"C c #CB5060", +"Z c #C04471", +"A c #C24571", +"S c #C34670", +"D c #C24671", +"F c #C14473", +"G c #C24572", +"H c #C04375", +"J c #C14474", +"K c #B53885", +"L c #B83B81", +"P c #BA3C80", +"I c #BA3C81", +"U c #B83985", +"Y c #B83A85", +"T c #B63789", +"R c #B4358B", +"E c #B5378A", +"W c #B3348E", +"Q c #B3348F", +"! c #B4358D", +"~ c #B63888", +"^ c #AF2F96", +"/ c #AE2F97", +"( c #AB2C99", +") c #A82A9D", +"_ c #AB2B9E", +"` c #AC2C9C", +"' c #AF3095", +"] c #B23390", +"[ c #B03095", +"{ c #9E1DB2", +"} c #9F1EB2", +"| c #9B1BB5", +" . c #9D1CB5", +".. c #9A17BF", +"X. c #9B19BB", +"o. c #9C1ABA", +"O. c #9A19BC", +"+. c #9B19BC", +"@. c #A01EB3", +"#. c #A726A5", +"$. c #A625A6", +"%. c #A626A6", +"&. c #A929A0", +"*. c #A828A2", +"=. c #A423AB", +"-. c #A524A8", +";. c #A524AA", +":. c #A221AE", +">. c #8E0CCD", +",. c #910FCB", +"<. c #900DCE", +"1. c #9413C4", +"2. c #9613C6", +"3. c #9815C2", +"4. c #9310CA", +"5. c #9512C8", +"6. c #8F0CD2", +"7. c #8E0BD4", +"8. c #8D09D7", +"9. c #8603DE", +"0. c #8A05DD", +"q. c #8C08D8", +"w. c #8200E1", +"e. c #8200E2", +"r. c #8300E2", +"t. c #8300E3", +"y. c #8401E0", +"u. c #8602E0", +"i. c #8602E2", +"p. c #8400E4", +"a. c #8400E5", +"s. c #8500E5", +"d. c #8501E5", +"f. c #8601E5", +"g. c #8500E6", +"h. c #8804E0", +"j. c None", +/* pixels */ +"j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.j.a.j.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.j.a.g.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.j.g.a.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.a.a.a.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.a.a.a.a.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.g.a.a.a.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.a.a.j.j.a.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.a.a.j.j.a.a.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.p.j.j.j.w.w.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.w.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.a.a.j.j.j.j.a.a.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.j.a.a.w.j.j.a.a.a.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.p.a.a.a.j.a.a.a.a.j.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.a.a.w.j.w.w.j.a.a.a.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.j.a.a.p.j.j.j.j.p.g.a.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.p.a.a.w.j.j.j.j.p.g.a.j.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.a.g.a.p.j.j.j.j.p.f.a.a.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.j.a.h.q.>.j.j.j.j.,.7.0.p.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.9.q.4.3. .j.j.j.j.{ X.2.6.j.j.j.j.j.j.j.", +"j.j.j.j.j.j.<.3.@.#._ j.j.j.j.( *.:.X.2.j.j.j.j.j.j.", +"j.j.j.j.j.j.O.;.` ! K j.j.j.j.I E [ #.@.j.j.j.j.j.j.", +"j.j.j.j.j. .;.' Y o F j.j.j.j.v J P ] &.j.j.j.j.j.j.", +"j.j.j.j.j.$.' P F M k j.j.j.j.k M v O ! ( j.j.j.j.j.", +"j.j.j.j.j.' P F M j 3 j.j.j.j.1 6 z b O E j.j.j.j.j.", +"j.j.j.j.j.~ F n C 2 9 j.j.j.j.w 9 6 z V X j.j.j.j.j.", +"j.j.j.j.! O V C 2 w % j.j.j.j.% * 9 6 z F P j.j.j.j.", +"j.j.j.j.K S z y t : $ j.j.j.j.p s - 9 j M O j.j.j.j.", +"j.j.j./ + V C 9 * s j.j.j.j.j.j.p : t 1 z J E j.j.j.", +"j.j.:.] J z 2 t : j.j.j.j.j.j.j.j.s * 9 j b I *.j.j.", +"j.5.;.~ S z y t j.j.j.j.j.j.j.j.j.j.: r 6 M X _ X.j." +}; diff --git a/debian/dirs b/debian/dirs index 8b9a4657..3783a46c 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,3 +1,4 @@ etc/apt/sources.list.d usr/bin usr/share/altos +/usr/share/pixmaps diff --git a/debian/menu b/debian/menu index 9bd98c5a..c175534d 100644 --- a/debian/menu +++ b/debian/menu @@ -1,2 +1,6 @@ -?package(altos):needs="X11" section="Applications/Viewers"\ - title="ao-view" command="/usr/bin/ao-view" +?package(altos): \ + needs="X11" \ + section="Applications/Viewers" \ + title="ao-view" \ + command="/usr/bin/ao-view" \ + icon="/usr/share/pixmaps/altusmetrum.xpm" diff --git a/debian/rules b/debian/rules index a2fd3fc7..fff5585f 100755 --- a/debian/rules +++ b/debian/rules @@ -52,6 +52,8 @@ binary-arch: install dh_installexamples dh_install dh_installmenu + install debian/altusmetrum.xpm \ + debian/altos/usr/share/pixmaps/altusmetrum.xpm # dh_installdebconf # dh_installlogrotate # dh_installemacsen -- cgit v1.2.3 From 1495e2f27acde3743c3764a0c31ee082224d6c64 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 31 Aug 2009 16:42:55 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index afa99366..bf4f9012 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit c8c5b7963babe8eb16e2651fba9cd2c8d1cba74e +Author: Bdale Garbee +Date: Mon Aug 31 16:42:37 2009 -0600 + + deliver an icon for the Debian menu system + +commit 591b99c232e780246fc07841c09c8c4e7835facb +Author: Bdale Garbee +Date: Mon Aug 31 16:26:00 2009 -0600 + + update changelogs for Debian build + commit b34474c1f3083e73b7184d519f54d4c8031836fd Merge: 8df1697 0d65bff Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 5445a1f5..f8c6e148 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+11+gc8c5b79) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 31 Aug 2009 16:42:55 -0600 + altos (0.5+9+gb34474c) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 6926c4ab5d87a8f2eb4fcde2c673fb3a4639e115 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 31 Aug 2009 16:47:44 -0600 Subject: pixmap file should not be executable --- debian/rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/rules b/debian/rules index fff5585f..74cc078d 100755 --- a/debian/rules +++ b/debian/rules @@ -38,6 +38,8 @@ install: build dh_installdirs $(MAKE) DESTDIR=$(CURDIR)/debian/altos install + install -o root -g root -m 0644 debian/altusmetrum.xpm \ + $(CURDIR)/debian/altos/usr/share/pixmaps/altusmetrum.xpm # Build architecture-independent files here. binary-indep: install @@ -52,8 +54,6 @@ binary-arch: install dh_installexamples dh_install dh_installmenu - install debian/altusmetrum.xpm \ - debian/altos/usr/share/pixmaps/altusmetrum.xpm # dh_installdebconf # dh_installlogrotate # dh_installemacsen -- cgit v1.2.3 From 9ddd8696b4004ccc03238d95a8c2a1d07075e0fb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 31 Aug 2009 16:48:03 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index bf4f9012..a5c9604a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 6926c4ab5d87a8f2eb4fcde2c673fb3a4639e115 +Author: Bdale Garbee +Date: Mon Aug 31 16:47:44 2009 -0600 + + pixmap file should not be executable + +commit 1495e2f27acde3743c3764a0c31ee082224d6c64 +Author: Bdale Garbee +Date: Mon Aug 31 16:42:55 2009 -0600 + + update changelogs for Debian build + commit c8c5b7963babe8eb16e2651fba9cd2c8d1cba74e Author: Bdale Garbee Date: Mon Aug 31 16:42:37 2009 -0600 diff --git a/debian/changelog b/debian/changelog index f8c6e148..0f2dd70a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+13+g6926c4a) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 31 Aug 2009 16:48:03 -0600 + altos (0.5+11+gc8c5b79) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 7d39f17684feb49ac8a0017902158f298696e37c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 21:57:54 -0700 Subject: Make eeprom reads and writes across block boundary work Reading and writing across the block boundary was not stepping the eeprom position after the partial i/o operation at the end of the first block. This meant that the operation would re-use the end of the previous block, either re-reading or re-writing it. Signed-off-by: Keith Packard --- src/ao_ee.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_ee.c b/src/ao_ee.c index f299b925..9b6db234 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -271,6 +271,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* See how much is left */ buf += this_len; len -= this_len; + pos += this_len; } return 1; } @@ -306,6 +307,7 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* See how much is left */ buf += this_len; len -= this_len; + pos += this_len; } return 1; } -- cgit v1.2.3 From acea083d80e1ecc4287083519ea666964016b257 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 22:00:37 -0700 Subject: Make the ao_log_record structures 8 bytes again. When the GPS signal strength data was added, the structure was accidentally extended to 9 bytes, making all log records 9 bytes long. While not a serious problem, this left log records spanning across eeprom block boundaries, which seems like a bad plan. Signed-off-by: Keith Packard --- src/ao.h | 1 - src/ao_gps_report.c | 1 - 2 files changed, 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 27ec010f..8e342558 100644 --- a/src/ao.h +++ b/src/ao.h @@ -503,7 +503,6 @@ struct ao_log_record { uint16_t svid; uint8_t state; uint8_t c_n; - uint8_t unused; } gps_sat; struct { uint16_t d0; diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index acf8bb40..75c944f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -75,7 +75,6 @@ ao_gps_tracking_report(void) (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) { gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; - gps_log.u.gps_sat.unused = 0; ao_log_data(&gps_log); } } -- cgit v1.2.3 From e2e449d5c23356e913f312de1fb2611a9dd5a352 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 22:01:52 -0700 Subject: Remove bit-banging debug support from TM board builds Our current TM boards don't have the wires to do bit-banging to another cc1111 board, so it doesn't make sense to fill up their flash with useless code (and the 'help' text with useless commands). Leave this to the TI board until we have boards that can serve as debug dongles. Signed-off-by: Keith Packard --- src/Makefile | 10 ++++++++-- src/ao_log.c | 3 +++ src/ao_teledongle.c | 1 - src/ao_telemetrum.c | 1 - src/ao_teleterra.c | 1 - 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/Makefile b/src/Makefile index 96049c65..828c48bd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,7 +24,6 @@ INC = \ # ALTOS_SRC = \ ao_cmd.c \ - ao_dbg.c \ ao_dma.c \ ao_mutex.c \ ao_panic.c \ @@ -70,6 +69,12 @@ TELE_FAKE_SRC = \ ao_adc_fake.c \ ao_ee_fake.c +# +# Debug dongle driver (only on TI) +# +DBG_DONGLE_SRC = \ + ao_dbg.c + # # Drivers only on TeleMetrum # @@ -115,7 +120,8 @@ TI_SRC = \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ $(TELE_FAKE_SRC) \ - $(TI_MAIN_SRC) + $(TI_MAIN_SRC) \ + $(DBG_DONGLE_SRC) TT_MAIN_SRC = \ ao_teleterra.c diff --git a/src/ao_log.c b/src/ao_log.c index 19bfdfb8..7945ace4 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -109,6 +109,9 @@ ao_log_dump_next(void) __xdata uint8_t ao_log_adc_pos; __xdata enum flight_state ao_log_state; +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + void ao_log(void) { diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 4ebc53a5..d7b4b75a 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,7 +33,6 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 5e951b49..1dbacf89 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -41,7 +41,6 @@ main(void) ao_telemetry_init(); ao_radio_init(); ao_igniter_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c index 6464ccc0..deb63597 100644 --- a/src/ao_teleterra.c +++ b/src/ao_teleterra.c @@ -34,7 +34,6 @@ main(void) ao_gps_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_radio_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 9fafee109e96435c96639b21211cac0500673a63 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 2 Sep 2009 23:18:15 -0600 Subject: update changelogs for Debian build --- ChangeLog | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 69 insertions(+) diff --git a/ChangeLog b/ChangeLog index a5c9604a..c099f684 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,55 @@ +commit cb4a73f3b65ba72f645fd37ab8712829c9537bf8 +Merge: 9ddd869 e2e449d +Author: Bdale Garbee +Date: Wed Sep 2 23:17:37 2009 -0600 + + Merge commit 'origin/master' + +commit e2e449d5c23356e913f312de1fb2611a9dd5a352 +Author: Keith Packard +Date: Wed Sep 2 22:01:52 2009 -0700 + + Remove bit-banging debug support from TM board builds + + Our current TM boards don't have the wires to do bit-banging to + another cc1111 board, so it doesn't make sense to fill up their flash + with useless code (and the 'help' text with useless commands). Leave + this to the TI board until we have boards that can serve as debug dongles. + + Signed-off-by: Keith Packard + +commit acea083d80e1ecc4287083519ea666964016b257 +Author: Keith Packard +Date: Wed Sep 2 22:00:37 2009 -0700 + + Make the ao_log_record structures 8 bytes again. + + When the GPS signal strength data was added, the structure was + accidentally extended to 9 bytes, making all log records 9 bytes + long. While not a serious problem, this left log records spanning + across eeprom block boundaries, which seems like a bad plan. + + Signed-off-by: Keith Packard + +commit 7d39f17684feb49ac8a0017902158f298696e37c +Author: Keith Packard +Date: Wed Sep 2 21:57:54 2009 -0700 + + Make eeprom reads and writes across block boundary work + + Reading and writing across the block boundary was not stepping the + eeprom position after the partial i/o operation at the end of the + first block. This meant that the operation would re-use the end of the + previous block, either re-reading or re-writing it. + + Signed-off-by: Keith Packard + +commit 9ddd8696b4004ccc03238d95a8c2a1d07075e0fb +Author: Bdale Garbee +Date: Mon Aug 31 16:48:03 2009 -0600 + + update changelogs for Debian build + commit 6926c4ab5d87a8f2eb4fcde2c673fb3a4639e115 Author: Bdale Garbee Date: Mon Aug 31 16:47:44 2009 -0600 @@ -29,6 +81,17 @@ Date: Mon Aug 31 16:25:32 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos +commit 6358041f846ba9a20fa650c367d907dc4336e54c +Author: Keith Packard +Date: Sat Aug 22 13:38:56 2009 -0700 + + Enable GPS degraded mode, set 10 sec degraded timeout. + + No reason not to let the GPS report solutions whenever it likes, let's + see how this works. + + Signed-off-by: Keith Packard + commit 0d65bff443c17d4d98c18b620ec075ab66b30efd Author: Keith Packard Date: Fri Aug 21 10:47:46 2009 -0700 diff --git a/debian/changelog b/debian/changelog index 0f2dd70a..e7c236a2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+19+gcb4a73f) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Wed, 02 Sep 2009 23:18:15 -0600 + altos (0.5+13+g6926c4a) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 54545640b0db7747137655f84bc67fd290ecb904 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 11:45:52 -0700 Subject: Add back the RDF tone generator Tracking the rocket on the ground may be easier using tones than using the digital data stream, so we'll try that and see what we think. This reverts commit 3a3bfd471a868d546d83cdc431b53c8f5208edb9. Signed-off-by: Keith Packard --- src/ao.h | 9 ++++++ src/ao_flight.c | 7 +++++ src/ao_flight_test.c | 1 + src/ao_radio.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_telemetry.c | 20 ++++++++++++ 5 files changed, 126 insertions(+) diff --git a/src/ao.h b/src/ao.h index 8e342558..37f21508 100644 --- a/src/ao.h +++ b/src/ao.h @@ -777,6 +777,9 @@ struct ao_telemetry { void ao_telemetry_set_interval(uint16_t interval); +void +ao_rdf_set(uint8_t rdf); + void ao_telemetry_init(void); @@ -796,6 +799,12 @@ struct ao_radio_recv { void ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +void +ao_radio_rdf(void); + +void +ao_radio_rdf_abort(void); + void ao_radio_init(void); diff --git a/src/ao_flight.c b/src/ao_flight.c index be9b3bb6..2b062c13 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -227,6 +227,7 @@ ao_flight(void) /* Turn on telemetry system */ + ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); ao_flight_state = ao_flight_pad; @@ -277,6 +278,9 @@ ao_flight(void) /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + /* disable RDF beacon */ + ao_rdf_set(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } @@ -356,6 +360,9 @@ ao_flight(void) /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); + /* Enable RDF beacon */ + ao_rdf_set(1); + /* * Start recording min/max accel and pres for a while * to figure out when the rocket has landed diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 1466b886..9fcb00c2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -68,6 +68,7 @@ uint8_t ao_adc_head; #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) +#define ao_rdf_set(rdf) enum ao_igniter { ao_igniter_drogue = 0, diff --git a/src/ao_radio.c b/src/ao_radio.c index ca1ec7e8..e4d42c6c 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -77,6 +77,29 @@ #define DEVIATION_M 6 #define DEVIATION_E 3 +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), + * so the DRATE_E and DRATE_M values are: + * + * M is 94 and E is 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ + +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 94 +#define RDF_PACKET_LEN 50 + +/* + * RDF deviation should match the normal NFM value of 5kHz + * + * M is 6 and E is 1 + * + */ + +#define RDF_DEVIATION_M 6 +#define RDF_DEVIATION_E 1 + /* This are from the table for 433MHz */ #define RF_POWER_M30_DBM 0x12 @@ -184,6 +207,28 @@ static __code uint8_t radio_setup[] = { RF_IOCFG0_OFF, 0x00, }; +static __code uint8_t rdf_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | + RF_MDMCFG1_NUM_PREAMBLE_2 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* packet length */ + RF_PKTLEN_OFF, RDF_PACKET_LEN, + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; static __code uint8_t telemetry_setup[] = { RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | @@ -275,6 +320,50 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant ao_mutex_put(&ao_radio_mutex); } +__xdata ao_radio_rdf_running; +__xdata ao_radio_rdf_value = 0x55; + +void +ao_radio_rdf(void) +{ + uint8_t i; + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + ao_radio_rdf_running = 1; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; + + ao_dma_set_transfer(ao_radio_dma, + &ao_radio_rdf_value, + &RFDXADDR, + RDF_PACKET_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + ao_radio_rdf_running = 0; + ao_radio_idle(); + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[telemetry_setup[i]] = telemetry_setup[i+1]; + ao_mutex_put(&ao_radio_mutex); +} + +void +ao_radio_rdf_abort(void) +{ + if (ao_radio_rdf_running) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } +} + void ao_radio_init(void) { diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 9f57f3a9..7eefee3c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,6 +18,10 @@ #include "ao.h" __xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL AO_SEC_TO_TICKS(3) void ao_telemetry(void) @@ -27,6 +31,7 @@ ao_telemetry(void) ao_config_get(); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); @@ -43,6 +48,13 @@ ao_telemetry(void) ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry); ao_delay(ao_telemetry_interval); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL; + ao_radio_rdf(); + ao_delay(ao_telemetry_interval); + } } } @@ -53,6 +65,14 @@ ao_telemetry_set_interval(uint16_t interval) ao_wakeup(&ao_telemetry_interval); } +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); +} + __xdata struct ao_task ao_telemetry_task; void -- cgit v1.2.3 From fee46389b70a624ab5b1128a8b4c3083c7747bcb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 11:46:55 -0700 Subject: Make RDF beacon only run on pad and after landing. It's pretty much impossible to RDF the rocket during flight, and it interferes with the telemetry data stream. Leave it enabled on the pad so that radios can be tested, and then re-enable it once the rocket has landed. This patch also turns the rdf 'on' time into a parameter so it can be changed, and then sets that parameter to 500ms, once every 5 seconds. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_flight.c | 5 ++--- src/ao_radio.c | 18 +++++++++++++++--- src/ao_telemetry.c | 9 ++++++--- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/ao.h b/src/ao.h index 37f21508..4116be65 100644 --- a/src/ao.h +++ b/src/ao.h @@ -800,7 +800,7 @@ void ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; void -ao_radio_rdf(void); +ao_radio_rdf(int ms); void ao_radio_rdf_abort(void); diff --git a/src/ao_flight.c b/src/ao_flight.c index 2b062c13..ec89e7c2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -360,9 +360,6 @@ ao_flight(void) /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); - /* Enable RDF beacon */ - ao_rdf_set(1); - /* * Start recording min/max accel and pres for a while * to figure out when the rocket has landed @@ -445,6 +442,8 @@ ao_flight(void) /* turn off the ADC capture */ ao_timer_set_adc_interval(0); + /* Enable RDF beacon */ + ao_rdf_set(1); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } diff --git a/src/ao_radio.c b/src/ao_radio.c index e4d42c6c..76fa3e5d 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -223,7 +223,6 @@ static __code uint8_t rdf_setup[] = { (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), /* packet length */ - RF_PKTLEN_OFF, RDF_PACKET_LEN, RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_ADR_CHK_NONE), RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| @@ -324,19 +323,32 @@ __xdata ao_radio_rdf_running; __xdata ao_radio_rdf_value = 0x55; void -ao_radio_rdf(void) +ao_radio_rdf(int ms) { uint8_t i; + uint8_t pkt_len; ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); ao_radio_rdf_running = 1; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; + /* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + if (ms > (255 * 4)) + ms = 255 * 4; + pkt_len = ms >> 2; + RF[RF_PKTLEN_OFF] = pkt_len; + ao_dma_set_transfer(ao_radio_dma, &ao_radio_rdf_value, &RFDXADDR, - RDF_PACKET_LEN, + pkt_len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 7eefee3c..d52e589c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -21,7 +21,8 @@ __xdata uint16_t ao_telemetry_interval = 0; __xdata uint8_t ao_rdf = 0; __xdata uint16_t ao_rdf_time; -#define AO_RDF_INTERVAL AO_SEC_TO_TICKS(3) +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 void ao_telemetry(void) @@ -51,8 +52,8 @@ ao_telemetry(void) if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL; - ao_radio_rdf(); + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); ao_delay(ao_telemetry_interval); } } @@ -71,6 +72,8 @@ ao_rdf_set(uint8_t rdf) ao_rdf = rdf; if (rdf == 0) ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); } __xdata struct ao_task ao_telemetry_task; -- cgit v1.2.3 From 15341b6e6dcf52df083d6aa37ef881ea6ad48ee5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 12:25:37 -0700 Subject: Set all of the values to reset the radio for telemetry Was sizeof(rdf_setup) instead of sizeof(telemetry_setup) when resetting the radio back to telemetry data mode from rdf mode. With the length value removed from the rdf config, these two arrays are no longer the same length, and so the last config value was not set leaving the radio sending garbage. Signed-off-by: Keith Packard --- src/ao_radio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index 76fa3e5d..a7fa682e 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -222,7 +222,7 @@ static __code uint8_t rdf_setup[] = { RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - /* packet length */ + /* packet length is set in-line */ RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_ADR_CHK_NONE), RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| @@ -362,7 +362,7 @@ ao_radio_rdf(int ms) ao_sleep(&ao_radio_dma_done); ao_radio_rdf_running = 0; ao_radio_idle(); - for (i = 0; i < sizeof (rdf_setup); i += 2) + for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; ao_mutex_put(&ao_radio_mutex); } -- cgit v1.2.3 From 0c771d999914f9d17c723900f2987acc45fd0fbb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 13:00:02 -0700 Subject: Move usb scanning code to ao-tools library This will allow the scanning code to be used by the command line tools as well as the ao-view GUI. Now that ao-view depends on the ao-tools library, it has been moved to the ao-tools directory as well. Signed-off-by: Keith Packard --- INSTALL | 17 +- Makefile.am | 2 +- ao-tools/Makefile.am | 2 +- ao-tools/ao-view/.gitignore | 4 + ao-tools/ao-view/Makefile.am | 37 ++ ao-tools/ao-view/ao-view.1 | 50 +++ ao-tools/ao-view/aoview.glade | 744 +++++++++++++++++++++++++++++++++++ ao-tools/ao-view/aoview.h | 323 +++++++++++++++ ao-tools/ao-view/aoview_convert.c | 42 ++ ao-tools/ao-view/aoview_dev_dialog.c | 173 ++++++++ ao-tools/ao-view/aoview_eeprom.c | 157 ++++++++ ao-tools/ao-view/aoview_file.c | 236 +++++++++++ ao-tools/ao-view/aoview_flite.c | 135 +++++++ ao-tools/ao-view/aoview_label.c | 73 ++++ ao-tools/ao-view/aoview_log.c | 70 ++++ ao-tools/ao-view/aoview_main.c | 116 ++++++ ao-tools/ao-view/aoview_monitor.c | 229 +++++++++++ ao-tools/ao-view/aoview_replay.c | 147 +++++++ ao-tools/ao-view/aoview_serial.c | 270 +++++++++++++ ao-tools/ao-view/aoview_state.c | 373 ++++++++++++++++++ ao-tools/ao-view/aoview_table.c | 83 ++++ ao-tools/ao-view/aoview_util.c | 91 +++++ ao-tools/ao-view/aoview_voice.c | 122 ++++++ ao-tools/ao-view/design | 27 ++ ao-tools/lib/Makefile.am | 3 + ao-tools/lib/cc-usbdev.c | 228 +++++++++++ ao-tools/lib/cc-util.c | 80 ++++ ao-tools/lib/cc.h | 51 +++ ao-view/.gitignore | 4 - ao-view/Makefile.am | 35 -- ao-view/ao-view.1 | 50 --- ao-view/aoview.glade | 744 ----------------------------------- ao-view/aoview.h | 337 ---------------- ao-view/aoview_convert.c | 42 -- ao-view/aoview_dev.c | 208 ---------- ao-view/aoview_dev_dialog.c | 168 -------- ao-view/aoview_eeprom.c | 157 -------- ao-view/aoview_file.c | 236 ----------- ao-view/aoview_flite.c | 135 ------- ao-view/aoview_label.c | 73 ---- ao-view/aoview_log.c | 70 ---- ao-view/aoview_main.c | 116 ------ ao-view/aoview_monitor.c | 229 ----------- ao-view/aoview_replay.c | 147 ------- ao-view/aoview_serial.c | 270 ------------- ao-view/aoview_state.c | 373 ------------------ ao-view/aoview_table.c | 83 ---- ao-view/aoview_util.c | 91 ----- ao-view/aoview_voice.c | 122 ------ ao-view/design | 27 -- configure.ac | 2 +- 51 files changed, 3881 insertions(+), 3723 deletions(-) create mode 100644 ao-tools/ao-view/.gitignore create mode 100644 ao-tools/ao-view/Makefile.am create mode 100644 ao-tools/ao-view/ao-view.1 create mode 100644 ao-tools/ao-view/aoview.glade create mode 100644 ao-tools/ao-view/aoview.h create mode 100644 ao-tools/ao-view/aoview_convert.c create mode 100644 ao-tools/ao-view/aoview_dev_dialog.c create mode 100644 ao-tools/ao-view/aoview_eeprom.c create mode 100644 ao-tools/ao-view/aoview_file.c create mode 100644 ao-tools/ao-view/aoview_flite.c create mode 100644 ao-tools/ao-view/aoview_label.c create mode 100644 ao-tools/ao-view/aoview_log.c create mode 100644 ao-tools/ao-view/aoview_main.c create mode 100644 ao-tools/ao-view/aoview_monitor.c create mode 100644 ao-tools/ao-view/aoview_replay.c create mode 100644 ao-tools/ao-view/aoview_serial.c create mode 100644 ao-tools/ao-view/aoview_state.c create mode 100644 ao-tools/ao-view/aoview_table.c create mode 100644 ao-tools/ao-view/aoview_util.c create mode 100644 ao-tools/ao-view/aoview_voice.c create mode 100644 ao-tools/ao-view/design create mode 100644 ao-tools/lib/cc-usbdev.c create mode 100644 ao-tools/lib/cc-util.c create mode 100644 ao-tools/lib/cc.h delete mode 100644 ao-view/.gitignore delete mode 100644 ao-view/Makefile.am delete mode 100644 ao-view/ao-view.1 delete mode 100644 ao-view/aoview.glade delete mode 100644 ao-view/aoview.h delete mode 100644 ao-view/aoview_convert.c delete mode 100644 ao-view/aoview_dev.c delete mode 100644 ao-view/aoview_dev_dialog.c delete mode 100644 ao-view/aoview_eeprom.c delete mode 100644 ao-view/aoview_file.c delete mode 100644 ao-view/aoview_flite.c delete mode 100644 ao-view/aoview_label.c delete mode 100644 ao-view/aoview_log.c delete mode 100644 ao-view/aoview_main.c delete mode 100644 ao-view/aoview_monitor.c delete mode 100644 ao-view/aoview_replay.c delete mode 100644 ao-view/aoview_serial.c delete mode 100644 ao-view/aoview_state.c delete mode 100644 ao-view/aoview_table.c delete mode 100644 ao-view/aoview_util.c delete mode 100644 ao-view/aoview_voice.c delete mode 100644 ao-view/design diff --git a/INSTALL b/INSTALL index 8b82ade0..2550dab7 100644 --- a/INSTALL +++ b/INSTALL @@ -2,7 +2,7 @@ Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, -2006, 2007, 2008 Free Software Foundation, Inc. +2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is free documentation; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. @@ -159,7 +159,7 @@ Particular systems CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: - ./configure CC="cc -Ae" + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. @@ -174,6 +174,16 @@ and if that doesn't work, try ./configure CC="cc -nodtk" + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + Specifying the System Type ========================== @@ -189,7 +199,8 @@ type, such as `sun4', or a canonical name which has the form: where SYSTEM can have one of these forms: - OS KERNEL-OS + OS + KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't diff --git a/Makefile.am b/Makefile.am index 96b9dea9..39e7c244 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src ao-view ao-tools ao-utils +SUBDIRS=src ao-tools ao-utils EXTRA_DIST = ChangeLog diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 98b88f38..02b4785e 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-load +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-load ao-view diff --git a/ao-tools/ao-view/.gitignore b/ao-tools/ao-view/.gitignore new file mode 100644 index 00000000..24fbc596 --- /dev/null +++ b/ao-tools/ao-view/.gitignore @@ -0,0 +1,4 @@ +*.o +aoview +aoview_glade.h +aoview_flite diff --git a/ao-tools/ao-view/Makefile.am b/ao-tools/ao-view/Makefile.am new file mode 100644 index 00000000..7b274a40 --- /dev/null +++ b/ao-tools/ao-view/Makefile.am @@ -0,0 +1,37 @@ +VERSION=$(shell git describe) + +AO_VIEW_CFLAGS=-I$(top_srcdir)/ao-tools/lib +AO_VIEW_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a +AM_CFLAGS=$(AO_VIEW_CFLAGS) $(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@ + +bin_PROGRAMS=ao-view + +ao_view_DEPENDENCIES=$(AO_VIEW_LIBS) +ao_view_LDADD=$(GNOME_LIBS) $(FLITE_LIBS) $(ALSA_LIBS) $(AO_VIEW_LIBS) $(LIBUSB_LIBS) + +ao_view_SOURCES = \ + aoview_main.c \ + aoview_dev_dialog.c \ + aoview_serial.c \ + aoview_monitor.c \ + aoview_state.c \ + aoview_convert.c \ + aoview_log.c \ + aoview_table.c \ + aoview_util.c \ + aoview_file.c \ + aoview_eeprom.c \ + aoview_voice.c \ + aoview_replay.c \ + aoview_label.c \ + aoview_flite.c \ + aoview.h + +BUILT_SOURCES = aoview_glade.h + +CLEANFILES = aoview_glade.h + +man_MANS=ao-view.1 + +aoview_glade.h: aoview.glade + sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@ diff --git a/ao-tools/ao-view/ao-view.1 b/ao-tools/ao-view/ao-view.1 new file mode 100644 index 00000000..99834c4e --- /dev/null +++ b/ao-tools/ao-view/ao-view.1 @@ -0,0 +1,50 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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 "ao-view" "" +.SH NAME +ao-view \- Rocket flight monitor +.SH SYNOPSIS +.B "ao-view" +[\--tty \fItty-device\fP] +.SH DESCRIPTION +.I ao-view +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 OPTIONS +The usual Gtk+ command line options can be used, along with +.IP "\--tty" +This selects a target device to connect at startup time to. +The target device may also be selected through the user interface. +.SH USAGE +When connected to a TeleDongle device, ao-view 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, ao-view 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-load(1), ao-eeprom(1) +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-view/aoview.glade b/ao-tools/ao-view/aoview.glade new file mode 100644 index 00000000..9a746110 --- /dev/null +++ b/ao-tools/ao-view/aoview.glade @@ -0,0 +1,744 @@ + + + + + + 900 + 700 + True + AltOS View + + + True + vertical + + + True + + + True + _File + True + + + True + + + gtk-new + True + True + True + + + + + gtk-open + True + True + True + + + + + gtk-save + True + True + True + + + + + gtk-save-as + True + True + True + + + + + True + + + + + gtk-quit + True + True + True + + + + + + + + + + True + _Edit + True + + + True + + + gtk-cut + True + True + True + + + + + gtk-copy + True + True + True + + + + + gtk-paste + True + True + True + + + + + gtk-delete + True + True + True + + + + + + + + + True + _Device + True + + + True + + + _Connect to device + True + True + False + + + + + True + gtk-connect + + + + + + + _Disconnect + True + True + False + + + True + gtk-disconnect + + + + + + + True + False + + + + + _Save EEPROM data + True + True + False + + + + + True + gtk-save + + + + + + + _Replay + True + True + False + + + + + True + gtk-media-play + + + + + + + + + + + True + _Log + True + + + True + + + _New log + True + True + False + + + True + gtk-new + + + + + + + _Configure Log + True + True + False + + + + True + gtk-preferences + + + + + + + + + + + True + _Voice + True + + + True + + + True + Enable _Voice + True + True + + + + + + + + + True + _Help + True + + + True + + + gtk-about + True + True + True + + + + + + + + + + False + 0 + + + + + True + 2 + 4 + 3 + True + + + True + Height (m) + center + + + + + True + State + + + 1 + 2 + + + + + True + RSSI (dBm) + + + 2 + 3 + + + + + True + 2 + 0 + True + + + 1 + 2 + + + + + True + 2 + pad + True + + + 1 + 2 + 1 + 2 + + + + + True + 2 + -50 + True + + + 2 + 3 + 1 + 2 + + + + + True + Speed (m/s) + + + 3 + 4 + + + + + True + 0 + True + + + 3 + 4 + 1 + 2 + + + + + False + 1 + + + + + True + + + True + True + False + both + + + 0 + + + + + True + True + False + both + + + 1 + + + + + True + True + False + both + + + 2 + + + + + 2 + + + + + + + 5 + normal + False + + + True + vertical + 2 + + + 300 + 100 + True + True + False + True + 0 + False + 1 + both + True + + + 1 + + + + + True + end + + + gtk-cancel + 1 + True + True + True + True + True + + + + False + False + 0 + + + + + gtk-connect + True + True + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + + 5 + Configure Log Directory + dialog + False + select-folder + + + True + vertical + 2 + + + True + end + + + gtk-cancel + True + True + True + True + + + + False + False + 0 + + + + + gtk-ok + True + True + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + + 5 + Failed to create log + normal + True + aoview + error + close + Cannot create log file + + + True + vertical + 2 + + + True + end + + + False + end + 0 + + + + + + + 5 + Failed to open device + normal + True + aoview + error + close + Cannot open device + + + True + vertical + 2 + + + True + end + + + False + end + 0 + + + + + + + 5 + About AoView + False + normal + aoview + False + AoView + Copyright © 2009 Keith Packard + AltOS data capture and display. + http://altusmetrum.org + AoView 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. + +AoView 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 AoView; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + Keith Packard <keithp@keithp.com> + True + + + + + True + vertical + 2 + + + True + end + + + False + end + 0 + + + + + + + 5 + EEPROM save complete + normal + True + aoview + close + Saving EEPROM data as + <filename> + + + + + True + vertical + 2 + + + True + end + + + False + end + 0 + + + + + + + 5 + True + dialog + True + aoview + False + + + True + vertical + 2 + + + True + end + + + gtk-cancel + True + True + True + True + + + + False + False + 0 + + + + + gtk-ok + True + True + True + True + + + False + False + 1 + + + + + False + end + 0 + + + + + + diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h new file mode 100644 index 00000000..6a4753ac --- /dev/null +++ b/ao-tools/ao-view/aoview.h @@ -0,0 +1,323 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AOVIEW_H_ +#define _AOVIEW_H_ + +#define _GNU_SOURCE + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cc.h" + +#include +#include +#include + +struct aogps_time { + int hour; + int minute; + int second; +}; + +struct aogps { + int nsat; + int gps_locked; + int gps_connected; + struct aogps_time gps_time; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + + int gps_extended; /* has extra data */ + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless? */ + int h_error; /* m */ + int v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct aogps_sat { + int svid; + int state; + int c_n0; +}; + +struct aogps_tracking { + int channels; + struct aogps_sat sats[12]; +}; + +struct aodata { + char callsign[16]; + int serial; + int rssi; + char state[16]; + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + int flight_accel; + int ground_accel; + int flight_vel; + int flight_pres; + int ground_pres; + struct aogps gps; + struct aogps_tracking gps_tracking; +}; + +struct aostate { + struct aodata data; + + /* derived data */ + + struct aodata prev_data; + + double report_time; + + gboolean ascent; /* going up? */ + + int ground_altitude; + int height; + double speed; + double acceleration; + double battery; + double temperature; + double main_sense; + double drogue_sense; + double baro_speed; + + int max_height; + double max_acceleration; + double max_speed; + + struct aogps gps; + struct aogps_tracking gps_tracking; + + int gps_valid; + double pad_lat; + double pad_lon; + double pad_alt; + double pad_lat_total; + double pad_lon_total; + double pad_alt_total; + int npad; + int prev_npad; + + double distance; + double bearing; + int gps_height; + + int speak_tick; + int speak_altitude; +}; + +extern struct aostate aostate; + +/* GPS is 'stable' when we've seen at least this many samples */ +#define MIN_PAD_SAMPLES 10 + +void +aoview_monitor_disconnect(void); + +gboolean +aoview_monitor_connect(char *tty); + +gboolean +aoview_monitor_parse(const char *line); + +void +aoview_monitor_reset(void); + +struct aoview_serial * +aoview_serial_open(const char *tty); + +void +aoview_serial_close(struct aoview_serial *serial); + +typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents); + +void +aoview_serial_set_callback(struct aoview_serial *serial, + aoview_serial_callback func); + +void +aoview_serial_printf(struct aoview_serial *serial, char *format, ...); + +int +aoview_serial_read(struct aoview_serial *serial, char *buf, int len); + +int +aoview_serial_getc(struct aoview_serial *serial); + +void +aoview_dev_dialog_init(GladeXML *xml); + +void +aoview_state_notify(struct aodata *data); + +void +aoview_state_new(void); + +void +aoview_state_init(GladeXML *xml); + +int16_t +aoview_pres_to_altitude(int16_t pres); + +int16_t +aoview_altitude_to_pres(int16_t alt); + +char * +aoview_fullname (char *dir, char *file); + +char * +aoview_basename(char *file); + +GtkTreeViewColumn * +aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width); + +int +aoview_mkdir(char *dir); + +void +aoview_log_init(GladeXML *xml); + +void +aoview_log_set_serial(int serial); + +int +aoview_log_get_serial(void); + +void +aoview_log_printf(char *format, ...); + +void +aoview_log_new(void); + +void +aoview_table_start(void); + +void +aoview_table_add_row(int column, char *label, char *format, ...); + +void +aoview_table_finish(void); + +void +aoview_table_init(GladeXML *xml); + +void +aoview_table_clear(void); + +struct aoview_file; + +extern char *aoview_file_dir; + +void +aoview_file_finish(struct aoview_file *file); + +gboolean +aoview_file_start(struct aoview_file *file); + +const char * +aoview_file_name(struct aoview_file *file); + +void +aoview_file_set_serial(struct aoview_file *file, int serial); + +int +aoview_file_get_serial(struct aoview_file *file); + +void +aoview_file_printf(struct aoview_file *file, char *format, ...); + +void +aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap); + +struct aoview_file * +aoview_file_new(char *ext); + +void +aoview_file_destroy(struct aoview_file *file); + +void +aoview_file_init(GladeXML *xml); + +/* aoview_eeprom.c */ + +gboolean +aoview_eeprom_save(const char *device); + +void +aoview_eeprom_init(GladeXML *xml); + +/* aoview_voice.c */ +void aoview_voice_open(void); + +void aoview_voice_close(void); + +void aoview_voice_speak(char *format, ...); + +/* aoview_label.c */ + +void aoview_label_init(GladeXML *xml); + +void +aoview_label_show(struct aostate *state); + +/* aoview_flite.c */ + +FILE * +aoview_flite_start(void); + +void +aoview_flite_stop(void); + +/* aoview_main.c */ + +extern char *aoview_tty; + +#endif /* _AOVIEW_H_ */ diff --git a/ao-tools/ao-view/aoview_convert.c b/ao-tools/ao-view/aoview_convert.c new file mode 100644 index 00000000..02416647 --- /dev/null +++ b/ao-tools/ao-view/aoview_convert.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static int16_t altitude_table[2048] = { +#include "altitude.h" +}; + +int16_t +aoview_pres_to_altitude(int16_t pres) +{ + pres = pres >> 4; + if (pres < 0) pres = 0; + if (pres > 2047) pres = 2047; + return altitude_table[pres]; +} + +int16_t +aoview_altitude_to_pres(int16_t alt) +{ + int16_t pres; + + for (pres = 0; pres < 2047; pres++) + if (altitude_table[pres] <= alt) + break; + return pres << 4; +} diff --git a/ao-tools/ao-view/aoview_dev_dialog.c b/ao-tools/ao-view/aoview_dev_dialog.c new file mode 100644 index 00000000..87396c1f --- /dev/null +++ b/ao-tools/ao-view/aoview_dev_dialog.c @@ -0,0 +1,173 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static void +aoview_dev_dialog_map(GtkWidget *widget, gpointer data) +{ + GtkTreeView *dev_list = data; + GtkListStore *list_store; + GtkTreeIter iter; + int ndev, n; + struct cc_usbdevs *devs; + struct cc_usbdev *dev; + + list_store = gtk_list_store_new(3, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + devs = cc_usbdevs_scan(); + if (devs) { + for (n = 0; n < devs->ndev; n++) { + dev = devs->dev[n]; + gtk_list_store_append(list_store, &iter); + gtk_list_store_set(list_store, &iter, + 0, dev->product, + 1, dev->serial, + 2, dev->tty, + -1); + } + } + gtk_tree_view_set_model (dev_list, GTK_TREE_MODEL(list_store)); + g_object_unref(G_OBJECT(list_store)); + gtk_tree_view_columns_autosize(dev_list); + cc_usbdevs_free(devs); +} + +static GtkMessageDialog *dev_open_fail_dialog; + +static void +aoview_dev_open_failed(char *name) +{ + char *utf8_file; + utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL); + if (!utf8_file) + utf8_file = name; + gtk_message_dialog_format_secondary_text(dev_open_fail_dialog, + "\"%s\"", utf8_file); + if (utf8_file != name) + g_free(utf8_file); + gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog)); + gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog)); +} + +gboolean dialog_save_log; + +static void +aoview_dev_selected(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) +{ + gchar *string; + gtk_tree_model_get(model, iter, + 2, &string, + -1); + if (dialog_save_log) { + dialog_save_log = FALSE; + if (!aoview_eeprom_save(string)) + aoview_dev_open_failed(string); + } else { + if (!aoview_monitor_connect(string)) + aoview_dev_open_failed(string); + } +} + +static GtkWidget *dialog; + +static void +aoview_dev_dialog_connect(GtkWidget *widget, gpointer data) +{ + GtkTreeView *dev_list = data; + GtkListStore *list_store; + GtkTreeSelection *tree_selection; + + list_store = GTK_LIST_STORE(gtk_tree_view_get_model(dev_list)); + tree_selection = gtk_tree_view_get_selection(dev_list); + gtk_tree_selection_selected_foreach(tree_selection, + aoview_dev_selected, + data); + gtk_widget_hide(dialog); +} + +static void +aoview_dev_disconnect(GtkWidget *widget) +{ + aoview_monitor_disconnect(); +} + +static void +aoview_dev_savelog(GtkWidget *widget, gpointer data) +{ + dialog_save_log = TRUE; + gtk_widget_show(dialog); +} + +#define _(a) a + +void +aoview_dev_dialog_init(GladeXML *xml) +{ + GtkTreeView *dev_list; + GtkWidget *connect_button; + GtkTreeSelection *dev_selection; + GtkWidget *ao_disconnect; + GtkWidget *ao_savelog; + + dialog = glade_xml_get_widget(xml, "device_connect_dialog"); + assert(dialog); + + dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list")); + assert(dev_list); + + aoview_add_plain_text_column(dev_list, _("Product"), 0, 16); + aoview_add_plain_text_column(dev_list, _("Serial"), 1, 8); + aoview_add_plain_text_column(dev_list, _("Device"), 2, 13); + + dev_selection = gtk_tree_view_get_selection(dev_list); + gtk_tree_selection_set_mode(dev_selection, GTK_SELECTION_SINGLE); + + g_signal_connect(G_OBJECT(dialog), "map", + G_CALLBACK(aoview_dev_dialog_map), + dev_list); + + connect_button = glade_xml_get_widget(xml, "connect_button"); + assert(connect_button); + + g_signal_connect(G_OBJECT(connect_button), "clicked", + G_CALLBACK(aoview_dev_dialog_connect), + dev_list); + + + ao_disconnect = glade_xml_get_widget(xml, "ao_disconnect"); + assert(ao_disconnect); + + g_signal_connect(G_OBJECT(ao_disconnect), "activate", + G_CALLBACK(aoview_dev_disconnect), + ao_disconnect); + + ao_savelog = glade_xml_get_widget(xml, "ao_savelog"); + assert(ao_savelog); + + g_signal_connect(G_OBJECT(ao_savelog), "activate", + G_CALLBACK(aoview_dev_savelog), + dialog); + dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog")); + assert(dev_open_fail_dialog); +} diff --git a/ao-tools/ao-view/aoview_eeprom.c b/ao-tools/ao-view/aoview_eeprom.c new file mode 100644 index 00000000..34e2deed --- /dev/null +++ b/ao-tools/ao-view/aoview_eeprom.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +#define EEPROM_LEN 1024 + +static struct aoview_file *eeprom_file; +static char eeprom_line[EEPROM_LEN + 1]; +static int eeprom_pos; +static GtkMessageDialog *eeprom_save_done; +static GtkWidget *eeprom_save_close; +static gboolean eeprom_save_shown; + +static void +aoview_eeprom_disconnect(struct aoview_serial *serial) +{ + aoview_file_finish(eeprom_file); +} + +static void +aoview_eeprom_done(struct aoview_serial *serial) +{ + gtk_window_set_title(GTK_WINDOW(eeprom_save_done), + "EEPROM data saved"); + gtk_message_dialog_set_markup(eeprom_save_done, + "EEPROM data saved as"); + if (!eeprom_save_shown) + gtk_widget_show(GTK_WIDGET(eeprom_save_done)); + eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done)); + if (eeprom_save_close) + gtk_widget_set_sensitive(eeprom_save_close, TRUE); + aoview_eeprom_disconnect(serial); +} + +static gboolean +aoview_eeprom_parse(struct aoview_serial *serial, + char *line) +{ + char cmd; + int tick; + int a; + int b; + int serial_number; + const char *name; + char *utf8_name; + + if (!strcmp(line, "end")) { + aoview_eeprom_done(serial); + return FALSE; + } + if (sscanf(line, "serial-number %u", &serial_number) == 1) { + aoview_file_set_serial(eeprom_file, serial_number); + } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { + aoview_file_printf(eeprom_file, "%s\n", line); + if (cmd == 'S' && a == 8) { + aoview_eeprom_done(serial); + return FALSE; + } + + if (!eeprom_save_shown) + { + name = aoview_file_name(eeprom_file); + if (name) { + utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL); + if (!utf8_name) + utf8_name = (char *) name; + gtk_widget_set_sensitive(eeprom_save_close, FALSE); + gtk_window_set_title(GTK_WINDOW(eeprom_save_done), + "Saving EEPROM data"); + gtk_message_dialog_set_markup(eeprom_save_done, + "Saving EEPROM data as"); + gtk_message_dialog_format_secondary_text(eeprom_save_done, "%s", + utf8_name); + if (utf8_name != name) + g_free(utf8_name); + gtk_container_check_resize(GTK_CONTAINER(eeprom_save_done)); + gtk_widget_show(GTK_WIDGET(eeprom_save_done)); + eeprom_save_shown = TRUE; + eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done)); + if (eeprom_save_close) + gtk_widget_set_sensitive(eeprom_save_close, FALSE); + } + } + } + return TRUE; +} + +static void +aoview_eeprom_callback(gpointer user_data, + struct aoview_serial *serial, + gint revents) +{ + int c; + + if (revents & (G_IO_HUP|G_IO_ERR)) { + aoview_eeprom_disconnect(serial); + return; + } + if (revents & G_IO_IN) { + for (;;) { + c = aoview_serial_getc(serial); + if (c == -1) + break; + if (c == '\r') + continue; + if (c == '\n') { + eeprom_line[eeprom_pos] = '\0'; + if (eeprom_pos) + if (!aoview_eeprom_parse(serial, eeprom_line)) + break; + eeprom_pos = 0; + } else if (eeprom_pos < EEPROM_LEN) + eeprom_line[eeprom_pos++] = c; + } + } +} + +gboolean +aoview_eeprom_save(const char *device) +{ + struct aoview_serial *serial; + + gtk_widget_hide(GTK_WIDGET(eeprom_save_done)); + eeprom_save_shown = FALSE; + serial = aoview_serial_open(device); + if (!serial) + return FALSE; + aoview_serial_set_callback(serial, aoview_eeprom_callback); + aoview_serial_printf(serial, "v\nl\n"); + return TRUE; +} + +void +aoview_eeprom_init(GladeXML *xml) +{ + eeprom_file = aoview_file_new("eeprom"); + assert(eeprom_file); + + eeprom_save_done = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "ao_save_done")); + assert(eeprom_save_done); + +} diff --git a/ao-tools/ao-view/aoview_file.c b/ao-tools/ao-view/aoview_file.c new file mode 100644 index 00000000..5288c2f7 --- /dev/null +++ b/ao-tools/ao-view/aoview_file.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +char *aoview_file_dir; + +#define ALTOS_DIR_PATH "/apps/aoview/log_dir" +#define DEFAULT_DIR "AltOS" + +struct aoview_file { + char *ext; + FILE *file; + char *name; + int failed; + int serial; + int sequence; +}; + +static void +aoview_file_save_conf(void) +{ + GConfClient *gconf_client; + + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + gconf_client_set_string(gconf_client, + ALTOS_DIR_PATH, + aoview_file_dir, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + } +} + +static void +aoview_file_configure(GtkWidget *widget, gpointer data) +{ + GtkFileChooser *chooser = data; + aoview_file_dir = gtk_file_chooser_get_filename(chooser); + aoview_file_save_conf(); + gtk_widget_hide(GTK_WIDGET(chooser)); +} + +void +aoview_file_finish(struct aoview_file *file) +{ + if (file->file) { + fclose(file->file); + file->file = NULL; + free(file->name); + file->name = NULL; + } + file->failed = 0; +} + +const char * +aoview_file_name(struct aoview_file *file) +{ + return file->name; +} + +static GtkMessageDialog *file_fail_dialog; + +static void +aoview_file_open_failed(char *name) +{ + char *utf8_file; + utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL); + if (!utf8_file) + utf8_file = name; + gtk_message_dialog_format_secondary_text(file_fail_dialog, + "\"%s\"", utf8_file); + if (utf8_file != name) + g_free(utf8_file); + gtk_widget_show(GTK_WIDGET(file_fail_dialog)); +} + +gboolean +aoview_file_start(struct aoview_file *file) +{ + char base[50]; + struct tm tm; + time_t now; + char *full; + int r; + + if (file->file) + return TRUE; + + if (file->failed) + return FALSE; + + now = time(NULL); + (void) localtime_r(&now, &tm); + aoview_mkdir(aoview_file_dir); + for (;;) { + snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + file->serial, + file->sequence, + file->ext); + full = aoview_fullname(aoview_file_dir, base); + r = access(full, F_OK); + if (r < 0) { + file->file = fopen(full, "w"); + if (!file->file) { + aoview_file_open_failed(full); + free(full); + file->failed = 1; + return FALSE; + } else { + setlinebuf(file->file); + file->name = full; + return TRUE; + } + } + free(full); + file->sequence++; + } +} + +void +aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap) +{ + if (!aoview_file_start(file)) + return; + vfprintf(file->file, format, ap); +} + +void +aoview_file_printf(struct aoview_file *file, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + aoview_file_vprintf(file, format, ap); + va_end(ap); +} + +struct aoview_file * +aoview_file_new(char *ext) +{ + struct aoview_file *file; + + file = calloc (1, sizeof (struct aoview_file)); + if (!file) + return NULL; + file->ext = strdup(ext); + if (!file->ext) { + free(file); + return NULL; + } + return file; +} + +void +aoview_file_destroy(struct aoview_file *file) +{ + if (file->file) + fclose(file->file); + if (file->name) + free(file->name); + free(file->ext); + free(file); +} + +void +aoview_file_set_serial(struct aoview_file *file, int serial) +{ + if (serial != file->serial) + aoview_file_finish(file); + file->serial = serial; +} + +int +aoview_file_get_serial(struct aoview_file *file) +{ + return file->serial; +} + +void +aoview_file_init(GladeXML *xml) +{ + GConfClient *gconf_client; + char *file_dir = NULL; + GtkFileChooser *file_chooser_dialog; + GtkWidget *file_configure_ok; + + g_type_init(); + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + file_dir = gconf_client_get_string(gconf_client, + ALTOS_DIR_PATH, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + } + if (!file_dir) { + aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR); + aoview_file_save_conf(); + } else { + aoview_file_dir = strdup(file_dir); + } + + file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog")); + assert(file_chooser_dialog); + gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir); + + file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok"); + assert(file_configure_ok); + + g_signal_connect(G_OBJECT(file_configure_ok), "clicked", + G_CALLBACK(aoview_file_configure), + file_chooser_dialog); + + + file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog")); + assert(file_fail_dialog); +} diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c new file mode 100644 index 00000000..e1b75898 --- /dev/null +++ b/ao-tools/ao-view/aoview_flite.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 +#include +#include "aoview.h" +#include + +cst_voice *register_cmu_us_kal(); +static cst_voice *voice; + +static FILE *pipe_write; +static GThread *aoview_flite_thread; + +static snd_pcm_t *alsa_handle; + +gpointer +aoview_flite_task(gpointer data) +{ + FILE *input = data; + char line[1024]; + cst_wave *wave; + int rate; + int channels; + int err; + char *samples; + int num_samples; + + err = snd_pcm_open(&alsa_handle, "default", + SND_PCM_STREAM_PLAYBACK, 0); + if (err >= 0) + { + if (err < 0) { + snd_pcm_close(alsa_handle); + alsa_handle = 0; + } + } + rate = 0; + channels = 0; + while (fgets(line, sizeof (line) - 1, input) != NULL) { + if (!alsa_handle) + continue; + wave = flite_text_to_wave(line, voice); + if (wave->sample_rate != rate || + wave->num_channels != channels) + { + rate = wave->sample_rate; + channels = wave->num_channels; + err = snd_pcm_set_params(alsa_handle, + SND_PCM_FORMAT_S16, + SND_PCM_ACCESS_RW_INTERLEAVED, + channels, + rate, + 1, + 100000); + if (err < 0) + fprintf(stderr, "alsa set_params error %s\n", + strerror(-err)); + } + err = snd_pcm_prepare(alsa_handle); + if (err < 0) + fprintf(stderr, "alsa pcm_prepare error %s\n", + strerror(-err)); + samples = (char *) wave->samples; + num_samples = wave->num_samples; + while (num_samples > 0) { + err = snd_pcm_writei(alsa_handle, + samples, num_samples); + if (err <= 0) { + fprintf(stderr, "alsa write error %s\n", + strerror(-err)); + break; + } + num_samples -= err; + samples += err * 2 * channels; + } + snd_pcm_drain(alsa_handle); + delete_wave(wave); + } + snd_pcm_close(alsa_handle); + alsa_handle = 0; + return NULL; +} + +void +aoview_flite_stop(void) +{ + int status; + if (pipe_write) { + fclose(pipe_write); + pipe_write = NULL; + } + if (aoview_flite_thread) { + g_thread_join(aoview_flite_thread); + aoview_flite_thread = NULL; + } +} + +FILE * +aoview_flite_start(void) +{ + static once; + int p[2]; + GError *error; + FILE *pipe_read; + + if (!once) { + flite_init(); + voice = register_cmu_us_kal(); + if (!voice) { + perror("register voice"); + exit(1); + } + } + aoview_flite_stop(); + pipe(p); + pipe_read = fdopen(p[0], "r"); + pipe_write = fdopen(p[1], "w"); + g_thread_create(aoview_flite_task, pipe_read, TRUE, &error); + return pipe_write; +} diff --git a/ao-tools/ao-view/aoview_label.c b/ao-tools/ao-view/aoview_label.c new file mode 100644 index 00000000..24313626 --- /dev/null +++ b/ao-tools/ao-view/aoview_label.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static struct { + char *name; + char *initial_value; + GtkLabel *widget; +} label_widgets[] = { + { "height_label", "Height (m)", NULL }, + { "state_label", "State", NULL }, + { "rssi_label", "RSSI (dBm)", NULL }, + { "speed_label", "Speed (m/s)", NULL }, + { "height_value", "0", NULL }, + { "state_value", "pad", NULL }, + { "rssi_value", "-50", NULL }, + { "speed_value", "0", NULL }, +}; + +static void +aoview_label_assign(GtkLabel *widget, char *value) +{ + char *markup; + + markup = g_markup_printf_escaped("%s", value); + gtk_label_set_markup(widget, markup); + g_free(markup); +} + +void +aoview_label_show(struct aostate *state) +{ + char line[1024]; + sprintf(line, "%d", state->height); + aoview_label_assign(label_widgets[4].widget, line); + + aoview_label_assign(label_widgets[5].widget, state->data.state); + + sprintf(line, "%d", state->data.rssi); + aoview_label_assign(label_widgets[6].widget, line); + + if (state->ascent) + sprintf(line, "%6.0f", fabs(state->speed)); + else + sprintf(line, "%6.0f", fabs(state->baro_speed)); + aoview_label_assign(label_widgets[7].widget, line); +} + +void +aoview_label_init(GladeXML *xml) +{ + int i; + for (i = 0; i < sizeof(label_widgets)/sizeof(label_widgets[0]); i++) { + label_widgets[i].widget = GTK_LABEL(glade_xml_get_widget(xml, label_widgets[i].name)); + aoview_label_assign(label_widgets[i].widget, label_widgets[i].initial_value); + assert(label_widgets[i].widget); + } +} diff --git a/ao-tools/ao-view/aoview_log.c b/ao-tools/ao-view/aoview_log.c new file mode 100644 index 00000000..1b89c28c --- /dev/null +++ b/ao-tools/ao-view/aoview_log.c @@ -0,0 +1,70 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static struct aoview_file *aoview_log; + +void +aoview_log_new(void) +{ + aoview_file_finish(aoview_log); + aoview_state_new(); +} + +void +aoview_log_set_serial(int serial) +{ + aoview_file_set_serial(aoview_log, serial); +} + +int +aoview_log_get_serial(void) +{ + return aoview_file_get_serial(aoview_log); +} + +void +aoview_log_printf(char *format, ...) +{ + va_list ap; + + va_start(ap, format); + aoview_file_vprintf(aoview_log, format, ap); + va_end(ap); +} + +static void +aoview_log_new_item(GtkWidget *widget, gpointer data) +{ + aoview_file_finish(aoview_log); +} + +void +aoview_log_init(GladeXML *xml) +{ + GtkWidget *log_new; + + aoview_log = aoview_file_new("telem"); + assert(aoview_log); + + log_new = glade_xml_get_widget(xml, "log_new"); + assert(log_new); + g_signal_connect(G_OBJECT(log_new), "activate", + G_CALLBACK(aoview_log_new_item), + NULL); +} diff --git a/ao-tools/ao-view/aoview_main.c b/ao-tools/ao-view/aoview_main.c new file mode 100644 index 00000000..64c1c027 --- /dev/null +++ b/ao-tools/ao-view/aoview_main.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static const char aoview_glade[] = { +#include "aoview_glade.h" +}; + +static void usage(void) { + printf("aoview [--device|-d device_file]"); + exit(1); +} + +static void destroy_event(GtkWidget *widget, gpointer data) +{ + gtk_main_quit(); +} + +extern int _Xdebug; +char *aoview_tty = NULL; + +int main(int argc, char **argv) +{ + GladeXML *xml = NULL; + GtkWidget *mainwindow; + GtkAboutDialog *about_dialog; + + static struct option long_options[] = { + { "tty", 1, 0, 'T'}, + { "sync", 0, 0, 's'}, + { 0, 0, 0, 0 } + }; + for (;;) { + int c, temp; + + c = getopt_long_only(argc, argv, "sT:", long_options, &temp); + if (c == -1) + break; + + switch (c) { + case 'T': + aoview_tty = optarg; + break; + case 's': + _Xdebug = 1; + break; + default: + usage(); + } + } + + g_thread_init(NULL); + gtk_init(&argc, &argv); + glade_init(); + + xml = glade_xml_new_from_buffer(aoview_glade, sizeof (aoview_glade), NULL, NULL); + + /* connect the signals in the interface */ + glade_xml_signal_autoconnect(xml); + + /* Hook up the close button. */ + mainwindow = glade_xml_get_widget(xml, "aoview"); + assert(mainwindow); + + g_signal_connect (G_OBJECT(mainwindow), "destroy", + G_CALLBACK(destroy_event), NULL); + + about_dialog = GTK_ABOUT_DIALOG(glade_xml_get_widget(xml, "about_dialog")); + assert(about_dialog); + gtk_about_dialog_set_version(about_dialog, AOVIEW_VERSION); + + aoview_voice_init(xml); + + aoview_dev_dialog_init(xml); + + aoview_state_init(xml); + + aoview_file_init(xml); + + aoview_log_init(xml); + + aoview_table_init(xml); + + aoview_eeprom_init(xml); + + aoview_replay_init(xml); + + aoview_label_init(xml); + + if (aoview_tty) { + if (!aoview_monitor_connect(aoview_tty)) { + perror(aoview_tty); + exit(1); + } + } + aoview_voice_speak("rocket flight monitor ready\n"); + + gtk_main(); + + return 0; +} diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c new file mode 100644 index 00000000..8564014b --- /dev/null +++ b/ao-tools/ao-view/aoview_monitor.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static struct aoview_serial *monitor_serial; + +#define MONITOR_LEN 1024 + +static char monitor_line[MONITOR_LEN + 1]; +static int monitor_pos; + +void +aoview_monitor_disconnect(void) +{ + if (monitor_serial) { + aoview_serial_close(monitor_serial); + monitor_serial = NULL; + } + aoview_log_new(); +} + +static void +aoview_parse_string(char *target, int len, char *source) +{ + strncpy(target, source, len-1); + target[len-1] = '\0'; +} + +static void +aoview_parse_int(int *target, char *source) +{ + *target = strtol(source, NULL, 0); +} + +static void +aoview_parse_hex(int *target, char *source) +{ + *target = strtol(source, NULL, 16); +} + +static void +aoview_parse_pos(double *target, char *source) +{ + int deg; + double min; + char dir; + double r; + + if (sscanf(source, "%d°%lf'%c", °, &min, &dir) != 3) { + *target = 0; + return; + } + r = deg + min / 60.0; + if (dir == 'S' || dir == 'W') + r = -r; + *target = r; +} + +#define PARSE_MAX_WORDS 256 + +gboolean +aoview_monitor_parse(const char *input_line) +{ + char *saveptr; + char *words[PARSE_MAX_WORDS]; + int nword; + char line_buf[8192], *line; + struct aodata data; + int tracking_pos; + + /* avoid smashing our input parameter */ + strncpy (line_buf, input_line, sizeof (line_buf)-1); + line_buf[sizeof(line_buf) - 1] = '\0'; + line = line_buf; + for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { + words[nword] = strtok_r(line, " \t\n", &saveptr); + line = NULL; + if (words[nword] == NULL) + break; + } + if (nword < 36) + return FALSE; + if (strcmp(words[0], "CALL") != 0) + return FALSE; + aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]); + aoview_parse_int(&data.serial, words[3]); + + aoview_parse_int(&data.rssi, words[5]); + aoview_parse_string(data.state, sizeof (data.state), words[9]); + aoview_parse_int(&data.tick, words[10]); + aoview_parse_int(&data.accel, words[12]); + aoview_parse_int(&data.pres, words[14]); + aoview_parse_int(&data.temp, words[16]); + aoview_parse_int(&data.batt, words[18]); + aoview_parse_int(&data.drogue, words[20]); + aoview_parse_int(&data.main, words[22]); + aoview_parse_int(&data.flight_accel, words[24]); + aoview_parse_int(&data.ground_accel, words[26]); + aoview_parse_int(&data.flight_vel, words[28]); + aoview_parse_int(&data.flight_pres, words[30]); + aoview_parse_int(&data.ground_pres, words[32]); + aoview_parse_int(&data.gps.nsat, words[34]); + if (strcmp (words[36], "unlocked") == 0) { + data.gps.gps_connected = 1; + data.gps.gps_locked = 0; + data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; + data.gps.lat = data.gps.lon = 0; + data.gps.alt = 0; + tracking_pos = 37; + } else if (nword >= 40) { + data.gps.gps_locked = 1; + data.gps.gps_connected = 1; + sscanf(words[36], "%d:%d:%d", &data.gps.gps_time.hour, &data.gps.gps_time.minute, &data.gps.gps_time.second); + aoview_parse_pos(&data.gps.lat, words[37]); + aoview_parse_pos(&data.gps.lon, words[38]); + sscanf(words[39], "%dm", &data.gps.alt); + tracking_pos = 46; + } else { + data.gps.gps_connected = 0; + data.gps.gps_locked = 0; + data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; + data.gps.lat = data.gps.lon = 0; + data.gps.alt = 0; + tracking_pos = -1; + } + if (nword >= 46) { + data.gps.gps_extended = 1; + sscanf(words[40], "%lfm/s", &data.gps.ground_speed); + sscanf(words[41], "%d", &data.gps.course); + sscanf(words[42], "%lfm/s", &data.gps.climb_rate); + sscanf(words[43], "%lf", &data.gps.hdop); + sscanf(words[44], "%d", &data.gps.h_error); + sscanf(words[45], "%d", &data.gps.v_error); + } else { + data.gps.gps_extended = 0; + data.gps.ground_speed = 0; + data.gps.course = 0; + data.gps.climb_rate = 0; + data.gps.hdop = 0; + data.gps.h_error = 0; + data.gps.v_error = 0; + } + if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { + int c, n, pos; + aoview_parse_int(&n, words[tracking_pos + 1]); + pos = tracking_pos + 2; + if (nword >= pos + n * 3) { + data.gps_tracking.channels = n; + for (c = 0; c < n; c++) { + aoview_parse_int(&data.gps_tracking.sats[c].svid, + words[pos + 0]); + aoview_parse_hex(&data.gps_tracking.sats[c].state, + words[pos + 1]); + aoview_parse_int(&data.gps_tracking.sats[c].c_n0, + words[pos + 2]); + pos += 3; + } + } else { + data.gps_tracking.channels = 0; + } + } else { + data.gps_tracking.channels = 0; + } + aoview_state_notify(&data); + return TRUE; +} + +static void +aoview_monitor_callback(gpointer user_data, + struct aoview_serial *serial, + gint revents) +{ + int c; + + if (revents & (G_IO_HUP|G_IO_ERR)) { + aoview_monitor_disconnect(); + return; + } + if (revents & G_IO_IN) { + for (;;) { + c = aoview_serial_getc(serial); + if (c == -1) + break; + if (c == '\r') + continue; + if (c == '\n') { + monitor_line[monitor_pos] = '\0'; + if (monitor_pos) { + if (aoview_monitor_parse(monitor_line)) { + aoview_log_set_serial(aostate.data.serial); + if (aoview_log_get_serial()) + aoview_log_printf ("%s\n", monitor_line); + } + } + monitor_pos = 0; + } else if (monitor_pos < MONITOR_LEN) + monitor_line[monitor_pos++] = c; + } + } +} + +gboolean +aoview_monitor_connect(char *tty) +{ + aoview_monitor_disconnect(); + monitor_serial = aoview_serial_open(tty); + if (!monitor_serial) + return FALSE; + aoview_table_clear(); + aoview_state_reset(); + aoview_serial_set_callback(monitor_serial, + aoview_monitor_callback); + return TRUE; +} diff --git a/ao-tools/ao-view/aoview_replay.c b/ao-tools/ao-view/aoview_replay.c new file mode 100644 index 00000000..da7b5d6a --- /dev/null +++ b/ao-tools/ao-view/aoview_replay.c @@ -0,0 +1,147 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +static GtkFileChooser *replay_dialog; +static GtkWidget *replay_ok; +static FILE *replay_file; +static int replay_tick; + +static int +find_tick(char *line, gboolean *is_pad) +{ + char *state = strstr(line, "STATE"); + if (!state) + return -1; + state = strchr(state, ' '); + if (!state) + return -1; + while (*state == ' ') + state++; + *is_pad = strncmp(state, "pad", 3) == 0; + while (*state && !isdigit(*state)) + state++; + return atoi(state); +} + +static void +aoview_replay_close(void) +{ + if (replay_file) { + fclose(replay_file); + replay_file = NULL; + } +} + +static char replay_line[1024]; + +static gboolean +aoview_replay_read(gpointer data); + +static gboolean +aoview_replay_execute(gpointer data) +{ + aoview_monitor_parse(replay_line); + g_idle_add(aoview_replay_read, NULL); + return FALSE; +} + +static gboolean +aoview_replay_read(gpointer data) +{ + int tick; + gboolean is_pad; + + if (!replay_file) + return FALSE; + if (fgets(replay_line, sizeof (replay_line), replay_file)) { + tick = find_tick(replay_line, &is_pad); + if (tick >= 0 && replay_tick >= 0 && !is_pad) { + while (tick < replay_tick) + tick += 65536; + g_timeout_add((tick - replay_tick) * 10, + aoview_replay_execute, + NULL); + } else { + aoview_replay_execute(NULL); + } + replay_tick = tick; + } else { + aoview_replay_close(); + } + return FALSE; +} + +static void +aoview_replay_open(GtkWidget *widget, gpointer data) +{ + char *replay_file_name; + GtkWidget *dialog; + + aoview_replay_close(); + replay_file_name = gtk_file_chooser_get_filename(replay_dialog); + replay_file = fopen(replay_file_name, "r"); + if (!replay_file) { + dialog = gtk_message_dialog_new(GTK_WINDOW(replay_dialog), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + "Error loading file '%s': %s", + replay_file_name, g_strerror(errno)); + gtk_dialog_run(GTK_DIALOG(dialog)); + gtk_widget_destroy(dialog); + } else { + replay_tick = -1; + aoview_state_reset(); + aoview_replay_read(NULL); + } + gtk_widget_hide(GTK_WIDGET(replay_dialog)); +} + +void +aoview_replay_init(GladeXML *xml) +{ + GtkFileFilter *telem_filter; + GtkFileFilter *all_filter; + GtkFileFilter *log_filter; + + telem_filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(telem_filter, "*.telem"); + gtk_file_filter_set_name(telem_filter, "Telemetry Files"); + + log_filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(log_filter, "*.log"); + gtk_file_filter_set_name(log_filter, "Log Files"); + + all_filter = gtk_file_filter_new(); + gtk_file_filter_add_pattern(all_filter, "*"); + gtk_file_filter_set_name(all_filter, "All Files"); + + replay_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "ao_replay_dialog")); + assert(replay_dialog); + gtk_file_chooser_set_current_folder(replay_dialog, aoview_file_dir); + gtk_file_chooser_add_filter(replay_dialog, telem_filter); + gtk_file_chooser_add_filter(replay_dialog, log_filter); + gtk_file_chooser_add_filter(replay_dialog, all_filter); + + replay_ok = glade_xml_get_widget(xml, "ao_replay_ok"); + assert(replay_ok); + g_signal_connect(G_OBJECT(replay_ok), "clicked", + G_CALLBACK(aoview_replay_open), + replay_dialog); +} diff --git a/ao-tools/ao-view/aoview_serial.c b/ao-tools/ao-view/aoview_serial.c new file mode 100644 index 00000000..29038b79 --- /dev/null +++ b/ao-tools/ao-view/aoview_serial.c @@ -0,0 +1,270 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" +#include + +#define AOVIEW_SERIAL_IN_BUF 64 +#define AOVIEW_SERIAL_OUT_BUF 64 + +struct aoview_buf { + char *buf; + int off; + int count; + int size; +}; + +static int +aoview_buf_write(struct aoview_buf *buf, char *data, int len) +{ + if (buf->count + len > buf->size) { + int new_size = buf->size * 2; + if (new_size == 0) + new_size = 1024; + if (buf->buf) + buf->buf = realloc (buf->buf, new_size); + else + buf->buf = malloc (new_size); + buf->size = new_size; + } + memcpy(buf->buf + buf->count, data, len); + buf->count += len; + return len; +} + +static int +aoview_buf_read(struct aoview_buf *buf, char *data, int len) +{ + if (len > buf->count - buf->off) + len = buf->count - buf->off; + memcpy (data, buf->buf + buf->off, len); + buf->off += len; + if (buf->off == buf->count) + buf->off = buf->count = 0; + return len; +} + +static int +aoview_buf_getc(struct aoview_buf *buf) +{ + char b; + int r; + + r = aoview_buf_read(buf, &b, 1); + if (r == 1) + return (int) b; + return -1; +} + +static void +aoview_buf_flush(struct aoview_buf *buf, int fd) +{ + int ret; + + if (buf->count > buf->off) { + ret = write(fd, buf->buf + buf->off, buf->count - buf->off); + if (ret > 0) { + buf->off += ret; + if (buf->off == buf->count) + buf->off = buf->count = 0; + } + } +} + +static void +aoview_buf_fill(struct aoview_buf *buf, int fd) +{ + int ret; + + while (buf->count >= buf->size) { + int new_size = buf->size * 2; + buf->buf = realloc (buf->buf, new_size); + buf->size = new_size; + } + + ret = read(fd, buf->buf + buf->count, buf->size - buf->count); + if (ret > 0) + buf->count += ret; +} + +static void +aoview_buf_init(struct aoview_buf *buf) +{ + buf->buf = malloc (buf->size = 1024); + buf->count = 0; +} + +static void +aoview_buf_fini(struct aoview_buf *buf) +{ + free(buf->buf); +} + +struct aoview_serial { + GSource source; + int fd; + struct termios save_termios; + struct aoview_buf in_buf; + struct aoview_buf out_buf; + GPollFD poll_fd; +}; + + +void +aoview_serial_printf(struct aoview_serial *serial, char *format, ...) +{ + char buf[1024]; + va_list ap; + int ret; + + /* sprintf to a local buffer */ + va_start(ap, format); + ret = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if (ret > sizeof(buf)) { + fprintf(stderr, "printf overflow for format %s\n", + format); + } + + /* flush local buffer to the wire */ + aoview_buf_write(&serial->out_buf, buf, ret); + aoview_buf_flush(&serial->out_buf, serial->fd); +} + +int +aoview_serial_read(struct aoview_serial *serial, char *buf, int len) +{ + return aoview_buf_read(&serial->in_buf, buf, len); +} + +int +aoview_serial_getc(struct aoview_serial *serial) +{ + return aoview_buf_getc(&serial->in_buf); +} + +static gboolean +serial_prepare(GSource *source, gint *timeout) +{ + struct aoview_serial *serial = (struct aoview_serial *) source; + *timeout = -1; + + if (serial->out_buf.count) + serial->poll_fd.events |= G_IO_OUT; + else + serial->poll_fd.events &= ~G_IO_OUT; + return FALSE; +} + +static gboolean +serial_check(GSource *source) +{ + struct aoview_serial *serial = (struct aoview_serial *) source; + gint revents = serial->poll_fd.revents; + + if (revents & G_IO_NVAL) + return FALSE; + if (revents & G_IO_IN) + return TRUE; + if (revents & G_IO_OUT) + return TRUE; + return FALSE; +} + +static gboolean +serial_dispatch(GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + struct aoview_serial *serial = (struct aoview_serial *) source; + aoview_serial_callback func = (aoview_serial_callback) callback; + gint revents = serial->poll_fd.revents; + + if (revents & G_IO_IN) + aoview_buf_fill(&serial->in_buf, serial->fd); + + if (revents & G_IO_OUT) + aoview_buf_flush(&serial->out_buf, serial->fd); + + if (func) + (*func)(user_data, serial, revents); + return TRUE; +} + +static void +serial_finalize(GSource *source) +{ + struct aoview_serial *serial = (struct aoview_serial *) source; + + aoview_buf_fini(&serial->in_buf); + aoview_buf_fini(&serial->out_buf); + tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios); + close (serial->fd); +} + +static GSourceFuncs serial_funcs = { + serial_prepare, + serial_check, + serial_dispatch, + serial_finalize +}; + +struct aoview_serial * +aoview_serial_open(const char *tty) +{ + struct aoview_serial *serial; + struct termios termios; + + serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial)); + aoview_buf_init(&serial->in_buf); + aoview_buf_init(&serial->out_buf); + serial->fd = open (tty, O_RDWR | O_NONBLOCK); + if (serial->fd < 0) { + g_source_destroy(&serial->source); + return NULL; + } + tcgetattr(serial->fd, &termios); + serial->save_termios = termios; + cfmakeraw(&termios); + tcsetattr(serial->fd, TCSAFLUSH, &termios); + + aoview_serial_printf(serial, "E 0\n"); + tcdrain(serial->fd); + usleep(15*1000); + tcflush(serial->fd, TCIFLUSH); + serial->poll_fd.fd = serial->fd; + serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR; + g_source_attach(&serial->source, NULL); + g_source_add_poll(&serial->source,&serial->poll_fd); + aoview_serial_set_callback(serial, NULL); + return serial; +} + +void +aoview_serial_close(struct aoview_serial *serial) +{ + g_source_remove_poll(&serial->source, &serial->poll_fd); + close(serial->fd); + g_source_destroy(&serial->source); +} + +void +aoview_serial_set_callback(struct aoview_serial *serial, + aoview_serial_callback func) +{ + g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL); +} diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c new file mode 100644 index 00000000..f75066dd --- /dev/null +++ b/ao-tools/ao-view/aoview_state.c @@ -0,0 +1,373 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" +#include + +static inline double sqr(double a) { return a * a; }; + +static void +aoview_great_circle (double start_lat, double start_lon, + double end_lat, double end_lon, + double *dist, double *bearing) +{ + const double rad = M_PI / 180; + const double earth_radius = 6371.2 * 1000; /* in meters */ + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + + double d_lat = lat2 - lat1; + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) + + sqr(cos(lat1) * sin(lat2) - + sin(lat1) * cos(lat2) * cos(d_lon))); + double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon); + double d = atan2(vdn,vdd); + double course; + + if (cos(lat1) < 1e-20) { + if (lat1 > 0) + course = M_PI; + else + course = -M_PI; + } else { + if (d < 1e-10) + course = 0; + else + course = acos((sin(lat2)-sin(lat1)*cos(d)) / + (sin(d)*cos(lat1))); + if (sin(lon2-lon1) > 0) + course = 2 * M_PI-course; + } + *dist = d * earth_radius; + *bearing = course * 180/M_PI; +} + +static void +aoview_state_add_deg(int column, char *label, double deg, char pos, char neg) +{ + double int_part; + double min; + char sign = pos; + + if (deg < 0) { + deg = -deg; + sign = neg; + } + int_part = floor (deg); + min = (deg - int_part) * 60.0; + aoview_table_add_row(column, label, "%d°%lf'%c", + (int) int_part, min, sign); + +} + +static char *ascent_states[] = { + "boost", + "fast", + "coast", + 0, +}; + +static double +aoview_time(void) +{ + struct timespec now; + + clock_gettime(CLOCK_MONOTONIC, &now); + return (double) now.tv_sec + (double) now.tv_nsec / 1.0e9; +} + +/* + * Fill out the derived data fields + */ +static void +aoview_state_derive(struct aodata *data, struct aostate *state) +{ + int i; + double new_height; + double height_change; + double time_change; + int tick_count; + + state->report_time = aoview_time(); + + state->prev_data = state->data; + state->prev_npad = state->npad; + state->data = *data; + tick_count = data->tick; + if (tick_count < state->prev_data.tick) + tick_count += 65536; + time_change = (tick_count - state->prev_data.tick) / 100.0; + + state->ground_altitude = aoview_pres_to_altitude(data->ground_pres); + new_height = aoview_pres_to_altitude(data->flight_pres) - state->ground_altitude; + height_change = new_height - state->height; + state->height = new_height; + if (time_change) + state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0; + state->acceleration = (data->ground_accel - data->flight_accel) / 27.0; + state->speed = data->flight_vel / 2700.0; + state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; + state->drogue_sense = data->drogue / 32767.0 * 15.0; + state->main_sense = data->main / 32767.0 * 15.0; + state->battery = data->batt / 32767.0 * 5.0; + if (!strcmp(data->state, "pad")) { + if (data->gps.gps_locked && data->gps.nsat >= 4) { + state->npad++; + state->pad_lat_total += data->gps.lat; + state->pad_lon_total += data->gps.lon; + state->pad_alt_total += data->gps.alt; + if (state->npad > 1) { + state->pad_lat = (state->pad_lat * 31 + data->gps.lat) / 32.0; + state->pad_lon = (state->pad_lon * 31 + data->gps.lon) / 32.0; + state->pad_alt = (state->pad_alt * 31 + data->gps.alt) / 32.0; + } else { + state->pad_lat = data->gps.lat; + state->pad_lon = data->gps.lon; + state->pad_alt = data->gps.alt; + } + } + } + state->ascent = FALSE; + for (i = 0; ascent_states[i]; i++) + if (!strcmp(data->state, ascent_states[i])) + state->ascent = TRUE; + + /* Only look at accelerometer data on the way up */ + if (state->ascent && state->acceleration > state->max_acceleration) + state->max_acceleration = state->acceleration; + if (state->ascent && state->speed > state->max_speed) + state->max_speed = state->speed; + + if (state->height > state->max_height) + state->max_height = state->height; + state->gps.gps_locked = data->gps.gps_locked; + state->gps.gps_connected = data->gps.gps_connected; + if (data->gps.gps_locked) { + state->gps = data->gps; + state->gps_valid = 1; + if (state->npad) + aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon, + &state->distance, &state->bearing); + } + if (data->gps_tracking.channels) + state->gps_tracking = data->gps_tracking; + if (state->npad) { + state->gps_height = state->gps.alt - state->pad_alt; + } else { + state->gps_height = 0; + } +} + +void +aoview_speak_state(struct aostate *state) +{ + if (strcmp(state->data.state, state->prev_data.state)) { + aoview_voice_speak("%s\n", state->data.state); + if (!strcmp(state->data.state, "drogue")) + aoview_voice_speak("apogee %d meters\n", + (int) state->max_height); + if (!strcmp(state->prev_data.state, "boost")) + aoview_voice_speak("max speed %d meters per second\n", + (int) state->max_speed); + } + if (state->prev_npad < MIN_PAD_SAMPLES && state->npad >= MIN_PAD_SAMPLES) + aoview_voice_speak("g p s ready\n"); +} + +void +aoview_speak_height(struct aostate *state) +{ + aoview_voice_speak("%d meters\n", state->height); +} + +struct aostate aostate; + +static guint aostate_timeout; + +#define COMPASS_LIMIT(n) ((n * 22.5) + 22.5/2) + +static char *compass_points[] = { + "north", + "north north east", + "north east", + "east north east", + "east", + "east south east", + "south east", + "south south east", + "south", + "south south west", + "south west", + "west south west", + "west", + "west north west", + "north west", + "north north west", +}; + +static char * +aoview_compass_point(double bearing) +{ + int i; + while (bearing < 0) + bearing += 360.0; + while (bearing >= 360.0) + bearing -= 360.0; + + i = floor ((bearing - 22.5/2) / 22.5 + 0.5); + if (i < 0) i = 0; + if (i >= sizeof (compass_points) / sizeof (compass_points[0])) + i = 0; + return compass_points[i]; +} + +static gboolean +aoview_state_timeout(gpointer data) +{ + double now = aoview_time(); + + if (strlen(aostate.data.state) > 0 && strcmp(aostate.data.state, "pad") != 0) + aoview_speak_height(&aostate); + if (now - aostate.report_time >= 20 || !strcmp(aostate.data.state, "landed")) { + if (!aostate.ascent) { + if (fabs(aostate.baro_speed) < 20 && aostate.height < 100) + aoview_voice_speak("rocket landed safely\n"); + else + aoview_voice_speak("rocket may have crashed\n"); + if (aostate.gps_valid) { + aoview_voice_speak("rocket reported %s of pad distance %d meters\n", + aoview_compass_point(aostate.bearing), + (int) aostate.distance); + } + } + aostate_timeout = 0; + return FALSE; + } + return TRUE; +} + +void +aoview_state_reset(void) +{ + memset(&aostate, '\0', sizeof (aostate)); +} + +void +aoview_state_notify(struct aodata *data) +{ + struct aostate *state = &aostate; + aoview_state_derive(data, state); + aoview_table_start(); + + if (state->npad >= MIN_PAD_SAMPLES) + aoview_table_add_row(0, "Ground state", "ready"); + else + aoview_table_add_row(0, "Ground state", "waiting for gps (%d)", + MIN_PAD_SAMPLES - state->npad); + aoview_table_add_row(0, "Rocket state", "%s", state->data.state); + aoview_table_add_row(0, "Callsign", "%s", state->data.callsign); + aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial); + + aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi); + aoview_table_add_row(0, "Height", "%6dm", state->height); + aoview_table_add_row(0, "Max height", "%6dm", state->max_height); + aoview_table_add_row(0, "Acceleration", "%7.1fm/s²", state->acceleration); + aoview_table_add_row(0, "Max acceleration", "%7.1fm/s²", state->max_acceleration); + aoview_table_add_row(0, "Speed", "%7.1fm/s", state->ascent ? state->speed : state->baro_speed); + aoview_table_add_row(0, "Max Speed", "%7.1fm/s", state->max_speed); + aoview_table_add_row(0, "Temperature", "%6.2f°C", state->temperature); + aoview_table_add_row(0, "Battery", "%5.2fV", state->battery); + aoview_table_add_row(0, "Drogue", "%5.2fV", state->drogue_sense); + aoview_table_add_row(0, "Main", "%5.2fV", state->main_sense); + aoview_table_add_row(0, "Pad altitude", "%dm", state->ground_altitude); + aoview_table_add_row(1, "Satellites", "%d", state->gps.nsat); + if (state->gps.gps_locked) { + aoview_table_add_row(1, "GPS", "locked"); + } else if (state->gps.gps_connected) { + aoview_table_add_row(1, "GPS", "unlocked"); + } else { + aoview_table_add_row(1, "GPS", "not available"); + } + if (state->gps_valid) { + aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S'); + aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); + aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); + aoview_table_add_row(1, "GPS height", "%d", state->gps_height); + aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", + state->gps.gps_time.hour, + state->gps.gps_time.minute, + state->gps.gps_time.second); + } + if (state->gps.gps_extended) { + aoview_table_add_row(1, "GPS ground speed", "%7.1fm/s %d°", + state->gps.ground_speed, + state->gps.course); + aoview_table_add_row(1, "GPS climb rate", "%7.1fm/s", + state->gps.climb_rate); + aoview_table_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)", + state->gps.hdop, state->gps.h_error, state->gps.v_error); + } + if (state->npad) { + aoview_table_add_row(1, "Distance from pad", "%5.0fm", state->distance); + aoview_table_add_row(1, "Direction from pad", "%4.0f°", state->bearing); + aoview_state_add_deg(1, "Pad latitude", state->pad_lat, 'N', 'S'); + aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W'); + aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt); + } + if (state->gps.gps_connected) { + int nsat_vis = 0; + int nsat_locked = 0; + int c; + + for (c = 0; c < state->gps_tracking.channels; c++) { + if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf) + nsat_locked++; + } + aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels); + aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked); + for (c = 0; c < state->gps_tracking.channels; c++) { + aoview_table_add_row(2, "Satellite id,state,C/N0", + "%3d,%02x,%2d%s", + state->gps_tracking.sats[c].svid, + state->gps_tracking.sats[c].state, + state->gps_tracking.sats[c].c_n0, + (state->gps_tracking.sats[c].state & 0xff) == 0xbf ? + " LOCKED" : ""); + } + } + aoview_table_finish(); + aoview_label_show(state); + aoview_speak_state(state); + if (!aostate_timeout && strcmp(state->data.state, "pad") != 0) + aostate_timeout = g_timeout_add_seconds(10, aoview_state_timeout, NULL); +} + +void +aoview_state_new(void) +{ +} + +void +aoview_state_init(GladeXML *xml) +{ + aoview_state_new(); +} diff --git a/ao-tools/ao-view/aoview_table.c b/ao-tools/ao-view/aoview_table.c new file mode 100644 index 00000000..e75ae670 --- /dev/null +++ b/ao-tools/ao-view/aoview_table.c @@ -0,0 +1,83 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +#define NCOL 3 + +static GtkTreeView *dataview[NCOL]; +static GtkListStore *datalist[NCOL]; + +void +aoview_table_start(void) +{ + int col; + for (col = 0; col < NCOL; col++) + datalist[col] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); +} + +void +aoview_table_add_row(int col, char *label, char *format, ...) +{ + char buf[1024]; + va_list ap; + GtkTreeIter iter; + + va_start(ap, format); + vsnprintf(buf, sizeof (buf), format, ap); + va_end(ap); + gtk_list_store_append(datalist[col], &iter); + gtk_list_store_set(datalist[col], &iter, + 0, label, + 1, buf, + -1); +} + +void +aoview_table_finish(void) +{ + int col; + for (col = 0; col < NCOL; col++) { + gtk_tree_view_set_model(dataview[col], GTK_TREE_MODEL(datalist[col])); + g_object_unref(G_OBJECT(datalist[col])); + gtk_tree_view_columns_autosize(dataview[col]); + } +} + +void +aoview_table_clear(void) +{ + int col; + for (col = 0; col < NCOL; col++) + gtk_tree_view_set_model(dataview[col], NULL); +} + +void +aoview_table_init(GladeXML *xml) +{ + int col; + + for (col = 0; col < NCOL; col++) { + char name[32]; + sprintf(name, "dataview_%d", col); + dataview[col] = GTK_TREE_VIEW(glade_xml_get_widget(xml, name)); + assert(dataview[col]); + + aoview_add_plain_text_column(dataview[col], "Field", 0, 20); + aoview_add_plain_text_column(dataview[col], "Value", 1, 32); + } +} diff --git a/ao-tools/ao-view/aoview_util.c b/ao-tools/ao-view/aoview_util.c new file mode 100644 index 00000000..6ea62ac9 --- /dev/null +++ b/ao-tools/ao-view/aoview_util.c @@ -0,0 +1,91 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +char * +aoview_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +char * +aoview_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +int +aoview_mkdir(char *dir) +{ + char *slash; + char *d; + char *part; + + d = dir; + for (;;) { + slash = strchr (d, '/'); + if (!slash) + slash = d + strlen(d); + if (!*slash) + break; + part = strndup(dir, slash - dir); + if (!access(part, F_OK)) + if (mkdir(part, 0777) < 0) + return -errno; + free(part); + d = slash + 1; + } + return 0; +} + +GtkTreeViewColumn * +aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width) +{ + GtkCellRenderer *renderer; + GtkTreeViewColumn *column; + + renderer = gtk_cell_renderer_text_new (); + g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); + g_object_set(renderer, "width-chars", width, NULL); + column = gtk_tree_view_column_new_with_attributes (title, renderer, + "text", model_column, + NULL); + gtk_tree_view_column_set_resizable (column, FALSE); + gtk_tree_view_append_column (view, column); + + return column; +} diff --git a/ao-tools/ao-view/aoview_voice.c b/ao-tools/ao-view/aoview_voice.c new file mode 100644 index 00000000..24422df6 --- /dev/null +++ b/ao-tools/ao-view/aoview_voice.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + +#if HAVE_FLITE +#include + +FILE *aoview_flite; + +void aoview_voice_open(void) +{ + int err; + + if (!aoview_flite) + aoview_flite = aoview_flite_start(); +} + +void aoview_voice_close(void) +{ + if (aoview_flite) { + aoview_flite_stop(); + aoview_flite = NULL; + } +} + +void aoview_voice_speak(char *format, ...) +{ + va_list ap; + + if (aoview_flite) { + va_start(ap, format); + vfprintf(aoview_flite, format, ap); + fflush(aoview_flite); + va_end(ap); + } +} + +#else +void aoview_voice_open(void) +{ +} + +void aoview_voice_close(void) +{ +} + +void aoview_voice_speak(char *format, ...) +{ +} +#endif + + +static GtkCheckMenuItem *voice_enable; + +#define ALTOS_VOICE_PATH "/apps/aoview/voice" + +static void +aoview_voice_enable(GtkWidget *widget, gpointer data) +{ + gboolean enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + GError *error; + GConfClient *gconf_client; + + if (enabled) { + aoview_voice_open(); + aoview_voice_speak("enable voice\n"); + } else { + aoview_voice_speak("disable voice\n"); + aoview_voice_close(); + } + gconf_client = gconf_client_get_default(); + gconf_client_set_bool(gconf_client, + ALTOS_VOICE_PATH, + enabled, + &error); +} + +void +aoview_voice_init(GladeXML *xml) +{ + gboolean enabled; + GConfClient *gconf_client; + + voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable")); + assert(voice_enable); + + gconf_client = gconf_client_get_default(); + enabled = TRUE; + if (gconf_client) + { + GError *error; + + error = NULL; + enabled = gconf_client_get_bool(gconf_client, + ALTOS_VOICE_PATH, + &error); + if (error) + enabled = TRUE; + } + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(voice_enable), enabled); + if (enabled) + aoview_voice_open(); + + g_signal_connect(G_OBJECT(voice_enable), "toggled", + G_CALLBACK(aoview_voice_enable), + voice_enable); +} diff --git a/ao-tools/ao-view/design b/ao-tools/ao-view/design new file mode 100644 index 00000000..6ec2ea70 --- /dev/null +++ b/ao-tools/ao-view/design @@ -0,0 +1,27 @@ +Requirements: + real-time display of telemetry + off-line display of logged data + Logging of telemetry + Capture of logged data to disk + +Input data: + accelerometer + barometer + thermometer + gps + drogue and main continuity + battery voltage + time + reported flight state + reported events + +Computed data: + velocity (from accelerometer) + altitude + range + direction + +Displays: + numeric display of current rocket status + (graphics come later) + text message log diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index 9584e216..f66ee0a9 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -16,6 +16,9 @@ libao_tools_a_SOURCES = \ ccdbg-state.c \ cc-usb.c \ cc-usb.h \ + cc.h \ + cc-usbdev.c \ + cc-util.c \ cc-bitbang.c \ cc-bitbang.h \ cp-usb-async.c \ diff --git a/ao-tools/lib/cc-usbdev.c b/ao-tools/lib/cc-usbdev.c new file mode 100644 index 00000000..d8bb8b11 --- /dev/null +++ b/ao-tools/lib/cc-usbdev.c @@ -0,0 +1,228 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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. + */ + +#include "cc.h" + +#include +#include +#include +#include +#include + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} + +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct cc_usbdev * +usb_scan_device(char *sys) +{ + struct cc_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct cc_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product = load_string(sys, "product"); + usbdev->serial = load_string(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +static void +usbdev_free(struct cc_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product); + free(usbdev->serial); + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct cc_usbdevs * +cc_usbdevs_scan(void) +{ + int e; + struct dirent **ents; + char *dir; + struct cc_usbdev *dev; + struct cc_usbdevs *devs; + int n; + + devs = calloc(1, sizeof (struct cc_usbdevs)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (dev->idVendor == 0xfffe && dev->tty) { + if (devs->dev) + devs->dev = realloc(devs->dev, + devs->ndev + 1 * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + } + free(ents); + return devs; +} + +void +cc_usbdevs_free(struct cc_usbdevs *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} diff --git a/ao-tools/lib/cc-util.c b/ao-tools/lib/cc-util.c new file mode 100644 index 00000000..7104470c --- /dev/null +++ b/ao-tools/lib/cc-util.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +int +cc_mkdir(char *dir) +{ + char *slash; + char *d; + char *part; + + d = dir; + for (;;) { + slash = strchr (d, '/'); + if (!slash) + slash = d + strlen(d); + if (!*slash) + break; + part = strndup(dir, slash - dir); + if (!access(part, F_OK)) + if (mkdir(part, 0777) < 0) + return -errno; + free(part); + d = slash + 1; + } + return 0; +} diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h new file mode 100644 index 00000000..dad11bf3 --- /dev/null +++ b/ao-tools/lib/cc.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CC_H_ +#define _CC_H_ + +char * +cc_fullname (char *dir, char *file); + +char * +cc_basename(char *file); + +int +cc_mkdir(char *dir); + +struct cc_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product; + char *serial; + int idProduct; + int idVendor; +}; + +struct cc_usbdevs { + struct cc_usbdev **dev; + int ndev; +}; + +void +cc_usbdevs_free(struct cc_usbdevs *usbdevs); + +struct cc_usbdevs * +cc_usbdevs_scan(void); + +#endif /* _CC_H_ */ diff --git a/ao-view/.gitignore b/ao-view/.gitignore deleted file mode 100644 index 24fbc596..00000000 --- a/ao-view/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -*.o -aoview -aoview_glade.h -aoview_flite diff --git a/ao-view/Makefile.am b/ao-view/Makefile.am deleted file mode 100644 index 17661c8e..00000000 --- a/ao-view/Makefile.am +++ /dev/null @@ -1,35 +0,0 @@ -VERSION=$(shell git describe) - -AM_CFLAGS=$(GNOME_CFLAGS) $(ALSA_CFLAGS) -I$(top_srcdir)/src -DAOVIEW_VERSION=\"$(VERSION)\" @FLITE_INCS@ - -bin_PROGRAMS=ao-view - -ao_view_LDADD=$(GNOME_LIBS) $(FLITE_LIBS) $(ALSA_LIBS) - -ao_view_SOURCES = \ - aoview_main.c \ - aoview_dev.c \ - aoview_dev_dialog.c \ - aoview_serial.c \ - aoview_monitor.c \ - aoview_state.c \ - aoview_convert.c \ - aoview_log.c \ - aoview_table.c \ - aoview_util.c \ - aoview_file.c \ - aoview_eeprom.c \ - aoview_voice.c \ - aoview_replay.c \ - aoview_label.c \ - aoview_flite.c \ - aoview.h - -BUILT_SOURCES = aoview_glade.h - -CLEANFILES = aoview_glade.h - -man_MANS=ao-view.1 - -aoview_glade.h: aoview.glade - sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/"/' $< > $@ diff --git a/ao-view/ao-view.1 b/ao-view/ao-view.1 deleted file mode 100644 index 99834c4e..00000000 --- a/ao-view/ao-view.1 +++ /dev/null @@ -1,50 +0,0 @@ -.\" -.\" Copyright © 2009 Keith Packard -.\" -.\" 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 "ao-view" "" -.SH NAME -ao-view \- Rocket flight monitor -.SH SYNOPSIS -.B "ao-view" -[\--tty \fItty-device\fP] -.SH DESCRIPTION -.I ao-view -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 OPTIONS -The usual Gtk+ command line options can be used, along with -.IP "\--tty" -This selects a target device to connect at startup time to. -The target device may also be selected through the user interface. -.SH USAGE -When connected to a TeleDongle device, ao-view 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, ao-view 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-load(1), ao-eeprom(1) -.SH AUTHOR -Keith Packard diff --git a/ao-view/aoview.glade b/ao-view/aoview.glade deleted file mode 100644 index 9a746110..00000000 --- a/ao-view/aoview.glade +++ /dev/null @@ -1,744 +0,0 @@ - - - - - - 900 - 700 - True - AltOS View - - - True - vertical - - - True - - - True - _File - True - - - True - - - gtk-new - True - True - True - - - - - gtk-open - True - True - True - - - - - gtk-save - True - True - True - - - - - gtk-save-as - True - True - True - - - - - True - - - - - gtk-quit - True - True - True - - - - - - - - - - True - _Edit - True - - - True - - - gtk-cut - True - True - True - - - - - gtk-copy - True - True - True - - - - - gtk-paste - True - True - True - - - - - gtk-delete - True - True - True - - - - - - - - - True - _Device - True - - - True - - - _Connect to device - True - True - False - - - - - True - gtk-connect - - - - - - - _Disconnect - True - True - False - - - True - gtk-disconnect - - - - - - - True - False - - - - - _Save EEPROM data - True - True - False - - - - - True - gtk-save - - - - - - - _Replay - True - True - False - - - - - True - gtk-media-play - - - - - - - - - - - True - _Log - True - - - True - - - _New log - True - True - False - - - True - gtk-new - - - - - - - _Configure Log - True - True - False - - - - True - gtk-preferences - - - - - - - - - - - True - _Voice - True - - - True - - - True - Enable _Voice - True - True - - - - - - - - - True - _Help - True - - - True - - - gtk-about - True - True - True - - - - - - - - - - False - 0 - - - - - True - 2 - 4 - 3 - True - - - True - Height (m) - center - - - - - True - State - - - 1 - 2 - - - - - True - RSSI (dBm) - - - 2 - 3 - - - - - True - 2 - 0 - True - - - 1 - 2 - - - - - True - 2 - pad - True - - - 1 - 2 - 1 - 2 - - - - - True - 2 - -50 - True - - - 2 - 3 - 1 - 2 - - - - - True - Speed (m/s) - - - 3 - 4 - - - - - True - 0 - True - - - 3 - 4 - 1 - 2 - - - - - False - 1 - - - - - True - - - True - True - False - both - - - 0 - - - - - True - True - False - both - - - 1 - - - - - True - True - False - both - - - 2 - - - - - 2 - - - - - - - 5 - normal - False - - - True - vertical - 2 - - - 300 - 100 - True - True - False - True - 0 - False - 1 - both - True - - - 1 - - - - - True - end - - - gtk-cancel - 1 - True - True - True - True - True - - - - False - False - 0 - - - - - gtk-connect - True - True - True - True - True - True - - - False - False - 1 - - - - - False - end - 0 - - - - - - - 5 - Configure Log Directory - dialog - False - select-folder - - - True - vertical - 2 - - - True - end - - - gtk-cancel - True - True - True - True - - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - True - True - - - False - False - 1 - - - - - False - end - 0 - - - - - - - 5 - Failed to create log - normal - True - aoview - error - close - Cannot create log file - - - True - vertical - 2 - - - True - end - - - False - end - 0 - - - - - - - 5 - Failed to open device - normal - True - aoview - error - close - Cannot open device - - - True - vertical - 2 - - - True - end - - - False - end - 0 - - - - - - - 5 - About AoView - False - normal - aoview - False - AoView - Copyright © 2009 Keith Packard - AltOS data capture and display. - http://altusmetrum.org - AoView 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. - -AoView 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 AoView; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - Keith Packard <keithp@keithp.com> - True - - - - - True - vertical - 2 - - - True - end - - - False - end - 0 - - - - - - - 5 - EEPROM save complete - normal - True - aoview - close - Saving EEPROM data as - <filename> - - - - - True - vertical - 2 - - - True - end - - - False - end - 0 - - - - - - - 5 - True - dialog - True - aoview - False - - - True - vertical - 2 - - - True - end - - - gtk-cancel - True - True - True - True - - - - False - False - 0 - - - - - gtk-ok - True - True - True - True - - - False - False - 1 - - - - - False - end - 0 - - - - - - diff --git a/ao-view/aoview.h b/ao-view/aoview.h deleted file mode 100644 index 9ca65298..00000000 --- a/ao-view/aoview.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AOVIEW_H_ -#define _AOVIEW_H_ - -#define _GNU_SOURCE - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct usbdev { - char *sys; - char *tty; - char *manufacturer; - char *product; - char *serial; - int idProduct; - int idVendor; -}; - -struct aogps_time { - int hour; - int minute; - int second; -}; - -struct aogps { - int nsat; - int gps_locked; - int gps_connected; - struct aogps_time gps_time; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - - int gps_extended; /* has extra data */ - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless? */ - int h_error; /* m */ - int v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct aogps_sat { - int svid; - int state; - int c_n0; -}; - -struct aogps_tracking { - int channels; - struct aogps_sat sats[12]; -}; - -struct aodata { - char callsign[16]; - int serial; - int rssi; - char state[16]; - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - int flight_accel; - int ground_accel; - int flight_vel; - int flight_pres; - int ground_pres; - struct aogps gps; - struct aogps_tracking gps_tracking; -}; - -struct aostate { - struct aodata data; - - /* derived data */ - - struct aodata prev_data; - - double report_time; - - gboolean ascent; /* going up? */ - - int ground_altitude; - int height; - double speed; - double acceleration; - double battery; - double temperature; - double main_sense; - double drogue_sense; - double baro_speed; - - int max_height; - double max_acceleration; - double max_speed; - - struct aogps gps; - struct aogps_tracking gps_tracking; - - int gps_valid; - double pad_lat; - double pad_lon; - double pad_alt; - double pad_lat_total; - double pad_lon_total; - double pad_alt_total; - int npad; - int prev_npad; - - double distance; - double bearing; - int gps_height; - - int speak_tick; - int speak_altitude; -}; - -extern struct aostate aostate; - -/* GPS is 'stable' when we've seen at least this many samples */ -#define MIN_PAD_SAMPLES 10 - -void -aoview_monitor_disconnect(void); - -gboolean -aoview_monitor_connect(char *tty); - -gboolean -aoview_monitor_parse(const char *line); - -void -aoview_monitor_reset(void); - -struct aoview_serial * -aoview_serial_open(const char *tty); - -void -aoview_serial_close(struct aoview_serial *serial); - -typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents); - -void -aoview_serial_set_callback(struct aoview_serial *serial, - aoview_serial_callback func); - -void -aoview_serial_printf(struct aoview_serial *serial, char *format, ...); - -int -aoview_serial_read(struct aoview_serial *serial, char *buf, int len); - -int -aoview_serial_getc(struct aoview_serial *serial); - -void -aoview_dev_dialog_init(GladeXML *xml); - -int -aoview_usb_scan(struct usbdev ***devs_ret); - -void -aoview_usbdev_free(struct usbdev *usbdev); - -void -aoview_state_notify(struct aodata *data); - -void -aoview_state_new(void); - -void -aoview_state_init(GladeXML *xml); - -int16_t -aoview_pres_to_altitude(int16_t pres); - -int16_t -aoview_altitude_to_pres(int16_t alt); - -char * -aoview_fullname (char *dir, char *file); - -char * -aoview_basename(char *file); - -GtkTreeViewColumn * -aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width); - -int -aoview_mkdir(char *dir); - -void -aoview_log_init(GladeXML *xml); - -void -aoview_log_set_serial(int serial); - -int -aoview_log_get_serial(void); - -void -aoview_log_printf(char *format, ...); - -void -aoview_log_new(void); - -void -aoview_table_start(void); - -void -aoview_table_add_row(int column, char *label, char *format, ...); - -void -aoview_table_finish(void); - -void -aoview_table_init(GladeXML *xml); - -void -aoview_table_clear(void); - -struct aoview_file; - -extern char *aoview_file_dir; - -void -aoview_file_finish(struct aoview_file *file); - -gboolean -aoview_file_start(struct aoview_file *file); - -const char * -aoview_file_name(struct aoview_file *file); - -void -aoview_file_set_serial(struct aoview_file *file, int serial); - -int -aoview_file_get_serial(struct aoview_file *file); - -void -aoview_file_printf(struct aoview_file *file, char *format, ...); - -void -aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap); - -struct aoview_file * -aoview_file_new(char *ext); - -void -aoview_file_destroy(struct aoview_file *file); - -void -aoview_file_init(GladeXML *xml); - -/* aoview_eeprom.c */ - -gboolean -aoview_eeprom_save(const char *device); - -void -aoview_eeprom_init(GladeXML *xml); - -/* aoview_voice.c */ -void aoview_voice_open(void); - -void aoview_voice_close(void); - -void aoview_voice_speak(char *format, ...); - -/* aoview_label.c */ - -void aoview_label_init(GladeXML *xml); - -void -aoview_label_show(struct aostate *state); - -/* aoview_flite.c */ - -FILE * -aoview_flite_start(void); - -void -aoview_flite_stop(void); - -/* aoview_main.c */ - -extern char *aoview_tty; - -#endif /* _AOVIEW_H_ */ diff --git a/ao-view/aoview_convert.c b/ao-view/aoview_convert.c deleted file mode 100644 index 02416647..00000000 --- a/ao-view/aoview_convert.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static int16_t altitude_table[2048] = { -#include "altitude.h" -}; - -int16_t -aoview_pres_to_altitude(int16_t pres) -{ - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; -} - -int16_t -aoview_altitude_to_pres(int16_t alt) -{ - int16_t pres; - - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; -} diff --git a/ao-view/aoview_dev.c b/ao-view/aoview_dev.c deleted file mode 100644 index 9b8cc19e..00000000 --- a/ao-view/aoview_dev.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" -#include -#include - -static char * -load_string(char *dir, char *file) -{ - char *full = aoview_fullname(dir, file); - char line[4096]; - char *r; - FILE *f; - int rlen; - - f = fopen(full, "r"); - free(full); - if (!f) - return NULL; - r = fgets(line, sizeof (line), f); - fclose(f); - if (!r) - return NULL; - rlen = strlen(r); - if (r[rlen-1] == '\n') - r[rlen-1] = '\0'; - return strdup(r); -} - -static int -load_hex(char *dir, char *file) -{ - char *line; - char *end; - long i; - - line = load_string(dir, file); - if (!line) - return -1; - i = strtol(line, &end, 16); - free(line); - if (end == line) - return -1; - return i; -} - -static int -dir_filter_tty_colon(const struct dirent *d) -{ - return strncmp(d->d_name, "tty:", 4) == 0; -} - -static int -dir_filter_tty(const struct dirent *d) -{ - return strncmp(d->d_name, "tty", 3) == 0; -} - -static char * -usb_tty(char *sys) -{ - char *base; - int num_configs; - int config; - struct dirent **namelist; - int interface; - int num_interfaces; - char endpoint_base[20]; - char *endpoint_full; - char *tty_dir; - int ntty; - char *tty; - - base = aoview_basename(sys); - num_configs = load_hex(sys, "bNumConfigurations"); - num_interfaces = load_hex(sys, "bNumInterfaces"); - for (config = 1; config <= num_configs; config++) { - for (interface = 0; interface < num_interfaces; interface++) { - sprintf(endpoint_base, "%s:%d.%d", - base, config, interface); - endpoint_full = aoview_fullname(sys, endpoint_base); - - /* Check for tty:ttyACMx style names - */ - ntty = scandir(endpoint_full, &namelist, - dir_filter_tty_colon, - alphasort); - if (ntty > 0) { - free(endpoint_full); - tty = aoview_fullname("/dev", namelist[0]->d_name + 4); - free(namelist); - return tty; - } - - /* Check for tty/ttyACMx style names - */ - tty_dir = aoview_fullname(endpoint_full, "tty"); - free(endpoint_full); - ntty = scandir(tty_dir, &namelist, - dir_filter_tty, - alphasort); - free (tty_dir); - if (ntty > 0) { - tty = aoview_fullname("/dev", namelist[0]->d_name); - free(namelist); - return tty; - } - } - } - return NULL; -} - -static struct usbdev * -usb_scan_device(char *sys) -{ - struct usbdev *usbdev; - - usbdev = calloc(1, sizeof (struct usbdev)); - if (!usbdev) - return NULL; - usbdev->sys = strdup(sys); - usbdev->manufacturer = load_string(sys, "manufacturer"); - usbdev->product = load_string(sys, "product"); - usbdev->serial = load_string(sys, "serial"); - usbdev->idProduct = load_hex(sys, "idProduct"); - usbdev->idVendor = load_hex(sys, "idVendor"); - usbdev->tty = usb_tty(sys); - return usbdev; -} - -void -aoview_usbdev_free(struct usbdev *usbdev) -{ - free(usbdev->sys); - free(usbdev->manufacturer); - free(usbdev->product); - free(usbdev->serial); - free(usbdev->tty); - free(usbdev); -} - -#define USB_DEVICES "/sys/bus/usb/devices" - -static int -dir_filter_dev(const struct dirent *d) -{ - const char *n = d->d_name; - char c; - - while ((c = *n++)) { - if (isdigit(c)) - continue; - if (c == '-') - continue; - if (c == '.' && n != d->d_name + 1) - continue; - return 0; - } - return 1; -} - -int -aoview_usb_scan(struct usbdev ***devs_ret) -{ - int n; - int ndev = 0; - int e; - struct dirent **ents; - char *dir; - struct usbdev **devs = NULL; - struct usbdev *dev; - - n = scandir (USB_DEVICES, &ents, - dir_filter_dev, - alphasort); - if (!n) - return 0; - for (e = 0; e < n; e++) { - dir = aoview_fullname(USB_DEVICES, ents[e]->d_name); - dev = usb_scan_device(dir); - free(dir); - if (dev->idVendor == 0xfffe && dev->tty) { - if (devs) - devs = realloc(devs, ndev + 1 * sizeof (struct usbdev *)); - else - devs = malloc (sizeof (struct usbdev *)); - devs[ndev++] = dev; - } - } - free(ents); - *devs_ret = devs; - return ndev; -} diff --git a/ao-view/aoview_dev_dialog.c b/ao-view/aoview_dev_dialog.c deleted file mode 100644 index 3f92085c..00000000 --- a/ao-view/aoview_dev_dialog.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static void -aoview_dev_dialog_map(GtkWidget *widget, gpointer data) -{ - GtkTreeView *dev_list = data; - GtkListStore *list_store; - GtkTreeIter iter; - int ndev, n; - struct usbdev **devs; - - list_store = gtk_list_store_new(3, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING); - - ndev = aoview_usb_scan(&devs); - for (n = 0; n < ndev; n++) { - gtk_list_store_append(list_store, &iter); - gtk_list_store_set(list_store, &iter, - 0, devs[n]->product, - 1, devs[n]->serial, - 2, devs[n]->tty, - -1); - } - gtk_tree_view_set_model (dev_list, GTK_TREE_MODEL(list_store)); - g_object_unref(G_OBJECT(list_store)); - gtk_tree_view_columns_autosize(dev_list); -} - -static GtkMessageDialog *dev_open_fail_dialog; - -static void -aoview_dev_open_failed(char *name) -{ - char *utf8_file; - utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL); - if (!utf8_file) - utf8_file = name; - gtk_message_dialog_format_secondary_text(dev_open_fail_dialog, - "\"%s\"", utf8_file); - if (utf8_file != name) - g_free(utf8_file); - gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog)); - gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog)); -} - -gboolean dialog_save_log; - -static void -aoview_dev_selected(GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - gchar *string; - gtk_tree_model_get(model, iter, - 2, &string, - -1); - if (dialog_save_log) { - dialog_save_log = FALSE; - if (!aoview_eeprom_save(string)) - aoview_dev_open_failed(string); - } else { - if (!aoview_monitor_connect(string)) - aoview_dev_open_failed(string); - } -} - -static GtkWidget *dialog; - -static void -aoview_dev_dialog_connect(GtkWidget *widget, gpointer data) -{ - GtkTreeView *dev_list = data; - GtkListStore *list_store; - GtkTreeSelection *tree_selection; - - list_store = GTK_LIST_STORE(gtk_tree_view_get_model(dev_list)); - tree_selection = gtk_tree_view_get_selection(dev_list); - gtk_tree_selection_selected_foreach(tree_selection, - aoview_dev_selected, - data); - gtk_widget_hide(dialog); -} - -static void -aoview_dev_disconnect(GtkWidget *widget) -{ - aoview_monitor_disconnect(); -} - -static void -aoview_dev_savelog(GtkWidget *widget, gpointer data) -{ - dialog_save_log = TRUE; - gtk_widget_show(dialog); -} - -#define _(a) a - -void -aoview_dev_dialog_init(GladeXML *xml) -{ - GtkTreeView *dev_list; - GtkWidget *connect_button; - GtkTreeSelection *dev_selection; - GtkWidget *ao_disconnect; - GtkWidget *ao_savelog; - - dialog = glade_xml_get_widget(xml, "device_connect_dialog"); - assert(dialog); - - dev_list = GTK_TREE_VIEW(glade_xml_get_widget(xml, "dev_list")); - assert(dev_list); - - aoview_add_plain_text_column(dev_list, _("Product"), 0, 16); - aoview_add_plain_text_column(dev_list, _("Serial"), 1, 8); - aoview_add_plain_text_column(dev_list, _("Device"), 2, 13); - - dev_selection = gtk_tree_view_get_selection(dev_list); - gtk_tree_selection_set_mode(dev_selection, GTK_SELECTION_SINGLE); - - g_signal_connect(G_OBJECT(dialog), "map", - G_CALLBACK(aoview_dev_dialog_map), - dev_list); - - connect_button = glade_xml_get_widget(xml, "connect_button"); - assert(connect_button); - - g_signal_connect(G_OBJECT(connect_button), "clicked", - G_CALLBACK(aoview_dev_dialog_connect), - dev_list); - - - ao_disconnect = glade_xml_get_widget(xml, "ao_disconnect"); - assert(ao_disconnect); - - g_signal_connect(G_OBJECT(ao_disconnect), "activate", - G_CALLBACK(aoview_dev_disconnect), - ao_disconnect); - - ao_savelog = glade_xml_get_widget(xml, "ao_savelog"); - assert(ao_savelog); - - g_signal_connect(G_OBJECT(ao_savelog), "activate", - G_CALLBACK(aoview_dev_savelog), - dialog); - dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog")); - assert(dev_open_fail_dialog); -} diff --git a/ao-view/aoview_eeprom.c b/ao-view/aoview_eeprom.c deleted file mode 100644 index 34e2deed..00000000 --- a/ao-view/aoview_eeprom.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -#define EEPROM_LEN 1024 - -static struct aoview_file *eeprom_file; -static char eeprom_line[EEPROM_LEN + 1]; -static int eeprom_pos; -static GtkMessageDialog *eeprom_save_done; -static GtkWidget *eeprom_save_close; -static gboolean eeprom_save_shown; - -static void -aoview_eeprom_disconnect(struct aoview_serial *serial) -{ - aoview_file_finish(eeprom_file); -} - -static void -aoview_eeprom_done(struct aoview_serial *serial) -{ - gtk_window_set_title(GTK_WINDOW(eeprom_save_done), - "EEPROM data saved"); - gtk_message_dialog_set_markup(eeprom_save_done, - "EEPROM data saved as"); - if (!eeprom_save_shown) - gtk_widget_show(GTK_WIDGET(eeprom_save_done)); - eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done)); - if (eeprom_save_close) - gtk_widget_set_sensitive(eeprom_save_close, TRUE); - aoview_eeprom_disconnect(serial); -} - -static gboolean -aoview_eeprom_parse(struct aoview_serial *serial, - char *line) -{ - char cmd; - int tick; - int a; - int b; - int serial_number; - const char *name; - char *utf8_name; - - if (!strcmp(line, "end")) { - aoview_eeprom_done(serial); - return FALSE; - } - if (sscanf(line, "serial-number %u", &serial_number) == 1) { - aoview_file_set_serial(eeprom_file, serial_number); - } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { - aoview_file_printf(eeprom_file, "%s\n", line); - if (cmd == 'S' && a == 8) { - aoview_eeprom_done(serial); - return FALSE; - } - - if (!eeprom_save_shown) - { - name = aoview_file_name(eeprom_file); - if (name) { - utf8_name = g_filename_to_utf8(name, -1, NULL, NULL, NULL); - if (!utf8_name) - utf8_name = (char *) name; - gtk_widget_set_sensitive(eeprom_save_close, FALSE); - gtk_window_set_title(GTK_WINDOW(eeprom_save_done), - "Saving EEPROM data"); - gtk_message_dialog_set_markup(eeprom_save_done, - "Saving EEPROM data as"); - gtk_message_dialog_format_secondary_text(eeprom_save_done, "%s", - utf8_name); - if (utf8_name != name) - g_free(utf8_name); - gtk_container_check_resize(GTK_CONTAINER(eeprom_save_done)); - gtk_widget_show(GTK_WIDGET(eeprom_save_done)); - eeprom_save_shown = TRUE; - eeprom_save_close = gtk_window_get_default_widget(GTK_WINDOW(eeprom_save_done)); - if (eeprom_save_close) - gtk_widget_set_sensitive(eeprom_save_close, FALSE); - } - } - } - return TRUE; -} - -static void -aoview_eeprom_callback(gpointer user_data, - struct aoview_serial *serial, - gint revents) -{ - int c; - - if (revents & (G_IO_HUP|G_IO_ERR)) { - aoview_eeprom_disconnect(serial); - return; - } - if (revents & G_IO_IN) { - for (;;) { - c = aoview_serial_getc(serial); - if (c == -1) - break; - if (c == '\r') - continue; - if (c == '\n') { - eeprom_line[eeprom_pos] = '\0'; - if (eeprom_pos) - if (!aoview_eeprom_parse(serial, eeprom_line)) - break; - eeprom_pos = 0; - } else if (eeprom_pos < EEPROM_LEN) - eeprom_line[eeprom_pos++] = c; - } - } -} - -gboolean -aoview_eeprom_save(const char *device) -{ - struct aoview_serial *serial; - - gtk_widget_hide(GTK_WIDGET(eeprom_save_done)); - eeprom_save_shown = FALSE; - serial = aoview_serial_open(device); - if (!serial) - return FALSE; - aoview_serial_set_callback(serial, aoview_eeprom_callback); - aoview_serial_printf(serial, "v\nl\n"); - return TRUE; -} - -void -aoview_eeprom_init(GladeXML *xml) -{ - eeprom_file = aoview_file_new("eeprom"); - assert(eeprom_file); - - eeprom_save_done = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "ao_save_done")); - assert(eeprom_save_done); - -} diff --git a/ao-view/aoview_file.c b/ao-view/aoview_file.c deleted file mode 100644 index 5288c2f7..00000000 --- a/ao-view/aoview_file.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -char *aoview_file_dir; - -#define ALTOS_DIR_PATH "/apps/aoview/log_dir" -#define DEFAULT_DIR "AltOS" - -struct aoview_file { - char *ext; - FILE *file; - char *name; - int failed; - int serial; - int sequence; -}; - -static void -aoview_file_save_conf(void) -{ - GConfClient *gconf_client; - - gconf_client = gconf_client_get_default(); - if (gconf_client) - { - gconf_client_set_string(gconf_client, - ALTOS_DIR_PATH, - aoview_file_dir, - NULL); - g_object_unref(G_OBJECT(gconf_client)); - } -} - -static void -aoview_file_configure(GtkWidget *widget, gpointer data) -{ - GtkFileChooser *chooser = data; - aoview_file_dir = gtk_file_chooser_get_filename(chooser); - aoview_file_save_conf(); - gtk_widget_hide(GTK_WIDGET(chooser)); -} - -void -aoview_file_finish(struct aoview_file *file) -{ - if (file->file) { - fclose(file->file); - file->file = NULL; - free(file->name); - file->name = NULL; - } - file->failed = 0; -} - -const char * -aoview_file_name(struct aoview_file *file) -{ - return file->name; -} - -static GtkMessageDialog *file_fail_dialog; - -static void -aoview_file_open_failed(char *name) -{ - char *utf8_file; - utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL); - if (!utf8_file) - utf8_file = name; - gtk_message_dialog_format_secondary_text(file_fail_dialog, - "\"%s\"", utf8_file); - if (utf8_file != name) - g_free(utf8_file); - gtk_widget_show(GTK_WIDGET(file_fail_dialog)); -} - -gboolean -aoview_file_start(struct aoview_file *file) -{ - char base[50]; - struct tm tm; - time_t now; - char *full; - int r; - - if (file->file) - return TRUE; - - if (file->failed) - return FALSE; - - now = time(NULL); - (void) localtime_r(&now, &tm); - aoview_mkdir(aoview_file_dir); - for (;;) { - snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - file->serial, - file->sequence, - file->ext); - full = aoview_fullname(aoview_file_dir, base); - r = access(full, F_OK); - if (r < 0) { - file->file = fopen(full, "w"); - if (!file->file) { - aoview_file_open_failed(full); - free(full); - file->failed = 1; - return FALSE; - } else { - setlinebuf(file->file); - file->name = full; - return TRUE; - } - } - free(full); - file->sequence++; - } -} - -void -aoview_file_vprintf(struct aoview_file *file, char *format, va_list ap) -{ - if (!aoview_file_start(file)) - return; - vfprintf(file->file, format, ap); -} - -void -aoview_file_printf(struct aoview_file *file, char *format, ...) -{ - va_list ap; - - va_start(ap, format); - aoview_file_vprintf(file, format, ap); - va_end(ap); -} - -struct aoview_file * -aoview_file_new(char *ext) -{ - struct aoview_file *file; - - file = calloc (1, sizeof (struct aoview_file)); - if (!file) - return NULL; - file->ext = strdup(ext); - if (!file->ext) { - free(file); - return NULL; - } - return file; -} - -void -aoview_file_destroy(struct aoview_file *file) -{ - if (file->file) - fclose(file->file); - if (file->name) - free(file->name); - free(file->ext); - free(file); -} - -void -aoview_file_set_serial(struct aoview_file *file, int serial) -{ - if (serial != file->serial) - aoview_file_finish(file); - file->serial = serial; -} - -int -aoview_file_get_serial(struct aoview_file *file) -{ - return file->serial; -} - -void -aoview_file_init(GladeXML *xml) -{ - GConfClient *gconf_client; - char *file_dir = NULL; - GtkFileChooser *file_chooser_dialog; - GtkWidget *file_configure_ok; - - g_type_init(); - gconf_client = gconf_client_get_default(); - if (gconf_client) - { - file_dir = gconf_client_get_string(gconf_client, - ALTOS_DIR_PATH, - NULL); - g_object_unref(G_OBJECT(gconf_client)); - } - if (!file_dir) { - aoview_file_dir = aoview_fullname(getenv("HOME"), DEFAULT_DIR); - aoview_file_save_conf(); - } else { - aoview_file_dir = strdup(file_dir); - } - - file_chooser_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "file_chooser_dialog")); - assert(file_chooser_dialog); - gtk_file_chooser_set_filename(file_chooser_dialog, aoview_file_dir); - - file_configure_ok = glade_xml_get_widget(xml, "file_configure_ok"); - assert(file_configure_ok); - - g_signal_connect(G_OBJECT(file_configure_ok), "clicked", - G_CALLBACK(aoview_file_configure), - file_chooser_dialog); - - - file_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "file_fail_dialog")); - assert(file_fail_dialog); -} diff --git a/ao-view/aoview_flite.c b/ao-view/aoview_flite.c deleted file mode 100644 index e1b75898..00000000 --- a/ao-view/aoview_flite.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 -#include -#include "aoview.h" -#include - -cst_voice *register_cmu_us_kal(); -static cst_voice *voice; - -static FILE *pipe_write; -static GThread *aoview_flite_thread; - -static snd_pcm_t *alsa_handle; - -gpointer -aoview_flite_task(gpointer data) -{ - FILE *input = data; - char line[1024]; - cst_wave *wave; - int rate; - int channels; - int err; - char *samples; - int num_samples; - - err = snd_pcm_open(&alsa_handle, "default", - SND_PCM_STREAM_PLAYBACK, 0); - if (err >= 0) - { - if (err < 0) { - snd_pcm_close(alsa_handle); - alsa_handle = 0; - } - } - rate = 0; - channels = 0; - while (fgets(line, sizeof (line) - 1, input) != NULL) { - if (!alsa_handle) - continue; - wave = flite_text_to_wave(line, voice); - if (wave->sample_rate != rate || - wave->num_channels != channels) - { - rate = wave->sample_rate; - channels = wave->num_channels; - err = snd_pcm_set_params(alsa_handle, - SND_PCM_FORMAT_S16, - SND_PCM_ACCESS_RW_INTERLEAVED, - channels, - rate, - 1, - 100000); - if (err < 0) - fprintf(stderr, "alsa set_params error %s\n", - strerror(-err)); - } - err = snd_pcm_prepare(alsa_handle); - if (err < 0) - fprintf(stderr, "alsa pcm_prepare error %s\n", - strerror(-err)); - samples = (char *) wave->samples; - num_samples = wave->num_samples; - while (num_samples > 0) { - err = snd_pcm_writei(alsa_handle, - samples, num_samples); - if (err <= 0) { - fprintf(stderr, "alsa write error %s\n", - strerror(-err)); - break; - } - num_samples -= err; - samples += err * 2 * channels; - } - snd_pcm_drain(alsa_handle); - delete_wave(wave); - } - snd_pcm_close(alsa_handle); - alsa_handle = 0; - return NULL; -} - -void -aoview_flite_stop(void) -{ - int status; - if (pipe_write) { - fclose(pipe_write); - pipe_write = NULL; - } - if (aoview_flite_thread) { - g_thread_join(aoview_flite_thread); - aoview_flite_thread = NULL; - } -} - -FILE * -aoview_flite_start(void) -{ - static once; - int p[2]; - GError *error; - FILE *pipe_read; - - if (!once) { - flite_init(); - voice = register_cmu_us_kal(); - if (!voice) { - perror("register voice"); - exit(1); - } - } - aoview_flite_stop(); - pipe(p); - pipe_read = fdopen(p[0], "r"); - pipe_write = fdopen(p[1], "w"); - g_thread_create(aoview_flite_task, pipe_read, TRUE, &error); - return pipe_write; -} diff --git a/ao-view/aoview_label.c b/ao-view/aoview_label.c deleted file mode 100644 index 24313626..00000000 --- a/ao-view/aoview_label.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static struct { - char *name; - char *initial_value; - GtkLabel *widget; -} label_widgets[] = { - { "height_label", "Height (m)", NULL }, - { "state_label", "State", NULL }, - { "rssi_label", "RSSI (dBm)", NULL }, - { "speed_label", "Speed (m/s)", NULL }, - { "height_value", "0", NULL }, - { "state_value", "pad", NULL }, - { "rssi_value", "-50", NULL }, - { "speed_value", "0", NULL }, -}; - -static void -aoview_label_assign(GtkLabel *widget, char *value) -{ - char *markup; - - markup = g_markup_printf_escaped("%s", value); - gtk_label_set_markup(widget, markup); - g_free(markup); -} - -void -aoview_label_show(struct aostate *state) -{ - char line[1024]; - sprintf(line, "%d", state->height); - aoview_label_assign(label_widgets[4].widget, line); - - aoview_label_assign(label_widgets[5].widget, state->data.state); - - sprintf(line, "%d", state->data.rssi); - aoview_label_assign(label_widgets[6].widget, line); - - if (state->ascent) - sprintf(line, "%6.0f", fabs(state->speed)); - else - sprintf(line, "%6.0f", fabs(state->baro_speed)); - aoview_label_assign(label_widgets[7].widget, line); -} - -void -aoview_label_init(GladeXML *xml) -{ - int i; - for (i = 0; i < sizeof(label_widgets)/sizeof(label_widgets[0]); i++) { - label_widgets[i].widget = GTK_LABEL(glade_xml_get_widget(xml, label_widgets[i].name)); - aoview_label_assign(label_widgets[i].widget, label_widgets[i].initial_value); - assert(label_widgets[i].widget); - } -} diff --git a/ao-view/aoview_log.c b/ao-view/aoview_log.c deleted file mode 100644 index 1b89c28c..00000000 --- a/ao-view/aoview_log.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static struct aoview_file *aoview_log; - -void -aoview_log_new(void) -{ - aoview_file_finish(aoview_log); - aoview_state_new(); -} - -void -aoview_log_set_serial(int serial) -{ - aoview_file_set_serial(aoview_log, serial); -} - -int -aoview_log_get_serial(void) -{ - return aoview_file_get_serial(aoview_log); -} - -void -aoview_log_printf(char *format, ...) -{ - va_list ap; - - va_start(ap, format); - aoview_file_vprintf(aoview_log, format, ap); - va_end(ap); -} - -static void -aoview_log_new_item(GtkWidget *widget, gpointer data) -{ - aoview_file_finish(aoview_log); -} - -void -aoview_log_init(GladeXML *xml) -{ - GtkWidget *log_new; - - aoview_log = aoview_file_new("telem"); - assert(aoview_log); - - log_new = glade_xml_get_widget(xml, "log_new"); - assert(log_new); - g_signal_connect(G_OBJECT(log_new), "activate", - G_CALLBACK(aoview_log_new_item), - NULL); -} diff --git a/ao-view/aoview_main.c b/ao-view/aoview_main.c deleted file mode 100644 index 64c1c027..00000000 --- a/ao-view/aoview_main.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static const char aoview_glade[] = { -#include "aoview_glade.h" -}; - -static void usage(void) { - printf("aoview [--device|-d device_file]"); - exit(1); -} - -static void destroy_event(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -extern int _Xdebug; -char *aoview_tty = NULL; - -int main(int argc, char **argv) -{ - GladeXML *xml = NULL; - GtkWidget *mainwindow; - GtkAboutDialog *about_dialog; - - static struct option long_options[] = { - { "tty", 1, 0, 'T'}, - { "sync", 0, 0, 's'}, - { 0, 0, 0, 0 } - }; - for (;;) { - int c, temp; - - c = getopt_long_only(argc, argv, "sT:", long_options, &temp); - if (c == -1) - break; - - switch (c) { - case 'T': - aoview_tty = optarg; - break; - case 's': - _Xdebug = 1; - break; - default: - usage(); - } - } - - g_thread_init(NULL); - gtk_init(&argc, &argv); - glade_init(); - - xml = glade_xml_new_from_buffer(aoview_glade, sizeof (aoview_glade), NULL, NULL); - - /* connect the signals in the interface */ - glade_xml_signal_autoconnect(xml); - - /* Hook up the close button. */ - mainwindow = glade_xml_get_widget(xml, "aoview"); - assert(mainwindow); - - g_signal_connect (G_OBJECT(mainwindow), "destroy", - G_CALLBACK(destroy_event), NULL); - - about_dialog = GTK_ABOUT_DIALOG(glade_xml_get_widget(xml, "about_dialog")); - assert(about_dialog); - gtk_about_dialog_set_version(about_dialog, AOVIEW_VERSION); - - aoview_voice_init(xml); - - aoview_dev_dialog_init(xml); - - aoview_state_init(xml); - - aoview_file_init(xml); - - aoview_log_init(xml); - - aoview_table_init(xml); - - aoview_eeprom_init(xml); - - aoview_replay_init(xml); - - aoview_label_init(xml); - - if (aoview_tty) { - if (!aoview_monitor_connect(aoview_tty)) { - perror(aoview_tty); - exit(1); - } - } - aoview_voice_speak("rocket flight monitor ready\n"); - - gtk_main(); - - return 0; -} diff --git a/ao-view/aoview_monitor.c b/ao-view/aoview_monitor.c deleted file mode 100644 index 8564014b..00000000 --- a/ao-view/aoview_monitor.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static struct aoview_serial *monitor_serial; - -#define MONITOR_LEN 1024 - -static char monitor_line[MONITOR_LEN + 1]; -static int monitor_pos; - -void -aoview_monitor_disconnect(void) -{ - if (monitor_serial) { - aoview_serial_close(monitor_serial); - monitor_serial = NULL; - } - aoview_log_new(); -} - -static void -aoview_parse_string(char *target, int len, char *source) -{ - strncpy(target, source, len-1); - target[len-1] = '\0'; -} - -static void -aoview_parse_int(int *target, char *source) -{ - *target = strtol(source, NULL, 0); -} - -static void -aoview_parse_hex(int *target, char *source) -{ - *target = strtol(source, NULL, 16); -} - -static void -aoview_parse_pos(double *target, char *source) -{ - int deg; - double min; - char dir; - double r; - - if (sscanf(source, "%d°%lf'%c", °, &min, &dir) != 3) { - *target = 0; - return; - } - r = deg + min / 60.0; - if (dir == 'S' || dir == 'W') - r = -r; - *target = r; -} - -#define PARSE_MAX_WORDS 256 - -gboolean -aoview_monitor_parse(const char *input_line) -{ - char *saveptr; - char *words[PARSE_MAX_WORDS]; - int nword; - char line_buf[8192], *line; - struct aodata data; - int tracking_pos; - - /* avoid smashing our input parameter */ - strncpy (line_buf, input_line, sizeof (line_buf)-1); - line_buf[sizeof(line_buf) - 1] = '\0'; - line = line_buf; - for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { - words[nword] = strtok_r(line, " \t\n", &saveptr); - line = NULL; - if (words[nword] == NULL) - break; - } - if (nword < 36) - return FALSE; - if (strcmp(words[0], "CALL") != 0) - return FALSE; - aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]); - aoview_parse_int(&data.serial, words[3]); - - aoview_parse_int(&data.rssi, words[5]); - aoview_parse_string(data.state, sizeof (data.state), words[9]); - aoview_parse_int(&data.tick, words[10]); - aoview_parse_int(&data.accel, words[12]); - aoview_parse_int(&data.pres, words[14]); - aoview_parse_int(&data.temp, words[16]); - aoview_parse_int(&data.batt, words[18]); - aoview_parse_int(&data.drogue, words[20]); - aoview_parse_int(&data.main, words[22]); - aoview_parse_int(&data.flight_accel, words[24]); - aoview_parse_int(&data.ground_accel, words[26]); - aoview_parse_int(&data.flight_vel, words[28]); - aoview_parse_int(&data.flight_pres, words[30]); - aoview_parse_int(&data.ground_pres, words[32]); - aoview_parse_int(&data.gps.nsat, words[34]); - if (strcmp (words[36], "unlocked") == 0) { - data.gps.gps_connected = 1; - data.gps.gps_locked = 0; - data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; - data.gps.lat = data.gps.lon = 0; - data.gps.alt = 0; - tracking_pos = 37; - } else if (nword >= 40) { - data.gps.gps_locked = 1; - data.gps.gps_connected = 1; - sscanf(words[36], "%d:%d:%d", &data.gps.gps_time.hour, &data.gps.gps_time.minute, &data.gps.gps_time.second); - aoview_parse_pos(&data.gps.lat, words[37]); - aoview_parse_pos(&data.gps.lon, words[38]); - sscanf(words[39], "%dm", &data.gps.alt); - tracking_pos = 46; - } else { - data.gps.gps_connected = 0; - data.gps.gps_locked = 0; - data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; - data.gps.lat = data.gps.lon = 0; - data.gps.alt = 0; - tracking_pos = -1; - } - if (nword >= 46) { - data.gps.gps_extended = 1; - sscanf(words[40], "%lfm/s", &data.gps.ground_speed); - sscanf(words[41], "%d", &data.gps.course); - sscanf(words[42], "%lfm/s", &data.gps.climb_rate); - sscanf(words[43], "%lf", &data.gps.hdop); - sscanf(words[44], "%d", &data.gps.h_error); - sscanf(words[45], "%d", &data.gps.v_error); - } else { - data.gps.gps_extended = 0; - data.gps.ground_speed = 0; - data.gps.course = 0; - data.gps.climb_rate = 0; - data.gps.hdop = 0; - data.gps.h_error = 0; - data.gps.v_error = 0; - } - if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { - int c, n, pos; - aoview_parse_int(&n, words[tracking_pos + 1]); - pos = tracking_pos + 2; - if (nword >= pos + n * 3) { - data.gps_tracking.channels = n; - for (c = 0; c < n; c++) { - aoview_parse_int(&data.gps_tracking.sats[c].svid, - words[pos + 0]); - aoview_parse_hex(&data.gps_tracking.sats[c].state, - words[pos + 1]); - aoview_parse_int(&data.gps_tracking.sats[c].c_n0, - words[pos + 2]); - pos += 3; - } - } else { - data.gps_tracking.channels = 0; - } - } else { - data.gps_tracking.channels = 0; - } - aoview_state_notify(&data); - return TRUE; -} - -static void -aoview_monitor_callback(gpointer user_data, - struct aoview_serial *serial, - gint revents) -{ - int c; - - if (revents & (G_IO_HUP|G_IO_ERR)) { - aoview_monitor_disconnect(); - return; - } - if (revents & G_IO_IN) { - for (;;) { - c = aoview_serial_getc(serial); - if (c == -1) - break; - if (c == '\r') - continue; - if (c == '\n') { - monitor_line[monitor_pos] = '\0'; - if (monitor_pos) { - if (aoview_monitor_parse(monitor_line)) { - aoview_log_set_serial(aostate.data.serial); - if (aoview_log_get_serial()) - aoview_log_printf ("%s\n", monitor_line); - } - } - monitor_pos = 0; - } else if (monitor_pos < MONITOR_LEN) - monitor_line[monitor_pos++] = c; - } - } -} - -gboolean -aoview_monitor_connect(char *tty) -{ - aoview_monitor_disconnect(); - monitor_serial = aoview_serial_open(tty); - if (!monitor_serial) - return FALSE; - aoview_table_clear(); - aoview_state_reset(); - aoview_serial_set_callback(monitor_serial, - aoview_monitor_callback); - return TRUE; -} diff --git a/ao-view/aoview_replay.c b/ao-view/aoview_replay.c deleted file mode 100644 index da7b5d6a..00000000 --- a/ao-view/aoview_replay.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -static GtkFileChooser *replay_dialog; -static GtkWidget *replay_ok; -static FILE *replay_file; -static int replay_tick; - -static int -find_tick(char *line, gboolean *is_pad) -{ - char *state = strstr(line, "STATE"); - if (!state) - return -1; - state = strchr(state, ' '); - if (!state) - return -1; - while (*state == ' ') - state++; - *is_pad = strncmp(state, "pad", 3) == 0; - while (*state && !isdigit(*state)) - state++; - return atoi(state); -} - -static void -aoview_replay_close(void) -{ - if (replay_file) { - fclose(replay_file); - replay_file = NULL; - } -} - -static char replay_line[1024]; - -static gboolean -aoview_replay_read(gpointer data); - -static gboolean -aoview_replay_execute(gpointer data) -{ - aoview_monitor_parse(replay_line); - g_idle_add(aoview_replay_read, NULL); - return FALSE; -} - -static gboolean -aoview_replay_read(gpointer data) -{ - int tick; - gboolean is_pad; - - if (!replay_file) - return FALSE; - if (fgets(replay_line, sizeof (replay_line), replay_file)) { - tick = find_tick(replay_line, &is_pad); - if (tick >= 0 && replay_tick >= 0 && !is_pad) { - while (tick < replay_tick) - tick += 65536; - g_timeout_add((tick - replay_tick) * 10, - aoview_replay_execute, - NULL); - } else { - aoview_replay_execute(NULL); - } - replay_tick = tick; - } else { - aoview_replay_close(); - } - return FALSE; -} - -static void -aoview_replay_open(GtkWidget *widget, gpointer data) -{ - char *replay_file_name; - GtkWidget *dialog; - - aoview_replay_close(); - replay_file_name = gtk_file_chooser_get_filename(replay_dialog); - replay_file = fopen(replay_file_name, "r"); - if (!replay_file) { - dialog = gtk_message_dialog_new(GTK_WINDOW(replay_dialog), - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_CLOSE, - "Error loading file '%s': %s", - replay_file_name, g_strerror(errno)); - gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - } else { - replay_tick = -1; - aoview_state_reset(); - aoview_replay_read(NULL); - } - gtk_widget_hide(GTK_WIDGET(replay_dialog)); -} - -void -aoview_replay_init(GladeXML *xml) -{ - GtkFileFilter *telem_filter; - GtkFileFilter *all_filter; - GtkFileFilter *log_filter; - - telem_filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(telem_filter, "*.telem"); - gtk_file_filter_set_name(telem_filter, "Telemetry Files"); - - log_filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(log_filter, "*.log"); - gtk_file_filter_set_name(log_filter, "Log Files"); - - all_filter = gtk_file_filter_new(); - gtk_file_filter_add_pattern(all_filter, "*"); - gtk_file_filter_set_name(all_filter, "All Files"); - - replay_dialog = GTK_FILE_CHOOSER(glade_xml_get_widget(xml, "ao_replay_dialog")); - assert(replay_dialog); - gtk_file_chooser_set_current_folder(replay_dialog, aoview_file_dir); - gtk_file_chooser_add_filter(replay_dialog, telem_filter); - gtk_file_chooser_add_filter(replay_dialog, log_filter); - gtk_file_chooser_add_filter(replay_dialog, all_filter); - - replay_ok = glade_xml_get_widget(xml, "ao_replay_ok"); - assert(replay_ok); - g_signal_connect(G_OBJECT(replay_ok), "clicked", - G_CALLBACK(aoview_replay_open), - replay_dialog); -} diff --git a/ao-view/aoview_serial.c b/ao-view/aoview_serial.c deleted file mode 100644 index 29038b79..00000000 --- a/ao-view/aoview_serial.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" -#include - -#define AOVIEW_SERIAL_IN_BUF 64 -#define AOVIEW_SERIAL_OUT_BUF 64 - -struct aoview_buf { - char *buf; - int off; - int count; - int size; -}; - -static int -aoview_buf_write(struct aoview_buf *buf, char *data, int len) -{ - if (buf->count + len > buf->size) { - int new_size = buf->size * 2; - if (new_size == 0) - new_size = 1024; - if (buf->buf) - buf->buf = realloc (buf->buf, new_size); - else - buf->buf = malloc (new_size); - buf->size = new_size; - } - memcpy(buf->buf + buf->count, data, len); - buf->count += len; - return len; -} - -static int -aoview_buf_read(struct aoview_buf *buf, char *data, int len) -{ - if (len > buf->count - buf->off) - len = buf->count - buf->off; - memcpy (data, buf->buf + buf->off, len); - buf->off += len; - if (buf->off == buf->count) - buf->off = buf->count = 0; - return len; -} - -static int -aoview_buf_getc(struct aoview_buf *buf) -{ - char b; - int r; - - r = aoview_buf_read(buf, &b, 1); - if (r == 1) - return (int) b; - return -1; -} - -static void -aoview_buf_flush(struct aoview_buf *buf, int fd) -{ - int ret; - - if (buf->count > buf->off) { - ret = write(fd, buf->buf + buf->off, buf->count - buf->off); - if (ret > 0) { - buf->off += ret; - if (buf->off == buf->count) - buf->off = buf->count = 0; - } - } -} - -static void -aoview_buf_fill(struct aoview_buf *buf, int fd) -{ - int ret; - - while (buf->count >= buf->size) { - int new_size = buf->size * 2; - buf->buf = realloc (buf->buf, new_size); - buf->size = new_size; - } - - ret = read(fd, buf->buf + buf->count, buf->size - buf->count); - if (ret > 0) - buf->count += ret; -} - -static void -aoview_buf_init(struct aoview_buf *buf) -{ - buf->buf = malloc (buf->size = 1024); - buf->count = 0; -} - -static void -aoview_buf_fini(struct aoview_buf *buf) -{ - free(buf->buf); -} - -struct aoview_serial { - GSource source; - int fd; - struct termios save_termios; - struct aoview_buf in_buf; - struct aoview_buf out_buf; - GPollFD poll_fd; -}; - - -void -aoview_serial_printf(struct aoview_serial *serial, char *format, ...) -{ - char buf[1024]; - va_list ap; - int ret; - - /* sprintf to a local buffer */ - va_start(ap, format); - ret = vsnprintf(buf, sizeof(buf), format, ap); - va_end(ap); - if (ret > sizeof(buf)) { - fprintf(stderr, "printf overflow for format %s\n", - format); - } - - /* flush local buffer to the wire */ - aoview_buf_write(&serial->out_buf, buf, ret); - aoview_buf_flush(&serial->out_buf, serial->fd); -} - -int -aoview_serial_read(struct aoview_serial *serial, char *buf, int len) -{ - return aoview_buf_read(&serial->in_buf, buf, len); -} - -int -aoview_serial_getc(struct aoview_serial *serial) -{ - return aoview_buf_getc(&serial->in_buf); -} - -static gboolean -serial_prepare(GSource *source, gint *timeout) -{ - struct aoview_serial *serial = (struct aoview_serial *) source; - *timeout = -1; - - if (serial->out_buf.count) - serial->poll_fd.events |= G_IO_OUT; - else - serial->poll_fd.events &= ~G_IO_OUT; - return FALSE; -} - -static gboolean -serial_check(GSource *source) -{ - struct aoview_serial *serial = (struct aoview_serial *) source; - gint revents = serial->poll_fd.revents; - - if (revents & G_IO_NVAL) - return FALSE; - if (revents & G_IO_IN) - return TRUE; - if (revents & G_IO_OUT) - return TRUE; - return FALSE; -} - -static gboolean -serial_dispatch(GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - struct aoview_serial *serial = (struct aoview_serial *) source; - aoview_serial_callback func = (aoview_serial_callback) callback; - gint revents = serial->poll_fd.revents; - - if (revents & G_IO_IN) - aoview_buf_fill(&serial->in_buf, serial->fd); - - if (revents & G_IO_OUT) - aoview_buf_flush(&serial->out_buf, serial->fd); - - if (func) - (*func)(user_data, serial, revents); - return TRUE; -} - -static void -serial_finalize(GSource *source) -{ - struct aoview_serial *serial = (struct aoview_serial *) source; - - aoview_buf_fini(&serial->in_buf); - aoview_buf_fini(&serial->out_buf); - tcsetattr(serial->fd, TCSAFLUSH, &serial->save_termios); - close (serial->fd); -} - -static GSourceFuncs serial_funcs = { - serial_prepare, - serial_check, - serial_dispatch, - serial_finalize -}; - -struct aoview_serial * -aoview_serial_open(const char *tty) -{ - struct aoview_serial *serial; - struct termios termios; - - serial = (struct aoview_serial *) g_source_new(&serial_funcs, sizeof (struct aoview_serial)); - aoview_buf_init(&serial->in_buf); - aoview_buf_init(&serial->out_buf); - serial->fd = open (tty, O_RDWR | O_NONBLOCK); - if (serial->fd < 0) { - g_source_destroy(&serial->source); - return NULL; - } - tcgetattr(serial->fd, &termios); - serial->save_termios = termios; - cfmakeraw(&termios); - tcsetattr(serial->fd, TCSAFLUSH, &termios); - - aoview_serial_printf(serial, "E 0\n"); - tcdrain(serial->fd); - usleep(15*1000); - tcflush(serial->fd, TCIFLUSH); - serial->poll_fd.fd = serial->fd; - serial->poll_fd.events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR; - g_source_attach(&serial->source, NULL); - g_source_add_poll(&serial->source,&serial->poll_fd); - aoview_serial_set_callback(serial, NULL); - return serial; -} - -void -aoview_serial_close(struct aoview_serial *serial) -{ - g_source_remove_poll(&serial->source, &serial->poll_fd); - close(serial->fd); - g_source_destroy(&serial->source); -} - -void -aoview_serial_set_callback(struct aoview_serial *serial, - aoview_serial_callback func) -{ - g_source_set_callback(&serial->source, (GSourceFunc) func, serial, NULL); -} diff --git a/ao-view/aoview_state.c b/ao-view/aoview_state.c deleted file mode 100644 index f75066dd..00000000 --- a/ao-view/aoview_state.c +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" -#include - -static inline double sqr(double a) { return a * a; }; - -static void -aoview_great_circle (double start_lat, double start_lon, - double end_lat, double end_lon, - double *dist, double *bearing) -{ - const double rad = M_PI / 180; - const double earth_radius = 6371.2 * 1000; /* in meters */ - double lat1 = rad * start_lat; - double lon1 = rad * -start_lon; - double lat2 = rad * end_lat; - double lon2 = rad * -end_lon; - - double d_lat = lat2 - lat1; - double d_lon = lon2 - lon1; - - /* From http://en.wikipedia.org/wiki/Great-circle_distance */ - double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) + - sqr(cos(lat1) * sin(lat2) - - sin(lat1) * cos(lat2) * cos(d_lon))); - double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon); - double d = atan2(vdn,vdd); - double course; - - if (cos(lat1) < 1e-20) { - if (lat1 > 0) - course = M_PI; - else - course = -M_PI; - } else { - if (d < 1e-10) - course = 0; - else - course = acos((sin(lat2)-sin(lat1)*cos(d)) / - (sin(d)*cos(lat1))); - if (sin(lon2-lon1) > 0) - course = 2 * M_PI-course; - } - *dist = d * earth_radius; - *bearing = course * 180/M_PI; -} - -static void -aoview_state_add_deg(int column, char *label, double deg, char pos, char neg) -{ - double int_part; - double min; - char sign = pos; - - if (deg < 0) { - deg = -deg; - sign = neg; - } - int_part = floor (deg); - min = (deg - int_part) * 60.0; - aoview_table_add_row(column, label, "%d°%lf'%c", - (int) int_part, min, sign); - -} - -static char *ascent_states[] = { - "boost", - "fast", - "coast", - 0, -}; - -static double -aoview_time(void) -{ - struct timespec now; - - clock_gettime(CLOCK_MONOTONIC, &now); - return (double) now.tv_sec + (double) now.tv_nsec / 1.0e9; -} - -/* - * Fill out the derived data fields - */ -static void -aoview_state_derive(struct aodata *data, struct aostate *state) -{ - int i; - double new_height; - double height_change; - double time_change; - int tick_count; - - state->report_time = aoview_time(); - - state->prev_data = state->data; - state->prev_npad = state->npad; - state->data = *data; - tick_count = data->tick; - if (tick_count < state->prev_data.tick) - tick_count += 65536; - time_change = (tick_count - state->prev_data.tick) / 100.0; - - state->ground_altitude = aoview_pres_to_altitude(data->ground_pres); - new_height = aoview_pres_to_altitude(data->flight_pres) - state->ground_altitude; - height_change = new_height - state->height; - state->height = new_height; - if (time_change) - state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0; - state->acceleration = (data->ground_accel - data->flight_accel) / 27.0; - state->speed = data->flight_vel / 2700.0; - state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; - state->drogue_sense = data->drogue / 32767.0 * 15.0; - state->main_sense = data->main / 32767.0 * 15.0; - state->battery = data->batt / 32767.0 * 5.0; - if (!strcmp(data->state, "pad")) { - if (data->gps.gps_locked && data->gps.nsat >= 4) { - state->npad++; - state->pad_lat_total += data->gps.lat; - state->pad_lon_total += data->gps.lon; - state->pad_alt_total += data->gps.alt; - if (state->npad > 1) { - state->pad_lat = (state->pad_lat * 31 + data->gps.lat) / 32.0; - state->pad_lon = (state->pad_lon * 31 + data->gps.lon) / 32.0; - state->pad_alt = (state->pad_alt * 31 + data->gps.alt) / 32.0; - } else { - state->pad_lat = data->gps.lat; - state->pad_lon = data->gps.lon; - state->pad_alt = data->gps.alt; - } - } - } - state->ascent = FALSE; - for (i = 0; ascent_states[i]; i++) - if (!strcmp(data->state, ascent_states[i])) - state->ascent = TRUE; - - /* Only look at accelerometer data on the way up */ - if (state->ascent && state->acceleration > state->max_acceleration) - state->max_acceleration = state->acceleration; - if (state->ascent && state->speed > state->max_speed) - state->max_speed = state->speed; - - if (state->height > state->max_height) - state->max_height = state->height; - state->gps.gps_locked = data->gps.gps_locked; - state->gps.gps_connected = data->gps.gps_connected; - if (data->gps.gps_locked) { - state->gps = data->gps; - state->gps_valid = 1; - if (state->npad) - aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon, - &state->distance, &state->bearing); - } - if (data->gps_tracking.channels) - state->gps_tracking = data->gps_tracking; - if (state->npad) { - state->gps_height = state->gps.alt - state->pad_alt; - } else { - state->gps_height = 0; - } -} - -void -aoview_speak_state(struct aostate *state) -{ - if (strcmp(state->data.state, state->prev_data.state)) { - aoview_voice_speak("%s\n", state->data.state); - if (!strcmp(state->data.state, "drogue")) - aoview_voice_speak("apogee %d meters\n", - (int) state->max_height); - if (!strcmp(state->prev_data.state, "boost")) - aoview_voice_speak("max speed %d meters per second\n", - (int) state->max_speed); - } - if (state->prev_npad < MIN_PAD_SAMPLES && state->npad >= MIN_PAD_SAMPLES) - aoview_voice_speak("g p s ready\n"); -} - -void -aoview_speak_height(struct aostate *state) -{ - aoview_voice_speak("%d meters\n", state->height); -} - -struct aostate aostate; - -static guint aostate_timeout; - -#define COMPASS_LIMIT(n) ((n * 22.5) + 22.5/2) - -static char *compass_points[] = { - "north", - "north north east", - "north east", - "east north east", - "east", - "east south east", - "south east", - "south south east", - "south", - "south south west", - "south west", - "west south west", - "west", - "west north west", - "north west", - "north north west", -}; - -static char * -aoview_compass_point(double bearing) -{ - int i; - while (bearing < 0) - bearing += 360.0; - while (bearing >= 360.0) - bearing -= 360.0; - - i = floor ((bearing - 22.5/2) / 22.5 + 0.5); - if (i < 0) i = 0; - if (i >= sizeof (compass_points) / sizeof (compass_points[0])) - i = 0; - return compass_points[i]; -} - -static gboolean -aoview_state_timeout(gpointer data) -{ - double now = aoview_time(); - - if (strlen(aostate.data.state) > 0 && strcmp(aostate.data.state, "pad") != 0) - aoview_speak_height(&aostate); - if (now - aostate.report_time >= 20 || !strcmp(aostate.data.state, "landed")) { - if (!aostate.ascent) { - if (fabs(aostate.baro_speed) < 20 && aostate.height < 100) - aoview_voice_speak("rocket landed safely\n"); - else - aoview_voice_speak("rocket may have crashed\n"); - if (aostate.gps_valid) { - aoview_voice_speak("rocket reported %s of pad distance %d meters\n", - aoview_compass_point(aostate.bearing), - (int) aostate.distance); - } - } - aostate_timeout = 0; - return FALSE; - } - return TRUE; -} - -void -aoview_state_reset(void) -{ - memset(&aostate, '\0', sizeof (aostate)); -} - -void -aoview_state_notify(struct aodata *data) -{ - struct aostate *state = &aostate; - aoview_state_derive(data, state); - aoview_table_start(); - - if (state->npad >= MIN_PAD_SAMPLES) - aoview_table_add_row(0, "Ground state", "ready"); - else - aoview_table_add_row(0, "Ground state", "waiting for gps (%d)", - MIN_PAD_SAMPLES - state->npad); - aoview_table_add_row(0, "Rocket state", "%s", state->data.state); - aoview_table_add_row(0, "Callsign", "%s", state->data.callsign); - aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial); - - aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi); - aoview_table_add_row(0, "Height", "%6dm", state->height); - aoview_table_add_row(0, "Max height", "%6dm", state->max_height); - aoview_table_add_row(0, "Acceleration", "%7.1fm/s²", state->acceleration); - aoview_table_add_row(0, "Max acceleration", "%7.1fm/s²", state->max_acceleration); - aoview_table_add_row(0, "Speed", "%7.1fm/s", state->ascent ? state->speed : state->baro_speed); - aoview_table_add_row(0, "Max Speed", "%7.1fm/s", state->max_speed); - aoview_table_add_row(0, "Temperature", "%6.2f°C", state->temperature); - aoview_table_add_row(0, "Battery", "%5.2fV", state->battery); - aoview_table_add_row(0, "Drogue", "%5.2fV", state->drogue_sense); - aoview_table_add_row(0, "Main", "%5.2fV", state->main_sense); - aoview_table_add_row(0, "Pad altitude", "%dm", state->ground_altitude); - aoview_table_add_row(1, "Satellites", "%d", state->gps.nsat); - if (state->gps.gps_locked) { - aoview_table_add_row(1, "GPS", "locked"); - } else if (state->gps.gps_connected) { - aoview_table_add_row(1, "GPS", "unlocked"); - } else { - aoview_table_add_row(1, "GPS", "not available"); - } - if (state->gps_valid) { - aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S'); - aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); - aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); - aoview_table_add_row(1, "GPS height", "%d", state->gps_height); - aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", - state->gps.gps_time.hour, - state->gps.gps_time.minute, - state->gps.gps_time.second); - } - if (state->gps.gps_extended) { - aoview_table_add_row(1, "GPS ground speed", "%7.1fm/s %d°", - state->gps.ground_speed, - state->gps.course); - aoview_table_add_row(1, "GPS climb rate", "%7.1fm/s", - state->gps.climb_rate); - aoview_table_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)", - state->gps.hdop, state->gps.h_error, state->gps.v_error); - } - if (state->npad) { - aoview_table_add_row(1, "Distance from pad", "%5.0fm", state->distance); - aoview_table_add_row(1, "Direction from pad", "%4.0f°", state->bearing); - aoview_state_add_deg(1, "Pad latitude", state->pad_lat, 'N', 'S'); - aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W'); - aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt); - } - if (state->gps.gps_connected) { - int nsat_vis = 0; - int nsat_locked = 0; - int c; - - for (c = 0; c < state->gps_tracking.channels; c++) { - if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf) - nsat_locked++; - } - aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels); - aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked); - for (c = 0; c < state->gps_tracking.channels; c++) { - aoview_table_add_row(2, "Satellite id,state,C/N0", - "%3d,%02x,%2d%s", - state->gps_tracking.sats[c].svid, - state->gps_tracking.sats[c].state, - state->gps_tracking.sats[c].c_n0, - (state->gps_tracking.sats[c].state & 0xff) == 0xbf ? - " LOCKED" : ""); - } - } - aoview_table_finish(); - aoview_label_show(state); - aoview_speak_state(state); - if (!aostate_timeout && strcmp(state->data.state, "pad") != 0) - aostate_timeout = g_timeout_add_seconds(10, aoview_state_timeout, NULL); -} - -void -aoview_state_new(void) -{ -} - -void -aoview_state_init(GladeXML *xml) -{ - aoview_state_new(); -} diff --git a/ao-view/aoview_table.c b/ao-view/aoview_table.c deleted file mode 100644 index e75ae670..00000000 --- a/ao-view/aoview_table.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -#define NCOL 3 - -static GtkTreeView *dataview[NCOL]; -static GtkListStore *datalist[NCOL]; - -void -aoview_table_start(void) -{ - int col; - for (col = 0; col < NCOL; col++) - datalist[col] = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING); -} - -void -aoview_table_add_row(int col, char *label, char *format, ...) -{ - char buf[1024]; - va_list ap; - GtkTreeIter iter; - - va_start(ap, format); - vsnprintf(buf, sizeof (buf), format, ap); - va_end(ap); - gtk_list_store_append(datalist[col], &iter); - gtk_list_store_set(datalist[col], &iter, - 0, label, - 1, buf, - -1); -} - -void -aoview_table_finish(void) -{ - int col; - for (col = 0; col < NCOL; col++) { - gtk_tree_view_set_model(dataview[col], GTK_TREE_MODEL(datalist[col])); - g_object_unref(G_OBJECT(datalist[col])); - gtk_tree_view_columns_autosize(dataview[col]); - } -} - -void -aoview_table_clear(void) -{ - int col; - for (col = 0; col < NCOL; col++) - gtk_tree_view_set_model(dataview[col], NULL); -} - -void -aoview_table_init(GladeXML *xml) -{ - int col; - - for (col = 0; col < NCOL; col++) { - char name[32]; - sprintf(name, "dataview_%d", col); - dataview[col] = GTK_TREE_VIEW(glade_xml_get_widget(xml, name)); - assert(dataview[col]); - - aoview_add_plain_text_column(dataview[col], "Field", 0, 20); - aoview_add_plain_text_column(dataview[col], "Value", 1, 32); - } -} diff --git a/ao-view/aoview_util.c b/ao-view/aoview_util.c deleted file mode 100644 index 6ea62ac9..00000000 --- a/ao-view/aoview_util.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -char * -aoview_fullname (char *dir, char *file) -{ - char *new; - int dlen = strlen (dir); - int flen = strlen (file); - int slen = 0; - - if (dir[dlen-1] != '/') - slen = 1; - new = malloc (dlen + slen + flen + 1); - if (!new) - return 0; - strcpy(new, dir); - if (slen) - strcat (new, "/"); - strcat(new, file); - return new; -} - -char * -aoview_basename(char *file) -{ - char *b; - - b = strrchr(file, '/'); - if (!b) - return file; - return b + 1; -} - -int -aoview_mkdir(char *dir) -{ - char *slash; - char *d; - char *part; - - d = dir; - for (;;) { - slash = strchr (d, '/'); - if (!slash) - slash = d + strlen(d); - if (!*slash) - break; - part = strndup(dir, slash - dir); - if (!access(part, F_OK)) - if (mkdir(part, 0777) < 0) - return -errno; - free(part); - d = slash + 1; - } - return 0; -} - -GtkTreeViewColumn * -aoview_add_plain_text_column (GtkTreeView *view, const gchar *title, gint model_column, gint width) -{ - GtkCellRenderer *renderer; - GtkTreeViewColumn *column; - - renderer = gtk_cell_renderer_text_new (); - g_object_set(renderer, "ellipsize", PANGO_ELLIPSIZE_NONE, NULL); - g_object_set(renderer, "width-chars", width, NULL); - column = gtk_tree_view_column_new_with_attributes (title, renderer, - "text", model_column, - NULL); - gtk_tree_view_column_set_resizable (column, FALSE); - gtk_tree_view_append_column (view, column); - - return column; -} diff --git a/ao-view/aoview_voice.c b/ao-view/aoview_voice.c deleted file mode 100644 index 24422df6..00000000 --- a/ao-view/aoview_voice.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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 "aoview.h" - -#if HAVE_FLITE -#include - -FILE *aoview_flite; - -void aoview_voice_open(void) -{ - int err; - - if (!aoview_flite) - aoview_flite = aoview_flite_start(); -} - -void aoview_voice_close(void) -{ - if (aoview_flite) { - aoview_flite_stop(); - aoview_flite = NULL; - } -} - -void aoview_voice_speak(char *format, ...) -{ - va_list ap; - - if (aoview_flite) { - va_start(ap, format); - vfprintf(aoview_flite, format, ap); - fflush(aoview_flite); - va_end(ap); - } -} - -#else -void aoview_voice_open(void) -{ -} - -void aoview_voice_close(void) -{ -} - -void aoview_voice_speak(char *format, ...) -{ -} -#endif - - -static GtkCheckMenuItem *voice_enable; - -#define ALTOS_VOICE_PATH "/apps/aoview/voice" - -static void -aoview_voice_enable(GtkWidget *widget, gpointer data) -{ - gboolean enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); - GError *error; - GConfClient *gconf_client; - - if (enabled) { - aoview_voice_open(); - aoview_voice_speak("enable voice\n"); - } else { - aoview_voice_speak("disable voice\n"); - aoview_voice_close(); - } - gconf_client = gconf_client_get_default(); - gconf_client_set_bool(gconf_client, - ALTOS_VOICE_PATH, - enabled, - &error); -} - -void -aoview_voice_init(GladeXML *xml) -{ - gboolean enabled; - GConfClient *gconf_client; - - voice_enable = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "voice_enable")); - assert(voice_enable); - - gconf_client = gconf_client_get_default(); - enabled = TRUE; - if (gconf_client) - { - GError *error; - - error = NULL; - enabled = gconf_client_get_bool(gconf_client, - ALTOS_VOICE_PATH, - &error); - if (error) - enabled = TRUE; - } - gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(voice_enable), enabled); - if (enabled) - aoview_voice_open(); - - g_signal_connect(G_OBJECT(voice_enable), "toggled", - G_CALLBACK(aoview_voice_enable), - voice_enable); -} diff --git a/ao-view/design b/ao-view/design deleted file mode 100644 index 6ec2ea70..00000000 --- a/ao-view/design +++ /dev/null @@ -1,27 +0,0 @@ -Requirements: - real-time display of telemetry - off-line display of logged data - Logging of telemetry - Capture of logged data to disk - -Input data: - accelerometer - barometer - thermometer - gps - drogue and main continuity - battery voltage - time - reported flight state - reported events - -Computed data: - velocity (from accelerometer) - altitude - range - direction - -Displays: - numeric display of current rocket status - (graphics come later) - text message log diff --git a/configure.ac b/configure.ac index b52bb6e9..dfbae71d 100644 --- a/configure.ac +++ b/configure.ac @@ -73,7 +73,6 @@ PKG_CHECK_MODULES([ALSA], [alsa]) AC_OUTPUT([ Makefile -ao-view/Makefile ao-tools/Makefile ao-tools/lib/Makefile ao-tools/ao-rawload/Makefile @@ -81,5 +80,6 @@ ao-tools/ao-dbg/Makefile ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile ao-tools/ao-load/Makefile +ao-tools/ao-view/Makefile ao-utils/Makefile ]) -- cgit v1.2.3 From 0935d6a7e907e20381a42882ae728051f9bece02 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 14:21:19 -0700 Subject: Parse the USB serial number as an integer. AltOS devices use simple integer serial numbers, so parse the USB value as such to make matching values more forgiving. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_dev_dialog.c | 2 +- ao-tools/lib/cc-usbdev.c | 97 ++++++++++++++++++++++++++++++++++-- ao-tools/lib/cc.h | 5 +- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/ao-tools/ao-view/aoview_dev_dialog.c b/ao-tools/ao-view/aoview_dev_dialog.c index 87396c1f..2ea43203 100644 --- a/ao-tools/ao-view/aoview_dev_dialog.c +++ b/ao-tools/ao-view/aoview_dev_dialog.c @@ -29,7 +29,7 @@ aoview_dev_dialog_map(GtkWidget *widget, gpointer data) list_store = gtk_list_store_new(3, G_TYPE_STRING, - G_TYPE_STRING, + G_TYPE_INT, G_TYPE_STRING); devs = cc_usbdevs_scan(); diff --git a/ao-tools/lib/cc-usbdev.c b/ao-tools/lib/cc-usbdev.c index d8bb8b11..ed39c062 100644 --- a/ao-tools/lib/cc-usbdev.c +++ b/ao-tools/lib/cc-usbdev.c @@ -16,8 +16,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#define _GNU_SOURCE #include "cc.h" - #include #include #include @@ -64,6 +64,23 @@ load_hex(char *dir, char *file) return i; } +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + static int dir_filter_tty_colon(const struct dirent *d) { @@ -141,7 +158,7 @@ usb_scan_device(char *sys) usbdev->sys = strdup(sys); usbdev->manufacturer = load_string(sys, "manufacturer"); usbdev->product = load_string(sys, "product"); - usbdev->serial = load_string(sys, "serial"); + usbdev->serial = load_dec(sys, "serial"); usbdev->idProduct = load_hex(sys, "idProduct"); usbdev->idVendor = load_hex(sys, "idVendor"); usbdev->tty = usb_tty(sys); @@ -154,8 +171,9 @@ usbdev_free(struct cc_usbdev *usbdev) free(usbdev->sys); free(usbdev->manufacturer); free(usbdev->product); - free(usbdev->serial); - free(usbdev->tty); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); free(usbdev); } @@ -226,3 +244,74 @@ cc_usbdevs_free(struct cc_usbdevs *usbdevs) usbdev_free(usbdevs->dev[i]); free(usbdevs); } + +static char * +match_dev(char *product, int serial) +{ + struct cc_usbdevs *devs; + struct cc_usbdev *dev; + int i; + char *tty = NULL; + + devs = cc_usbdevs_scan(); + if (!devs) + return NULL; + for (i = 0; i < devs->ndev; i++) { + dev = devs->dev[i]; + if (product && strcmp (product, dev->product) != 0) + continue; + if (serial && serial != dev->serial) + continue; + break; + } + if (i < devs->ndev) { + tty = devs->dev[i]->tty; + devs->dev[i]->tty = NULL; + } + cc_usbdevs_free(devs); + return tty; +} + +char * +cc_usbdevs_find_by_arg(char *arg, char *default_product) +{ + char *product; + int serial; + char *end; + char *colon; + char *tty; + + if (arg) + { + /* check for */ + serial = strtol(arg, &end, 0); + if (end != arg) { + if (*end != '\0') + return NULL; + product = NULL; + } else { + /* check for : */ + colon = strchr(arg, ':'); + if (colon) { + product = strndup(arg, colon - arg); + serial = strtol(colon + 1, &end, 0); + if (*end != '\0') + return NULL; + } else { + product = arg; + serial = 0; + } + } + } else { + product = NULL; + serial = 0; + } + tty = NULL; + if (!product && default_product) + tty = match_dev(default_product, serial); + if (!tty) + tty = match_dev(product, serial); + if (product && product != arg) + free(product); + return tty; +} diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index dad11bf3..0933f272 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -32,7 +32,7 @@ struct cc_usbdev { char *tty; char *manufacturer; char *product; - char *serial; + int serial; /* AltOS always uses simple integer serial numbers */ int idProduct; int idVendor; }; @@ -48,4 +48,7 @@ cc_usbdevs_free(struct cc_usbdevs *usbdevs); struct cc_usbdevs * cc_usbdevs_scan(void); +char * +cc_usbdevs_find_by_arg(char *arg, char *default_product); + #endif /* _CC_H_ */ -- cgit v1.2.3 From df88ae4c5f229efcc0ea5cb0a81fc2bb8f96fea2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 14:23:02 -0700 Subject: Add 'ao-list' utility to show attached AltOS devices Signed-off-by: Keith Packard --- ao-tools/ao-list/Makefile.am | 12 ++++++++++++ ao-tools/ao-list/ao-list.1 | 32 ++++++++++++++++++++++++++++++++ ao-tools/ao-list/ao-list.c | 41 +++++++++++++++++++++++++++++++++++++++++ configure.ac | 1 + 4 files changed, 86 insertions(+) create mode 100644 ao-tools/ao-list/Makefile.am create mode 100644 ao-tools/ao-list/ao-list.1 create mode 100644 ao-tools/ao-list/ao-list.c diff --git a/ao-tools/ao-list/Makefile.am b/ao-tools/ao-list/Makefile.am new file mode 100644 index 00000000..de3c4deb --- /dev/null +++ b/ao-tools/ao-list/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-list + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_LIST_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_list_DEPENDENCIES = $(AO_LIST_LIBS) + +ao_list_LDADD=$(AO_LIST_LIBS) $(LIBUSB_LIBS) + +ao_list_SOURCES = ao-list.c + +man_MANS = ao-list.1 diff --git a/ao-tools/ao-list/ao-list.1 b/ao-tools/ao-list/ao-list.1 new file mode 100644 index 00000000..03968c25 --- /dev/null +++ b/ao-tools/ao-list/ao-list.1 @@ -0,0 +1,32 @@ +/.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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-LIST 1 "ao-list" "" +.SH NAME +ao-list \- List connected AltOS devices +.SH SYNOPSIS +.B "ao-list" +.SH DESCRIPTION +.I ao-list +scans the attached USB devices, locates those running AltOS and +displays their product name and serial number along with the tty +device associated with the serial port over USB provided by AltOS. +.SH USAGE +.I ao-list +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-list/ao-list.c b/ao-tools/ao-list/ao-list.c new file mode 100644 index 00000000..c4b43d8f --- /dev/null +++ b/ao-tools/ao-list/ao-list.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 +#include +#include +#include +#include "cc.h" + +int +main (int argc, char **argv) +{ + struct cc_usbdevs *devs; + struct cc_usbdev *dev; + int i; + + devs = cc_usbdevs_scan(); + if (devs) { + for (i = 0; i < devs->ndev; i++) { + dev = devs->dev[i]; + printf ("%-20.20s %6d %s\n", + dev->product, dev->serial, dev->tty); + } + cc_usbdevs_free(devs); + } + return 0; +} diff --git a/configure.ac b/configure.ac index dfbae71d..56402857 100644 --- a/configure.ac +++ b/configure.ac @@ -79,6 +79,7 @@ ao-tools/ao-rawload/Makefile ao-tools/ao-dbg/Makefile ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile +ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile ao-tools/ao-view/Makefile ao-utils/Makefile -- cgit v1.2.3 From 332b056459b1352e233a8bf5f08498df12d32160 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 15:01:32 -0700 Subject: 'fix' ao-eeprom to read two blocks at once. Work around kernel bugs. The kernel appears to leave serial data undelivered at times. Reading two blocks at once appears to make it relinquish the queued data. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-eeprom/ao-eeprom.c | 20 ++++++++++++++------ ao-tools/lib/cc-usb.c | 12 +++++++++--- ao-tools/lib/cc-usb.h | 2 +- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 02b4785e..28e77b08 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-load ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-view diff --git a/ao-tools/ao-eeprom/ao-eeprom.c b/ao-tools/ao-eeprom/ao-eeprom.c index 726cc22c..b865e298 100644 --- a/ao-tools/ao-eeprom/ao-eeprom.c +++ b/ao-tools/ao-eeprom/ao-eeprom.c @@ -21,17 +21,19 @@ #include #include #include "cc-usb.h" +#include "cc.h" #define NUM_BLOCK 512 static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ]\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device \n", program); exit(1); } @@ -40,23 +42,29 @@ main (int argc, char **argv) { struct cc_usb *cc; int block; - uint8_t bytes[32 * (2 + 8)]; + uint8_t bytes[2 * 32 * (2 + 8)]; uint8_t *b; int i, j; uint32_t addr; char *tty = NULL; + char *device = NULL; int c; - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; break; + case 'D': + device = optarg; + break; default: usage(argv[0]); break; } } + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); if (!tty) tty = getenv("ALTOS_TTY"); if (!tty) @@ -64,11 +72,11 @@ main (int argc, char **argv) cc = cc_usb_open(tty); if (!cc) exit(1); - for (block = 0; block < NUM_BLOCK; block++) { + for (block = 0; block < NUM_BLOCK; block += 2) { cc_queue_read(cc, bytes, sizeof (bytes)); - cc_usb_printf(cc, "e %x\n", block); + cc_usb_printf(cc, "e %x\ne %x\n", block, block + 1); cc_usb_sync(cc); - for (i = 0; i < 32; i++) { + for (i = 0; i < 32 * 2; i++) { b = bytes + (i * 10); addr = block * 256 + i * 8; printf ("%06x", addr); diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 81309983..17f05911 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -157,7 +157,8 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len) /* * Flush pending writes, fill pending reads */ -void + +int cc_usb_sync(struct cc_usb *cc) { int ret; @@ -167,7 +168,7 @@ cc_usb_sync(struct cc_usb *cc) fds.fd = cc->fd; for (;;) { if (cc->read_count || cc->out_count) - timeout = -1; + timeout = 5000; else timeout = 0; fds.events = 0; @@ -176,8 +177,13 @@ cc_usb_sync(struct cc_usb *cc) if (cc->out_count) fds.events |= POLLOUT; ret = poll(&fds, 1, timeout); - if (ret == 0) + if (ret == 0) { + if (timeout) { + fprintf(stderr, "USB link timeout\n"); + exit(1); + } break; + } if (ret < 0) { perror("poll"); break; diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h index d7acfbd2..9baabd95 100644 --- a/ao-tools/lib/cc-usb.h +++ b/ao-tools/lib/cc-usb.h @@ -47,7 +47,7 @@ cc_usb_debug_mode(struct cc_usb *cc); int cc_usb_reset(struct cc_usb *cc); -void +int cc_usb_sync(struct cc_usb *cc); void -- cgit v1.2.3 From 4f8eff7401ee2d8092ab36fa33411f9b23dda880 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 4 Sep 2009 16:03:55 -0600 Subject: update changelogs for Debian build --- ChangeLog | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++ 2 files changed, 99 insertions(+) diff --git a/ChangeLog b/ChangeLog index c099f684..771118c2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,96 @@ +commit 332b056459b1352e233a8bf5f08498df12d32160 +Author: Keith Packard +Date: Fri Sep 4 15:01:32 2009 -0700 + + 'fix' ao-eeprom to read two blocks at once. Work around kernel bugs. + + The kernel appears to leave serial data undelivered at times. Reading + two blocks at once appears to make it relinquish the queued data. + + Signed-off-by: Keith Packard + +commit df88ae4c5f229efcc0ea5cb0a81fc2bb8f96fea2 +Author: Keith Packard +Date: Fri Sep 4 14:23:02 2009 -0700 + + Add 'ao-list' utility to show attached AltOS devices + + Signed-off-by: Keith Packard + +commit 0935d6a7e907e20381a42882ae728051f9bece02 +Author: Keith Packard +Date: Fri Sep 4 14:21:19 2009 -0700 + + Parse the USB serial number as an integer. + + AltOS devices use simple integer serial numbers, so parse the USB + value as such to make matching values more forgiving. + + Signed-off-by: Keith Packard + +commit 0c771d999914f9d17c723900f2987acc45fd0fbb +Author: Keith Packard +Date: Fri Sep 4 13:00:02 2009 -0700 + + Move usb scanning code to ao-tools library + + This will allow the scanning code to be used by the command line tools + as well as the ao-view GUI. + + Now that ao-view depends on the ao-tools library, it has been moved to + the ao-tools directory as well. + + Signed-off-by: Keith Packard + +commit 15341b6e6dcf52df083d6aa37ef881ea6ad48ee5 +Author: Keith Packard +Date: Fri Sep 4 12:25:37 2009 -0700 + + Set all of the values to reset the radio for telemetry + + Was sizeof(rdf_setup) instead of sizeof(telemetry_setup) when + resetting the radio back to telemetry data mode from rdf mode. With + the length value removed from the rdf config, these two arrays are no + longer the same length, and so the last config value was not set + leaving the radio sending garbage. + + Signed-off-by: Keith Packard + +commit fee46389b70a624ab5b1128a8b4c3083c7747bcb +Author: Keith Packard +Date: Fri Sep 4 11:46:55 2009 -0700 + + Make RDF beacon only run on pad and after landing. + + It's pretty much impossible to RDF the rocket during flight, and it + interferes with the telemetry data stream. Leave it enabled on the pad + so that radios can be tested, and then re-enable it once the rocket + has landed. + + This patch also turns the rdf 'on' time into a parameter so it can be + changed, and then sets that parameter to 500ms, once every 5 seconds. + + Signed-off-by: Keith Packard + +commit 54545640b0db7747137655f84bc67fd290ecb904 +Author: Keith Packard +Date: Fri Sep 4 11:45:52 2009 -0700 + + Add back the RDF tone generator + + Tracking the rocket on the ground may be easier using tones than using + the digital data stream, so we'll try that and see what we think. + + This reverts commit 3a3bfd471a868d546d83cdc431b53c8f5208edb9. + + Signed-off-by: Keith Packard + +commit 9fafee109e96435c96639b21211cac0500673a63 +Author: Bdale Garbee +Date: Wed Sep 2 23:18:15 2009 -0600 + + update changelogs for Debian build + commit cb4a73f3b65ba72f645fd37ab8712829c9537bf8 Merge: 9ddd869 e2e449d Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index e7c236a2..ae7b9642 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+27+g332b056) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Fri, 04 Sep 2009 16:03:55 -0600 + altos (0.5+19+gcb4a73f) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 73adae3661160d410dcc802873b530d255c210e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 15:30:22 -0700 Subject: Add --device/-D support to the command line tools and manuals Use the new cc_usbdevs_find_by_arg function to locate suitable target devices connected via USB. Signed-off-by: Keith Packard --- ao-tools/ao-dbg/ao-dbg-main.c | 5 +++++ ao-tools/ao-dbg/ao-dbg-parse.c | 5 +++++ ao-tools/ao-dbg/ao-dbg.1 | 20 +++++++++++++++++++- ao-tools/ao-dbg/ao-dbg.h | 2 ++ ao-tools/ao-eeprom/ao-eeprom.1 | 26 +++++++++++++++++++++++++- ao-tools/ao-load/ao-load.1 | 26 +++++++++++++++++++++++++- ao-tools/ao-load/ao-load.c | 12 ++++++++++-- ao-tools/ao-rawload/ao-rawload.1 | 26 +++++++++++++++++++++++++- ao-tools/ao-rawload/ao-rawload.c | 11 +++++++++-- 9 files changed, 125 insertions(+), 8 deletions(-) diff --git a/ao-tools/ao-dbg/ao-dbg-main.c b/ao-tools/ao-dbg/ao-dbg-main.c index f1e2c111..21b83a3d 100644 --- a/ao-tools/ao-dbg/ao-dbg-main.c +++ b/ao-tools/ao-dbg/ao-dbg-main.c @@ -34,6 +34,7 @@ struct ccdbg *s51_dbg; int s51_interrupted = 0; int s51_monitor = 0; char *s51_tty = NULL; +char *s51_device = NULL; static FILE *s51_input; static FILE *s51_output; @@ -52,6 +53,7 @@ void s51_sigint() static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, { 0, 0, 0, 0 }, }; @@ -114,6 +116,9 @@ main(int argc, char **argv) case 'T': s51_tty = optarg; break; + case 'D': + s51_device = optarg; + break; } } if (s51_port) { diff --git a/ao-tools/ao-dbg/ao-dbg-parse.c b/ao-tools/ao-dbg/ao-dbg-parse.c index 825d0e9c..dcb9099d 100644 --- a/ao-tools/ao-dbg/ao-dbg-parse.c +++ b/ao-tools/ao-dbg/ao-dbg-parse.c @@ -195,6 +195,11 @@ command_read (void) enum command_result result; struct command_function *func; + if (!s51_tty) { + if (!s51_device) + s51_device = getenv("AO_DBG_DEVICE"); + s51_tty = cc_usbdevs_find_by_arg(s51_device, "TIDongle"); + } s51_dbg = ccdbg_open (s51_tty); if (!s51_dbg) exit(1); diff --git a/ao-tools/ao-dbg/ao-dbg.1 b/ao-tools/ao-dbg/ao-dbg.1 index a850c454..00d3ac86 100644 --- a/ao-tools/ao-dbg/ao-dbg.1 +++ b/ao-tools/ao-dbg/ao-dbg.1 @@ -35,6 +35,9 @@ ao-dbg \- hex debugger for cc1111 processors [\-h] [\-m] [\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] .SH DESCRIPTION .I ao-dbg connects to a cc1111 processor through either a suitable cc1111 board @@ -80,11 +83,26 @@ This should print a usage message, but does nothing useful currently. .IP "\-m" This option is not present in the original 8051 emulator, and causes ao-dbg to dump all commands and replies that are received from and sent to sdcdb. -.IP "\-T" +.TP +\-T tty-device | --tty tty-device This selects which tty device the debugger uses to communicate with the target device. The special name 'BITBANG' directs ao-dbg to use the cp2103 connection, otherwise this should be a usb serial port connected to a suitable cc1111 debug node. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleMetrum:2 +.br +TeleMetrum +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. .SH COMMANDS Once started, ao-dbg connects to the cc1111 and then reads and executes commands, either from stdin, or the nework connection to diff --git a/ao-tools/ao-dbg/ao-dbg.h b/ao-tools/ao-dbg/ao-dbg.h index c1789d10..edc650a5 100644 --- a/ao-tools/ao-dbg/ao-dbg.h +++ b/ao-tools/ao-dbg/ao-dbg.h @@ -17,12 +17,14 @@ */ #include +#include extern char *s51_prompt; extern struct ccdbg *s51_dbg; extern int s51_interrupted; extern int s51_monitor; extern char *s51_tty; +extern char *s51_device; enum command_result { command_success, command_debug, command_syntax, command_interrupt, command_error, diff --git a/ao-tools/ao-eeprom/ao-eeprom.1 b/ao-tools/ao-eeprom/ao-eeprom.1 index 8caff9d1..ed498147 100644 --- a/ao-tools/ao-eeprom/ao-eeprom.1 +++ b/ao-tools/ao-eeprom/ao-eeprom.1 @@ -21,7 +21,31 @@ ao-eeprom \- Fetch eeprom contents from TeleMetrum device .SH SYNOPSIS .B "ao-eeprom" -[\-tty \fItty-device\fP] +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device the debugger uses to communicate with +the target device. The special name 'BITBANG' directs ao-dbg to use +the cp2103 connection, otherwise this should be a usb serial port +connected to a suitable cc1111 debug node. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleMetrum:2 +.br +TeleMetrum +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. .SH DESCRIPTION .I ao-eeprom downloads the eeprom contents from a connected TeleMetrum device. diff --git a/ao-tools/ao-load/ao-load.1 b/ao-tools/ao-load/ao-load.1 index 10484f3b..eb2bc0d8 100644 --- a/ao-tools/ao-load/ao-load.1 +++ b/ao-tools/ao-load/ao-load.1 @@ -21,13 +21,37 @@ ao-load \- flash a program to a AltOS device .SH SYNOPSIS .B "ao-load" -[\-tty \fItty-device\fP] +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] \fIfile.ihx\fP \fIdevice serial number\fP .SH DESCRIPTION .I ao-load loads the specified .ihx file into the target device flash memory, customizing the AltOS image with the specified serial number. +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device the debugger uses to communicate with +the target device. The special name 'BITBANG' directs ao-dbg to use +the cp2103 connection, otherwise this should be a usb serial port +connected to a suitable cc1111 debug node. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleMetrum:2 +.br +TeleMetrum +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. .SH USAGE .I ao-load reads the specified .ihx file into memory, locates the matching .map diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index c27fcbe9..f5466612 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -22,6 +22,7 @@ #include #include #include "ccdbg.h" +#include "cc.h" #define AO_USB_DESC_STRING 3 @@ -91,12 +92,13 @@ rewrite(struct hex_image *image, unsigned addr, char *data, int len) static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] file.ihx serial-number\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx serial-number\n", program); exit(1); } @@ -122,13 +124,17 @@ main (int argc, char **argv) unsigned usb_descriptors; int string_num; char *tty = NULL; + char *device = NULL; int c; - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; break; + case 'D': + device = optarg; + break; default: usage(argv[0]); break; @@ -219,6 +225,8 @@ main (int argc, char **argv) if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) usage(argv[0]); + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TIDongle"); dbg = ccdbg_open(tty); if (!dbg) exit (1); diff --git a/ao-tools/ao-rawload/ao-rawload.1 b/ao-tools/ao-rawload/ao-rawload.1 index e79645f1..6b6a6e2c 100644 --- a/ao-tools/ao-rawload/ao-rawload.1 +++ b/ao-tools/ao-rawload/ao-rawload.1 @@ -21,12 +21,36 @@ ao-rawload \- flash a program to a AltOS device .SH SYNOPSIS .B "ao-rawload" -[\-tty \fItty-device\fP] +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] \fIfile.ihx\fP .SH DESCRIPTION .I ao-rawload loads the specified .ihx file, without modification, into the target device flash memory. +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device the debugger uses to communicate with +the target device. The special name 'BITBANG' directs ao-dbg to use +the cp2103 connection, otherwise this should be a usb serial port +connected to a suitable cc1111 debug node. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleMetrum:2 +.br +TeleMetrum +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. .SH USAGE .I ao-rawload reads the specified .ihx file into memory. It then connects to the diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index 1f1537b9..255f63ec 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -22,12 +22,13 @@ static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] file.ihx\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx\n", program); exit(1); } @@ -42,13 +43,17 @@ main (int argc, char **argv) char *filename; FILE *file; char *tty = NULL; + char *device = NULL; int c; - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; break; + case 'D': + device = optarg; + break; default: usage(argv[0]); break; @@ -75,6 +80,8 @@ main (int argc, char **argv) } ccdbg_hex_file_free(hex); + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TIDongle"); dbg = ccdbg_open(tty); if (!dbg) exit (1); -- cgit v1.2.3 From 26f56b51bd11aa91f1d77b81827b49c28cb6ec5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Sep 2009 00:29:26 -0700 Subject: Add ao-dumplog to capture flight log from command line This duplicates the functionality of the flight log stuf in ao-view, except from the command line where it belongs. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-dumplog/Makefile.am | 12 +++ ao-tools/ao-dumplog/ao-dumplog.1 | 68 ++++++++++++++++ ao-tools/ao-dumplog/ao-dumplog.c | 103 ++++++++++++++++++++++++ ao-tools/lib/Makefile.am | 3 +- ao-tools/lib/cc-usb.c | 164 +++++++++++++++++++++++++-------------- ao-tools/lib/cc-usb.h | 8 +- ao-tools/lib/cc.h | 9 +++ configure.ac | 1 + 9 files changed, 308 insertions(+), 62 deletions(-) create mode 100644 ao-tools/ao-dumplog/Makefile.am create mode 100644 ao-tools/ao-dumplog/ao-dumplog.1 create mode 100644 ao-tools/ao-dumplog/ao-dumplog.c diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 28e77b08..b61f045f 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-view diff --git a/ao-tools/ao-dumplog/Makefile.am b/ao-tools/ao-dumplog/Makefile.am new file mode 100644 index 00000000..a80cac33 --- /dev/null +++ b/ao-tools/ao-dumplog/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-dumplog + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) +AO_DUMPLOG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_dumplog_DEPENDENCIES = $(AO_DUMPLOG_LIBS) + +ao_dumplog_LDADD=$(AO_DUMPLOG_LIBS) $(LIBUSB_LIBS) $(GNOME_LIBS) + +ao_dumplog_SOURCES = ao-dumplog.c + +man_MANS = ao-dumplog.1 diff --git a/ao-tools/ao-dumplog/ao-dumplog.1 b/ao-tools/ao-dumplog/ao-dumplog.1 new file mode 100644 index 00000000..8c2df7c6 --- /dev/null +++ b/ao-tools/ao-dumplog/ao-dumplog.1 @@ -0,0 +1,68 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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-DUMPLOG 1 "ao-dumplog" "" +.SH NAME +ao-dumplog \- Store flight log from TeleMetrum device +.SH SYNOPSIS +.B "ao-dumplog" +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device ao-dumplog uses to communicate with +the target device. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleMetrum:2 +.br +TeleMetrum +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. +.SH DESCRIPTION +.I ao-dumplog +downloads the flight log from a connected TeleMetrum device and stores +it to the configured flight log directory using a name of the form +.IP +\fIyyyy\fP-\fImm\fP-\fIdd\fP-serialP-\fIsss\fP-flight-\fIfff\fP.eeprom +.PP +\fIyyyy\fP is the current year +.br +\fImm\fP is the current month +.br +\fIdd\fP is the current day +.br +\fIsss\fP is the device serial number +.br +\fIfff\fP is a flight sequence number (to make filenames unique) +.SH USAGE +.I ao-dumplog +connects to the specified target device and dumps the stored flight +log. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c new file mode 100644 index 00000000..4bccfd61 --- /dev/null +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -0,0 +1,103 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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. + */ + +#include +#include +#include +#include +#include "cc-usb.h" +#include "cc.h" + +#define NUM_BLOCK 512 + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ] [--device \n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + struct cc_usb *cc; + char *tty = NULL; + char *device = NULL; + int c; + char line[8192]; + FILE *out; + char *filename; + int serial_number; + char cmd; + int tick, a, b; + + while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + case 'D': + device = optarg; + break; + default: + usage(argv[0]); + break; + } + } + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); + if (!tty) + tty = getenv("ALTOS_TTY"); + if (!tty) + tty="/dev/ttyACM0"; + cc = cc_usb_open(tty); + if (!cc) + exit(1); + /* send a 'version' command followed by a 'log' command */ + cc_usb_printf(cc, "v\nl\n"); + out = NULL; + for (;;) { + cc_usb_getline(cc, line, sizeof (line)); + if (!strcmp (line, "end")) + break; + if (sscanf(line, "serial-number %u", &serial_number) == 1) { + filename = cc_make_filename(serial_number, "eeprom"); + out = fopen (filename, "w"); + if (!out) { + perror(filename); + } + } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { + if (out) { + fprintf(out, "%s\n", line); + if (cmd == 'S' && a == 8) { + fclose(out); + out = NULL; + } + } + } + } + if (out) + fclose (out); + cc_usb_close(cc); + exit (0); +} diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index f66ee0a9..da13ede9 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -1,6 +1,6 @@ noinst_LIBRARIES = libao-tools.a -AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS) +AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) libao_tools_a_SOURCES = \ ccdbg-command.c \ @@ -14,6 +14,7 @@ libao_tools_a_SOURCES = \ ccdbg-memory.c \ ccdbg-rom.c \ ccdbg-state.c \ + cc-log.c \ cc-usb.c \ cc-usb.h \ cc.h \ diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 17f05911..80d9c04f 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -30,27 +30,29 @@ #include "cc-usb.h" -#define CC_NUM_READ 16 +#define CC_NUM_HEX_READ 64 /* * AltOS has different buffer sizes for in/out packets */ -#define CC_IN_BUF 256 +#define CC_IN_BUF 65536 #define CC_OUT_BUF 64 #define DEFAULT_TTY "/dev/ttyACM0" -struct cc_read { +struct cc_hex_read { uint8_t *buf; int len; }; struct cc_usb { - int fd; - uint8_t in_buf[CC_IN_BUF]; - int in_count; - uint8_t out_buf[CC_OUT_BUF]; - int out_count; - struct cc_read read_buf[CC_NUM_READ]; - int read_count; + int fd; + uint8_t in_buf[CC_IN_BUF]; + int in_pos; + int in_count; + uint8_t out_buf[CC_OUT_BUF]; + int out_count; + + struct cc_hex_read hex_buf[CC_NUM_HEX_READ]; + int hex_count; }; #define NOT_HEX 0xff @@ -72,61 +74,48 @@ cc_hex_nibble(uint8_t c) * and write them to the waiting buffer */ static void -cc_handle_in(struct cc_usb *cc) +cc_handle_hex_read(struct cc_usb *cc) { uint8_t h, l; - int in_pos; - int read_pos; + int hex_pos; - in_pos = 0; - read_pos = 0; - while (read_pos < cc->read_count && in_pos < cc->in_count) { + hex_pos = 0; + while (hex_pos < cc->hex_count && cc->in_pos < cc->in_count) { /* * Skip to next hex character */ - while (in_pos < cc->in_count && - cc_hex_nibble(cc->in_buf[in_pos]) == NOT_HEX) - in_pos++; + while (cc->in_pos < cc->in_count && + cc_hex_nibble(cc->in_buf[cc->in_pos]) == NOT_HEX) + cc->in_pos++; /* * Make sure we have two characters left */ - if (cc->in_count - in_pos < 2) + if (cc->in_count - cc->in_pos < 2) break; /* * Parse hex number */ - h = cc_hex_nibble(cc->in_buf[in_pos]); - l = cc_hex_nibble(cc->in_buf[in_pos+1]); + h = cc_hex_nibble(cc->in_buf[cc->in_pos]); + l = cc_hex_nibble(cc->in_buf[cc->in_pos+1]); if (h == NOT_HEX || l == NOT_HEX) { fprintf(stderr, "hex read error\n"); break; } - in_pos += 2; + cc->in_pos += 2; /* * Store hex number */ - *cc->read_buf[read_pos].buf++ = (h << 4) | l; - if (--cc->read_buf[read_pos].len <= 0) - read_pos++; - } - - /* Move remaining bytes to the start of the input buffer */ - if (in_pos) { - memmove(cc->in_buf, cc->in_buf + in_pos, - cc->in_count - in_pos); - cc->in_count -= in_pos; + *cc->hex_buf[hex_pos].buf++ = (h << 4) | l; + if (--cc->hex_buf[hex_pos].len <= 0) + hex_pos++; } - /* Move pending reads to the start of the array */ - if (read_pos) { - memmove(cc->read_buf, cc->read_buf + read_pos, - (cc->read_count - read_pos) * sizeof (cc->read_buf[0])); - cc->read_count -= read_pos; + /* Move pending hex reads to the start of the array */ + if (hex_pos) { + memmove(cc->hex_buf, cc->hex_buf + hex_pos, + (cc->hex_count - hex_pos) * sizeof (cc->hex_buf[0])); + cc->hex_count -= hex_pos; } - - /* Once we're done reading, flush any pending input */ - if (cc->read_count == 0) - cc->in_count = 0; } static void @@ -158,8 +147,8 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len) * Flush pending writes, fill pending reads */ -int -cc_usb_sync(struct cc_usb *cc) +static int +_cc_usb_sync(struct cc_usb *cc, int wait_for_input) { int ret; struct pollfd fds; @@ -167,26 +156,33 @@ cc_usb_sync(struct cc_usb *cc) fds.fd = cc->fd; for (;;) { - if (cc->read_count || cc->out_count) + if (cc->hex_count || cc->out_count) timeout = 5000; + else if (wait_for_input && cc->in_pos == cc->in_count) + timeout = wait_for_input; else timeout = 0; fds.events = 0; + /* Move remaining bytes to the start of the input buffer */ + if (cc->in_pos) { + memmove(cc->in_buf, cc->in_buf + cc->in_pos, + cc->in_count - cc->in_pos); + cc->in_count -= cc->in_pos; + cc->in_pos = 0; + } if (cc->in_count < CC_IN_BUF) fds.events |= POLLIN; if (cc->out_count) fds.events |= POLLOUT; ret = poll(&fds, 1, timeout); if (ret == 0) { - if (timeout) { - fprintf(stderr, "USB link timeout\n"); - exit(1); - } + if (timeout) + return -1; break; } if (ret < 0) { perror("poll"); - break; + return -1; } if (fds.revents & POLLIN) { ret = read(cc->fd, cc->in_buf + cc->in_count, @@ -194,7 +190,8 @@ cc_usb_sync(struct cc_usb *cc) if (ret > 0) { cc_usb_dbg(24, cc->in_buf + cc->in_count, ret); cc->in_count += ret; - cc_handle_in(cc); + if (cc->hex_count) + cc_handle_hex_read(cc); } else if (ret < 0) perror("read"); } @@ -211,6 +208,16 @@ cc_usb_sync(struct cc_usb *cc) perror("write"); } } + return 0; +} + +void +cc_usb_sync(struct cc_usb *cc) +{ + if (_cc_usb_sync(cc, 0) < 0) { + fprintf(stderr, "USB link timeout\n"); + exit(1); + } } void @@ -244,6 +251,38 @@ cc_usb_printf(struct cc_usb *cc, char *format, ...) } } +int +cc_usb_getchar(struct cc_usb *cc) +{ + while (cc->in_pos == cc->in_count) { + if (_cc_usb_sync(cc, 5000) < 0) { + fprintf(stderr, "USB link timeout\n"); + exit(1); + } + } + return cc->in_buf[cc->in_pos++]; +} + +void +cc_usb_getline(struct cc_usb *cc, char *line, int max) +{ + int c; + + while ((c = cc_usb_getchar(cc)) != '\n') { + switch (c) { + case '\r': + break; + default: + if (max > 1) { + *line++ = c; + max--; + } + break; + } + } + *line++ = '\0'; +} + int cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len) { @@ -266,12 +305,18 @@ cc_usb_send_bytes(struct cc_usb *cc, uint8_t *bytes, int len) void cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len) { - struct cc_read *read_buf; - while (cc->read_count >= CC_NUM_READ) + struct cc_hex_read *hex_buf; + + /* At the start of a command sequence, flush any pending input */ + if (cc->hex_count == 0) { cc_usb_sync(cc); - read_buf = &cc->read_buf[cc->read_count++]; - read_buf->buf = buf; - read_buf->len = len; + cc->in_count = 0; + } + while (cc->hex_count >= CC_NUM_HEX_READ) + cc_usb_sync(cc); + hex_buf = &cc->hex_buf[cc->hex_count++]; + hex_buf->buf = buf; + hex_buf->len = len; } int @@ -351,9 +396,10 @@ cc_usb_open(char *tty) cfmakeraw(&termios); tcsetattr(cc->fd, TCSAFLUSH, &termios); cc_usb_printf(cc, "E 0\nm 0\n"); - cc_usb_sync(cc); - sleep(1); - cc_usb_sync(cc); + do { + cc->in_count = cc->in_pos = 0; + _cc_usb_sync(cc, 100); + } while (cc->in_count > 0); return cc; } diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h index 9baabd95..7b6be350 100644 --- a/ao-tools/lib/cc-usb.h +++ b/ao-tools/lib/cc-usb.h @@ -47,12 +47,18 @@ cc_usb_debug_mode(struct cc_usb *cc); int cc_usb_reset(struct cc_usb *cc); -int +void cc_usb_sync(struct cc_usb *cc); void cc_queue_read(struct cc_usb *cc, uint8_t *buf, int len); +int +cc_usb_getchar(struct cc_usb *cc); + +void +cc_usb_getline(struct cc_usb *cc, char *line, int max); + void cc_usb_printf(struct cc_usb *cc, char *format, ...); diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 0933f272..f92a29f7 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -51,4 +51,13 @@ cc_usbdevs_scan(void); char * cc_usbdevs_find_by_arg(char *arg, char *default_product); +void +cc_set_log_dir(char *dir); + +char * +cc_get_log_dir(void); + +char * +cc_make_filename(int serial, char *ext); + #endif /* _CC_H_ */ diff --git a/configure.ac b/configure.ac index 56402857..73a33ac3 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,7 @@ ao-tools/Makefile ao-tools/lib/Makefile ao-tools/ao-rawload/Makefile ao-tools/ao-dbg/Makefile +ao-tools/ao-dumplog/Makefile ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile ao-tools/ao-list/Makefile -- cgit v1.2.3 From c46e832b28820d7c5be4efaacbbd7c0607927fe5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Sep 2009 22:03:31 -0700 Subject: Add simple post-flight analysis tool (ao-postflight) This tool reads either an eeprom or telem log file and displays some rudimentary data (max accel/alt for each flight stage). Signed-off-by: Keith Packard --- .gitignore | 4 + ao-tools/Makefile.am | 2 +- ao-tools/ao-dumplog/ao-dumplog.c | 1 + ao-tools/ao-postflight/Makefile.am | 12 ++ ao-tools/ao-postflight/ao-postflight.1 | 29 ++++ ao-tools/ao-postflight/ao-postflight.c | 166 ++++++++++++++++++++ ao-tools/lib/Makefile.am | 4 + ao-tools/lib/cc-analyse.c | 58 +++++++ ao-tools/lib/cc-convert.c | 275 +++++++++++++++++++++++++++++++++ ao-tools/lib/cc-log.c | 114 ++++++++++++++ ao-tools/lib/cc-logfile.c | 218 ++++++++++++++++++++++++++ ao-tools/lib/cc-telem.c | 164 ++++++++++++++++++++ ao-tools/lib/cc-util.c | 2 +- ao-tools/lib/cc.h | 207 +++++++++++++++++++++++++ configure.ac | 1 + 15 files changed, 1255 insertions(+), 2 deletions(-) create mode 100644 ao-tools/ao-postflight/Makefile.am create mode 100644 ao-tools/ao-postflight/ao-postflight.1 create mode 100644 ao-tools/ao-postflight/ao-postflight.c create mode 100644 ao-tools/lib/cc-analyse.c create mode 100644 ao-tools/lib/cc-convert.c create mode 100644 ao-tools/lib/cc-log.c create mode 100644 ao-tools/lib/cc-logfile.c create mode 100644 ao-tools/lib/cc-telem.c diff --git a/.gitignore b/.gitignore index b3d2d562..0ca4bed4 100644 --- a/.gitignore +++ b/.gitignore @@ -22,9 +22,13 @@ ao-teleterra.h ao-tidongle.h ao-tools/ao-bitbang/ao-bitbang ao-tools/ao-dbg/ao-dbg +ao-tools/ao-dumplog/ao-dumplog ao-tools/ao-eeprom/ao-eeprom +ao-tools/ao-list/ao-list ao-tools/ao-load/ao-load +ao-tools/ao-postflight/ao-postflight ao-tools/ao-rawload/ao-rawload +ao-tools/ao-view/ao-view ao-view/Makefile ao-view/ao-view autom4te.cache diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index b61f045f..2850e909 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index 4bccfd61..b930f0e5 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -86,6 +86,7 @@ main (int argc, char **argv) if (!out) { perror(filename); } + fprintf (out, "%s\n", line); } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { if (out) { fprintf(out, "%s\n", line); diff --git a/ao-tools/ao-postflight/Makefile.am b/ao-tools/ao-postflight/Makefile.am new file mode 100644 index 00000000..301ac454 --- /dev/null +++ b/ao-tools/ao-postflight/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-postflight + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_postflight_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_postflight_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) $(GNOME_LIBS) + +ao_postflight_SOURCES = ao-postflight.c + +man_MANS = ao-postflight.1 diff --git a/ao-tools/ao-postflight/ao-postflight.1 b/ao-tools/ao-postflight/ao-postflight.1 new file mode 100644 index 00000000..fe02587f --- /dev/null +++ b/ao-tools/ao-postflight/ao-postflight.1 @@ -0,0 +1,29 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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-POSTFLIGHT 1 "ao-postflight" "" +.SH NAME +ao-postflight \- Analyse a flight log (either telemetry or eeprom) +.SH SYNOPSIS +.B "ao-postflight" +{flight.eeprom|flight.telem} +.SH DESCRIPTION +.I ao-postflight +reads the specified flight log and produces a summary of the flight on stdout. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c new file mode 100644 index 00000000..f0e2c2ae --- /dev/null +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -0,0 +1,166 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cc-usb.h" +#include "cc.h" + +#define NUM_BLOCK 512 + +static const struct option options[] = { + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s {flight-log} ...\n", program); + exit(1); +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +void +analyse_flight(struct cc_flightraw *f) +{ + double height; + double accel; + double boost_start, boost_stop; + double min_pres; + int i; + int pres_i, accel_i; + int boost_start_set = 0; + int boost_stop_set = 0; + enum ao_flight_state state; + double state_start, state_stop; + + printf ("Flight: %9d\nSerial: %9d\n", + f->flight, f->serial); + boost_start = f->accel.data[0].time; + boost_stop = f->accel.data[f->accel.num-1].time; + for (i = 0; i < f->state.num; i++) { + if (f->state.data[i].value == ao_flight_boost && !boost_start_set) { + boost_start = f->state.data[i].time; + boost_start_set = 1; + } + if (f->state.data[i].value > ao_flight_boost && !boost_stop_set) { + boost_stop = f->state.data[i].time; + boost_stop_set = 1; + } + } + + pres_i = cc_timedata_min(&f->pres, f->pres.data[0].time, + f->pres.data[f->pres.num-1].time); + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("Max height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + + accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop); + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + for (i = 0; i < f->state.num; i++) { + state = f->state.data[i].value; + state_start = f->state.data[i].time; + if (i < f->state.num - 1) + state_stop = f->state.data[i+1].time; + else + state_stop = f->accel.data[f->accel.num-1].time; + printf("State: %s\n", state_names[state]); + printf("\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); + printf("\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); + accel_i = cc_timedata_min(&f->accel, state_start, state_stop); + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + + pres_i = cc_timedata_min(&f->pres, state_start, state_stop); + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + } +} + +int +main (int argc, char **argv) +{ + FILE *file; + int i; + int ret = 0; + struct cc_flightraw *raw; + int c; + int serial; + char *s; + + while ((c = getopt_long(argc, argv, "", options, NULL)) != -1) { + switch (c) { + default: + usage(argv[0]); + break; + } + } + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + perror(argv[i]); + ret++; + continue; + } + s = strstr(argv[i], "-serial-"); + if (s) + serial = atoi(s + 8); + else + serial = 0; + raw = cc_log_read(file); + if (!raw) { + perror(argv[i]); + ret++; + continue; + } + if (!raw->serial) + raw->serial = serial; + analyse_flight(raw); + cc_flightraw_free(raw); + } + return ret; +} diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index da13ede9..e682f757 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -14,6 +14,8 @@ libao_tools_a_SOURCES = \ ccdbg-memory.c \ ccdbg-rom.c \ ccdbg-state.c \ + cc-analyse.c \ + cc-convert.c \ cc-log.c \ cc-usb.c \ cc-usb.h \ @@ -22,5 +24,7 @@ libao_tools_a_SOURCES = \ cc-util.c \ cc-bitbang.c \ cc-bitbang.h \ + cc-logfile.c \ + cc-telem.c \ cp-usb-async.c \ cp-usb-async.h diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c new file mode 100644 index 00000000..6fd36cdc --- /dev/null +++ b/ao-tools/lib/cc-analyse.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" + +int +cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) +{ + int i; + int set = 0; + int min_i; + double min; + + if (d->num == 0) + return 0; + for (i = 0; i < d->num; i++) + if (min_time <= d->data[i].time && d->data[i].time <= max_time) + if (!set || d->data[i].value < min) { + min_i = i; + min = d->data[i].value; + set = 1; + } + return min_i; +} + +int +cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) +{ + int i; + double max; + int max_i; + int set = 0; + + if (d->num == 0) + return 0; + for (i = 0; i < d->num; i++) + if (min_time <= d->data[i].time && d->data[i].time <= max_time) + if (!set || d->data[i].value > max) { + max_i = i; + max = d->data[i].value; + set = 1; + } + return max_i; +} diff --git a/ao-tools/lib/cc-convert.c b/ao-tools/lib/cc-convert.c new file mode 100644 index 00000000..ac6962ba --- /dev/null +++ b/ao-tools/lib/cc-convert.c @@ -0,0 +1,275 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include + +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +double +cc_pressure_to_altitude(double pressure) +{ + + double next_base_temperature = LAYER0_BASE_TEMPERATURE; + double next_base_pressure = LAYER0_BASE_PRESSURE; + + double altitude; + double base_pressure; + double base_temperature; + double base; /* base for function to determine base pressure of next layer */ + double exponent; /* exponent for function to determine base pressure + of next layer */ + double coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +/* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + +static const double counts_per_kPa = 27 * 2047 / 3300; +static const double counts_at_101_3kPa = 1674.0; + +double +cc_barometer_to_pressure(double count) +{ + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; +} + +double +cc_barometer_to_altitude(double baro) +{ + double Pa = cc_barometer_to_pressure(baro); + return cc_pressure_to_altitude(Pa); +} + +static const double count_per_mss = 27.0; + +double +cc_accelerometer_to_acceleration(double accel, double ground_accel) +{ + return (ground_accel - accel) / count_per_mss; +} + +double +cc_thermometer_to_temperature(double thermo) +{ + return ((thermo / 32767 * 3.3) - 0.5) / 0.01; +} + +double +cc_battery_to_voltage(double battery) +{ + return battery / 32767.0 * 5.0; +} + +double +cc_ignitor_to_voltage(double ignite) +{ + return ignite / 32767 * 15.0; +} + +static inline double sqr(double a) { return a * a; } + +void +cc_great_circle (double start_lat, double start_lon, + double end_lat, double end_lon, + double *dist, double *bearing) +{ + const double rad = M_PI / 180; + const double earth_radius = 6371.2 * 1000; /* in meters */ + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + +// double d_lat = lat2 - lat1; + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) + + sqr(cos(lat1) * sin(lat2) - + sin(lat1) * cos(lat2) * cos(d_lon))); + double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon); + double d = atan2(vdn,vdd); + double course; + + if (cos(lat1) < 1e-20) { + if (lat1 > 0) + course = M_PI; + else + course = -M_PI; + } else { + if (d < 1e-10) + course = 0; + else + course = acos((sin(lat2)-sin(lat1)*cos(d)) / + (sin(d)*cos(lat1))); + if (sin(lon2-lon1) > 0) + course = 2 * M_PI-course; + } + *dist = d * earth_radius; + *bearing = course * 180/M_PI; +} diff --git a/ao-tools/lib/cc-log.c b/ao-tools/lib/cc-log.c new file mode 100644 index 00000000..dd8177f4 --- /dev/null +++ b/ao-tools/lib/cc-log.c @@ -0,0 +1,114 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 +#include +#include +#include +#include +#include "cc.h" + +static char *cc_file_dir; + +#define ALTOS_DIR_PATH "/apps/aoview/log_dir" +#define DEFAULT_DIR "AltOS" + +static void +cc_file_save_conf(void) +{ + GConfClient *gconf_client; + + g_type_init(); + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + gconf_client_set_string(gconf_client, + ALTOS_DIR_PATH, + cc_file_dir, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + } +} + +static void +cc_file_load_conf(void) +{ + char *file_dir; + GConfClient *gconf_client; + + g_type_init(); + gconf_client = gconf_client_get_default(); + if (gconf_client) + { + file_dir = gconf_client_get_string(gconf_client, + ALTOS_DIR_PATH, + NULL); + g_object_unref(G_OBJECT(gconf_client)); + if (file_dir) + cc_file_dir = strdup(file_dir); + } +} + +void +cc_set_log_dir(char *dir) +{ + cc_file_dir = strdup(dir); + cc_file_save_conf(); +} + +char * +cc_get_log_dir(void) +{ + cc_file_load_conf(); + if (!cc_file_dir) { + cc_file_dir = cc_fullname(getenv("HOME"), DEFAULT_DIR); + cc_file_save_conf(); + } + return cc_file_dir; +} + +char * +cc_make_filename(int serial, char *ext) +{ + char base[50]; + struct tm tm; + time_t now; + char *full; + int r; + int sequence; + + now = time(NULL); + (void) localtime_r(&now, &tm); + cc_mkdir(cc_get_log_dir()); + sequence = 0; + for (;;) { + snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + serial, + sequence, + ext); + full = cc_fullname(cc_get_log_dir(), base); + r = access(full, F_OK); + if (r < 0) + return full; + free(full); + sequence++; + } + +} diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c new file mode 100644 index 00000000..444ff089 --- /dev/null +++ b/ao-tools/lib/cc-logfile.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include +#include + +static int +timedata_add(struct cc_timedata *data, double time, double value) +{ + struct cc_timedataelt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_timedataelt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_timedataelt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + if (data->num && data->data[data->num-1].time > time) + time += 65536; + data->data[data->num].time = time; + data->data[data->num].value = value; + data->num++; + return 1; +} + +static void +timedata_free(struct cc_timedata *data) +{ + if (data->data) + free(data->data); +} + +static int +gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) +{ + struct cc_gpselt *newdata; + int newsize; + if (data->size == data->num) { + if (data->size == 0) + newdata = malloc((newsize = 256) * sizeof (struct cc_gpselt)); + else + newdata = realloc (data->data, (newsize = data->size * 2) + * sizeof (struct cc_gpselt)); + if (!newdata) + return 0; + data->size = newsize; + data->data = newdata; + } + data->data[data->num] = *elt; + data->num++; + return 1; +} + +static void +gpsdata_free(struct cc_gpsdata *data) +{ + if (data->data) + free(data->data); +} + +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' + +#define AO_LOG_POS_NONE (~0UL) + +static int +read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int *ground_pres_count) +{ + char type; + int tick; + int a, b; + struct cc_gpselt gps; + int serial; + + if (sscanf(line, "serial-number %u", &serial) == 1) { + f->serial = serial; + return 1; + } + if (sscanf(line, "%c %x %x %x", &type, &tick, &a, &b) != 4) + return 0; + switch (type) { + case AO_LOG_FLIGHT: + f->ground_accel = a; + f->ground_pres = 0; + f->flight = b; + *ground_pres = 0; + *ground_pres_count = 0; + break; + case AO_LOG_SENSOR: + timedata_add(&f->accel, tick, a); + timedata_add(&f->pres, tick, b); + if (*ground_pres_count < 20) { + *ground_pres += b; + (*ground_pres_count)++; + if (*ground_pres_count >= 20) + f->ground_pres = *ground_pres / *ground_pres_count; + } + break; + case AO_LOG_TEMP_VOLT: + timedata_add(&f->temp, tick, a); + timedata_add(&f->volt, tick, b); + break; + case AO_LOG_DEPLOY: + timedata_add(&f->drogue, tick, a); + timedata_add(&f->main, tick, b); + break; + case AO_LOG_STATE: + timedata_add(&f->state, tick, a); + break; + case AO_LOG_GPS_TIME: + gps.time = tick; + break; + case AO_LOG_GPS_LAT: + gps.lat = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_LON: + gps.lon = ((int32_t) (a + (b << 16))) / 10000000.0; + break; + case AO_LOG_GPS_ALT: + gps.alt = ((int32_t) (a + (b << 16))); + gpsdata_add(&f->gps, &gps); + break; + case AO_LOG_GPS_SAT: + break; + default: + return 0; + } + return 1; +} + +static int +read_telem(const char *line, struct cc_flightraw *f) +{ + struct cc_telem telem; + struct cc_gpselt gps; + if (!cc_telem_parse(line, &telem)) + return 0; + f->ground_accel = telem.ground_accel; + f->ground_pres = telem.ground_pres; + f->flight = 0; + timedata_add(&f->accel, telem.tick, telem.flight_accel); + timedata_add(&f->pres, telem.tick, telem.flight_pres); + timedata_add(&f->temp, telem.tick, telem.temp); + timedata_add(&f->volt, telem.tick, telem.batt); + timedata_add(&f->drogue, telem.tick, telem.drogue); + timedata_add(&f->main, telem.tick, telem.main); + if (telem.gps.gps_locked) { + gps.time = telem.tick; + gps.lat = telem.gps.lat; + gps.lon = telem.gps.lon; + gps.alt = telem.gps.alt; + gpsdata_add(&f->gps, &gps); + } + return 1; +} + +struct cc_flightraw * +cc_log_read(FILE *file) +{ + struct cc_flightraw *f; + char line[8192]; + double ground_pres; + int ground_pres_count; + + f = calloc(1, sizeof (struct cc_flightraw)); + if (!f) + return NULL; + while (fgets(line, sizeof (line), file)) { + if (read_eeprom(line, f, &ground_pres, &ground_pres_count)) + continue; + if (read_telem(line, f)) + continue; + fprintf (stderr, "invalid line: %s", line); + } + return f; +} + +void +cc_flightraw_free(struct cc_flightraw *raw) +{ + timedata_free(&raw->accel); + timedata_free(&raw->pres); + timedata_free(&raw->temp); + timedata_free(&raw->volt); + timedata_free(&raw->main); + timedata_free(&raw->drogue); + timedata_free(&raw->state); + gpsdata_free(&raw->gps); + free(raw); +} diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c new file mode 100644 index 00000000..a6ac0313 --- /dev/null +++ b/ao-tools/lib/cc-telem.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include +#include + +static void +cc_parse_string(char *target, int len, char *source) +{ + strncpy(target, source, len-1); + target[len-1] = '\0'; +} + +static void +cc_parse_int(int *target, char *source) +{ + *target = strtol(source, NULL, 0); +} + +static void +cc_parse_hex(int *target, char *source) +{ + *target = strtol(source, NULL, 16); +} + +static void +cc_parse_pos(double *target, char *source) +{ + int deg; + double min; + char dir; + double r; + + if (sscanf(source, "%d°%lf'%c", °, &min, &dir) != 3) { + *target = 0; + return; + } + r = deg + min / 60.0; + if (dir == 'S' || dir == 'W') + r = -r; + *target = r; +} + +#define PARSE_MAX_WORDS 512 + +int +cc_telem_parse(const char *input_line, struct cc_telem *telem) +{ + char *saveptr; + char *words[PARSE_MAX_WORDS]; + int nword; + char line_buf[8192], *line; + int tracking_pos; + + /* avoid smashing our input parameter */ + strncpy (line_buf, input_line, sizeof (line_buf)-1); + line_buf[sizeof(line_buf) - 1] = '\0'; + line = line_buf; + for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { + words[nword] = strtok_r(line, " \t\n", &saveptr); + line = NULL; + if (words[nword] == NULL) + break; + } + if (nword < 36) + return FALSE; + if (strcmp(words[0], "CALL") != 0) + return FALSE; + cc_parse_string(telem->callsign, sizeof (telem->callsign), words[1]); + cc_parse_int(&telem->serial, words[3]); + + cc_parse_int(&telem->rssi, words[5]); + cc_parse_string(telem->state, sizeof (telem->state), words[9]); + cc_parse_int(&telem->tick, words[10]); + cc_parse_int(&telem->accel, words[12]); + cc_parse_int(&telem->pres, words[14]); + cc_parse_int(&telem->temp, words[16]); + cc_parse_int(&telem->batt, words[18]); + cc_parse_int(&telem->drogue, words[20]); + cc_parse_int(&telem->main, words[22]); + cc_parse_int(&telem->flight_accel, words[24]); + cc_parse_int(&telem->ground_accel, words[26]); + cc_parse_int(&telem->flight_vel, words[28]); + cc_parse_int(&telem->flight_pres, words[30]); + cc_parse_int(&telem->ground_pres, words[32]); + cc_parse_int(&telem->gps.nsat, words[34]); + if (strcmp (words[36], "unlocked") == 0) { + telem->gps.gps_connected = 1; + telem->gps.gps_locked = 0; + telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; + telem->gps.lat = telem->gps.lon = 0; + telem->gps.alt = 0; + tracking_pos = 37; + } else if (nword >= 40) { + telem->gps.gps_locked = 1; + telem->gps.gps_connected = 1; + sscanf(words[36], "%d:%d:%d", &telem->gps.gps_time.hour, &telem->gps.gps_time.minute, &telem->gps.gps_time.second); + cc_parse_pos(&telem->gps.lat, words[37]); + cc_parse_pos(&telem->gps.lon, words[38]); + sscanf(words[39], "%dm", &telem->gps.alt); + tracking_pos = 46; + } else { + telem->gps.gps_connected = 0; + telem->gps.gps_locked = 0; + telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; + telem->gps.lat = telem->gps.lon = 0; + telem->gps.alt = 0; + tracking_pos = -1; + } + if (nword >= 46) { + telem->gps.gps_extended = 1; + sscanf(words[40], "%lfm/s", &telem->gps.ground_speed); + sscanf(words[41], "%d", &telem->gps.course); + sscanf(words[42], "%lfm/s", &telem->gps.climb_rate); + sscanf(words[43], "%lf", &telem->gps.hdop); + sscanf(words[44], "%d", &telem->gps.h_error); + sscanf(words[45], "%d", &telem->gps.v_error); + } else { + telem->gps.gps_extended = 0; + telem->gps.ground_speed = 0; + telem->gps.course = 0; + telem->gps.climb_rate = 0; + telem->gps.hdop = 0; + telem->gps.h_error = 0; + telem->gps.v_error = 0; + } + if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { + int c, n, pos; + cc_parse_int(&n, words[tracking_pos + 1]); + pos = tracking_pos + 2; + if (nword >= pos + n * 3) { + telem->gps_tracking.channels = n; + for (c = 0; c < n; c++) { + cc_parse_int(&telem->gps_tracking.sats[c].svid, + words[pos + 0]); + cc_parse_hex(&telem->gps_tracking.sats[c].state, + words[pos + 1]); + cc_parse_int(&telem->gps_tracking.sats[c].c_n0, + words[pos + 2]); + pos += 3; + } + } else { + telem->gps_tracking.channels = 0; + } + } else { + telem->gps_tracking.channels = 0; + } + return TRUE; +} diff --git a/ao-tools/lib/cc-util.c b/ao-tools/lib/cc-util.c index 7104470c..65488ee9 100644 --- a/ao-tools/lib/cc-util.c +++ b/ao-tools/lib/cc-util.c @@ -15,8 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "cc.h" #define _GNU_SOURCE +#include "cc.h" #include #include #include diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index f92a29f7..3975cf1b 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -18,6 +18,8 @@ #ifndef _CC_H_ #define _CC_H_ +#include + char * cc_fullname (char *dir, char *file); @@ -60,4 +62,209 @@ cc_get_log_dir(void); char * cc_make_filename(int serial, char *ext); +/* + * For sequential data which are not evenly spaced + */ + +struct cc_timedataelt { + double time; + double value; +}; + +struct cc_timedata { + int num; + int size; + struct cc_timedataelt *data; +}; + + +/* + * For GPS data + */ + +struct cc_gpselt { + double time; + double lat; + double lon; + double alt; +}; + +struct cc_gpsdata { + int num; + int size; + double time_offset; + struct cc_gpselt *data; +}; + +/* + * For sequential data which are evenly spaced + */ +struct cc_perioddata { + int num; + double start; + double step; + double *data; +}; + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +struct cc_flightraw { + int flight; + int serial; + double ground_accel; + double ground_pres; + struct cc_timedata accel; + struct cc_timedata pres; + struct cc_timedata temp; + struct cc_timedata volt; + struct cc_timedata main; + struct cc_timedata drogue; + struct cc_timedata state; + struct cc_gpsdata gps; +}; + +struct cc_flightraw * +cc_log_read(FILE *file); + +void +cc_flightraw_free(struct cc_flightraw *raw); + +struct cc_flightcooked { + struct cc_perioddata accel_accel; + struct cc_perioddata accel_speed; + struct cc_perioddata accel_pos; + struct cc_perioddata pres_pos; + struct cc_perioddata pres_speed; + struct cc_perioddata pres_accel; + struct cc_perioddata gps_lat; + struct cc_perioddata gps_lon; + struct cc_perioddata gps_alt; + struct cc_timedata state; +}; + +/* + * Telemetry data contents + */ + + +struct cc_gps_time { + int hour; + int minute; + int second; +}; + +struct cc_gps { + int nsat; + int gps_locked; + int gps_connected; + struct cc_gps_time gps_time; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + + int gps_extended; /* has extra data */ + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless? */ + int h_error; /* m */ + int v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct cc_gps_sat { + int svid; + int state; + int c_n0; +}; + +struct cc_gps_tracking { + int channels; + struct cc_gps_sat sats[12]; +}; + +struct cc_telem { + char callsign[16]; + int serial; + int rssi; + char state[16]; + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + int flight_accel; + int ground_accel; + int flight_vel; + int flight_pres; + int ground_pres; + struct cc_gps gps; + struct cc_gps_tracking gps_tracking; +}; + +int +cc_telem_parse(const char *input_line, struct cc_telem *telem); + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +/* Conversion functions */ +double +cc_pressure_to_altitude(double pressure); + +double +cc_altitude_to_pressure(double altitude); + +double +cc_barometer_to_pressure(double baro); + +double +cc_barometer_to_altitude(double baro); + +double +cc_accelerometer_to_acceleration(double accel, double ground_accel); + +double +cc_thermometer_to_temperature(double thermo); + +double +cc_battery_to_voltage(double battery); + +double +cc_ignitor_to_voltage(double ignite); + +void +cc_great_circle (double start_lat, double start_lon, + double end_lat, double end_lon, + double *dist, double *bearing); + +int +cc_timedata_min(struct cc_timedata *d, double min_time, double max_time); + +int +cc_timedata_max(struct cc_timedata *d, double min_time, double max_time); + #endif /* _CC_H_ */ diff --git a/configure.ac b/configure.ac index 73a33ac3..c668df04 100644 --- a/configure.ac +++ b/configure.ac @@ -82,6 +82,7 @@ ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile +ao-tools/ao-postflight/Makefile ao-tools/ao-view/Makefile ao-utils/Makefile ]) -- cgit v1.2.3 From 6d018ab933832e2d80bb1564c339d9fb18b57be2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Sep 2009 22:45:49 -0700 Subject: Handle vageries of .telem files in ao-postflight Telem files have multiple entries of the same state, and sometimes long gaps between recordings. Deal with this as best as possible. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 60 +++++++++++++++++++++------------- ao-tools/lib/cc-analyse.c | 8 ++--- ao-tools/lib/cc-logfile.c | 35 +++++++++++++++++++- ao-tools/lib/cc.h | 3 +- 4 files changed, 77 insertions(+), 29 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index f0e2c2ae..9371f351 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -81,43 +81,57 @@ analyse_flight(struct cc_flightraw *f) pres_i = cc_timedata_min(&f->pres, f->pres.data[0].time, f->pres.data[f->pres.num-1].time); - min_pres = f->pres.data[pres_i].value; - height = cc_barometer_to_altitude(min_pres) - - cc_barometer_to_altitude(f->ground_pres); - printf ("Max height: %9.2fm %9.2fft %9.2fs\n", - height, height * 100 / 2.54 / 12, - (f->pres.data[pres_i].time - boost_start) / 100.0); + if (pres_i) + { + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("Max height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + } accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop); - accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, - f->ground_accel); - printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", - accel, accel / 9.80665, - (f->accel.data[accel_i].time - boost_start) / 100.0); + if (accel_i) + { + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + } for (i = 0; i < f->state.num; i++) { state = f->state.data[i].value; state_start = f->state.data[i].time; + while (i < f->state.num - 1 && f->state.data[i+1].value == state) + i++; if (i < f->state.num - 1) - state_stop = f->state.data[i+1].time; + state_stop = f->state.data[i + 1].time; else state_stop = f->accel.data[f->accel.num-1].time; printf("State: %s\n", state_names[state]); printf("\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); printf("\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); accel_i = cc_timedata_min(&f->accel, state_start, state_stop); - accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, - f->ground_accel); - printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", - accel, accel / 9.80665, - (f->accel.data[accel_i].time - boost_start) / 100.0); + if (accel_i >= 0) + { + accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, + f->ground_accel); + printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", + accel, accel / 9.80665, + (f->accel.data[accel_i].time - boost_start) / 100.0); + } pres_i = cc_timedata_min(&f->pres, state_start, state_stop); - min_pres = f->pres.data[pres_i].value; - height = cc_barometer_to_altitude(min_pres) - - cc_barometer_to_altitude(f->ground_pres); - printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", - height, height * 100 / 2.54 / 12, - (f->pres.data[pres_i].time - boost_start) / 100.0); + if (pres_i >= 0) + { + min_pres = f->pres.data[pres_i].value; + height = cc_barometer_to_altitude(min_pres) - + cc_barometer_to_altitude(f->ground_pres); + printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", + height, height * 100 / 2.54 / 12, + (f->pres.data[pres_i].time - boost_start) / 100.0); + } } } diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index 6fd36cdc..fc8a8417 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -22,11 +22,11 @@ cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) { int i; int set = 0; - int min_i; + int min_i = -1; double min; if (d->num == 0) - return 0; + return -1; for (i = 0; i < d->num; i++) if (min_time <= d->data[i].time && d->data[i].time <= max_time) if (!set || d->data[i].value < min) { @@ -42,11 +42,11 @@ cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) { int i; double max; - int max_i; + int max_i = -1; int set = 0; if (d->num == 0) - return 0; + return -1; for (i = 0; i < d->num; i++) if (min_time <= d->data[i].time && d->data[i].time <= max_time) if (!set || d->data[i].value > max) { diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 444ff089..4abf7eb6 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -18,6 +18,7 @@ #include "cc.h" #include #include +#include static int timedata_add(struct cc_timedata *data, double time, double value) @@ -35,8 +36,11 @@ timedata_add(struct cc_timedata *data, double time, double value) data->size = newsize; data->data = newdata; } - if (data->num && data->data[data->num-1].time > time) + time += data->time_offset; + if (data->num && data->data[data->num-1].time > time) { + data->time_offset += 65536; time += 65536; + } data->data[data->num].time = time; data->data[data->num].value = value; data->num++; @@ -66,6 +70,11 @@ gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) data->size = newsize; data->data = newdata; } + elt->time += data->time_offset; + if (data->num && data->data[data->num-1].time > elt->time) { + data->time_offset += 65536; + elt->time += 65536; + } data->data[data->num] = *elt; data->num++; return 1; @@ -156,6 +165,29 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * return 1; } +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static enum ao_flight_state +state_name_to_state(char *state_name) +{ + enum ao_flight_state state; + for (state = ao_flight_startup; state < ao_flight_invalid; state++) + if (!strcmp(state_names[state], state_name)) + return state; + return ao_flight_invalid; +} + static int read_telem(const char *line, struct cc_flightraw *f) { @@ -172,6 +204,7 @@ read_telem(const char *line, struct cc_flightraw *f) timedata_add(&f->volt, telem.tick, telem.batt); timedata_add(&f->drogue, telem.tick, telem.drogue); timedata_add(&f->main, telem.tick, telem.main); + timedata_add(&f->state, telem.tick, state_name_to_state(telem.state)); if (telem.gps.gps_locked) { gps.time = telem.tick; gps.lat = telem.gps.lat; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 3975cf1b..57f80b8d 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -75,6 +75,7 @@ struct cc_timedata { int num; int size; struct cc_timedataelt *data; + double time_offset; }; @@ -92,8 +93,8 @@ struct cc_gpselt { struct cc_gpsdata { int num; int size; - double time_offset; struct cc_gpselt *data; + double time_offset; }; /* -- cgit v1.2.3 From 384dbe9fc7fa8e4e5dceec5e150f0f1d3383bbdc Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 10:40:06 -0600 Subject: update changelogs for Debian build --- ChangeLog | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 63 insertions(+) diff --git a/ChangeLog b/ChangeLog index 771118c2..cd539832 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,60 @@ +commit 35c54b3a278fa9bc2bc7f4b5ee04866697c93ba0 +Merge: 4f8eff7 6d018ab +Author: Bdale Garbee +Date: Sun Sep 6 10:39:23 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 6d018ab933832e2d80bb1564c339d9fb18b57be2 +Author: Keith Packard +Date: Sat Sep 5 22:45:49 2009 -0700 + + Handle vageries of .telem files in ao-postflight + + Telem files have multiple entries of the same state, and sometimes + long gaps between recordings. Deal with this as best as possible. + + Signed-off-by: Keith Packard + +commit c46e832b28820d7c5be4efaacbbd7c0607927fe5 +Author: Keith Packard +Date: Sat Sep 5 22:03:31 2009 -0700 + + Add simple post-flight analysis tool (ao-postflight) + + This tool reads either an eeprom or telem log file and displays some + rudimentary data (max accel/alt for each flight stage). + + Signed-off-by: Keith Packard + +commit 26f56b51bd11aa91f1d77b81827b49c28cb6ec5f +Author: Keith Packard +Date: Sat Sep 5 00:29:26 2009 -0700 + + Add ao-dumplog to capture flight log from command line + + This duplicates the functionality of the flight log stuf in ao-view, + except from the command line where it belongs. + + Signed-off-by: Keith Packard + +commit 73adae3661160d410dcc802873b530d255c210e5 +Author: Keith Packard +Date: Fri Sep 4 15:30:22 2009 -0700 + + Add --device/-D support to the command line tools and manuals + + Use the new cc_usbdevs_find_by_arg function to locate suitable target + devices connected via USB. + + Signed-off-by: Keith Packard + +commit 4f8eff7401ee2d8092ab36fa33411f9b23dda880 +Author: Bdale Garbee +Date: Fri Sep 4 16:03:55 2009 -0600 + + update changelogs for Debian build + commit 332b056459b1352e233a8bf5f08498df12d32160 Author: Keith Packard Date: Fri Sep 4 15:01:32 2009 -0700 diff --git a/debian/changelog b/debian/changelog index ae7b9642..b697e0b1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+33+g35c54b3) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 10:40:06 -0600 + altos (0.5+27+g332b056) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 7a19aac5e881e635962a64fff73027ca2143b96f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 12:51:48 -0700 Subject: Add DSP code to filter data, allowing for integration/differentiation This adds the computation of speed from both accelerometer and barometer measurements and then presents a periodic flight profile using filtered data as a detailed flight record. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 135 +++++++++-- ao-tools/lib/Makefile.am | 10 +- ao-tools/lib/cc-analyse.c | 57 +++++ ao-tools/lib/cc-dsp.c | 145 ++++++++++++ ao-tools/lib/cc-integrate.c | 78 +++++++ ao-tools/lib/cc-period.c | 64 +++++ ao-tools/lib/cc-process.c | 140 +++++++++++ ao-tools/lib/cc.h | 28 +++ ao-tools/lib/cephes.h | 122 ++++++++++ ao-tools/lib/chbevl.c | 81 +++++++ ao-tools/lib/cmath.h | 179 ++++++++++++++ ao-tools/lib/i0.c | 414 +++++++++++++++++++++++++++++++++ ao-tools/lib/mconf.h | 211 +++++++++++++++++ 13 files changed, 1639 insertions(+), 25 deletions(-) create mode 100644 ao-tools/lib/cc-dsp.c create mode 100644 ao-tools/lib/cc-integrate.c create mode 100644 ao-tools/lib/cc-period.c create mode 100644 ao-tools/lib/cc-process.c create mode 100644 ao-tools/lib/cephes.h create mode 100644 ao-tools/lib/chbevl.c create mode 100644 ao-tools/lib/cmath.h create mode 100644 ao-tools/lib/i0.c create mode 100644 ao-tools/lib/mconf.h diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 9371f351..c5814c93 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -27,16 +27,6 @@ #define NUM_BLOCK 512 -static const struct option options[] = { - { 0, 0, 0, 0}, -}; - -static void usage(char *program) -{ - fprintf(stderr, "usage: %s {flight-log} ...\n", program); - exit(1); -} - static const char *state_names[] = { "startup", "idle", @@ -51,20 +41,23 @@ static const char *state_names[] = { }; void -analyse_flight(struct cc_flightraw *f) +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) { double height; double accel; + double speed; double boost_start, boost_stop; double min_pres; int i; - int pres_i, accel_i; + int pres_i, accel_i, speed_i; int boost_start_set = 0; int boost_stop_set = 0; enum ao_flight_state state; double state_start, state_stop; + struct cc_flightcooked *cooked; + double apogee; - printf ("Flight: %9d\nSerial: %9d\n", + fprintf(summary_file, "Flight: %9d\nSerial: %9d\n", f->flight, f->serial); boost_start = f->accel.data[0].time; boost_stop = f->accel.data[f->accel.num-1].time; @@ -81,25 +74,37 @@ analyse_flight(struct cc_flightraw *f) pres_i = cc_timedata_min(&f->pres, f->pres.data[0].time, f->pres.data[f->pres.num-1].time); - if (pres_i) + if (pres_i >= 0) { min_pres = f->pres.data[pres_i].value; height = cc_barometer_to_altitude(min_pres) - cc_barometer_to_altitude(f->ground_pres); - printf ("Max height: %9.2fm %9.2fft %9.2fs\n", + fprintf(summary_file, "Max height: %9.2fm %9.2fft %9.2fs\n", height, height * 100 / 2.54 / 12, (f->pres.data[pres_i].time - boost_start) / 100.0); + apogee = f->pres.data[pres_i].time; } + cooked = cc_flight_cook(f); + if (cooked) { + speed_i = cc_perioddata_max(&cooked->accel_speed, boost_start, boost_stop); + if (speed_i >= 0) { + speed = cooked->accel_speed.data[speed_i]; + fprintf(summary_file, "Max speed: %9.2fm/s %9.2fft/s %9.2fs\n", + speed, speed * 100 / 2.4 / 12.0, + (cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0); + } + } accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop); - if (accel_i) + if (accel_i >= 0) { accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, f->ground_accel); - printf ("Max accel: %9.2fm/s² %9.2fg %9.2fs\n", + fprintf(summary_file, "Max accel: %9.2fm/s² %9.2fg %9.2fs\n", accel, accel / 9.80665, (f->accel.data[accel_i].time - boost_start) / 100.0); } + for (i = 0; i < f->state.num; i++) { state = f->state.data[i].value; state_start = f->state.data[i].time; @@ -109,50 +114,132 @@ analyse_flight(struct cc_flightraw *f) state_stop = f->state.data[i + 1].time; else state_stop = f->accel.data[f->accel.num-1].time; - printf("State: %s\n", state_names[state]); - printf("\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); - printf("\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); + fprintf(summary_file, "State: %s\n", state_names[state]); + fprintf(summary_file, "\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); + fprintf(summary_file, "\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); accel_i = cc_timedata_min(&f->accel, state_start, state_stop); if (accel_i >= 0) { accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, f->ground_accel); - printf("\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", + fprintf(summary_file, "\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", accel, accel / 9.80665, (f->accel.data[accel_i].time - boost_start) / 100.0); } + if (cooked) { + if (state_start < apogee) { + speed_i = cc_perioddata_max(&cooked->accel_speed, state_start, state_stop); + if (speed_i >= 0) + speed = cooked->accel_speed.data[speed_i]; + } else { + speed_i = cc_perioddata_max(&cooked->pres_speed, state_start, state_stop); + if (speed_i >= 0) + speed = cooked->pres_speed.data[speed_i]; + } + if (speed_i >= 0) + fprintf(summary_file, "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n", + speed, speed * 100 / 2.4 / 12.0, + (cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0); + } pres_i = cc_timedata_min(&f->pres, state_start, state_stop); if (pres_i >= 0) { min_pres = f->pres.data[pres_i].value; height = cc_barometer_to_altitude(min_pres) - cc_barometer_to_altitude(f->ground_pres); - printf ("\tMax height: %9.2fm %9.2fft %9.2fs\n", + fprintf(summary_file, "\tMax height: %9.2fm %9.2fft %9.2fs\n", height, height * 100 / 2.54 / 12, (f->pres.data[pres_i].time - boost_start) / 100.0); } } + if (cooked && detail_file) { + double apogee_time; + double max_height = 0; + int i; + + for (i = 0; i < cooked->pres_pos.num; i++) { + if (cooked->pres_pos.data[i] > max_height) { + max_height = cooked->pres_pos.data[i]; + apogee_time = cooked->pres_pos.start + cooked->pres_pos.step * i; + } + } + fprintf(detail_file, "%9s %9s %9s %9s\n", + "time", "height", "speed", "accel"); + for (i = 0; i < cooked->pres_pos.num; i++) { + double time = (cooked->accel_accel.start + i * cooked->accel_accel.step - boost_start) / 100.0; + double accel = cooked->accel_accel.data[i]; + double pos = cooked->pres_pos.data[i]; + double speed; + if (cooked->pres_pos.start + cooked->pres_pos.step * i < apogee_time) + speed = cooked->accel_speed.data[i]; + else + speed = cooked->pres_speed.data[i]; + fprintf(detail_file, "%9.2f %9.2f %9.2f %9.2f\n", + time, pos, speed, accel); + } + } +} + +static const struct option options[] = { + { .name = "summary", .has_arg = 1, .val = 'S' }, + { .name = "detail", .has_arg = 1, .val = 'D' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--summary=] [--detail=serial) raw->serial = serial; - analyse_flight(raw); + analyse_flight(raw, summary_file, detail_file); cc_flightraw_free(raw); } return ret; diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index e682f757..79972f46 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -16,7 +16,11 @@ libao_tools_a_SOURCES = \ ccdbg-state.c \ cc-analyse.c \ cc-convert.c \ + cc-dsp.c \ cc-log.c \ + cc-integrate.c \ + cc-period.c \ + cc-process.c \ cc-usb.c \ cc-usb.h \ cc.h \ @@ -27,4 +31,8 @@ libao_tools_a_SOURCES = \ cc-logfile.c \ cc-telem.c \ cp-usb-async.c \ - cp-usb-async.h + cp-usb-async.h \ + i0.c \ + chbevl.c \ + mconf.h \ + cephes.h diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index fc8a8417..0e020115 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -16,6 +16,7 @@ */ #include "cc.h" +#include int cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) @@ -56,3 +57,59 @@ cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) } return max_i; } + +int +cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double min; + int min_i; + + if (d->num == 0) + return -1; + start = (int) ceil((min_time - d->start) / d->step); + if (start < 0) + start = 0; + stop = (int) floor((max_time - d->start) / d->step); + if (stop >= d->num) + stop = d->num - 1; + if (stop < start) + return -1; + min = d->data[start]; + min_i = start; + for (i = start + 1; i <= stop; i++) + if (d->data[i] < min) { + min = d->data[i]; + min_i = i; + } + return min_i; +} + +int +cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double max; + int max_i; + + if (d->num == 0) + return -1; + start = (int) ceil((min_time - d->start) / d->step); + if (start < 0) + start = 0; + stop = (int) floor((max_time - d->start) / d->step); + if (stop >= d->num) + stop = d->num - 1; + if (stop < start) + return -1; + max = d->data[start]; + max_i = start; + for (i = start + 1; i <= stop; i++) + if (fabs(d->data[i]) > max) { + max = fabs(d->data[i]); + max_i = i; + } + return max_i; +} diff --git a/ao-tools/lib/cc-dsp.c b/ao-tools/lib/cc-dsp.c new file mode 100644 index 00000000..518c1a68 --- /dev/null +++ b/ao-tools/lib/cc-dsp.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include "cephes.h" +#include +#include + +static inline double sqr (double x) { return x * x; } + +/* + * Kaiser Window digital filter + */ + +#if 0 +/* not used in this program */ +static double highpass (double n, double m, double wc) +{ + double alpha = m/2; + double dist; + + dist = n - alpha; + if (dist == 0) + return (M_PI/2 - wc) / M_PI; + return -sin(dist * (M_PI/2-wc)) / (M_PI * dist); +} +#endif + +static double lowpass (double n, double m, double wc) +{ + double alpha = m/2; + double dist; + dist = n - alpha; + if (dist == 0) + return wc / M_PI; + return sin (wc * dist) / (M_PI * dist); +} + +static double kaiser (double n, double m, double beta) +{ + double alpha = m / 2; + return i0 (beta * sqrt (1 - sqr((n - alpha) / alpha))) / i0(beta); +} + +static double beta (double A) +{ + if (A > 50) + return 0.1102 * (A - 8.7); + else if (A >= 21) + return 0.5842 * pow((A - 21), 0.4) + 0.07886 * (A - 21); + else + return 0.0; +} + +static int M (double A, double delta_omega) +{ + if (A > 21) + return ceil ((A - 7.95) / (2.285 * delta_omega)); + else + return ceil(5.79 / delta_omega); +} + +struct filter_param { + double omega_pass; + double delta_omega; + double A; + double beta; + int M; +} filter_param_t; + +static struct filter_param +filter (double omega_pass, double omega_stop, double error) +{ + struct filter_param p; + p.omega_pass = omega_pass; + p.delta_omega = omega_stop - omega_pass; + p.A = -20 * log10 (error); + p.beta = beta (p.A); + p.M = M (p.A, p.delta_omega); + if ((p.M & 1) == 1) + p.M++; + return p; +} + +static double * +make_low_pass_filter(double omega_pass, double omega_stop, double error, int *length_p) +{ + struct filter_param p = filter(omega_pass, omega_stop, error); + int length; + int n; + double *lpf; + + length = p.M + 1; + lpf = calloc (length, sizeof(double)); + for (n = 0; n < length; n++) + lpf[n] = lowpass(n, p.M, omega_pass) * kaiser(n, p.M, p.beta); + *length_p = length; + return lpf; +} + +static double * +convolve(double *d, int d_len, double *e, int e_len) +{ + int w = (e_len - 1) / 2; + int n; + double *con = calloc (d_len, sizeof (double)); + + for (n = 0; n < d_len; n++) { + double v = 0; + int o; + for (o = -w; o <= w; o++) { + int p = n + o; + double sample = p < 0 ? d[0] : p >= d_len ? d[d_len-1] : d[p]; + v += sample * e[o + w]; + } + con[n] = v; + } + return con; +} + +double * +cc_low_pass(double *data, int data_len, double omega_pass, double omega_stop, double error) +{ + int fir_len; + double *fir = make_low_pass_filter(omega_pass, omega_stop, error, &fir_len); + double *result; + + result = convolve(data, data_len, fir, fir_len); + free(fir); + return result; +} diff --git a/ao-tools/lib/cc-integrate.c b/ao-tools/lib/cc-integrate.c new file mode 100644 index 00000000..08ca295c --- /dev/null +++ b/ao-tools/lib/cc-integrate.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include + +struct cc_timedata * +cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), double a) +{ + struct cc_timedata *r; + int n; + + r = calloc (1, sizeof (struct cc_timedata)); + r->num = d->num; + r->size = d->num; + r->data = calloc (r->size, sizeof (struct cc_timedataelt)); + r->time_offset = d->time_offset; + for (n = 0; n < d->num; n++) { + r->data[n].time = d->data[n].time; + r->data[n].value = f(d->data[n].value, a); + } + return r; +} + +struct cc_timedata * +cc_timedata_integrate(struct cc_timedata *d) +{ + struct cc_timedata *i; + int n; + + i = calloc (1, sizeof (struct cc_timedata)); + i->num = d->num; + i->size = d->num; + i->data = calloc (i->size, sizeof (struct cc_timedataelt)); + i->time_offset = d->time_offset; + for (n = 0; n < d->num; n++) { + i->data[n].time = d->data[n].time; + if (n == 0) { + i->data[n].value = 0; + } else { + i->data[n].value = i->data[n-1].value + + (d->data[n].value + d->data[n-1].value) / 2 * + ((d->data[n].time - d->data[n-1].time) / 100.0); + } + } + return i; +} + +struct cc_perioddata * +cc_perioddata_differentiate(struct cc_perioddata *i) +{ + struct cc_perioddata *d; + int n; + + d = calloc (1, sizeof (struct cc_perioddata)); + d->num = i->num; + d->start = i->start; + d->step = i->step; + d->data = calloc (d->num, sizeof(double)); + for (n = 1; n < d->num; n++) + d->data[n] = (i->data[n] - i->data[n-1]) / i->step; + d->data[0] = d->data[1]; + return d; +} diff --git a/ao-tools/lib/cc-period.c b/ao-tools/lib/cc-period.c new file mode 100644 index 00000000..c74cf9dc --- /dev/null +++ b/ao-tools/lib/cc-period.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include + +struct cc_perioddata * +cc_period_make(struct cc_timedata *td, double start_time, double stop_time) +{ + int len = stop_time - start_time + 1; + struct cc_perioddata *pd; + int i; + double prev_time; + double next_time; + double interval; + + pd = calloc(1, sizeof (struct cc_perioddata)); + pd->start = start_time; + pd->step = 1; + pd->num = len; + pd->data = calloc(len, sizeof(double)); + prev_time = start_time; + for (i = 0; i < td->num; i++) { + if (start_time <= td->data[i].time && td->data[i].time <= stop_time) { + int pos = td->data[i].time - start_time; + + if (i < td->num - 1 && td->data[i+1].time < stop_time) + next_time = (td->data[i].time + td->data[i+1].time) / 2.0; + else + next_time = stop_time; + interval = next_time - prev_time; + pd->data[pos] = td->data[i].value * interval; + prev_time = next_time; + } + } + return pd; +} + +struct cc_perioddata * +cc_period_low_pass(struct cc_perioddata *raw, double omega_pass, double omega_stop, double error) +{ + struct cc_perioddata *filtered; + + filtered = calloc (1, sizeof (struct cc_perioddata)); + filtered->start = raw->start; + filtered->step = raw->step; + filtered->num = raw->num; + filtered->data = cc_low_pass(raw->data, raw->num, omega_pass, omega_stop, error); + return filtered; +} diff --git a/ao-tools/lib/cc-process.c b/ao-tools/lib/cc-process.c new file mode 100644 index 00000000..e906b635 --- /dev/null +++ b/ao-tools/lib/cc-process.c @@ -0,0 +1,140 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "cc.h" +#include +#include +#include + +static void +cook_timed(struct cc_timedata *td, struct cc_perioddata *pd, + double start_time, double stop_time, + double omega_pass, double omega_stop, double error) +{ + struct cc_perioddata *unfiltered, *filtered; + + unfiltered = cc_period_make(td, start_time, stop_time); + filtered = cc_period_low_pass (unfiltered, omega_pass, omega_stop, error); + *pd = *filtered; + free (filtered); + free (unfiltered->data); + free (unfiltered); + free (td->data); + free (td); +} + +static double +barometer_to_altitude(double b, double pad_alt) +{ + return cc_barometer_to_altitude(b) - pad_alt; +} + +struct cc_flightcooked * +cc_flight_cook(struct cc_flightraw *raw) +{ + struct cc_flightcooked *cooked; + double flight_start; + double flight_stop; + int start_set = 0; + int stop_set = 0; + int i; + struct cc_timedata *accel; + struct cc_timedata *accel_speed; + struct cc_timedata *accel_pos; + struct cc_timedata *pres; + struct cc_perioddata *pres_speed; + struct cc_perioddata *pres_accel; + + if (raw->accel.num == 0) + return NULL; + + cooked = calloc (1, sizeof (struct cc_flightcooked)); + + /* + * Find flight start and stop times by looking at + * state transitions. The stop time is set to the time + * of landing, which may be long after it landed (due to radio + * issues). Refine this value by looking through the sensor data + */ + for (i = 0; i < raw->state.num; i++) { + if (!start_set && raw->state.data[i].value > ao_flight_pad) { + flight_start = raw->state.data[i].time; + start_set = 1; + } + if (!stop_set && raw->state.data[i].value > ao_flight_main) { + flight_stop = raw->state.data[i].time; + stop_set = 1; + } + } + + if (!start_set) + flight_start = raw->accel.data[0].time; + if (stop_set) { + for (i = 0; i < raw->accel.num - 1; i++) { + if (raw->accel.data[i+1].time >= flight_stop) { + flight_stop = raw->accel.data[i].time; + break; + } + } + } else { + flight_stop = raw->accel.data[raw->accel.num-1].time; + } + + /* Integrate the accelerometer data to get speed and position */ + accel = cc_timedata_convert(&raw->accel, cc_accelerometer_to_acceleration, raw->ground_accel); + accel_speed = cc_timedata_integrate(accel); + accel_pos = cc_timedata_integrate(accel_speed); + +#define ACCEL_OMEGA_PASS (2 * M_PI * 5 / 100) +#define ACCEL_OMEGA_STOP (2 * M_PI * 8 / 100) +#define BARO_OMEGA_PASS (2 * M_PI * .5 / 100) +#define BARO_OMEGA_STOP (2 * M_PI * 1 / 100) +#define FILTER_ERROR (1e-8) + + cook_timed(accel, &cooked->accel_accel, + flight_start, flight_stop, + ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); + cook_timed(accel_speed, &cooked->accel_speed, + flight_start, flight_stop, + ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); + cook_timed(accel_pos, &cooked->accel_pos, + flight_start, flight_stop, + ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); + + /* Filter the pressure data */ + pres = cc_timedata_convert(&raw->pres, barometer_to_altitude, + cc_barometer_to_altitude(raw->ground_pres)); + cook_timed(pres, &cooked->pres_pos, + flight_start, flight_stop, + BARO_OMEGA_PASS, BARO_OMEGA_STOP, FILTER_ERROR); + /* differentiate twice to get to acceleration */ + pres_speed = cc_perioddata_differentiate(&cooked->pres_pos); + pres_accel = cc_perioddata_differentiate(pres_speed); + + cooked->pres_speed = *pres_speed; + free(pres_speed); + cooked->pres_accel = *pres_accel; + free(pres_accel); + + /* copy state */ + cooked->state.num = raw->state.num; + cooked->state.size = raw->state.num; + cooked->state.data = calloc(cooked->state.num, sizeof (struct cc_timedataelt)); + memcpy(cooked->state.data, raw->state.data, cooked->state.num * sizeof (struct cc_timedataelt)); + cooked->state.time_offset = raw->state.time_offset; + return cooked; +} diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 57f80b8d..356794e0 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -268,4 +268,32 @@ cc_timedata_min(struct cc_timedata *d, double min_time, double max_time); int cc_timedata_max(struct cc_timedata *d, double min_time, double max_time); +int +cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time); + +int +cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time); + +double * +cc_low_pass(double *data, int data_len, double omega_pass, double omega_stop, double error); + +struct cc_perioddata * +cc_period_make(struct cc_timedata *td, double start_time, double stop_time); + +struct cc_perioddata * +cc_period_low_pass(struct cc_perioddata *raw, double omega_pass, double omega_stop, double error); + +struct cc_timedata * +cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), double a); + +struct cc_timedata * +cc_timedata_integrate(struct cc_timedata *d); + +struct cc_perioddata * +cc_perioddata_differentiate(struct cc_perioddata *i); + +struct cc_flightcooked * +cc_flight_cook(struct cc_flightraw *raw); + + #endif /* _CC_H_ */ diff --git a/ao-tools/lib/cephes.h b/ao-tools/lib/cephes.h new file mode 100644 index 00000000..f8ec264f --- /dev/null +++ b/ao-tools/lib/cephes.h @@ -0,0 +1,122 @@ +/* + * This file comes from the cephes math library, which was + * released under the GPLV2+ license as a part of the Debian labplot + * package (I've included the GPLV2 license reference here to make + * this clear) - Keith Packard + * + * Cephes Math Library Release 2.0: April, 1987 + * Copyright 1984, 1987 by Stephen L. Moshier + * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 + * + * 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. + */ +/* + * Prototypes of Cephes functions + */ + +#ifndef _CEPHES_H_ +#define _CEPHES_H_ + +/* Variable for error reporting. See mtherr.c. */ +extern int merror; + +#if 0 +extern int airy ( double x, double *ai, double *aip, double *bi, double *bip ); +extern double beta ( double a, double b ); +extern double lbeta ( double a, double b ); +extern double chdtrc ( double df, double x ); +extern double chdtr ( double df, double x ); +extern double chdtri ( double df, double y ); +extern double dawsn ( double xx ); +extern double ellie ( double phi, double m ); +extern double ellik ( double phi, double m ); +extern double ellpe ( double x ); +extern double ellpk ( double x ); +extern double expn ( int n, double x ); +extern double fac ( int i ); +extern double fdtrc ( int ia, int ib, double x ); +extern double fdtr ( int ia, int ib, double x ); +extern double fdtri ( int ia, int ib, double y ); +extern double frexp ( double x, int *pw2 ); +extern double ldexp ( double x, int pw2 ); +extern int fresnl ( double xxa, double *ssa, double *cca ); +extern double gdtr ( double a, double b, double x ); +extern double gdtrc ( double a, double b, double x ); +extern double hyp2f0 ( double a, double b, double x, int type, double *err ); +extern double hyp2f1 ( double a, double b, double c, double x ); +extern double hyperg ( double a, double b, double x ); +#endif +extern double i0 ( double x ); +extern double i0e ( double x ); +#if 0 +extern double i1 ( double x ); +extern double i1e ( double x ); +extern double iv ( double v, double x ); +extern double igamc ( double a, double x ); +extern double igam ( double a, double x ); +extern double igami ( double a, double y0_ ); +extern double incbet ( double aa, double bb, double xx ); +extern double incbi ( double aa, double bb, double yy0 ); +extern double jv ( double n, double x ); +extern double k0 ( double x ); +extern double k0e ( double x ); +extern double k1 ( double x ); +extern double k1e ( double x ); +extern double kn ( int nn, double x ); +extern int mtherr ( char *name, int code ); +extern double ndtr ( double a ); +extern double ndtri ( double y0_ ); +extern double pdtrc ( int k, double m ); +extern double pdtr ( int k, double m ); +extern double pdtri ( int k, double y ); +extern double psi ( double x ); +extern void revers ( double y[], double x[], int n ); +extern double true_gamma ( double x ); +extern double rgamma ( double x ); +extern int shichi ( double x, double *si, double *ci ); +extern int sici ( double x, double *si, double *ci ); +extern double spence ( double x ); +extern double stdtr ( int k, double t ); +extern double stdtri ( int k, double p ); +extern double onef2 ( double a, double b, double c, double x, double *err ); +extern double threef0 ( double a, double b, double c, double x, double *err ); +extern double struve ( double v, double x ); +extern double log1p ( double x ); +extern double expm1 ( double x ); +extern double cosm1 ( double x ); +extern double yv ( double v, double x ); +extern double zeta ( double x, double q ); +extern double zetac ( double x ); + +#endif +extern double chbevl ( double x, void *P, int n ); +#if 0 +extern double polevl ( double x, void *P, int n ); +extern double p1evl ( double x, void *P, int n ); + +/* polyn.c */ +extern void polini ( int maxdeg ); +extern void polprt ( double a[], int na, int d ); +extern void polclr ( double *a, int n ); +extern void polmov ( double *a, int na, double *b ); +extern void polmul ( double a[], int na, double b[], int nb, double c[] ); +extern void poladd ( double a[], int na, double b[], int nb, double c[] ); +extern void polsub ( double a[], int na, double b[], int nb, double c[] ); +extern int poldiv ( double a[], int na, double b[], int nb, double c[] ); +extern void polsbt ( double a[], int na, double b[], int nb, double c[] ); +extern double poleva ( double a[], int na, double x ); + +#endif + +#endif /* _CEPHES_H_ */ diff --git a/ao-tools/lib/chbevl.c b/ao-tools/lib/chbevl.c new file mode 100644 index 00000000..22892413 --- /dev/null +++ b/ao-tools/lib/chbevl.c @@ -0,0 +1,81 @@ +/* chbevl.c + * + * Evaluate Chebyshev series + * + * + * + * SYNOPSIS: + * + * int N; + * double x, y, coef[N], chebevl(); + * + * y = chbevl( x, coef, N ); + * + * + * + * DESCRIPTION: + * + * Evaluates the series + * + * N-1 + * - ' + * y = > coef[i] T (x/2) + * - i + * i=0 + * + * of Chebyshev polynomials Ti at argument x/2. + * + * Coefficients are stored in reverse order, i.e. the zero + * order term is last in the array. Note N is the number of + * coefficients, not the order. + * + * If coefficients are for the interval a to b, x must + * have been transformed to x -> 2(2x - b - a)/(b-a) before + * entering the routine. This maps x from (a, b) to (-1, 1), + * over which the Chebyshev polynomials are defined. + * + * If the coefficients are for the inverted interval, in + * which (a, b) is mapped to (1/b, 1/a), the transformation + * required is x -> 2(2ab/x - b - a)/(b-a). If b is infinity, + * this becomes x -> 4a/x - 1. + * + * + * + * SPEED: + * + * Taking advantage of the recurrence properties of the + * Chebyshev polynomials, the routine requires one more + * addition per loop than evaluating a nested polynomial of + * the same degree. + * + */ + /* chbevl.c */ + +/* +Cephes Math Library Release 2.0: April, 1987 +Copyright 1985, 1987 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + +#include "cephes.h" + +double chbevl(double x,void* array,int n ) +{ +double b0, b1, b2, *p; +int i; + +p = (double *) array; +b0 = *p++; +b1 = 0.0; +i = n - 1; + +do + { + b2 = b1; + b1 = b0; + b0 = x * b1 - b2 + *p++; + } +while( --i ); + +return( 0.5*(b0-b2) ); +} diff --git a/ao-tools/lib/cmath.h b/ao-tools/lib/cmath.h new file mode 100644 index 00000000..2751aecf --- /dev/null +++ b/ao-tools/lib/cmath.h @@ -0,0 +1,179 @@ +/* + * Grace - GRaphing, Advanced Computation and Exploration of data + * + * Home page: http://plasma-gate.weizmann.ac.il/Grace/ + * + * Copyright (c) 1991-1995 Paul J Turner, Portland, OR + * Copyright (c) 1996-2000 Grace Development Team + * + * Maintained by Evgeny Stambulchik + * + * + * All Rights Reserved + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* cmath.h - replacement for math.h or missing in libm functions */ + +#if defined(HAVE_MATH_H) +# include +#endif +#if defined(HAVE_FLOAT_H) +# include +#endif +#if defined(HAVE_IEEEFP_H) +# include +#endif + +#ifndef __GRACE_SOURCE_ + +#ifndef MACHEP +extern double MACHEP; +#endif + +#ifndef UFLOWTHRESH +extern double UFLOWTHRESH; +#endif + +#ifndef MAXNUM +extern double MAXNUM; +#endif + +#endif /* __GRACE_SOURCE_ */ + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#ifndef M_SQRT2 +# define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#endif + +#ifndef M_SQRT1_2 +# define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#endif + +#ifndef M_SQRT1_3 +# define M_SQRT1_3 0.57735026918962576451 /* 1/sqrt(3) */ +#endif + +#ifndef HAVE_HYPOT +# define hypot(x, y) sqrt((x)*(x) + (y)*(y)) +#endif + +extern double round ( double x ); +#ifndef HAVE_RINT +# define rint round +#else +# ifndef HAVE_RINT_DECL +extern double rint ( double x ); +# endif +#endif + +#ifndef HAVE_CBRT_DECL +extern double cbrt ( double x ); +#endif + +/* Cygnus gnuwin32 has the log2 macro */ +#ifdef log2 +# undef log2 +#endif + +#ifndef HAVE_LOG2_DECL +extern double log2 ( double x ); +#endif + +#ifndef HAVE_LGAMMA +extern int sgngam; +# define lgamma lgam +# define signgam sgngam +extern double lgam ( double x ); +#else +# ifndef HAVE_LGAMMA_DECL +extern double lgamma ( double x ); +# endif +# ifndef HAVE_SIGNGAM_DECL +extern int signgam; +# endif +# define lgam lgamma +# define sgngam signgam +#endif + +#ifndef HAVE_ACOSH_DECL +extern double acosh ( double x ); +#endif + +#ifndef HAVE_ASINH_DECL +extern double asinh ( double x ); +#endif + +#ifndef HAVE_ATANH_DECL +extern double atanh ( double x ); +#endif + +#ifndef HAVE_ERF_DECL +extern double erf ( double x ); +#endif + +#ifndef HAVE_ERFC_DECL +extern double erfc ( double x ); +#endif + +#ifndef HAVE_Y0_DECL +extern double y0 ( double x ); +#endif +#ifndef HAVE_Y1_DECL +extern double y1 ( double x ); +#endif +#ifndef HAVE_YN_DECL +extern double yn ( int n, double x ); +#endif +#ifndef HAVE_J0_DECL +extern double j0 ( double x ); +#endif +#ifndef HAVE_J1_DECL +extern double j1 ( double x ); +#endif +#ifndef HAVE_JN_DECL +extern double jn ( int n, double x ); +#endif + +/* isfinite is a macro */ +#ifdef isfinite +# define HAVE_ISFINITE_MACRO +#endif + +#ifndef HAVE_FINITE +# define finite isfinite +# if !defined(HAVE_ISFINITE_DECL) && !defined(HAVE_ISFINITE_MACRO) +extern int isfinite ( double x ); +# endif +#else +# ifndef HAVE_FINITE_DECL +extern int finite ( double x ); +# endif +#endif + +#ifndef HAVE_ISNAN_DECL +#ifdef __FreeBSD__ +# include +# if __FreeBSD_version < 500100 +extern int isnan ( double x ); +# endif +#endif +#else +extern int isnan ( double x ); +#endif diff --git a/ao-tools/lib/i0.c b/ao-tools/lib/i0.c new file mode 100644 index 00000000..6f7b5a57 --- /dev/null +++ b/ao-tools/lib/i0.c @@ -0,0 +1,414 @@ +/* + * This file comes from the cephes math library, which was + * released under the GPLV2+ license as a part of the Debian labplot + * package (I've included the GPLV2 license reference here to make + * this clear) - Keith Packard + * + * Cephes Math Library Release 2.0: April, 1987 + * Copyright 1984, 1987 by Stephen L. Moshier + * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 + * + * 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. + */ + +/* i0.c + * + * Modified Bessel function of order zero + * + * + * + * SYNOPSIS: + * + * double x, y, i0(); + * + * y = i0( x ); + * + * + * + * DESCRIPTION: + * + * Returns modified Bessel function of order zero of the + * argument. + * + * The function is defined as i0(x) = j0( ix ). + * + * The range is partitioned into the two intervals [0,8] and + * (8, infinity). Chebyshev polynomial expansions are employed + * in each interval. + * + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * DEC 0,30 6000 8.2e-17 1.9e-17 + * IEEE 0,30 30000 5.8e-16 1.4e-16 + * + */ + /* i0e.c + * + * Modified Bessel function of order zero, + * exponentially scaled + * + * + * + * SYNOPSIS: + * + * double x, y, i0e(); + * + * y = i0e( x ); + * + * + * + * DESCRIPTION: + * + * Returns exponentially scaled modified Bessel function + * of order zero of the argument. + * + * The function is defined as i0e(x) = exp(-|x|) j0( ix ). + * + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE 0,30 30000 5.4e-16 1.2e-16 + * See i0(). + * + */ + +/* i0.c */ + + +/* +Cephes Math Library Release 2.0: April, 1987 +Copyright 1984, 1987 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + +#include +#include "mconf.h" +#include "cephes.h" + +/* Chebyshev coefficients for exp(-x) I0(x) + * in the interval [0,8]. + * + * lim(x->0){ exp(-x) I0(x) } = 1. + */ + +#ifdef UNK +static double A[] = +{ +-4.41534164647933937950E-18, + 3.33079451882223809783E-17, +-2.43127984654795469359E-16, + 1.71539128555513303061E-15, +-1.16853328779934516808E-14, + 7.67618549860493561688E-14, +-4.85644678311192946090E-13, + 2.95505266312963983461E-12, +-1.72682629144155570723E-11, + 9.67580903537323691224E-11, +-5.18979560163526290666E-10, + 2.65982372468238665035E-9, +-1.30002500998624804212E-8, + 6.04699502254191894932E-8, +-2.67079385394061173391E-7, + 1.11738753912010371815E-6, +-4.41673835845875056359E-6, + 1.64484480707288970893E-5, +-5.75419501008210370398E-5, + 1.88502885095841655729E-4, +-5.76375574538582365885E-4, + 1.63947561694133579842E-3, +-4.32430999505057594430E-3, + 1.05464603945949983183E-2, +-2.37374148058994688156E-2, + 4.93052842396707084878E-2, +-9.49010970480476444210E-2, + 1.71620901522208775349E-1, +-3.04682672343198398683E-1, + 6.76795274409476084995E-1 +}; +#endif + +#ifdef DEC +static unsigned short A[] = { +0121642,0162671,0004646,0103567, +0022431,0115424,0135755,0026104, +0123214,0023533,0110365,0156635, +0023767,0033304,0117662,0172716, +0124522,0100426,0012277,0157531, +0025254,0155062,0054461,0030465, +0126010,0131143,0013560,0153604, +0026517,0170577,0006336,0114437, +0127227,0162253,0152243,0052734, +0027724,0142766,0061641,0160200, +0130416,0123760,0116564,0125262, +0031066,0144035,0021246,0054641, +0131537,0053664,0060131,0102530, +0032201,0155664,0165153,0020652, +0132617,0061434,0074423,0176145, +0033225,0174444,0136147,0122542, +0133624,0031576,0056453,0020470, +0034211,0175305,0172321,0041314, +0134561,0054462,0147040,0165315, +0035105,0124333,0120203,0162532, +0135427,0013750,0174257,0055221, +0035726,0161654,0050220,0100162, +0136215,0131361,0000325,0041110, +0036454,0145417,0117357,0017352, +0136702,0072367,0104415,0133574, +0037111,0172126,0072505,0014544, +0137302,0055601,0120550,0033523, +0037457,0136543,0136544,0043002, +0137633,0177536,0001276,0066150, +0040055,0041164,0100655,0010521 +}; +#endif + +#ifdef IBMPC +static unsigned short A[] = { +0xd0ef,0x2134,0x5cb7,0xbc54, +0xa589,0x977d,0x3362,0x3c83, +0xbbb4,0x721e,0x84eb,0xbcb1, +0x5eba,0x93f6,0xe6d8,0x3cde, +0xfbeb,0xc297,0x5022,0xbd0a, +0x2627,0x4b26,0x9b46,0x3d35, +0x1af0,0x62ee,0x164c,0xbd61, +0xd324,0xe19b,0xfe2f,0x3d89, +0x6abc,0x7a94,0xfc95,0xbdb2, +0x3c10,0xcc74,0x98be,0x3dda, +0x9556,0x13ae,0xd4fe,0xbe01, +0xcb34,0xa454,0xd903,0x3e26, +0x30ab,0x8c0b,0xeaf6,0xbe4b, +0x6435,0x9d4d,0x3b76,0x3e70, +0x7f8d,0x8f22,0xec63,0xbe91, +0xf4ac,0x978c,0xbf24,0x3eb2, +0x6427,0xcba5,0x866f,0xbed2, +0x2859,0xbe9a,0x3f58,0x3ef1, +0x1d5a,0x59c4,0x2b26,0xbf0e, +0x7cab,0x7410,0xb51b,0x3f28, +0xeb52,0x1f15,0xe2fd,0xbf42, +0x100e,0x8a12,0xdc75,0x3f5a, +0xa849,0x201a,0xb65e,0xbf71, +0xe3dd,0xf3dd,0x9961,0x3f85, +0xb6f0,0xf121,0x4e9e,0xbf98, +0xa32d,0xcea8,0x3e8a,0x3fa9, +0x06ea,0x342d,0x4b70,0xbfb8, +0x88c0,0x77ac,0xf7ac,0x3fc5, +0xcd8d,0xc057,0x7feb,0xbfd3, +0xa22a,0x9035,0xa84e,0x3fe5, +}; +#endif + +#ifdef MIEEE +static unsigned short A[] = { +0xbc54,0x5cb7,0x2134,0xd0ef, +0x3c83,0x3362,0x977d,0xa589, +0xbcb1,0x84eb,0x721e,0xbbb4, +0x3cde,0xe6d8,0x93f6,0x5eba, +0xbd0a,0x5022,0xc297,0xfbeb, +0x3d35,0x9b46,0x4b26,0x2627, +0xbd61,0x164c,0x62ee,0x1af0, +0x3d89,0xfe2f,0xe19b,0xd324, +0xbdb2,0xfc95,0x7a94,0x6abc, +0x3dda,0x98be,0xcc74,0x3c10, +0xbe01,0xd4fe,0x13ae,0x9556, +0x3e26,0xd903,0xa454,0xcb34, +0xbe4b,0xeaf6,0x8c0b,0x30ab, +0x3e70,0x3b76,0x9d4d,0x6435, +0xbe91,0xec63,0x8f22,0x7f8d, +0x3eb2,0xbf24,0x978c,0xf4ac, +0xbed2,0x866f,0xcba5,0x6427, +0x3ef1,0x3f58,0xbe9a,0x2859, +0xbf0e,0x2b26,0x59c4,0x1d5a, +0x3f28,0xb51b,0x7410,0x7cab, +0xbf42,0xe2fd,0x1f15,0xeb52, +0x3f5a,0xdc75,0x8a12,0x100e, +0xbf71,0xb65e,0x201a,0xa849, +0x3f85,0x9961,0xf3dd,0xe3dd, +0xbf98,0x4e9e,0xf121,0xb6f0, +0x3fa9,0x3e8a,0xcea8,0xa32d, +0xbfb8,0x4b70,0x342d,0x06ea, +0x3fc5,0xf7ac,0x77ac,0x88c0, +0xbfd3,0x7feb,0xc057,0xcd8d, +0x3fe5,0xa84e,0x9035,0xa22a +}; +#endif + + +/* Chebyshev coefficients for exp(-x) sqrt(x) I0(x) + * in the inverted interval [8,infinity]. + * + * lim(x->inf){ exp(-x) sqrt(x) I0(x) } = 1/sqrt(2pi). + */ + +#ifdef UNK +static double B[] = +{ +-7.23318048787475395456E-18, +-4.83050448594418207126E-18, + 4.46562142029675999901E-17, + 3.46122286769746109310E-17, +-2.82762398051658348494E-16, +-3.42548561967721913462E-16, + 1.77256013305652638360E-15, + 3.81168066935262242075E-15, +-9.55484669882830764870E-15, +-4.15056934728722208663E-14, + 1.54008621752140982691E-14, + 3.85277838274214270114E-13, + 7.18012445138366623367E-13, +-1.79417853150680611778E-12, +-1.32158118404477131188E-11, +-3.14991652796324136454E-11, + 1.18891471078464383424E-11, + 4.94060238822496958910E-10, + 3.39623202570838634515E-9, + 2.26666899049817806459E-8, + 2.04891858946906374183E-7, + 2.89137052083475648297E-6, + 6.88975834691682398426E-5, + 3.36911647825569408990E-3, + 8.04490411014108831608E-1 +}; +#endif + +#ifdef DEC +static unsigned short B[] = { +0122005,0066672,0123124,0054311, +0121662,0033323,0030214,0104602, +0022515,0170300,0113314,0020413, +0022437,0117350,0035402,0007146, +0123243,0000135,0057220,0177435, +0123305,0073476,0144106,0170702, +0023777,0071755,0017527,0154373, +0024211,0052214,0102247,0033270, +0124454,0017763,0171453,0012322, +0125072,0166316,0075505,0154616, +0024612,0133770,0065376,0025045, +0025730,0162143,0056036,0001632, +0026112,0015077,0150464,0063542, +0126374,0101030,0014274,0065457, +0127150,0077271,0125763,0157617, +0127412,0104350,0040713,0120445, +0027121,0023765,0057500,0001165, +0030407,0147146,0003643,0075644, +0031151,0061445,0044422,0156065, +0031702,0132224,0003266,0125551, +0032534,0000076,0147153,0005555, +0033502,0004536,0004016,0026055, +0034620,0076433,0142314,0171215, +0036134,0146145,0013454,0101104, +0040115,0171425,0062500,0047133 +}; +#endif + +#ifdef IBMPC +static unsigned short B[] = { +0x8b19,0x54ca,0xadb7,0xbc60, +0x9130,0x6611,0x46da,0xbc56, +0x8421,0x12d9,0xbe18,0x3c89, +0x41cd,0x0760,0xf3dd,0x3c83, +0x1fe4,0xabd2,0x600b,0xbcb4, +0xde38,0xd908,0xaee7,0xbcb8, +0xfb1f,0xa3ea,0xee7d,0x3cdf, +0xe6d7,0x9094,0x2a91,0x3cf1, +0x629a,0x7e65,0x83fe,0xbd05, +0xbb32,0xcf68,0x5d99,0xbd27, +0xc545,0x0d5f,0x56ff,0x3d11, +0xc073,0x6b83,0x1c8c,0x3d5b, +0x8cec,0xfa26,0x4347,0x3d69, +0x8d66,0x0317,0x9043,0xbd7f, +0x7bf2,0x357e,0x0fd7,0xbdad, +0x7425,0x0839,0x511d,0xbdc1, +0x004f,0xabe8,0x24fe,0x3daa, +0x6f75,0xc0f4,0xf9cc,0x3e00, +0x5b87,0xa922,0x2c64,0x3e2d, +0xd56d,0x80d6,0x5692,0x3e58, +0x616e,0xd9cd,0x8007,0x3e8b, +0xc586,0xc101,0x412b,0x3ec8, +0x9e52,0x7899,0x0fa3,0x3f12, +0x9049,0xa2e5,0x998c,0x3f6b, +0x09cb,0xaca8,0xbe62,0x3fe9 +}; +#endif + +#ifdef MIEEE +static unsigned short B[] = { +0xbc60,0xadb7,0x54ca,0x8b19, +0xbc56,0x46da,0x6611,0x9130, +0x3c89,0xbe18,0x12d9,0x8421, +0x3c83,0xf3dd,0x0760,0x41cd, +0xbcb4,0x600b,0xabd2,0x1fe4, +0xbcb8,0xaee7,0xd908,0xde38, +0x3cdf,0xee7d,0xa3ea,0xfb1f, +0x3cf1,0x2a91,0x9094,0xe6d7, +0xbd05,0x83fe,0x7e65,0x629a, +0xbd27,0x5d99,0xcf68,0xbb32, +0x3d11,0x56ff,0x0d5f,0xc545, +0x3d5b,0x1c8c,0x6b83,0xc073, +0x3d69,0x4347,0xfa26,0x8cec, +0xbd7f,0x9043,0x0317,0x8d66, +0xbdad,0x0fd7,0x357e,0x7bf2, +0xbdc1,0x511d,0x0839,0x7425, +0x3daa,0x24fe,0xabe8,0x004f, +0x3e00,0xf9cc,0xc0f4,0x6f75, +0x3e2d,0x2c64,0xa922,0x5b87, +0x3e58,0x5692,0x80d6,0xd56d, +0x3e8b,0x8007,0xd9cd,0x616e, +0x3ec8,0x412b,0xc101,0xc586, +0x3f12,0x0fa3,0x7899,0x9e52, +0x3f6b,0x998c,0xa2e5,0x9049, +0x3fe9,0xbe62,0xaca8,0x09cb +}; +#endif + +double i0(double x) +{ +double y; + +if( x < 0 ) + x = -x; +if( x <= 8.0 ) + { + y = (x/2.0) - 2.0; + return( exp(x) * chbevl( y, A, 30 ) ); + } + +return( exp(x) * chbevl( 32.0/x - 2.0, B, 25 ) / sqrt(x) ); + +} + + + + +double i0e(double x ) +{ +double y; + +if( x < 0 ) + x = -x; +if( x <= 8.0 ) + { + y = (x/2.0) - 2.0; + return( chbevl( y, A, 30 ) ); + } + +return( chbevl( 32.0/x - 2.0, B, 25 ) / sqrt(x) ); + +} diff --git a/ao-tools/lib/mconf.h b/ao-tools/lib/mconf.h new file mode 100644 index 00000000..af1ebb51 --- /dev/null +++ b/ao-tools/lib/mconf.h @@ -0,0 +1,211 @@ +/* + * This file comes from the cephes math library, which was + * released under the GPLV2+ license as a part of the Debian labplot + * package (I've included the GPLV2 license reference here to make + * this clear) - Keith Packard + * + * Cephes Math Library Release 2.0: April, 1987 + * Copyright 1984, 1987 by Stephen L. Moshier + * Direct inquiries to 30 Frost Street, Cambridge, MA 02140 + * + * 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. + */ +/* mconf.h + * + * Common include file for math routines + * + * + * + * SYNOPSIS: + * + * #include "mconf.h" + * + * + * + * DESCRIPTION: + * + * This file contains definitions for error codes that are + * passed to the common error handling routine mtherr() + * (which see). + * + * The file also includes a conditional assembly definition + * for the type of computer arithmetic (IEEE, DEC, Motorola + * IEEE, or UNKnown). + * + * For Digital Equipment PDP-11 and VAX computers, certain + * IBM systems, and others that use numbers with a 56-bit + * significand, the symbol DEC should be defined. In this + * mode, most floating point constants are given as arrays + * of octal integers to eliminate decimal to binary conversion + * errors that might be introduced by the compiler. + * + * For little-endian computers, such as IBM PC, that follow the + * IEEE Standard for Binary Floating Point Arithmetic (ANSI/IEEE + * Std 754-1985), the symbol IBMPC should be defined. These + * numbers have 53-bit significands. In this mode, constants + * are provided as arrays of hexadecimal 16 bit integers. + * + * Big-endian IEEE format is denoted MIEEE. On some RISC + * systems such as Sun SPARC, double precision constants + * must be stored on 8-byte address boundaries. Since integer + * arrays may be aligned differently, the MIEEE configuration + * may fail on such machines. + * + * To accommodate other types of computer arithmetic, all + * constants are also provided in a normal decimal radix + * which one can hope are correctly converted to a suitable + * format by the available C language compiler. To invoke + * this mode, define the symbol UNK. + * + * An important difference among these modes is a predefined + * set of machine arithmetic constants for each. The numbers + * MACHEP (the machine roundoff error), MAXNUM (largest number + * represented), and several other parameters are preset by + * the configuration symbol. Check the file const.c to + * ensure that these values are correct for your computer. + * + * Configurations NANS, INFINITIES, MINUSZERO, and DENORMAL + * may fail on many systems. Verify that they are supposed + * to work on your computer. + */ + +/* +Cephes Math Library Release 2.3: June, 1995 +Copyright 1984, 1987, 1989, 1995 by Stephen L. Moshier + +Adjusted for use with ACE/gr by Evgeny Stambulchik, October 1997 +*/ + +#define __GRACE_SOURCE_ + +#include "cmath.h" + +/* Type of computer arithmetic */ +/* In ACE/gr, defined as a compiler directive - no need to define here */ + +/* PDP-11, Pro350, VAX: + */ +#if defined(HAVE_DEC_FPU) +# define DEC 1 +#endif + +/* Intel IEEE, low order words come first: + */ +#if defined(HAVE_LIEEE_FPU) +# define IBMPC 1 +#endif + +/* Motorola IEEE, high order words come first + * (Sun 680x0 workstation): + */ +#if defined(HAVE_BIEEE_FPU) +# define MIEEE 1 +#endif + +/* UNKnown arithmetic, invokes coefficients given in + * normal decimal format. Beware of range boundary + * problems (MACHEP, MAXLOG, etc. in const.c) and + * roundoff problems in pow.c: + * (Sun SPARCstation) + */ + +#if (!defined (DEC) && !defined (IBMPC) && !defined (MIEEE)) +# define UNK 1 +#endif + +/* Define this `volatile' if your compiler thinks + * that floating point arithmetic obeys the associative + * and distributive laws. It will defeat some optimizations + * (but probably not enough of them). + * + * #define VOLATILE volatile + */ + +#ifndef VOLATILE +# define VOLATILE +#endif + +#ifdef PI +# undef PI +#endif + +#ifdef NAN +# undef NAN +#endif + +#ifdef INFINITY +# undef INFINITY +#endif + +/* Constant definitions for math error conditions + */ + +#if defined(DOMAIN) +# undef DOMAIN +#endif +#define DOMAIN 1 /* argument domain error */ + +#if defined(SING) +# undef SING +#endif +#define SING 2 /* argument singularity */ + +#if defined(OVERFLOW) +# undef OVERFLOW +#endif +#define OVERFLOW 3 /* overflow range error */ + +#if defined(UNDERFLOW) +# undef UNDERFLOW +#endif +#define UNDERFLOW 4 /* underflow range error */ + +#if defined(TLOSS) +# undef TLOSS +#endif +#define TLOSS 5 /* total loss of precision */ + +#if defined(PLOSS) +# undef PLOSS +#endif +#define PLOSS 6 /* partial loss of precision */ + +#if defined(EDOM) +# undef EDOM +#endif +#define EDOM 33 + +#if defined(ERANGE) +# undef ERANGE +#endif +#define ERANGE 34 + +#if !defined (UNK) + /* Define to support tiny denormal numbers, else undefine. */ +# define DENORMAL 1 + + /* Define to ask for infinity support, else undefine. */ +# define INFINITIES 1 + + /* Define to ask for support of numbers that are Not-a-Number, + else undefine. This may automatically define INFINITIES in some files. */ +# define NANS 1 + + /* Define to distinguish between -0.0 and +0.0. */ +# define MINUSZERO 1 +#endif + +/* Define 1 for ANSI C atan2() function + See atan.c and clog.c. */ +#define ANSIC 1 -- cgit v1.2.3 From 45e2938121411d1fc9b3aec3fdeaaeb3c90db5ed Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 14:02:14 -0600 Subject: update changelogs for Debian build --- ChangeLog | 25 +++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/ChangeLog b/ChangeLog index cd539832..59ada262 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +commit d42ebf0661ecf15455e5051de1e16ae66f8dd857 +Merge: 384dbe9 7a19aac +Author: Bdale Garbee +Date: Sun Sep 6 14:02:09 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 7a19aac5e881e635962a64fff73027ca2143b96f +Author: Keith Packard +Date: Sun Sep 6 12:51:48 2009 -0700 + + Add DSP code to filter data, allowing for integration/differentiation + + This adds the computation of speed from both accelerometer and + barometer measurements and then presents a periodic flight profile + using filtered data as a detailed flight record. + + Signed-off-by: Keith Packard + +commit 384dbe9fc7fa8e4e5dceec5e150f0f1d3383bbdc +Author: Bdale Garbee +Date: Sun Sep 6 10:40:06 2009 -0600 + + update changelogs for Debian build + commit 35c54b3a278fa9bc2bc7f4b5ee04866697c93ba0 Merge: 4f8eff7 6d018ab Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index b697e0b1..d87f20c5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+36+gd42ebf0) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 14:02:14 -0600 + altos (0.5+33+g35c54b3) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From e35e485ffe6b26034788ab295121bc2693b7eec1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 13:04:31 -0700 Subject: Initialize summary_name and detail_name so stuff appears on stdout. Uninitialized variables lead to mysterious results. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index c5814c93..6683c67c 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -205,7 +205,7 @@ main (int argc, char **argv) int c; int serial; char *s; - char *summary_name, *detail_name; + char *summary_name = NULL, *detail_name = NULL; while ((c = getopt_long(argc, argv, "S:D:", options, NULL)) != -1) { switch (c) { -- cgit v1.2.3 From 773c4ffbc1d2e02eb02cfa543a077a408986da30 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 14:05:55 -0600 Subject: update changelogs for Debian build --- ChangeLog | 23 +++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 29 insertions(+) diff --git a/ChangeLog b/ChangeLog index 59ada262..e78fef87 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +commit 45ede4a4b203ef9da5bf05c49cb9c5a2e6382ec5 +Merge: 45e2938 e35e485 +Author: Bdale Garbee +Date: Sun Sep 6 14:05:51 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit e35e485ffe6b26034788ab295121bc2693b7eec1 +Author: Keith Packard +Date: Sun Sep 6 13:04:31 2009 -0700 + + Initialize summary_name and detail_name so stuff appears on stdout. + + Uninitialized variables lead to mysterious results. + + Signed-off-by: Keith Packard + +commit 45e2938121411d1fc9b3aec3fdeaaeb3c90db5ed +Author: Bdale Garbee +Date: Sun Sep 6 14:02:14 2009 -0600 + + update changelogs for Debian build + commit d42ebf0661ecf15455e5051de1e16ae66f8dd857 Merge: 384dbe9 7a19aac Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index d87f20c5..3425cd55 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+39+g45ede4a) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 14:05:55 -0600 + altos (0.5+36+gd42ebf0) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 73f4a57239f770aff603b961169c0e2cfe2c276b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 13:08:54 -0700 Subject: Use pressure speed for drogue and beyond states. Fix differentiation time. Drogue state should always use pressure speeds. Differentiation code was using centi-seconds instead of seconds. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 2 +- ao-tools/lib/cc-integrate.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 6683c67c..0c632c34 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -128,7 +128,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) } if (cooked) { - if (state_start < apogee) { + if (state < ao_flight_drogue) { speed_i = cc_perioddata_max(&cooked->accel_speed, state_start, state_stop); if (speed_i >= 0) speed = cooked->accel_speed.data[speed_i]; diff --git a/ao-tools/lib/cc-integrate.c b/ao-tools/lib/cc-integrate.c index 08ca295c..f9793dcd 100644 --- a/ao-tools/lib/cc-integrate.c +++ b/ao-tools/lib/cc-integrate.c @@ -72,7 +72,7 @@ cc_perioddata_differentiate(struct cc_perioddata *i) d->step = i->step; d->data = calloc (d->num, sizeof(double)); for (n = 1; n < d->num; n++) - d->data[n] = (i->data[n] - i->data[n-1]) / i->step; + d->data[n] = (i->data[n] - i->data[n-1]) / (i->step / 100.0); d->data[0] = d->data[1]; return d; } -- cgit v1.2.3 From d0eac989b1ffc8ae30ba12da403eb4bf1ad42d6b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 13:15:10 -0700 Subject: Don't look at NULL strings (summary_name) Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 0c632c34..c1e4d800 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -230,7 +230,7 @@ main (int argc, char **argv) } } if (detail_name) { - if (!strcmp (summary_name, detail_name)) + if (summary_name && !strcmp (summary_name, detail_name)) detail_file = summary_file; else { detail_file = fopen(detail_name, "w"); -- cgit v1.2.3 From 0fc344dfc031a8b1eef7cc40efb1d5ba7782269d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 14:15:57 -0600 Subject: update changelogs for Debian build --- ChangeLog | 33 +++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/ChangeLog b/ChangeLog index e78fef87..bd7e99fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +commit 4b0de757874c0ecaf38e3dfd3beefc398150e3d5 +Merge: 773c4ff d0eac98 +Author: Bdale Garbee +Date: Sun Sep 6 14:15:53 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit d0eac989b1ffc8ae30ba12da403eb4bf1ad42d6b +Author: Keith Packard +Date: Sun Sep 6 13:15:10 2009 -0700 + + Don't look at NULL strings (summary_name) + + Signed-off-by: Keith Packard + +commit 73f4a57239f770aff603b961169c0e2cfe2c276b +Author: Keith Packard +Date: Sun Sep 6 13:08:54 2009 -0700 + + Use pressure speed for drogue and beyond states. Fix differentiation time. + + Drogue state should always use pressure speeds. + + Differentiation code was using centi-seconds instead of seconds. + + Signed-off-by: Keith Packard + +commit 773c4ffbc1d2e02eb02cfa543a077a408986da30 +Author: Bdale Garbee +Date: Sun Sep 6 14:05:55 2009 -0600 + + update changelogs for Debian build + commit 45ede4a4b203ef9da5bf05c49cb9c5a2e6382ec5 Merge: 45e2938 e35e485 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 3425cd55..11751700 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+43+g4b0de75) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 14:15:57 -0600 + altos (0.5+39+g45ede4a) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 32d3536706324808df6cd02248a236302b831571 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 16:24:35 -0700 Subject: Add plots to ao-postflight using the plplot library It's not perfect, but it generates .svg plot output. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/Makefile.am | 4 +- ao-tools/ao-postflight/ao-postflight.c | 132 +++++++++++++++++++++---- ao-tools/lib/cc-analyse.c | 174 +++++++++++++++++++++++++++++---- ao-tools/lib/cc-process.c | 18 ++++ ao-tools/lib/cc.h | 29 ++++++ configure.ac | 2 + 6 files changed, 318 insertions(+), 41 deletions(-) diff --git a/ao-tools/ao-postflight/Makefile.am b/ao-tools/ao-postflight/Makefile.am index 301ac454..589d164a 100644 --- a/ao-tools/ao-postflight/Makefile.am +++ b/ao-tools/ao-postflight/Makefile.am @@ -1,11 +1,11 @@ bin_PROGRAMS=ao-postflight -AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) $(PLPLOT_CFLAGS) AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a ao_postflight_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) -ao_postflight_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) $(GNOME_LIBS) +ao_postflight_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) $(GNOME_LIBS) $(PLPLOT_LIBS) ao_postflight_SOURCES = ao-postflight.c diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index c1e4d800..bc6638e9 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -24,8 +24,7 @@ #include #include "cc-usb.h" #include "cc.h" - -#define NUM_BLOCK 512 +#include static const char *state_names[] = { "startup", @@ -40,12 +39,75 @@ static const char *state_names[] = { "invalid" }; -void -analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) +static void +plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label, + double min_time, double max_time) +{ + double *times; + double ymin, ymax; + int ymin_i, ymax_i; + int i; + int start, stop; + + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) + return; + + times = calloc(stop - start + 1, sizeof (double)); + for (i = start; i <= stop; i++) + times[i-start] = i * d->step / 100.0; + + ymin_i = cc_perioddata_min(d, min_time, max_time); + ymax_i = cc_perioddata_max(d, min_time, max_time); + ymin = d->data[ymin_i]; + ymax = d->data[ymax_i]; + plenv(times[0], times[stop-start], + ymin, ymax, 0, 2); + plcol0(1); + pllab("Time", axis_label, plot_label); + plline(stop - start + 1, times, d->data + start); +} + +static struct cc_perioddata * +merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split_time) +{ + int i; + struct cc_perioddata *pd; + int num; + double start_time, stop_time; + double t; + + pd = calloc(1, sizeof (struct cc_perioddata)); + start_time = first->start; + stop_time = last->start + last->step * last->num; + num = (stop_time - start_time) / first->step; + pd->num = num; + pd->data = calloc(num, sizeof (double)); + pd->start = first->start; + pd->step = first->step; + for (i = 0; i < num; i++) { + t = pd->start + i * pd->step; + if (t <= split_time) { + pd->data[i] = first->data[i]; + } else { + int j; + + j = (t - last->start) / last->step; + if (j < 0 || j >= last->num) + pd->data[i] = 0; + else + pd->data[i] = last->data[j]; + } + } + return pd; +} + +static void +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, char *plot_name) { double height; double accel; double speed; + double avg_speed; double boost_start, boost_stop; double min_pres; int i; @@ -129,18 +191,24 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) if (cooked) { if (state < ao_flight_drogue) { - speed_i = cc_perioddata_max(&cooked->accel_speed, state_start, state_stop); + speed_i = cc_perioddata_max_mag(&cooked->accel_speed, state_start, state_stop); if (speed_i >= 0) speed = cooked->accel_speed.data[speed_i]; + avg_speed = cc_perioddata_average(&cooked->accel_speed, state_start, state_stop); } else { - speed_i = cc_perioddata_max(&cooked->pres_speed, state_start, state_stop); + speed_i = cc_perioddata_max_mag(&cooked->pres_speed, state_start, state_stop); if (speed_i >= 0) speed = cooked->pres_speed.data[speed_i]; + avg_speed = cc_perioddata_average(&cooked->pres_speed, state_start, state_stop); } if (speed_i >= 0) + { fprintf(summary_file, "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n", speed, speed * 100 / 2.4 / 12.0, (cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0); + fprintf(summary_file, "\tAvg speed: %9.2fm/s %9.2fft/s\n", + avg_speed, avg_speed * 100 / 2.4 / 12.0); + } } pres_i = cc_timedata_min(&f->pres, state_start, state_stop); if (pres_i >= 0) @@ -154,16 +222,10 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) } } if (cooked && detail_file) { - double apogee_time; double max_height = 0; int i; + double *times; - for (i = 0; i < cooked->pres_pos.num; i++) { - if (cooked->pres_pos.data[i] > max_height) { - max_height = cooked->pres_pos.data[i]; - apogee_time = cooked->pres_pos.start + cooked->pres_pos.step * i; - } - } fprintf(detail_file, "%9s %9s %9s %9s\n", "time", "height", "speed", "accel"); for (i = 0; i < cooked->pres_pos.num; i++) { @@ -171,7 +233,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) double accel = cooked->accel_accel.data[i]; double pos = cooked->pres_pos.data[i]; double speed; - if (cooked->pres_pos.start + cooked->pres_pos.step * i < apogee_time) + if (cooked->pres_pos.start + cooked->pres_pos.step * i < apogee) speed = cooked->accel_speed.data[i]; else speed = cooked->pres_speed.data[i]; @@ -179,17 +241,41 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file) time, pos, speed, accel); } } + if (cooked && plot_name) { + struct cc_perioddata *speed; + plsdev("svgcairo"); + plsfnam(plot_name); +#define PLOT_DPI 96 + plspage(PLOT_DPI, PLOT_DPI, 8 * PLOT_DPI, 8 * PLOT_DPI, 0, 0); + plscolbg(0xff, 0xff, 0xff); + plscol0(1,0,0,0); + plstar(2, 3); + speed = merge_data(&cooked->accel_speed, &cooked->pres_speed, apogee); + + plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10); + plot_perioddata(&cooked->pres_pos, "meters", "Height", boost_start, apogee); + plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10); + plot_perioddata(speed, "meters/second", "Speed", boost_start, apogee); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", boost_start, apogee); + free(speed->data); + free(speed); + plend(); + } + if (cooked) + cc_flightcooked_free(cooked); } static const struct option options[] = { - { .name = "summary", .has_arg = 1, .val = 'S' }, - { .name = "detail", .has_arg = 1, .val = 'D' }, + { .name = "summary", .has_arg = 1, .val = 's' }, + { .name = "detail", .has_arg = 1, .val = 'd' }, + { .name = "plot", .has_arg = 1, .val = 'p' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--summary=] [--detail=] [--detail=] {flight-log} ...\n", program); exit(1); } @@ -206,15 +292,19 @@ main (int argc, char **argv) int serial; char *s; char *summary_name = NULL, *detail_name = NULL; + char *plot_name = NULL; - while ((c = getopt_long(argc, argv, "S:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "s:d:p:", options, NULL)) != -1) { switch (c) { - case 'S': + case 's': summary_name = optarg; break; - case 'D': + case 'd': detail_name = optarg; break; + case 'p': + plot_name = optarg; + break; default: usage(argv[0]); break; @@ -260,7 +350,7 @@ main (int argc, char **argv) } if (!raw->serial) raw->serial = serial; - analyse_flight(raw, summary_file, detail_file); + analyse_flight(raw, summary_file, detail_file, plot_name); cc_flightraw_free(raw); } return ret; diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index 0e020115..cdb16f02 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -38,6 +38,26 @@ cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) return min_i; } +int +cc_timedata_min_mag(struct cc_timedata *d, double min_time, double max_time) +{ + int i; + int set = 0; + int min_i = -1; + double min; + + if (d->num == 0) + return -1; + for (i = 0; i < d->num; i++) + if (min_time <= d->data[i].time && d->data[i].time <= max_time) + if (!set || fabs(d->data[i].value) < min) { + min_i = i; + min = fabs(d->data[i].value); + set = 1; + } + return min_i; +} + int cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) { @@ -58,23 +78,81 @@ cc_timedata_max(struct cc_timedata *d, double min_time, double max_time) return max_i; } +int +cc_timedata_max_mag(struct cc_timedata *d, double min_time, double max_time) +{ + int i; + double max; + int max_i = -1; + int set = 0; + + if (d->num == 0) + return -1; + for (i = 0; i < d->num; i++) + if (min_time <= d->data[i].time && d->data[i].time <= max_time) + if (!set || fabs(d->data[i].value) > max) { + max_i = i; + max = fabs(d->data[i].value); + set = 1; + } + return max_i; +} + +double +cc_timedata_average(struct cc_timedata *td, double start_time, double stop_time) +{ + int i; + double prev_time; + double next_time; + double interval; + double sum = 0.0; + double period = 0.0; + + prev_time = start_time; + for (i = 0; i < td->num; i++) { + if (start_time <= td->data[i].time && td->data[i].time <= stop_time) { + if (i < td->num - 1 && td->data[i+1].time < stop_time) + next_time = (td->data[i].time + td->data[i+1].time) / 2.0; + else + next_time = stop_time; + interval = next_time - prev_time; + sum += td->data[i].value * interval; + period += interval; + prev_time = next_time; + } + } + return sum / period; +} + +int +cc_perioddata_limits(struct cc_perioddata *d, double min_time, double max_time, int *start, int *stop) +{ + double start_d, stop_d; + + if (d->num == 0) + return 0; + start_d = ceil((min_time - d->start) / d->step); + if (start_d < 0) + start_d = 0; + stop_d = floor((max_time - d->start) / d->step); + if (stop_d >= d->num) + stop_d = d->num - 1; + if (stop_d < start_d) + return 0; + *start = (int) start_d; + *stop = (int) stop_d; + return 1; +} + int cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time) { - int start, stop; int i; double min; int min_i; + int start, stop; - if (d->num == 0) - return -1; - start = (int) ceil((min_time - d->start) / d->step); - if (start < 0) - start = 0; - stop = (int) floor((max_time - d->start) / d->step); - if (stop >= d->num) - stop = d->num - 1; - if (stop < start) + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) return -1; min = d->data[start]; min_i = start; @@ -86,6 +164,26 @@ cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time) return min_i; } +int +cc_perioddata_min_mag(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double min; + int min_i; + + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) + return -1; + min = d->data[start]; + min_i = start; + for (i = start + 1; i <= stop; i++) + if (fabs(d->data[i]) < min) { + min = fabs(d->data[i]); + min_i = i; + } + return min_i; +} + int cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time) { @@ -94,15 +192,27 @@ cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time) double max; int max_i; - if (d->num == 0) + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) return -1; - start = (int) ceil((min_time - d->start) / d->step); - if (start < 0) - start = 0; - stop = (int) floor((max_time - d->start) / d->step); - if (stop >= d->num) - stop = d->num - 1; - if (stop < start) + max = d->data[start]; + max_i = start; + for (i = start + 1; i <= stop; i++) + if (d->data[i] > max) { + max = d->data[i]; + max_i = i; + } + return max_i; +} + +int +cc_perioddata_max_mag(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double max; + int max_i; + + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) return -1; max = d->data[start]; max_i = start; @@ -113,3 +223,31 @@ cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time) } return max_i; } + +double +cc_perioddata_average(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double sum = 0.0; + + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) + return 0.0; + for (i = start; i <= stop; i++) + sum += d->data[i]; + return sum / (stop - start + 1); +} + +double +cc_perioddata_average_mag(struct cc_perioddata *d, double min_time, double max_time) +{ + int start, stop; + int i; + double sum = 0.0; + + if (!cc_perioddata_limits(d, min_time, max_time, &start, &stop)) + return 0.0; + for (i = start; i <= stop; i++) + sum += fabs(d->data[i]); + return sum / (stop - start + 1); +} diff --git a/ao-tools/lib/cc-process.c b/ao-tools/lib/cc-process.c index e906b635..469ad2f2 100644 --- a/ao-tools/lib/cc-process.c +++ b/ao-tools/lib/cc-process.c @@ -138,3 +138,21 @@ cc_flight_cook(struct cc_flightraw *raw) cooked->state.time_offset = raw->state.time_offset; return cooked; } + +#define if_free(x) ((x) ? free(x) : (void) 0) + +void +cc_flightcooked_free(struct cc_flightcooked *cooked) +{ + if_free(cooked->accel_accel.data); + if_free(cooked->accel_speed.data); + if_free(cooked->accel_pos.data); + if_free(cooked->pres_pos.data); + if_free(cooked->pres_speed.data); + if_free(cooked->pres_accel.data); + if_free(cooked->gps_lat.data); + if_free(cooked->gps_lon.data); + if_free(cooked->gps_alt.data); + if_free(cooked->state.data); + free(cooked); +} diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 356794e0..4e9aadc4 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -265,15 +265,42 @@ cc_great_circle (double start_lat, double start_lon, int cc_timedata_min(struct cc_timedata *d, double min_time, double max_time); +int +cc_timedata_min_mag(struct cc_timedata *d, double min_time, double max_time); + int cc_timedata_max(struct cc_timedata *d, double min_time, double max_time); +int +cc_timedata_max_mag(struct cc_timedata *d, double min_time, double max_time); + +double +cc_timedata_average(struct cc_timedata *d, double min_time, double max_time); + +double +cc_timedata_average_mag(struct cc_timedata *d, double min_time, double max_time); + +int +cc_perioddata_limits(struct cc_perioddata *d, double min_time, double max_time, int *start, int *stop); + int cc_perioddata_min(struct cc_perioddata *d, double min_time, double max_time); +int +cc_perioddata_min_mag(struct cc_perioddata *d, double min_time, double max_time); + int cc_perioddata_max(struct cc_perioddata *d, double min_time, double max_time); +int +cc_perioddata_max_mag(struct cc_perioddata *d, double min_time, double max_time); + +double +cc_perioddata_average(struct cc_perioddata *d, double min_time, double max_time); + +double +cc_perioddata_average_mag(struct cc_perioddata *d, double min_time, double max_time); + double * cc_low_pass(double *data, int data_len, double omega_pass, double omega_stop, double error); @@ -295,5 +322,7 @@ cc_perioddata_differentiate(struct cc_perioddata *i); struct cc_flightcooked * cc_flight_cook(struct cc_flightraw *raw); +void +cc_flightcooked_free(struct cc_flightcooked *cooked); #endif /* _CC_H_ */ diff --git a/configure.ac b/configure.ac index c668df04..6265c34e 100644 --- a/configure.ac +++ b/configure.ac @@ -71,6 +71,8 @@ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) PKG_CHECK_MODULES([ALSA], [alsa]) +PKG_CHECK_MODULES([PLPLOT], [plplotd-gnome2]) + AC_OUTPUT([ Makefile ao-tools/Makefile -- cgit v1.2.3 From 2e6686b1e183c66188ea447b8a54e4c29402443b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 16:45:47 -0700 Subject: Use plplotd instead of plplotd-gnome2 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 6265c34e..77699fba 100644 --- a/configure.ac +++ b/configure.ac @@ -71,7 +71,7 @@ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) PKG_CHECK_MODULES([ALSA], [alsa]) -PKG_CHECK_MODULES([PLPLOT], [plplotd-gnome2]) +PKG_CHECK_MODULES([PLPLOT], [plplotd]) AC_OUTPUT([ Makefile -- cgit v1.2.3 From ae4e131b61244e06020b82919e31e05dd7dba88f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 17:46:39 -0600 Subject: update changelogs for Debian build --- ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 42 insertions(+) diff --git a/ChangeLog b/ChangeLog index bd7e99fb..4716e727 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +commit 37e6c9a492a1d51373bf9333fb3172e0c377720f +Merge: d256f82 2e6686b +Author: Bdale Garbee +Date: Sun Sep 6 17:46:10 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 2e6686b1e183c66188ea447b8a54e4c29402443b +Author: Keith Packard +Date: Sun Sep 6 16:45:47 2009 -0700 + + Use plplotd instead of plplotd-gnome2 + +commit d256f8204e9fce53ae4309562bb4c0cde1fae43e +Merge: 0fc344d 32d3536 +Author: Bdale Garbee +Date: Sun Sep 6 17:34:08 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 32d3536706324808df6cd02248a236302b831571 +Author: Keith Packard +Date: Sun Sep 6 16:24:35 2009 -0700 + + Add plots to ao-postflight using the plplot library + + It's not perfect, but it generates .svg plot output. + + Signed-off-by: Keith Packard + +commit 0fc344dfc031a8b1eef7cc40efb1d5ba7782269d +Author: Bdale Garbee +Date: Sun Sep 6 14:15:57 2009 -0600 + + update changelogs for Debian build + commit 4b0de757874c0ecaf38e3dfd3beefc398150e3d5 Merge: 773c4ff d0eac98 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 11751700..67ee5ca0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+48+g37e6c9a) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 17:46:39 -0600 + altos (0.5+43+g4b0de75) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 9d7e96e323d652de08b2f2a73e0eb3c321080185 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 17:47:56 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4716e727..8904196e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit ae4e131b61244e06020b82919e31e05dd7dba88f +Author: Bdale Garbee +Date: Sun Sep 6 17:46:39 2009 -0600 + + update changelogs for Debian build + commit 37e6c9a492a1d51373bf9333fb3172e0c377720f Merge: d256f82 2e6686b Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 67ee5ca0..e7415cb5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+49+gae4e131) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 17:47:56 -0600 + altos (0.5+48+g37e6c9a) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 3f95a5abbf8ada70328ced45fbb2781ed1cb3d29 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 17:48:10 -0600 Subject: more build deps for plotting lib --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3aa6d5dd..d5a1259c 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline5-dev, libusb-1.0-0-dev, nickle, sdcc +Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline5-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev Standards-Version: 3.8.3 Homepage: http://altusmetrum.org/ -- cgit v1.2.3 From 97acef95cc9843998963921459fdd71dd7eaa6b4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 17:48:23 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8904196e..f36f4e25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 3f95a5abbf8ada70328ced45fbb2781ed1cb3d29 +Author: Bdale Garbee +Date: Sun Sep 6 17:48:10 2009 -0600 + + more build deps for plotting lib + +commit 9d7e96e323d652de08b2f2a73e0eb3c321080185 +Author: Bdale Garbee +Date: Sun Sep 6 17:47:56 2009 -0600 + + update changelogs for Debian build + commit ae4e131b61244e06020b82919e31e05dd7dba88f Author: Bdale Garbee Date: Sun Sep 6 17:46:39 2009 -0600 diff --git a/debian/changelog b/debian/changelog index e7415cb5..90ebbdf6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+51+g3f95a5a) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 17:48:22 -0600 + altos (0.5+49+gae4e131) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From a5e94aa0677070a051714443cf7fd7e2b5e90269 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 17:59:47 -0600 Subject: need a run-time dependency to pull in the cairo module --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index d5a1259c..d28be629 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ Homepage: http://altusmetrum.org/ Package: altos Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, nickle +Depends: ${shlibs:Depends}, ${misc:Depends}, nickle, plplot9-driver-cairo Description: Altus Metrum firmware and utilities Firmware and utilities needed to support the TeleMetrum dual-deploy recording altimeter for high power model rocketry. -- cgit v1.2.3 From 0b24e4034f93010372a3d084668d10f0e4a2c2e1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 6 Sep 2009 18:01:20 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index f36f4e25..809f112f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit a5e94aa0677070a051714443cf7fd7e2b5e90269 +Author: Bdale Garbee +Date: Sun Sep 6 17:59:47 2009 -0600 + + need a run-time dependency to pull in the cairo module + +commit 97acef95cc9843998963921459fdd71dd7eaa6b4 +Author: Bdale Garbee +Date: Sun Sep 6 17:48:23 2009 -0600 + + update changelogs for Debian build + commit 3f95a5abbf8ada70328ced45fbb2781ed1cb3d29 Author: Bdale Garbee Date: Sun Sep 6 17:48:10 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 90ebbdf6..ab433f29 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+53+ga5e94aa) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 06 Sep 2009 18:01:20 -0600 + altos (0.5+51+g3f95a5a) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 9177f5f4e9d832558ddd9ab227c4511f6201e7e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 18:11:24 -0700 Subject: Update usage and man page for ao-postflight --- ao-tools/ao-postflight/ao-postflight.1 | 10 +++++++++- ao-tools/ao-postflight/ao-postflight.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.1 b/ao-tools/ao-postflight/ao-postflight.1 index fe02587f..ac1c18a4 100644 --- a/ao-tools/ao-postflight/ao-postflight.1 +++ b/ao-tools/ao-postflight/ao-postflight.1 @@ -21,9 +21,17 @@ ao-postflight \- Analyse a flight log (either telemetry or eeprom) .SH SYNOPSIS .B "ao-postflight" +[\-s ] +[\--summary=] +[\-d ] +[\-p ] +[\--plot=] {flight.eeprom|flight.telem} .SH DESCRIPTION .I ao-postflight -reads the specified flight log and produces a summary of the flight on stdout. +reads the specified flight log and produces a summary of the flight on +stdout or to the specified file along with an optional .svg format +plot and detailed table of time/height/speed/accel. .SH AUTHOR Keith Packard diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index bc6638e9..4ca39c24 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -275,7 +275,7 @@ static const struct option options[] = { static void usage(char *program) { - fprintf(stderr, "usage: %s [--summary=] [--detail=] {flight-log} ...\n", program); + fprintf(stderr, "usage: %s [--summary=] [-s ] [--detail=] [--plot= -p ] {flight-log} ...\n", program); exit(1); } -- cgit v1.2.3 From 932f1539b38567e565fd484171c13539b1467308 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 20:26:17 -0700 Subject: Color plots, integrate only flight portion of data. Telemetry files have piles of pad data which shouldn't be integrated into the velocity data as it tends to generate huge values from the noise of the sensor. Also make the data lines colored to keep them visually distinct from the rest of the plot image. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.1 | 22 ++++-- ao-tools/ao-postflight/ao-postflight.c | 118 ++++++++++++++++++++++++++++----- ao-tools/lib/cc-analyse.c | 14 ++++ ao-tools/lib/cc-integrate.c | 21 +++--- ao-tools/lib/cc-period.c | 26 +++----- ao-tools/lib/cc-process.c | 20 ++++-- ao-tools/lib/cc.h | 12 +++- 7 files changed, 180 insertions(+), 53 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.1 b/ao-tools/ao-postflight/ao-postflight.1 index ac1c18a4..eca4bb34 100644 --- a/ao-tools/ao-postflight/ao-postflight.1 +++ b/ao-tools/ao-postflight/ao-postflight.1 @@ -23,15 +23,29 @@ ao-postflight \- Analyse a flight log (either telemetry or eeprom) .B "ao-postflight" [\-s ] [\--summary=] -[\-d ] [\--detail=] +[\-r ] +[\--raw=] [\-p ] [\--plot=] {flight.eeprom|flight.telem} .SH DESCRIPTION .I ao-postflight -reads the specified flight log and produces a summary of the flight on -stdout or to the specified file along with an optional .svg format -plot and detailed table of time/height/speed/accel. +reads the specified flight log and produces several different kinds of +output. +.IP Summary +By default, summary information is shown on stdout. With the --summary +option, it can be redirected to a file. +.IP Detail +When requested with the --detail option, a filtered version of the +flight position, speed and acceleration are written to the specified +file. +.IP Raw +The --raw option writes the unfiltered, but converted acceleration +and height data to the specified file. +.IP Plot +The --plot option writes plots of height, speed and acceleration to +the specified file in .svg format .SH AUTHOR Keith Packard diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 4ca39c24..ded2f3c2 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -39,9 +39,19 @@ static const char *state_names[] = { "invalid" }; +static int plot_colors[3][3] = { + { 0, 0x90, 0 }, /* height */ + { 0xa0, 0, 0 }, /* speed */ + { 0, 0, 0xc0 }, /* accel */ +}; + +#define PLOT_HEIGHT 0 +#define PLOT_SPEED 1 +#define PLOT_ACCEL 2 + static void plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label, - double min_time, double max_time) + double min_time, double max_time, int plot_type) { double *times; double ymin, ymax; @@ -60,11 +70,58 @@ plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label, ymax_i = cc_perioddata_max(d, min_time, max_time); ymin = d->data[ymin_i]; ymax = d->data[ymax_i]; + plscol0(1, 0, 0, 0); + plscol0(2, plot_colors[plot_type][0], plot_colors[plot_type][1], plot_colors[plot_type][2]); + plcol0(1); plenv(times[0], times[stop-start], ymin, ymax, 0, 2); - plcol0(1); pllab("Time", axis_label, plot_label); + plcol0(2); plline(stop - start + 1, times, d->data + start); + free(times); +} + +static void +plot_timedata(struct cc_timedata *d, char *axis_label, char *plot_label, + double min_time, double max_time) +{ + double *times; + double *values; + double ymin, ymax; + int ymin_i, ymax_i; + int i; + int start = -1, stop = -1; + double start_time = 0, stop_time = 0; + int num; + + for (i = 0; i < d->num; i++) { + if (start < 0 && d->data[i].time >= min_time) { + start_time = d->data[i].time; + start = i; + } + if (d->data[i].time <= max_time) { + stop_time = d->data[i].time; + stop = i; + } + } + + times = calloc(stop - start + 1, sizeof (double)); + values = calloc(stop - start + 1, sizeof (double)); + + ymin_i = cc_timedata_min(d, min_time, max_time); + ymax_i = cc_timedata_max(d, min_time, max_time); + ymin = d->data[ymin_i].value; + ymax = d->data[ymax_i].value; + plcol0(1); + pllab("Time", axis_label, plot_label); + for (i = start; i <= stop; i++) { + times[i-start] = (d->data[i].time - start_time)/100.0; + values[i-start] = d->data[i].value; + } + plenv(times[0], times[stop-start], ymin, ymax, 0, 2); + plline(stop - start + 1, times, values); + free(times); + free(values); } static struct cc_perioddata * @@ -102,7 +159,7 @@ merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split } static void -analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, char *plot_name) +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name) { double height; double accel; @@ -241,6 +298,17 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, ch time, pos, speed, accel); } } + if (raw_file) { + fprintf(raw_file, "%9s %9s %9s\n", + "time", "height", "accel"); + for (i = 0; i < cooked->pres.num; i++) { + double time = cooked->pres.data[i].time; + double pres = cooked->pres.data[i].value; + double accel = cooked->accel.data[i].value; + fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f\n", + time, pres, accel); + } + } if (cooked && plot_name) { struct cc_perioddata *speed; plsdev("svgcairo"); @@ -252,12 +320,12 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, ch plstar(2, 3); speed = merge_data(&cooked->accel_speed, &cooked->pres_speed, apogee); - plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10); - plot_perioddata(&cooked->pres_pos, "meters", "Height", boost_start, apogee); - plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10); - plot_perioddata(speed, "meters/second", "Speed", boost_start, apogee); - plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10); - plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", boost_start, apogee); + plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10, PLOT_HEIGHT); + plot_perioddata(&cooked->pres_pos, "meters", "Height to Apogee", boost_start, apogee, PLOT_HEIGHT); + plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10, PLOT_SPEED); + plot_perioddata(speed, "meters/second", "Speed to Apogee", boost_start, apogee, PLOT_SPEED); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10, PLOT_ACCEL); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration to Apogee", boost_start, apogee, PLOT_ACCEL); free(speed->data); free(speed); plend(); @@ -270,12 +338,18 @@ static const struct option options[] = { { .name = "summary", .has_arg = 1, .val = 's' }, { .name = "detail", .has_arg = 1, .val = 'd' }, { .name = "plot", .has_arg = 1, .val = 'p' }, + { .name = "raw", .has_arg = 1, .val = 'r' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--summary=] [-s ] [--detail=] [--plot= -p ] {flight-log} ...\n", program); + fprintf(stderr, "usage: %s\n" + "\t[--summary=] [-s ]\n" + "\t[--detail=]\n" + "\t[--raw= -r -p ]\n" + "\t{flight-log} ...\n", program); exit(1); } @@ -283,18 +357,21 @@ int main (int argc, char **argv) { FILE *file; - FILE *summary_file; - FILE *detail_file; + FILE *summary_file = NULL; + FILE *detail_file = NULL; + FILE *raw_file = NULL; int i; int ret = 0; struct cc_flightraw *raw; int c; int serial; char *s; - char *summary_name = NULL, *detail_name = NULL; + char *summary_name = NULL; + char *detail_name = NULL; + char *raw_name = NULL; char *plot_name = NULL; - while ((c = getopt_long(argc, argv, "s:d:p:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "s:d:p:r:", options, NULL)) != -1) { switch (c) { case 's': summary_name = optarg; @@ -305,13 +382,15 @@ main (int argc, char **argv) case 'p': plot_name = optarg; break; + case 'r': + raw_name = optarg; + break; default: usage(argv[0]); break; } } summary_file = stdout; - detail_file = NULL; if (summary_name) { summary_file = fopen(summary_name, "w"); if (!summary_file) { @@ -330,6 +409,13 @@ main (int argc, char **argv) } } } + if (raw_name) { + raw_file = fopen (raw_name, "w"); + if (!raw_file) { + perror(raw_name); + exit(1); + } + } for (i = optind; i < argc; i++) { file = fopen(argv[i], "r"); if (!file) { @@ -350,7 +436,7 @@ main (int argc, char **argv) } if (!raw->serial) raw->serial = serial; - analyse_flight(raw, summary_file, detail_file, plot_name); + analyse_flight(raw, summary_file, detail_file, raw_file, plot_name); cc_flightraw_free(raw); } return ret; diff --git a/ao-tools/lib/cc-analyse.c b/ao-tools/lib/cc-analyse.c index cdb16f02..27c416a6 100644 --- a/ao-tools/lib/cc-analyse.c +++ b/ao-tools/lib/cc-analyse.c @@ -18,6 +18,20 @@ #include "cc.h" #include +void +cc_timedata_limits(struct cc_timedata *d, double min_time, double max_time, int *start, int *stop) +{ + int i; + + *start = -1; + for (i = 0; i < d->num; i++) { + if (*start < 0 && min_time <= d->data[i].time) + *start = i; + if (d->data[i].time <= max_time) + *stop = i; + } +} + int cc_timedata_min(struct cc_timedata *d, double min_time, double max_time) { diff --git a/ao-tools/lib/cc-integrate.c b/ao-tools/lib/cc-integrate.c index f9793dcd..ba50761b 100644 --- a/ao-tools/lib/cc-integrate.c +++ b/ao-tools/lib/cc-integrate.c @@ -37,24 +37,27 @@ cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), doub } struct cc_timedata * -cc_timedata_integrate(struct cc_timedata *d) +cc_timedata_integrate(struct cc_timedata *d, double min_time, double max_time) { struct cc_timedata *i; - int n; + int n, m; + int start, stop; + cc_timedata_limits(d, min_time, max_time, &start, &stop); i = calloc (1, sizeof (struct cc_timedata)); - i->num = d->num; - i->size = d->num; + i->num = stop - start + 1; + i->size = i->num; i->data = calloc (i->size, sizeof (struct cc_timedataelt)); - i->time_offset = d->time_offset; - for (n = 0; n < d->num; n++) { - i->data[n].time = d->data[n].time; + i->time_offset = d->data[start].time; + for (n = 0; n < i->num; n++) { + m = n + start; + i->data[n].time = d->data[m].time; if (n == 0) { i->data[n].value = 0; } else { i->data[n].value = i->data[n-1].value + - (d->data[n].value + d->data[n-1].value) / 2 * - ((d->data[n].time - d->data[n-1].time) / 100.0); + (d->data[m].value + d->data[m-1].value) / 2 * + ((d->data[m].time - d->data[m-1].time) / 100.0); } } return i; diff --git a/ao-tools/lib/cc-period.c b/ao-tools/lib/cc-period.c index c74cf9dc..2a4e5952 100644 --- a/ao-tools/lib/cc-period.c +++ b/ao-tools/lib/cc-period.c @@ -17,35 +17,27 @@ #include "cc.h" #include +#include struct cc_perioddata * cc_period_make(struct cc_timedata *td, double start_time, double stop_time) { int len = stop_time - start_time + 1; struct cc_perioddata *pd; - int i; - double prev_time; - double next_time; - double interval; + int i, j; + double t; pd = calloc(1, sizeof (struct cc_perioddata)); pd->start = start_time; pd->step = 1; pd->num = len; pd->data = calloc(len, sizeof(double)); - prev_time = start_time; - for (i = 0; i < td->num; i++) { - if (start_time <= td->data[i].time && td->data[i].time <= stop_time) { - int pos = td->data[i].time - start_time; - - if (i < td->num - 1 && td->data[i+1].time < stop_time) - next_time = (td->data[i].time + td->data[i+1].time) / 2.0; - else - next_time = stop_time; - interval = next_time - prev_time; - pd->data[pos] = td->data[i].value * interval; - prev_time = next_time; - } + j = 0; + for (i = 0; i < pd->num; i++) { + t = start_time + i * pd->step; + while (j < td->num - 1 && fabs(t - td->data[j].time) > fabs(t - td->data[j+1].time)) + j++; + pd->data[i] = td->data[j].value; } return pd; } diff --git a/ao-tools/lib/cc-process.c b/ao-tools/lib/cc-process.c index 469ad2f2..5c1acc6b 100644 --- a/ao-tools/lib/cc-process.c +++ b/ao-tools/lib/cc-process.c @@ -33,8 +33,6 @@ cook_timed(struct cc_timedata *td, struct cc_perioddata *pd, free (filtered); free (unfiltered->data); free (unfiltered); - free (td->data); - free (td); } static double @@ -93,11 +91,15 @@ cc_flight_cook(struct cc_flightraw *raw) } else { flight_stop = raw->accel.data[raw->accel.num-1].time; } + cooked->flight_start = flight_start; + cooked->flight_stop = flight_stop; /* Integrate the accelerometer data to get speed and position */ accel = cc_timedata_convert(&raw->accel, cc_accelerometer_to_acceleration, raw->ground_accel); - accel_speed = cc_timedata_integrate(accel); - accel_pos = cc_timedata_integrate(accel_speed); + cooked->accel = *accel; + free(accel); + accel_speed = cc_timedata_integrate(&cooked->accel, flight_start - 10, flight_stop); + accel_pos = cc_timedata_integrate(accel_speed, flight_start - 10, flight_stop); #define ACCEL_OMEGA_PASS (2 * M_PI * 5 / 100) #define ACCEL_OMEGA_STOP (2 * M_PI * 8 / 100) @@ -105,20 +107,24 @@ cc_flight_cook(struct cc_flightraw *raw) #define BARO_OMEGA_STOP (2 * M_PI * 1 / 100) #define FILTER_ERROR (1e-8) - cook_timed(accel, &cooked->accel_accel, + cook_timed(&cooked->accel, &cooked->accel_accel, flight_start, flight_stop, ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); cook_timed(accel_speed, &cooked->accel_speed, flight_start, flight_stop, ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); + free(accel_speed->data); free(accel_speed); cook_timed(accel_pos, &cooked->accel_pos, flight_start, flight_stop, ACCEL_OMEGA_PASS, ACCEL_OMEGA_STOP, FILTER_ERROR); + free(accel_pos->data); free(accel_pos); /* Filter the pressure data */ pres = cc_timedata_convert(&raw->pres, barometer_to_altitude, cc_barometer_to_altitude(raw->ground_pres)); - cook_timed(pres, &cooked->pres_pos, + cooked->pres = *pres; + free(pres); + cook_timed(&cooked->pres, &cooked->pres_pos, flight_start, flight_stop, BARO_OMEGA_PASS, BARO_OMEGA_STOP, FILTER_ERROR); /* differentiate twice to get to acceleration */ @@ -154,5 +160,7 @@ cc_flightcooked_free(struct cc_flightcooked *cooked) if_free(cooked->gps_lon.data); if_free(cooked->gps_alt.data); if_free(cooked->state.data); + if_free(cooked->accel.data); + if_free(cooked->pres.data); free(cooked); } diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 4e9aadc4..01226958 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -142,6 +142,9 @@ void cc_flightraw_free(struct cc_flightraw *raw); struct cc_flightcooked { + double flight_start; + double flight_stop; + struct cc_perioddata accel_accel; struct cc_perioddata accel_speed; struct cc_perioddata accel_pos; @@ -151,6 +154,10 @@ struct cc_flightcooked { struct cc_perioddata gps_lat; struct cc_perioddata gps_lon; struct cc_perioddata gps_alt; + + /* unfiltered, but converted */ + struct cc_timedata pres; + struct cc_timedata accel; struct cc_timedata state; }; @@ -262,6 +269,9 @@ cc_great_circle (double start_lat, double start_lon, double end_lat, double end_lon, double *dist, double *bearing); +void +cc_timedata_limits(struct cc_timedata *d, double min_time, double max_time, int *start, int *stop); + int cc_timedata_min(struct cc_timedata *d, double min_time, double max_time); @@ -314,7 +324,7 @@ struct cc_timedata * cc_timedata_convert(struct cc_timedata *d, double (*f)(double v, double a), double a); struct cc_timedata * -cc_timedata_integrate(struct cc_timedata *d); +cc_timedata_integrate(struct cc_timedata *d, double min_time, double max_time); struct cc_perioddata * cc_perioddata_differentiate(struct cc_perioddata *i); -- cgit v1.2.3 From 9e660315e1bd2bf71ab1c0574e895e1f7608a58f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 21:01:44 -0700 Subject: Fix cc_period_make to not get stuck on samples with matching time When two samples have matching times, step to the second one; otherwise, we'll get stuck forever. Signed-off-by: Keith Packard --- ao-tools/lib/cc-period.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/lib/cc-period.c b/ao-tools/lib/cc-period.c index 2a4e5952..844ac79e 100644 --- a/ao-tools/lib/cc-period.c +++ b/ao-tools/lib/cc-period.c @@ -35,7 +35,7 @@ cc_period_make(struct cc_timedata *td, double start_time, double stop_time) j = 0; for (i = 0; i < pd->num; i++) { t = start_time + i * pd->step; - while (j < td->num - 1 && fabs(t - td->data[j].time) > fabs(t - td->data[j+1].time)) + while (j < td->num - 1 && fabs(t - td->data[j].time) >= fabs(t - td->data[j+1].time)) j++; pd->data[i] = td->data[j].value; } -- cgit v1.2.3 From 8b485d937ff148848ebda7f9ca6be29bb1de1f16 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Sep 2009 21:02:48 -0700 Subject: Show acceleration only during boost phase. We're interested in motor performance; the rest of the flight is boring, after all. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index ded2f3c2..3a6f04b6 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -325,7 +325,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10, PLOT_SPEED); plot_perioddata(speed, "meters/second", "Speed to Apogee", boost_start, apogee, PLOT_SPEED); plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10, PLOT_ACCEL); - plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration to Apogee", boost_start, apogee, PLOT_ACCEL); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration during Boost", boost_start, boost_stop + (boost_stop - boost_start) / 2.0, PLOT_ACCEL); free(speed->data); free(speed); plend(); -- cgit v1.2.3 From 078e9cdbdb388b22c6151f76ff0660fc14b8ef55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Sep 2009 11:53:06 -0700 Subject: Plot raw accel data for the motor accel section. This shows a short sequence of accelerometer data without any filtering. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 3a6f04b6..1e6ac744 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -83,7 +83,7 @@ plot_perioddata(struct cc_perioddata *d, char *axis_label, char *plot_label, static void plot_timedata(struct cc_timedata *d, char *axis_label, char *plot_label, - double min_time, double max_time) + double min_time, double max_time, int plot_type) { double *times; double *values; @@ -112,13 +112,16 @@ plot_timedata(struct cc_timedata *d, char *axis_label, char *plot_label, ymax_i = cc_timedata_max(d, min_time, max_time); ymin = d->data[ymin_i].value; ymax = d->data[ymax_i].value; - plcol0(1); - pllab("Time", axis_label, plot_label); for (i = start; i <= stop; i++) { times[i-start] = (d->data[i].time - start_time)/100.0; values[i-start] = d->data[i].value; } + plscol0(1, 0, 0, 0); + plscol0(2, plot_colors[plot_type][0], plot_colors[plot_type][1], plot_colors[plot_type][2]); + plcol0(1); plenv(times[0], times[stop-start], ymin, ymax, 0, 2); + pllab("Time", axis_label, plot_label); + plcol0(2); plline(stop - start + 1, times, values); free(times); free(values); @@ -320,12 +323,20 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI plstar(2, 3); speed = merge_data(&cooked->accel_speed, &cooked->pres_speed, apogee); - plot_perioddata(&cooked->pres_pos, "meters", "Height", -1e10, 1e10, PLOT_HEIGHT); - plot_perioddata(&cooked->pres_pos, "meters", "Height to Apogee", boost_start, apogee, PLOT_HEIGHT); - plot_perioddata(speed, "meters/second", "Speed", -1e10, 1e10, PLOT_SPEED); - plot_perioddata(speed, "meters/second", "Speed to Apogee", boost_start, apogee, PLOT_SPEED); - plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", -1e10, 1e10, PLOT_ACCEL); - plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration during Boost", boost_start, boost_stop + (boost_stop - boost_start) / 2.0, PLOT_ACCEL); + plot_perioddata(&cooked->pres_pos, "meters", "Height", + -1e10, 1e10, PLOT_HEIGHT); + plot_perioddata(&cooked->pres_pos, "meters", "Height to Apogee", + boost_start, apogee + (apogee - boost_start) / 10.0, PLOT_HEIGHT); + plot_perioddata(speed, "meters/second", "Speed", + -1e10, 1e10, PLOT_SPEED); + plot_perioddata(speed, "meters/second", "Speed to Apogee", + boost_start, apogee + (apogee - boost_start) / 10.0, PLOT_SPEED); + plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration", + -1e10, 1e10, PLOT_ACCEL); +/* plot_perioddata(&cooked->accel_accel, "meters/second²", "Acceleration during Boost", + boost_start, boost_stop + (boost_stop - boost_start) / 2.0, PLOT_ACCEL); */ + plot_timedata(&cooked->accel, "meters/second²", "Acceleration during Boost", + boost_start, boost_stop + (boost_stop - boost_start) / 2.0, PLOT_ACCEL); free(speed->data); free(speed); plend(); -- cgit v1.2.3 From c8a81a419f7f2331624f90bd6c107a86f6b04451 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 20 Sep 2009 09:21:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 72 insertions(+) diff --git a/ChangeLog b/ChangeLog index 809f112f..ec555bf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,69 @@ +commit df42ccaaf468cdc5d93cbd1c001f58df58419722 +Merge: 0b24e40 078e9cd +Author: Bdale Garbee +Date: Sun Sep 20 09:19:28 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 078e9cdbdb388b22c6151f76ff0660fc14b8ef55 +Author: Keith Packard +Date: Thu Sep 10 11:53:06 2009 -0700 + + Plot raw accel data for the motor accel section. + + This shows a short sequence of accelerometer data without any filtering. + + Signed-off-by: Keith Packard + +commit 8b485d937ff148848ebda7f9ca6be29bb1de1f16 +Author: Keith Packard +Date: Sun Sep 6 21:02:48 2009 -0700 + + Show acceleration only during boost phase. + + We're interested in motor performance; the rest of the flight is + boring, after all. + + Signed-off-by: Keith Packard + +commit 9e660315e1bd2bf71ab1c0574e895e1f7608a58f +Author: Keith Packard +Date: Sun Sep 6 21:01:44 2009 -0700 + + Fix cc_period_make to not get stuck on samples with matching time + + When two samples have matching times, step to the second one; + otherwise, we'll get stuck forever. + + Signed-off-by: Keith Packard + +commit 932f1539b38567e565fd484171c13539b1467308 +Author: Keith Packard +Date: Sun Sep 6 20:26:17 2009 -0700 + + Color plots, integrate only flight portion of data. + + Telemetry files have piles of pad data which shouldn't be integrated + into the velocity data as it tends to generate huge values from the + noise of the sensor. + + Also make the data lines colored to keep them visually distinct from + the rest of the plot image. + + Signed-off-by: Keith Packard + +commit 9177f5f4e9d832558ddd9ab227c4511f6201e7e5 +Author: Keith Packard +Date: Sun Sep 6 18:11:24 2009 -0700 + + Update usage and man page for ao-postflight + +commit 0b24e4034f93010372a3d084668d10f0e4a2c2e1 +Author: Bdale Garbee +Date: Sun Sep 6 18:01:20 2009 -0600 + + update changelogs for Debian build + commit a5e94aa0677070a051714443cf7fd7e2b5e90269 Author: Bdale Garbee Date: Sun Sep 6 17:59:47 2009 -0600 diff --git a/debian/changelog b/debian/changelog index ab433f29..69d143d5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+60+gdf42cca) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sun, 20 Sep 2009 09:21:00 -0600 + altos (0.5+53+ga5e94aa) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From bc7ccb339e538a0e6120db0e5c0d9130c565e0dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Sep 2009 13:32:59 -0700 Subject: ao_rawload: Don't reset after we finish loading --- ao-tools/ao-rawload/ao-rawload.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index 255f63ec..d9ee5718 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -105,8 +105,6 @@ main (int argc, char **argv) ccdbg_close(dbg); exit(1); } - ccdbg_set_pc(dbg, image->address); - ccdbg_resume(dbg); ccdbg_close(dbg); exit (0); } -- cgit v1.2.3 From 7ea371a09385e2a93199f78685e8cb86793ed104 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Sep 2009 13:33:26 -0700 Subject: Add --gps option to ao-postflight --- ao-tools/ao-postflight/ao-postflight.c | 31 ++++++++++++++-- ao-tools/lib/cc-logfile.c | 66 ++++++++++++++++++++++++++++++++-- ao-tools/lib/cc.h | 25 +++++++++++++ 3 files changed, 116 insertions(+), 6 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 1e6ac744..6418521e 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -162,7 +162,7 @@ merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split } static void -analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name) +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name, FILE *gps_file) { double height; double accel; @@ -312,6 +312,17 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI time, pres, accel); } } + if (gps_file) { + fprintf(gps_file, "%9s %12s %12s %12s\n", + "time", "lat", "lon", "alt"); + for (i = 0; i < f->gps.num; i++) { + fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f\n", + (f->gps.data[i].time - boost_start) / 100.0, + f->gps.data[i].lat, + f->gps.data[i].lon, + f->gps.data[i].alt); + } + } if (cooked && plot_name) { struct cc_perioddata *speed; plsdev("svgcairo"); @@ -350,6 +361,7 @@ static const struct option options[] = { { .name = "detail", .has_arg = 1, .val = 'd' }, { .name = "plot", .has_arg = 1, .val = 'p' }, { .name = "raw", .has_arg = 1, .val = 'r' }, + { .name = "gps", .has_arg = 1, .val = 'g' }, { 0, 0, 0, 0}, }; @@ -360,6 +372,7 @@ static void usage(char *program) "\t[--detail=]\n" "\t[--raw= -r -p ]\n" + "\t[--gps= -g ]\n" "\t{flight-log} ...\n", program); exit(1); } @@ -371,6 +384,7 @@ main (int argc, char **argv) FILE *summary_file = NULL; FILE *detail_file = NULL; FILE *raw_file = NULL; + FILE *gps_file = NULL; int i; int ret = 0; struct cc_flightraw *raw; @@ -381,8 +395,9 @@ main (int argc, char **argv) char *detail_name = NULL; char *raw_name = NULL; char *plot_name = NULL; + char *gps_name = NULL; - while ((c = getopt_long(argc, argv, "s:d:p:r:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "s:d:p:r:g:", options, NULL)) != -1) { switch (c) { case 's': summary_name = optarg; @@ -396,6 +411,9 @@ main (int argc, char **argv) case 'r': raw_name = optarg; break; + case 'g': + gps_name = optarg; + break; default: usage(argv[0]); break; @@ -427,6 +445,13 @@ main (int argc, char **argv) exit(1); } } + if (gps_name) { + gps_file = fopen(gps_name, "w"); + if (!gps_file) { + perror(gps_name); + exit(1); + } + } for (i = optind; i < argc; i++) { file = fopen(argv[i], "r"); if (!file) { @@ -447,7 +472,7 @@ main (int argc, char **argv) } if (!raw->serial) raw->serial = serial; - analyse_flight(raw, summary_file, detail_file, raw_file, plot_name); + analyse_flight(raw, summary_file, detail_file, raw_file, plot_name, gps_file); cc_flightraw_free(raw); } return ret; diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 4abf7eb6..2136eec4 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -80,6 +80,44 @@ gpsdata_add(struct cc_gpsdata *data, struct cc_gpselt *elt) return 1; } +static int +gpssat_add(struct cc_gpsdata *data, struct cc_gpssat *sat) +{ + int i, j; + int reuse = 0; + int newsizesats; + struct cc_gpssats *newsats; + + for (i = data->numsats; --i >= 0;) { + if (data->sats[i].sat[0].time == sat->time) { + reuse = 1; + break; + } + if (data->sats[i].sat[0].time < sat->time) + break; + } + if (!reuse) { + if (data->numsats == data->sizesats) { + if (data->sizesats == 0) + newsats = malloc((newsizesats = 256) * sizeof (struct cc_gpssats)); + else + newsats = realloc (data->data, (newsizesats = data->sizesats * 2) + * sizeof (struct cc_gpssats)); + if (!newsats) + return 0; + data->sats = newsats; + } + i = data->numsats++; + data->sats[i].nsat = 0; + } + j = data->sats[i].nsat; + if (j < 12) { + data->sats[i].sat[j] = *sat; + data->sats[i].nsat = j + 1; + } + return 1; +} + static void gpsdata_free(struct cc_gpsdata *data) { @@ -100,13 +138,20 @@ gpsdata_free(struct cc_gpsdata *data) #define AO_LOG_POS_NONE (~0UL) +#define GPS_TIME 1 +#define GPS_LAT 2 +#define GPS_LON 4 +#define GPS_ALT 8 + static int read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int *ground_pres_count) { char type; int tick; int a, b; - struct cc_gpselt gps; + static struct cc_gpselt gps; + static int gps_valid; + struct cc_gpssat sat; int serial; if (sscanf(line, "serial-number %u", &serial) == 1) { @@ -145,23 +190,38 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * timedata_add(&f->state, tick, a); break; case AO_LOG_GPS_TIME: + /* the flight computer writes TIME first, so reset + * any stale data before adding this record + */ gps.time = tick; + gps_valid = GPS_TIME; break; case AO_LOG_GPS_LAT: gps.lat = ((int32_t) (a + (b << 16))) / 10000000.0; + gps_valid |= GPS_LAT; break; case AO_LOG_GPS_LON: gps.lon = ((int32_t) (a + (b << 16))) / 10000000.0; + gps_valid |= GPS_LON; break; case AO_LOG_GPS_ALT: - gps.alt = ((int32_t) (a + (b << 16))); - gpsdata_add(&f->gps, &gps); + gps.alt = (int16_t) a; + gps_valid |= GPS_ALT; break; case AO_LOG_GPS_SAT: + sat.time = tick; + sat.svid = a; + sat.state = (b & 0xff); + sat.c_n = (b >> 8) & 0xff; + gpssat_add(&f->gps, &sat); break; default: return 0; } + if (gps_valid == 0xf) { + gps_valid = 0; + gpsdata_add(&f->gps, &gps); + } return 1; } diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 01226958..b5f1132f 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -19,6 +19,7 @@ #define _CC_H_ #include +#include char * cc_fullname (char *dir, char *file); @@ -90,11 +91,35 @@ struct cc_gpselt { double alt; }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct cc_gpssat { + double time; + uint16_t svid; + uint8_t state; + uint8_t c_n; +}; + +struct cc_gpssats { + int nsat; + struct cc_gpssat sat[12]; +}; + struct cc_gpsdata { int num; int size; struct cc_gpselt *data; double time_offset; + int numsats; + int sizesats; + struct cc_gpssats *sats; }; /* -- cgit v1.2.3 From 74f0fb4dd189abc1d5027c64fa5a648a6003285a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 20 Sep 2009 13:33:59 -0700 Subject: make bit-banging reset script actually reset --- ao-tools/tests/reset | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ao-tools/tests/reset b/ao-tools/tests/reset index a32c8bec..65b72803 100644 --- a/ao-tools/tests/reset +++ b/ao-tools/tests/reset @@ -1,5 +1,7 @@ # reset C D R -C D R -C D R +C D . +C D . +C D . +C D . C D R -- cgit v1.2.3 From 459ff3d377297f80ee2fba0df0a29ff6603467a1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 21 Sep 2009 11:00:32 -0700 Subject: update changelogs for Debian build --- ChangeLog | 31 +++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index ec555bf8..10c3c730 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +commit 327c64305a59f48ababf19875874a550af6b9cef +Merge: c8a81a4 74f0fb4 +Author: Bdale Garbee +Date: Mon Sep 21 11:00:22 2009 -0700 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 74f0fb4dd189abc1d5027c64fa5a648a6003285a +Author: Keith Packard +Date: Sun Sep 20 13:33:59 2009 -0700 + + make bit-banging reset script actually reset + +commit 7ea371a09385e2a93199f78685e8cb86793ed104 +Author: Keith Packard +Date: Sun Sep 20 13:33:26 2009 -0700 + + Add --gps option to ao-postflight + +commit bc7ccb339e538a0e6120db0e5c0d9130c565e0dd +Author: Keith Packard +Date: Sun Sep 20 13:32:59 2009 -0700 + + ao_rawload: Don't reset after we finish loading + +commit c8a81a419f7f2331624f90bd6c107a86f6b04451 +Author: Bdale Garbee +Date: Sun Sep 20 09:21:00 2009 -0600 + + update changelogs for Debian build + commit df42ccaaf468cdc5d93cbd1c001f58df58419722 Merge: 0b24e40 078e9cd Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 69d143d5..875e1f0c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+65+g327c643) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 21 Sep 2009 11:00:31 -0700 + altos (0.5+60+gdf42cca) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From dfc73cba1bee8b121e00e8cba45e7dfaaf79e9d8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 21 Sep 2009 22:46:59 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 10c3c730..56d1495f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 459ff3d377297f80ee2fba0df0a29ff6603467a1 +Author: Bdale Garbee +Date: Mon Sep 21 11:00:32 2009 -0700 + + update changelogs for Debian build + commit 327c64305a59f48ababf19875874a550af6b9cef Merge: c8a81a4 74f0fb4 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 875e1f0c..2aaa3c3c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+66+g459ff3d) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 21 Sep 2009 22:46:58 -0700 + altos (0.5+65+g327c643) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From ac4b8a73848f434999a532eab4665253c267c597 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Oct 2009 20:05:36 -0700 Subject: ao-postflight: dump out GPS signal data Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 6418521e..cc9f64b4 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -313,14 +313,30 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI } } if (gps_file) { + int j = 0; fprintf(gps_file, "%9s %12s %12s %12s\n", "time", "lat", "lon", "alt"); for (i = 0; i < f->gps.num; i++) { - fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f\n", + int nsat = 0; + int k; + while (j < f->gps.numsats - 1) { + if (f->gps.sats[j].sat[0].time <= f->gps.data[i].time && + f->gps.data[i].time < f->gps.sats[j+1].sat[0].time) + break; + j++; + } + fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f", (f->gps.data[i].time - boost_start) / 100.0, f->gps.data[i].lat, f->gps.data[i].lon, f->gps.data[i].alt); + nsat = 0; + for (k = 0; k < f->gps.sats[j].nsat; k++) { + fprintf (gps_file, " %12.7f", (double) f->gps.sats[j].sat[k].c_n); + if (f->gps.sats[j].sat[k].state == 0xbf) + nsat++; + } + fprintf(gps_file, " %d\n", nsat); } } if (cooked && plot_name) { -- cgit v1.2.3 From a3771bfc5ce740f9d89193e9f8b1d7987aa57264 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Oct 2009 20:06:00 -0700 Subject: ao-view: fix snd_pcm_open return checking I don't know how this code was supposed to work before... Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_flite.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c index e1b75898..bc702b0f 100644 --- a/ao-tools/ao-view/aoview_flite.c +++ b/ao-tools/ao-view/aoview_flite.c @@ -42,12 +42,10 @@ aoview_flite_task(gpointer data) err = snd_pcm_open(&alsa_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); - if (err >= 0) - { - if (err < 0) { - snd_pcm_close(alsa_handle); - alsa_handle = 0; - } + if (err < 0) { + fprintf(stderr, "alsa open failed %s\n", + strerror(-err)); + alsa_handle = NULL; } rate = 0; channels = 0; -- cgit v1.2.3 From 33b0b6f2f2e07de105619a7b463226d2813152ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Oct 2009 22:02:40 -0700 Subject: Add support for the SkyTraq GPS unit This is a build-time option selected by hacking the Makefile at present. Signed-off-by: Keith Packard --- src/Makefile | 9 +- src/ao.h | 3 +- src/ao_gps.c | 457 -------------------------------------------- src/ao_gps_sirf.c | 457 ++++++++++++++++++++++++++++++++++++++++++++ src/ao_gps_skytraq.c | 369 +++++++++++++++++++++++++++++++++++ src/ao_gps_test.c | 2 +- src/ao_gps_test_skytraq.c | 478 ++++++++++++++++++++++++++++++++++++++++++++++ src/ao_serial.c | 9 +- 8 files changed, 1321 insertions(+), 463 deletions(-) delete mode 100644 src/ao_gps.c create mode 100644 src/ao_gps_sirf.c create mode 100644 src/ao_gps_skytraq.c create mode 100644 src/ao_gps_test_skytraq.c diff --git a/src/Makefile b/src/Makefile index 828c48bd..892635cb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,7 @@ TELE_RECEIVER_SRC =\ TELE_DRIVER_SRC = \ ao_convert.c \ - ao_gps.c \ + ao_gps_skytraq.c \ ao_serial.c # @@ -189,7 +189,7 @@ SYM=$(REL:.rel=.sym) PROGS= telemetrum.ihx tidongle.ihx \ teleterra.ihx teledongle.ihx -HOST_PROGS=ao_flight_test ao_gps_test +HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq PCDB=$(PROGS:.ihx=.cdb) PLNK=$(PROGS:.ihx=.lnk) @@ -271,5 +271,8 @@ install: ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -ao_gps_test: ao_gps.c ao_gps_test.c ao_gps_print.c ao_host.h +ao_gps_test: ao_gps_sirf.c ao_gps_test.c ao_gps_print.c ao_host.h cc -g -o $@ ao_gps_test.c + +ao_gps_test_skytraq: ao_gps_skytraq.c ao_gps_test_skytraq.c ao_gps_print.c ao_host.h + cc -g -o $@ ao_gps_test_skytraq.c diff --git a/src/ao.h b/src/ao.h index 4116be65..0f3f0ea7 100644 --- a/src/ao.h +++ b/src/ao.h @@ -668,7 +668,8 @@ void ao_serial_putchar(char c) __critical; #define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_57600 1 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 void ao_serial_set_speed(uint8_t speed); diff --git a/src/ao_gps.c b/src/ao_gps.c deleted file mode 100644 index 2b3a5178..00000000 --- a/src/ao_gps.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -__xdata uint8_t ao_gps_mutex; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; - -static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; - -const char ao_gps_config[] = { - - 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ - 136, /* mode control */ - 0, 0, /* reserved */ - 0, /* degraded mode (allow 1-SV navigation) */ - 0, 0, /* reserved */ - 0, 0, /* user specified altitude */ - 2, /* alt hold mode (disabled, require 3d fixes) */ - 0, /* alt hold source (use last computed altitude) */ - 0, /* reserved */ - 10, /* Degraded time out (10 sec) */ - 10, /* Dead Reckoning time out (10 sec) */ - 0, /* Track smoothing (disabled) */ - 0x00, 0x8e, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ - 166, /* Set message rate */ - 2, /* enable/disable all messages */ - 0, /* message id (ignored) */ - 0, /* update rate (0 = disable) */ - 0, 0, 0, 0, /* reserved */ - 0x00, 0xa8, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ - 143, /* static navigation */ - 0, /* disable */ - 0x00, 0x8f, 0xb0, 0xb3, -}; - -#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) -#define NAV_TYPE_NO_FIX (0 << 0) -#define NAV_TYPE_SV_KF (1 << 0) -#define NAV_TYPE_2_SV_KF (2 << 0) -#define NAV_TYPE_3_SV_KF (3 << 0) -#define NAV_TYPE_4_SV_KF (4 << 0) -#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) -#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) -#define NAV_TYPE_DR (7 << 0) -#define NAV_TYPE_TRICKLE_POWER (1 << 3) -#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) -#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) -#define NAV_TYPE_DGPS_APPLIED (1 << 7) -#define NAV_TYPE_SENSOR_DR (1 << 8) -#define NAV_TYPE_OVERDETERMINED (1 << 9) -#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) -#define NAV_TYPE_FIX_MI_EDIT (1 << 11) -#define NAV_TYPE_INVALID_VELOCITY (1 << 12) -#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) -#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) - -struct sirf_geodetic_nav_data { - uint16_t nav_type; - uint16_t utc_year; - uint8_t utc_month; - uint8_t utc_day; - uint8_t utc_hour; - uint8_t utc_minute; - uint16_t utc_second; - int32_t lat; - int32_t lon; - int32_t alt_msl; - uint16_t ground_speed; - uint16_t course; - int16_t climb_rate; - uint32_t h_error; - uint32_t v_error; - uint8_t num_sv; - uint8_t hdop; -}; - -static __xdata struct sirf_geodetic_nav_data ao_sirf_data; - -struct sirf_measured_sat_data { - uint8_t svid; - uint16_t state; - uint8_t c_n_1; -}; - -struct sirf_measured_tracker_data { - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - struct sirf_measured_sat_data sats[12]; -}; - -static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; - -static __pdata uint16_t ao_sirf_cksum; -static __pdata uint16_t ao_sirf_len; - -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) - -static uint8_t data_byte(void) -{ - uint8_t c = ao_sirf_byte(); - --ao_sirf_len; - ao_sirf_cksum += c; - return c; -} - -static char __xdata *sirf_target; - -static void sirf_u16(uint8_t offset) -{ - uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); - uint16_t val; - - val = data_byte() << 8; - val |= data_byte (); - *ptr = val; -} - -static void sirf_u8(uint8_t offset) -{ - uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); - uint8_t val; - - val = data_byte (); - *ptr = val; -} - -static void sirf_u32(uint8_t offset) __reentrant -{ - uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); - uint32_t val; - - val = ((uint32_t) data_byte ()) << 24; - val |= ((uint32_t) data_byte ()) << 16; - val |= ((uint32_t) data_byte ()) << 8; - val |= ((uint32_t) data_byte ()); - *ptr = val; -} - -static void sirf_discard(uint8_t len) -{ - while (len--) - data_byte(); -} - -#define SIRF_END 0 -#define SIRF_DISCARD 1 -#define SIRF_U8 2 -#define SIRF_U16 3 -#define SIRF_U32 4 -#define SIRF_U8X10 5 - -struct sirf_packet_parse { - uint8_t type; - uint8_t offset; -}; - -static void -ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant -{ - uint8_t i, offset, j; - - sirf_target = target; - for (i = 0; ; i++) { - offset = parse[i].offset; - switch (parse[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - case SIRF_U8X10: - for (j = 10; j--;) - sirf_u8(offset++); - break; - } - } -} - -static const struct sirf_packet_parse geodetic_nav_data_packet[] = { - { SIRF_DISCARD, 2 }, /* 1 nav valid */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ - { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ - { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ - { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ - { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ - { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ - { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ - { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, - clock bias error, clock drift, - clock drift error, distance, - distance error, heading error */ /* 58 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ - { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ - { SIRF_END, 0 }, /* 91 */ -}; - -static void -ao_sirf_parse_41(void) __reentrant -{ - ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); -} - -static const struct sirf_packet_parse measured_tracker_data_packet[] = { - { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ - { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ - { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ - { SIRF_END, 0 }, -}; - -static const struct sirf_packet_parse measured_sat_data_packet[] = { - { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ - { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ - { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ - { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ - { SIRF_END, 0 }, -}; - -static void -ao_sirf_parse_4(void) __reentrant -{ - uint8_t i; - ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); - for (i = 0; i < 12; i++) - ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); -} - -static void -ao_gps_setup(void) __reentrant -{ - uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); - for (k = 0; k < 3; k++) - for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); -} - -static const char ao_gps_set_message_rate[] = { - 0xa0, 0xa2, 0x00, 0x08, - 166, - 0, -}; - -void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) -{ - uint16_t cksum = 0x00a6; - uint8_t i; - - for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); - cksum = 0xa6 + msg + rate; - for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); -} - -static const uint8_t sirf_disable[] = { - 2, - 9, - 10, - 27, - 50, - 52, -}; - -void -ao_gps(void) __reentrant -{ - uint8_t i, k; - uint16_t cksum; - - ao_gps_setup(); - for (k = 0; k < 5; k++) - { - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (i = 0; i < sizeof (sirf_disable); i++) - ao_sirf_set_message_rate(sirf_disable[i], 0); - ao_sirf_set_message_rate(41, 1); - ao_sirf_set_message_rate(4, 1); - } - for (;;) { - /* Locate the begining of the next record */ - while (ao_sirf_byte() != (uint8_t) 0xa0) - ; - if (ao_sirf_byte() != (uint8_t) 0xa2) - continue; - - /* Length */ - ao_sirf_len = ao_sirf_byte() << 8; - ao_sirf_len |= ao_sirf_byte(); - if (ao_sirf_len > 1023) - continue; - - ao_sirf_cksum = 0; - - /* message ID */ - i = data_byte (); /* 0 */ - - switch (i) { - case 41: - if (ao_sirf_len < 90) - break; - ao_sirf_parse_41(); - break; - case 4: - if (ao_sirf_len < 187) - break; - ao_sirf_parse_4(); - break; - } - if (ao_sirf_len != 0) - continue; - - /* verify checksum and end sequence */ - ao_sirf_cksum &= 0x7fff; - cksum = ao_sirf_byte() << 8; - cksum |= ao_sirf_byte(); - if (ao_sirf_cksum != cksum) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb0) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb3) - continue; - - switch (i) { - case 41: - ao_mutex_get(&ao_gps_mutex); - ao_gps_data.hour = ao_sirf_data.utc_hour; - ao_gps_data.minute = ao_sirf_data.utc_minute; - ao_gps_data.second = ao_sirf_data.utc_second / 1000; - ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; - if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) - ao_gps_data.flags |= AO_GPS_VALID; - ao_gps_data.latitude = ao_sirf_data.lat; - ao_gps_data.longitude = ao_sirf_data.lon; - ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; - ao_gps_data.ground_speed = ao_sirf_data.ground_speed; - ao_gps_data.course = ao_sirf_data.course / 200; - ao_gps_data.hdop = ao_sirf_data.hdop; - ao_gps_data.climb_rate = ao_sirf_data.climb_rate; - if (ao_sirf_data.h_error > 6553500) - ao_gps_data.h_error = 65535; - else - ao_gps_data.h_error = ao_sirf_data.h_error / 100; - if (ao_sirf_data.v_error > 6553500) - ao_gps_data.v_error = 65535; - else - ao_gps_data.v_error = ao_sirf_data.v_error / 100; - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - break; - case 4: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; - for (i = 0; i < 12; i++) { - ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; - ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; - } - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - break; - } - } -} - -__xdata struct ao_task ao_gps_task; - -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); -} diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c new file mode 100644 index 00000000..2b3a5178 --- /dev/null +++ b/src/ao_gps_sirf.c @@ -0,0 +1,457 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +__xdata uint8_t ao_gps_mutex; +__xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; + +static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; + +const char ao_gps_config[] = { + + 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ + 136, /* mode control */ + 0, 0, /* reserved */ + 0, /* degraded mode (allow 1-SV navigation) */ + 0, 0, /* reserved */ + 0, 0, /* user specified altitude */ + 2, /* alt hold mode (disabled, require 3d fixes) */ + 0, /* alt hold source (use last computed altitude) */ + 0, /* reserved */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ + 0, /* Track smoothing (disabled) */ + 0x00, 0x8e, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ + 166, /* Set message rate */ + 2, /* enable/disable all messages */ + 0, /* message id (ignored) */ + 0, /* update rate (0 = disable) */ + 0, 0, 0, 0, /* reserved */ + 0x00, 0xa8, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ + 143, /* static navigation */ + 0, /* disable */ + 0x00, 0x8f, 0xb0, 0xb3, +}; + +#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) +#define NAV_TYPE_NO_FIX (0 << 0) +#define NAV_TYPE_SV_KF (1 << 0) +#define NAV_TYPE_2_SV_KF (2 << 0) +#define NAV_TYPE_3_SV_KF (3 << 0) +#define NAV_TYPE_4_SV_KF (4 << 0) +#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) +#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) +#define NAV_TYPE_DR (7 << 0) +#define NAV_TYPE_TRICKLE_POWER (1 << 3) +#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) +#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) +#define NAV_TYPE_DGPS_APPLIED (1 << 7) +#define NAV_TYPE_SENSOR_DR (1 << 8) +#define NAV_TYPE_OVERDETERMINED (1 << 9) +#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) +#define NAV_TYPE_FIX_MI_EDIT (1 << 11) +#define NAV_TYPE_INVALID_VELOCITY (1 << 12) +#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) +#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) + +struct sirf_geodetic_nav_data { + uint16_t nav_type; + uint16_t utc_year; + uint8_t utc_month; + uint8_t utc_day; + uint8_t utc_hour; + uint8_t utc_minute; + uint16_t utc_second; + int32_t lat; + int32_t lon; + int32_t alt_msl; + uint16_t ground_speed; + uint16_t course; + int16_t climb_rate; + uint32_t h_error; + uint32_t v_error; + uint8_t num_sv; + uint8_t hdop; +}; + +static __xdata struct sirf_geodetic_nav_data ao_sirf_data; + +struct sirf_measured_sat_data { + uint8_t svid; + uint16_t state; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + +static __pdata uint16_t ao_sirf_cksum; +static __pdata uint16_t ao_sirf_len; + +#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) + +static uint8_t data_byte(void) +{ + uint8_t c = ao_sirf_byte(); + --ao_sirf_len; + ao_sirf_cksum += c; + return c; +} + +static char __xdata *sirf_target; + +static void sirf_u16(uint8_t offset) +{ + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); + uint16_t val; + + val = data_byte() << 8; + val |= data_byte (); + *ptr = val; +} + +static void sirf_u8(uint8_t offset) +{ + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); + uint8_t val; + + val = data_byte (); + *ptr = val; +} + +static void sirf_u32(uint8_t offset) __reentrant +{ + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); + uint32_t val; + + val = ((uint32_t) data_byte ()) << 24; + val |= ((uint32_t) data_byte ()) << 16; + val |= ((uint32_t) data_byte ()) << 8; + val |= ((uint32_t) data_byte ()); + *ptr = val; +} + +static void sirf_discard(uint8_t len) +{ + while (len--) + data_byte(); +} + +#define SIRF_END 0 +#define SIRF_DISCARD 1 +#define SIRF_U8 2 +#define SIRF_U16 3 +#define SIRF_U32 4 +#define SIRF_U8X10 5 + +struct sirf_packet_parse { + uint8_t type; + uint8_t offset; +}; + +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + +static const struct sirf_packet_parse geodetic_nav_data_packet[] = { + { SIRF_DISCARD, 2 }, /* 1 nav valid */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ + { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ + { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ + { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ + { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ + { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ + { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ + { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, + clock bias error, clock drift, + clock drift error, distance, + distance error, heading error */ /* 58 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ + { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ + { SIRF_END, 0 }, /* 91 */ +}; + +static void +ao_sirf_parse_41(void) __reentrant +{ + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} + +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ + { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); +} + +static void +ao_gps_setup(void) __reentrant +{ + uint8_t i, k; + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); + for (k = 0; k < 3; k++) + for (i = 0; i < sizeof (ao_gps_set_nmea); i++) + ao_serial_putchar(ao_gps_set_nmea[i]); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); +} + +static const char ao_gps_set_message_rate[] = { + 0xa0, 0xa2, 0x00, 0x08, + 166, + 0, +}; + +void +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) +{ + uint16_t cksum = 0x00a6; + uint8_t i; + + for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) + ao_serial_putchar(ao_gps_set_message_rate[i]); + ao_serial_putchar(msg); + ao_serial_putchar(rate); + cksum = 0xa6 + msg + rate; + for (i = 0; i < 4; i++) + ao_serial_putchar(0); + ao_serial_putchar((cksum >> 8) & 0x7f); + ao_serial_putchar(cksum & 0xff); + ao_serial_putchar(0xb0); + ao_serial_putchar(0xb3); +} + +static const uint8_t sirf_disable[] = { + 2, + 9, + 10, + 27, + 50, + 52, +}; + +void +ao_gps(void) __reentrant +{ + uint8_t i, k; + uint16_t cksum; + + ao_gps_setup(); + for (k = 0; k < 5; k++) + { + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (i = 0; i < sizeof (sirf_disable); i++) + ao_sirf_set_message_rate(sirf_disable[i], 0); + ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); + } + for (;;) { + /* Locate the begining of the next record */ + while (ao_sirf_byte() != (uint8_t) 0xa0) + ; + if (ao_sirf_byte() != (uint8_t) 0xa2) + continue; + + /* Length */ + ao_sirf_len = ao_sirf_byte() << 8; + ao_sirf_len |= ao_sirf_byte(); + if (ao_sirf_len > 1023) + continue; + + ao_sirf_cksum = 0; + + /* message ID */ + i = data_byte (); /* 0 */ + + switch (i) { + case 41: + if (ao_sirf_len < 90) + break; + ao_sirf_parse_41(); + break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; + } + if (ao_sirf_len != 0) + continue; + + /* verify checksum and end sequence */ + ao_sirf_cksum &= 0x7fff; + cksum = ao_sirf_byte() << 8; + cksum |= ao_sirf_byte(); + if (ao_sirf_cksum != cksum) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb0) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb3) + continue; + + switch (i) { + case 41: + ao_mutex_get(&ao_gps_mutex); + ao_gps_data.hour = ao_sirf_data.utc_hour; + ao_gps_data.minute = ao_sirf_data.utc_minute; + ao_gps_data.second = ao_sirf_data.utc_second / 1000; + ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; + if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) + ao_gps_data.flags |= AO_GPS_VALID; + ao_gps_data.latitude = ao_sirf_data.lat; + ao_gps_data.longitude = ao_sirf_data.lon; + ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; + ao_gps_data.ground_speed = ao_sirf_data.ground_speed; + ao_gps_data.course = ao_sirf_data.course / 200; + ao_gps_data.hdop = ao_sirf_data.hdop; + ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + if (ao_sirf_data.h_error > 6553500) + ao_gps_data.h_error = 65535; + else + ao_gps_data.h_error = ao_sirf_data.h_error / 100; + if (ao_sirf_data.v_error > 6553500) + ao_gps_data.v_error = 65535; + else + ao_gps_data.v_error = ao_sirf_data.v_error / 100; + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; + } + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c new file mode 100644 index 00000000..b397d975 --- /dev/null +++ b/src/ao_gps_skytraq.c @@ -0,0 +1,369 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +#define AO_GPS_LEADER 3 + +static const char ao_gps_header[] = "GPG"; + +__xdata uint8_t ao_gps_mutex; +static __xdata char ao_gps_char; +static __xdata uint8_t ao_gps_cksum; +static __xdata uint8_t ao_gps_error; + +__xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; + +static __xdata struct ao_gps_data ao_gps_next; +static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; + +static const char ao_gps_config[] = { + 0xa0, 0xa1, 0x00, 0x09, /* length 9 bytes */ + 0x08, /* configure nmea */ + 1, /* gga interval */ + 1, /* gsa interval */ + 1, /* gsv interval */ + 1, /* gll interval */ + 1, /* rmc interval */ + 1, /* vtg interval */ + 1, /* zda interval */ + 0, /* attributes (0 = update to sram, 1 = update flash too) */ + 0x09, 0x0d, 0x0a, +}; + +static void +ao_gps_lexchar(void) +{ + if (ao_gps_error) + ao_gps_char = '\n'; + else + ao_gps_char = ao_serial_getchar(); + ao_gps_cksum ^= ao_gps_char; +} + +void +ao_gps_skip(void) +{ + while (ao_gps_char >= '0') + ao_gps_lexchar(); +} + +void +ao_gps_skip_field(void) +{ + while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + ao_gps_lexchar(); +} + +void +ao_gps_skip_sep(void) +{ + if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + ao_gps_lexchar(); +} + +__xdata static uint8_t ao_gps_num_width; + +static int16_t +ao_gps_decimal(uint8_t max_width) +{ + int16_t v; + __xdata uint8_t neg = 0; + + ao_gps_skip_sep(); + if (ao_gps_char == '-') { + neg = 1; + ao_gps_lexchar(); + } + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if (ao_gps_char < '0' || '9' < ao_gps_char) + break; + v = v * (int16_t) 10 + ao_gps_char - '0'; + ao_gps_num_width++; + ao_gps_lexchar(); + } + if (neg) + v = -v; + return v; +} + +static uint8_t +ao_gps_hex(uint8_t max_width) +{ + uint8_t v, d; + + ao_gps_skip_sep(); + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if ('0' <= ao_gps_char && ao_gps_char <= '9') + d = ao_gps_char - '0'; + else if ('A' <= ao_gps_char && ao_gps_char <= 'F') + d = ao_gps_char - 'A' + 10; + else if ('a' <= ao_gps_char && ao_gps_char <= 'f') + d = ao_gps_char - 'a' + 10; + else + break; + v = (v << 4) | d; + ao_gps_num_width++; + ao_gps_lexchar(); + } + return v; +} + +static int32_t +ao_gps_parse_pos(uint8_t deg_width) __reentrant +{ + int32_t d; + int32_t m; + int32_t f; + + d = ao_gps_decimal(deg_width); + m = ao_gps_decimal(2); + if (ao_gps_char == '.') { + f = ao_gps_decimal(4); + while (ao_gps_num_width < 4) { + f *= 10; + ao_gps_num_width++; + } + } else { + f = 0; + if (ao_gps_char != ',') + ao_gps_error = 1; + } + d = d * 10000000l; + m = m * 10000l + f; + d = d + m * 50 / 3; + return d; +} + +static uint8_t +ao_gps_parse_flag(char no_c, char yes_c) __reentrant +{ + uint8_t ret = 0; + ao_gps_skip_sep(); + if (ao_gps_char == yes_c) + ret = 1; + else if (ao_gps_char == no_c) + ret = 0; + else + ao_gps_error = 1; + ao_gps_lexchar(); + return ret; +} + + +void +ao_gps(void) __reentrant +{ + char c; + uint8_t i; + + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (;;) { + /* Locate the begining of the next record */ + for (;;) { + c = ao_serial_getchar(); + if (c == '$') + break; + } + + ao_gps_cksum = 0; + ao_gps_error = 0; + + /* Skip anything other than GPG */ + for (i = 0; i < AO_GPS_LEADER; i++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[i]) + break; + } + if (i != AO_GPS_LEADER) + continue; + + /* pull the record identifier characters off the link */ + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + i = ao_gps_char; + ao_gps_lexchar(); + if (ao_gps_char != ',') + continue; + + if (c == (uint8_t) 'G' && i == (uint8_t) 'A') { + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next.flags = AO_GPS_RUNNING; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + ao_gps_skip_field(); /* Horizontal dilution */ + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } + } else if (c == (uint8_t) 'S' && i == (uint8_t) 'V') { + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + 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 */ + 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].state = 0xbf; + else + ao_gps_tracking_next.sats[i].state = 0; + ao_gps_tracking_next.channels = i + 1; + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } + } + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index c94128d9..366bca71 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -398,7 +398,7 @@ ao_serial_set_speed(uint8_t speed) } #include "ao_gps_print.c" -#include "ao_gps.c" +#include "ao_gps_sirf.c" void ao_dump_state(void *wchan) diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c new file mode 100644 index 00000000..510bc419 --- /dev/null +++ b/src/ao_gps_test_skytraq.c @@ -0,0 +1,478 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) + +struct ao_gps_data { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10â· */ + int32_t longitude; /* degrees * 10â· */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_skytraq_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + +// fwrite(msg, 1, len, stdout); + return; + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t skytraq_message[4096]; +static int skytraq_message_len; +static uint8_t skytraq_in_message[4096]; +static int skytraq_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; +// printf ("c: %02x %c\n", uc, uc); + if (skytraq_in_len || uc == '$') { + if (skytraq_in_len < 4096) + skytraq_in_message[skytraq_in_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); + skytraq_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (skytraq_message_len || uc == 0xa0) { + if (skytraq_message_len < 4096) + skytraq_message[skytraq_message_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("send", skytraq_message, skytraq_message_len); + skytraq_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_9600: + cfsetspeed(&termios, B38400); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#include "ao_gps_print.c" +#include "ao_gps_skytraq.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps(); +} diff --git a/src/ao_serial.c b/src/ao_serial.c index 59110354..1e3ea3e3 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -60,7 +60,10 @@ ao_serial_getchar(void) __critical ao_sleep(&ao_usart1_rx_fifo); ao_fifo_remove(ao_usart1_rx_fifo, c); if (serial_echo) { - printf("%02x\n", ((int) c) & 0xff); + printf("%02x ", ((int) c) & 0xff); + if (c >= ' ') + putchar(c); + putchar('\n'); flush(); } return c; @@ -121,6 +124,10 @@ static const struct { /* .baud = */ 163, /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB }, + /* [AO_SERIAL_SPEED_9600] = */ { + /* .baud = */ 163, + /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, /* [AO_SERIAL_SPEED_57600] = */ { /* .baud = */ 59, /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB -- cgit v1.2.3 From 2f7603490a169df8f18b565db4fa967832ffc9bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Oct 2009 22:48:29 -0700 Subject: Build two versions of TM, one for SiRF, one for SkyTraq This creates two separate images, depending on which GPS unit is connected. Signed-off-by: Keith Packard --- .gitignore | 4 +++- src/Makefile | 41 ++++++++++++++++++++++++++++++++++------- src/ao_teleterra.c | 1 - src/skytraq-cksum | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/skytraq-cksum diff --git a/.gitignore b/.gitignore index 0ca4bed4..a6f94439 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ TAGS aclocal.m4 src/ao_flight_test src/ao_gps_test +src/ao_gps_test_skytraq ao-teledongle.h ao-telemetrum.h ao-teleterra.h @@ -47,6 +48,7 @@ missing stamp-h1 tags teledongle -telemetrum +telemetrum-sirf +telemetrum-sky teleterra tidongle diff --git a/src/Makefile b/src/Makefile index 892635cb..9891cdad 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,6 @@ TELE_RECEIVER_SRC =\ TELE_DRIVER_SRC = \ ao_convert.c \ - ao_gps_skytraq.c \ ao_serial.c # @@ -84,6 +83,17 @@ TM_DRIVER_SRC = \ ao_gps_report.c \ ao_ignite.c +# +# Drivers only on TeleMetrum +# +TM_SIRF_DRIVER_SRC = \ + ao_gps_sirf.c +# +# Drivers only on TeleMetrum +# +TM_SKY_DRIVER_SRC = \ + ao_gps_skytraq.c + # # Tasks run on TeleMetrum # @@ -108,6 +118,14 @@ TM_SRC = \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) +TM_SIRF_SRC = \ + $(TM_SRC) \ + $(TM_SIRF_DRIVER_SRC) + +TM_SKY_SRC = \ + $(TM_SRC) \ + $(TM_SKY_DRIVER_SRC) + TI_MAIN_SRC = \ ao_tidongle.c @@ -161,13 +179,16 @@ SRC = \ $(TELE_COMMON_SRC) \ $(TELE_FAKE_SRC) \ $(TM_DRIVER_SRC) \ + $(TM_SIRF_DRIVER_SRC) \ + $(TM_SKY_DRIVER_SRC) \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) \ $(TI_MAIN_SRC) \ $(TD_MAIN_SRC) \ $(TT_MAIN_SRC) -TM_REL=$(TM_SRC:.c=.rel) ao_product-telemetrum.rel +TM_SIRF_REL=$(TM_SIRF_SRC:.c=.rel) ao_product-telemetrum.rel +TM_SKY_REL=$(TM_SKY_SRC:.c=.rel) ao_product-telemetrum.rel TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel @@ -186,7 +207,7 @@ LST=$(REL:.rel=.lst) RST=$(REL:.rel=.rst) SYM=$(REL:.rel=.sym) -PROGS= telemetrum.ihx tidongle.ihx \ +PROGS= telemetrum-sirf.ihx telemetrum-sky.ihx tidongle.ihx \ teleterra.ihx teledongle.ihx HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq @@ -202,15 +223,21 @@ PAOM=$(PROGS:.ihx=) all: $(PROGS) $(HOST_PROGS) -telemetrum.ihx: $(TM_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_REL) - sh check-stack ao.h telemetrum.mem +telemetrum-sirf.ihx: $(TM_SIRF_REL) Makefile + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SIRF_REL) + sh check-stack ao.h telemetrum-sirf.mem + +telemetrum-sky.ihx: $(TM_SKY_REL) Makefile + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SKY_REL) + sh check-stack ao.h telemetrum-sky.mem + +telemetrum-sky.ihx: telemetrum-sirf.ihx tidongle.ihx: $(TI_REL) Makefile $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL) sh check-stack ao.h tidongle.mem -tidongle.ihx: telemetrum.ihx +tidongle.ihx: telemetrum-sky.ihx teleterra.ihx: $(TT_REL) Makefile $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL) diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c index deb63597..d696b914 100644 --- a/src/ao_teleterra.c +++ b/src/ao_teleterra.c @@ -31,7 +31,6 @@ main(void) ao_cmd_init(); ao_usb_init(); ao_serial_init(); - ao_gps_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_radio_init(); ao_config_init(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum new file mode 100644 index 00000000..e4960bff --- /dev/null +++ b/src/skytraq-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum ^= msg[i]; + sum &= 0xff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa1, 0x02x, 0x%02x,\t\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x0d, 0x0a,\n", + csum); +} + +main(); -- cgit v1.2.3 From e29961fdb2a48874c895829880eadbf13e094c0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 11:43:31 -0700 Subject: Add channel menu to ao-view. Sets radio channel when TD is connected, saves selected channel in gconf database. Signed-off-by: Keith Packard --- ao-tools/ao-view/Makefile.am | 1 + ao-tools/ao-view/aoview.glade | 101 ++++++++++++++++++++++++++++++++++++++ ao-tools/ao-view/aoview.h | 11 +++++ ao-tools/ao-view/aoview_channel.c | 90 +++++++++++++++++++++++++++++++++ ao-tools/ao-view/aoview_main.c | 2 + ao-tools/ao-view/aoview_monitor.c | 12 +++++ 6 files changed, 217 insertions(+) create mode 100644 ao-tools/ao-view/aoview_channel.c diff --git a/ao-tools/ao-view/Makefile.am b/ao-tools/ao-view/Makefile.am index 7b274a40..7a288417 100644 --- a/ao-tools/ao-view/Makefile.am +++ b/ao-tools/ao-view/Makefile.am @@ -25,6 +25,7 @@ ao_view_SOURCES = \ aoview_replay.c \ aoview_label.c \ aoview_flite.c \ + aoview_channel.c \ aoview.h BUILT_SOURCES = aoview_glade.h diff --git a/ao-tools/ao-view/aoview.glade b/ao-tools/ao-view/aoview.glade index 9a746110..c302ad0d 100644 --- a/ao-tools/ao-view/aoview.glade +++ b/ao-tools/ao-view/aoview.glade @@ -257,6 +257,107 @@ + + + True + _Channel + True + + + True + + + True + Channel 0 (434.550MHz) + True + True + + + + + True + Channel 1 (434.650MHz) + True + True + channel_0 + + + + + True + Channel 2 (434.750MHz) + True + True + channel_0 + + + + + True + Channel 3 (434.850MHz) + True + True + channel_0 + + + + + True + Channel 4 (434.950MHz) + True + True + channel_0 + + + + + True + Channel 5 (435.050MHz) + True + True + channel_0 + + + + + True + Channel 6 (435.150MHz) + True + True + channel_0 + + + + + True + Channel 7 (435.250MHz) + True + True + channel_0 + + + + + True + Channel 8 (435.350MHz) + True + True + channel_0 + + + + + True + Channel 9 (435.450MHz) + True + True + channel_0 + + + + + + True diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h index 6a4753ac..c582159c 100644 --- a/ao-tools/ao-view/aoview.h +++ b/ao-tools/ao-view/aoview.h @@ -168,6 +168,9 @@ aoview_monitor_connect(char *tty); gboolean aoview_monitor_parse(const char *line); +void +aoview_monitor_set_channel(int channel); + void aoview_monitor_reset(void); @@ -320,4 +323,12 @@ aoview_flite_stop(void); extern char *aoview_tty; +/* aoview_channel.c */ + +int +aoview_channel_current(void); + +void +aoview_channel_init(GladeXML *xml); + #endif /* _AOVIEW_H_ */ diff --git a/ao-tools/ao-view/aoview_channel.c b/ao-tools/ao-view/aoview_channel.c new file mode 100644 index 00000000..959173ca --- /dev/null +++ b/ao-tools/ao-view/aoview_channel.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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 "aoview.h" + + +#define NUM_CHANNEL 10 + +static GtkRadioMenuItem *channel_item[NUM_CHANNEL]; + +int +aoview_channel_current(void) +{ + int c; + + for (c = 0; c < NUM_CHANNEL; c++) + if(gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(channel_item[c]))) + return c; + return -1; +} + +static void +aoview_channel_notify(int channel) +{ + if (0 <= channel && channel < NUM_CHANNEL) + gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(channel_item[channel]), TRUE); +} + +#define ALTOS_CHANNEL_PATH "/apps/aoview/channel" + +static void +aoview_channel_change(GtkWidget *widget, gpointer data) +{ + gboolean enabled = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget)); + int c = (int) data; + GConfClient *gconf_client; + GError *error; + + if (enabled) { + aoview_monitor_set_channel(c); + gconf_client = gconf_client_get_default(); + gconf_client_set_int(gconf_client, ALTOS_CHANNEL_PATH, c, &error); + } +} + +void +aoview_channel_init(GladeXML *xml) +{ + int c; + GConfClient *gconf_client; + + for (c = 0; c < NUM_CHANNEL; c++) { + char name[32]; + + sprintf(name, "channel_%d", c); + channel_item[c] = GTK_RADIO_MENU_ITEM(glade_xml_get_widget(xml, name)); + assert(channel_item[c]); + g_signal_connect(G_OBJECT(channel_item[c]), "toggled", + G_CALLBACK(aoview_channel_change), + (gpointer) c); + } + gconf_client = gconf_client_get_default(); + c = 0; + if (gconf_client) + { + GError *error; + + error = NULL; + c = gconf_client_get_int(gconf_client, + ALTOS_CHANNEL_PATH, + &error); + if (error) + c = 0; + } + aoview_channel_notify(c); +} diff --git a/ao-tools/ao-view/aoview_main.c b/ao-tools/ao-view/aoview_main.c index 64c1c027..714bee9a 100644 --- a/ao-tools/ao-view/aoview_main.c +++ b/ao-tools/ao-view/aoview_main.c @@ -86,6 +86,8 @@ int main(int argc, char **argv) aoview_voice_init(xml); + aoview_channel_init(xml); + aoview_dev_dialog_init(xml); aoview_state_init(xml); diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 8564014b..48e20320 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -82,6 +82,7 @@ aoview_monitor_parse(const char *input_line) char line_buf[8192], *line; struct aodata data; int tracking_pos; + int channel; /* avoid smashing our input parameter */ strncpy (line_buf, input_line, sizeof (line_buf)-1); @@ -214,15 +215,26 @@ aoview_monitor_callback(gpointer user_data, } } +void +aoview_monitor_set_channel(int channel) +{ + if (monitor_serial) + aoview_serial_printf(monitor_serial, "c r %d\n", channel); +} + gboolean aoview_monitor_connect(char *tty) { + int channel; aoview_monitor_disconnect(); monitor_serial = aoview_serial_open(tty); if (!monitor_serial) return FALSE; aoview_table_clear(); aoview_state_reset(); + channel = aoview_channel_current(); + if (channel >= 0) + aoview_monitor_set_channel(channel); aoview_serial_set_callback(monitor_serial, aoview_monitor_callback); return TRUE; -- cgit v1.2.3 From b8fc3975bd92037a0cf53b0ff2b0e05ce0ba668f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 13:39:01 -0700 Subject: Send 0-length IN packet to flush USB after full packet USB bulk transfers are a sequence of maximum-sized packets followed by a short packet, which signals the end of the transfer. When the last packet of the transfer would be a full-sized packet, an additional packet of zero length is sent to signal the transfer end. Signed-off-by: Keith Packard --- src/ao_usb.c | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/ao_usb.c b/src/ao_usb.c index 99f0715b..22665725 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -21,6 +21,7 @@ struct ao_task __xdata ao_usb_task; static __xdata uint16_t ao_usb_in_bytes; +static __xdata uint16_t ao_usb_in_bytes_last; static __xdata uint16_t ao_usb_out_bytes; static __xdata uint8_t ao_usb_iif; static __xdata uint8_t ao_usb_running; @@ -321,13 +322,40 @@ ao_usb_ep0(void) } } +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + USBINDEX = AO_USB_IN_EP; + if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) + break; + ao_sleep(&ao_usb_in_bytes); + } +} + +/* Send the current IN packet */ +static void +ao_usb_in_send(void) +{ + USBINDEX = AO_USB_IN_EP; + USBCSIL |= USBCSIL_INPKT_RDY; + ao_usb_in_bytes_last = ao_usb_in_bytes; + ao_usb_in_bytes = 0; +} + void ao_usb_flush(void) __critical { - if (ao_usb_in_bytes) { - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes = 0; + if (!ao_usb_running) + return; + + /* If there are pending bytes, or if the last packet was full, + * send another IN packet + */ + if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { + ao_usb_in_wait(); + ao_usb_in_send(); } } @@ -336,18 +364,13 @@ ao_usb_putchar(char c) __critical { if (!ao_usb_running) return; - for (;;) { - USBINDEX = AO_USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - ao_sleep(&ao_usb_in_bytes); - } + + ao_usb_in_wait(); + + /* Queue a byte, sending the packet when full */ USBFIFO[AO_USB_IN_EP << 1] = c; - if (++ao_usb_in_bytes == AO_USB_IN_SIZE) { - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes = 0; - } + if (++ao_usb_in_bytes == AO_USB_IN_SIZE) + ao_usb_in_send(); } char -- cgit v1.2.3 From 5f26ad663b3f60dddc9d967206e365f45dc4acd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 13:58:16 -0700 Subject: ao-dumplog: switch to 'e' command, display progress Using the 'e' command allows additional checking of the data, including end-to-end checksums and detection of missing data. Progress is displayed by showing the recorded flight state along with a '.' for each eeprom block read. Signed-off-by: Keith Packard --- ao-tools/ao-dumplog/ao-dumplog.c | 95 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 86 insertions(+), 9 deletions(-) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index b930f0e5..158a445b 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -37,6 +37,30 @@ static void usage(char *program) exit(1); } +static uint8_t +log_checksum(int d[8]) +{ + uint8_t sum = 0x5a; + int i; + + for (i = 0; i < 8; i++) + sum += (uint8_t) d[i]; + return -sum; +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + int main (int argc, char **argv) { @@ -50,6 +74,12 @@ main (int argc, char **argv) int serial_number; char cmd; int tick, a, b; + int block; + int addr; + int received_addr; + int data[8]; + int done; + int column; while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { @@ -74,12 +104,10 @@ main (int argc, char **argv) if (!cc) exit(1); /* send a 'version' command followed by a 'log' command */ - cc_usb_printf(cc, "v\nl\n"); + cc_usb_printf(cc, "v\n"); out = NULL; for (;;) { cc_usb_getline(cc, line, sizeof (line)); - if (!strcmp (line, "end")) - break; if (sscanf(line, "serial-number %u", &serial_number) == 1) { filename = cc_make_filename(serial_number, "eeprom"); out = fopen (filename, "w"); @@ -87,16 +115,65 @@ main (int argc, char **argv) perror(filename); } fprintf (out, "%s\n", line); - } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { - if (out) { - fprintf(out, "%s\n", line); - if (cmd == 'S' && a == 8) { - fclose(out); - out = NULL; + } + if (!strncmp(line, "software-version", 16)) + break; + } + if (!out) { + fprintf(stderr, "no serial number found\n"); + cc_usb_close(cc); + exit(1); + } + printf ("Serial number: %d\n", serial_number); + printf ("File name: %s\n", filename); + done = 0; + column = 0; + for (block = 0; !done && block < 511; block++) { + cc_usb_printf(cc, "e %x\n", block); + if (column == 64) { + putchar('\n'); + column = 0; + } + putchar('.'); fflush(stdout); column++; + for (addr = 0; addr < 0x100;) { + cc_usb_getline(cc, line, sizeof (line)); + if (sscanf(line, "00%x %x %x %x %x %x %x %x %x", + &received_addr, + &data[0], &data[1], &data[2], &data[3], + &data[4], &data[5], &data[6], &data[7]) == 9) + { + if (received_addr != addr) + fprintf(stderr, "data out of sync at 0x%x\n", + block * 256 + received_addr); + + if (log_checksum(data) != 0) + fprintf (stderr, "invalid checksum at 0x%x\n", + block * 256 + received_addr); + + cmd = data[0]; + tick = data[2] + (data[3] << 8); + a = data[4] + (data[5] << 8); + b = data[6] + (data[7] << 8); + if (cmd == 'S' && a <= 8) { + if (column) putchar('\n'); + printf("%s\n", state_names[a]); + column = 0; + } + if (out) { + fprintf(out, "%c %4x %4x %4x\n", + cmd, tick, a, b); + if (cmd == 'S' && a == 8) { + fclose(out); + out = NULL; + done = 1; + } } + addr += 8; } } } + if (column) + putchar('\n'); if (out) fclose (out); cc_usb_close(cc); -- cgit v1.2.3 From adf8764bc4591795ba4e618ccbd6393fc6ce6450 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 10 Oct 2009 15:11:23 -0600 Subject: update changelogs for Debian build --- ChangeLog | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 +++++ 2 files changed, 75 insertions(+) diff --git a/ChangeLog b/ChangeLog index 56d1495f..de5b1978 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,72 @@ +commit 541da6f3bbf81be93dfe3c01f7c8cfd757b28a2b +Merge: dfc73cb 5f26ad6 +Author: Bdale Garbee +Date: Sat Oct 10 15:05:50 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 5f26ad663b3f60dddc9d967206e365f45dc4acd1 +Author: Keith Packard +Date: Sat Oct 10 13:58:16 2009 -0700 + + ao-dumplog: switch to 'e' command, display progress + + Using the 'e' command allows additional checking of the data, + including end-to-end checksums and detection of missing data. + + Progress is displayed by showing the recorded flight state along with + a '.' for each eeprom block read. + + Signed-off-by: Keith Packard + +commit b8fc3975bd92037a0cf53b0ff2b0e05ce0ba668f +Author: Keith Packard +Date: Sat Oct 10 13:39:01 2009 -0700 + + Send 0-length IN packet to flush USB after full packet + + USB bulk transfers are a sequence of maximum-sized packets followed by + a short packet, which signals the end of the transfer. When the last + packet of the transfer would be a full-sized packet, an additional + packet of zero length is sent to signal the transfer end. + + Signed-off-by: Keith Packard + +commit e29961fdb2a48874c895829880eadbf13e094c0c +Author: Keith Packard +Date: Sat Oct 10 11:43:31 2009 -0700 + + Add channel menu to ao-view. + + Sets radio channel when TD is connected, saves selected channel in + gconf database. + + Signed-off-by: Keith Packard + +commit a3771bfc5ce740f9d89193e9f8b1d7987aa57264 +Author: Keith Packard +Date: Tue Oct 6 20:06:00 2009 -0700 + + ao-view: fix snd_pcm_open return checking + + I don't know how this code was supposed to work before... + + Signed-off-by: Keith Packard + +commit ac4b8a73848f434999a532eab4665253c267c597 +Author: Keith Packard +Date: Tue Oct 6 20:05:36 2009 -0700 + + ao-postflight: dump out GPS signal data + + Signed-off-by: Keith Packard + +commit dfc73cba1bee8b121e00e8cba45e7dfaaf79e9d8 +Author: Bdale Garbee +Date: Mon Sep 21 22:46:59 2009 -0700 + + update changelogs for Debian build + commit 459ff3d377297f80ee2fba0df0a29ff6603467a1 Author: Bdale Garbee Date: Mon Sep 21 11:00:32 2009 -0700 diff --git a/debian/changelog b/debian/changelog index 2aaa3c3c..e536c536 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+73+g541da6f) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Sat, 10 Oct 2009 15:11:23 -0600 + altos (0.5+66+g459ff3d) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 8f7ea3de7037f40b0ff462b60d503c19431ae62b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 15:08:14 -0700 Subject: Report igniter continuity in pad/idle mode via beeper one short beep = drogue two short beeps = main three short beeps = both one long warble = neither In idle mode, it does this just once. In pad mode, it keeps testing and reporting. Signed-off-by: Keith Packard --- src/ao_report.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/ao_report.c b/src/ao_report.c index 14eaf428..3b469de6 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -97,6 +97,34 @@ ao_report_altitude(void) } } +static uint8_t +ao_report_igniter_ready(enum ao_igniter igniter) +{ + return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; +} + +static void +ao_report_continuity(void) __reentrant +{ + uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); + if (c) { + while (c--) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(25)); + pause(AO_MS_TO_TICKS(100)); + } + } else { + c = 10; + while (c--) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(20)); + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); + } + } + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); +} + void ao_report(void) { @@ -105,6 +133,10 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); + if (ao_flight_state == ao_flight_idle) + ao_report_continuity(); + while (ao_flight_state == ao_flight_pad) + ao_report_continuity(); __critical { while (ao_report_state == ao_flight_state) ao_sleep(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From 2b765728ce177e26899f6feef00bfdf6aeaf2678 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 17:15:38 -0700 Subject: Add apogee igniter delay. Provide for a delay after apogee before the drogue charge is fired. This allows TM to be used as a back-up altimeter. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_config.c | 39 ++++++++++++++++++++++++++++++++++++--- src/ao_ignite.c | 4 ++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index 4116be65..f89568f2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -860,7 +860,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 0 +#define AO_CONFIG_MINOR 1 struct ao_config { uint8_t major; @@ -869,6 +869,7 @@ struct ao_config { int16_t accel_zero_g; uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; + uint8_t apogee_delay; }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 657c7a8a..021fb6f6 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -26,6 +26,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 #define AO_CONFIG_DEFAULT_CALLSIGN "KD7SQG" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 +#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 static void _ao_config_put(void) @@ -48,9 +49,16 @@ _ao_config_get(void) memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config_dirty = 1; + } + if (ao_config.minor < AO_CONFIG_MINOR) { + /* Fixups for major version 1 */ + if (ao_config.minor < 1) + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } - /* deal with minor version issues here, at 0 we haven't any */ ao_config_loaded = 1; } @@ -124,7 +132,7 @@ ao_config_radio_channel_set(void) __reentrant void ao_config_main_deploy_show(void) __reentrant { - printf("Main deploy set to %d meters (%d feet)\n", + printf("Main deploy: %d meters (%d feet)\n", ao_config.main_deploy, (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100)); } @@ -146,7 +154,7 @@ ao_config_main_deploy_set(void) __reentrant void ao_config_accel_zero_g_show(void) __reentrant { - printf("Accel zero g point set to %d\n", + printf("Accel zero g point: %d\n", ao_config.accel_zero_g); } @@ -189,6 +197,27 @@ ao_config_accel_zero_g_set(void) __reentrant ao_config_accel_zero_g_show(); } +void +ao_config_apogee_delay_show(void) __reentrant +{ + printf("Apogee delay: %d seconds\n", + ao_config.apogee_delay); +} + +void +ao_config_apogee_delay_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.apogee_delay = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_apogee_delay_show(); +} + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -214,6 +243,8 @@ __code struct ao_config_var ao_config_vars[] = { "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, + { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, + "d Set apogee igniter delay (in seconds)" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, { 'w', ao_config_write, ao_config_write, @@ -258,6 +289,8 @@ void ao_config_show(void) __reentrant { uint8_t cmd; + printf("Config version: %d.%d\n", + ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) (*ao_config_vars[cmd].show)(); diff --git a/src/ao_ignite.c b/src/ao_ignite.c index be291523..8206e342 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -103,10 +103,14 @@ ao_igniter(void) __xdata enum ao_ignter igniter; __xdata enum ao_igniter_status status; + ao_config_get(); for (;;) { ao_sleep(&ao_ignition); for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + ao_igniter_fire(igniter); ao_delay(AO_IGNITER_CHARGE_TIME); status = ao_igniter_status(igniter); -- cgit v1.2.3 From 6c4cdc927b43736b39be29d23ac3dc723f69e4d6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 15:57:19 -0600 Subject: update changelogs for Debian build --- ChangeLog | 40 ++++++++++++++++++++++++++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 46 insertions(+) diff --git a/ChangeLog b/ChangeLog index de5b1978..83023fd3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +commit c57bd7fd2f80e50b0b4c87fccb024ab07c93773d +Merge: adf8764 2b76572 +Author: Bdale Garbee +Date: Mon Oct 12 15:57:08 2009 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 2b765728ce177e26899f6feef00bfdf6aeaf2678 +Author: Keith Packard +Date: Sat Oct 10 17:15:38 2009 -0700 + + Add apogee igniter delay. + + Provide for a delay after apogee before the drogue charge is + fired. This allows TM to be used as a back-up altimeter. + + Signed-off-by: Keith Packard + +commit 8f7ea3de7037f40b0ff462b60d503c19431ae62b +Author: Keith Packard +Date: Sat Oct 10 15:08:14 2009 -0700 + + Report igniter continuity in pad/idle mode via beeper + + one short beep = drogue + two short beeps = main + three short beeps = both + one long warble = neither + + In idle mode, it does this just once. In pad mode, it keeps testing + and reporting. + + Signed-off-by: Keith Packard + +commit adf8764bc4591795ba4e618ccbd6393fc6ce6450 +Author: Bdale Garbee +Date: Sat Oct 10 15:11:23 2009 -0600 + + update changelogs for Debian build + commit 541da6f3bbf81be93dfe3c01f7c8cfd757b28a2b Merge: dfc73cb 5f26ad6 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index e536c536..4c503f86 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+77+gc57bd7f) unstable; urgency=low + + * build for Debian from git + + -- Bdale Garbee Mon, 12 Oct 2009 15:57:19 -0600 + altos (0.5+73+g541da6f) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 241a860fe856b1dfad6e792736313648300d5c24 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:48:43 -0600 Subject: flush repetitive junk out of debian/changelog, and update the prebuild target in debian/rules to put git commit details into the Debian changelog --- debian/changelog | 137 ------------------------------------------------------- debian/rules | 2 +- 2 files changed, 1 insertion(+), 138 deletions(-) diff --git a/debian/changelog b/debian/changelog index 4c503f86..e886205e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,140 +4,3 @@ altos (0.5+77+gc57bd7f) unstable; urgency=low -- Bdale Garbee Mon, 12 Oct 2009 15:57:19 -0600 -altos (0.5+73+g541da6f) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sat, 10 Oct 2009 15:11:23 -0600 - -altos (0.5+66+g459ff3d) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Mon, 21 Sep 2009 22:46:58 -0700 - -altos (0.5+65+g327c643) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Mon, 21 Sep 2009 11:00:31 -0700 - -altos (0.5+60+gdf42cca) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 20 Sep 2009 09:21:00 -0600 - -altos (0.5+53+ga5e94aa) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 18:01:20 -0600 - -altos (0.5+51+g3f95a5a) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 17:48:22 -0600 - -altos (0.5+49+gae4e131) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 17:47:56 -0600 - -altos (0.5+48+g37e6c9a) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 17:46:39 -0600 - -altos (0.5+43+g4b0de75) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 14:15:57 -0600 - -altos (0.5+39+g45ede4a) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 14:05:55 -0600 - -altos (0.5+36+gd42ebf0) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 14:02:14 -0600 - -altos (0.5+33+g35c54b3) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Sun, 06 Sep 2009 10:40:06 -0600 - -altos (0.5+27+g332b056) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Fri, 04 Sep 2009 16:03:55 -0600 - -altos (0.5+19+gcb4a73f) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Wed, 02 Sep 2009 23:18:15 -0600 - -altos (0.5+13+g6926c4a) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Mon, 31 Aug 2009 16:48:03 -0600 - -altos (0.5+11+gc8c5b79) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Mon, 31 Aug 2009 16:42:55 -0600 - -altos (0.5+9+gb34474c) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Mon, 31 Aug 2009 16:26:00 -0600 - -altos (0.4+98+g42ab6d5) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Wed, 19 Aug 2009 02:21:23 -0600 - -altos (0.4+96+g8d4d665) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Wed, 19 Aug 2009 02:11:11 -0600 - -altos (0.4+94+g21e3dd0) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Wed, 19 Aug 2009 02:07:16 -0600 - -altos (0.4+92+g4486d91) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Wed, 19 Aug 2009 00:52:57 -0600 - -altos (0.4+88+gcd5ce66) unstable; urgency=low - - * build for Debian from git - - -- Bdale Garbee Tue, 18 Aug 2009 21:57:00 -0600 - -altos (0) unstable; urgency=low - - * Initial packaging - - -- Bdale Garbee Tue, 18 Aug 2009 11:43:43 -0600 diff --git a/debian/rules b/debian/rules index 74cc078d..0033fcbe 100755 --- a/debian/rules +++ b/debian/rules @@ -6,7 +6,7 @@ PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: - dch -v `git describe | tr - +` "build for Debian from git" + git-dch --release --new-version=`git describe | tr - +` git log > ChangeLog git commit ChangeLog debian/changelog \ -m "update changelogs for Debian build" -- cgit v1.2.3 From 8d4aa4ee54f85f4951cdd7293d58aaa405cfcdc5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:49:34 -0600 Subject: update changelogs for Debian build --- ChangeLog | 13 +++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/ChangeLog b/ChangeLog index 83023fd3..cfc37bce 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +commit 241a860fe856b1dfad6e792736313648300d5c24 +Author: Bdale Garbee +Date: Mon Oct 12 16:48:43 2009 -0600 + + flush repetitive junk out of debian/changelog, and update the prebuild target + in debian/rules to put git commit details into the Debian changelog + +commit 6c4cdc927b43736b39be29d23ac3dc723f69e4d6 +Author: Bdale Garbee +Date: Mon Oct 12 15:57:19 2009 -0600 + + update changelogs for Debian build + commit c57bd7fd2f80e50b0b4c87fccb024ab07c93773d Merge: adf8764 2b76572 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index e886205e..11f0b5cf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.5+79+g241a860) unstable; urgency=low + + * flush repetitive junk out of debian/changelog, and update the + prebuild target + + -- Bdale Garbee Mon, 12 Oct 2009 16:49:23 -0600 + altos (0.5+77+gc57bd7f) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 7da56ad8576ef212ffb6cb573bdaf578453e3fe0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:52:52 -0600 Subject: add support for tagging git repository on each Debian package build --- debian/rules | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 0033fcbe..384bacf6 100755 --- a/debian/rules +++ b/debian/rules @@ -3,13 +3,15 @@ export DH_VERBOSE=1 PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') +DEB_VERSION := $(shell git describe | tr - +) # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: - git-dch --release --new-version=`git describe | tr - +` + git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog git commit ChangeLog debian/changelog \ -m "update changelogs for Debian build" + git tag debian/$(DEB_VERSION) configure: configure-stamp configure-stamp: -- cgit v1.2.3 From 23bc21a93ccb9f35917f283ac5df6ce0870df71a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:54:16 -0600 Subject: undue damage from partial build --- debian/changelog | 7 ------- 1 file changed, 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index 11f0b5cf..e886205e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,3 @@ -altos (0.5+79+g241a860) unstable; urgency=low - - * flush repetitive junk out of debian/changelog, and update the - prebuild target - - -- Bdale Garbee Mon, 12 Oct 2009 16:49:23 -0600 - altos (0.5+77+gc57bd7f) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 67bf7d388a6dd2dbf65575bf4f0423ad355b4f2f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:54:44 -0600 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 8 ++++++++ 2 files changed, 26 insertions(+) diff --git a/ChangeLog b/ChangeLog index cfc37bce..c04c1027 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 23bc21a93ccb9f35917f283ac5df6ce0870df71a +Author: Bdale Garbee +Date: Mon Oct 12 16:54:16 2009 -0600 + + undue damage from partial build + +commit 7da56ad8576ef212ffb6cb573bdaf578453e3fe0 +Author: Bdale Garbee +Date: Mon Oct 12 16:52:52 2009 -0600 + + add support for tagging git repository on each Debian package build + +commit 8d4aa4ee54f85f4951cdd7293d58aaa405cfcdc5 +Author: Bdale Garbee +Date: Mon Oct 12 16:49:34 2009 -0600 + + update changelogs for Debian build + commit 241a860fe856b1dfad6e792736313648300d5c24 Author: Bdale Garbee Date: Mon Oct 12 16:48:43 2009 -0600 diff --git a/debian/changelog b/debian/changelog index e886205e..89d87b4c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +altos (0.5+82+g23bc21a) unstable; urgency=low + + * flush repetitive junk out of debian/changelog, and update the + prebuild target + * add support for tagging git repository on each Debian package build + + -- Bdale Garbee Mon, 12 Oct 2009 16:54:28 -0600 + altos (0.5+77+gc57bd7f) unstable; urgency=low * build for Debian from git -- cgit v1.2.3 From 513328ac5f7c25f9ee144ab6befbea60d69eed1a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:56:50 -0600 Subject: automate push of updated and tagged master branch during debian/rules prebuild --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index 384bacf6..f306f1df 100755 --- a/debian/rules +++ b/debian/rules @@ -12,6 +12,7 @@ prebuild: git commit ChangeLog debian/changelog \ -m "update changelogs for Debian build" git tag debian/$(DEB_VERSION) + git push --tags master configure: configure-stamp configure-stamp: -- cgit v1.2.3 From 68008ac11c2735ca53a1b474324df43f2f1d5cdd Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:57:33 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c04c1027..3415e58d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 513328ac5f7c25f9ee144ab6befbea60d69eed1a +Author: Bdale Garbee +Date: Mon Oct 12 16:56:50 2009 -0600 + + automate push of updated and tagged master branch during debian/rules prebuild + +commit 67bf7d388a6dd2dbf65575bf4f0423ad355b4f2f +Author: Bdale Garbee +Date: Mon Oct 12 16:54:44 2009 -0600 + + update changelogs for Debian build + commit 23bc21a93ccb9f35917f283ac5df6ce0870df71a Author: Bdale Garbee Date: Mon Oct 12 16:54:16 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 89d87b4c..92c97471 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,5 +1,7 @@ -altos (0.5+82+g23bc21a) unstable; urgency=low +altos (0.5+84+g513328a) unstable; urgency=low + * automate push of updated and tagged master branch during + debian/rules prebuild * flush repetitive junk out of debian/changelog, and update the prebuild target * add support for tagging git repository on each Debian package build -- cgit v1.2.3 From 2de548f45d0f50b558acc83f57e1e2fc1223ab92 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:58:19 -0600 Subject: oops, forgot to specify the repo to push to --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index f306f1df..ac594c07 100755 --- a/debian/rules +++ b/debian/rules @@ -12,7 +12,7 @@ prebuild: git commit ChangeLog debian/changelog \ -m "update changelogs for Debian build" git tag debian/$(DEB_VERSION) - git push --tags master + git push --tags origin master configure: configure-stamp configure-stamp: -- cgit v1.2.3 From 550482d953c491a5ede9f2d243493afb13289898 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 12 Oct 2009 16:58:46 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3415e58d..37c80609 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 2de548f45d0f50b558acc83f57e1e2fc1223ab92 +Author: Bdale Garbee +Date: Mon Oct 12 16:58:19 2009 -0600 + + oops, forgot to specify the repo to push to + +commit 68008ac11c2735ca53a1b474324df43f2f1d5cdd +Author: Bdale Garbee +Date: Mon Oct 12 16:57:33 2009 -0600 + + update changelogs for Debian build + commit 513328ac5f7c25f9ee144ab6befbea60d69eed1a Author: Bdale Garbee Date: Mon Oct 12 16:56:50 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 92c97471..44204885 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.5+84+g513328a) unstable; urgency=low +altos (0.5+86+g2de548f) unstable; urgency=low * automate push of updated and tagged master branch during debian/rules prebuild -- cgit v1.2.3 From d709a0688eff84e25e24d755850ef045d6b0c3de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Oct 2009 12:56:45 +0900 Subject: Save some DSEG space by marking cmd functions __reentrant __reentrant causes the compiler to place args and locals on the stack instead of in the data segment. Signed-off-by: Keith Packard --- src/ao_adc.c | 4 ++-- src/ao_ee.c | 20 ++++++++++---------- src/ao_flight.c | 2 +- src/ao_gps_sirf.c | 2 +- src/ao_log.c | 2 +- src/ao_usb.c | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ao_adc.c b/src/ao_adc.c index 26209dcf..d9672671 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -61,9 +61,9 @@ ao_adc_isr(void) interrupt 1 } static void -ao_adc_dump(void) +ao_adc_dump(void) __reentrant { - __xdata struct ao_adc packet; + static __xdata struct ao_adc packet; ao_adc_get(&packet); printf("tick: %5u accel: %4d pres: %4d temp: %4d batt: %4d drogue: %4d main: %4d\n", packet.tick, packet.accel >> 4, packet.pres >> 4, packet.temp >> 4, diff --git a/src/ao_ee.c b/src/ao_ee.c index 9b6db234..26cfb7fd 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -351,11 +351,11 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant } static void -ee_dump(void) +ee_dump(void) __reentrant { - __xdata uint8_t b; - __xdata uint16_t block; - __xdata uint8_t i; + uint8_t b; + uint16_t block; + uint8_t i; ao_cmd_hex(); block = ao_cmd_lex_i; @@ -377,13 +377,13 @@ ee_dump(void) } static void -ee_store(void) +ee_store(void) __reentrant { - __xdata uint16_t block; - __xdata uint8_t i; - __xdata uint16_t len; - __xdata uint8_t b; - __xdata uint32_t addr; + uint16_t block; + uint8_t i; + uint16_t len; + uint8_t b; + uint32_t addr; ao_cmd_hex(); block = ao_cmd_lex_i; diff --git a/src/ao_flight.c b/src/ao_flight.c index ec89e7c2..c43d0711 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -458,7 +458,7 @@ ao_flight(void) #define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700)) static void -ao_flight_status(void) +ao_flight_status(void) __reentrant { printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", ao_state_names[ao_flight_state], diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 2b3a5178..58438760 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -302,7 +302,7 @@ static const char ao_gps_set_message_rate[] = { }; void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant { uint16_t cksum = 0x00a6; uint8_t i; diff --git a/src/ao_log.c b/src/ao_log.c index 7945ace4..b2bfbd6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -192,7 +192,7 @@ ao_log_stop(void) } static void -dump_log(void) +dump_log(void) __reentrant { uint8_t more; diff --git a/src/ao_usb.c b/src/ao_usb.c index 22665725..8926b9ca 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -72,7 +72,7 @@ uint8_t * __xdata ao_usb_ep0_in_data; __xdata uint8_t ao_usb_ep0_in_len; __xdata uint8_t ao_usb_ep0_in_buf[2]; __xdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__data ao_usb_ep0_out_data; +__xdata uint8_t *__xdata ao_usb_ep0_out_data; __xdata uint8_t ao_usb_configuration; /* Send an IN data packet */ -- cgit v1.2.3 From b657aa209b9ea3b3efd33a940283b3ba60a169af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Oct 2009 12:59:53 +0900 Subject: Add ao_wake_task and ao_exit ao_wake_task signals a specific task to wake up. ao_exit terminates the current task. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_task.c | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index b6862a87..13271109 100644 --- a/src/ao.h +++ b/src/ao.h @@ -63,6 +63,10 @@ ao_sleep(__xdata void *wchan); void ao_wakeup(__xdata void *wchan); +/* Wake up a specific task */ +void +ao_wake_task(__xdata struct ao_task *task); + /* Yield the processor to another task */ void ao_yield(void) _naked; @@ -71,6 +75,10 @@ ao_yield(void) _naked; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; +/* Terminate the current task */ +void +ao_exit(void); + /* Dump task info to console */ void ao_task_info(void); diff --git a/src/ao_task.c b/src/ao_task.c index 12b73943..136444b0 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -93,7 +93,9 @@ ao_yield(void) _naked push _bp _endasm; - if (ao_cur_task_index != AO_NO_TASK_INDEX) + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else { uint8_t stack_len; __data uint8_t *stack_ptr; @@ -198,6 +200,24 @@ ao_wakeup(__xdata void *wchan) ao_tasks[i]->wchan = NULL; } +void +ao_wake_task(__xdata struct ao_task *task) +{ + task->wchan = NULL; +} + +void +ao_exit(void) +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + void ao_task_info(void) { -- cgit v1.2.3 From 690fc263516d8beb6b24e86fbcd6588f42ce4e5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Oct 2009 17:18:49 +0900 Subject: Add keyhole-markup generation for ao-postflight. This lets you see the flight path in googleearth. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 76 ++++++++++++++++++++++++++++++++-- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index cc9f64b4..60d8c036 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -161,8 +161,33 @@ merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split return pd; } +static const char kml_header[] = + "\n" + "\n" + " \n" + " gps\n" + " \n" + " \n" + " \n" + " 1\n" + " absolute\n" + " \n"; + +static const char kml_footer[] = + "\n" + " \n" + " \n" + "\n" + "\n"; + static void -analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name, FILE *gps_file) +analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, + FILE *raw_file, char *plot_name, FILE *gps_file, FILE *kml_file) { double height; double accel; @@ -339,6 +364,37 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FI fprintf(gps_file, " %d\n", nsat); } } + if (kml_file) { + int j = 0; + + fprintf(kml_file, "%s", kml_header); + for (i = 0; i < f->gps.num; i++) { + int nsat = 0; + int k; + while (j < f->gps.numsats - 1) { + if (f->gps.sats[j].sat[0].time <= f->gps.data[i].time && + f->gps.data[i].time < f->gps.sats[j+1].sat[0].time) + break; + j++; + } + nsat = 0; + for (k = 0; k < f->gps.sats[j].nsat; k++) + if (f->gps.sats[j].sat[k].state == 0xbf) + nsat++; + + fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", + f->gps.data[i].lon, + f->gps.data[i].lat, + f->gps.data[i].alt, + (f->gps.data[i].time - boost_start) / 100.0, + nsat); + if (i < f->gps.num - 1) + fprintf(kml_file, ",\n"); + else + fprintf(kml_file, "\n"); + } + fprintf(kml_file, "%s", kml_footer); + } if (cooked && plot_name) { struct cc_perioddata *speed; plsdev("svgcairo"); @@ -378,6 +434,7 @@ static const struct option options[] = { { .name = "plot", .has_arg = 1, .val = 'p' }, { .name = "raw", .has_arg = 1, .val = 'r' }, { .name = "gps", .has_arg = 1, .val = 'g' }, + { .name = "kml", .has_arg = 1, .val = 'k' }, { 0, 0, 0, 0}, }; @@ -389,6 +446,7 @@ static void usage(char *program) "\t[--raw= -r -p ]\n" "\t[--gps= -g ]\n" + "\t[--kml= -k ]\n" "\t{flight-log} ...\n", program); exit(1); } @@ -401,6 +459,7 @@ main (int argc, char **argv) FILE *detail_file = NULL; FILE *raw_file = NULL; FILE *gps_file = NULL; + FILE *kml_file = NULL; int i; int ret = 0; struct cc_flightraw *raw; @@ -412,8 +471,9 @@ main (int argc, char **argv) char *raw_name = NULL; char *plot_name = NULL; char *gps_name = NULL; + char *kml_name = NULL; - while ((c = getopt_long(argc, argv, "s:d:p:r:g:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "s:d:p:r:g:k:", options, NULL)) != -1) { switch (c) { case 's': summary_name = optarg; @@ -430,6 +490,9 @@ main (int argc, char **argv) case 'g': gps_name = optarg; break; + case 'k': + kml_name = optarg; + break; default: usage(argv[0]); break; @@ -468,6 +531,13 @@ main (int argc, char **argv) exit(1); } } + if (kml_name) { + kml_file = fopen(kml_name, "w"); + if (!kml_file) { + perror(kml_name); + exit(1); + } + } for (i = optind; i < argc; i++) { file = fopen(argv[i], "r"); if (!file) { @@ -488,7 +558,7 @@ main (int argc, char **argv) } if (!raw->serial) raw->serial = serial; - analyse_flight(raw, summary_file, detail_file, raw_file, plot_name, gps_file); + analyse_flight(raw, summary_file, detail_file, raw_file, plot_name, gps_file, kml_file); cc_flightraw_free(raw); } return ret; -- cgit v1.2.3 From 7b14c3e609749f4fc00dbd660541375048535218 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 16:39:15 -0700 Subject: Initial packet bits. Just testing transmission --- src/Makefile | 1 + src/ao.h | 65 ++++++----- src/ao_dma.c | 6 +- src/ao_gps_skytraq.c | 6 + src/ao_monitor.c | 4 +- src/ao_packet.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_radio.c | 70 +++++++++++- src/ao_teledongle.c | 1 + src/ao_telemetrum.c | 1 + src/skytraq-cksum | 2 +- 10 files changed, 427 insertions(+), 37 deletions(-) create mode 100644 src/ao_packet.c diff --git a/src/Makefile b/src/Makefile index 9891cdad..4575f443 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,6 +44,7 @@ ALTOS_DRIVER_SRC = \ TELE_COMMON_SRC = \ ao_gps_print.c \ + ao_packet.c \ ao_state.c # diff --git a/src/ao.h b/src/ao.h index 13271109..e86b4bf9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -138,7 +138,7 @@ ao_clock_init(void); * ao_adc.c */ -#define AO_ADC_RING 64 +#define AO_ADC_RING 32 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -349,9 +349,15 @@ ao_cmd_init(void); * ao_dma.c */ -/* Allocate a DMA channel. the 'done' parameter will be set to 1 - * when the dma is finished and will be used to wakeup any waiters +/* Allocate a DMA channel. the 'done' parameter will be set + * when the dma is finished or aborted and will be used to + * wakeup any waiters */ + +#define AO_DMA_DONE 1 +#define AO_DMA_ABORTED 2 +#define AO_DMA_TIMEOUT 4 + uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -374,7 +380,7 @@ ao_dma_trigger(uint8_t id); /* Abort a running DMA transfer */ void -ao_dma_abort(uint8_t id); +ao_dma_abort(uint8_t id, uint8_t reason); /* DMA interrupt routine */ void @@ -796,6 +802,19 @@ ao_telemetry_init(void); * ao_radio.c */ +extern __xdata uint8_t ao_radio_dma; +extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_mutex; + +void +ao_radio_set_telemetry(void); + +void +ao_radio_set_packet(void); + +void +ao_radio_set_rdf(void); + void ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; @@ -805,15 +824,21 @@ struct ao_radio_recv { uint8_t status; }; -void +uint8_t ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; void ao_radio_rdf(int ms); +void +ao_radio_abort(uint8_t reason); + void ao_radio_rdf_abort(void); +void +ao_radio_idle(void); + void ao_radio_init(void); @@ -943,35 +968,21 @@ struct ao_fifo { * Packet-based command interface */ -#define AO_PACKET_MAX 32 -#define AO_PACKET_WIN 256 - -#define AO_PACKET_FIN (1 << 0) -#define AO_PACKET_SYN (1 << 1) -#define AO_PACKET_RST (1 << 2) -#define AO_PACKET_ACK (1 << 3) +#define AO_PACKET_MAX 8 struct ao_packet { uint8_t addr; - uint8_t flags; - uint16_t seq; - uint16_t ack; - uint16_t window; uint8_t len; + uint8_t seq; + uint8_t ack; uint8_t d[AO_PACKET_MAX]; }; -uint8_t -ao_packet_connect(uint8_t dest); - -uint8_t -ao_packet_accept(void); - -int -ao_packet_send(uint8_t *data, int len); - -int -ao_packet_recv(uint8_t *data, int len); +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; void ao_packet_init(void); diff --git a/src/ao_dma.c b/src/ao_dma.c index a4d45f14..704108e6 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -102,11 +102,13 @@ ao_dma_trigger(uint8_t id) } void -ao_dma_abort(uint8_t id) +ao_dma_abort(uint8_t id, uint8_t reason) { uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; + *(ao_dma_done[id]) |= reason; + ao_wakeup(ao_dma_done[id]); } void @@ -122,7 +124,7 @@ ao_dma_isr(void) interrupt 8 DMAIF = 0; /* Clear the completed ID */ DMAIRQ = ~mask; - *(ao_dma_done[id]) = 1; + *(ao_dma_done[id]) |= AO_DMA_DONE; ao_wakeup(ao_dma_done[id]); break; } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index b397d975..cd5f78b9 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -46,6 +46,12 @@ static const char ao_gps_config[] = { 1, /* zda interval */ 0, /* attributes (0 = update to sram, 1 = update flash too) */ 0x09, 0x0d, 0x0a, + + 0xa0, 0xa1, 0x00, 0x03, /* length: 3 bytes */ + 0x3c, /* configure navigation mode */ + 0x00, /* 0 = car, 1 = pedestrian */ + 0x00, /* 0 = update to sram, 1 = update sram + flash */ + 0x3c, 0x0d, 0x0a, }; static void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index e57ea145..9431f726 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -30,7 +30,8 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - ao_radio_recv(&recv); + if (!ao_radio_recv(&recv)) + continue; state = recv.telemetry.flight_state; memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) @@ -74,6 +75,7 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); + ao_radio_abort(AO_DMA_ABORTED); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c new file mode 100644 index 00000000..e3133b88 --- /dev/null +++ b/src/ao_packet.c @@ -0,0 +1,308 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata struct ao_packet_recv rx_packet; +static __xdata struct ao_packet tx_packet; +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_len, rx_used, tx_used; +static __pdata uint8_t rx_seq; + +static __xdata uint16_t ao_packet_timer_delay; +static __xdata uint8_t ao_packet_timer_cancelled; + +static __xdata struct ao_task ao_packet_task; +static __xdata struct ao_task ao_packet_timer_task; +static __xdata uint8_t ao_packet_enable; +static __xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_timer(void) __reentrant +{ + uint16_t delay; + + while (ao_packet_enable) { + + /* wait until the timer task is needed + */ + while (!ao_packet_timer_delay && ao_packet_enable) + ao_sleep(&ao_packet_timer_delay); + + delay = ao_packet_timer_delay; + ao_packet_timer_delay = 0; + + /* pause waiting for either a timeout or + * a timer cancel + */ + ao_delay(delay); + + /* if not canceled, abort the receive + */ + if (!ao_packet_timer_cancelled) { + printf ("packet timeout\n"); flush(); + ao_radio_abort(AO_DMA_TIMEOUT); + } + } + ao_exit(); +} + +void +ao_packet_timer_set(uint16_t delay) +{ + ao_packet_timer_delay = delay; + ao_packet_timer_cancelled = 0; + ao_wakeup(&ao_packet_timer_delay); +} + +void +ao_packet_timer_cancel(void) +{ + ao_packet_timer_cancelled = 1; + ao_packet_timer_delay = 0; + ao_wake_task(&ao_packet_timer_task); +} + +void +ao_packet_send(void) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + ao_dma_set_transfer(ao_radio_dma, + &tx_packet, + &RFDXADDR, + sizeof (struct ao_packet), + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + ao_mutex_put(&ao_radio_mutex); +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + ao_dma_set_transfer(ao_radio_dma, + &RFDXADDR, + &rx_packet, + sizeof (struct ao_packet_recv), + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_SRX; + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + dma_done = ao_radio_dma_done; + ao_mutex_put(&ao_radio_mutex); + + if (dma_done & AO_DMA_DONE) { + printf ("rssi %d status %x\n", rx_packet.rssi, rx_packet.status); flush(); + if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { + printf ("bad crc\n"); flush(); +// return AO_DMA_ABORTED; + } + if (rx_packet.packet.len) { + if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) + { + memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); + rx_used = 0; + rx_len = rx_packet.packet.len; + rx_seq = rx_packet.packet.seq; + tx_packet.ack = rx_seq; + ao_wakeup(&rx_data); + } + } + if (rx_packet.packet.ack == tx_packet.seq) { + tx_packet.len = 0; + ao_wakeup(&tx_packet); + } + } + return dma_done; +} + +void +ao_packet_slave(void) +{ + tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + while (ao_packet_enable) { + ao_packet_recv(); + ao_led_toggle(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_send(); + ao_led_toggle(AO_LED_RED); + } + ao_exit(); +} + +/* Thread for the master side of the packet link */ + +void +ao_packet_master(void) +{ + uint8_t status; + tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + while (ao_packet_enable) { + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_send(); + ao_led_toggle(AO_LED_RED); + ao_packet_timer_set(AO_MS_TO_TICKS(1000)); + status = ao_packet_recv(); + ao_packet_timer_cancel(); + if (status & AO_DMA_DONE) { + ao_led_toggle(AO_LED_GREEN); + ao_packet_master_sleeping = 1; + ao_sleep(AO_MS_TO_TICKS(1000)); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +void +ao_packet_flush(void) +{ + if (!tx_used) + return; + + /* Wait for previous packet to be received + */ + while (tx_packet.len) + ao_sleep(&tx_packet); + + /* Prepare next packet + */ + if (tx_used) { + memcpy(&tx_packet.d, tx_data, tx_used); + tx_packet.len = tx_used; + tx_packet.seq++; + tx_used = 0; + + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); + } +} + +void +ao_packet_putchar(char c) +{ + while (tx_used == AO_PACKET_MAX && ao_packet_enable) + ao_packet_flush(); + + if (ao_packet_enable) + tx_data[tx_used++] = c; +} + +char +ao_packet_getchar(void) __critical +{ + while (rx_used == rx_len && ao_packet_enable) + ao_sleep(&rx_data); + + if (!ao_packet_enable) + return 0; + + return rx_data[rx_used++]; +} + +static void +ao_packet_echo(void) __reentrant +{ + uint8_t c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (ao_packet_enable) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + ao_radio_set_packet(); + if (ao_cmd_lex_c == 'm') { + while ((c = getchar()) != '~') + ao_packet_send(); + } else { + for (;;) { + ao_packet_recv(); + ao_led_toggle(AO_LED_GREEN); + if (rx_packet.packet.d[0] == (uint8_t) '@') + break; + } + } + ao_packet_enable = 0; + return; +#if 0 + if (ao_cmd_lex_c == 'm') { + ao_add_task(&ao_packet_timer_task, ao_packet_timer, "timeout"); + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + } + else + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + ao_packet_putchar(c); + if (c == '\n') + ao_packet_flush(); + } + ao_packet_enable = 0; + ao_radio_abort(AO_DMA_ABORTED); + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_wake_task(&ao_packet_echo_task); + ao_wake_task(&ao_packet_task); + } +#endif +} + +__code struct ao_cmds ao_packet_cmds[] = { + { 'p', ao_packet_forward, "p {m|s} Remote packet link. m=master, s=slave" }, + { 0, ao_packet_forward, NULL }, +}; + +void +ao_packet_init(void) +{ + ao_cmd_register(&ao_packet_cmds[0]); +} diff --git a/src/ao_radio.c b/src/ao_radio.c index a7fa682e..2dfa9279 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -255,11 +255,62 @@ static __code uint8_t telemetry_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; +static __code uint8_t packet_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* max packet length */ + RF_PKTLEN_OFF, sizeof (struct ao_packet), + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; + + +void +ao_radio_set_telemetry(void) +{ + uint8_t i; + for (i = 0; i < sizeof (telemetry_setup); i += 2) + RF[telemetry_setup[i]] = telemetry_setup[i+1]; +} + +void +ao_radio_set_packet(void) +{ + uint8_t i; + for (i = 0; i < sizeof (packet_setup); i += 2) + RF[packet_setup[i]] = packet_setup[i+1]; +} + +void +ao_radio_set_rdf(void) +{ + uint8_t i; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; +} + __xdata uint8_t ao_radio_dma; __xdata uint8_t ao_radio_dma_done; __xdata uint8_t ao_radio_mutex; -static void +void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -295,7 +346,7 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant ao_mutex_put(&ao_radio_mutex); } -void +uint8_t ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant { ao_config_get(); @@ -317,6 +368,7 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant __critical while (!ao_radio_dma_done) ao_sleep(&ao_radio_dma_done); ao_mutex_put(&ao_radio_mutex); + return (ao_radio_dma_done & AO_DMA_DONE); } __xdata ao_radio_rdf_running; @@ -367,13 +419,18 @@ ao_radio_rdf(int ms) ao_mutex_put(&ao_radio_mutex); } +void +ao_radio_abort(uint8_t reason) +{ + ao_dma_abort(ao_radio_dma, reason); + ao_radio_idle(); +} + void ao_radio_rdf_abort(void) { - if (ao_radio_rdf_running) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } + if (ao_radio_rdf_running) + ao_radio_abort(AO_DMA_ABORTED); } void @@ -382,6 +439,7 @@ ao_radio_init(void) uint8_t i; for (i = 0; i < sizeof (radio_setup); i += 2) RF[radio_setup[i]] = radio_setup[i+1]; + ao_radio_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index d7b4b75a..98642180 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,6 +33,7 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); + ao_packet_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 1dbacf89..07737f30 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -40,6 +40,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); + ao_packet_init(); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum index e4960bff..ab0464a7 100644 --- a/src/skytraq-cksum +++ b/src/skytraq-cksum @@ -32,7 +32,7 @@ void main() } } } - printf("\t0xa0, 0xa1, 0x02x, 0x%02x,\t\t/* length: %d bytes */\n", + printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); for (int i = 0; i < dim(input); i++) printf("%s\n", input[i]); -- cgit v1.2.3 From 9b31f07fe3556896b3e997bba156e30ef5777a80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:43:52 -0700 Subject: Add radio carrier command --- src/ao_radio.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index 2dfa9279..55a0c297 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -430,9 +430,29 @@ void ao_radio_rdf_abort(void) { if (ao_radio_rdf_running) - ao_radio_abort(AO_DMA_ABORTED); + ao_radio_abort(); } +/* Output carrier */ +void +ao_radio_test(void) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + printf ("Hit a character to stop..."); flush(); + RFST = RFST_STX; + getchar(); + ao_radio_idle(); + ao_mutex_put(&ao_radio_mutex); + putchar('\n'); +} + +__code struct ao_cmds ao_radio_cmds[] = { + { 'C', ao_radio_test, "C Radio carrier test" }, + { 0, ao_radio_test, NULL }, +}; + void ao_radio_init(void) { @@ -442,4 +462,5 @@ ao_radio_init(void) ao_radio_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From 251b0971f049cbf2f8db79a32729d47441ce65f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:45:43 -0700 Subject: Wait for TX to finish sending data --- src/ao.h | 4 ++++ src/ao_radio.c | 30 ++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/ao.h b/src/ao.h index e86b4bf9..84e92f35 100644 --- a/src/ao.h +++ b/src/ao.h @@ -804,8 +804,12 @@ ao_telemetry_init(void); extern __xdata uint8_t ao_radio_dma; extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; +void +ao_radio_general_isr(void) interrupt 16; + void ao_radio_set_telemetry(void); diff --git a/src/ao_radio.c b/src/ao_radio.c index 55a0c297..43899f44 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -281,6 +281,24 @@ static __code uint8_t packet_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; +__xdata uint8_t ao_radio_dma; +__xdata uint8_t ao_radio_dma_done; +__xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) interrupt 16 +{ + S1CON &= ~0x03; + if (RFIF & RFIF_IM_TIMEOUT) { + ao_dma_abort(ao_radio_dma); + RFIF &= ~ RFIF_IM_TIMEOUT; + } else if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } +} void ao_radio_set_telemetry(void) @@ -306,10 +324,6 @@ ao_radio_set_rdf(void) RF[rdf_setup[i]] = rdf_setup[i+1]; } -__xdata uint8_t ao_radio_dma; -__xdata uint8_t ao_radio_dma_done; -__xdata uint8_t ao_radio_mutex; - void ao_radio_idle(void) { @@ -328,6 +342,7 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); + ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, telemetry, @@ -341,8 +356,8 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); } @@ -462,5 +477,8 @@ ao_radio_init(void) ao_radio_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + RFIF = 0; + RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; + IEN2 |= IEN2_RFIE; ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From 73db30b2f9128c37dc7fa075793a8862814ce044 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:46:21 -0700 Subject: Add ao_alarm --- src/ao.h | 13 +++++++++++-- src/ao_task.c | 23 ++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/src/ao.h b/src/ao.h index 84e92f35..b90befe5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -40,6 +40,7 @@ /* An AltOS task */ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ + uint16_t alarm; /* abort ao_sleep time */ uint8_t stack_count; /* amount of saved stack */ uint8_t task_id; /* index in the task array */ __code char *name; /* task name */ @@ -55,8 +56,12 @@ extern __xdata struct ao_task *__data ao_cur_task; ao_task.c */ -/* Suspend the current task until wchan is awoken */ -void +/* Suspend the current task until wchan is awoken. + * returns: + * 0 on normal wake + * 1 on alarm + */ +uint8_t ao_sleep(__xdata void *wchan); /* Wake all tasks sleeping on wchan */ @@ -67,6 +72,10 @@ ao_wakeup(__xdata void *wchan); void ao_wake_task(__xdata struct ao_task *task); +/* set an alarm to go off in 'delay' ticks */ +void +ao_alarm(uint16_t delay); + /* Yield the processor to another task */ void ao_yield(void) _naked; diff --git a/src/ao_task.c b/src/ao_task.c index 136444b0..14aa84c8 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -129,6 +129,13 @@ ao_yield(void) _naked break; } + /* Check if the alarm is set for a time which has passed */ + if (ao_cur_task->alarm && + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { + ao_cur_task_index = ao_next_task_index; + break; + } + /* Enter lower power mode when there isn't anything to do */ if (ao_next_task_index == ao_cur_task_index) PCON = PCON_IDLE; @@ -181,13 +188,20 @@ ao_yield(void) _naked _endasm; } -void +uint8_t ao_sleep(__xdata void *wchan) { __critical { ao_cur_task->wchan = wchan; } ao_yield(); + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + ao_cur_task->alarm = 0; + return 1; + } + ao_cur_task->alarm = 0; + return 0; } void @@ -200,6 +214,13 @@ ao_wakeup(__xdata void *wchan) ao_tasks[i]->wchan = NULL; } +void +ao_alarm(uint16_t delay) +{ + if (!(ao_cur_task->alarm = ao_time() + delay)) + ao_cur_task->alarm = 1; +} + void ao_wake_task(__xdata struct ao_task *task) { -- cgit v1.2.3 From b428faf74ae145126ec1da972028fcfe0b4b2b18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:48:36 -0700 Subject: Remove reason from ao_dma_abort --- src/ao.h | 5 ++--- src/ao_dma.c | 4 ++-- src/ao_monitor.c | 2 +- src/ao_packet.c | 2 +- src/ao_radio.c | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/ao.h b/src/ao.h index b90befe5..2e2fb589 100644 --- a/src/ao.h +++ b/src/ao.h @@ -365,7 +365,6 @@ ao_cmd_init(void); #define AO_DMA_DONE 1 #define AO_DMA_ABORTED 2 -#define AO_DMA_TIMEOUT 4 uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -389,7 +388,7 @@ ao_dma_trigger(uint8_t id); /* Abort a running DMA transfer */ void -ao_dma_abort(uint8_t id, uint8_t reason); +ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void @@ -844,7 +843,7 @@ void ao_radio_rdf(int ms); void -ao_radio_abort(uint8_t reason); +ao_radio_abort(void); void ao_radio_rdf_abort(void); diff --git a/src/ao_dma.c b/src/ao_dma.c index 704108e6..110138b5 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -102,12 +102,12 @@ ao_dma_trigger(uint8_t id) } void -ao_dma_abort(uint8_t id, uint8_t reason) +ao_dma_abort(uint8_t id) { uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; - *(ao_dma_done[id]) |= reason; + *(ao_dma_done[id]) |= AO_DMA_ABORTED; ao_wakeup(ao_dma_done[id]); } diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 9431f726..d0c1da34 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -75,7 +75,7 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - ao_radio_abort(AO_DMA_ABORTED); + ao_radio_abort(); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c index e3133b88..ccd83785 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -288,7 +288,7 @@ ao_packet_forward(void) __reentrant ao_packet_flush(); } ao_packet_enable = 0; - ao_radio_abort(AO_DMA_ABORTED); + 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); diff --git a/src/ao_radio.c b/src/ao_radio.c index 43899f44..c7c8dc8d 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -435,9 +435,9 @@ ao_radio_rdf(int ms) } void -ao_radio_abort(uint8_t reason) +ao_radio_abort(void) { - ao_dma_abort(ao_radio_dma, reason); + ao_dma_abort(ao_radio_dma); ao_radio_idle(); } -- cgit v1.2.3 From c5ec6fcfa1bd17aad0f85d2fbe603f1d125836e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:50:54 -0700 Subject: Switch packet code from timer thread to ao_alarm --- src/ao_packet.c | 89 +++++++++------------------------------------------------ 1 file changed, 14 insertions(+), 75 deletions(-) diff --git a/src/ao_packet.c b/src/ao_packet.c index ccd83785..7d277d70 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -24,60 +24,10 @@ static __xdata char rx_data[AO_PACKET_MAX]; static __pdata uint8_t rx_len, rx_used, tx_used; static __pdata uint8_t rx_seq; -static __xdata uint16_t ao_packet_timer_delay; -static __xdata uint8_t ao_packet_timer_cancelled; - static __xdata struct ao_task ao_packet_task; -static __xdata struct ao_task ao_packet_timer_task; static __xdata uint8_t ao_packet_enable; static __xdata uint8_t ao_packet_master_sleeping; -void -ao_packet_timer(void) __reentrant -{ - uint16_t delay; - - while (ao_packet_enable) { - - /* wait until the timer task is needed - */ - while (!ao_packet_timer_delay && ao_packet_enable) - ao_sleep(&ao_packet_timer_delay); - - delay = ao_packet_timer_delay; - ao_packet_timer_delay = 0; - - /* pause waiting for either a timeout or - * a timer cancel - */ - ao_delay(delay); - - /* if not canceled, abort the receive - */ - if (!ao_packet_timer_cancelled) { - printf ("packet timeout\n"); flush(); - ao_radio_abort(AO_DMA_TIMEOUT); - } - } - ao_exit(); -} - -void -ao_packet_timer_set(uint16_t delay) -{ - ao_packet_timer_delay = delay; - ao_packet_timer_cancelled = 0; - ao_wakeup(&ao_packet_timer_delay); -} - -void -ao_packet_timer_cancel(void) -{ - ao_packet_timer_cancelled = 1; - ao_packet_timer_delay = 0; - ao_wake_task(&ao_packet_timer_task); -} - void ao_packet_send(void) { @@ -124,7 +74,10 @@ ao_packet_recv(void) ao_dma_start(ao_radio_dma); RFST = RFST_SRX; __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + if (ao_sleep(&ao_radio_dma_done) != 0) { + printf("recv timeout\n"); flush(); + ao_radio_abort(); + } dma_done = ao_radio_dma_done; ao_mutex_put(&ao_radio_mutex); @@ -174,19 +127,22 @@ void ao_packet_master(void) { uint8_t status; - tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + tx_packet.addr = ao_serial_number; + tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { + ao_led_on(AO_LED_RED); ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_toggle(AO_LED_RED); - ao_packet_timer_set(AO_MS_TO_TICKS(1000)); + ao_led_off(AO_LED_RED); + ao_led_on(AO_LED_GREEN); + ao_alarm(AO_MS_TO_TICKS(1000)); status = ao_packet_recv(); - ao_packet_timer_cancel(); + ao_led_off(AO_LED_GREEN); if (status & AO_DMA_DONE) { - ao_led_toggle(AO_LED_GREEN); ao_packet_master_sleeping = 1; - ao_sleep(AO_MS_TO_TICKS(1000)); + ao_delay(AO_MS_TO_TICKS(1000)); ao_packet_master_sleeping = 0; } } @@ -260,25 +216,8 @@ ao_packet_forward(void) __reentrant ao_packet_enable = 1; ao_cmd_white(); - ao_radio_set_packet(); - if (ao_cmd_lex_c == 'm') { - while ((c = getchar()) != '~') - ao_packet_send(); - } else { - for (;;) { - ao_packet_recv(); - ao_led_toggle(AO_LED_GREEN); - if (rx_packet.packet.d[0] == (uint8_t) '@') - break; - } - } - ao_packet_enable = 0; - return; -#if 0 - if (ao_cmd_lex_c == 'm') { - ao_add_task(&ao_packet_timer_task, ao_packet_timer, "timeout"); + if (ao_cmd_lex_c == 'm') ao_add_task(&ao_packet_task, ao_packet_master, "master"); - } else ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); -- cgit v1.2.3 From d46797e5c08d4955d516458185e2cfb51ee2d567 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:51:38 -0700 Subject: Use ao_radio_done to wait for TX to completely finish with packet --- src/ao_packet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ao_packet.c b/src/ao_packet.c index 7d277d70..da33bb4c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -34,6 +34,7 @@ ao_packet_send(void) ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); + ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &tx_packet, @@ -47,8 +48,8 @@ ao_packet_send(void) DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); } -- cgit v1.2.3 From bf65e0b2a1299b49adc2d339ab9d9c7599aded9e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:52:22 -0700 Subject: Send SYN packet to set sequence numbers --- src/ao.h | 1 + src/ao_packet.c | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/ao.h b/src/ao.h index 2e2fb589..e2f137bd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -981,6 +981,7 @@ struct ao_fifo { */ #define AO_PACKET_MAX 8 +#define AO_PACKET_SYN 0xff struct ao_packet { uint8_t addr; diff --git a/src/ao_packet.c b/src/ao_packet.c index da33bb4c..620cd001 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -83,14 +83,22 @@ ao_packet_recv(void) ao_mutex_put(&ao_radio_mutex); if (dma_done & AO_DMA_DONE) { - printf ("rssi %d status %x\n", rx_packet.rssi, rx_packet.status); flush(); if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { printf ("bad crc\n"); flush(); -// return AO_DMA_ABORTED; + return AO_DMA_ABORTED; } - if (rx_packet.packet.len) { + if (rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = rx_packet.packet.seq; + tx_packet.seq = rx_packet.packet.ack; + tx_packet.ack = rx_seq; + } else if (rx_packet.packet.len) { if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) { + printf ("rx len %3d seq %3d ack %3d\n", + rx_packet.packet.len, + rx_packet.packet.seq, + rx_packet.packet.ack); + flush(); memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); rx_used = 0; rx_len = rx_packet.packet.len; @@ -110,14 +118,17 @@ ao_packet_recv(void) void ao_packet_slave(void) { - tx_packet.addr = ao_serial_number; ao_radio_set_packet(); + tx_packet.addr = ao_serial_number; + tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { + ao_led_on(AO_LED_GREEN); ao_packet_recv(); - ao_led_toggle(AO_LED_GREEN); + ao_led_off(AO_LED_GREEN); + ao_led_on(AO_LED_RED); ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_toggle(AO_LED_RED); + ao_led_off(AO_LED_RED); } ao_exit(); } -- cgit v1.2.3 From 6a7aa1810a90a9216160aec55ec4bd02b3240e1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:52:44 -0700 Subject: Add RFIM register --- src/cc1111.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/cc1111.h b/src/cc1111.h index 87b14485..ee4c9f09 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -882,6 +882,16 @@ sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) +sfr at 0x91 RFIM; +#define RFIM_IM_TXUNF (1 << 7) +#define RFIM_IM_RXOVF (1 << 6) +#define RFIM_IM_TIMEOUT (1 << 5) +#define RFIM_IM_DONE (1 << 4) +#define RFIM_IM_CS (1 << 3) +#define RFIM_IM_PQT (1 << 2) +#define RFIM_IM_CCA (1 << 1) +#define RFIM_IM_SFD (1 << 0) + sfr at 0xE1 RFST; #define RFST_SFSTXON 0x00 -- cgit v1.2.3 From 4f7ed9ff484778381db647c27d2a34d0cadec41e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:53:03 -0700 Subject: Do more flushing in packet test code --- src/ao_packet.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/ao_packet.c b/src/ao_packet.c index 620cd001..0dce326c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -198,8 +198,10 @@ ao_packet_putchar(char c) char ao_packet_getchar(void) __critical { - while (rx_used == rx_len && ao_packet_enable) + while (rx_used == rx_len && ao_packet_enable) { + flush(); ao_sleep(&rx_data); + } if (!ao_packet_enable) return 0; @@ -213,8 +215,11 @@ ao_packet_echo(void) __reentrant uint8_t c; while (ao_packet_enable) { c = ao_packet_getchar(); - if (ao_packet_enable) + if (ao_packet_enable) { putchar(c); + if (c == (uint8_t) '\n') + flush(); + } } ao_exit(); } @@ -233,18 +238,14 @@ ao_packet_forward(void) __reentrant else ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { + while ((c = getchar()) != '~') ao_packet_putchar(c); - if (c == '\n') - ao_packet_flush(); - } 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); } -#endif } __code struct ao_cmds ao_packet_cmds[] = { -- cgit v1.2.3 From 442b1ef18c8320d4e5329dc92bb5268a36058fc5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:19:41 -0700 Subject: Use ao_alarm for ao_delay so it can be easily interrupted --- src/ao_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao_timer.c b/src/ao_timer.c index 78c6e063..d7603435 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -24,13 +24,13 @@ uint16_t ao_time(void) __critical return ao_tick_count; } +static __xdata uint8_t ao_forever; + void ao_delay(uint16_t ticks) { - uint16_t until = ao_time() + ticks; - - while ((int16_t) (until - ao_time()) > 0) - ao_sleep(DATA_TO_XDATA(&ao_tick_count)); + ao_alarm(ticks); + ao_sleep(&ao_forever); } #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -- cgit v1.2.3 From cd0d495d7ef276956e730196476daa70a4359918 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:20:26 -0700 Subject: Poke master to speed up packet rate when things are busy --- src/ao.h | 2 +- src/ao_packet.c | 71 +++++++++++++++++++++++++-------------------------------- 2 files changed, 32 insertions(+), 41 deletions(-) diff --git a/src/ao.h b/src/ao.h index e2f137bd..aeceb870 100644 --- a/src/ao.h +++ b/src/ao.h @@ -981,7 +981,7 @@ struct ao_fifo { */ #define AO_PACKET_MAX 8 -#define AO_PACKET_SYN 0xff +#define AO_PACKET_SYN (uint8_t) 0xff struct ao_packet { uint8_t addr; diff --git a/src/ao_packet.c b/src/ao_packet.c index 0dce326c..ba559512 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -31,8 +31,16 @@ static __xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) { + ao_led_on(AO_LED_RED); ao_config_get(); ao_mutex_get(&ao_radio_mutex); + if (tx_used && tx_packet.len == 0) { + memcpy(&tx_packet.d, tx_data, tx_used); + tx_packet.len = tx_used; + tx_packet.seq++; + tx_used = 0; + ao_wakeup(&tx_data); + } ao_radio_idle(); ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; @@ -51,6 +59,7 @@ ao_packet_send(void) __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); + ao_led_off(AO_LED_RED); } uint8_t @@ -58,6 +67,7 @@ ao_packet_recv(void) { uint8_t dma_done; + ao_led_on(AO_LED_GREEN); ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); @@ -75,30 +85,28 @@ ao_packet_recv(void) ao_dma_start(ao_radio_dma); RFST = RFST_SRX; __critical while (!ao_radio_dma_done) - if (ao_sleep(&ao_radio_dma_done) != 0) { - printf("recv timeout\n"); flush(); + if (ao_sleep(&ao_radio_dma_done) != 0) ao_radio_abort(); - } dma_done = ao_radio_dma_done; ao_mutex_put(&ao_radio_mutex); + ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { - if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { - printf ("bad crc\n"); flush(); + if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return AO_DMA_ABORTED; - } if (rx_packet.packet.len == AO_PACKET_SYN) { rx_seq = rx_packet.packet.seq; tx_packet.seq = rx_packet.packet.ack; tx_packet.ack = rx_seq; } else if (rx_packet.packet.len) { - if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) - { + if (rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && rx_used == rx_len) { +#if 0 printf ("rx len %3d seq %3d ack %3d\n", rx_packet.packet.len, rx_packet.packet.seq, rx_packet.packet.ack); flush(); +#endif memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); rx_used = 0; rx_len = rx_packet.packet.len; @@ -122,13 +130,8 @@ ao_packet_slave(void) tx_packet.addr = ao_serial_number; tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_led_on(AO_LED_GREEN); ao_packet_recv(); - ao_led_off(AO_LED_GREEN); - ao_led_on(AO_LED_RED); - ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_off(AO_LED_RED); } ao_exit(); } @@ -144,15 +147,13 @@ ao_packet_master(void) tx_packet.addr = ao_serial_number; tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_led_on(AO_LED_RED); - ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_off(AO_LED_RED); - ao_led_on(AO_LED_GREEN); - ao_alarm(AO_MS_TO_TICKS(1000)); + ao_alarm(AO_MS_TO_TICKS(100)); status = ao_packet_recv(); - ao_led_off(AO_LED_GREEN); if (status & AO_DMA_DONE) { + /* if we can transmit data, do so */ + if (tx_used && tx_packet.len == 0) + continue; ao_packet_master_sleeping = 1; ao_delay(AO_MS_TO_TICKS(1000)); ao_packet_master_sleeping = 0; @@ -164,32 +165,20 @@ ao_packet_master(void) void ao_packet_flush(void) { - if (!tx_used) - return; - - /* Wait for previous packet to be received - */ - while (tx_packet.len) - ao_sleep(&tx_packet); - - /* Prepare next packet + /* If there is data to send, and this is the master, + * then poke the master to send all queued data */ - if (tx_used) { - memcpy(&tx_packet.d, tx_data, tx_used); - tx_packet.len = tx_used; - tx_packet.seq++; - tx_used = 0; - - if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); - } + if (tx_used && ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); } void ao_packet_putchar(char c) { - while (tx_used == AO_PACKET_MAX && ao_packet_enable) + while (tx_used == AO_PACKET_MAX && ao_packet_enable) { ao_packet_flush(); + ao_sleep(&tx_data); + } if (ao_packet_enable) tx_data[tx_used++] = c; @@ -199,7 +188,9 @@ char ao_packet_getchar(void) __critical { while (rx_used == rx_len && ao_packet_enable) { - flush(); + /* poke the master to get more data */ + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); ao_sleep(&rx_data); } @@ -217,7 +208,7 @@ ao_packet_echo(void) __reentrant c = ao_packet_getchar(); if (ao_packet_enable) { putchar(c); - if (c == (uint8_t) '\n') + if (c == (uint8_t) '\n' || c == (uint8_t) '\r') flush(); } } -- cgit v1.2.3 From 6c1a9ce16b966a21c885bf3be31cbcb85368b3fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:30:22 -0700 Subject: No need to wakeup &ao_tick_count now --- src/ao_timer.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ao_timer.c b/src/ao_timer.c index d7603435..e81f937d 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -46,7 +46,6 @@ void ao_timer_isr(void) interrupt 9 ao_adc_count = 0; ao_adc_poll(); } - ao_wakeup(DATA_TO_XDATA(&ao_tick_count)); } void -- cgit v1.2.3 From ca5d323a3d206050d95f52a61e92c69e1f54e7b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Nov 2009 20:57:03 -0800 Subject: Enable packet-based communcation to command processor This splits the packet code into master/slave halves and hooks the slave side up to the getchar/putchar/flush logic in ao_stdio.c Signed-off-by: Keith Packard --- src/Makefile | 2 + src/ao.h | 53 ++++++++++++++- src/ao_flight.c | 4 +- src/ao_flight_test.c | 1 + src/ao_packet.c | 177 +++++++++++-------------------------------------- src/ao_packet_master.c | 142 +++++++++++++++++++++++++++++++++++++++ src/ao_packet_slave.c | 58 ++++++++++++++++ src/ao_stdio.c | 44 ++++++++++-- src/ao_teledongle.c | 3 +- src/ao_telemetrum.c | 2 +- src/ao_usb.c | 28 +++++--- 11 files changed, 356 insertions(+), 158 deletions(-) create mode 100644 src/ao_packet_master.c create mode 100644 src/ao_packet_slave.c diff --git a/src/Makefile b/src/Makefile index 4575f443..d984e9dc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -45,6 +45,7 @@ ALTOS_DRIVER_SRC = \ TELE_COMMON_SRC = \ ao_gps_print.c \ ao_packet.c \ + ao_packet_slave.c \ ao_state.c # @@ -52,6 +53,7 @@ TELE_COMMON_SRC = \ # TELE_RECEIVER_SRC =\ ao_monitor.c \ + ao_packet_master.c \ ao_rssi.c # diff --git a/src/ao.h b/src/ao.h index aeceb870..65a594c0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -106,6 +106,7 @@ ao_start_scheduler(void); #define AO_PANIC_EE 4 /* Mis-using eeprom API */ #define AO_PANIC_LOG 5 /* Failing to read/write log data */ #define AO_PANIC_CMD 6 /* Too many command sets registered */ +#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ /* Stop the operating system, beeping and blinking the reason */ void @@ -873,9 +874,24 @@ ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; * ao_stdio.c */ +#define AO_READ_AGAIN ((char) -1) + +struct ao_stdio { + char (*pollchar)(void); + void (*putchar)(char c) __reentrant; + void (*flush)(void); +}; + void flush(void); +extern __xdata uint8_t ao_stdin_ready; + +void +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char) __reentrant, + void (*flush)(void)); + /* * ao_ignite.c */ @@ -997,7 +1013,42 @@ struct ao_packet_recv { uint8_t status; }; +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); + +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + void -ao_packet_init(void); +ao_packet_slave_init(void); #endif /* _AO_H_ */ diff --git a/src/ao_flight.c b/src/ao_flight.c index c43d0711..e91a5daa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -235,9 +235,9 @@ ao_flight(void) } else { ao_flight_state = ao_flight_idle; - /* Turn on the Green LED in idle mode + /* Turn on packet system in idle mode */ - ao_led_on(AO_LED_GREEN); + ao_packet_slave_start(); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } /* signal successful initialization by turning off the LED */ diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 9fcb00c2..83c63016 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -69,6 +69,7 @@ uint8_t ao_adc_head; #define ao_usb_disable() #define ao_telemetry_set_interval(x) #define ao_rdf_set(rdf) +#define ao_packet_slave_start() enum ao_igniter { ao_igniter_drogue = 0, diff --git a/src/ao_packet.c b/src/ao_packet.c index ba559512..3ce7e9ab 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -17,16 +17,17 @@ #include "ao.h" -static __xdata struct ao_packet_recv rx_packet; -static __xdata struct ao_packet tx_packet; +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + static __xdata char tx_data[AO_PACKET_MAX]; static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_len, rx_used, tx_used; static __pdata uint8_t rx_seq; -static __xdata struct ao_task ao_packet_task; -static __xdata uint8_t ao_packet_enable; -static __xdata uint8_t ao_packet_master_sleeping; +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) @@ -34,18 +35,18 @@ ao_packet_send(void) ao_led_on(AO_LED_RED); ao_config_get(); ao_mutex_get(&ao_radio_mutex); - if (tx_used && tx_packet.len == 0) { - memcpy(&tx_packet.d, tx_data, tx_used); - tx_packet.len = tx_used; - tx_packet.seq++; - tx_used = 0; + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; ao_wakeup(&tx_data); } ao_radio_idle(); ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, - &tx_packet, + &ao_tx_packet, &RFDXADDR, sizeof (struct ao_packet), DMA_CFG0_WORDSIZE_8 | @@ -74,7 +75,7 @@ ao_packet_recv(void) RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, - &rx_packet, + &ao_rx_packet, sizeof (struct ao_packet_recv), DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | @@ -92,160 +93,60 @@ ao_packet_recv(void) ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { - if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return AO_DMA_ABORTED; - if (rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = rx_packet.packet.seq; - tx_packet.seq = rx_packet.packet.ack; - tx_packet.ack = rx_seq; - } else if (rx_packet.packet.len) { - if (rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && rx_used == rx_len) { -#if 0 - printf ("rx len %3d seq %3d ack %3d\n", - rx_packet.packet.len, - rx_packet.packet.seq, - rx_packet.packet.ack); - flush(); -#endif - memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); - rx_used = 0; - rx_len = rx_packet.packet.len; - rx_seq = rx_packet.packet.seq; - tx_packet.ack = rx_seq; - ao_wakeup(&rx_data); + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) { + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + ao_wakeup(&ao_stdin_ready); } } - if (rx_packet.packet.ack == tx_packet.seq) { - tx_packet.len = 0; - ao_wakeup(&tx_packet); + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); } } return dma_done; } -void -ao_packet_slave(void) -{ - ao_radio_set_packet(); - tx_packet.addr = ao_serial_number; - tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - ao_packet_recv(); - ao_packet_send(); - } - ao_exit(); -} - -/* Thread for the master side of the packet link */ - -void -ao_packet_master(void) -{ - uint8_t status; - - ao_radio_set_packet(); - tx_packet.addr = ao_serial_number; - tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - ao_packet_send(); - ao_alarm(AO_MS_TO_TICKS(100)); - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { - /* if we can transmit data, do so */ - if (tx_used && tx_packet.len == 0) - continue; - ao_packet_master_sleeping = 1; - ao_delay(AO_MS_TO_TICKS(1000)); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - void ao_packet_flush(void) { /* If there is data to send, and this is the master, * then poke the master to send all queued data */ - if (tx_used && ao_packet_master_sleeping) + if (ao_packet_tx_used && ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); } void -ao_packet_putchar(char c) +ao_packet_putchar(char c) __reentrant { - while (tx_used == AO_PACKET_MAX && ao_packet_enable) { + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { ao_packet_flush(); ao_sleep(&tx_data); } if (ao_packet_enable) - tx_data[tx_used++] = c; + tx_data[ao_packet_tx_used++] = c; } char -ao_packet_getchar(void) __critical +ao_packet_pollchar(void) __critical { - while (rx_used == rx_len && ao_packet_enable) { - /* poke the master to get more data */ - if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); - ao_sleep(&rx_data); - } - if (!ao_packet_enable) - return 0; + return AO_READ_AGAIN; - return rx_data[rx_used++]; -} - -static void -ao_packet_echo(void) __reentrant -{ - uint8_t c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (ao_packet_enable) { - putchar(c); - if (c == (uint8_t) '\n' || c == (uint8_t) '\r') - flush(); - } - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - if (ao_cmd_lex_c == 'm') - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - else - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') - ao_packet_putchar(c); - 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); - } -} - -__code struct ao_cmds ao_packet_cmds[] = { - { 'p', ao_packet_forward, "p {m|s} Remote packet link. m=master, s=slave" }, - { 0, ao_packet_forward, NULL }, -}; + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; -void -ao_packet_init(void) -{ - ao_cmd_register(&ao_packet_cmds[0]); + return rx_data[ao_packet_rx_used++]; } diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c new file mode 100644 index 00000000..2751f414 --- /dev/null +++ b/src/ao_packet_master.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static char +ao_packet_getchar(void) +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) + { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + uint8_t c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (ao_packet_enable) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + uint8_t status; + + ao_radio_set_packet(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + status = ao_packet_recv(); + if (status & AO_DMA_DONE) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + else + flush(); + ao_packet_master_sleeping = 1; + ao_delay(ao_packet_master_delay); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); + ao_set_monitor(0); + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + if (c == '\r') c = '\n'; + ao_packet_putchar(c); + } + 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(); + } +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { 'p', ao_packet_forward, "p Remote packet link." }, + { 0, ao_packet_forward, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c new file mode 100644 index 00000000..ba5ad1c1 --- /dev/null +++ b/src/ao_packet_slave.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_packet_slave(void) +{ + ao_radio_set_packet(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + ao_packet_recv(); + ao_packet_send(); + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); +} + +void +ao_packet_slave_stop(void) +{ + ao_packet_enable = 0; + ao_radio_abort(); + while (ao_packet_task.wchan) { + ao_wake_task(&ao_packet_task); + ao_yield(); + } + ao_radio_set_telemetry(); +} + +void +ao_packet_slave_init(void) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + ao_packet_flush); +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index fb8ce093..7bc416e1 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -21,22 +21,56 @@ * Basic I/O functions to support SDCC stdio package */ +#define AO_NUM_STDIOS 2 + +static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; +static __data int8_t ao_cur_stdio; +static __data int8_t ao_num_stdios; + void putchar(char c) { if (c == '\n') - ao_usb_putchar('\r'); - ao_usb_putchar(c); + (*stdios[ao_cur_stdio].putchar)('\r'); + (*stdios[ao_cur_stdio].putchar)(c); } void flush(void) { - ao_usb_flush(); + stdios[ao_cur_stdio].flush(); } +__xdata uint8_t ao_stdin_ready; + char -getchar(void) +getchar(void) __reentrant +{ + char c; + int8_t stdio = ao_cur_stdio; + + for (;;) { + c = stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + return c; +} + +void +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) { - return ao_usb_getchar(); + if (ao_num_stdios == AO_NUM_STDIOS) + ao_panic(AO_PANIC_STDIO); + stdios[ao_num_stdios].pollchar = pollchar; + stdios[ao_num_stdios].putchar = putchar; + stdios[ao_num_stdios].flush = flush; + ao_num_stdios++; } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 98642180..e4828d80 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,7 +33,8 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_packet_init(); + ao_packet_slave_init(); + ao_packet_master_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 07737f30..5250078e 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -40,7 +40,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_init(); + ao_packet_slave_init(); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/ao_usb.c b/src/ao_usb.c index 8926b9ca..daca71a7 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -53,7 +53,7 @@ ao_usb_isr(void) interrupt 6 ao_wakeup(&ao_usb_in_bytes); if (USBOIF & (1 << AO_USB_OUT_EP)) - ao_wakeup(&ao_usb_out_bytes); + ao_wakeup(&ao_stdin_ready); if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); @@ -360,7 +360,7 @@ ao_usb_flush(void) __critical } void -ao_usb_putchar(char c) __critical +ao_usb_putchar(char c) __critical __reentrant { if (!ao_usb_running) return; @@ -374,16 +374,13 @@ ao_usb_putchar(char c) __critical } char -ao_usb_getchar(void) __critical +ao_usb_pollchar(void) __critical { - __xdata char c; + char c; while (ao_usb_out_bytes == 0) { - for (;;) { - USBINDEX = AO_USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) != 0) - break; - ao_sleep(&ao_usb_out_bytes); - } + USBINDEX = AO_USB_OUT_EP; + if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) + return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; } --ao_usb_out_bytes; @@ -395,6 +392,16 @@ ao_usb_getchar(void) __critical return c; } +char +ao_usb_getchar(void) +{ + char c; + + while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + return c; +} + void ao_usb_enable(void) { @@ -438,4 +445,5 @@ ao_usb_init(void) ao_usb_enable(); ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } -- cgit v1.2.3 From 8203bfa58af32a1d07a44c1c151b200df0b65f15 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 2 Nov 2009 15:56:42 -0700 Subject: de-version the libreadline-dev build dependency --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index d28be629..3029e7d4 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline5-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev +Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev Standards-Version: 3.8.3 Homepage: http://altusmetrum.org/ -- cgit v1.2.3 From 6b1e77569e2fed3c44606ed268421df5d3ed4020 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 2 Nov 2009 15:57:41 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 37c80609..6ef95b01 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 8203bfa58af32a1d07a44c1c151b200df0b65f15 +Author: Bdale Garbee +Date: Mon Nov 2 15:56:42 2009 -0700 + + de-version the libreadline-dev build dependency + +commit 550482d953c491a5ede9f2d243493afb13289898 +Author: Bdale Garbee +Date: Mon Oct 12 16:58:46 2009 -0600 + + update changelogs for Debian build + commit 2de548f45d0f50b558acc83f57e1e2fc1223ab92 Author: Bdale Garbee Date: Mon Oct 12 16:58:19 2009 -0600 diff --git a/debian/changelog b/debian/changelog index 44204885..628fce03 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.5+88+g8203bfa) unstable; urgency=low + + * de-version the libreadline-dev build dependency + + -- Bdale Garbee Mon, 02 Nov 2009 15:57:29 -0700 + altos (0.5+86+g2de548f) unstable; urgency=low * automate push of updated and tagged master branch during -- cgit v1.2.3 From 127c3125e5a4b86b8f304bc2889e313688c3d83e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 2 Nov 2009 15:59:12 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6ef95b01..5bdb6694 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 6b1e77569e2fed3c44606ed268421df5d3ed4020 +Author: Bdale Garbee +Date: Mon Nov 2 15:57:41 2009 -0700 + + update changelogs for Debian build + commit 8203bfa58af32a1d07a44c1c151b200df0b65f15 Author: Bdale Garbee Date: Mon Nov 2 15:56:42 2009 -0700 diff --git a/debian/changelog b/debian/changelog index 628fce03..d4f7f50e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.5+88+g8203bfa) unstable; urgency=low +altos (0.5+89+g6b1e775) unstable; urgency=low * de-version the libreadline-dev build dependency -- cgit v1.2.3 From f9de20000794c97a04d5bc2476191864bd2af371 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 2 Nov 2009 16:00:11 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5bdb6694..8eb36eac 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 127c3125e5a4b86b8f304bc2889e313688c3d83e +Author: Bdale Garbee +Date: Mon Nov 2 15:59:12 2009 -0700 + + update changelogs for Debian build + commit 6b1e77569e2fed3c44606ed268421df5d3ed4020 Author: Bdale Garbee Date: Mon Nov 2 15:57:41 2009 -0700 diff --git a/debian/changelog b/debian/changelog index d4f7f50e..1040de36 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.5+89+g6b1e775) unstable; urgency=low +altos (0.5+90+g127c312) unstable; urgency=low * de-version the libreadline-dev build dependency -- cgit v1.2.3 From d519564fd08d2defe1211de83ccbdfa3c7cfe702 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 15:45:07 -0800 Subject: Add more docs to the README file --- README | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/README b/README index 1244f849..282b9ce5 100644 --- a/README +++ b/README @@ -17,18 +17,18 @@ Copyright and License with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. -Parameters: +Tasking API: - * Multi-tasking - * Non-preemptive - * Unix-style sleep/wakeup scheduling - * Strict round-robin, no priorities + * Multi-tasking + * Non-preemptive + * Unix-style sleep/wakeup scheduling + * Strict round-robin, no priorities -API: + uint8_t ao_sleep(void *wchan) - void ao_sleep(void *wchan) - - Puts current task to sleep. Will wake up when wchan is signalled + Puts current task to sleep. Will wake up when wchan is + signalled (returning 0), or when an alarm has expired + (returning 1). void ao_wakeup(void *wchan) @@ -52,3 +52,63 @@ API: Any fatal error should call this function, which can display the error code in some cryptic fashion. + + void ao_wake_task(struct ao_task *task) + + Wake the task as if the wchan it is waiting on had + been signalled. + + void ao_alarm(uint16_t delay) + + Queue an alarm to expire 'delay' ticks in the future. + The alarm will cause the task to wake from ao_sleep + and return 1. Alarms are cancelled if the task is + awoken by ao_wakeup or ao_wake_task. + + void ao_exit(void) + + Stop the current task and remove it from the list of + available tasks. + +Timer API + + * Regular timer ticks (at 100Hz, by default) + * All time values are in ticks + + uint16_t ao_time(void) + + Returns the curent tick count + + void ao_delay(uint16_t delay) + + Suspend task execution for 'delay' ticks. + +DMA API + + * Static DMA entry allocation + + uint8_t ao_dma_alloc(uint8_t *done) + + Allocates one of the 5 DMA units on the cc1111 + processor. When this DMA unit is finished, it will + set *done to 1 and wakeup anyone waiting on that. + + void ao_dma_set_transfer(uint8_t id, void *src, void *dst, + uint16_t count, uint8_t cfg0, uint8_t cfg1) + + Prepares the specified DMA unit for operation. + + void ao_dma_start(uint8_t id) + + Start DMA on the specified channel. + + void ao_dma_trigger(uint8_t id) + + Manually trigger a DMA channel + + void ao_dma_abort(uint8_t id) + + Abort a pending DMA transfer, signalling + that by setting the associated 'done' to + AO_DMA_ABORTED and waking any task + sleeping on that. -- cgit v1.2.3 From b92333ff5e75bf96804359e9fbf464d3b518bd95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 15:45:42 -0800 Subject: Disable interrupts while removing tasks from task list --- src/ao_task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_task.c b/src/ao_task.c index 14aa84c8..4664163d 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -228,7 +228,7 @@ ao_wake_task(__xdata struct ao_task *task) } void -ao_exit(void) +ao_exit(void) __critical { uint8_t i; ao_num_tasks--; -- cgit v1.2.3 From b219801fb0e5eaff7778d21701da977104522da3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 15:45:58 -0800 Subject: Add ao_usb_pollchar to ao.h --- src/ao.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ao.h b/src/ao.h index 65a594c0..4cceefe1 100644 --- a/src/ao.h +++ b/src/ao.h @@ -291,6 +291,12 @@ ao_usb_putchar(char c); char ao_usb_getchar(void); +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + /* Flush the USB output queue */ void ao_usb_flush(void); -- cgit v1.2.3 From 17611788aadc9460287145a340a7c18bf63766aa Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 2 Nov 2009 16:54:06 -0700 Subject: update changelogs for Debian build --- ChangeLog | 215 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 28 ++++++++ 2 files changed, 243 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8eb36eac..3ef8d797 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +commit 7db9d86178ecfd58cc1c17ac9fcbdcfd2f13aaec +Merge: b219801 f9de200 +Author: Keith Packard +Date: Mon Nov 2 15:47:40 2009 -0800 + + Merge remote branch 'origin/master' + +commit b219801fb0e5eaff7778d21701da977104522da3 +Author: Keith Packard +Date: Mon Nov 2 15:45:58 2009 -0800 + + Add ao_usb_pollchar to ao.h + +commit b92333ff5e75bf96804359e9fbf464d3b518bd95 +Author: Keith Packard +Date: Mon Nov 2 15:45:42 2009 -0800 + + Disable interrupts while removing tasks from task list + +commit d519564fd08d2defe1211de83ccbdfa3c7cfe702 +Author: Keith Packard +Date: Mon Nov 2 15:45:07 2009 -0800 + + Add more docs to the README file + +commit f9de20000794c97a04d5bc2476191864bd2af371 +Author: Bdale Garbee +Date: Mon Nov 2 16:00:11 2009 -0700 + + update changelogs for Debian build + commit 127c3125e5a4b86b8f304bc2889e313688c3d83e Author: Bdale Garbee Date: Mon Nov 2 15:59:12 2009 -0700 @@ -16,6 +47,134 @@ Date: Mon Nov 2 15:56:42 2009 -0700 de-version the libreadline-dev build dependency +commit 0b483233118673cbc2cda1be6acd379df82bc95a +Merge: ca5d323 550482d +Author: Keith Packard +Date: Sun Nov 1 20:59:02 2009 -0800 + + Merge remote branch 'origin/master' into skytraq + +commit ca5d323a3d206050d95f52a61e92c69e1f54e7b5 +Author: Keith Packard +Date: Sun Nov 1 20:57:03 2009 -0800 + + Enable packet-based communcation to command processor + + This splits the packet code into master/slave halves and hooks the + slave side up to the getchar/putchar/flush logic in ao_stdio.c + + Signed-off-by: Keith Packard + +commit 6c1a9ce16b966a21c885bf3be31cbcb85368b3fa +Author: Keith Packard +Date: Sat Oct 31 01:30:22 2009 -0700 + + No need to wakeup &ao_tick_count now + +commit cd0d495d7ef276956e730196476daa70a4359918 +Author: Keith Packard +Date: Sat Oct 31 01:20:26 2009 -0700 + + Poke master to speed up packet rate when things are busy + +commit 442b1ef18c8320d4e5329dc92bb5268a36058fc5 +Author: Keith Packard +Date: Sat Oct 31 01:19:41 2009 -0700 + + Use ao_alarm for ao_delay so it can be easily interrupted + +commit 4f7ed9ff484778381db647c27d2a34d0cadec41e +Author: Keith Packard +Date: Fri Oct 30 23:53:03 2009 -0700 + + Do more flushing in packet test code + +commit 6a7aa1810a90a9216160aec55ec4bd02b3240e1b +Author: Keith Packard +Date: Fri Oct 30 23:52:44 2009 -0700 + + Add RFIM register + +commit bf65e0b2a1299b49adc2d339ab9d9c7599aded9e +Author: Keith Packard +Date: Fri Oct 30 23:52:22 2009 -0700 + + Send SYN packet to set sequence numbers + +commit d46797e5c08d4955d516458185e2cfb51ee2d567 +Author: Keith Packard +Date: Fri Oct 30 23:51:38 2009 -0700 + + Use ao_radio_done to wait for TX to completely finish with packet + +commit c5ec6fcfa1bd17aad0f85d2fbe603f1d125836e6 +Author: Keith Packard +Date: Fri Oct 30 23:50:54 2009 -0700 + + Switch packet code from timer thread to ao_alarm + +commit b428faf74ae145126ec1da972028fcfe0b4b2b18 +Author: Keith Packard +Date: Fri Oct 30 23:48:36 2009 -0700 + + Remove reason from ao_dma_abort + +commit 73db30b2f9128c37dc7fa075793a8862814ce044 +Author: Keith Packard +Date: Fri Oct 30 23:46:21 2009 -0700 + + Add ao_alarm + +commit 251b0971f049cbf2f8db79a32729d47441ce65f3 +Author: Keith Packard +Date: Fri Oct 30 23:45:43 2009 -0700 + + Wait for TX to finish sending data + +commit 9b31f07fe3556896b3e997bba156e30ef5777a80 +Author: Keith Packard +Date: Fri Oct 30 23:43:52 2009 -0700 + + Add radio carrier command + +commit 7b14c3e609749f4fc00dbd660541375048535218 +Author: Keith Packard +Date: Fri Oct 30 16:39:15 2009 -0700 + + Initial packet bits. Just testing transmission + +commit 690fc263516d8beb6b24e86fbcd6588f42ce4e5c +Author: Keith Packard +Date: Wed Oct 21 17:18:49 2009 +0900 + + Add keyhole-markup generation for ao-postflight. + + This lets you see the flight path in googleearth. + + Signed-off-by: Keith Packard + +commit b657aa209b9ea3b3efd33a940283b3ba60a169af +Author: Keith Packard +Date: Fri Oct 16 12:59:53 2009 +0900 + + Add ao_wake_task and ao_exit + + ao_wake_task signals a specific task to wake up. + ao_exit terminates the current task. + + Signed-off-by: Keith Packard + +commit d709a0688eff84e25e24d755850ef045d6b0c3de +Author: Keith Packard +Date: Fri Oct 16 12:56:45 2009 +0900 + + Save some DSEG space by marking cmd functions __reentrant + + __reentrant causes the compiler to place args and locals on the stack + instead of in the data segment. + + Signed-off-by: Keith Packard + commit 550482d953c491a5ede9f2d243493afb13289898 Author: Bdale Garbee Date: Mon Oct 12 16:58:46 2009 -0600 @@ -84,6 +243,13 @@ Date: Mon Oct 12 15:57:08 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos +commit 69b6f6bb465163cf767bb68e0e4a716d8ad2b39c +Merge: bc77da6 2b76572 +Author: Keith Packard +Date: Sat Oct 10 17:16:21 2009 -0700 + + Merge branch 'master' into skytraq + commit 2b765728ce177e26899f6feef00bfdf6aeaf2678 Author: Keith Packard Date: Sat Oct 10 17:15:38 2009 -0700 @@ -95,6 +261,13 @@ Date: Sat Oct 10 17:15:38 2009 -0700 Signed-off-by: Keith Packard +commit bc77da68c9cb7d4cca483eadbbb7e9ccf71c0060 +Merge: 46cccf6 8f7ea3d +Author: Keith Packard +Date: Sat Oct 10 15:09:48 2009 -0700 + + Merge branch 'master' into skytraq + commit 8f7ea3de7037f40b0ff462b60d503c19431ae62b Author: Keith Packard Date: Sat Oct 10 15:08:14 2009 -0700 @@ -124,6 +297,13 @@ Date: Sat Oct 10 15:05:50 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos +commit 46cccf62fb40514b5930fcb2ffdaf2735415c764 +Merge: fb8f3fe 5f26ad6 +Author: Keith Packard +Date: Sat Oct 10 14:00:03 2009 -0700 + + Merge branch 'master' into skytraq + commit 5f26ad663b3f60dddc9d967206e365f45dc4acd1 Author: Keith Packard Date: Sat Oct 10 13:58:16 2009 -0700 @@ -138,6 +318,13 @@ Date: Sat Oct 10 13:58:16 2009 -0700 Signed-off-by: Keith Packard +commit fb8f3fee6a1bab1e46d782e84405845cee2dadb4 +Merge: 22856cf b8fc397 +Author: Keith Packard +Date: Sat Oct 10 13:41:00 2009 -0700 + + Merge branch 'master' into skytraq + commit b8fc3975bd92037a0cf53b0ff2b0e05ce0ba668f Author: Keith Packard Date: Sat Oct 10 13:39:01 2009 -0700 @@ -151,6 +338,13 @@ Date: Sat Oct 10 13:39:01 2009 -0700 Signed-off-by: Keith Packard +commit 22856cf8bb0f5e1f37c9b774132d9ef6934526ed +Merge: 2f76034 e29961f +Author: Keith Packard +Date: Sat Oct 10 11:44:20 2009 -0700 + + Merge branch 'master' into skytraq + commit e29961fdb2a48874c895829880eadbf13e094c0c Author: Keith Packard Date: Sat Oct 10 11:43:31 2009 -0700 @@ -162,6 +356,27 @@ Date: Sat Oct 10 11:43:31 2009 -0700 Signed-off-by: Keith Packard +commit 2f7603490a169df8f18b565db4fa967832ffc9bd +Author: Keith Packard +Date: Fri Oct 9 22:48:29 2009 -0700 + + Build two versions of TM, one for SiRF, one for SkyTraq + + This creates two separate images, depending on which GPS unit is + connected. + + Signed-off-by: Keith Packard + +commit 33b0b6f2f2e07de105619a7b463226d2813152ab +Author: Keith Packard +Date: Fri Oct 9 22:02:40 2009 -0700 + + Add support for the SkyTraq GPS unit + + This is a build-time option selected by hacking the Makefile at present. + + Signed-off-by: Keith Packard + commit a3771bfc5ce740f9d89193e9f8b1d7987aa57264 Author: Keith Packard Date: Tue Oct 6 20:06:00 2009 -0700 diff --git a/debian/changelog b/debian/changelog index 1040de36..d15ee3c7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,31 @@ +altos (0.6) unstable; urgency=low + + [ Keith Packard ] + * Add support for the SkyTraq GPS unit + * Build two versions of TM, one for SiRF, one for SkyTraq + * Save some DSEG space by marking cmd functions __reentrant + * Add ao_wake_task and ao_exit + * Add keyhole-markup generation for ao-postflight. + * Initial packet bits. Just testing transmission + * Add radio carrier command + * Wait for TX to finish sending data + * Add ao_alarm + * Remove reason from ao_dma_abort + * Switch packet code from timer thread to ao_alarm + * Use ao_radio_done to wait for TX to completely finish with packet + * Send SYN packet to set sequence numbers + * Add RFIM register + * Do more flushing in packet test code + * Use ao_alarm for ao_delay so it can be easily interrupted + * Poke master to speed up packet rate when things are busy + * No need to wakeup &ao_tick_count now + * Enable packet-based communcation to command processor + * Add more docs to the README file + * Disable interrupts while removing tasks from task list + * Add ao_usb_pollchar to ao.h + + -- Bdale Garbee Mon, 02 Nov 2009 16:53:45 -0700 + altos (0.5+90+g127c312) unstable; urgency=low * de-version the libreadline-dev build dependency -- cgit v1.2.3 From 144db05f6b286a0450d486f69ce192632a2c0656 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:38:18 -0800 Subject: Add two-point accelerometer calibration. Calibration now uses two values, one upside right and the other upside down instead of a single horizontal value. This allows the use of other accelerometers and compensates for variations in the divider circuit to provide more accurate data. --- debian/rules | 2 +- src/ao.h | 10 +++++---- src/ao_config.c | 61 +++++++++++++++++++++++++++++++++++++--------------- src/ao_flight.c | 46 +++++++++++++++++++-------------------- src/ao_flight_test.c | 7 ++++-- 5 files changed, 79 insertions(+), 47 deletions(-) diff --git a/debian/rules b/debian/rules index ac594c07..260ba773 100755 --- a/debian/rules +++ b/debian/rules @@ -9,7 +9,7 @@ DEB_VERSION := $(shell git describe | tr - +) prebuild: git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog - git commit ChangeLog debian/changelog \ + git commit -n ChangeLog debian/changelog \ -m "update changelogs for Debian build" git tag debian/$(DEB_VERSION) git push --tags origin master diff --git a/src/ao.h b/src/ao.h index 4cceefe1..22e8785f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -117,8 +117,9 @@ ao_panic(uint8_t reason); */ /* Our timer runs at 100Hz */ -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) +#define AO_HERTZ 100 +#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) +#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) /* Returns the current time in ticks */ uint16_t @@ -928,16 +929,17 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 1 +#define AO_CONFIG_MINOR 2 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; - int16_t accel_zero_g; + int16_t accel_plus_g; uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; + int16_t accel_minus_g; }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 021fb6f6..85fcff8c 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -45,7 +45,8 @@ _ao_config_get(void) ao_config.minor = AO_CONFIG_MINOR; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - ao_config.accel_zero_g = AO_CONFIG_DEFAULT_ACCEL_ZERO_G; + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); @@ -53,9 +54,14 @@ _ao_config_get(void) ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for major version 1 */ + /* Fixups for mior version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + /* Fixupes for minor version 2 */ + if (ao_config.minor < 2) { + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -152,23 +158,28 @@ ao_config_main_deploy_set(void) __reentrant } void -ao_config_accel_zero_g_show(void) __reentrant +ao_config_accel_calibrate_show(void) __reentrant { - printf("Accel zero g point: %d\n", - ao_config.accel_zero_g); + printf("Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); } -#define ZERO_G_SAMPLES 1000 +#define ACCEL_CALIBRATE_SAMPLES 1024 +#define ACCEL_CALIBRATE_SHIFT 10 static int16_t -ao_config_accel_zero_g_auto(void) __reentrant +ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; uint8_t cal_adc_ring; - puts("Calibrating accelerometer..."); flush(); - i = ZERO_G_SAMPLES; + printf("Orient %s and press a key...", orientation); + flush(); + (void) getchar(); + puts("\r\n"); flush(); + puts("Calibrating..."); flush(); + i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; cal_adc_ring = ao_adc_head; while (i) { @@ -179,22 +190,38 @@ ao_config_accel_zero_g_auto(void) __reentrant i--; } } - return (int16_t) (accel_total / ZERO_G_SAMPLES); + return accel_total >> ACCEL_CALIBRATE_SHIFT; } + void -ao_config_accel_zero_g_set(void) __reentrant +ao_config_accel_calibrate_set(void) __reentrant { + int16_t up, down; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i == 0) - ao_cmd_lex_i = ao_config_accel_zero_g_auto(); + if (ao_cmd_lex_i == 0) { + up = ao_config_accel_calibrate_auto("antenna up"); + down = ao_config_accel_calibrate_auto("antenna down"); + } else { + up = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + down = ao_cmd_lex_i; + } + if (up >= down) { + printf("Invalid accel calibration: antenna up (%d) should be less than antenna down (%d)\n", + up, down); + return; + } ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.accel_zero_g = ao_cmd_lex_i; + ao_config.accel_plus_g = up; + ao_config.accel_minus_g = down; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_accel_zero_g_show(); + ao_config_accel_calibrate_show(); } void @@ -237,8 +264,8 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, - { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show, - "a Set accelerometer zero g point (0 for auto)" }, + { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, + "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, diff --git a/src/ao_flight.c b/src/ao_flight.c index e91a5daa..92c955fb 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -48,6 +48,7 @@ __pdata int16_t ao_interval_max_pres; __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; +__pdata int16_t ao_accel_2g; /* Accelerometer calibration * @@ -72,19 +73,18 @@ __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; #define GRAVITY 9.80665 /* convert m/s to velocity count */ -#define VEL_MPS_TO_COUNT(mps) ((int32_t) (((mps) / GRAVITY) * ACCEL_G * 100)) +#define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) #define ACCEL_G 265 -#define ACCEL_ZERO_G 16000 -#define ACCEL_NOSE_UP (ACCEL_G * 2 /3) -#define ACCEL_BOOST ACCEL_G * 2 +#define ACCEL_NOSE_UP (ao_accel_2g / 4) +#define ACCEL_BOOST ao_accel_2g #define ACCEL_INT_LAND (ACCEL_G / 10) -#define ACCEL_VEL_LAND VEL_MPS_TO_COUNT(10) #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) -#define ACCEL_VEL_APOGEE VEL_MPS_TO_COUNT(2) -#define ACCEL_VEL_MAIN VEL_MPS_TO_COUNT(100) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) +int32_t accel_vel_mach; +int32_t accel_vel_boost; + /* * Barometer calibration * @@ -170,14 +170,14 @@ ao_flight(void) * so subtract instead of add. */ ticks = ao_flight_tick - ao_flight_prev_tick; - ao_vel_change = (((ao_raw_accel >> 1) + (ao_raw_accel_prev >> 1)) - ao_ground_accel); + ao_vel_change = ao_ground_accel - (((ao_raw_accel + 1) >> 1) + ((ao_raw_accel_prev + 1) >> 1)); ao_raw_accel_prev = ao_raw_accel; /* one is a common interval */ if (ticks == 1) - ao_flight_vel -= (int32_t) ao_vel_change; + ao_flight_vel += (int32_t) ao_vel_change; else - ao_flight_vel -= (int32_t) ao_vel_change * (int32_t) ticks; + ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } @@ -211,6 +211,9 @@ ao_flight(void) ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + accel_vel_mach = ACCEL_VEL_MACH; + accel_vel_boost = ACCEL_VEL_BOOST; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; @@ -218,8 +221,9 @@ ao_flight(void) /* Go to pad state if the nose is pointing up */ ao_config_get(); - if (ao_flight_accel < ao_config.accel_zero_g - ACCEL_NOSE_UP) { - + if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && + ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP) + { /* Disable the USB controller in flight mode * to save power */ @@ -337,19 +341,15 @@ ao_flight(void) /* apogee detect: coast to drogue deploy: * - * accelerometer: abs(velocity) > min_velocity + 2m/s - * OR * barometer: fall at least 10m * - * If the barometer saturates because the flight - * goes over its measuring range (about 53k'), - * requiring a 10m fall will avoid prematurely - * detecting apogee; the accelerometer will take - * over in that case and the integrated velocity - * measurement should suffice to find apogee + * It would be nice to use the accelerometer + * to detect apogee as well, but tests have + * shown that flights far from vertical would + * grossly mis-detect apogee. So, for now, + * we'll trust to a single sensor for this test */ - if (/* abs(ao_flight_vel) > ao_min_vel + ACCEL_VEL_APOGEE || */ - ao_flight_pres > ao_min_pres + BARO_APOGEE) + if (ao_flight_pres > ao_min_pres + BARO_APOGEE) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -462,7 +462,7 @@ ao_flight_status(void) __reentrant { printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", ao_state_names[ao_flight_state], - AO_ACCEL_COUNT_TO_MSS(ACCEL_ZERO_G - ao_flight_accel), + AO_ACCEL_COUNT_TO_MSS( - ao_flight_accel), AO_VEL_COUNT_TO_MS(ao_flight_vel), ao_pres_to_altitude(ao_flight_pres), ao_pres_to_altitude(ao_main_pres)); diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 83c63016..61f48cb6 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -22,6 +22,8 @@ #include #include +#define AO_HERTZ 100 + #define AO_ADC_RING 64 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -144,12 +146,13 @@ ao_altitude_to_pres(int16_t alt) __reentrant struct ao_config { uint16_t main_deploy; - int16_t accel_zero_g; + int16_t accel_plus_g; + int16_t accel_minus_g; }; #define ao_config_get() -struct ao_config ao_config = { 250, 16000 }; +struct ao_config ao_config = { 250, 15937, 16467 }; #include "ao_flight.c" -- cgit v1.2.3 From 47f510464907d2b9488109c96ade87a41d878842 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:46:39 -0800 Subject: Remove "l" command as ao-dumplong no longer uses it --- src/ao_log.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/ao_log.c b/src/ao_log.c index b2bfbd6f..50778f55 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -191,29 +191,6 @@ ao_log_stop(void) ao_log_flush(); } -static void -dump_log(void) __reentrant -{ - uint8_t more; - - for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) { - printf("%c %4x %4x %4x\n", - ao_log_dump.type, - ao_log_dump.tick, - ao_log_dump.u.anon.d0, - ao_log_dump.u.anon.d1); - if (ao_log_dump.type == AO_LOG_STATE && - ao_log_dump.u.state.state == ao_flight_landed) - break; - } - printf("end\n"); -} - -__code struct ao_cmds ao_log_cmds[] = { - { 'l', dump_log, "l Dump last flight log" }, - { 0, dump_log, NULL }, -}; - static __xdata struct ao_task ao_log_task; void @@ -228,5 +205,4 @@ ao_log_init(void) /* Create a task to log events to eeprom */ ao_add_task(&ao_log_task, ao_log, "log"); - ao_cmd_register(&ao_log_cmds[0]); } -- cgit v1.2.3 From a4137263b69864c524d39c6ff88a0225fd06e79b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:47:15 -0800 Subject: Remove "d" command --- src/ao_cmd.c | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 33619b24..e3f85bc9 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -178,33 +178,6 @@ eol(void) ao_cmd_lex(); } -static void -dump(void) -{ - __xdata uint16_t c; - __xdata uint8_t * __xdata start, * __xdata end; - - ao_cmd_hex(); - start = (uint8_t __xdata *) ao_cmd_lex_i; - ao_cmd_hex(); - end = (uint8_t __xdata *) ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - c = 0; - while (start <= end) { - if ((c & 7) == 0) { - if (c) - putchar('\n'); - ao_cmd_put16((uint16_t) start); - } - putchar(' '); - ao_cmd_put8(*start); - ++c; - start++; - } - putchar('\n'); -} - static void echo(void) { @@ -305,7 +278,6 @@ __code struct ao_cmds ao_base_cmds[] = { { '?', help, "? Print this message" }, { 'T', ao_task_info, "T Show task states" }, { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, - { 'd', dump, "d Dump memory" }, { 'v', version, "v Show version" }, { 0, help, NULL }, }; -- cgit v1.2.3 From 79718e798e96567f0ba11c61f187e432fdcf95ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:48:16 -0800 Subject: Remove "f" command --- src/ao_flight.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 92c955fb..f50491d9 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -454,27 +454,8 @@ ao_flight(void) } } -#define AO_ACCEL_COUNT_TO_MSS(count) ((count) / 27) -#define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700)) - -static void -ao_flight_status(void) __reentrant -{ - printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", - ao_state_names[ao_flight_state], - AO_ACCEL_COUNT_TO_MSS( - ao_flight_accel), - AO_VEL_COUNT_TO_MS(ao_flight_vel), - ao_pres_to_altitude(ao_flight_pres), - ao_pres_to_altitude(ao_main_pres)); -} - static __xdata struct ao_task flight_task; -__code struct ao_cmds ao_flight_cmds[] = { - { 'f', ao_flight_status, "f Display current flight state" }, - { 0, ao_flight_status, NULL } -}; - void ao_flight_init(void) { @@ -486,5 +467,4 @@ ao_flight_init(void) ao_interval_end = AO_INTERVAL_TICKS; ao_add_task(&flight_task, ao_flight, "flight"); - ao_cmd_register(&ao_flight_cmds[0]); } -- cgit v1.2.3 From f57bea012d4fbca097df0d98fcd30eb4abd9701a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:47:41 -0800 Subject: Reformat ADC values to show all 16 bits --- src/ao_adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_adc.c b/src/ao_adc.c index d9672671..a8784667 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -65,9 +65,9 @@ ao_adc_dump(void) __reentrant { static __xdata struct ao_adc packet; ao_adc_get(&packet); - printf("tick: %5u accel: %4d pres: %4d temp: %4d batt: %4d drogue: %4d main: %4d\n", - packet.tick, packet.accel >> 4, packet.pres >> 4, packet.temp >> 4, - packet.v_batt >> 4, packet.sense_d >> 4, packet.sense_m >> 4); + printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", + packet.tick, packet.accel, packet.pres, packet.temp, + packet.v_batt, packet.sense_d, packet.sense_m); } __code struct ao_cmds ao_adc_cmds[] = { -- cgit v1.2.3 From b529e5e8998702986909111a457f3ce9932e1ccf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 23:48:29 -0800 Subject: ao_flight_test was using accel value for pressure too --- src/ao_flight_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 61f48cb6..2bf7f2b2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -217,7 +217,7 @@ ao_sleep(void *wchan) type = words[0][0]; tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); - b = strtoul(words[2], NULL, 16); + b = strtoul(words[3], NULL, 16); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 1de322b960005c9a16051afa1881fadb00f4bcd6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Nov 2009 00:40:38 -0800 Subject: Pass accel calibration over telemetry stream. Telemetry data format change. This allows the ground station to convert the accelerometer sensor values into acceleration and speed data. This requires a new telemetry data structure, and so TeleMetrum and TeleDongle units must be updated synchronously. ao-view will parse either telemetry stream, and the serial format from TeleDongle now has a version number to allow for future changes. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview.h | 2 ++ ao-tools/ao-view/aoview_monitor.c | 23 ++++++++++++++++++++--- ao-tools/ao-view/aoview_state.c | 6 ++++-- src/ao.h | 3 +++ src/ao_monitor.c | 18 +++++++++++------- src/ao_telemetry.c | 2 ++ 6 files changed, 42 insertions(+), 12 deletions(-) diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h index c582159c..b6d5bcdf 100644 --- a/ao-tools/ao-view/aoview.h +++ b/ao-tools/ao-view/aoview.h @@ -104,6 +104,8 @@ struct aodata { int flight_vel; int flight_pres; int ground_pres; + int accel_plus_g; + int accel_minus_g; struct aogps gps; struct aogps_tracking gps_tracking; }; diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 48e20320..6d57f556 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -77,7 +77,9 @@ gboolean aoview_monitor_parse(const char *input_line) { char *saveptr; - char *words[PARSE_MAX_WORDS]; + char *raw_words[PARSE_MAX_WORDS]; + char **words; + int version = 0; int nword; char line_buf[8192], *line; struct aodata data; @@ -89,13 +91,19 @@ aoview_monitor_parse(const char *input_line) line_buf[sizeof(line_buf) - 1] = '\0'; line = line_buf; for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { - words[nword] = strtok_r(line, " \t\n", &saveptr); + raw_words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; - if (words[nword] == NULL) + if (raw_words[nword] == NULL) break; } if (nword < 36) return FALSE; + words = raw_words; + if (strcmp(words[0], "VERSION") == 0) { + aoview_parse_int(&version, words[1]); + words += 2; + nword -= 2; + } if (strcmp(words[0], "CALL") != 0) return FALSE; aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]); @@ -115,6 +123,15 @@ aoview_monitor_parse(const char *input_line) aoview_parse_int(&data.flight_vel, words[28]); aoview_parse_int(&data.flight_pres, words[30]); aoview_parse_int(&data.ground_pres, words[32]); + if (version >= 1) { + aoview_parse_int(&data.accel_plus_g, words[34]); + aoview_parse_int(&data.accel_minus_g, words[36]); + words += 4; + nword -= 4; + } else { + data.accel_plus_g = data.ground_accel; + data.accel_minus_g = data.ground_accel + 530; + } aoview_parse_int(&data.gps.nsat, words[34]); if (strcmp (words[36], "unlocked") == 0) { data.gps.gps_connected = 1; diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index f75066dd..f8f01685 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -105,6 +105,7 @@ aoview_state_derive(struct aodata *data, struct aostate *state) double new_height; double height_change; double time_change; + double accel_counts_per_mss; int tick_count; state->report_time = aoview_time(); @@ -123,8 +124,9 @@ aoview_state_derive(struct aodata *data, struct aostate *state) state->height = new_height; if (time_change) state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0; - state->acceleration = (data->ground_accel - data->flight_accel) / 27.0; - state->speed = data->flight_vel / 2700.0; + accel_counts_per_mss = ((data->accel_minus_g - data->accel_plus_g) / 2.0) / 9.80665; + state->acceleration = (data->ground_accel - data->flight_accel) / accel_counts_per_mss; + state->speed = data->flight_vel / (accel_counts_per_mss * 100.0); state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; state->drogue_sense = data->drogue / 32767.0 * 15.0; state->main_sense = data->main / 32767.0 * 15.0; diff --git a/src/ao.h b/src/ao.h index 22e8785f..bc9afcc3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -784,6 +784,7 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 +#define AO_TELEMETRY_VERSION 1 struct ao_telemetry { uint8_t addr; @@ -793,6 +794,8 @@ struct ao_telemetry { int32_t flight_vel; int16_t flight_pres; int16_t ground_pres; + int16_t accel_plus_g; + int16_t accel_minus_g; struct ao_adc adc; struct ao_gps_data gps; char callsign[AO_MAX_CALLSIGN]; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index d0c1da34..cd0d693e 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -37,12 +37,14 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf ("CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", - callsign, - recv.telemetry.addr, - (int) recv.rssi - 74, recv.status, - ao_state_names[state]); - printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d ", + printf("VERSION %d CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", + AO_TELEMETRY_VERSION, + callsign, + recv.telemetry.addr, + (int) recv.rssi - 74, recv.status, + ao_state_names[state]); + printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " + "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", recv.telemetry.adc.tick, recv.telemetry.adc.accel, recv.telemetry.adc.pres, @@ -54,7 +56,9 @@ ao_monitor(void) recv.telemetry.ground_accel, recv.telemetry.flight_vel, recv.telemetry.flight_pres, - recv.telemetry.ground_pres); + recv.telemetry.ground_pres, + recv.telemetry.accel_plus_g, + recv.telemetry.accel_minus_g); ao_gps_print(&recv.telemetry.gps); putchar(' '); ao_gps_tracking_print(&recv.telemetry.gps_tracking); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index d52e589c..9c923984 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -32,6 +32,8 @@ ao_telemetry(void) ao_config_get(); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + telemetry.accel_plus_g = ao_config.accel_plus_g; + telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) -- cgit v1.2.3 From 27ebaf8e13aed06bb1ea6e770f767495a02be6c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Nov 2009 01:27:37 -0800 Subject: Add ability to dump eeprom data over radio link. This adds a '-R' option to ao-dumplog to redirect the connection through a USB attached TeleDongle over the radio link to a remote TeleMetrum device. Signed-off-by: Keith Packard --- ao-tools/ao-dumplog/ao-dumplog.c | 19 +++++++++++++++---- ao-tools/lib/cc-usb.c | 26 ++++++++++++++++++++++++++ ao-tools/lib/cc-usb.h | 6 ++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index 158a445b..4bfb7e51 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -28,12 +28,13 @@ 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' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device \n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [-R]\n", program); exit(1); } @@ -80,8 +81,9 @@ main (int argc, char **argv) int data[8]; int done; int column; + int remote = 0; - while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:R", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -89,13 +91,20 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'R': + remote = 1; + break; default: usage(argv[0]); break; } } - if (!tty) - tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); + if (!tty) { + if (remote) + tty = cc_usbdevs_find_by_arg(device, "TeleDongle"); + else + tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); + } if (!tty) tty = getenv("ALTOS_TTY"); if (!tty) @@ -103,6 +112,8 @@ main (int argc, char **argv) cc = cc_usb_open(tty); if (!cc) exit(1); + if (remote) + cc_usb_open_remote(cc); /* send a 'version' command followed by a 'log' command */ cc_usb_printf(cc, "v\n"); out = NULL; diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 80d9c04f..9b3b831f 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -53,6 +53,8 @@ struct cc_usb { struct cc_hex_read hex_buf[CC_NUM_HEX_READ]; int hex_count; + + int remote; }; #define NOT_HEX 0xff @@ -372,6 +374,28 @@ cc_usb_reset(struct cc_usb *cc) return 1; } +void +cc_usb_open_remote(struct cc_usb *cc) +{ + if (!cc->remote) { + cc_usb_printf(cc, "p\nE 0\n"); + do { + cc->in_count = cc->in_pos = 0; + _cc_usb_sync(cc, 100); + } while (cc->in_count > 0); + cc->remote = 1; + } +} + +void +cc_usb_close_remote(struct cc_usb *cc) +{ + if (cc->remote) { + cc_usb_printf(cc, "~"); + cc->remote = 0; + } +} + static struct termios save_termios; struct cc_usb * @@ -406,6 +430,8 @@ cc_usb_open(char *tty) void cc_usb_close(struct cc_usb *cc) { + cc_usb_close_remote(cc); + cc_usb_sync(cc); tcsetattr(cc->fd, TCSAFLUSH, &save_termios); close (cc->fd); free (cc); diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h index 7b6be350..627f1b5d 100644 --- a/ao-tools/lib/cc-usb.h +++ b/ao-tools/lib/cc-usb.h @@ -62,4 +62,10 @@ cc_usb_getline(struct cc_usb *cc, char *line, int max); void cc_usb_printf(struct cc_usb *cc, char *format, ...); +void +cc_usb_open_remote(struct cc_usb *cc); + +void +cc_usb_close_remote(struct cc_usb *cc); + #endif /* _CC_USB_H_ */ -- cgit v1.2.3 From bc62bb254085cc705203b57260c04ac5e14c6611 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:29:37 -0800 Subject: In packet master, move USB flush from packet thread to echo thread This keeps the packet thread from blocking on USB and also makes the flush happen after every packet (slightly more USB traffic, but packets are slow anyway). Signed-off-by: Keith Packard --- src/ao_packet_master.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 2751f414..d03899d1 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -27,6 +27,7 @@ ao_packet_getchar(void) break; if (ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); + flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -94,8 +95,6 @@ ao_packet_master(void) continue; if (ao_rx_packet.packet.len) ao_packet_master_busy(); - else - flush(); ao_packet_master_sleeping = 1; ao_delay(ao_packet_master_delay); ao_packet_master_sleeping = 0; -- cgit v1.2.3 From 3ece984f4d72b4f720a5efdfaad7cff77a93d676 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:32:07 -0800 Subject: In USB pollchar, wait for packet before re-checking USB out len This probably wouldn't actually cause a problem, but it seems more reliable to wait for a packet interrupt before re-reading the packet OUT len register. This could avoid spinning while waiting for a USB packet, which seems like a good thing. Signed-off-by: Keith Packard --- src/ao_usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ao_usb.c b/src/ao_usb.c index daca71a7..527e9b30 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -377,11 +377,13 @@ char ao_usb_pollchar(void) __critical { char c; - while (ao_usb_out_bytes == 0) { + if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; + if (ao_usb_out_bytes == 0) + return AO_READ_AGAIN; } --ao_usb_out_bytes; c = USBFIFO[AO_USB_OUT_EP << 1]; -- cgit v1.2.3 From 036400a2db303f3db3be7cc0426f88359c6bd2b1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:42:51 -0800 Subject: Explicitly use USB I/O routines in packet code Using the implicit stdio functions (putchar/getchar/flush) would result in essentially random redirection of each, depending on whether the packet code had characters available when getchar was called. This would cause lockups in putchar. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index d03899d1..f3a024ca 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -27,7 +27,7 @@ ao_packet_getchar(void) break; if (ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); - flush(); + ao_usb_flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -40,7 +40,7 @@ ao_packet_echo(void) __reentrant while (ao_packet_enable) { c = ao_packet_getchar(); if (ao_packet_enable) - putchar(c); + ao_usb_putchar(c); } ao_exit(); } @@ -114,7 +114,7 @@ ao_packet_forward(void) __reentrant ao_set_monitor(0); ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { + while ((c = ao_usb_getchar()) != '~') { if (c == '\r') c = '\n'; ao_packet_putchar(c); } -- cgit v1.2.3 From 843ee489aac34ad6d81f55f1c85fb9eecc42d86b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:59:12 -0800 Subject: Flush pending input when switching to remote packet mode Any pending input would just confuse the application, so pull it off the link and dump it. Signed-off-by: Keith Packard --- ao-tools/lib/cc-usb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 9b3b831f..53a50741 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -378,7 +378,7 @@ void cc_usb_open_remote(struct cc_usb *cc) { if (!cc->remote) { - cc_usb_printf(cc, "p\nE 0\n"); + cc_usb_printf(cc, "\np\nE 0\n"); do { cc->in_count = cc->in_pos = 0; _cc_usb_sync(cc, 100); @@ -419,7 +419,7 @@ cc_usb_open(char *tty) save_termios = termios; cfmakeraw(&termios); tcsetattr(cc->fd, TCSAFLUSH, &termios); - cc_usb_printf(cc, "E 0\nm 0\n"); + cc_usb_printf(cc, "\nE 0\nm 0\n"); do { cc->in_count = cc->in_pos = 0; _cc_usb_sync(cc, 100); -- cgit v1.2.3 From 5a79a04ddb0b3ee64de34e366f71a0f6db509c01 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:59:51 -0800 Subject: Stop recording in ao-dumplog after receiving an invalid block If no samples in a block are valid, assume the flight log is over. Signed-off-by: Keith Packard --- ao-tools/ao-dumplog/ao-dumplog.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index 4bfb7e51..b3a0a25a 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -82,6 +82,8 @@ main (int argc, char **argv) int done; int column; int remote = 0; + int any_valid; + int invalid; while ((c = getopt_long(argc, argv, "T:D:R", options, NULL)) != -1) { switch (c) { @@ -146,6 +148,7 @@ main (int argc, char **argv) column = 0; } putchar('.'); fflush(stdout); column++; + any_valid = 0; for (addr = 0; addr < 0x100;) { cc_usb_getline(cc, line, sizeof (line)); if (sscanf(line, "00%x %x %x %x %x %x %x %x %x", @@ -160,6 +163,8 @@ main (int argc, char **argv) if (log_checksum(data) != 0) fprintf (stderr, "invalid checksum at 0x%x\n", block * 256 + received_addr); + else + any_valid = 1; cmd = data[0]; tick = data[2] + (data[3] << 8); @@ -182,6 +187,11 @@ main (int argc, char **argv) addr += 8; } } + if (!any_valid) { + fclose(out); + out = NULL; + done = 1; + } } if (column) putchar('\n'); -- cgit v1.2.3 From 4114210e0b813f4af99d0cb7755ad2ac2c4b120e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:43:21 -0800 Subject: Move ao_match_word from ao_ignite.c to ao_cmd.c This is a generally useful command line utility. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_cmd.c | 14 ++++++++++++++ src/ao_ignite.c | 14 -------------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/ao.h b/src/ao.h index bc9afcc3..508ed37a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -350,6 +350,9 @@ ao_cmd_hex(void); void ao_cmd_decimal(void); +uint8_t +ao_match_word(__code char *word); + struct ao_cmds { char cmd; void (*func)(void); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index e3f85bc9..81a52708 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -171,6 +171,20 @@ ao_cmd_decimal(void) ao_cmd_status = r; } +uint8_t +ao_match_word(__code char *word) +{ + while (*word) { + if (ao_cmd_lex_c != *word) { + ao_cmd_status = ao_cmd_syntax_error; + return 0; + } + word++; + ao_cmd_lex(); + } + return 1; +} + static void eol(void) { diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 8206e342..981cf0ce 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -121,20 +121,6 @@ ao_igniter(void) } } -static uint8_t -ao_match_word(__code char *word) -{ - while (*word) { - if (ao_cmd_lex_c != *word) { - ao_cmd_status = ao_cmd_syntax_error; - return 0; - } - word++; - ao_cmd_lex(); - } - return 1; -} - void ao_ignite_manual(void) { -- cgit v1.2.3 From 0358988ac0ee25a564d48af79b1c3fb0c0fe0a88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:44:31 -0800 Subject: Add Watchdog Timer Control register definitions Signed-off-by: Keith Packard --- src/cc1111.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/cc1111.h b/src/cc1111.h index ee4c9f09..e8302df2 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -535,6 +535,23 @@ sfr at 0xB6 ADCCON3; */ sfr at 0xF2 ADCCFG; +/* + * Watchdog timer + */ + +sfr at 0xc9 WDCTL; + +#define WDCTL_CLEAR_FIRST (0xa << 4) +#define WDCTL_CLEAR_SECOND (0x5 << 4) +#define WDCTL_EN (1 << 3) +#define WDCTL_MODE_WATCHDOG (0 << 2) +#define WDCTL_MODE_TIMER (1 << 2) +#define WDCTL_MODE_MASK (1 << 2) +#define WDCTL_INT_32768 (0 << 0) +#define WDCTL_INT_8192 (1 << 0) +#define WDCTL_INT_512 (2 << 0) +#define WDCTL_INT_64 (3 << 0) + /* * Pin selectors, these set which pins are * using their peripheral function -- cgit v1.2.3 From 83afdbdc154fe013bfe35ce5ecf1d61570b04ed6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:45:00 -0800 Subject: Add reboot command. This resets the processor using the watchdog timer. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_cmd.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/src/ao.h b/src/ao.h index 508ed37a..2df81d2a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -107,6 +107,7 @@ ao_start_scheduler(void); #define AO_PANIC_LOG 5 /* Failing to read/write log data */ #define AO_PANIC_CMD 6 /* Too many command sets registered */ #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ +#define AO_PANIC_REBOOT 8 /* Reboot failed */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 81a52708..58039f3a 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -199,6 +199,17 @@ echo(void) lex_echo = ao_cmd_lex_i != 0; } +static void +ao_reboot(void) +{ + ao_cmd_white(); + if (!ao_match_word("eboot")) + return; + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; + ao_sleep(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} + static void version(void) { @@ -292,6 +303,7 @@ __code struct ao_cmds ao_base_cmds[] = { { '?', help, "? Print this message" }, { 'T', ao_task_info, "T Show task states" }, { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, + { 'r', ao_reboot, "r eboot Reboot" }, { 'v', version, "v Show version" }, { 0, help, NULL }, }; -- cgit v1.2.3 From adf656192441eb7f44792955c86e469145477e29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 22:11:59 -0800 Subject: Return radio to telemetry settings when packet system closed. To receive telemetry after disabling the packet system, the radio must be reconfigured for telemetry mode. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index f3a024ca..a499ce59 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -100,6 +100,7 @@ ao_packet_master(void) ao_packet_master_sleeping = 0; } } + ao_radio_set_telemetry(); ao_exit(); } -- cgit v1.2.3 From 03092d1a72a9651711e22c58dca6d6aba5705c5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 16:35:12 -0800 Subject: ao-postflight: fix sloppy gps sat data realloc code (was crashing). Realloc'ing the wrong data, and failing to set the realloc'ed size was causing ao-postflight to crash while reading long logs. Signed-off-by: Keith Packard --- ao-tools/lib/cc-logfile.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 2136eec4..3d346bcc 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -101,11 +101,12 @@ gpssat_add(struct cc_gpsdata *data, struct cc_gpssat *sat) if (data->sizesats == 0) newsats = malloc((newsizesats = 256) * sizeof (struct cc_gpssats)); else - newsats = realloc (data->data, (newsizesats = data->sizesats * 2) + newsats = realloc (data->sats, (newsizesats = data->sizesats * 2) * sizeof (struct cc_gpssats)); if (!newsats) return 0; data->sats = newsats; + data->sizesats = newsizesats; } i = data->numsats++; data->sats[i].nsat = 0; -- cgit v1.2.3 From 1c654a9369294c9b8066c33f91161d8005b96680 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 22:17:24 -0800 Subject: Loosen tolerances for main->landed transition Detecting that the rocket has landed is required for the system to flush the eeprom log and re-enable the RDF beacon. This patch changes the landed state entry requirements for the accelerometer to require only that the accelerometer stay within a quarter of a g (down from 1/10g) and changes the testing interval from 20 seconds to 5 seconds. The requirement that the barometric altitude be within 1000m of the launch altitude and that the barometer change by no more than 0.05kPa are unchanged. Signed-off-by: Keith Packard --- src/ao_flight.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index f50491d9..f57573d0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -75,10 +75,10 @@ __pdata int16_t ao_accel_2g; /* convert m/s to velocity count */ #define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) -#define ACCEL_G 265 -#define ACCEL_NOSE_UP (ao_accel_2g / 4) +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) #define ACCEL_BOOST ao_accel_2g -#define ACCEL_INT_LAND (ACCEL_G / 10) +#define ACCEL_COAST (ao_accel_2g >> 3) +#define ACCEL_INT_LAND (ao_accel_2g >> 3) #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) @@ -132,7 +132,7 @@ __xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(20) +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define abs(a) ((a) < 0 ? -(a) : (a)) @@ -301,7 +301,7 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ - if (ao_flight_accel > ao_ground_accel + (ACCEL_G >> 2) || + if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) { ao_flight_state = ao_flight_fast; @@ -432,20 +432,20 @@ ao_flight(void) ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; - } - if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && - ao_flight_pres > ao_ground_pres - BARO_LAND && - (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) - { - ao_flight_state = ao_flight_landed; + if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && + ao_flight_pres > ao_ground_pres - BARO_LAND && + (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) + { + ao_flight_state = ao_flight_landed; - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - /* Enable RDF beacon */ - ao_rdf_set(1); + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + /* Enable RDF beacon */ + ao_rdf_set(1); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } } break; case ao_flight_landed: -- cgit v1.2.3 From 0e0db8ca3af4c07bae909938486766c646bf580b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 22:24:09 -0800 Subject: Provide a dummy 'uninstall' target in the src directory. Signed-off-by: Keith Packard --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Makefile b/src/Makefile index d984e9dc..8c24e6f4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -298,6 +298,8 @@ clean: install: +uninstall: + ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -- cgit v1.2.3 From 4cffc9c4b079e39c8196ddbaf91129cda6df7f8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 22:24:37 -0800 Subject: Share telemetry parsing code in cc library. ao-view had a private copy of the telemetry parsing code which included the ability to parse the newer version of that file. Those changes have been moved to the library version and the private copy removed. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview.h | 77 ++---------------- ao-tools/ao-view/aoview_monitor.c | 159 +------------------------------------- ao-tools/ao-view/aoview_state.c | 4 +- ao-tools/lib/cc-telem.c | 24 +++++- ao-tools/lib/cc.h | 2 + 5 files changed, 33 insertions(+), 233 deletions(-) diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h index b6d5bcdf..b937df7c 100644 --- a/ao-tools/ao-view/aoview.h +++ b/ao-tools/ao-view/aoview.h @@ -43,79 +43,12 @@ #include #include -struct aogps_time { - int hour; - int minute; - int second; -}; - -struct aogps { - int nsat; - int gps_locked; - int gps_connected; - struct aogps_time gps_time; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - - int gps_extended; /* has extra data */ - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless? */ - int h_error; /* m */ - int v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct aogps_sat { - int svid; - int state; - int c_n0; -}; - -struct aogps_tracking { - int channels; - struct aogps_sat sats[12]; -}; - -struct aodata { - char callsign[16]; - int serial; - int rssi; - char state[16]; - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - int flight_accel; - int ground_accel; - int flight_vel; - int flight_pres; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - struct aogps gps; - struct aogps_tracking gps_tracking; -}; - struct aostate { - struct aodata data; + struct cc_telem data; /* derived data */ - struct aodata prev_data; + struct cc_telem prev_data; double report_time; @@ -135,8 +68,8 @@ struct aostate { double max_acceleration; double max_speed; - struct aogps gps; - struct aogps_tracking gps_tracking; + struct cc_gps gps; + struct cc_gps_tracking gps_tracking; int gps_valid; double pad_lat; @@ -201,7 +134,7 @@ void aoview_dev_dialog_init(GladeXML *xml); void -aoview_state_notify(struct aodata *data); +aoview_state_notify(struct cc_telem *data); void aoview_state_new(void); diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 6d57f556..0f4afb0f 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -34,167 +34,14 @@ aoview_monitor_disconnect(void) aoview_log_new(); } -static void -aoview_parse_string(char *target, int len, char *source) -{ - strncpy(target, source, len-1); - target[len-1] = '\0'; -} - -static void -aoview_parse_int(int *target, char *source) -{ - *target = strtol(source, NULL, 0); -} - -static void -aoview_parse_hex(int *target, char *source) -{ - *target = strtol(source, NULL, 16); -} - -static void -aoview_parse_pos(double *target, char *source) -{ - int deg; - double min; - char dir; - double r; - - if (sscanf(source, "%d°%lf'%c", °, &min, &dir) != 3) { - *target = 0; - return; - } - r = deg + min / 60.0; - if (dir == 'S' || dir == 'W') - r = -r; - *target = r; -} - -#define PARSE_MAX_WORDS 256 - gboolean aoview_monitor_parse(const char *input_line) { - char *saveptr; - char *raw_words[PARSE_MAX_WORDS]; - char **words; - int version = 0; - int nword; - char line_buf[8192], *line; - struct aodata data; - int tracking_pos; - int channel; + struct cc_telem telem; - /* avoid smashing our input parameter */ - strncpy (line_buf, input_line, sizeof (line_buf)-1); - line_buf[sizeof(line_buf) - 1] = '\0'; - line = line_buf; - for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { - raw_words[nword] = strtok_r(line, " \t\n", &saveptr); - line = NULL; - if (raw_words[nword] == NULL) - break; - } - if (nword < 36) - return FALSE; - words = raw_words; - if (strcmp(words[0], "VERSION") == 0) { - aoview_parse_int(&version, words[1]); - words += 2; - nword -= 2; - } - if (strcmp(words[0], "CALL") != 0) + if (!cc_telem_parse(input_line, &telem)) return FALSE; - aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]); - aoview_parse_int(&data.serial, words[3]); - - aoview_parse_int(&data.rssi, words[5]); - aoview_parse_string(data.state, sizeof (data.state), words[9]); - aoview_parse_int(&data.tick, words[10]); - aoview_parse_int(&data.accel, words[12]); - aoview_parse_int(&data.pres, words[14]); - aoview_parse_int(&data.temp, words[16]); - aoview_parse_int(&data.batt, words[18]); - aoview_parse_int(&data.drogue, words[20]); - aoview_parse_int(&data.main, words[22]); - aoview_parse_int(&data.flight_accel, words[24]); - aoview_parse_int(&data.ground_accel, words[26]); - aoview_parse_int(&data.flight_vel, words[28]); - aoview_parse_int(&data.flight_pres, words[30]); - aoview_parse_int(&data.ground_pres, words[32]); - if (version >= 1) { - aoview_parse_int(&data.accel_plus_g, words[34]); - aoview_parse_int(&data.accel_minus_g, words[36]); - words += 4; - nword -= 4; - } else { - data.accel_plus_g = data.ground_accel; - data.accel_minus_g = data.ground_accel + 530; - } - aoview_parse_int(&data.gps.nsat, words[34]); - if (strcmp (words[36], "unlocked") == 0) { - data.gps.gps_connected = 1; - data.gps.gps_locked = 0; - data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; - data.gps.lat = data.gps.lon = 0; - data.gps.alt = 0; - tracking_pos = 37; - } else if (nword >= 40) { - data.gps.gps_locked = 1; - data.gps.gps_connected = 1; - sscanf(words[36], "%d:%d:%d", &data.gps.gps_time.hour, &data.gps.gps_time.minute, &data.gps.gps_time.second); - aoview_parse_pos(&data.gps.lat, words[37]); - aoview_parse_pos(&data.gps.lon, words[38]); - sscanf(words[39], "%dm", &data.gps.alt); - tracking_pos = 46; - } else { - data.gps.gps_connected = 0; - data.gps.gps_locked = 0; - data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; - data.gps.lat = data.gps.lon = 0; - data.gps.alt = 0; - tracking_pos = -1; - } - if (nword >= 46) { - data.gps.gps_extended = 1; - sscanf(words[40], "%lfm/s", &data.gps.ground_speed); - sscanf(words[41], "%d", &data.gps.course); - sscanf(words[42], "%lfm/s", &data.gps.climb_rate); - sscanf(words[43], "%lf", &data.gps.hdop); - sscanf(words[44], "%d", &data.gps.h_error); - sscanf(words[45], "%d", &data.gps.v_error); - } else { - data.gps.gps_extended = 0; - data.gps.ground_speed = 0; - data.gps.course = 0; - data.gps.climb_rate = 0; - data.gps.hdop = 0; - data.gps.h_error = 0; - data.gps.v_error = 0; - } - if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { - int c, n, pos; - aoview_parse_int(&n, words[tracking_pos + 1]); - pos = tracking_pos + 2; - if (nword >= pos + n * 3) { - data.gps_tracking.channels = n; - for (c = 0; c < n; c++) { - aoview_parse_int(&data.gps_tracking.sats[c].svid, - words[pos + 0]); - aoview_parse_hex(&data.gps_tracking.sats[c].state, - words[pos + 1]); - aoview_parse_int(&data.gps_tracking.sats[c].c_n0, - words[pos + 2]); - pos += 3; - } - } else { - data.gps_tracking.channels = 0; - } - } else { - data.gps_tracking.channels = 0; - } - aoview_state_notify(&data); + aoview_state_notify(&telem); return TRUE; } diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index f8f01685..a7545c51 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -99,7 +99,7 @@ aoview_time(void) * Fill out the derived data fields */ static void -aoview_state_derive(struct aodata *data, struct aostate *state) +aoview_state_derive(struct cc_telem *data, struct aostate *state) { int i; double new_height; @@ -274,7 +274,7 @@ aoview_state_reset(void) } void -aoview_state_notify(struct aodata *data) +aoview_state_notify(struct cc_telem *data) { struct aostate *state = &aostate; aoview_state_derive(data, state); diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index a6ac0313..f82ab961 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -62,7 +62,9 @@ int cc_telem_parse(const char *input_line, struct cc_telem *telem) { char *saveptr; - char *words[PARSE_MAX_WORDS]; + char *raw_words[PARSE_MAX_WORDS]; + char **words; + int version = 0; int nword; char line_buf[8192], *line; int tracking_pos; @@ -72,13 +74,20 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) line_buf[sizeof(line_buf) - 1] = '\0'; line = line_buf; for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { - words[nword] = strtok_r(line, " \t\n", &saveptr); + raw_words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; - if (words[nword] == NULL) + if (raw_words[nword] == NULL) break; } if (nword < 36) return FALSE; + words = raw_words; + if (strcmp(words[0], "VERSION") == 0) { + cc_parse_int(&version, words[1]); + words += 2; + nword -= 2; + } + if (strcmp(words[0], "CALL") != 0) return FALSE; cc_parse_string(telem->callsign, sizeof (telem->callsign), words[1]); @@ -98,6 +107,15 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) cc_parse_int(&telem->flight_vel, words[28]); cc_parse_int(&telem->flight_pres, words[30]); cc_parse_int(&telem->ground_pres, words[32]); + if (version >= 1) { + cc_parse_int(&telem->accel_plus_g, words[34]); + cc_parse_int(&telem->accel_minus_g, words[36]); + words += 4; + nword -= 4; + } else { + telem->accel_plus_g = telem->ground_accel; + telem->accel_minus_g = telem->ground_accel + 530; + } cc_parse_int(&telem->gps.nsat, words[34]); if (strcmp (words[36], "unlocked") == 0) { telem->gps.gps_connected = 1; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index b5f1132f..fd461e5c 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -252,6 +252,8 @@ struct cc_telem { int flight_vel; int flight_pres; int ground_pres; + int accel_plus_g; + int accel_minus_g; struct cc_gps gps; struct cc_gps_tracking gps_tracking; }; -- cgit v1.2.3 From 9b06e294e2777f69bcf5e98789c3f5477097d53b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 15:51:58 -0800 Subject: Enable telemetry receive in ao_view --- ao-tools/ao-view/aoview_monitor.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 0f4afb0f..3d235e44 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -99,6 +99,7 @@ aoview_monitor_connect(char *tty) channel = aoview_channel_current(); if (channel >= 0) aoview_monitor_set_channel(channel); + aoview_serial_printf(monitor_serial, "m 1\n"); aoview_serial_set_callback(monitor_serial, aoview_monitor_callback); return TRUE; -- cgit v1.2.3 From 6391c89bd5b89f5f46255b8365c658a873e5959a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 15:53:01 -0800 Subject: Switch order of serial/flight in ao-postflight summary --- ao-tools/ao-postflight/ao-postflight.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 60d8c036..733eb38c 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -204,8 +204,10 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, struct cc_flightcooked *cooked; double apogee; - fprintf(summary_file, "Flight: %9d\nSerial: %9d\n", - f->flight, f->serial); + fprintf(summary_file, + "Serial: %9d\n" + "Flight: %9d\n", + f->serial, f->flight); boost_start = f->accel.data[0].time; boost_stop = f->accel.data[f->accel.num-1].time; for (i = 0; i < f->state.num; i++) { -- cgit v1.2.3 From 3ee279ba76c2a79d142c466f19ef758cf4c01d70 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 15:59:01 -0800 Subject: Add flight number to telemetry stream. This makes it easier to tie the telemetry and eeprom files together as they're now both labeled with serial and flight numbers, which should be unique. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 1 + ao-tools/lib/cc-telem.c | 7 ++++++ ao-tools/lib/cc.h | 1 + src/ao.h | 11 +++++---- src/ao_log.c | 51 +++++++++++------------------------------ src/ao_monitor.c | 3 ++- src/ao_telemetry.c | 3 +++ 7 files changed, 34 insertions(+), 43 deletions(-) diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index a7545c51..2f613d44 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -288,6 +288,7 @@ aoview_state_notify(struct cc_telem *data) aoview_table_add_row(0, "Rocket state", "%s", state->data.state); aoview_table_add_row(0, "Callsign", "%s", state->data.callsign); aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial); + aoview_table_add_row(0, "Rocket flight", "%d", state->data.flight); aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi); aoview_table_add_row(0, "Height", "%6dm", state->height); diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index f82ab961..0e1483f7 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -93,6 +93,13 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) cc_parse_string(telem->callsign, sizeof (telem->callsign), words[1]); cc_parse_int(&telem->serial, words[3]); + if (version >= 2) { + cc_parse_int(&telem->flight, words[5]); + words += 2; + nword -= 2; + } else + telem->flight = 0; + cc_parse_int(&telem->rssi, words[5]); cc_parse_string(telem->state, sizeof (telem->state), words[9]); cc_parse_int(&telem->tick, words[10]); diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index fd461e5c..b8e3c061 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -238,6 +238,7 @@ struct cc_gps_tracking { struct cc_telem { char callsign[16]; int serial; + int flight; int rssi; char state[16]; int tick; diff --git a/src/ao.h b/src/ao.h index 2df81d2a..f266ac64 100644 --- a/src/ao.h +++ b/src/ao.h @@ -553,11 +553,11 @@ ao_log_data(struct ao_log_record *log); void ao_log_flush(void); -/* Log dumping API: - * ao_log_dump_first() - get first log record - * ao_log_dump_next() - get next log record +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. */ -extern __xdata struct ao_log_record ao_log_dump; +extern __xdata uint16_t ao_flight_number; /* Retrieve first log record for the current flight */ uint8_t @@ -788,10 +788,11 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 1 +#define AO_TELEMETRY_VERSION 2 struct ao_telemetry { uint8_t addr; + uint16_t flight; uint8_t flight_state; int16_t flight_accel; int16_t ground_accel; diff --git a/src/ao_log.c b/src/ao_log.c index 50778f55..44ce90e0 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -59,51 +59,30 @@ ao_log_flush(void) ao_ee_flush(); } -__xdata struct ao_log_record ao_log_dump; -static __xdata uint16_t ao_log_dump_flight; -static __xdata uint32_t ao_log_dump_pos; +__xdata struct ao_log_record log; +__xdata uint16_t ao_flight_number; static uint8_t ao_log_dump_check_data(void) { - if (ao_log_csum((uint8_t *) &ao_log_dump) != 0) + if (ao_log_csum((uint8_t *) &log) != 0) return 0; return 1; } -static uint8_t -ao_log_dump_scan(void) +static void +ao_log_scan(void) { - if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, sizeof (struct ao_log_record))) + if (!ao_ee_read(0, (uint8_t *) &log, sizeof (struct ao_log_record))) ao_panic(AO_PANIC_LOG); - if (ao_log_dump_check_data() && ao_log_dump.type == AO_LOG_FLIGHT) { - ao_log_dump_flight = ao_log_dump.u.flight.flight; - return 1; + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { + ao_flight_number = log.u.flight.flight + 1; + if (ao_flight_number == 0) + ao_flight_number = 1; } else { - ao_log_dump_flight = 0; - return 0; + ao_flight_number = 1; } -} - -uint8_t -ao_log_dump_first(void) -{ - ao_log_dump_pos = 0; - if (!ao_log_dump_scan()) - return 0; - return 1; -} - -uint8_t -ao_log_dump_next(void) -{ - ao_log_dump_pos += sizeof (struct ao_log_record); - if (ao_log_dump_pos >= AO_EE_DEVICE_SIZE) - return 0; - if (!ao_ee_read(ao_log_dump_pos, (uint8_t *) &ao_log_dump, - sizeof (struct ao_log_record))) - return 0; - return ao_log_dump_check_data(); + ao_wakeup(&ao_flight_number); } __xdata uint8_t ao_log_adc_pos; @@ -115,9 +94,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - static __xdata struct ao_log_record log; - - ao_log_dump_scan(); + ao_log_scan(); while (!ao_log_running) ao_sleep(&ao_log_running); @@ -125,7 +102,7 @@ ao_log(void) log.type = AO_LOG_FLIGHT; log.tick = ao_flight_tick; log.u.flight.ground_accel = ao_ground_accel; - log.u.flight.flight = ao_log_dump_flight + 1; + log.u.flight.flight = ao_flight_number; ao_log_data(&log); /* Write the whole contents of the ring to the log diff --git a/src/ao_monitor.c b/src/ao_monitor.c index cd0d693e..628b6e67 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -37,10 +37,11 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", + printf("VERSION %d CALL %s SERIAL %3d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", AO_TELEMETRY_VERSION, callsign, recv.telemetry.addr, + recv.telemetry.flight, (int) recv.rssi - 74, recv.status, ao_state_names[state]); printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 9c923984..88ac142c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -30,8 +30,11 @@ ao_telemetry(void) static __xdata struct ao_telemetry telemetry; ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + telemetry.flight = ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); -- cgit v1.2.3 From 524665fc221b0d483453c67b7211e282cebc8980 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 16:04:41 -0800 Subject: Add date to GPS data, captured from GPRMC packet. Pull the date out of the GPS stream and send it over the telemetry link and write it to the eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 4 +++ ao-tools/lib/cc-telem.c | 12 ++++++++ ao-tools/lib/cc.h | 3 ++ src/ao.h | 10 ++++++ src/ao_gps_print.c | 4 +++ src/ao_gps_report.c | 12 ++++++-- src/ao_gps_skytraq.c | 67 ++++++++++++++++++++++++++++++++++++----- src/ao_gps_test.c | 4 +++ src/ao_gps_test_skytraq.c | 4 +++ 9 files changed, 111 insertions(+), 9 deletions(-) diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index 2f613d44..21cea99a 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -315,6 +315,10 @@ aoview_state_notify(struct cc_telem *data) aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); aoview_table_add_row(1, "GPS height", "%d", state->gps_height); + aoview_table_add_row(1, "GPS date", "%04d-%02d-%02d", + state->gps.gps_time.year, + state->gps.gps_time.month, + state->gps.gps_time.day); aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", state->gps.gps_time.hour, state->gps.gps_time.minute, diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index 0e1483f7..9a2f6155 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -127,6 +127,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) if (strcmp (words[36], "unlocked") == 0) { telem->gps.gps_connected = 1; telem->gps.gps_locked = 0; + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; telem->gps.lat = telem->gps.lon = 0; telem->gps.alt = 0; @@ -134,6 +135,16 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } else if (nword >= 40) { telem->gps.gps_locked = 1; telem->gps.gps_connected = 1; + if (version >= 2) { + sscanf(words[36], "%d-%d-%d", + &telem->gps.gps_time.year, + &telem->gps.gps_time.month, + &telem->gps.gps_time.day); + words += 1; + nword -= 1; + } else { + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; + } sscanf(words[36], "%d:%d:%d", &telem->gps.gps_time.hour, &telem->gps.gps_time.minute, &telem->gps.gps_time.second); cc_parse_pos(&telem->gps.lat, words[37]); cc_parse_pos(&telem->gps.lon, words[38]); @@ -142,6 +153,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } else { telem->gps.gps_connected = 0; telem->gps.gps_locked = 0; + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; telem->gps.lat = telem->gps.lon = 0; telem->gps.alt = 0; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index b8e3c061..ebc0db7d 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -192,6 +192,9 @@ struct cc_flightcooked { struct cc_gps_time { + int year; + int month; + int day; int hour; int minute; int second; diff --git a/src/ao.h b/src/ao.h index f266ac64..c1a0f6e3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -493,6 +493,7 @@ ao_ee_init(void); #define AO_LOG_GPS_LON 'W' #define AO_LOG_GPS_ALT 'H' #define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' #define AO_LOG_POS_NONE (~0UL) @@ -538,6 +539,11 @@ struct ao_log_record { uint8_t state; uint8_t c_n; } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + } gps_date; struct { uint16_t d0; uint16_t d1; @@ -720,8 +726,12 @@ ao_serial_init(void); #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index cc751337..95439ec7 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -53,6 +53,10 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant ao_gps_split(gps_data->latitude, &lat); ao_gps_split(gps_data->longitude, &lon); + printf(" 20%02d-%02d-%02d", + gps_data->year, + gps_data->month, + gps_data->day); printf(" %2d:%02d:%02d", gps_data->hour, gps_data->minute, diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index 75c944f5..e3e27523 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -22,6 +22,7 @@ ao_gps_report(void) { static __xdata struct ao_log_record gps_log; static __xdata struct ao_gps_data gps_data; + uint8_t date_reported = 0; for (;;) { ao_sleep(&ao_gps_data); @@ -49,6 +50,14 @@ ao_gps_report(void) gps_log.u.gps_altitude.altitude = gps_data.altitude; 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); + } } } @@ -71,8 +80,7 @@ ao_gps_tracking_report(void) gps_log.tick = ao_time(); gps_log.type = AO_LOG_GPS_SAT; for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid) && - (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) { gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; ao_log_data(&gps_log); diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index cd5f78b9..b2eef04b 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -19,9 +19,9 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 3 +#define AO_GPS_LEADER 2 -static const char ao_gps_header[] = "GPG"; +static const char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; static __xdata char ao_gps_char; @@ -32,6 +32,7 @@ __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; static __xdata struct ao_gps_data ao_gps_next; +static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; static const char ao_gps_config[] = { @@ -181,7 +182,7 @@ ao_gps_parse_flag(char no_c, char yes_c) __reentrant void ao_gps(void) __reentrant { - char c; + char a, c; uint8_t i; ao_serial_set_speed(AO_SERIAL_SPEED_9600); @@ -198,7 +199,7 @@ ao_gps(void) __reentrant ao_gps_cksum = 0; ao_gps_error = 0; - /* Skip anything other than GPG */ + /* Skip anything other than GP */ for (i = 0; i < AO_GPS_LEADER; i++) { ao_gps_lexchar(); if (ao_gps_char != ao_gps_header[i]) @@ -209,6 +210,8 @@ ao_gps(void) __reentrant /* pull the record identifier characters off the link */ ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); c = ao_gps_char; ao_gps_lexchar(); i = ao_gps_char; @@ -216,7 +219,7 @@ ao_gps(void) __reentrant if (ao_gps_char != ',') continue; - if (c == (uint8_t) 'G' && i == (uint8_t) 'A') { + if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { /* Now read the data into the gps data record * * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 @@ -245,7 +248,7 @@ ao_gps(void) __reentrant * *66 checksum */ - ao_gps_next.flags = AO_GPS_RUNNING; + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; ao_gps_next.hour = ao_gps_decimal(2); ao_gps_next.minute = ao_gps_decimal(2); ao_gps_next.second = ao_gps_decimal(2); @@ -290,7 +293,7 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } - } else if (c == (uint8_t) 'S' && i == (uint8_t) 'V') { + } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { uint8_t done; /* Now read the data into the GPS tracking data record * @@ -345,6 +348,56 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); } + } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } } } } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 366bca71..3692f0e5 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -27,8 +27,12 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 510bc419..ccf96378 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -27,8 +27,12 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; -- cgit v1.2.3 From b0d7e3f9c9322542e9b649bb6ad7f7e5bb99dffa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 16:20:18 -0800 Subject: Stop using SiRF state info. With the switch to the skytraq GPS unit, we don't have the same level of detail in the GPS stream, so stop reporting that in the telemetry stream, in the UI and writing it to eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 4 ++-- ao-tools/lib/cc-logfile.c | 1 - ao-tools/lib/cc-telem.c | 17 ++++++++++++----- ao-tools/lib/cc.h | 1 - src/ao.h | 12 +----------- src/ao_gps_print.c | 7 +++---- src/ao_gps_sirf.c | 5 +---- src/ao_gps_skytraq.c | 6 ++---- src/ao_gps_test.c | 5 ++--- 9 files changed, 23 insertions(+), 35 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 733eb38c..c12939aa 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -360,7 +360,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, nsat = 0; for (k = 0; k < f->gps.sats[j].nsat; k++) { fprintf (gps_file, " %12.7f", (double) f->gps.sats[j].sat[k].c_n); - if (f->gps.sats[j].sat[k].state == 0xbf) + if (f->gps.sats[j].sat[k].svid != 0) nsat++; } fprintf(gps_file, " %d\n", nsat); @@ -381,7 +381,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, } nsat = 0; for (k = 0; k < f->gps.sats[j].nsat; k++) - if (f->gps.sats[j].sat[k].state == 0xbf) + if (f->gps.sats[j].sat[k].svid != 0) nsat++; fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 3d346bcc..9d086c82 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -212,7 +212,6 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * case AO_LOG_GPS_SAT: sat.time = tick; sat.svid = a; - sat.state = (b & 0xff); sat.c_n = (b >> 8) & 0xff; gpssat_add(&f->gps, &sat); break; diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index 9a2f6155..ccd40ac2 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -178,18 +178,25 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { int c, n, pos; + int per_sat; + int state; + + if (version >= 2) + per_sat = 2; + else + per_sat = 3; cc_parse_int(&n, words[tracking_pos + 1]); pos = tracking_pos + 2; - if (nword >= pos + n * 3) { + if (nword >= pos + n * per_sat) { telem->gps_tracking.channels = n; for (c = 0; c < n; c++) { cc_parse_int(&telem->gps_tracking.sats[c].svid, words[pos + 0]); - cc_parse_hex(&telem->gps_tracking.sats[c].state, - words[pos + 1]); + if (version < 2) + cc_parse_hex(&state, words[pos + 1]); cc_parse_int(&telem->gps_tracking.sats[c].c_n0, - words[pos + 2]); - pos += 3; + words[pos + per_sat - 1]); + pos += per_sat; } } else { telem->gps_tracking.channels = 0; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index ebc0db7d..0e8ced8a 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -103,7 +103,6 @@ struct cc_gpselt { struct cc_gpssat { double time; uint16_t svid; - uint8_t state; uint8_t c_n; }; diff --git a/src/ao.h b/src/ao.h index c1a0f6e3..b72cac5c 100644 --- a/src/ao.h +++ b/src/ao.h @@ -536,7 +536,7 @@ struct ao_log_record { } gps_altitude; struct { uint16_t svid; - uint8_t state; + uint8_t unused; uint8_t c_n; } gps_sat; struct { @@ -747,18 +747,8 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - struct ao_gps_sat_data { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 95439ec7..b8b73cd2 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -112,17 +112,16 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ sat = gps_tracking_data->sats; v = 0; for (c = 0; c < n; c++) { - if (sat->svid && sat->state) + if (sat->svid) v++; sat++; } printf("%d ", v); sat = gps_tracking_data->sats; for (c = 0; c < n; c++) { - if (sat->svid && sat->state) - printf (" %3d %02x %3d", + if (sat->svid) + printf (" %3d %3d", sat->svid, - sat->state, sat->c_n_1); sat++; } diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 58438760..eb00224c 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -108,7 +108,6 @@ static __xdata struct sirf_geodetic_nav_data ao_sirf_data; struct sirf_measured_sat_data { uint8_t svid; - uint16_t state; uint8_t c_n_1; }; @@ -264,8 +263,7 @@ static const struct sirf_packet_parse measured_tracker_data_packet[] = { static const struct sirf_packet_parse measured_sat_data_packet[] = { { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ - { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ { SIRF_END, 0 }, @@ -421,7 +419,6 @@ ao_gps(void) __reentrant ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; for (i = 0; i < 12; i++) { ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; } ao_mutex_put(&ao_gps_mutex); diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index b2eef04b..bf192f28 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -326,10 +326,8 @@ ao_gps(void) __reentrant 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].state = 0xbf; - else - ao_gps_tracking_next.sats[i].state = 0; + 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; } if (ao_gps_char == '*') { diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 3692f0e5..fddfedfd 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -59,7 +59,6 @@ struct ao_gps_data { struct ao_gps_sat_data { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; @@ -435,9 +434,9 @@ ao_dump_state(void *wchan) printf("\n"); printf ("\t"); for (i = 0; i < 12; i++) - printf (" %2d(%02x)", + printf (" %2d(%02d)", ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].state); + ao_gps_tracking_data.sats[i].c_n_1); printf ("\n"); } -- cgit v1.2.3 From c2f661b75ec035f6a3f700962290ef297f9ab0af Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 20 Nov 2009 11:44:06 -0700 Subject: update changelogs for Debian build --- ChangeLog | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 33 +++++++ 2 files changed, 302 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3ef8d797..01451761 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,272 @@ +commit b0d7e3f9c9322542e9b649bb6ad7f7e5bb99dffa +Author: Keith Packard +Date: Sun Nov 15 16:20:18 2009 -0800 + + Stop using SiRF state info. + + With the switch to the skytraq GPS unit, we don't have the same level + of detail in the GPS stream, so stop reporting that in the telemetry + stream, in the UI and writing it to eeprom. + + Signed-off-by: Keith Packard + +commit 524665fc221b0d483453c67b7211e282cebc8980 +Author: Keith Packard +Date: Sun Nov 15 16:04:41 2009 -0800 + + Add date to GPS data, captured from GPRMC packet. + + Pull the date out of the GPS stream and send it over the telemetry + link and write it to the eeprom. + + Signed-off-by: Keith Packard + +commit 3ee279ba76c2a79d142c466f19ef758cf4c01d70 +Author: Keith Packard +Date: Sun Nov 15 15:59:01 2009 -0800 + + Add flight number to telemetry stream. + + This makes it easier to tie the telemetry and eeprom files together as + they're now both labeled with serial and flight numbers, which should + be unique. + + Signed-off-by: Keith Packard + +commit 6391c89bd5b89f5f46255b8365c658a873e5959a +Author: Keith Packard +Date: Sun Nov 15 15:53:01 2009 -0800 + + Switch order of serial/flight in ao-postflight summary + +commit 9b06e294e2777f69bcf5e98789c3f5477097d53b +Author: Keith Packard +Date: Sun Nov 15 15:51:58 2009 -0800 + + Enable telemetry receive in ao_view + +commit 4cffc9c4b079e39c8196ddbaf91129cda6df7f8b +Author: Keith Packard +Date: Sat Nov 14 22:24:37 2009 -0800 + + Share telemetry parsing code in cc library. + + ao-view had a private copy of the telemetry parsing code which + included the ability to parse the newer version of that file. Those + changes have been moved to the library version and the private copy removed. + + Signed-off-by: Keith Packard + +commit 0e0db8ca3af4c07bae909938486766c646bf580b +Author: Keith Packard +Date: Sat Nov 14 22:24:09 2009 -0800 + + Provide a dummy 'uninstall' target in the src directory. + + Signed-off-by: Keith Packard + +commit 1c654a9369294c9b8066c33f91161d8005b96680 +Author: Keith Packard +Date: Sat Nov 14 22:17:24 2009 -0800 + + Loosen tolerances for main->landed transition + + Detecting that the rocket has landed is required for the system to + flush the eeprom log and re-enable the RDF beacon. This patch changes + the landed state entry requirements for the accelerometer to require + only that the accelerometer stay within a quarter of a g (down from + 1/10g) and changes the testing interval from 20 seconds to 5 + seconds. + + The requirement that the barometric altitude be within 1000m of the + launch altitude and that the barometer change by no more than 0.05kPa + are unchanged. + + Signed-off-by: Keith Packard + +commit 03092d1a72a9651711e22c58dca6d6aba5705c5e +Author: Keith Packard +Date: Sat Nov 14 16:35:12 2009 -0800 + + ao-postflight: fix sloppy gps sat data realloc code (was crashing). + + Realloc'ing the wrong data, and failing to set the realloc'ed size was + causing ao-postflight to crash while reading long logs. + + Signed-off-by: Keith Packard + +commit adf656192441eb7f44792955c86e469145477e29 +Author: Keith Packard +Date: Thu Nov 5 22:11:59 2009 -0800 + + Return radio to telemetry settings when packet system closed. + + To receive telemetry after disabling the packet system, the radio must + be reconfigured for telemetry mode. + + Signed-off-by: Keith Packard + +commit 83afdbdc154fe013bfe35ce5ecf1d61570b04ed6 +Author: Keith Packard +Date: Thu Nov 5 21:45:00 2009 -0800 + + Add reboot command. + + This resets the processor using the watchdog timer. + + Signed-off-by: Keith Packard + +commit 0358988ac0ee25a564d48af79b1c3fb0c0fe0a88 +Author: Keith Packard +Date: Thu Nov 5 21:44:31 2009 -0800 + + Add Watchdog Timer Control register definitions + + Signed-off-by: Keith Packard + +commit 4114210e0b813f4af99d0cb7755ad2ac2c4b120e +Author: Keith Packard +Date: Thu Nov 5 21:43:21 2009 -0800 + + Move ao_match_word from ao_ignite.c to ao_cmd.c + + This is a generally useful command line utility. + + Signed-off-by: Keith Packard + +commit 5a79a04ddb0b3ee64de34e366f71a0f6db509c01 +Author: Keith Packard +Date: Wed Nov 4 21:59:51 2009 -0800 + + Stop recording in ao-dumplog after receiving an invalid block + + If no samples in a block are valid, assume the flight log is over. + + Signed-off-by: Keith Packard + +commit 843ee489aac34ad6d81f55f1c85fb9eecc42d86b +Author: Keith Packard +Date: Wed Nov 4 21:59:12 2009 -0800 + + Flush pending input when switching to remote packet mode + + Any pending input would just confuse the application, so pull it off + the link and dump it. + + Signed-off-by: Keith Packard + +commit 036400a2db303f3db3be7cc0426f88359c6bd2b1 +Author: Keith Packard +Date: Wed Nov 4 21:42:51 2009 -0800 + + Explicitly use USB I/O routines in packet code + + Using the implicit stdio functions (putchar/getchar/flush) would + result in essentially random redirection of each, depending on whether + the packet code had characters available when getchar was called. This + would cause lockups in putchar. + + Signed-off-by: Keith Packard + +commit 3ece984f4d72b4f720a5efdfaad7cff77a93d676 +Author: Keith Packard +Date: Wed Nov 4 21:32:07 2009 -0800 + + In USB pollchar, wait for packet before re-checking USB out len + + This probably wouldn't actually cause a problem, but it seems more + reliable to wait for a packet interrupt before re-reading the packet + OUT len register. This could avoid spinning while waiting for a USB + packet, which seems like a good thing. + + Signed-off-by: Keith Packard + +commit bc62bb254085cc705203b57260c04ac5e14c6611 +Author: Keith Packard +Date: Wed Nov 4 21:29:37 2009 -0800 + + In packet master, move USB flush from packet thread to echo thread + + This keeps the packet thread from blocking on USB and also makes the + flush happen after every packet (slightly more USB traffic, but + packets are slow anyway). + + Signed-off-by: Keith Packard + +commit 27ebaf8e13aed06bb1ea6e770f767495a02be6c5 +Author: Keith Packard +Date: Tue Nov 3 01:27:37 2009 -0800 + + Add ability to dump eeprom data over radio link. + + This adds a '-R' option to ao-dumplog to redirect the connection + through a USB attached TeleDongle over the radio link to a remote + TeleMetrum device. + + Signed-off-by: Keith Packard + +commit 1de322b960005c9a16051afa1881fadb00f4bcd6 +Author: Keith Packard +Date: Tue Nov 3 00:40:38 2009 -0800 + + Pass accel calibration over telemetry stream. Telemetry data format change. + + This allows the ground station to convert the accelerometer sensor + values into acceleration and speed data. This requires a new telemetry + data structure, and so TeleMetrum and TeleDongle units must be updated + synchronously. ao-view will parse either telemetry stream, and the + serial format from TeleDongle now has a version number to allow for + future changes. + + Signed-off-by: Keith Packard + +commit b529e5e8998702986909111a457f3ce9932e1ccf +Author: Keith Packard +Date: Mon Nov 2 23:48:29 2009 -0800 + + ao_flight_test was using accel value for pressure too + +commit f57bea012d4fbca097df0d98fcd30eb4abd9701a +Author: Keith Packard +Date: Mon Nov 2 21:47:41 2009 -0800 + + Reformat ADC values to show all 16 bits + +commit 79718e798e96567f0ba11c61f187e432fdcf95ee +Author: Keith Packard +Date: Mon Nov 2 21:48:16 2009 -0800 + + Remove "f" command + +commit a4137263b69864c524d39c6ff88a0225fd06e79b +Author: Keith Packard +Date: Mon Nov 2 21:47:15 2009 -0800 + + Remove "d" command + +commit 47f510464907d2b9488109c96ade87a41d878842 +Author: Keith Packard +Date: Mon Nov 2 21:46:39 2009 -0800 + + Remove "l" command as ao-dumplong no longer uses it + +commit 144db05f6b286a0450d486f69ce192632a2c0656 +Author: Keith Packard +Date: Mon Nov 2 21:38:18 2009 -0800 + + Add two-point accelerometer calibration. + + Calibration now uses two values, one upside right and the other upside + down instead of a single horizontal value. This allows the use of + other accelerometers and compensates for variations in the divider + circuit to provide more accurate data. + +commit 17611788aadc9460287145a340a7c18bf63766aa +Author: Bdale Garbee +Date: Mon Nov 2 16:54:06 2009 -0700 + + update changelogs for Debian build + commit 7db9d86178ecfd58cc1c17ac9fcbdcfd2f13aaec Merge: b219801 f9de200 Author: Keith Packard diff --git a/debian/changelog b/debian/changelog index d15ee3c7..d76c0026 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,36 @@ +altos (0.6+27+gb0d7e3f) unstable; urgency=low + + [ Keith Packard ] + * Add two-point accelerometer calibration. + * Remove "l" command as ao-dumplong no longer uses it + * Remove "d" command + * Remove "f" command + * Reformat ADC values to show all 16 bits + * ao_flight_test was using accel value for pressure too + * Pass accel calibration over telemetry stream. Telemetry data format + change. + * Add ability to dump eeprom data over radio link. + * In packet master, move USB flush from packet thread to echo thread + * In USB pollchar, wait for packet before re-checking USB out len + * Explicitly use USB I/O routines in packet code + * Flush pending input when switching to remote packet mode + * Stop recording in ao-dumplog after receiving an invalid block + * Move ao_match_word from ao_ignite.c to ao_cmd.c + * Add Watchdog Timer Control register definitions + * Add reboot command. + * Return radio to telemetry settings when packet system closed. + * ao-postflight: fix sloppy gps sat data realloc code (was crashing). + * Loosen tolerances for main->landed transition + * Provide a dummy 'uninstall' target in the src directory. + * Share telemetry parsing code in cc library. + * Enable telemetry receive in ao_view + * Switch order of serial/flight in ao-postflight summary + * Add flight number to telemetry stream. + * Add date to GPS data, captured from GPRMC packet. + * Stop using SiRF state info. + + -- Bdale Garbee Fri, 20 Nov 2009 11:43:56 -0700 + altos (0.6) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From b75aa1c825b84bd7fa1578320fbc7e904c373a7d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 19 Nov 2009 21:43:13 -0700 Subject: fix typo in comment --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_config.c b/src/ao_config.c index 85fcff8c..e82aa015 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -54,7 +54,7 @@ _ao_config_get(void) ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for mior version 1 */ + /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; /* Fixupes for minor version 2 */ -- cgit v1.2.3 From 6894541e0ee144bfc689cc02d4ed333711d3b500 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Nov 2009 11:55:28 -0800 Subject: Reduce igniter firing time from 500ms to 50ms. Given that the system will brown-out with the longer pulse, it doesn't make sense to even try; failure at 50ms probably indicates a short. Signed-off-by: Keith Packard --- src/ao_ignite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 981cf0ce..4093b6a7 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -26,7 +26,7 @@ /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 #define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(500) +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) struct ao_ignition { -- cgit v1.2.3 From 8065b8146a31438e66f83c13b99281ec47439a73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Nov 2009 11:56:48 -0800 Subject: Add GPS date/time output to ao-postflight. GPS date/time information was already being stored in the log, it just wasn't getting displayed by ao-postflight. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 12 ++++++++++++ ao-tools/lib/cc-logfile.c | 16 ++++++++++++++++ ao-tools/lib/cc.h | 5 +++++ 3 files changed, 33 insertions(+) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index c12939aa..a19b7ebb 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -208,6 +208,18 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, "Serial: %9d\n" "Flight: %9d\n", f->serial, f->flight); + if (f->year) { + fprintf(summary_file, + "Date: %04d-%02d-%02d\n", + f->year, f->month, f->day); + } + if (f->gps.num) { + fprintf(summary_file, + "Time: %2d:%02d:%02d\n", + f->gps.data[0].hour, + f->gps.data[0].minute, + f->gps.data[0].second); + } boost_start = f->accel.data[0].time; boost_stop = f->accel.data[f->accel.num-1].time; for (i = 0; i < f->state.num; i++) { diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 9d086c82..b0fff9f8 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -136,6 +136,7 @@ gpsdata_free(struct cc_gpsdata *data) #define AO_LOG_GPS_LON 'W' #define AO_LOG_GPS_ALT 'H' #define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' #define AO_LOG_POS_NONE (~0UL) @@ -195,6 +196,10 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * * any stale data before adding this record */ gps.time = tick; + gps.hour = (a & 0xff); + gps.minute = (a >> 8) & 0xff; + gps.second = (b & 0xff); + gps.flags = (b >> 8) & 0xff; gps_valid = GPS_TIME; break; case AO_LOG_GPS_LAT: @@ -215,6 +220,11 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * sat.c_n = (b >> 8) & 0xff; gpssat_add(&f->gps, &sat); break; + case AO_LOG_GPS_DATE: + f->year = 2000 + (a & 0xff); + f->month = (a >> 8) & 0xff; + f->day = (b & 0xff); + break; default: return 0; } @@ -266,10 +276,16 @@ read_telem(const char *line, struct cc_flightraw *f) timedata_add(&f->main, telem.tick, telem.main); timedata_add(&f->state, telem.tick, state_name_to_state(telem.state)); if (telem.gps.gps_locked) { + f->year = telem.gps.gps_time.year; + f->month = telem.gps.gps_time.month; + f->day = telem.gps.gps_time.day; gps.time = telem.tick; gps.lat = telem.gps.lat; gps.lon = telem.gps.lon; gps.alt = telem.gps.alt; + gps.hour = telem.gps.gps_time.hour; + gps.minute = telem.gps.gps_time.minute; + gps.second = telem.gps.gps_time.second; gpsdata_add(&f->gps, &gps); } return 1; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 0e8ced8a..bdeeaaf5 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -86,6 +86,10 @@ struct cc_timedata { struct cc_gpselt { double time; + int hour; + int minute; + int second; + int flags; double lat; double lon; double alt; @@ -149,6 +153,7 @@ struct cc_flightraw { int serial; double ground_accel; double ground_pres; + int year, month, day; struct cc_timedata accel; struct cc_timedata pres; struct cc_timedata temp; -- cgit v1.2.3 From 87e6f3e5c1688503ab8595912d8d6eb7139830b7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Nov 2009 12:16:37 -0800 Subject: Eliminate SiRF state values from ao-view. With Skytraq not having any visible GPS state information, just remove this from the display. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 15 +++------------ ao-tools/lib/cc.h | 1 - 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index 21cea99a..838899a7 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -342,23 +342,14 @@ aoview_state_notify(struct cc_telem *data) } if (state->gps.gps_connected) { int nsat_vis = 0; - int nsat_locked = 0; int c; - for (c = 0; c < state->gps_tracking.channels; c++) { - if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf) - nsat_locked++; - } aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels); - aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked); for (c = 0; c < state->gps_tracking.channels; c++) { - aoview_table_add_row(2, "Satellite id,state,C/N0", - "%3d,%02x,%2d%s", + aoview_table_add_row(2, "Satellite id,C/N0", + "%3d,%2d", state->gps_tracking.sats[c].svid, - state->gps_tracking.sats[c].state, - state->gps_tracking.sats[c].c_n0, - (state->gps_tracking.sats[c].state & 0xff) == 0xbf ? - " LOCKED" : ""); + state->gps_tracking.sats[c].c_n0); } } aoview_table_finish(); diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index bdeeaaf5..46b16a8e 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -233,7 +233,6 @@ struct cc_gps { struct cc_gps_sat { int svid; - int state; int c_n0; }; -- cgit v1.2.3 From 8f036ee7cd30ce3ed2e5cc8501914a4c19b73875 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 20 Nov 2009 13:19:02 -0700 Subject: update changelogs for Debian build --- ChangeLog | 45 +++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 12 ++++++++++++ 2 files changed, 57 insertions(+) diff --git a/ChangeLog b/ChangeLog index 01451761..cb757385 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,48 @@ +commit 87e6f3e5c1688503ab8595912d8d6eb7139830b7 +Author: Keith Packard +Date: Fri Nov 20 12:16:37 2009 -0800 + + Eliminate SiRF state values from ao-view. + + With Skytraq not having any visible GPS state information, just + remove this from the display. + + Signed-off-by: Keith Packard + +commit 8065b8146a31438e66f83c13b99281ec47439a73 +Author: Keith Packard +Date: Fri Nov 20 11:56:48 2009 -0800 + + Add GPS date/time output to ao-postflight. + + GPS date/time information was already being stored in the log, it just + wasn't getting displayed by ao-postflight. + + Signed-off-by: Keith Packard + +commit 6894541e0ee144bfc689cc02d4ed333711d3b500 +Author: Keith Packard +Date: Fri Nov 20 11:55:28 2009 -0800 + + Reduce igniter firing time from 500ms to 50ms. + + Given that the system will brown-out with the longer pulse, it doesn't + make sense to even try; failure at 50ms probably indicates a short. + + Signed-off-by: Keith Packard + +commit b75aa1c825b84bd7fa1578320fbc7e904c373a7d +Author: Bdale Garbee +Date: Thu Nov 19 21:43:13 2009 -0700 + + fix typo in comment + +commit c2f661b75ec035f6a3f700962290ef297f9ab0af +Author: Bdale Garbee +Date: Fri Nov 20 11:44:06 2009 -0700 + + update changelogs for Debian build + commit b0d7e3f9c9322542e9b649bb6ad7f7e5bb99dffa Author: Keith Packard Date: Sun Nov 15 16:20:18 2009 -0800 diff --git a/debian/changelog b/debian/changelog index d76c0026..2c54a66e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +altos (0.6+32+g87e6f3e) unstable; urgency=low + + [ Bdale Garbee ] + * fix typo in comment + + [ Keith Packard ] + * Reduce igniter firing time from 500ms to 50ms. + * Add GPS date/time output to ao-postflight. + * Eliminate SiRF state values from ao-view. + + -- Bdale Garbee Fri, 20 Nov 2009 13:18:06 -0700 + altos (0.6+27+gb0d7e3f) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 80b23f3044a654d61212891a61fadb8a3a4e5572 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 18:57:45 -0800 Subject: Decode HDOP data from skytraq GPS The hdop data was getting dropped on the floor, but is rather useful when deciding if the GPS position is crazy or not. This reports HDOP * 5 (giving a useful range of .2-50). Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index bf192f28..ef581349 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -271,7 +271,15 @@ ao_gps(void) __reentrant ao_gps_next.flags |= i; ao_gps_lexchar(); - ao_gps_skip_field(); /* Horizontal dilution */ + ao_gps_next.hdop = ao_gps_decimal(0xff); + if (ao_gps_next.hdop <= 50) { + ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + if (ao_gps_char == '.') + ao_gps_next.hdop = (ao_gps_next.hdop + + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + ao_gps_next.hdop = 255; + ao_gps_skip_field(); ao_gps_next.altitude = ao_gps_decimal(0xff); ao_gps_skip_field(); /* skip any fractional portion */ -- cgit v1.2.3 From 1a3b4c02a01187f8b7b9a9c97712476d0007ab35 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 19:52:26 -0800 Subject: Document ao-postflight --gps and --kml options. These were missing from the man page, but included in the --help output. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.1 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ao-tools/ao-postflight/ao-postflight.1 b/ao-tools/ao-postflight/ao-postflight.1 index eca4bb34..7bafb6e1 100644 --- a/ao-tools/ao-postflight/ao-postflight.1 +++ b/ao-tools/ao-postflight/ao-postflight.1 @@ -29,6 +29,10 @@ ao-postflight \- Analyse a flight log (either telemetry or eeprom) [\--raw=] [\-p ] [\--plot=] +[\-g Date: Sat, 21 Nov 2009 20:35:22 -0800 Subject: Make ao-postflight create filenames using input filenames. Instead of requiring the user to provide names for the various output options, just create them from the input name by replacing the extension. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 139 +++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 49 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index a19b7ebb..7cedaa5b 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -392,9 +392,11 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, j++; } nsat = 0; - for (k = 0; k < f->gps.sats[j].nsat; k++) - if (f->gps.sats[j].sat[k].svid != 0) - nsat++; + if (j < f->gps.numsats) { + for (k = 0; k < f->gps.sats[j].nsat; k++) + if (f->gps.sats[j].sat[k].svid != 0) + nsat++; + } fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", f->gps.data[i].lon, @@ -443,12 +445,12 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, } static const struct option options[] = { - { .name = "summary", .has_arg = 1, .val = 's' }, - { .name = "detail", .has_arg = 1, .val = 'd' }, - { .name = "plot", .has_arg = 1, .val = 'p' }, - { .name = "raw", .has_arg = 1, .val = 'r' }, - { .name = "gps", .has_arg = 1, .val = 'g' }, - { .name = "kml", .has_arg = 1, .val = 'k' }, + { .name = "summary", .has_arg = 2, .val = 's' }, + { .name = "detail", .has_arg = 2, .val = 'd' }, + { .name = "plot", .has_arg = 2, .val = 'p' }, + { .name = "raw", .has_arg = 2, .val = 'r' }, + { .name = "gps", .has_arg = 2, .val = 'g' }, + { .name = "kml", .has_arg = 2, .val = 'k' }, { 0, 0, 0, 0}, }; @@ -465,6 +467,46 @@ static void usage(char *program) exit(1); } +char * +replace_extension(char *file, char *extension) +{ + char *slash; + char *dot; + char *new; + int newlen; + + slash = strrchr(file, '/'); + dot = strrchr(file, '.'); + if (!dot || (slash && dot < slash)) + dot = file + strlen(file); + newlen = (dot - file) + strlen (extension) + 1; + new = malloc (newlen); + strncpy (new, file, dot - file); + new[dot-file] = '\0'; + strcat (new, extension); + return new; +} + +FILE * +open_output(char *outname, char *inname, char *extension) +{ + char *o; + FILE *out; + + if (outname) + o = outname; + else + o = replace_extension(inname, extension); + out = fopen(o, "w"); + if (!out) { + perror (o); + exit(1); + } + if (o != outname) + free(o); + return out; +} + int main (int argc, char **argv) { @@ -486,72 +528,46 @@ main (int argc, char **argv) char *plot_name = NULL; char *gps_name = NULL; char *kml_name = NULL; + int has_summary = 0; + int has_detail = 0; + int has_plot = 0; + int has_raw = 0; + int has_gps = 0; + int has_kml = 0; while ((c = getopt_long(argc, argv, "s:d:p:r:g:k:", options, NULL)) != -1) { switch (c) { case 's': summary_name = optarg; + has_summary = 1; break; case 'd': detail_name = optarg; + has_detail = 1; break; case 'p': plot_name = optarg; + has_plot = 1; break; case 'r': raw_name = optarg; + has_raw = 1; break; case 'g': gps_name = optarg; + has_gps = 1; break; case 'k': kml_name = optarg; + has_kml = 1; break; default: usage(argv[0]); break; } } - summary_file = stdout; - if (summary_name) { - summary_file = fopen(summary_name, "w"); - if (!summary_file) { - perror (summary_name); - exit(1); - } - } - if (detail_name) { - if (summary_name && !strcmp (summary_name, detail_name)) - detail_file = summary_file; - else { - detail_file = fopen(detail_name, "w"); - if (!detail_file) { - perror(detail_name); - exit(1); - } - } - } - if (raw_name) { - raw_file = fopen (raw_name, "w"); - if (!raw_file) { - perror(raw_name); - exit(1); - } - } - if (gps_name) { - gps_file = fopen(gps_name, "w"); - if (!gps_file) { - perror(gps_name); - exit(1); - } - } - if (kml_name) { - kml_file = fopen(kml_name, "w"); - if (!kml_file) { - perror(kml_name); - exit(1); - } - } + if (!has_summary) + summary_file = stdout; for (i = optind; i < argc; i++) { file = fopen(argv[i], "r"); if (!file) { @@ -559,6 +575,16 @@ main (int argc, char **argv) ret++; continue; } + if (has_summary && !summary_file) + summary_file = open_output(summary_name, argv[i], ".summary"); + if (has_detail && !detail_file) + detail_file = open_output(detail_name, argv[i], ".detail"); + if (has_raw && !raw_file) + raw_file = open_output(raw_name, argv[i], ".raw"); + if (has_gps && !gps_file) + gps_file = open_output(gps_name, argv[i], ".gps"); + if (has_kml && !kml_file) + kml_file = open_output(gps_name, argv[i], ".kml"); s = strstr(argv[i], "-serial-"); if (s) serial = atoi(s + 8); @@ -574,6 +600,21 @@ main (int argc, char **argv) raw->serial = serial; analyse_flight(raw, summary_file, detail_file, raw_file, plot_name, gps_file, kml_file); cc_flightraw_free(raw); + if (has_summary && !summary_name) { + fclose(summary_file); summary_file = NULL; + } + if (has_detail && !detail_name) { + fclose(detail_file); detail_file = NULL; + } + if (has_summary && !raw_name) { + fclose(raw_file); raw_file = NULL; + } + if (has_gps && !gps_name) { + fclose(gps_file); gps_file = NULL; + } + if (has_kml && !kml_name) { + fclose(kml_file); kml_file = NULL; + } } return ret; } -- cgit v1.2.3 From 199f0cecae22645140185238682b9e1aba0e5715 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 20:36:20 -0800 Subject: Make TD print 0000-00-00 for invalid dates. This 'shouldn't' happen, but in case it does, I want to know about it. Signed-off-by: Keith Packard --- src/ao_gps_print.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index b8b73cd2..11213174 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -53,10 +53,13 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant ao_gps_split(gps_data->latitude, &lat); ao_gps_split(gps_data->longitude, &lon); - printf(" 20%02d-%02d-%02d", - gps_data->year, - gps_data->month, - gps_data->day); + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(" 20%02d-%02d-%02d", + gps_data->year, + gps_data->month, + gps_data->day); + else + printf (" 0000-00-00"); printf(" %2d:%02d:%02d", gps_data->hour, gps_data->minute, -- cgit v1.2.3 From 1e7fb61700f1f6f2ed5fdbc4380d7187b0cd187b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 21:09:03 -0800 Subject: Fix --plot arg handling. Add -all option. The --plot file name handing is special as the library wants a filename instead of a stdio file pointer. Add a --all option that just creates all of the possible outputs. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 7cedaa5b..ed91be15 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -451,12 +451,14 @@ static const struct option options[] = { { .name = "raw", .has_arg = 2, .val = 'r' }, { .name = "gps", .has_arg = 2, .val = 'g' }, { .name = "kml", .has_arg = 2, .val = 'k' }, + { .name = "all", .has_arg = 0, .val = 'a' }, { 0, 0, 0, 0}, }; static void usage(char *program) { fprintf(stderr, "usage: %s\n" + "\t[--all] [-a]\n" "\t[--summary=] [-s ]\n" "\t[--detail=]\n" "\t[--raw= -r serial) raw->serial = serial; - analyse_flight(raw, summary_file, detail_file, raw_file, plot_name, gps_file, kml_file); + analyse_flight(raw, summary_file, detail_file, raw_file, this_plot_name, gps_file, kml_file); cc_flightraw_free(raw); if (has_summary && !summary_name) { fclose(summary_file); summary_file = NULL; @@ -606,7 +618,10 @@ main (int argc, char **argv) if (has_detail && !detail_name) { fclose(detail_file); detail_file = NULL; } - if (has_summary && !raw_name) { + if (this_plot_name && this_plot_name != plot_name) { + free (this_plot_name); this_plot_name = NULL; + } + if (has_raw && !raw_name) { fclose(raw_file); raw_file = NULL; } if (has_gps && !gps_name) { -- cgit v1.2.3 From 2d77c18b15834046b7b79d49d87211828f2409e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 21:10:09 -0800 Subject: Convert telemetry file GPS satellite information in cc_log_read The satellite info wasn't being correctly converted from telemetry files to the data log structure, so ao-postflight was not seeing it. Signed-off-by: Keith Packard --- ao-tools/lib/cc-logfile.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index b0fff9f8..842e5c7c 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -263,6 +263,9 @@ read_telem(const char *line, struct cc_flightraw *f) { struct cc_telem telem; struct cc_gpselt gps; + struct cc_gpssat sat; + int s; + if (!cc_telem_parse(line, &telem)) return 0; f->ground_accel = telem.ground_accel; @@ -288,6 +291,12 @@ read_telem(const char *line, struct cc_flightraw *f) gps.second = telem.gps.gps_time.second; gpsdata_add(&f->gps, &gps); } + for (s = 0; s < telem.gps_tracking.channels; s++) { + sat.time = telem.tick; + sat.svid = telem.gps_tracking.sats[s].svid; + sat.c_n = telem.gps_tracking.sats[s].c_n0; + gpssat_add(&f->gps, &sat); + } return 1; } -- cgit v1.2.3 From b84b634d9ae8ce6ab1c02833a3ed8514404e1ca3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 22:11:45 -0800 Subject: Don't crash if --plot isn't passed on ao-postflight command line Crashing is not nice. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index ed91be15..caa7fb74 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -536,7 +536,7 @@ main (int argc, char **argv) int has_raw = 0; int has_gps = 0; int has_kml = 0; - char *this_plot_name; + char *this_plot_name = NULL;; while ((c = getopt_long(argc, argv, "s:d:p:r:g:k:a", options, NULL)) != -1) { switch (c) { -- cgit v1.2.3 From a9ada1b538af3308e1b22bd024d9204521184173 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 22:12:21 -0800 Subject: ao-postflight: compute barometric alt for each GPS position Print that to the --gps file, and use that in the --kml file for the altitude. Gives a very different picture of our flight tracks, presumably far more accurate (at least in altitude). Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 101 +++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 43 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index caa7fb74..51bcd6e3 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -351,10 +351,21 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, time, pres, accel); } } - if (gps_file) { - int j = 0; - fprintf(gps_file, "%9s %12s %12s %12s\n", - "time", "lat", "lon", "alt"); + if (gps_file || kml_file) { + int j = 0, baro_pos; + double baro_offset; + double baro = 0.0; + + if (gps_file) + fprintf(gps_file, "%9s %12s %12s %9s %8s %5s\n", + "time", "lat", "lon", "alt", "baro", "nsat"); + if (kml_file) + fprintf(kml_file, "%s", kml_header); + if (f->gps.num) + baro_offset = f->gps.data[0].alt; + else + baro_offset = 0; + baro_pos = 0; for (i = 0; i < f->gps.num; i++) { int nsat = 0; int k; @@ -364,52 +375,56 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, break; j++; } - fprintf(gps_file, "%12.7f %12.7f %12.7f %12.7f", - (f->gps.data[i].time - boost_start) / 100.0, - f->gps.data[i].lat, - f->gps.data[i].lon, - f->gps.data[i].alt); + if (cooked) { + while (baro_pos < cooked->pres_pos.num) { + double baro_time = cooked->accel_accel.start + baro_pos * cooked->accel_accel.step; + if (baro_time >= f->gps.data[i].time) + break; + baro_pos++; + } + if (baro_pos < cooked->pres_pos.num) + baro = cooked->pres_pos.data[baro_pos]; + } + if (gps_file) + fprintf(gps_file, "%12.7f %12.7f %12.7f %7.1f %7.1f", + (f->gps.data[i].time - boost_start) / 100.0, + f->gps.data[i].lat, + f->gps.data[i].lon, + f->gps.data[i].alt, + baro + baro_offset); + if (kml_file) { + fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", + f->gps.data[i].lon, + f->gps.data[i].lat, + baro + baro_offset, + f->gps.data[i].alt, + (f->gps.data[i].time - boost_start) / 100.0, + nsat); + if (i < f->gps.num - 1) + fprintf(kml_file, ",\n"); + else + fprintf(kml_file, "\n"); + } + nsat = 0; for (k = 0; k < f->gps.sats[j].nsat; k++) { - fprintf (gps_file, " %12.7f", (double) f->gps.sats[j].sat[k].c_n); if (f->gps.sats[j].sat[k].svid != 0) nsat++; } - fprintf(gps_file, " %d\n", nsat); - } - } - if (kml_file) { - int j = 0; - - fprintf(kml_file, "%s", kml_header); - for (i = 0; i < f->gps.num; i++) { - int nsat = 0; - int k; - while (j < f->gps.numsats - 1) { - if (f->gps.sats[j].sat[0].time <= f->gps.data[i].time && - f->gps.data[i].time < f->gps.sats[j+1].sat[0].time) - break; - j++; + if (gps_file) { + fprintf(gps_file, " %4d", nsat); + for (k = 0; k < f->gps.sats[j].nsat; k++) { + if (f->gps.sats[j].sat[k].svid != 0) { + fprintf (gps_file, " %3d(%4.1f)", + f->gps.sats[j].sat[k].svid, + (double) f->gps.sats[j].sat[k].c_n); + } + } + fprintf(gps_file, "\n"); } - nsat = 0; - if (j < f->gps.numsats) { - for (k = 0; k < f->gps.sats[j].nsat; k++) - if (f->gps.sats[j].sat[k].svid != 0) - nsat++; - } - - fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", - f->gps.data[i].lon, - f->gps.data[i].lat, - f->gps.data[i].alt, - (f->gps.data[i].time - boost_start) / 100.0, - nsat); - if (i < f->gps.num - 1) - fprintf(kml_file, ",\n"); - else - fprintf(kml_file, "\n"); } - fprintf(kml_file, "%s", kml_footer); + if (kml_file) + fprintf(kml_file, "%s", kml_footer); } if (cooked && plot_name) { struct cc_perioddata *speed; -- cgit v1.2.3 From 06cebd1026dc1bd6ee51526fa2d02905df3b3b37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Nov 2009 00:52:58 -0800 Subject: ao-postflight: don't try to use missing gps sat data Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 51bcd6e3..48752d07 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -407,20 +407,22 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, } nsat = 0; - for (k = 0; k < f->gps.sats[j].nsat; k++) { - if (f->gps.sats[j].sat[k].svid != 0) - nsat++; - } - if (gps_file) { - fprintf(gps_file, " %4d", nsat); + if (f->gps.sats) { for (k = 0; k < f->gps.sats[j].nsat; k++) { - if (f->gps.sats[j].sat[k].svid != 0) { - fprintf (gps_file, " %3d(%4.1f)", - f->gps.sats[j].sat[k].svid, - (double) f->gps.sats[j].sat[k].c_n); + if (f->gps.sats[j].sat[k].svid != 0) + nsat++; + } + if (gps_file) { + fprintf(gps_file, " %4d", nsat); + for (k = 0; k < f->gps.sats[j].nsat; k++) { + if (f->gps.sats[j].sat[k].svid != 0) { + fprintf (gps_file, " %3d(%4.1f)", + f->gps.sats[j].sat[k].svid, + (double) f->gps.sats[j].sat[k].c_n); + } } + fprintf(gps_file, "\n"); } - fprintf(gps_file, "\n"); } } if (kml_file) -- cgit v1.2.3 From d6ba07e885bdc62ba64719c9d8cc42fcecbcb09d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Nov 2009 01:10:44 -0800 Subject: Automatically extract flight number for eeprom and telem filenames. Extract flight number from either telemetry or eeprom files and use that in the resulting filenames. To ensure that files remain unique, add a new field, -seq-%03d. This is appended only when the sequence number is non-zero as it shouldn't occur in normal usage. This also eliminates some duplicate filename creation code in the library and aoview sources. Signed-off-by: Keith Packard --- ao-tools/ao-dumplog/ao-dumplog.c | 32 +++++++++++++++-------- ao-tools/ao-view/aoview_eeprom.c | 2 ++ ao-tools/ao-view/aoview_file.c | 53 +++++++++++++++++++-------------------- ao-tools/ao-view/aoview_log.c | 12 +++++++++ ao-tools/ao-view/aoview_monitor.c | 1 + ao-tools/lib/cc-log.c | 23 +++++++++++------ ao-tools/lib/cc.h | 2 +- 7 files changed, 78 insertions(+), 47 deletions(-) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index b3a0a25a..440a02b5 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "cc-usb.h" #include "cc.h" @@ -62,6 +63,7 @@ static const char *state_names[] = { "invalid" }; + int main (int argc, char **argv) { @@ -72,7 +74,8 @@ main (int argc, char **argv) char line[8192]; FILE *out; char *filename; - int serial_number; + int serial_number = 0; + int flight = 0; char cmd; int tick, a, b; int block; @@ -84,6 +87,7 @@ main (int argc, char **argv) int remote = 0; int any_valid; int invalid; + char serial_line[8192]; while ((c = getopt_long(argc, argv, "T:D:R", options, NULL)) != -1) { switch (c) { @@ -121,24 +125,17 @@ main (int argc, char **argv) out = NULL; for (;;) { cc_usb_getline(cc, line, sizeof (line)); - if (sscanf(line, "serial-number %u", &serial_number) == 1) { - filename = cc_make_filename(serial_number, "eeprom"); - out = fopen (filename, "w"); - if (!out) { - perror(filename); - } - fprintf (out, "%s\n", line); - } + if (sscanf(line, "serial-number %u", &serial_number) == 1) + strcpy(serial_line, line); if (!strncmp(line, "software-version", 16)) break; } - if (!out) { + if (!serial_number) { fprintf(stderr, "no serial number found\n"); cc_usb_close(cc); exit(1); } printf ("Serial number: %d\n", serial_number); - printf ("File name: %s\n", filename); done = 0; column = 0; for (block = 0; !done && block < 511; block++) { @@ -170,6 +167,19 @@ main (int argc, char **argv) tick = data[2] + (data[3] << 8); a = data[4] + (data[5] << 8); b = data[6] + (data[7] << 8); + if (cmd == 'F') { + flight = b; + filename = cc_make_filename(serial_number, flight, "eeprom"); + printf ("Flight: %d\n", flight); + printf ("File name: %s\n", filename); + out = fopen (filename, "w"); + if (!out) { + perror(filename); + exit(1); + } + fprintf(out, "%s\n", serial_line); + } + if (cmd == 'S' && a <= 8) { if (column) putchar('\n'); printf("%s\n", state_names[a]); diff --git a/ao-tools/ao-view/aoview_eeprom.c b/ao-tools/ao-view/aoview_eeprom.c index 34e2deed..447b83a4 100644 --- a/ao-tools/ao-view/aoview_eeprom.c +++ b/ao-tools/ao-view/aoview_eeprom.c @@ -66,6 +66,8 @@ aoview_eeprom_parse(struct aoview_serial *serial, if (sscanf(line, "serial-number %u", &serial_number) == 1) { aoview_file_set_serial(eeprom_file, serial_number); } else if (sscanf(line, "%c %x %x %x", &cmd, &tick, &a, &b) == 4) { + if (cmd == 'F') + aoview_file_set_flight(eeprom_file, b); aoview_file_printf(eeprom_file, "%s\n", line); if (cmd == 'S' && a == 8) { aoview_eeprom_done(serial); diff --git a/ao-tools/ao-view/aoview_file.c b/ao-tools/ao-view/aoview_file.c index 5288c2f7..292887a0 100644 --- a/ao-tools/ao-view/aoview_file.c +++ b/ao-tools/ao-view/aoview_file.c @@ -28,6 +28,7 @@ struct aoview_file { char *name; int failed; int serial; + int flight; int sequence; }; @@ -94,6 +95,7 @@ gboolean aoview_file_start(struct aoview_file *file) { char base[50]; + char seq[20]; struct tm tm; time_t now; char *full; @@ -105,34 +107,17 @@ aoview_file_start(struct aoview_file *file) if (file->failed) return FALSE; - now = time(NULL); - (void) localtime_r(&now, &tm); - aoview_mkdir(aoview_file_dir); - for (;;) { - snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - file->serial, - file->sequence, - file->ext); - full = aoview_fullname(aoview_file_dir, base); - r = access(full, F_OK); - if (r < 0) { - file->file = fopen(full, "w"); - if (!file->file) { - aoview_file_open_failed(full); - free(full); - file->failed = 1; - return FALSE; - } else { - setlinebuf(file->file); - file->name = full; - return TRUE; - } - } + full = cc_make_filename(file->serial, file->flight, file->ext); + file->file = fopen(full, "w"); + if (!file->file) { + aoview_file_open_failed(full); free(full); - file->sequence++; + file->failed = 1; + return FALSE; + } else { + setlinebuf(file->file); + file->name = full; + return TRUE; } } @@ -195,6 +180,20 @@ aoview_file_get_serial(struct aoview_file *file) return file->serial; } +void +aoview_file_set_flight(struct aoview_file *file, int flight) +{ + if (flight != file->flight) + aoview_file_finish(file); + file->flight = flight; +} + +int +aoview_file_get_flight(struct aoview_file *file) +{ + return file->flight; +} + void aoview_file_init(GladeXML *xml) { diff --git a/ao-tools/ao-view/aoview_log.c b/ao-tools/ao-view/aoview_log.c index 1b89c28c..2880ecb1 100644 --- a/ao-tools/ao-view/aoview_log.c +++ b/ao-tools/ao-view/aoview_log.c @@ -38,6 +38,18 @@ aoview_log_get_serial(void) return aoview_file_get_serial(aoview_log); } +void +aoview_log_set_flight(int flight) +{ + aoview_file_set_flight(aoview_log, flight); +} + +int +aoview_log_get_flight(void) +{ + return aoview_file_get_flight(aoview_log); +} + void aoview_log_printf(char *format, ...) { diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 3d235e44..4d7e7a9f 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -68,6 +68,7 @@ aoview_monitor_callback(gpointer user_data, if (monitor_pos) { if (aoview_monitor_parse(monitor_line)) { aoview_log_set_serial(aostate.data.serial); + aoview_log_set_flight(aostate.data.flight); if (aoview_log_get_serial()) aoview_log_printf ("%s\n", monitor_line); } diff --git a/ao-tools/lib/cc-log.c b/ao-tools/lib/cc-log.c index dd8177f4..ed51f87e 100644 --- a/ao-tools/lib/cc-log.c +++ b/ao-tools/lib/cc-log.c @@ -82,9 +82,10 @@ cc_get_log_dir(void) } char * -cc_make_filename(int serial, char *ext) +cc_make_filename(int serial, int flight, char *ext) { char base[50]; + char seq[20]; struct tm tm; time_t now; char *full; @@ -96,13 +97,19 @@ cc_make_filename(int serial, char *ext) cc_mkdir(cc_get_log_dir()); sequence = 0; for (;;) { - snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - tm.tm_year + 1900, - tm.tm_mon + 1, - tm.tm_mday, - serial, - sequence, - ext); + if (sequence) + snprintf(seq, sizeof(seq), "-seq-%03d", sequence); + else + seq[0] = '\0'; + + snprintf(base, sizeof (base), "%04d-%02d-%02d-serial-%03d-flight-%03d%s.%s", + tm.tm_year + 1900, + tm.tm_mon + 1, + tm.tm_mday, + serial, + flight, + seq, + ext); full = cc_fullname(cc_get_log_dir(), base); r = access(full, F_OK); if (r < 0) diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index 46b16a8e..ede46aa0 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -61,7 +61,7 @@ char * cc_get_log_dir(void); char * -cc_make_filename(int serial, char *ext); +cc_make_filename(int serial, int flight, char *ext); /* * For sequential data which are not evenly spaced -- cgit v1.2.3 From ea40561b36519a5dcabedabe18672b79ea5e9993 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 22 Nov 2009 10:18:44 -0700 Subject: update changelogs for Debian build --- ChangeLog | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 16 ++++++++ 2 files changed, 135 insertions(+) diff --git a/ChangeLog b/ChangeLog index cb757385..7f1234ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,122 @@ +commit d6ba07e885bdc62ba64719c9d8cc42fcecbcb09d +Author: Keith Packard +Date: Sun Nov 22 01:10:44 2009 -0800 + + Automatically extract flight number for eeprom and telem filenames. + + Extract flight number from either telemetry or eeprom files and use + that in the resulting filenames. To ensure that files remain unique, + add a new field, -seq-%03d. This is appended only when the sequence + number is non-zero as it shouldn't occur in normal usage. + + This also eliminates some duplicate filename creation code in the + library and aoview sources. + + Signed-off-by: Keith Packard + +commit 06cebd1026dc1bd6ee51526fa2d02905df3b3b37 +Author: Keith Packard +Date: Sun Nov 22 00:52:58 2009 -0800 + + ao-postflight: don't try to use missing gps sat data + + Signed-off-by: Keith Packard + +commit a9ada1b538af3308e1b22bd024d9204521184173 +Author: Keith Packard +Date: Sat Nov 21 22:12:21 2009 -0800 + + ao-postflight: compute barometric alt for each GPS position + + Print that to the --gps file, and use that in the --kml file for the + altitude. Gives a very different picture of our flight tracks, + presumably far more accurate (at least in altitude). + + Signed-off-by: Keith Packard + +commit b84b634d9ae8ce6ab1c02833a3ed8514404e1ca3 +Author: Keith Packard +Date: Sat Nov 21 22:11:45 2009 -0800 + + Don't crash if --plot isn't passed on ao-postflight command line + + Crashing is not nice. + + Signed-off-by: Keith Packard + +commit 2d77c18b15834046b7b79d49d87211828f2409e9 +Author: Keith Packard +Date: Sat Nov 21 21:10:09 2009 -0800 + + Convert telemetry file GPS satellite information in cc_log_read + + The satellite info wasn't being correctly converted from telemetry + files to the data log structure, so ao-postflight was not seeing it. + + Signed-off-by: Keith Packard + +commit 1e7fb61700f1f6f2ed5fdbc4380d7187b0cd187b +Author: Keith Packard +Date: Sat Nov 21 21:09:03 2009 -0800 + + Fix --plot arg handling. Add -all option. + + The --plot file name handing is special as the library wants a + filename instead of a stdio file pointer. + + Add a --all option that just creates all of the possible outputs. + + Signed-off-by: Keith Packard + +commit 199f0cecae22645140185238682b9e1aba0e5715 +Author: Keith Packard +Date: Sat Nov 21 20:36:20 2009 -0800 + + Make TD print 0000-00-00 for invalid dates. + + This 'shouldn't' happen, but in case it does, I want to know about it. + + Signed-off-by: Keith Packard + +commit 238d03462a56dc1b7c871608cb00f961a88c1b97 +Author: Keith Packard +Date: Sat Nov 21 20:35:22 2009 -0800 + + Make ao-postflight create filenames using input filenames. + + Instead of requiring the user to provide names for the various output + options, just create them from the input name by replacing the extension. + + Signed-off-by: Keith Packard + +commit 1a3b4c02a01187f8b7b9a9c97712476d0007ab35 +Author: Keith Packard +Date: Sat Nov 21 19:52:26 2009 -0800 + + Document ao-postflight --gps and --kml options. + + These were missing from the man page, but included in the --help output. + + Signed-off-by: Keith Packard + +commit 80b23f3044a654d61212891a61fadb8a3a4e5572 +Author: Keith Packard +Date: Sat Nov 21 18:57:45 2009 -0800 + + Decode HDOP data from skytraq GPS + + The hdop data was getting dropped on the floor, but is rather useful + when deciding if the GPS position is crazy or not. This reports HDOP * + 5 (giving a useful range of .2-50). + + Signed-off-by: Keith Packard + +commit 8f036ee7cd30ce3ed2e5cc8501914a4c19b73875 +Author: Bdale Garbee +Date: Fri Nov 20 13:19:02 2009 -0700 + + update changelogs for Debian build + commit 87e6f3e5c1688503ab8595912d8d6eb7139830b7 Author: Keith Packard Date: Fri Nov 20 12:16:37 2009 -0800 diff --git a/debian/changelog b/debian/changelog index 2c54a66e..575effd2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +altos (0.6+43+gd6ba07e) unstable; urgency=low + + [ Keith Packard ] + * Decode HDOP data from skytraq GPS + * Document ao-postflight --gps and --kml options. + * Make ao-postflight create filenames using input filenames. + * Make TD print 0000-00-00 for invalid dates. + * Fix --plot arg handling. Add -all option. + * Convert telemetry file GPS satellite information in cc_log_read + * Don't crash if --plot isn't passed on ao-postflight command line + * ao-postflight: compute barometric alt for each GPS position + * ao-postflight: don't try to use missing gps sat data + * Automatically extract flight number for eeprom and telem filenames. + + -- Bdale Garbee Sun, 22 Nov 2009 10:18:26 -0700 + altos (0.6+32+g87e6f3e) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From d34dcc5f3616e59ee90ed172770fe2a3eb1e0cac Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 26 Nov 2009 10:40:07 -0700 Subject: fix absolute path in debian/dirs, add Suggests for slim-altusmetrum --- debian/control | 1 + debian/dirs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3029e7d4..6700af37 100644 --- a/debian/control +++ b/debian/control @@ -10,6 +10,7 @@ Homepage: http://altusmetrum.org/ Package: altos Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, nickle, plplot9-driver-cairo +Suggests: slim-altusmetrum Description: Altus Metrum firmware and utilities Firmware and utilities needed to support the TeleMetrum dual-deploy recording altimeter for high power model rocketry. diff --git a/debian/dirs b/debian/dirs index 3783a46c..3a4a3418 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,4 +1,4 @@ etc/apt/sources.list.d usr/bin usr/share/altos -/usr/share/pixmaps +usr/share/pixmaps -- cgit v1.2.3 From ab1075e7219b02258c1613d93379582be4168947 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 26 Nov 2009 11:15:13 -0700 Subject: change home URL in control file to be the AltOS page --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 6700af37..63aa48df 100644 --- a/debian/control +++ b/debian/control @@ -5,7 +5,7 @@ Maintainer: Bdale Garbee Uploaders: Keith Packard Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev Standards-Version: 3.8.3 -Homepage: http://altusmetrum.org/ +Homepage: http://altusmetrum.org/AltOS Package: altos Architecture: any -- cgit v1.2.3 From 40533095a96b6c6364eebdc4b7d53c4eabe72e9a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 26 Nov 2009 11:16:04 -0700 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7f1234ee..46393ef7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit ab1075e7219b02258c1613d93379582be4168947 +Author: Bdale Garbee +Date: Thu Nov 26 11:15:13 2009 -0700 + + change home URL in control file to be the AltOS page + +commit d34dcc5f3616e59ee90ed172770fe2a3eb1e0cac +Author: Bdale Garbee +Date: Thu Nov 26 10:40:07 2009 -0700 + + fix absolute path in debian/dirs, add Suggests for slim-altusmetrum + +commit ea40561b36519a5dcabedabe18672b79ea5e9993 +Author: Bdale Garbee +Date: Sun Nov 22 10:18:44 2009 -0700 + + update changelogs for Debian build + commit d6ba07e885bdc62ba64719c9d8cc42fcecbcb09d Author: Keith Packard Date: Sun Nov 22 01:10:44 2009 -0800 diff --git a/debian/changelog b/debian/changelog index 575effd2..a5628444 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+46+gab1075e) unstable; urgency=low + + * fix absolute path in debian/dirs, add Suggests for slim-altusmetrum + * change home URL in control file to be the AltOS page + + -- Bdale Garbee Thu, 26 Nov 2009 11:15:47 -0700 + altos (0.6+43+gd6ba07e) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 291e2004e77debdc1543912cf11043c849305de8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 26 Nov 2009 11:18:37 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 46393ef7..3f165a10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 40533095a96b6c6364eebdc4b7d53c4eabe72e9a +Author: Bdale Garbee +Date: Thu Nov 26 11:16:04 2009 -0700 + + update changelogs for Debian build + commit ab1075e7219b02258c1613d93379582be4168947 Author: Bdale Garbee Date: Thu Nov 26 11:15:13 2009 -0700 diff --git a/debian/changelog b/debian/changelog index a5628444..2ce98aad 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+46+gab1075e) unstable; urgency=low +altos (0.6+47+g4053309) unstable; urgency=low * fix absolute path in debian/dirs, add Suggests for slim-altusmetrum * change home URL in control file to be the AltOS page -- cgit v1.2.3 From 9a1d7dd78c07d18954ef620b6ed25d6701df21e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 14:35:39 -0800 Subject: Change default callsign to "N0CALL" --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_config.c b/src/ao_config.c index e82aa015..7f76a585 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -24,7 +24,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 -#define AO_CONFIG_DEFAULT_CALLSIGN "KD7SQG" +#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -- cgit v1.2.3 From ce7325cefbbe91054c1e8174cf40a6c687f6694b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 4 Dec 2009 21:02:07 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3f165a10..34bab592 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 9a1d7dd78c07d18954ef620b6ed25d6701df21e2 +Author: Keith Packard +Date: Fri Dec 4 14:35:39 2009 -0800 + + Change default callsign to "N0CALL" + +commit 291e2004e77debdc1543912cf11043c849305de8 +Author: Bdale Garbee +Date: Thu Nov 26 11:18:37 2009 -0700 + + update changelogs for Debian build + commit 40533095a96b6c6364eebdc4b7d53c4eabe72e9a Author: Bdale Garbee Date: Thu Nov 26 11:16:04 2009 -0700 diff --git a/debian/changelog b/debian/changelog index 2ce98aad..34ec23a4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+49+g9a1d7dd) unstable; urgency=low + + [ Keith Packard ] + * Change default callsign to "N0CALL" + + -- Bdale Garbee Fri, 04 Dec 2009 21:01:55 -0700 + altos (0.6+47+g4053309) unstable; urgency=low * fix absolute path in debian/dirs, add Suggests for slim-altusmetrum -- cgit v1.2.3 From e6d6ad66ce177eb6e49eaa04b1ecc6426f4bbdbf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:35:40 -0800 Subject: Remove send_serial and serial_baud commands. No longer useful, and they take up space. Signed-off-by: Keith Packard --- src/ao_serial.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/src/ao_serial.c b/src/ao_serial.c index 1e3ea3e3..3f103766 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -85,16 +85,6 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static void -send_serial(void) -{ - ao_cmd_white(); - while (ao_cmd_lex_c != '\n') { - ao_serial_putchar(ao_cmd_lex_c); - ao_cmd_lex(); - } -} - static void monitor_serial(void) { @@ -102,18 +92,9 @@ monitor_serial(void) serial_echo = ao_cmd_lex_i != 0; } -static void -serial_baud(void) -{ - ao_cmd_hex(); - ao_serial_set_speed(ao_cmd_lex_i); -} - __code struct ao_cmds ao_serial_cmds[] = { - { 'S', send_serial, "S Send data to serial line" }, { 'M', monitor_serial, "M Monitor serial data" }, - { 'B', serial_baud, "B <0 = 4800, 1 = 57600> Set serial baud rate" }, - { 0, send_serial, NULL }, + { 0, monitor_serial, NULL }, }; static const struct { -- cgit v1.2.3 From c671a3f31f54715284beef5baa4a72ca922e4018 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:36:54 -0800 Subject: Make ao_cmd_decimal produce both 32 and 16 bit values. ao_cmd_lex_u32 is produced in addition to ao_cmd_lex_i so that functions can easily read 32-bit values from the command line. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_cmd.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index b72cac5c..287c912d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -330,6 +330,7 @@ enum ao_cmd_status { }; extern __xdata uint16_t ao_cmd_lex_i; +extern __xdata uint32_t ao_cmd_lex_u32; extern __xdata char ao_cmd_lex_c; extern __xdata enum ao_cmd_status ao_cmd_status; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 58039f3a..b6d2b886 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -18,6 +18,7 @@ #include "ao.h" __xdata uint16_t ao_cmd_lex_i; +__xdata uint32_t ao_cmd_lex_u32; __xdata char ao_cmd_lex_c; __xdata enum ao_cmd_status ao_cmd_status; static __xdata uint8_t lex_echo; @@ -157,11 +158,11 @@ ao_cmd_decimal(void) { __xdata uint8_t r = ao_cmd_lex_error; - ao_cmd_lex_i = 0; + ao_cmd_lex_u32 = 0; ao_cmd_white(); for(;;) { if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - ao_cmd_lex_i = (ao_cmd_lex_i * 10) + (ao_cmd_lex_c - '0'); + ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); else break; r = ao_cmd_success; @@ -169,6 +170,7 @@ ao_cmd_decimal(void) } if (r != ao_cmd_success) ao_cmd_status = r; + ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; } uint8_t -- cgit v1.2.3 From cd49847f3125df1733f298b56a43e8027ab5ce05 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:38:26 -0800 Subject: Add radio calibration configuration. The crystal we use is only good for 20ppm, which generates a fairly significant error bounds at our RF frequency. This commit adds a configuration variable that sets the RF frequency control variable so that the output frequency can be adjusted. Signed-off-by: Keith Packard --- src/ao.h | 9 +++++---- src/ao_config.c | 34 +++++++++++++++++++++++++++++++++- src/ao_radio.c | 52 ++++++++++++++++++++++++---------------------------- 3 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/ao.h b/src/ao.h index 287c912d..d8e1b92a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -938,17 +938,18 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 2 +#define AO_CONFIG_MINOR 3 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; - int16_t accel_plus_g; + int16_t accel_plus_g; /* changed for minor version 2 */ uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; - uint8_t apogee_delay; - int16_t accel_minus_g; + uint8_t apogee_delay; /* minor version 1 */ + int16_t accel_minus_g; /* minor version 2 */ + uint32_t radio_frequency; /* minor version 3 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 7f76a585..27a60ac1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,12 @@ __xdata uint8_t ao_config_mutex; #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 + */ +#define AO_CONFIG_DEFAULT_RADIO_FREQUENCY 1186611 static void _ao_config_put(void) @@ -51,17 +57,21 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - /* Fixupes for minor version 2 */ + /* Fixups for minor version 2 */ if (ao_config.minor < 2) { ao_config.accel_plus_g = 0; ao_config.accel_minus_g = 0; } + /* Fixups for minor version 3 */ + if (ao_config.minor < 3) + ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -245,6 +255,26 @@ ao_config_apogee_delay_set(void) __reentrant ao_config_apogee_delay_show(); } +void +ao_config_radio_frequency_show(void) __reentrant +{ + printf("Radio frequency: %ld\n", ao_config.radio_frequency); +} + +void +ao_config_radio_frequency_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.radio_frequency = ao_cmd_lex_u32; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_radio_frequency_show(); +} + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -268,6 +298,8 @@ __code struct ao_config_var ao_config_vars[] = { "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, + { 'f', ao_config_radio_frequency_set, ao_config_radio_frequency_show, + "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, diff --git a/src/ao_radio.c b/src/ao_radio.c index c7c8dc8d..6d25df39 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -28,14 +28,6 @@ * RX filter: 93.75 kHz */ -/* - * For 434.550MHz, the frequency value is: - * - * 434.550e6 / (24e6 / 2**16) = 1186611.2 - */ - -#define FREQ_CONTROL 1186611 - /* * For IF freq of 140.62kHz, the IF value is: * @@ -124,10 +116,6 @@ static __code uint8_t radio_setup[] = { RF_PA_TABLE1_OFF, RF_POWER, RF_PA_TABLE0_OFF, RF_POWER, - RF_FREQ2_OFF, (FREQ_CONTROL >> 16) & 0xff, - RF_FREQ1_OFF, (FREQ_CONTROL >> 8) & 0xff, - RF_FREQ0_OFF, (FREQ_CONTROL >> 0) & 0xff, - RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), @@ -336,14 +324,25 @@ ao_radio_idle(void) } } -void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +static void +ao_radio_get(void) { ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; + RF_FREQ2 = (uint8_t) (ao_config.radio_frequency >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_frequency >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_frequency); +} + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +void +ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +{ + ao_radio_get(); + ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, telemetry, &RFDXADDR, @@ -358,16 +357,13 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant RFST = RFST_STX; __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); } uint8_t ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant { - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, radio, @@ -382,7 +378,7 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant RFST = RFST_SRX; __critical while (!ao_radio_dma_done) ao_sleep(&ao_radio_dma_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); return (ao_radio_dma_done & AO_DMA_DONE); } @@ -394,8 +390,8 @@ ao_radio_rdf(int ms) { uint8_t i; uint8_t pkt_len; - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); + + ao_radio_get(); ao_radio_rdf_running = 1; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; @@ -431,7 +427,7 @@ ao_radio_rdf(int ms) ao_radio_idle(); for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); } void @@ -448,18 +444,18 @@ ao_radio_rdf_abort(void) ao_radio_abort(); } + /* Output carrier */ void ao_radio_test(void) { - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); + ao_packet_slave_stop(); + ao_radio_get(); printf ("Hit a character to stop..."); flush(); RFST = RFST_STX; getchar(); ao_radio_idle(); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); putchar('\n'); } -- cgit v1.2.3 From bf29a62532fec12e6af2d2f3a6624882c863e933 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 5 Dec 2009 11:03:42 -0700 Subject: update changelogs for Debian build --- ChangeLog | 40 ++++++++++++++++++++++++++++++++++++++++ debian/changelog | 9 +++++++++ 2 files changed, 49 insertions(+) diff --git a/ChangeLog b/ChangeLog index 34bab592..0939eb3e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +commit cd49847f3125df1733f298b56a43e8027ab5ce05 +Author: Keith Packard +Date: Fri Dec 4 23:38:26 2009 -0800 + + Add radio calibration configuration. + + The crystal we use is only good for 20ppm, which generates a fairly + significant error bounds at our RF frequency. This commit adds a + configuration variable that sets the RF frequency control variable so + that the output frequency can be adjusted. + + Signed-off-by: Keith Packard + +commit c671a3f31f54715284beef5baa4a72ca922e4018 +Author: Keith Packard +Date: Fri Dec 4 23:36:54 2009 -0800 + + Make ao_cmd_decimal produce both 32 and 16 bit values. + + ao_cmd_lex_u32 is produced in addition to ao_cmd_lex_i so that + functions can easily read 32-bit values from the command line. + + Signed-off-by: Keith Packard + +commit e6d6ad66ce177eb6e49eaa04b1ecc6426f4bbdbf +Author: Keith Packard +Date: Fri Dec 4 23:35:40 2009 -0800 + + Remove send_serial and serial_baud commands. + + No longer useful, and they take up space. + + Signed-off-by: Keith Packard + +commit ce7325cefbbe91054c1e8174cf40a6c687f6694b +Author: Bdale Garbee +Date: Fri Dec 4 21:02:07 2009 -0700 + + update changelogs for Debian build + commit 9a1d7dd78c07d18954ef620b6ed25d6701df21e2 Author: Keith Packard Date: Fri Dec 4 14:35:39 2009 -0800 diff --git a/debian/changelog b/debian/changelog index 34ec23a4..61e36e3b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +altos (0.6+53+gcd49847) unstable; urgency=low + + [ Keith Packard ] + * Remove send_serial and serial_baud commands. + * Make ao_cmd_decimal produce both 32 and 16 bit values. + * Add radio calibration configuration. + + -- Bdale Garbee Sat, 05 Dec 2009 11:02:49 -0700 + altos (0.6+49+g9a1d7dd) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 46f03ab3145a61139c8ca6fc99e8f2798728b5a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Dec 2009 15:36:12 -0800 Subject: Re-order config values. Change frequency to cal Place more often used values at top, and consistently call the radio value 'calibration' instead of 'frequency'. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_config.c | 28 ++++++++++++++-------------- src/ao_radio.c | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/ao.h b/src/ao.h index d8e1b92a..39f7bea2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -949,7 +949,7 @@ struct ao_config { char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ - uint32_t radio_frequency; /* minor version 3 */ + uint32_t radio_cal; /* minor version 3 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 27a60ac1..3609ec06 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -32,7 +32,7 @@ __xdata uint8_t ao_config_mutex; * * 434.550e6 / (24e6 / 2**16) = 1186611.2 */ -#define AO_CONFIG_DEFAULT_RADIO_FREQUENCY 1186611 +#define AO_CONFIG_DEFAULT_RADIO_CAL 1186611 static void _ao_config_put(void) @@ -57,7 +57,7 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; + ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -71,7 +71,7 @@ _ao_config_get(void) } /* Fixups for minor version 3 */ if (ao_config.minor < 3) - ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; + ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -256,23 +256,23 @@ ao_config_apogee_delay_set(void) __reentrant } void -ao_config_radio_frequency_show(void) __reentrant +ao_config_radio_cal_show(void) __reentrant { - printf("Radio frequency: %ld\n", ao_config.radio_frequency); + printf("Radio cal: %ld\n", ao_config.radio_cal); } void -ao_config_radio_frequency_set(void) __reentrant +ao_config_radio_cal_set(void) __reentrant { ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.radio_frequency = ao_cmd_lex_u32; + ao_config.radio_cal = ao_cmd_lex_u32; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_radio_frequency_show(); + ao_config_radio_cal_show(); } struct ao_config_var { @@ -294,16 +294,16 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, - { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, - "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, + "d Set apogee igniter delay (in seconds)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, - { 'f', ao_config_radio_frequency_set, ao_config_radio_frequency_show, - "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, - { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, - "d Set apogee igniter delay (in seconds)" }, + { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, + "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, + "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, { 'w', ao_config_write, ao_config_write, diff --git a/src/ao_radio.c b/src/ao_radio.c index 6d25df39..4dea6dce 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -331,9 +331,9 @@ ao_radio_get(void) ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_frequency >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_frequency >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_frequency); + RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_cal); } #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -- cgit v1.2.3 From 5481082b18226a0de6b377215b3b330bdbc4a6c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Dec 2009 19:50:38 -0800 Subject: Allow radio calibration to be set from ao-load This moves the initial radio calibration value into const memory where it will be used if no eeprom configuration value is available, either on an unprogrammed board with eeprom or a device without an eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 46 ++++++++++++++++++++++++++++++++++++---------- src/ao_config.c | 10 +++++++--- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index f5466612..4aa91b29 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -29,14 +29,17 @@ struct sym { unsigned addr; char *name; -} serial_symbols[] = { +} ao_symbols[] = { { 0, "_ao_serial_number" }, -#define AO_SERIAL_NUMBER (serial_symbols[0].addr) +#define AO_SERIAL_NUMBER (ao_symbols[0].addr) { 0, "_ao_usb_descriptors" }, -#define AO_USB_DESCRIPTORS (serial_symbols[1].addr) +#define AO_USB_DESCRIPTORS (ao_symbols[1].addr) + { 0, "_ao_radio_cal" }, +#define AO_RADIO_CAL (ao_symbols[2].addr) }; -#define NUM_SERIAL_SYMBOLS (sizeof(serial_symbols)/sizeof(serial_symbols[0])) +#define NUM_SERIAL_SYMBOLS 2 +#define NUM_SYMBOLS 3 static int find_symbols(FILE *map) @@ -64,14 +67,14 @@ find_symbols(FILE *map) a = strtoul(colon+1, &addr_end, 16); if (a == ULONG_MAX || addr_end == addr) continue; - for (s = 0; s < NUM_SERIAL_SYMBOLS; s++) - if (!strcmp(serial_symbols[s].name, name)) { - serial_symbols[s].addr = (unsigned) a; + for (s = 0; s < NUM_SYMBOLS; s++) + if (!strcmp(ao_symbols[s].name, name)) { + ao_symbols[s].addr = (unsigned) a; ++found; break; } } - return found == NUM_SERIAL_SYMBOLS; + return found >= NUM_SERIAL_SYMBOLS; } static int @@ -93,12 +96,13 @@ rewrite(struct hex_image *image, unsigned addr, char *data, int len) static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "cal", .has_arg = 1, .val = 'c' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx serial-number\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [--cal ] file.ihx serial-number\n", program); exit(1); } @@ -125,9 +129,12 @@ main (int argc, char **argv) int string_num; char *tty = NULL; char *device = NULL; + uint32_t cal = 0; + char cal_int[4]; + char *cal_end; int c; - while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:c:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -135,6 +142,11 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'c': + cal = strtoul(optarg, &cal_end, 10); + if (cal_end == optarg || *cal_end != '\0') + usage(argv[0]); + break; default: usage(argv[0]); break; @@ -225,6 +237,20 @@ main (int argc, char **argv) if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) usage(argv[0]); + if (cal) { + cal_int[0] = cal & 0xff; + cal_int[1] = (cal >> 8) & 0xff; + cal_int[2] = (cal >> 16) & 0xff; + cal_int[3] = (cal >> 24) & 0xff; + if (!AO_RADIO_CAL) { + fprintf(stderr, "Cannot find radio calibration location in image\n"); + exit(1); + } + if (!rewrite(image, AO_RADIO_CAL, cal_int, sizeof (cal_int))) { + fprintf(stderr, "Cannot rewrite radio calibration at %04x\n", AO_RADIO_CAL); + exit(1); + } + } if (!tty) tty = cc_usbdevs_find_by_arg(device, "TIDongle"); dbg = ccdbg_open(tty); diff --git a/src/ao_config.c b/src/ao_config.c index 3609ec06..4349bca8 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -31,8 +31,12 @@ __xdata uint8_t ao_config_mutex; * 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. */ -#define AO_CONFIG_DEFAULT_RADIO_CAL 1186611 +const uint32_t ao_radio_cal = 1186611; static void _ao_config_put(void) @@ -57,7 +61,7 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; + ao_config.radio_cal = ao_radio_cal; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -71,7 +75,7 @@ _ao_config_get(void) } /* Fixups for minor version 3 */ if (ao_config.minor < 3) - ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; + ao_config.radio_cal = ao_radio_cal; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } -- cgit v1.2.3 From 7ac8efea5d60b81adccdc1e38ac4c13facfae7c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 15 Dec 2009 23:58:29 -0800 Subject: Add --cal to man page --- ao-tools/ao-load/ao-load.1 | 11 +++++++++++ ao-tools/ao-rawload/ao-rawload.c | 12 +++++++++++- src/Makefile | 3 ++- src/ao_gps_sirf.c | 17 ----------------- src/ao_gps_skytraq.c | 17 ----------------- 5 files changed, 24 insertions(+), 36 deletions(-) diff --git a/ao-tools/ao-load/ao-load.1 b/ao-tools/ao-load/ao-load.1 index eb2bc0d8..79b76a79 100644 --- a/ao-tools/ao-load/ao-load.1 +++ b/ao-tools/ao-load/ao-load.1 @@ -25,6 +25,7 @@ ao-load \- flash a program to a AltOS device [\--tty \fItty-device\fP] [\-D \fIaltos-device\fP] [\--device \fIaltos-device\fP] +[\--cal \fIradio-calibration\fP] \fIfile.ihx\fP \fIdevice serial number\fP .SH DESCRIPTION @@ -52,6 +53,16 @@ TeleMetrum Leaving out the product name will cause the tool to select a suitable product, leaving out the serial number will cause the tool to match one of the available devices. +.TP +\-c radio-calibration | --cal radio-calibration +This programs the radio calibration value into the image for hardware +which doesn't have any eeprom storage for this value. The value here +can be computed given the current radio calibration value, the +measured frequency and the desired frequency: +.IP + cal' = cal * (desired/measured) +.IP +The default calibration value is 1186611. .SH USAGE .I ao-load reads the specified .ihx file into memory, locates the matching .map diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index d9ee5718..0098b658 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -19,16 +19,18 @@ #include #include #include "ccdbg.h" +#include "cc.h" static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "run", .has_arg = 0, .val = 'r' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [--run] file.ihx\n", program); exit(1); } @@ -45,6 +47,7 @@ main (int argc, char **argv) char *tty = NULL; char *device = NULL; int c; + int run = 0; while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { @@ -54,6 +57,9 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'r': + run = 1; + break; default: usage(argv[0]); break; @@ -105,6 +111,10 @@ main (int argc, char **argv) ccdbg_close(dbg); exit(1); } + if (run) { + ccdbg_set_pc(dbg, image->address); + ccdbg_resume(dbg); + } ccdbg_close(dbg); exit (0); } diff --git a/src/Makefile b/src/Makefile index 8c24e6f4..8074d42d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,7 @@ ALTOS_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_gps_print.c \ + ao_dbg.c \ ao_packet.c \ ao_packet_slave.c \ ao_state.c @@ -53,6 +53,7 @@ TELE_COMMON_SRC = \ # TELE_RECEIVER_SRC =\ ao_monitor.c \ + ao_gps_print.c \ ao_packet_master.c \ ao_rssi.c diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index eb00224c..64b66c95 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -430,25 +430,8 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ef581349..361c77ce 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -410,25 +410,8 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); } -- cgit v1.2.3 From bbb152c712801653374a8f82869e2e8bf41f7279 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 19 Dec 2009 12:05:40 -0700 Subject: update changelogs for Debian build --- ChangeLog | 35 +++++++++++++++++++++++++++++++++++ debian/changelog | 9 +++++++++ 2 files changed, 44 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0939eb3e..1ced1821 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,38 @@ +commit 7ac8efea5d60b81adccdc1e38ac4c13facfae7c9 +Author: Keith Packard +Date: Tue Dec 15 23:58:29 2009 -0800 + + Add --cal to man page + +commit 5481082b18226a0de6b377215b3b330bdbc4a6c6 +Author: Keith Packard +Date: Sat Dec 5 19:50:38 2009 -0800 + + Allow radio calibration to be set from ao-load + + This moves the initial radio calibration value into const memory where + it will be used if no eeprom configuration value is available, either + on an unprogrammed board with eeprom or a device without an eeprom. + + Signed-off-by: Keith Packard + +commit 46f03ab3145a61139c8ca6fc99e8f2798728b5a9 +Author: Keith Packard +Date: Sat Dec 5 15:36:12 2009 -0800 + + Re-order config values. Change frequency to cal + + Place more often used values at top, and consistently call the radio + value 'calibration' instead of 'frequency'. + + Signed-off-by: Keith Packard + +commit bf29a62532fec12e6af2d2f3a6624882c863e933 +Author: Bdale Garbee +Date: Sat Dec 5 11:03:42 2009 -0700 + + update changelogs for Debian build + commit cd49847f3125df1733f298b56a43e8027ab5ce05 Author: Keith Packard Date: Fri Dec 4 23:38:26 2009 -0800 diff --git a/debian/changelog b/debian/changelog index 61e36e3b..95f72382 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +altos (0.6+57+g7ac8efe) unstable; urgency=low + + [ Keith Packard ] + * Re-order config values. Change frequency to cal + * Allow radio calibration to be set from ao-load + * Add --cal to man page + + -- Bdale Garbee Sat, 19 Dec 2009 12:05:26 -0700 + altos (0.6+53+gcd49847) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From a15abc1882a3bdd2c980eed169f3b80337528390 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 19 Dec 2009 12:15:29 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1ced1821..25cf7f17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit bbb152c712801653374a8f82869e2e8bf41f7279 +Author: Bdale Garbee +Date: Sat Dec 19 12:05:40 2009 -0700 + + update changelogs for Debian build + commit 7ac8efea5d60b81adccdc1e38ac4c13facfae7c9 Author: Keith Packard Date: Tue Dec 15 23:58:29 2009 -0800 diff --git a/debian/changelog b/debian/changelog index 95f72382..d451654b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+57+g7ac8efe) unstable; urgency=low +altos (0.6+58+gbbb152c) unstable; urgency=low [ Keith Packard ] * Re-order config values. Change frequency to cal -- cgit v1.2.3 From 10d1bbcd9709a5eee8d50989215242b16feb7232 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 11:34:16 -0800 Subject: Use ao_radio_get/ao_radio_put in packet code. The ao_radio_get function both acquires the mutex *and* configures the radio channel and frequency. Failing to use this in the packet code would leave the radio frequency unconfigured. Signed-off-by: Keith Packard --- src/ao.h | 5 +++++ src/ao_packet.c | 16 ++++++---------- src/ao_radio.c | 3 +-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/ao.h b/src/ao.h index 39f7bea2..096a4d80 100644 --- a/src/ao.h +++ b/src/ao.h @@ -835,6 +835,11 @@ extern __xdata uint8_t ao_radio_mutex; void ao_radio_general_isr(void) interrupt 16; +void +ao_radio_get(void); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + void ao_radio_set_telemetry(void); diff --git a/src/ao_packet.c b/src/ao_packet.c index 3ce7e9ab..98fdcb90 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -33,8 +33,9 @@ void ao_packet_send(void) { ao_led_on(AO_LED_RED); - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); + ao_radio_get(); + + /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); ao_tx_packet.len = ao_packet_tx_used; @@ -42,9 +43,7 @@ ao_packet_send(void) ao_packet_tx_used = 0; ao_wakeup(&tx_data); } - ao_radio_idle(); ao_radio_done = 0; - RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &ao_tx_packet, &RFDXADDR, @@ -59,7 +58,7 @@ ao_packet_send(void) RFST = RFST_STX; __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); ao_led_off(AO_LED_RED); } @@ -69,10 +68,7 @@ ao_packet_recv(void) uint8_t dma_done; ao_led_on(AO_LED_GREEN); - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, &ao_rx_packet, @@ -89,7 +85,7 @@ ao_packet_recv(void) if (ao_sleep(&ao_radio_dma_done) != 0) ao_radio_abort(); dma_done = ao_radio_dma_done; - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { diff --git a/src/ao_radio.c b/src/ao_radio.c index 4dea6dce..1a0cf4fa 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -324,7 +324,7 @@ ao_radio_idle(void) } } -static void +void ao_radio_get(void) { ao_config_get(); @@ -336,7 +336,6 @@ ao_radio_get(void) RF_FREQ0 = (uint8_t) (ao_config.radio_cal); } -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant -- cgit v1.2.3 From d4cf1446680d8b47396bcda338e8df7af395d102 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 19 Dec 2009 13:53:38 -0700 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 25cf7f17..cee5bdee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 10d1bbcd9709a5eee8d50989215242b16feb7232 +Author: Keith Packard +Date: Sat Dec 19 11:34:16 2009 -0800 + + Use ao_radio_get/ao_radio_put in packet code. + + The ao_radio_get function both acquires the mutex *and* configures the + radio channel and frequency. Failing to use this in the packet code + would leave the radio frequency unconfigured. + + Signed-off-by: Keith Packard + +commit a15abc1882a3bdd2c980eed169f3b80337528390 +Author: Bdale Garbee +Date: Sat Dec 19 12:15:29 2009 -0700 + + update changelogs for Debian build + commit bbb152c712801653374a8f82869e2e8bf41f7279 Author: Bdale Garbee Date: Sat Dec 19 12:05:40 2009 -0700 diff --git a/debian/changelog b/debian/changelog index d451654b..b988eea8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+60+g10d1bbc) unstable; urgency=low + + [ Keith Packard ] + * Use ao_radio_get/ao_radio_put in packet code. + + -- Bdale Garbee Sat, 19 Dec 2009 13:53:32 -0700 + altos (0.6+58+gbbb152c) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 598d168bd6552c3756e4b0267de44147eadab9f6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 14:03:11 -0800 Subject: Disable monitor mode before attempting radio test. If monitor mode is left active, then the radio lock will not be able to be acquired for the radio test. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 14 ++++++++------ src/ao_radio.c | 1 + src/ao_telemetrum.c | 7 +++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index ba5ad1c1..122c4da0 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -40,13 +40,15 @@ ao_packet_slave_start(void) void ao_packet_slave_stop(void) { - ao_packet_enable = 0; - ao_radio_abort(); - while (ao_packet_task.wchan) { - ao_wake_task(&ao_packet_task); - ao_yield(); + if (ao_packet_enable) { + ao_packet_enable = 0; + ao_radio_abort(); + while (ao_packet_task.wchan) { + ao_wake_task(&ao_packet_task); + ao_yield(); + } + ao_radio_set_telemetry(); } - ao_radio_set_telemetry(); } void diff --git a/src/ao_radio.c b/src/ao_radio.c index 1a0cf4fa..bb19c6a9 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -448,6 +448,7 @@ ao_radio_rdf_abort(void) void ao_radio_test(void) { + ao_set_monitor(0); ao_packet_slave_stop(); ao_radio_get(); printf ("Hit a character to stop..."); flush(); diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 5250078e..990b0d77 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -17,6 +17,13 @@ #include "ao.h" +/* stub so as telemetrum doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + void main(void) { -- cgit v1.2.3 From eddb82390a0ecb07ef83c04861993842906b03ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 15:31:36 -0800 Subject: Ensure that ao_alarm waits at least the specified time Because the timer tick may happen soon, it's important to delay by another tick to ensure that we don't wake up early. Signed-off-by: Keith Packard --- src/ao_task.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ao_task.c b/src/ao_task.c index 4664163d..4a78766e 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -217,7 +217,10 @@ ao_wakeup(__xdata void *wchan) void ao_alarm(uint16_t delay) { - if (!(ao_cur_task->alarm = ao_time() + delay)) + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) ao_cur_task->alarm = 1; } -- cgit v1.2.3 From 3bab7e66d25988f5d63ec139c8814a85b983f8f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 20:32:18 -0800 Subject: Remove dbg driver code from telemetrum/teledongle The only board with debug outputs is the TI dongle at this point, so the debug modules were disabled in TM and TD some time ago. Unfortunately, the code was not removed then. Signed-off-by: Keith Packard --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 8074d42d..39599753 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,6 @@ ALTOS_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_dbg.c \ ao_packet.c \ ao_packet_slave.c \ ao_state.c -- cgit v1.2.3 From dc8d18736239b14c2ec48a40a01515912c5c25e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 01:22:06 -0800 Subject: Add AT45DBxx1D driver This driver supports the AT45DB011D through AT45DB321D DataFlash parts as found in TeleMetrum v0.2 Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao.h | 1 + src/ao_flash.c | 536 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 src/ao_flash.c diff --git a/src/Makefile b/src/Makefile index 39599753..dcd41718 100644 --- a/src/Makefile +++ b/src/Makefile @@ -82,7 +82,7 @@ DBG_DONGLE_SRC = \ # TM_DRIVER_SRC = \ ao_adc.c \ - ao_ee.c \ + ao_flash.c \ ao_gps_report.c \ ao_ignite.c diff --git a/src/ao.h b/src/ao.h index 096a4d80..1f27fe92 100644 --- a/src/ao.h +++ b/src/ao.h @@ -108,6 +108,7 @@ ao_start_scheduler(void); #define AO_PANIC_CMD 6 /* Too many command sets registered */ #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ #define AO_PANIC_REBOOT 8 /* Reboot failed */ +#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_flash.c b/src/ao_flash.c new file mode 100644 index 00000000..86b94765 --- /dev/null +++ b/src/ao_flash.c @@ -0,0 +1,536 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "at45db161d.h" + +/* + * Using SPI on USART 0, with P1_1 as the chip select + */ + +#define FLASH_CS P1_1 +#define FLASH_CS_INDEX 1 + +__xdata uint8_t ao_flash_dma_in_done; +__xdata uint8_t ao_flash_dma_out_done; +__xdata uint8_t ao_flash_mutex; + +uint8_t ao_flash_dma_out_id; +uint8_t ao_flash_dma_in_id; + +static __xdata uint8_t ao_flash_const = 0xff; + +#define ao_flash_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +void ao_flash_cs_low(void) +{ + ao_flash_delay(); + FLASH_CS = 0; + ao_flash_delay(); +} + +void ao_flash_cs_high(void) +{ + ao_flash_delay(); + FLASH_CS = 1; + ao_flash_delay(); +} + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +static void +ao_flash_send(void __xdata *block, uint16_t len) +{ + ao_dma_set_transfer(ao_flash_dma_in_id, + &U0DBUFXADDR, + &ao_flash_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_flash_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_flash_dma_in_id); + ao_dma_start(ao_flash_dma_out_id); + ao_dma_trigger(ao_flash_dma_out_id); + __critical while (!ao_flash_dma_in_done) + ao_sleep(&ao_flash_dma_in_done); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +static void +ao_flash_recv(void __xdata *block, uint16_t len) +{ + ao_dma_set_transfer(ao_flash_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_flash_dma_out_id, + &ao_flash_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_flash_dma_in_id); + ao_dma_start(ao_flash_dma_out_id); + ao_dma_trigger(ao_flash_dma_out_id); + __critical while (!ao_flash_dma_in_done) + ao_sleep(&ao_flash_dma_in_done); +} + +struct ao_flash_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_flash_instruction; + +static void +ao_flash_set_pagesize_512(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_SET_CONFIG; + ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; + ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; + ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_cs_high(); +} + + +static uint8_t +ao_flash_read_status(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ_STATUS; + ao_flash_send(&ao_flash_instruction, 1); + ao_flash_recv(&ao_flash_instruction, 1); + ao_flash_cs_high(); + return ao_flash_instruction.instruction; +} + +#define FLASH_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; +static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; +static __pdata uint8_t ao_flash_block_dirty; +static __pdata uint8_t ao_flash_write_pending; +static __pdata uint8_t ao_flash_setup_done; +static __data uint32_t ao_flash_device_size; +static __data uint8_t ao_flash_block_shift; + +static void +ao_flash_setup(void) +{ + uint8_t status; + + if (ao_flash_setup_done) + return; + + ao_mutex_get(&ao_flash_mutex); + if (ao_flash_setup_done) { + ao_mutex_put(&ao_flash_mutex); + return; + } + ao_flash_setup_done = 1; + + /* On first use, check to see if the flash chip has + * been programmed to use 512 byte pages. If not, do so. + * And then, because the flash part must be power cycled + * for that change to take effect, panic. + */ + status = ao_flash_read_status(); + + if (!(status & FLASH_STATUS_PAGESIZE_512)) { + ao_flash_set_pagesize_512(); + ao_panic(AO_PANIC_FLASH); + } + + switch (status & 0x3c) { + + /* AT45DB321D */ + case 0x34: + ao_flash_block_shift = 9; + ao_flash_device_size = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB161D */ + case 0x2c: + ao_flash_block_shift = 9; + ao_flash_device_size = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB081D */ + case 0x24: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB041D */ + case 0x1c: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 512 * (uint32_t) 1024); + break; + + /* AT45DB021D */ + case 0x14: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 256 * (uint32_t) 1024); + break; + + /* AT45DB011D */ + case 0x0c: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 128 * (uint32_t) 1024); + break; + + default: + ao_panic(AO_PANIC_FLASH); + } + ao_mutex_put(&ao_flash_mutex); +} + +static void +ao_flash_wait_write(void) +{ + if (ao_flash_write_pending) { + for (;;) { + uint8_t status = ao_flash_read_status(); + if ((status & FLASH_STATUS_RDY)) + break; + } + ao_flash_write_pending = 0; + } +} + +/* Write the current block to the FLASHPROM */ +static void +ao_flash_write_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_WRITE; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_flash_cs_high(); + ao_flash_write_pending = 1; +} + +/* Read the current block from the FLASHPROM */ +static void +ao_flash_read_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_flash_cs_high(); +} + +static void +ao_flash_flush_internal(void) +{ + if (ao_flash_block_dirty) { + ao_flash_write_block(); + ao_flash_block_dirty = 0; + } +} + +static void +ao_flash_fill(uint16_t block) +{ + if (block != ao_flash_block) { + ao_flash_flush_internal(); + ao_flash_block = block; + ao_flash_read_block(); + } +} + +uint8_t +ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +{ + uint16_t block; + uint16_t this_len; + uint16_t this_off; + + ao_flash_setup(); + if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & FLASH_BLOCK_MASK; + this_len = FLASH_BLOCK_SIZE - this_off; + block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + if (this_len > len) + this_len = len; + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (this_len != FLASH_BLOCK_SIZE) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + this_off, buf, this_len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +{ + uint16_t block; + uint16_t this_len; + uint16_t this_off; + + ao_flash_setup(); + if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + return 0; + while (len) { + + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & FLASH_BLOCK_MASK; + this_len = FLASH_BLOCK_SIZE - this_off; + block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + if (this_len > len) + this_len = len; + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, ao_flash_data + this_off, this_len); + } ao_mutex_put(&ao_flash_mutex); + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +void +ao_ee_flush(void) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); +} + +/* + * Read/write the config block, which is in + * the last block of the flash + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + ao_flash_setup(); + if (len > FLASH_BLOCK_SIZE) + return 0; + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(FLASH_CONFIG_BLOCK); + memcpy(ao_flash_data, buf, len); + ao_flash_block_dirty = 1; + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + ao_flash_setup(); + if (len > FLASH_BLOCK_SIZE) + return 0; + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(FLASH_CONFIG_BLOCK); + memcpy(buf, ao_flash_data, len); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +static void +flash_dump(void) __reentrant +{ + uint8_t b; + uint16_t block; + uint8_t i; + + ao_cmd_hex(); + block = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + i = 0; + do { + if ((i & 7) == 0) { + if (i) + putchar('\n'); + ao_cmd_put16((uint16_t) i); + } + putchar(' '); + ao_ee_read(((uint32_t) block << 8) | i, &b, 1); + ao_cmd_put8(b); + ++i; + } while (i != 0); + putchar('\n'); +} + +static void +flash_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + uint8_t b; + uint32_t addr; + + ao_cmd_hex(); + block = ao_cmd_lex_i; + ao_cmd_hex(); + i = ao_cmd_lex_i; + addr = ((uint32_t) block << 8) | i; + ao_cmd_hex(); + len = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + while (len--) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + b = ao_cmd_lex_i; + ao_ee_write(addr, &b, 1); + addr++; + } + ao_ee_flush(); +} + +__code struct ao_cmds ao_flash_cmds[] = { + { 'e', flash_dump, "e Dump a block of flash data" }, + { 'w', flash_store, "w ... Write data to flash" }, + { 0, flash_store, NULL }, +}; + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_ee_init(void) +{ + /* set up CS */ + FLASH_CS = 1; + P1DIR |= (1 << FLASH_CS_INDEX); + P1SEL &= ~(1 << FLASH_CS_INDEX); + + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_flash_dma_out_id = ao_dma_alloc(&ao_flash_dma_out_done); + + /* Set up IN DMA */ + ao_flash_dma_in_id = ao_dma_alloc(&ao_flash_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock, + * while the at45db161d.h is limited to 20MHz. So, + * use the 3MHz clock (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); + ao_cmd_register(&ao_flash_cmds[0]); +} -- cgit v1.2.3 From a0d4c1b06d27e850d233f8ddf8fe32912bf0ec8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 01:29:41 -0800 Subject: Remove green LED and temp sensor from v0.2 code Signed-off-by: Keith Packard --- src/ao_adc.c | 8 ++++++-- src/ao_telemetrum.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/ao_adc.c b/src/ao_adc.c index a8784667..b0bfceb1 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -51,7 +51,11 @@ ao_adc_isr(void) interrupt 1 a[1] = ADCH; if (sequence < 5) { /* start next channel conversion */ - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); + sequence++; + /* skip channel 2, we don't have a temp sensor on v0.2 */ + if (sequence == 2) + sequence++; + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); @@ -80,7 +84,7 @@ ao_adc_init(void) { ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ - (1 << 2) | /* temperature */ +/* (1 << 2) | v0.1 temperature */ (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 990b0d77..0de3572a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -30,7 +30,7 @@ main(void) ao_clock_init(); /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_init(AO_LED_RED); ao_led_on(AO_LED_RED); ao_timer_init(); -- cgit v1.2.3 From c1334f712f01543adb10809bc1a3ca120e27290b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 09:55:04 -0800 Subject: Add at45db161d.h header file for new flash part. Forgot to add this when I added the driver. Signed-off-by: Keith Packard --- src/at45db161d.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/at45db161d.h diff --git a/src/at45db161d.h b/src/at45db161d.h new file mode 100644 index 00000000..66869733 --- /dev/null +++ b/src/at45db161d.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ + +#ifndef _AT45DB161D_H_ +#define _AT45DB161D_H_ + +/* + * We reserve the last block on the device for + * configuration space. Writes and reads in this + * area return errors. + */ + +#define FLASH_BLOCK_SIZE_MAX 512 +#define FLASH_BLOCK_SHIFT (ao_flash_block_shift) +#define FLASH_BLOCK_SIZE (1 << FLASH_BLOCK_SHIFT) +#define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) +#define FLASH_DEVICE_SIZE (ao_flash_device_size) +#define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) +#define FLASH_CONFIG_BLOCK ((uint16_t) (FLASH_DATA_SIZE / FLASH_BLOCK_SIZE)) + +#define FLASH_READ 0x03 +#define FLASH_WRITE 0x82 +#define FLASH_READ_STATUS 0xd7 +#define FLASH_SET_CONFIG 0x3d + +#define FLASH_SET_512_BYTE_0 0x2a +#define FLASH_SET_512_BYTE_1 0x80 +#define FLASH_SET_512_BYTE_2 0xa6 + +#define FLASH_STATUS_RDY (1 << 7) +#define FLASH_STATUS_COMP (1 << 6) +#define FLASH_STATUS_PROTECT (1 << 1) +#define FLASH_STATUS_PAGESIZE_512 (1 << 0) + +#endif /* _AT45DB161D_H_ */ -- cgit v1.2.3 From d4c8895b349998e02e03ed83466a0ca7afb3d99b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 17:57:52 -0800 Subject: Add 'f' command to display flash status register contents Signed-off-by: Keith Packard --- src/ao_flash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ao_flash.c b/src/ao_flash.c index 86b94765..153015c6 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -480,9 +480,21 @@ flash_store(void) __reentrant ao_ee_flush(); } +static void +flash_status(void) __reentrant +{ + uint8_t status; + + ao_mutex_get(&ao_flash_mutex); { + status = ao_flash_read_status(); + printf ("Flash status: 0x%02x\n", status); + } ao_mutex_put(&ao_flash_mutex); +} + __code struct ao_cmds ao_flash_cmds[] = { { 'e', flash_dump, "e Dump a block of flash data" }, { 'w', flash_store, "w ... Write data to flash" }, + { 'f', flash_status, "f Show flash status register" }, { 0, flash_store, NULL }, }; -- cgit v1.2.3 From 05e5bb2d330b755967d06fb859585c81f5f5fbb5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 19:46:46 -0800 Subject: Dump more flash parameters for the flash_status command --- src/ao_flash.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ao_flash.c b/src/ao_flash.c index 153015c6..01d371bb 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -404,6 +404,7 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant if (len > FLASH_BLOCK_SIZE) return 0; ao_mutex_get(&ao_flash_mutex); { + printf("FLASH_CONFIG_BLOCK: %d\n", FLASH_CONFIG_BLOCK); ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(ao_flash_data, buf, len); ao_flash_block_dirty = 1; @@ -485,9 +486,16 @@ flash_status(void) __reentrant { uint8_t status; + ao_flash_setup(); ao_mutex_get(&ao_flash_mutex); { status = ao_flash_read_status(); printf ("Flash status: 0x%02x\n", status); + printf ("Flash block shift: %d\n", FLASH_BLOCK_SHIFT); + printf ("Flash block size: %d\n", FLASH_BLOCK_SIZE); + printf ("Flash block mask: %d\n", FLASH_BLOCK_MASK); + printf ("Flash device size: %ld\n", FLASH_DEVICE_SIZE); + printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); + printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); } ao_mutex_put(&ao_flash_mutex); } -- cgit v1.2.3 From 327e5e782958e516a7b7a786ab6c176b0decb8b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:04:42 -0800 Subject: Dump config block from read/write config and flash_status commands --- src/ao_flash.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/ao_flash.c b/src/ao_flash.c index 01d371bb..0120382d 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -397,6 +397,30 @@ ao_ee_flush(void) __reentrant * Read/write the config block, which is in * the last block of the flash */ + +void +ao_ee_dump_config(void) __reentrant +{ + uint16_t i; + printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = FLASH_BLOCK_NONE; + ao_flash_fill(FLASH_CONFIG_BLOCK); + i = 0; + do { + if ((i & 7) == 0) { + if (i) + putchar('\n'); + ao_cmd_put16((uint16_t) i); + } + putchar(' '); + ao_cmd_put8(ao_flash_data[i]); + ++i; + } while (i < sizeof (ao_config)); + } ao_mutex_put(&ao_flash_mutex); +} + uint8_t ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant { @@ -410,6 +434,7 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); + ao_ee_dump_config(); return 1; } @@ -419,6 +444,7 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_setup(); if (len > FLASH_BLOCK_SIZE) return 0; + ao_ee_dump_config(); ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(buf, ao_flash_data, len); @@ -497,6 +523,7 @@ flash_status(void) __reentrant printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); } ao_mutex_put(&ao_flash_mutex); + ao_ee_dump_config(); } __code struct ao_cmds ao_flash_cmds[] = { -- cgit v1.2.3 From 05bb953830604721c9a49dd56256b86f3666b5ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:42:57 -0800 Subject: Don't set ao_flash_setup_done until we're actually done. Because we're accessing this variable outside of the mutex, we need to make sure it isn't set until the data it covers has been initialized. Signed-off-by: Keith Packard --- src/ao_flash.c | 4 +++- src/at45db161d.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ao_flash.c b/src/ao_flash.c index 0120382d..3ea3e40b 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -169,6 +169,7 @@ static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; static __data uint32_t ao_flash_device_size; static __data uint8_t ao_flash_block_shift; +static __data uint16_t ao_flash_block_size; static void ao_flash_setup(void) @@ -183,7 +184,6 @@ ao_flash_setup(void) ao_mutex_put(&ao_flash_mutex); return; } - ao_flash_setup_done = 1; /* On first use, check to see if the flash chip has * been programmed to use 512 byte pages. If not, do so. @@ -238,6 +238,8 @@ ao_flash_setup(void) default: ao_panic(AO_PANIC_FLASH); } + ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); } diff --git a/src/at45db161d.h b/src/at45db161d.h index 66869733..8b72e647 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -28,7 +28,7 @@ #define FLASH_BLOCK_SIZE_MAX 512 #define FLASH_BLOCK_SHIFT (ao_flash_block_shift) -#define FLASH_BLOCK_SIZE (1 << FLASH_BLOCK_SHIFT) +#define FLASH_BLOCK_SIZE (ao_flash_block_size) #define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) #define FLASH_DEVICE_SIZE (ao_flash_device_size) #define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) -- cgit v1.2.3 From a6082a8b4501ac4cb18584ace1f0c40e088e5484 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:57:29 -0800 Subject: Remove flash debugging printfs Signed-off-by: Keith Packard --- src/ao_flash.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/src/ao_flash.c b/src/ao_flash.c index 3ea3e40b..638e51e0 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -400,29 +400,6 @@ ao_ee_flush(void) __reentrant * the last block of the flash */ -void -ao_ee_dump_config(void) __reentrant -{ - uint16_t i; - printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = FLASH_BLOCK_NONE; - ao_flash_fill(FLASH_CONFIG_BLOCK); - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_cmd_put8(ao_flash_data[i]); - ++i; - } while (i < sizeof (ao_config)); - } ao_mutex_put(&ao_flash_mutex); -} - uint8_t ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant { @@ -430,13 +407,11 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant if (len > FLASH_BLOCK_SIZE) return 0; ao_mutex_get(&ao_flash_mutex); { - printf("FLASH_CONFIG_BLOCK: %d\n", FLASH_CONFIG_BLOCK); ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(ao_flash_data, buf, len); ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); - ao_ee_dump_config(); return 1; } @@ -446,7 +421,6 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_setup(); if (len > FLASH_BLOCK_SIZE) return 0; - ao_ee_dump_config(); ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(buf, ao_flash_data, len); @@ -509,6 +483,29 @@ flash_store(void) __reentrant ao_ee_flush(); } +void +ao_ee_dump_config(void) __reentrant +{ + uint16_t i; + printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = FLASH_BLOCK_NONE; + ao_flash_fill(FLASH_CONFIG_BLOCK); + i = 0; + do { + if ((i & 7) == 0) { + if (i) + putchar('\n'); + ao_cmd_put16((uint16_t) i); + } + putchar(' '); + ao_cmd_put8(ao_flash_data[i]); + ++i; + } while (i < sizeof (ao_config)); + } ao_mutex_put(&ao_flash_mutex); +} + static void flash_status(void) __reentrant { -- cgit v1.2.3 From 28346736a7799c0767e54511d9949cd61d35e471 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:57:48 -0800 Subject: Add simple gps dump command 'g' This just dumps out the data in a very simple format to verify the GPS receiver. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 361c77ce..2392dacf 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -410,8 +410,24 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); + printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); + printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Alt: %d\n", ao_gps_data.altitude); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); } -- cgit v1.2.3 From 0c2533be15858774ef9381aa8c8344356fd5b971 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 22:06:19 -0800 Subject: Force idle mode by shorting the SPI clock to ground at boot time. This allows you to override the flight mode detection code in case the accelerometer calibration is broken somehow. Hold the SPI clock shoted to ground until the LED comes on, then remove it. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_flight.c | 8 ++++++-- src/ao_telemetrum.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 1f27fe92..2c6eb2b9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -618,6 +618,7 @@ extern __pdata int16_t ao_ground_pres; extern __pdata int16_t ao_ground_accel; extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; +extern __xdata uint8_t ao_flight_force_idle; /* Flight thread */ void diff --git a/src/ao_flight.c b/src/ao_flight.c index f57573d0..e0fd97f2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -50,6 +50,8 @@ __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; __pdata int16_t ao_accel_2g; +__xdata uint8_t ao_flight_force_idle; + /* Accelerometer calibration * * We're sampling the accelerometer through a resistor divider which @@ -221,8 +223,10 @@ ao_flight(void) /* Go to pad state if the nose is pointing up */ ao_config_get(); - if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && - ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP) + if (ao_config.accel_plus_g != 0 && + ao_config.accel_minus_g != 0 && + ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + !ao_flight_force_idle) { /* Disable the USB controller in flight mode * to save power diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 0de3572a..89743837 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -29,10 +29,20 @@ main(void) { ao_clock_init(); + /* Turn on the red LED until the system is stable */ ao_led_init(AO_LED_RED); ao_led_on(AO_LED_RED); + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } ao_timer_init(); ao_adc_init(); ao_beep_init(); -- cgit v1.2.3 From 9856b7c4397afcecc8f541af9a83824e817b3612 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 10 Jan 2010 16:31:50 -0800 Subject: Switch to using internal cc1111 temperature sensor v0.2 has no temperature sensor, and several of the v0.1 boards didn't get a temperature sensor loaded. Use the internal temperature sensor on the cc1111 in all cases instead. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 8 ++++---- ao-tools/lib/cc-convert.c | 11 ++++++++++- src/ao_adc.c | 12 +++++++----- src/ao_convert.c | 10 +++++++++- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index 838899a7..505bcddc 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -127,10 +127,10 @@ aoview_state_derive(struct cc_telem *data, struct aostate *state) accel_counts_per_mss = ((data->accel_minus_g - data->accel_plus_g) / 2.0) / 9.80665; state->acceleration = (data->ground_accel - data->flight_accel) / accel_counts_per_mss; state->speed = data->flight_vel / (accel_counts_per_mss * 100.0); - state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; - state->drogue_sense = data->drogue / 32767.0 * 15.0; - state->main_sense = data->main / 32767.0 * 15.0; - state->battery = data->batt / 32767.0 * 5.0; + state->temperature = cc_thermometer_to_temperature(data->temp); + state->drogue_sense = cc_ignitor_to_voltage(data->drogue); + state->main_sense = cc_ignitor_to_voltage(data->main); + state->battery = cc_battery_to_voltage(data->batt); if (!strcmp(data->state, "pad")) { if (data->gps.gps_locked && data->gps.nsat >= 4) { state->npad++; diff --git a/ao-tools/lib/cc-convert.c b/ao-tools/lib/cc-convert.c index ac6962ba..8d6876a0 100644 --- a/ao-tools/lib/cc-convert.c +++ b/ao-tools/lib/cc-convert.c @@ -213,10 +213,19 @@ cc_accelerometer_to_acceleration(double accel, double ground_accel) return (ground_accel - accel) / count_per_mss; } +/* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + double cc_thermometer_to_temperature(double thermo) { - return ((thermo / 32767 * 3.3) - 0.5) / 0.01; + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; } double diff --git a/src/ao_adc.c b/src/ao_adc.c index b0bfceb1..2b972e6c 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -46,16 +46,18 @@ ao_adc_isr(void) interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); a[0] = ADCL; a[1] = ADCH; if (sequence < 5) { /* start next channel conversion */ - sequence++; - /* skip channel 2, we don't have a temp sensor on v0.2 */ - if (sequence == 2) - sequence++; - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; + /* v0.2 replaces external temp sensor with internal one */ + if (sequence == 1) + ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + else + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); diff --git a/src/ao_convert.c b/src/ao_convert.c index 57ed7370..f29ce9e9 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -49,7 +49,15 @@ ao_temp_to_dC(int16_t temp) __reentrant int16_t ret; ao_mutex_get(&ao_temp_mutex); - ret = (int16_t) ((temp >> 4) * 3300L / 2047L) - 500; + /* Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + * ≃ (value - 19791) * 1012 / 65536 + */ + ret = ((temp - 19791) * 1012L) >> 16; ao_mutex_put(&ao_temp_mutex); return ret; } -- cgit v1.2.3 From 2a6350149407c7d2e7d143906c40c5e331248aeb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Feb 2010 18:48:56 -0800 Subject: Missing ao_mutex_put in gps_dump --- src/ao_gps_skytraq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 2392dacf..0dd45c0c 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -418,6 +418,7 @@ gps_dump(void) __reentrant 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); + ao_mutex_put(&ao_gps_mutex); } __code struct ao_cmds ao_gps_cmds[] = { -- cgit v1.2.3 From f8967607b3dda0c0ce7afe8bb077da2da5ed3dcd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2010 00:24:56 -0800 Subject: Compute daytime using GPS as time base --- ao-tools/ao-postflight/ao-postflight.c | 114 +++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 11 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 48752d07..cbf9c047 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -185,6 +185,75 @@ static const char kml_footer[] = "\n" "\n"; +static unsigned +gps_daytime(struct cc_gpselt *gps) +{ + return ((gps->hour * 60 + + gps->minute) * 60 + + gps->second) * 1000; +} + +int +daytime_hour(unsigned daytime) +{ + return daytime / 1000 / 60 / 60; +} + +int +daytime_minute(unsigned daytime) +{ + return (daytime / 1000 / 60) % 60; +} + +int +daytime_second(unsigned daytime) +{ + return (daytime / 1000) % 60; +} + +int +daytime_millisecond(unsigned daytime) +{ + return daytime % 1000; +} + +static unsigned +compute_daytime_ms(double time, struct cc_gpsdata *gps) +{ + int i; + unsigned gps_start_daytime, gps_stop_daytime; + + if (time <= gps->data[0].time) { + gps_stop_daytime = gps_daytime(&gps->data[0]); + return gps_stop_daytime - (gps->data[0].time - time) * 10; + } + for (i = 0; i < gps->num - 1; i++) + if (time > gps->data[i].time) + break; + gps_start_daytime = gps_daytime(&gps->data[i]); + if (i == gps->num - 1) { + return gps_start_daytime + (time - gps->data[i].time) * 10; + } else { + unsigned gps_period_daytime; + double gps_period_time; + double time_since_start; + + gps_stop_daytime = gps_daytime(&gps->data[i + 1]); + + /* range of gps daytime values */ + gps_period_daytime = gps_stop_daytime - gps_start_daytime; + + /* range of gps time values */ + gps_period_time = gps->data[i+1].time - gps->data[i].time; + + /* sample time after first gps time */ + time_since_start = time - gps->data[i].time; + + return gps_start_daytime + + gps_period_daytime * time_since_start / gps_period_time; + } +} + static void analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, FILE *raw_file, char *plot_name, FILE *gps_file, FILE *kml_file) @@ -325,30 +394,49 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, int i; double *times; - fprintf(detail_file, "%9s %9s %9s %9s\n", - "time", "height", "speed", "accel"); + fprintf(detail_file, "%9s %9s %9s %9s %9s\n", + "time", "height", "speed", "accel", "daytime"); for (i = 0; i < cooked->pres_pos.num; i++) { - double time = (cooked->accel_accel.start + i * cooked->accel_accel.step - boost_start) / 100.0; + double clock_time = cooked->accel_accel.start + i * cooked->accel_accel.step; + double time = (clock_time - boost_start) / 100.0; double accel = cooked->accel_accel.data[i]; double pos = cooked->pres_pos.data[i]; double speed; + unsigned daytime; if (cooked->pres_pos.start + cooked->pres_pos.step * i < apogee) speed = cooked->accel_speed.data[i]; else speed = cooked->pres_speed.data[i]; - fprintf(detail_file, "%9.2f %9.2f %9.2f %9.2f\n", - time, pos, speed, accel); + if (f->gps.num) + daytime = compute_daytime_ms(clock_time, &f->gps); + else + daytime = 0; + fprintf(detail_file, "%9.2f %9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n", + time, pos, speed, accel, + daytime_hour(daytime), + daytime_minute(daytime), + daytime_second(daytime), + daytime_millisecond(daytime)); } } if (raw_file) { - fprintf(raw_file, "%9s %9s %9s\n", - "time", "height", "accel"); + fprintf(raw_file, "%9s %9s %9s %9s\n", + "time", "height", "accel", "daytime"); for (i = 0; i < cooked->pres.num; i++) { double time = cooked->pres.data[i].time; double pres = cooked->pres.data[i].value; double accel = cooked->accel.data[i].value; - fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f\n", - time, pres, accel); + unsigned daytime; + if (f->gps.num) + daytime = compute_daytime_ms(time, &f->gps); + else + daytime = 0; + fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n", + time, pres, accel, + daytime_hour(daytime), + daytime_minute(daytime), + daytime_second(daytime), + daytime_millisecond(daytime)); } } if (gps_file || kml_file) { @@ -357,7 +445,8 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, double baro = 0.0; if (gps_file) - fprintf(gps_file, "%9s %12s %12s %9s %8s %5s\n", + fprintf(gps_file, "%2s %2s %2s %9s %12s %12s %9s %8s %5s\n", + "hr", "mn", "sc", "time", "lat", "lon", "alt", "baro", "nsat"); if (kml_file) fprintf(kml_file, "%s", kml_header); @@ -386,7 +475,10 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, baro = cooked->pres_pos.data[baro_pos]; } if (gps_file) - fprintf(gps_file, "%12.7f %12.7f %12.7f %7.1f %7.1f", + fprintf(gps_file, "%2d %2d %2d %12.7f %12.7f %12.7f %7.1f %7.1f", + f->gps.data[i].hour, + f->gps.data[i].minute, + f->gps.data[i].second, (f->gps.data[i].time - boost_start) / 100.0, f->gps.data[i].lat, f->gps.data[i].lon, -- cgit v1.2.3 From c83615567b4567f3dc45a7f7b894943b45fbb65c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Feb 2010 00:25:22 -0800 Subject: Pull in a bit more data for filtering the start of the boost --- ao-tools/lib/cc-process.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ao-tools/lib/cc-process.c b/ao-tools/lib/cc-process.c index 5c1acc6b..c756b570 100644 --- a/ao-tools/lib/cc-process.c +++ b/ao-tools/lib/cc-process.c @@ -70,7 +70,7 @@ cc_flight_cook(struct cc_flightraw *raw) */ for (i = 0; i < raw->state.num; i++) { if (!start_set && raw->state.data[i].value > ao_flight_pad) { - flight_start = raw->state.data[i].time; + flight_start = raw->state.data[i].time - 10; start_set = 1; } if (!stop_set && raw->state.data[i].value > ao_flight_main) { @@ -79,7 +79,7 @@ cc_flight_cook(struct cc_flightraw *raw) } } - if (!start_set) + if (!start_set || flight_start < raw->accel.data[0].time) flight_start = raw->accel.data[0].time; if (stop_set) { for (i = 0; i < raw->accel.num - 1; i++) { @@ -101,8 +101,8 @@ cc_flight_cook(struct cc_flightraw *raw) accel_speed = cc_timedata_integrate(&cooked->accel, flight_start - 10, flight_stop); accel_pos = cc_timedata_integrate(accel_speed, flight_start - 10, flight_stop); -#define ACCEL_OMEGA_PASS (2 * M_PI * 5 / 100) -#define ACCEL_OMEGA_STOP (2 * M_PI * 8 / 100) +#define ACCEL_OMEGA_PASS (2 * M_PI * 20 / 100) +#define ACCEL_OMEGA_STOP (2 * M_PI * 30 / 100) #define BARO_OMEGA_PASS (2 * M_PI * .5 / 100) #define BARO_OMEGA_STOP (2 * M_PI * 1 / 100) #define FILTER_ERROR (1e-8) -- cgit v1.2.3 From 876e9a10b9096ead85fbe08ec9a6a0329cf7cbd4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Feb 2010 16:42:27 -0800 Subject: Log GPS data on pad after boost detect. This wakes up the two GPS reporting tasks and gets them to report out any existing GPS data to the log file. To make sure the timestamps in that GPS data are accurate, this also records GPS time on receipt of the GPS data instead of when that is logged. Signed-off-by: Keith Packard --- src/ao.h | 2 ++ src/ao_flight.c | 4 ++++ src/ao_gps_report.c | 4 ++-- src/ao_gps_sirf.c | 2 ++ src/ao_gps_skytraq.c | 4 ++++ src/ao_gps_test.c | 2 ++ src/ao_gps_test_skytraq.c | 2 ++ 7 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 2c6eb2b9..d6be2223 100644 --- a/src/ao.h +++ b/src/ao.h @@ -731,6 +731,8 @@ ao_serial_init(void); #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +extern __xdata uint16_t ao_gps_tick; + struct ao_gps_data { uint8_t year; uint8_t month; diff --git a/src/ao_flight.c b/src/ao_flight.c index e0fd97f2..980c16be 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -289,6 +289,10 @@ ao_flight(void) /* disable RDF beacon */ ao_rdf_set(0); + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index e3e27523..cceb79ff 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -33,7 +33,7 @@ ao_gps_report(void) if (!(gps_data.flags & AO_GPS_VALID)) continue; - gps_log.tick = ao_time(); + gps_log.tick = ao_gps_tick; gps_log.type = AO_LOG_GPS_TIME; gps_log.u.gps_time.hour = gps_data.hour; gps_log.u.gps_time.minute = gps_data.minute; @@ -71,13 +71,13 @@ ao_gps_tracking_report(void) for (;;) { ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); + gps_log.tick = ao_gps_tick; memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) continue; - gps_log.tick = ao_time(); gps_log.type = AO_LOG_GPS_SAT; for (c = 0; c < n; c++) if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 64b66c95..a6167e6b 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -20,6 +20,7 @@ #endif __xdata uint8_t ao_gps_mutex; +__xdata uint16_t ao_gps_tick; __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; @@ -390,6 +391,7 @@ ao_gps(void) __reentrant switch (i) { case 41: ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_time(); ao_gps_data.hour = ao_sirf_data.utc_hour; ao_gps_data.minute = ao_sirf_data.utc_minute; ao_gps_data.second = ao_sirf_data.utc_second / 1000; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 0dd45c0c..ae8c7ef7 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -28,9 +28,11 @@ static __xdata char ao_gps_char; static __xdata uint8_t ao_gps_cksum; static __xdata uint8_t ao_gps_error; +__xdata uint16_t ao_gps_tick; __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; +static __xdata uint16_t ao_gps_next_tick; static __xdata struct ao_gps_data ao_gps_next; static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; @@ -248,6 +250,7 @@ ao_gps(void) __reentrant * *66 checksum */ + ao_gps_next_tick = ao_time(); ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; ao_gps_next.hour = ao_gps_decimal(2); ao_gps_next.minute = ao_gps_decimal(2); @@ -297,6 +300,7 @@ ao_gps(void) __reentrant ao_gps_error = 1; if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index fddfedfd..cdcc6f4c 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -400,6 +400,8 @@ ao_serial_set_speed(uint8_t speed) tcflush(fd, TCIFLUSH); } +#define ao_time() 0 + #include "ao_gps_print.c" #include "ao_gps_sirf.c" diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index ccf96378..7fa10eaa 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -408,6 +408,8 @@ ao_serial_set_speed(uint8_t speed) tcflush(fd, TCIFLUSH); } +#define ao_time() 0 + #include "ao_gps_print.c" #include "ao_gps_skytraq.c" -- cgit v1.2.3 From fd0a42e0e96dcb8ecc9e999f70bcf70692692af9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:21:07 -0800 Subject: Change barometer conversion code to shrink conversion table --- src/altitude.h | 2180 +++---------------------------------------------- src/ao_convert.c | 50 +- src/ao_convert_test.c | 75 ++ src/make-altitude | 103 ++- 4 files changed, 340 insertions(+), 2068 deletions(-) create mode 100644 src/ao_convert_test.c diff --git a/src/altitude.h b/src/altitude.h index 5225df4d..a278bbc6 100644 --- a/src/altitude.h +++ b/src/altitude.h @@ -1,2048 +1,132 @@ - 15837, /* 10.56 kPa 0 count */ - 15804, /* 10.61 kPa 1 count */ - 15772, /* 10.66 kPa 2 count */ - 15740, /* 10.72 kPa 3 count */ - 15708, /* 10.77 kPa 4 count */ - 15676, /* 10.83 kPa 5 count */ - 15644, /* 10.88 kPa 6 count */ - 15613, /* 10.94 kPa 7 count */ - 15581, /* 10.99 kPa 8 count */ - 15550, /* 11.04 kPa 9 count */ - 15519, /* 11.10 kPa 10 count */ - 15488, /* 11.15 kPa 11 count */ - 15457, /* 11.21 kPa 12 count */ - 15426, /* 11.26 kPa 13 count */ - 15396, /* 11.32 kPa 14 count */ - 15366, /* 11.37 kPa 15 count */ - 15335, /* 11.42 kPa 16 count */ - 15305, /* 11.48 kPa 17 count */ - 15275, /* 11.53 kPa 18 count */ - 15246, /* 11.59 kPa 19 count */ - 15216, /* 11.64 kPa 20 count */ - 15187, /* 11.70 kPa 21 count */ - 15157, /* 11.75 kPa 22 count */ - 15128, /* 11.80 kPa 23 count */ - 15099, /* 11.86 kPa 24 count */ - 15070, /* 11.91 kPa 25 count */ - 15041, /* 11.97 kPa 26 count */ - 15012, /* 12.02 kPa 27 count */ - 14984, /* 12.08 kPa 28 count */ - 14955, /* 12.13 kPa 29 count */ - 14927, /* 12.18 kPa 30 count */ - 14899, /* 12.24 kPa 31 count */ - 14871, /* 12.29 kPa 32 count */ - 14843, /* 12.35 kPa 33 count */ - 14815, /* 12.40 kPa 34 count */ - 14787, /* 12.46 kPa 35 count */ - 14760, /* 12.51 kPa 36 count */ - 14732, /* 12.56 kPa 37 count */ - 14705, /* 12.62 kPa 38 count */ - 14678, /* 12.67 kPa 39 count */ - 14651, /* 12.73 kPa 40 count */ - 14624, /* 12.78 kPa 41 count */ - 14597, /* 12.84 kPa 42 count */ - 14570, /* 12.89 kPa 43 count */ - 14543, /* 12.94 kPa 44 count */ - 14517, /* 13.00 kPa 45 count */ - 14490, /* 13.05 kPa 46 count */ - 14464, /* 13.11 kPa 47 count */ - 14438, /* 13.16 kPa 48 count */ - 14412, /* 13.22 kPa 49 count */ - 14386, /* 13.27 kPa 50 count */ - 14360, /* 13.32 kPa 51 count */ - 14334, /* 13.38 kPa 52 count */ - 14308, /* 13.43 kPa 53 count */ - 14283, /* 13.49 kPa 54 count */ - 14257, /* 13.54 kPa 55 count */ - 14232, /* 13.60 kPa 56 count */ - 14207, /* 13.65 kPa 57 count */ - 14182, /* 13.70 kPa 58 count */ - 14156, /* 13.76 kPa 59 count */ - 14132, /* 13.81 kPa 60 count */ - 14107, /* 13.87 kPa 61 count */ - 14082, /* 13.92 kPa 62 count */ - 14057, /* 13.98 kPa 63 count */ - 14033, /* 14.03 kPa 64 count */ - 14008, /* 14.08 kPa 65 count */ - 13984, /* 14.14 kPa 66 count */ - 13959, /* 14.19 kPa 67 count */ - 13935, /* 14.25 kPa 68 count */ - 13911, /* 14.30 kPa 69 count */ - 13887, /* 14.36 kPa 70 count */ - 13863, /* 14.41 kPa 71 count */ - 13839, /* 14.46 kPa 72 count */ - 13816, /* 14.52 kPa 73 count */ - 13792, /* 14.57 kPa 74 count */ - 13768, /* 14.63 kPa 75 count */ - 13745, /* 14.68 kPa 76 count */ - 13721, /* 14.74 kPa 77 count */ - 13698, /* 14.79 kPa 78 count */ - 13675, /* 14.84 kPa 79 count */ - 13652, /* 14.90 kPa 80 count */ - 13629, /* 14.95 kPa 81 count */ - 13606, /* 15.01 kPa 82 count */ - 13583, /* 15.06 kPa 83 count */ - 13560, /* 15.12 kPa 84 count */ - 13537, /* 15.17 kPa 85 count */ - 13515, /* 15.22 kPa 86 count */ - 13492, /* 15.28 kPa 87 count */ - 13470, /* 15.33 kPa 88 count */ - 13447, /* 15.39 kPa 89 count */ - 13425, /* 15.44 kPa 90 count */ - 13403, /* 15.50 kPa 91 count */ - 13380, /* 15.55 kPa 92 count */ - 13358, /* 15.60 kPa 93 count */ - 13336, /* 15.66 kPa 94 count */ - 13314, /* 15.71 kPa 95 count */ - 13292, /* 15.77 kPa 96 count */ - 13271, /* 15.82 kPa 97 count */ - 13249, /* 15.87 kPa 98 count */ - 13227, /* 15.93 kPa 99 count */ - 13206, /* 15.98 kPa 100 count */ - 13184, /* 16.04 kPa 101 count */ - 13163, /* 16.09 kPa 102 count */ - 13141, /* 16.15 kPa 103 count */ - 13120, /* 16.20 kPa 104 count */ - 13099, /* 16.25 kPa 105 count */ - 13078, /* 16.31 kPa 106 count */ - 13057, /* 16.36 kPa 107 count */ - 13036, /* 16.42 kPa 108 count */ - 13015, /* 16.47 kPa 109 count */ - 12994, /* 16.53 kPa 110 count */ - 12973, /* 16.58 kPa 111 count */ - 12952, /* 16.63 kPa 112 count */ - 12932, /* 16.69 kPa 113 count */ - 12911, /* 16.74 kPa 114 count */ - 12891, /* 16.80 kPa 115 count */ - 12870, /* 16.85 kPa 116 count */ - 12850, /* 16.91 kPa 117 count */ - 12829, /* 16.96 kPa 118 count */ - 12809, /* 17.01 kPa 119 count */ - 12789, /* 17.07 kPa 120 count */ - 12769, /* 17.12 kPa 121 count */ - 12749, /* 17.18 kPa 122 count */ - 12729, /* 17.23 kPa 123 count */ - 12709, /* 17.29 kPa 124 count */ - 12689, /* 17.34 kPa 125 count */ - 12669, /* 17.39 kPa 126 count */ - 12649, /* 17.45 kPa 127 count */ - 12630, /* 17.50 kPa 128 count */ - 12610, /* 17.56 kPa 129 count */ - 12590, /* 17.61 kPa 130 count */ - 12571, /* 17.67 kPa 131 count */ - 12551, /* 17.72 kPa 132 count */ - 12532, /* 17.77 kPa 133 count */ - 12513, /* 17.83 kPa 134 count */ - 12493, /* 17.88 kPa 135 count */ - 12474, /* 17.94 kPa 136 count */ - 12455, /* 17.99 kPa 137 count */ - 12436, /* 18.05 kPa 138 count */ - 12417, /* 18.10 kPa 139 count */ - 12398, /* 18.15 kPa 140 count */ - 12379, /* 18.21 kPa 141 count */ - 12360, /* 18.26 kPa 142 count */ - 12341, /* 18.32 kPa 143 count */ - 12323, /* 18.37 kPa 144 count */ - 12304, /* 18.43 kPa 145 count */ - 12285, /* 18.48 kPa 146 count */ - 12267, /* 18.53 kPa 147 count */ - 12248, /* 18.59 kPa 148 count */ - 12230, /* 18.64 kPa 149 count */ - 12211, /* 18.70 kPa 150 count */ - 12193, /* 18.75 kPa 151 count */ - 12174, /* 18.81 kPa 152 count */ - 12156, /* 18.86 kPa 153 count */ - 12138, /* 18.91 kPa 154 count */ - 12120, /* 18.97 kPa 155 count */ - 12102, /* 19.02 kPa 156 count */ - 12084, /* 19.08 kPa 157 count */ - 12065, /* 19.13 kPa 158 count */ - 12048, /* 19.19 kPa 159 count */ - 12030, /* 19.24 kPa 160 count */ - 12012, /* 19.29 kPa 161 count */ - 11994, /* 19.35 kPa 162 count */ - 11976, /* 19.40 kPa 163 count */ - 11958, /* 19.46 kPa 164 count */ - 11941, /* 19.51 kPa 165 count */ - 11923, /* 19.57 kPa 166 count */ - 11906, /* 19.62 kPa 167 count */ - 11888, /* 19.67 kPa 168 count */ - 11871, /* 19.73 kPa 169 count */ - 11853, /* 19.78 kPa 170 count */ - 11836, /* 19.84 kPa 171 count */ - 11818, /* 19.89 kPa 172 count */ - 11801, /* 19.95 kPa 173 count */ - 11784, /* 20.00 kPa 174 count */ - 11767, /* 20.05 kPa 175 count */ - 11750, /* 20.11 kPa 176 count */ - 11733, /* 20.16 kPa 177 count */ - 11715, /* 20.22 kPa 178 count */ - 11698, /* 20.27 kPa 179 count */ - 11682, /* 20.33 kPa 180 count */ - 11665, /* 20.38 kPa 181 count */ - 11648, /* 20.43 kPa 182 count */ - 11631, /* 20.49 kPa 183 count */ - 11614, /* 20.54 kPa 184 count */ - 11597, /* 20.60 kPa 185 count */ - 11581, /* 20.65 kPa 186 count */ - 11564, /* 20.71 kPa 187 count */ - 11547, /* 20.76 kPa 188 count */ - 11531, /* 20.81 kPa 189 count */ - 11514, /* 20.87 kPa 190 count */ - 11498, /* 20.92 kPa 191 count */ - 11481, /* 20.98 kPa 192 count */ - 11465, /* 21.03 kPa 193 count */ - 11449, /* 21.09 kPa 194 count */ - 11432, /* 21.14 kPa 195 count */ - 11416, /* 21.19 kPa 196 count */ - 11400, /* 21.25 kPa 197 count */ - 11384, /* 21.30 kPa 198 count */ - 11368, /* 21.36 kPa 199 count */ - 11352, /* 21.41 kPa 200 count */ - 11336, /* 21.47 kPa 201 count */ - 11319, /* 21.52 kPa 202 count */ - 11304, /* 21.57 kPa 203 count */ - 11288, /* 21.63 kPa 204 count */ - 11272, /* 21.68 kPa 205 count */ - 11256, /* 21.74 kPa 206 count */ - 11240, /* 21.79 kPa 207 count */ - 11224, /* 21.85 kPa 208 count */ - 11208, /* 21.90 kPa 209 count */ - 11193, /* 21.95 kPa 210 count */ - 11177, /* 22.01 kPa 211 count */ - 11162, /* 22.06 kPa 212 count */ - 11146, /* 22.12 kPa 213 count */ - 11130, /* 22.17 kPa 214 count */ - 11115, /* 22.23 kPa 215 count */ - 11099, /* 22.28 kPa 216 count */ - 11084, /* 22.33 kPa 217 count */ - 11069, /* 22.39 kPa 218 count */ - 11053, /* 22.44 kPa 219 count */ - 11038, /* 22.50 kPa 220 count */ - 11023, /* 22.55 kPa 221 count */ - 11007, /* 22.61 kPa 222 count */ - 10992, /* 22.66 kPa 223 count */ - 10977, /* 22.71 kPa 224 count */ - 10962, /* 22.77 kPa 225 count */ - 10947, /* 22.82 kPa 226 count */ - 10932, /* 22.88 kPa 227 count */ - 10917, /* 22.93 kPa 228 count */ - 10902, /* 22.99 kPa 229 count */ - 10887, /* 23.04 kPa 230 count */ - 10872, /* 23.09 kPa 231 count */ - 10857, /* 23.15 kPa 232 count */ - 10842, /* 23.20 kPa 233 count */ - 10827, /* 23.26 kPa 234 count */ - 10812, /* 23.31 kPa 235 count */ - 10797, /* 23.37 kPa 236 count */ - 10782, /* 23.42 kPa 237 count */ - 10768, /* 23.47 kPa 238 count */ - 10753, /* 23.53 kPa 239 count */ - 10738, /* 23.58 kPa 240 count */ - 10723, /* 23.64 kPa 241 count */ - 10709, /* 23.69 kPa 242 count */ - 10694, /* 23.75 kPa 243 count */ - 10679, /* 23.80 kPa 244 count */ - 10665, /* 23.85 kPa 245 count */ - 10650, /* 23.91 kPa 246 count */ - 10636, /* 23.96 kPa 247 count */ - 10621, /* 24.02 kPa 248 count */ - 10607, /* 24.07 kPa 249 count */ - 10592, /* 24.13 kPa 250 count */ - 10578, /* 24.18 kPa 251 count */ - 10563, /* 24.23 kPa 252 count */ - 10549, /* 24.29 kPa 253 count */ - 10535, /* 24.34 kPa 254 count */ - 10520, /* 24.40 kPa 255 count */ - 10506, /* 24.45 kPa 256 count */ - 10492, /* 24.51 kPa 257 count */ - 10478, /* 24.56 kPa 258 count */ - 10463, /* 24.61 kPa 259 count */ - 10449, /* 24.67 kPa 260 count */ - 10435, /* 24.72 kPa 261 count */ - 10421, /* 24.78 kPa 262 count */ - 10407, /* 24.83 kPa 263 count */ - 10393, /* 24.89 kPa 264 count */ - 10379, /* 24.94 kPa 265 count */ - 10364, /* 24.99 kPa 266 count */ - 10350, /* 25.05 kPa 267 count */ - 10336, /* 25.10 kPa 268 count */ - 10322, /* 25.16 kPa 269 count */ - 10309, /* 25.21 kPa 270 count */ - 10295, /* 25.27 kPa 271 count */ - 10281, /* 25.32 kPa 272 count */ - 10267, /* 25.37 kPa 273 count */ - 10253, /* 25.43 kPa 274 count */ - 10239, /* 25.48 kPa 275 count */ - 10225, /* 25.54 kPa 276 count */ - 10212, /* 25.59 kPa 277 count */ - 10198, /* 25.65 kPa 278 count */ - 10184, /* 25.70 kPa 279 count */ - 10170, /* 25.75 kPa 280 count */ - 10157, /* 25.81 kPa 281 count */ - 10143, /* 25.86 kPa 282 count */ - 10129, /* 25.92 kPa 283 count */ - 10116, /* 25.97 kPa 284 count */ - 10102, /* 26.03 kPa 285 count */ - 10089, /* 26.08 kPa 286 count */ - 10075, /* 26.13 kPa 287 count */ - 10062, /* 26.19 kPa 288 count */ - 10048, /* 26.24 kPa 289 count */ - 10035, /* 26.30 kPa 290 count */ - 10021, /* 26.35 kPa 291 count */ - 10008, /* 26.41 kPa 292 count */ - 9994, /* 26.46 kPa 293 count */ - 9981, /* 26.51 kPa 294 count */ - 9967, /* 26.57 kPa 295 count */ - 9954, /* 26.62 kPa 296 count */ - 9941, /* 26.68 kPa 297 count */ - 9928, /* 26.73 kPa 298 count */ - 9914, /* 26.79 kPa 299 count */ - 9901, /* 26.84 kPa 300 count */ - 9888, /* 26.89 kPa 301 count */ - 9875, /* 26.95 kPa 302 count */ - 9861, /* 27.00 kPa 303 count */ - 9848, /* 27.06 kPa 304 count */ - 9835, /* 27.11 kPa 305 count */ - 9822, /* 27.17 kPa 306 count */ - 9809, /* 27.22 kPa 307 count */ - 9796, /* 27.27 kPa 308 count */ - 9783, /* 27.33 kPa 309 count */ - 9770, /* 27.38 kPa 310 count */ - 9757, /* 27.44 kPa 311 count */ - 9744, /* 27.49 kPa 312 count */ - 9731, /* 27.55 kPa 313 count */ - 9718, /* 27.60 kPa 314 count */ - 9705, /* 27.65 kPa 315 count */ - 9692, /* 27.71 kPa 316 count */ - 9679, /* 27.76 kPa 317 count */ - 9666, /* 27.82 kPa 318 count */ - 9653, /* 27.87 kPa 319 count */ - 9640, /* 27.93 kPa 320 count */ - 9627, /* 27.98 kPa 321 count */ - 9615, /* 28.03 kPa 322 count */ - 9602, /* 28.09 kPa 323 count */ - 9589, /* 28.14 kPa 324 count */ - 9576, /* 28.20 kPa 325 count */ - 9564, /* 28.25 kPa 326 count */ - 9551, /* 28.31 kPa 327 count */ - 9538, /* 28.36 kPa 328 count */ - 9526, /* 28.41 kPa 329 count */ - 9513, /* 28.47 kPa 330 count */ - 9500, /* 28.52 kPa 331 count */ - 9488, /* 28.58 kPa 332 count */ - 9475, /* 28.63 kPa 333 count */ - 9463, /* 28.69 kPa 334 count */ - 9450, /* 28.74 kPa 335 count */ - 9438, /* 28.79 kPa 336 count */ - 9425, /* 28.85 kPa 337 count */ - 9413, /* 28.90 kPa 338 count */ - 9400, /* 28.96 kPa 339 count */ - 9388, /* 29.01 kPa 340 count */ - 9375, /* 29.07 kPa 341 count */ - 9363, /* 29.12 kPa 342 count */ - 9350, /* 29.17 kPa 343 count */ - 9338, /* 29.23 kPa 344 count */ - 9326, /* 29.28 kPa 345 count */ - 9313, /* 29.34 kPa 346 count */ - 9301, /* 29.39 kPa 347 count */ - 9289, /* 29.44 kPa 348 count */ - 9276, /* 29.50 kPa 349 count */ - 9264, /* 29.55 kPa 350 count */ - 9252, /* 29.61 kPa 351 count */ - 9240, /* 29.66 kPa 352 count */ - 9227, /* 29.72 kPa 353 count */ - 9215, /* 29.77 kPa 354 count */ - 9203, /* 29.82 kPa 355 count */ - 9191, /* 29.88 kPa 356 count */ - 9179, /* 29.93 kPa 357 count */ - 9167, /* 29.99 kPa 358 count */ - 9155, /* 30.04 kPa 359 count */ - 9142, /* 30.10 kPa 360 count */ - 9130, /* 30.15 kPa 361 count */ - 9118, /* 30.20 kPa 362 count */ - 9106, /* 30.26 kPa 363 count */ - 9094, /* 30.31 kPa 364 count */ - 9082, /* 30.37 kPa 365 count */ - 9070, /* 30.42 kPa 366 count */ - 9058, /* 30.48 kPa 367 count */ - 9046, /* 30.53 kPa 368 count */ - 9035, /* 30.58 kPa 369 count */ - 9023, /* 30.64 kPa 370 count */ - 9011, /* 30.69 kPa 371 count */ - 8999, /* 30.75 kPa 372 count */ - 8987, /* 30.80 kPa 373 count */ - 8975, /* 30.86 kPa 374 count */ - 8963, /* 30.91 kPa 375 count */ - 8952, /* 30.96 kPa 376 count */ - 8940, /* 31.02 kPa 377 count */ - 8928, /* 31.07 kPa 378 count */ - 8916, /* 31.13 kPa 379 count */ - 8904, /* 31.18 kPa 380 count */ - 8893, /* 31.24 kPa 381 count */ - 8881, /* 31.29 kPa 382 count */ - 8869, /* 31.34 kPa 383 count */ - 8858, /* 31.40 kPa 384 count */ - 8846, /* 31.45 kPa 385 count */ - 8834, /* 31.51 kPa 386 count */ - 8823, /* 31.56 kPa 387 count */ - 8811, /* 31.62 kPa 388 count */ - 8800, /* 31.67 kPa 389 count */ - 8788, /* 31.72 kPa 390 count */ - 8776, /* 31.78 kPa 391 count */ - 8765, /* 31.83 kPa 392 count */ - 8753, /* 31.89 kPa 393 count */ - 8742, /* 31.94 kPa 394 count */ - 8730, /* 32.00 kPa 395 count */ - 8719, /* 32.05 kPa 396 count */ - 8707, /* 32.10 kPa 397 count */ - 8696, /* 32.16 kPa 398 count */ - 8684, /* 32.21 kPa 399 count */ - 8673, /* 32.27 kPa 400 count */ - 8662, /* 32.32 kPa 401 count */ - 8650, /* 32.38 kPa 402 count */ - 8639, /* 32.43 kPa 403 count */ - 8628, /* 32.48 kPa 404 count */ - 8616, /* 32.54 kPa 405 count */ - 8605, /* 32.59 kPa 406 count */ - 8594, /* 32.65 kPa 407 count */ - 8582, /* 32.70 kPa 408 count */ - 8571, /* 32.76 kPa 409 count */ - 8560, /* 32.81 kPa 410 count */ - 8548, /* 32.86 kPa 411 count */ - 8537, /* 32.92 kPa 412 count */ - 8526, /* 32.97 kPa 413 count */ - 8515, /* 33.03 kPa 414 count */ - 8504, /* 33.08 kPa 415 count */ - 8492, /* 33.14 kPa 416 count */ - 8481, /* 33.19 kPa 417 count */ - 8470, /* 33.24 kPa 418 count */ - 8459, /* 33.30 kPa 419 count */ - 8448, /* 33.35 kPa 420 count */ - 8437, /* 33.41 kPa 421 count */ - 8426, /* 33.46 kPa 422 count */ - 8415, /* 33.52 kPa 423 count */ - 8403, /* 33.57 kPa 424 count */ - 8392, /* 33.62 kPa 425 count */ - 8381, /* 33.68 kPa 426 count */ - 8370, /* 33.73 kPa 427 count */ - 8359, /* 33.79 kPa 428 count */ - 8348, /* 33.84 kPa 429 count */ - 8337, /* 33.90 kPa 430 count */ - 8326, /* 33.95 kPa 431 count */ - 8316, /* 34.00 kPa 432 count */ - 8305, /* 34.06 kPa 433 count */ - 8294, /* 34.11 kPa 434 count */ - 8283, /* 34.17 kPa 435 count */ - 8272, /* 34.22 kPa 436 count */ - 8261, /* 34.28 kPa 437 count */ - 8250, /* 34.33 kPa 438 count */ - 8239, /* 34.38 kPa 439 count */ - 8228, /* 34.44 kPa 440 count */ - 8218, /* 34.49 kPa 441 count */ - 8207, /* 34.55 kPa 442 count */ - 8196, /* 34.60 kPa 443 count */ - 8185, /* 34.66 kPa 444 count */ - 8175, /* 34.71 kPa 445 count */ - 8164, /* 34.76 kPa 446 count */ - 8153, /* 34.82 kPa 447 count */ - 8142, /* 34.87 kPa 448 count */ - 8132, /* 34.93 kPa 449 count */ - 8121, /* 34.98 kPa 450 count */ - 8110, /* 35.04 kPa 451 count */ - 8100, /* 35.09 kPa 452 count */ - 8089, /* 35.14 kPa 453 count */ - 8078, /* 35.20 kPa 454 count */ - 8068, /* 35.25 kPa 455 count */ - 8057, /* 35.31 kPa 456 count */ - 8046, /* 35.36 kPa 457 count */ - 8036, /* 35.42 kPa 458 count */ - 8025, /* 35.47 kPa 459 count */ - 8015, /* 35.52 kPa 460 count */ - 8004, /* 35.58 kPa 461 count */ - 7994, /* 35.63 kPa 462 count */ - 7983, /* 35.69 kPa 463 count */ - 7973, /* 35.74 kPa 464 count */ - 7962, /* 35.80 kPa 465 count */ - 7952, /* 35.85 kPa 466 count */ - 7941, /* 35.90 kPa 467 count */ - 7931, /* 35.96 kPa 468 count */ - 7920, /* 36.01 kPa 469 count */ - 7910, /* 36.07 kPa 470 count */ - 7899, /* 36.12 kPa 471 count */ - 7889, /* 36.18 kPa 472 count */ - 7879, /* 36.23 kPa 473 count */ - 7868, /* 36.28 kPa 474 count */ - 7858, /* 36.34 kPa 475 count */ - 7847, /* 36.39 kPa 476 count */ - 7837, /* 36.45 kPa 477 count */ - 7827, /* 36.50 kPa 478 count */ - 7816, /* 36.56 kPa 479 count */ - 7806, /* 36.61 kPa 480 count */ - 7796, /* 36.66 kPa 481 count */ - 7785, /* 36.72 kPa 482 count */ - 7775, /* 36.77 kPa 483 count */ - 7765, /* 36.83 kPa 484 count */ - 7755, /* 36.88 kPa 485 count */ - 7744, /* 36.94 kPa 486 count */ - 7734, /* 36.99 kPa 487 count */ - 7724, /* 37.04 kPa 488 count */ - 7714, /* 37.10 kPa 489 count */ - 7704, /* 37.15 kPa 490 count */ - 7693, /* 37.21 kPa 491 count */ - 7683, /* 37.26 kPa 492 count */ - 7673, /* 37.32 kPa 493 count */ - 7663, /* 37.37 kPa 494 count */ - 7653, /* 37.42 kPa 495 count */ - 7643, /* 37.48 kPa 496 count */ - 7633, /* 37.53 kPa 497 count */ - 7623, /* 37.59 kPa 498 count */ - 7613, /* 37.64 kPa 499 count */ - 7602, /* 37.70 kPa 500 count */ - 7592, /* 37.75 kPa 501 count */ - 7582, /* 37.80 kPa 502 count */ - 7572, /* 37.86 kPa 503 count */ - 7562, /* 37.91 kPa 504 count */ - 7552, /* 37.97 kPa 505 count */ - 7542, /* 38.02 kPa 506 count */ - 7532, /* 38.08 kPa 507 count */ - 7522, /* 38.13 kPa 508 count */ - 7512, /* 38.18 kPa 509 count */ - 7502, /* 38.24 kPa 510 count */ - 7492, /* 38.29 kPa 511 count */ - 7483, /* 38.35 kPa 512 count */ - 7473, /* 38.40 kPa 513 count */ - 7463, /* 38.46 kPa 514 count */ - 7453, /* 38.51 kPa 515 count */ - 7443, /* 38.56 kPa 516 count */ - 7433, /* 38.62 kPa 517 count */ - 7423, /* 38.67 kPa 518 count */ - 7413, /* 38.73 kPa 519 count */ - 7403, /* 38.78 kPa 520 count */ - 7394, /* 38.84 kPa 521 count */ - 7384, /* 38.89 kPa 522 count */ - 7374, /* 38.94 kPa 523 count */ - 7364, /* 39.00 kPa 524 count */ - 7354, /* 39.05 kPa 525 count */ - 7345, /* 39.11 kPa 526 count */ - 7335, /* 39.16 kPa 527 count */ - 7325, /* 39.22 kPa 528 count */ - 7315, /* 39.27 kPa 529 count */ - 7306, /* 39.32 kPa 530 count */ - 7296, /* 39.38 kPa 531 count */ - 7286, /* 39.43 kPa 532 count */ - 7277, /* 39.49 kPa 533 count */ - 7267, /* 39.54 kPa 534 count */ - 7257, /* 39.60 kPa 535 count */ - 7248, /* 39.65 kPa 536 count */ - 7238, /* 39.70 kPa 537 count */ - 7228, /* 39.76 kPa 538 count */ - 7219, /* 39.81 kPa 539 count */ - 7209, /* 39.87 kPa 540 count */ - 7199, /* 39.92 kPa 541 count */ - 7190, /* 39.98 kPa 542 count */ - 7180, /* 40.03 kPa 543 count */ - 7171, /* 40.08 kPa 544 count */ - 7161, /* 40.14 kPa 545 count */ - 7152, /* 40.19 kPa 546 count */ - 7142, /* 40.25 kPa 547 count */ - 7132, /* 40.30 kPa 548 count */ - 7123, /* 40.36 kPa 549 count */ - 7113, /* 40.41 kPa 550 count */ - 7104, /* 40.46 kPa 551 count */ - 7094, /* 40.52 kPa 552 count */ - 7085, /* 40.57 kPa 553 count */ - 7075, /* 40.63 kPa 554 count */ - 7066, /* 40.68 kPa 555 count */ - 7056, /* 40.74 kPa 556 count */ - 7047, /* 40.79 kPa 557 count */ - 7038, /* 40.84 kPa 558 count */ - 7028, /* 40.90 kPa 559 count */ - 7019, /* 40.95 kPa 560 count */ - 7009, /* 41.01 kPa 561 count */ - 7000, /* 41.06 kPa 562 count */ - 6991, /* 41.12 kPa 563 count */ - 6981, /* 41.17 kPa 564 count */ - 6972, /* 41.22 kPa 565 count */ - 6962, /* 41.28 kPa 566 count */ - 6953, /* 41.33 kPa 567 count */ - 6944, /* 41.39 kPa 568 count */ - 6934, /* 41.44 kPa 569 count */ - 6925, /* 41.50 kPa 570 count */ - 6916, /* 41.55 kPa 571 count */ - 6907, /* 41.60 kPa 572 count */ - 6897, /* 41.66 kPa 573 count */ - 6888, /* 41.71 kPa 574 count */ - 6879, /* 41.77 kPa 575 count */ - 6869, /* 41.82 kPa 576 count */ - 6860, /* 41.88 kPa 577 count */ - 6851, /* 41.93 kPa 578 count */ - 6842, /* 41.98 kPa 579 count */ - 6833, /* 42.04 kPa 580 count */ - 6823, /* 42.09 kPa 581 count */ - 6814, /* 42.15 kPa 582 count */ - 6805, /* 42.20 kPa 583 count */ - 6796, /* 42.26 kPa 584 count */ - 6787, /* 42.31 kPa 585 count */ - 6777, /* 42.36 kPa 586 count */ - 6768, /* 42.42 kPa 587 count */ - 6759, /* 42.47 kPa 588 count */ - 6750, /* 42.53 kPa 589 count */ - 6741, /* 42.58 kPa 590 count */ - 6732, /* 42.64 kPa 591 count */ - 6723, /* 42.69 kPa 592 count */ - 6714, /* 42.74 kPa 593 count */ - 6705, /* 42.80 kPa 594 count */ - 6695, /* 42.85 kPa 595 count */ - 6686, /* 42.91 kPa 596 count */ - 6677, /* 42.96 kPa 597 count */ - 6668, /* 43.01 kPa 598 count */ - 6659, /* 43.07 kPa 599 count */ - 6650, /* 43.12 kPa 600 count */ - 6641, /* 43.18 kPa 601 count */ - 6632, /* 43.23 kPa 602 count */ - 6623, /* 43.29 kPa 603 count */ - 6614, /* 43.34 kPa 604 count */ - 6605, /* 43.39 kPa 605 count */ - 6596, /* 43.45 kPa 606 count */ - 6587, /* 43.50 kPa 607 count */ - 6578, /* 43.56 kPa 608 count */ - 6569, /* 43.61 kPa 609 count */ - 6560, /* 43.67 kPa 610 count */ - 6552, /* 43.72 kPa 611 count */ - 6543, /* 43.77 kPa 612 count */ - 6534, /* 43.83 kPa 613 count */ - 6525, /* 43.88 kPa 614 count */ - 6516, /* 43.94 kPa 615 count */ - 6507, /* 43.99 kPa 616 count */ - 6498, /* 44.05 kPa 617 count */ - 6489, /* 44.10 kPa 618 count */ - 6480, /* 44.15 kPa 619 count */ - 6472, /* 44.21 kPa 620 count */ - 6463, /* 44.26 kPa 621 count */ - 6454, /* 44.32 kPa 622 count */ - 6445, /* 44.37 kPa 623 count */ - 6436, /* 44.43 kPa 624 count */ - 6427, /* 44.48 kPa 625 count */ - 6419, /* 44.53 kPa 626 count */ - 6410, /* 44.59 kPa 627 count */ - 6401, /* 44.64 kPa 628 count */ - 6392, /* 44.70 kPa 629 count */ - 6384, /* 44.75 kPa 630 count */ - 6375, /* 44.81 kPa 631 count */ - 6366, /* 44.86 kPa 632 count */ - 6357, /* 44.91 kPa 633 count */ - 6349, /* 44.97 kPa 634 count */ - 6340, /* 45.02 kPa 635 count */ - 6331, /* 45.08 kPa 636 count */ - 6322, /* 45.13 kPa 637 count */ - 6314, /* 45.19 kPa 638 count */ - 6305, /* 45.24 kPa 639 count */ - 6296, /* 45.29 kPa 640 count */ - 6288, /* 45.35 kPa 641 count */ - 6279, /* 45.40 kPa 642 count */ - 6270, /* 45.46 kPa 643 count */ - 6262, /* 45.51 kPa 644 count */ - 6253, /* 45.57 kPa 645 count */ - 6245, /* 45.62 kPa 646 count */ - 6236, /* 45.67 kPa 647 count */ - 6227, /* 45.73 kPa 648 count */ - 6219, /* 45.78 kPa 649 count */ - 6210, /* 45.84 kPa 650 count */ - 6202, /* 45.89 kPa 651 count */ - 6193, /* 45.95 kPa 652 count */ - 6184, /* 46.00 kPa 653 count */ - 6176, /* 46.05 kPa 654 count */ - 6167, /* 46.11 kPa 655 count */ - 6159, /* 46.16 kPa 656 count */ - 6150, /* 46.22 kPa 657 count */ - 6142, /* 46.27 kPa 658 count */ - 6133, /* 46.33 kPa 659 count */ - 6125, /* 46.38 kPa 660 count */ - 6116, /* 46.43 kPa 661 count */ - 6108, /* 46.49 kPa 662 count */ - 6099, /* 46.54 kPa 663 count */ - 6091, /* 46.60 kPa 664 count */ - 6082, /* 46.65 kPa 665 count */ - 6074, /* 46.71 kPa 666 count */ - 6065, /* 46.76 kPa 667 count */ - 6057, /* 46.81 kPa 668 count */ - 6048, /* 46.87 kPa 669 count */ - 6040, /* 46.92 kPa 670 count */ - 6032, /* 46.98 kPa 671 count */ - 6023, /* 47.03 kPa 672 count */ - 6015, /* 47.09 kPa 673 count */ - 6006, /* 47.14 kPa 674 count */ - 5998, /* 47.19 kPa 675 count */ - 5990, /* 47.25 kPa 676 count */ - 5981, /* 47.30 kPa 677 count */ - 5973, /* 47.36 kPa 678 count */ - 5964, /* 47.41 kPa 679 count */ - 5956, /* 47.47 kPa 680 count */ - 5948, /* 47.52 kPa 681 count */ - 5939, /* 47.57 kPa 682 count */ - 5931, /* 47.63 kPa 683 count */ - 5923, /* 47.68 kPa 684 count */ - 5914, /* 47.74 kPa 685 count */ - 5906, /* 47.79 kPa 686 count */ - 5898, /* 47.85 kPa 687 count */ - 5890, /* 47.90 kPa 688 count */ - 5881, /* 47.95 kPa 689 count */ - 5873, /* 48.01 kPa 690 count */ - 5865, /* 48.06 kPa 691 count */ - 5856, /* 48.12 kPa 692 count */ - 5848, /* 48.17 kPa 693 count */ - 5840, /* 48.23 kPa 694 count */ - 5832, /* 48.28 kPa 695 count */ - 5823, /* 48.33 kPa 696 count */ - 5815, /* 48.39 kPa 697 count */ - 5807, /* 48.44 kPa 698 count */ - 5799, /* 48.50 kPa 699 count */ - 5791, /* 48.55 kPa 700 count */ - 5782, /* 48.61 kPa 701 count */ - 5774, /* 48.66 kPa 702 count */ - 5766, /* 48.71 kPa 703 count */ - 5758, /* 48.77 kPa 704 count */ - 5750, /* 48.82 kPa 705 count */ - 5742, /* 48.88 kPa 706 count */ - 5733, /* 48.93 kPa 707 count */ - 5725, /* 48.99 kPa 708 count */ - 5717, /* 49.04 kPa 709 count */ - 5709, /* 49.09 kPa 710 count */ - 5701, /* 49.15 kPa 711 count */ - 5693, /* 49.20 kPa 712 count */ - 5685, /* 49.26 kPa 713 count */ - 5677, /* 49.31 kPa 714 count */ - 5668, /* 49.37 kPa 715 count */ - 5660, /* 49.42 kPa 716 count */ - 5652, /* 49.47 kPa 717 count */ - 5644, /* 49.53 kPa 718 count */ - 5636, /* 49.58 kPa 719 count */ - 5628, /* 49.64 kPa 720 count */ - 5620, /* 49.69 kPa 721 count */ - 5612, /* 49.75 kPa 722 count */ - 5604, /* 49.80 kPa 723 count */ - 5596, /* 49.85 kPa 724 count */ - 5588, /* 49.91 kPa 725 count */ - 5580, /* 49.96 kPa 726 count */ - 5572, /* 50.02 kPa 727 count */ - 5564, /* 50.07 kPa 728 count */ - 5556, /* 50.13 kPa 729 count */ - 5548, /* 50.18 kPa 730 count */ - 5540, /* 50.23 kPa 731 count */ - 5532, /* 50.29 kPa 732 count */ - 5524, /* 50.34 kPa 733 count */ - 5516, /* 50.40 kPa 734 count */ - 5508, /* 50.45 kPa 735 count */ - 5500, /* 50.51 kPa 736 count */ - 5492, /* 50.56 kPa 737 count */ - 5484, /* 50.61 kPa 738 count */ - 5476, /* 50.67 kPa 739 count */ - 5468, /* 50.72 kPa 740 count */ - 5461, /* 50.78 kPa 741 count */ - 5453, /* 50.83 kPa 742 count */ - 5445, /* 50.89 kPa 743 count */ - 5437, /* 50.94 kPa 744 count */ - 5429, /* 50.99 kPa 745 count */ - 5421, /* 51.05 kPa 746 count */ - 5413, /* 51.10 kPa 747 count */ - 5405, /* 51.16 kPa 748 count */ - 5398, /* 51.21 kPa 749 count */ - 5390, /* 51.27 kPa 750 count */ - 5382, /* 51.32 kPa 751 count */ - 5374, /* 51.37 kPa 752 count */ - 5366, /* 51.43 kPa 753 count */ - 5358, /* 51.48 kPa 754 count */ - 5351, /* 51.54 kPa 755 count */ - 5343, /* 51.59 kPa 756 count */ - 5335, /* 51.65 kPa 757 count */ - 5327, /* 51.70 kPa 758 count */ - 5319, /* 51.75 kPa 759 count */ - 5312, /* 51.81 kPa 760 count */ - 5304, /* 51.86 kPa 761 count */ - 5296, /* 51.92 kPa 762 count */ - 5288, /* 51.97 kPa 763 count */ - 5281, /* 52.03 kPa 764 count */ - 5273, /* 52.08 kPa 765 count */ - 5265, /* 52.13 kPa 766 count */ - 5257, /* 52.19 kPa 767 count */ - 5250, /* 52.24 kPa 768 count */ - 5242, /* 52.30 kPa 769 count */ - 5234, /* 52.35 kPa 770 count */ - 5226, /* 52.41 kPa 771 count */ - 5219, /* 52.46 kPa 772 count */ - 5211, /* 52.51 kPa 773 count */ - 5203, /* 52.57 kPa 774 count */ - 5196, /* 52.62 kPa 775 count */ - 5188, /* 52.68 kPa 776 count */ - 5180, /* 52.73 kPa 777 count */ - 5173, /* 52.79 kPa 778 count */ - 5165, /* 52.84 kPa 779 count */ - 5157, /* 52.89 kPa 780 count */ - 5150, /* 52.95 kPa 781 count */ - 5142, /* 53.00 kPa 782 count */ - 5134, /* 53.06 kPa 783 count */ - 5127, /* 53.11 kPa 784 count */ - 5119, /* 53.17 kPa 785 count */ - 5112, /* 53.22 kPa 786 count */ - 5104, /* 53.27 kPa 787 count */ - 5096, /* 53.33 kPa 788 count */ - 5089, /* 53.38 kPa 789 count */ - 5081, /* 53.44 kPa 790 count */ - 5074, /* 53.49 kPa 791 count */ - 5066, /* 53.55 kPa 792 count */ - 5058, /* 53.60 kPa 793 count */ - 5051, /* 53.65 kPa 794 count */ - 5043, /* 53.71 kPa 795 count */ - 5036, /* 53.76 kPa 796 count */ - 5028, /* 53.82 kPa 797 count */ - 5021, /* 53.87 kPa 798 count */ - 5013, /* 53.93 kPa 799 count */ - 5006, /* 53.98 kPa 800 count */ - 4998, /* 54.03 kPa 801 count */ - 4991, /* 54.09 kPa 802 count */ - 4983, /* 54.14 kPa 803 count */ - 4976, /* 54.20 kPa 804 count */ - 4968, /* 54.25 kPa 805 count */ - 4961, /* 54.31 kPa 806 count */ - 4953, /* 54.36 kPa 807 count */ - 4946, /* 54.41 kPa 808 count */ - 4938, /* 54.47 kPa 809 count */ - 4931, /* 54.52 kPa 810 count */ - 4923, /* 54.58 kPa 811 count */ - 4916, /* 54.63 kPa 812 count */ - 4908, /* 54.69 kPa 813 count */ - 4901, /* 54.74 kPa 814 count */ - 4893, /* 54.79 kPa 815 count */ - 4886, /* 54.85 kPa 816 count */ - 4879, /* 54.90 kPa 817 count */ - 4871, /* 54.96 kPa 818 count */ - 4864, /* 55.01 kPa 819 count */ - 4856, /* 55.07 kPa 820 count */ - 4849, /* 55.12 kPa 821 count */ - 4842, /* 55.17 kPa 822 count */ - 4834, /* 55.23 kPa 823 count */ - 4827, /* 55.28 kPa 824 count */ - 4819, /* 55.34 kPa 825 count */ - 4812, /* 55.39 kPa 826 count */ - 4805, /* 55.45 kPa 827 count */ - 4797, /* 55.50 kPa 828 count */ - 4790, /* 55.55 kPa 829 count */ - 4783, /* 55.61 kPa 830 count */ - 4775, /* 55.66 kPa 831 count */ - 4768, /* 55.72 kPa 832 count */ - 4761, /* 55.77 kPa 833 count */ - 4753, /* 55.83 kPa 834 count */ - 4746, /* 55.88 kPa 835 count */ - 4739, /* 55.93 kPa 836 count */ - 4731, /* 55.99 kPa 837 count */ - 4724, /* 56.04 kPa 838 count */ - 4717, /* 56.10 kPa 839 count */ - 4709, /* 56.15 kPa 840 count */ - 4702, /* 56.21 kPa 841 count */ - 4695, /* 56.26 kPa 842 count */ - 4688, /* 56.31 kPa 843 count */ - 4680, /* 56.37 kPa 844 count */ - 4673, /* 56.42 kPa 845 count */ - 4666, /* 56.48 kPa 846 count */ - 4659, /* 56.53 kPa 847 count */ - 4651, /* 56.58 kPa 848 count */ - 4644, /* 56.64 kPa 849 count */ - 4637, /* 56.69 kPa 850 count */ - 4630, /* 56.75 kPa 851 count */ - 4622, /* 56.80 kPa 852 count */ - 4615, /* 56.86 kPa 853 count */ - 4608, /* 56.91 kPa 854 count */ - 4601, /* 56.96 kPa 855 count */ - 4594, /* 57.02 kPa 856 count */ - 4586, /* 57.07 kPa 857 count */ - 4579, /* 57.13 kPa 858 count */ - 4572, /* 57.18 kPa 859 count */ - 4565, /* 57.24 kPa 860 count */ - 4558, /* 57.29 kPa 861 count */ - 4550, /* 57.34 kPa 862 count */ - 4543, /* 57.40 kPa 863 count */ - 4536, /* 57.45 kPa 864 count */ - 4529, /* 57.51 kPa 865 count */ - 4522, /* 57.56 kPa 866 count */ - 4515, /* 57.62 kPa 867 count */ - 4508, /* 57.67 kPa 868 count */ - 4500, /* 57.72 kPa 869 count */ - 4493, /* 57.78 kPa 870 count */ - 4486, /* 57.83 kPa 871 count */ - 4479, /* 57.89 kPa 872 count */ - 4472, /* 57.94 kPa 873 count */ - 4465, /* 58.00 kPa 874 count */ - 4458, /* 58.05 kPa 875 count */ - 4451, /* 58.10 kPa 876 count */ - 4444, /* 58.16 kPa 877 count */ - 4437, /* 58.21 kPa 878 count */ - 4429, /* 58.27 kPa 879 count */ - 4422, /* 58.32 kPa 880 count */ - 4415, /* 58.38 kPa 881 count */ - 4408, /* 58.43 kPa 882 count */ - 4401, /* 58.48 kPa 883 count */ - 4394, /* 58.54 kPa 884 count */ - 4387, /* 58.59 kPa 885 count */ - 4380, /* 58.65 kPa 886 count */ - 4373, /* 58.70 kPa 887 count */ - 4366, /* 58.76 kPa 888 count */ - 4359, /* 58.81 kPa 889 count */ - 4352, /* 58.86 kPa 890 count */ - 4345, /* 58.92 kPa 891 count */ - 4338, /* 58.97 kPa 892 count */ - 4331, /* 59.03 kPa 893 count */ - 4324, /* 59.08 kPa 894 count */ - 4317, /* 59.14 kPa 895 count */ - 4310, /* 59.19 kPa 896 count */ - 4303, /* 59.24 kPa 897 count */ - 4296, /* 59.30 kPa 898 count */ - 4289, /* 59.35 kPa 899 count */ - 4282, /* 59.41 kPa 900 count */ - 4275, /* 59.46 kPa 901 count */ - 4268, /* 59.52 kPa 902 count */ - 4261, /* 59.57 kPa 903 count */ - 4254, /* 59.62 kPa 904 count */ - 4247, /* 59.68 kPa 905 count */ - 4240, /* 59.73 kPa 906 count */ - 4234, /* 59.79 kPa 907 count */ - 4227, /* 59.84 kPa 908 count */ - 4220, /* 59.90 kPa 909 count */ - 4213, /* 59.95 kPa 910 count */ - 4206, /* 60.00 kPa 911 count */ - 4199, /* 60.06 kPa 912 count */ - 4192, /* 60.11 kPa 913 count */ - 4185, /* 60.17 kPa 914 count */ - 4178, /* 60.22 kPa 915 count */ - 4171, /* 60.28 kPa 916 count */ - 4164, /* 60.33 kPa 917 count */ - 4158, /* 60.38 kPa 918 count */ - 4151, /* 60.44 kPa 919 count */ - 4144, /* 60.49 kPa 920 count */ - 4137, /* 60.55 kPa 921 count */ - 4130, /* 60.60 kPa 922 count */ - 4123, /* 60.66 kPa 923 count */ - 4116, /* 60.71 kPa 924 count */ - 4110, /* 60.76 kPa 925 count */ - 4103, /* 60.82 kPa 926 count */ - 4096, /* 60.87 kPa 927 count */ - 4089, /* 60.93 kPa 928 count */ - 4082, /* 60.98 kPa 929 count */ - 4076, /* 61.04 kPa 930 count */ - 4069, /* 61.09 kPa 931 count */ - 4062, /* 61.14 kPa 932 count */ - 4055, /* 61.20 kPa 933 count */ - 4048, /* 61.25 kPa 934 count */ - 4042, /* 61.31 kPa 935 count */ - 4035, /* 61.36 kPa 936 count */ - 4028, /* 61.42 kPa 937 count */ - 4021, /* 61.47 kPa 938 count */ - 4014, /* 61.52 kPa 939 count */ - 4008, /* 61.58 kPa 940 count */ - 4001, /* 61.63 kPa 941 count */ - 3994, /* 61.69 kPa 942 count */ - 3987, /* 61.74 kPa 943 count */ - 3981, /* 61.80 kPa 944 count */ - 3974, /* 61.85 kPa 945 count */ - 3967, /* 61.90 kPa 946 count */ - 3960, /* 61.96 kPa 947 count */ - 3954, /* 62.01 kPa 948 count */ - 3947, /* 62.07 kPa 949 count */ - 3940, /* 62.12 kPa 950 count */ - 3934, /* 62.18 kPa 951 count */ - 3927, /* 62.23 kPa 952 count */ - 3920, /* 62.28 kPa 953 count */ - 3913, /* 62.34 kPa 954 count */ - 3907, /* 62.39 kPa 955 count */ - 3900, /* 62.45 kPa 956 count */ - 3893, /* 62.50 kPa 957 count */ - 3887, /* 62.56 kPa 958 count */ - 3880, /* 62.61 kPa 959 count */ - 3873, /* 62.66 kPa 960 count */ - 3867, /* 62.72 kPa 961 count */ - 3860, /* 62.77 kPa 962 count */ - 3853, /* 62.83 kPa 963 count */ - 3847, /* 62.88 kPa 964 count */ - 3840, /* 62.94 kPa 965 count */ - 3833, /* 62.99 kPa 966 count */ - 3827, /* 63.04 kPa 967 count */ - 3820, /* 63.10 kPa 968 count */ - 3814, /* 63.15 kPa 969 count */ - 3807, /* 63.21 kPa 970 count */ - 3800, /* 63.26 kPa 971 count */ - 3794, /* 63.32 kPa 972 count */ - 3787, /* 63.37 kPa 973 count */ - 3780, /* 63.42 kPa 974 count */ - 3774, /* 63.48 kPa 975 count */ - 3767, /* 63.53 kPa 976 count */ - 3761, /* 63.59 kPa 977 count */ - 3754, /* 63.64 kPa 978 count */ - 3748, /* 63.70 kPa 979 count */ - 3741, /* 63.75 kPa 980 count */ - 3734, /* 63.80 kPa 981 count */ - 3728, /* 63.86 kPa 982 count */ - 3721, /* 63.91 kPa 983 count */ - 3715, /* 63.97 kPa 984 count */ - 3708, /* 64.02 kPa 985 count */ - 3702, /* 64.08 kPa 986 count */ - 3695, /* 64.13 kPa 987 count */ - 3688, /* 64.18 kPa 988 count */ - 3682, /* 64.24 kPa 989 count */ - 3675, /* 64.29 kPa 990 count */ - 3669, /* 64.35 kPa 991 count */ - 3662, /* 64.40 kPa 992 count */ - 3656, /* 64.46 kPa 993 count */ - 3649, /* 64.51 kPa 994 count */ - 3643, /* 64.56 kPa 995 count */ - 3636, /* 64.62 kPa 996 count */ - 3630, /* 64.67 kPa 997 count */ - 3623, /* 64.73 kPa 998 count */ - 3617, /* 64.78 kPa 999 count */ - 3610, /* 64.84 kPa 1000 count */ - 3604, /* 64.89 kPa 1001 count */ - 3597, /* 64.94 kPa 1002 count */ - 3591, /* 65.00 kPa 1003 count */ - 3584, /* 65.05 kPa 1004 count */ - 3578, /* 65.11 kPa 1005 count */ - 3571, /* 65.16 kPa 1006 count */ - 3565, /* 65.22 kPa 1007 count */ - 3559, /* 65.27 kPa 1008 count */ - 3552, /* 65.32 kPa 1009 count */ - 3546, /* 65.38 kPa 1010 count */ - 3539, /* 65.43 kPa 1011 count */ - 3533, /* 65.49 kPa 1012 count */ - 3526, /* 65.54 kPa 1013 count */ - 3520, /* 65.60 kPa 1014 count */ - 3514, /* 65.65 kPa 1015 count */ - 3507, /* 65.70 kPa 1016 count */ - 3501, /* 65.76 kPa 1017 count */ - 3494, /* 65.81 kPa 1018 count */ - 3488, /* 65.87 kPa 1019 count */ - 3481, /* 65.92 kPa 1020 count */ - 3475, /* 65.98 kPa 1021 count */ - 3469, /* 66.03 kPa 1022 count */ - 3462, /* 66.08 kPa 1023 count */ - 3456, /* 66.14 kPa 1024 count */ - 3450, /* 66.19 kPa 1025 count */ - 3443, /* 66.25 kPa 1026 count */ - 3437, /* 66.30 kPa 1027 count */ - 3430, /* 66.36 kPa 1028 count */ - 3424, /* 66.41 kPa 1029 count */ - 3418, /* 66.46 kPa 1030 count */ - 3411, /* 66.52 kPa 1031 count */ - 3405, /* 66.57 kPa 1032 count */ - 3399, /* 66.63 kPa 1033 count */ - 3392, /* 66.68 kPa 1034 count */ - 3386, /* 66.74 kPa 1035 count */ - 3380, /* 66.79 kPa 1036 count */ - 3373, /* 66.84 kPa 1037 count */ - 3367, /* 66.90 kPa 1038 count */ - 3361, /* 66.95 kPa 1039 count */ - 3354, /* 67.01 kPa 1040 count */ - 3348, /* 67.06 kPa 1041 count */ - 3342, /* 67.12 kPa 1042 count */ - 3335, /* 67.17 kPa 1043 count */ - 3329, /* 67.22 kPa 1044 count */ - 3323, /* 67.28 kPa 1045 count */ - 3316, /* 67.33 kPa 1046 count */ - 3310, /* 67.39 kPa 1047 count */ - 3304, /* 67.44 kPa 1048 count */ - 3298, /* 67.50 kPa 1049 count */ - 3291, /* 67.55 kPa 1050 count */ - 3285, /* 67.60 kPa 1051 count */ - 3279, /* 67.66 kPa 1052 count */ - 3273, /* 67.71 kPa 1053 count */ - 3266, /* 67.77 kPa 1054 count */ - 3260, /* 67.82 kPa 1055 count */ - 3254, /* 67.88 kPa 1056 count */ - 3248, /* 67.93 kPa 1057 count */ - 3241, /* 67.98 kPa 1058 count */ - 3235, /* 68.04 kPa 1059 count */ - 3229, /* 68.09 kPa 1060 count */ - 3223, /* 68.15 kPa 1061 count */ - 3216, /* 68.20 kPa 1062 count */ - 3210, /* 68.26 kPa 1063 count */ - 3204, /* 68.31 kPa 1064 count */ - 3198, /* 68.36 kPa 1065 count */ - 3191, /* 68.42 kPa 1066 count */ - 3185, /* 68.47 kPa 1067 count */ - 3179, /* 68.53 kPa 1068 count */ - 3173, /* 68.58 kPa 1069 count */ - 3167, /* 68.64 kPa 1070 count */ - 3160, /* 68.69 kPa 1071 count */ - 3154, /* 68.74 kPa 1072 count */ - 3148, /* 68.80 kPa 1073 count */ - 3142, /* 68.85 kPa 1074 count */ - 3136, /* 68.91 kPa 1075 count */ - 3130, /* 68.96 kPa 1076 count */ - 3123, /* 69.02 kPa 1077 count */ - 3117, /* 69.07 kPa 1078 count */ - 3111, /* 69.12 kPa 1079 count */ - 3105, /* 69.18 kPa 1080 count */ - 3099, /* 69.23 kPa 1081 count */ - 3093, /* 69.29 kPa 1082 count */ - 3087, /* 69.34 kPa 1083 count */ - 3080, /* 69.40 kPa 1084 count */ - 3074, /* 69.45 kPa 1085 count */ - 3068, /* 69.50 kPa 1086 count */ - 3062, /* 69.56 kPa 1087 count */ - 3056, /* 69.61 kPa 1088 count */ - 3050, /* 69.67 kPa 1089 count */ - 3044, /* 69.72 kPa 1090 count */ - 3037, /* 69.78 kPa 1091 count */ - 3031, /* 69.83 kPa 1092 count */ - 3025, /* 69.88 kPa 1093 count */ - 3019, /* 69.94 kPa 1094 count */ - 3013, /* 69.99 kPa 1095 count */ - 3007, /* 70.05 kPa 1096 count */ - 3001, /* 70.10 kPa 1097 count */ - 2995, /* 70.15 kPa 1098 count */ - 2989, /* 70.21 kPa 1099 count */ - 2983, /* 70.26 kPa 1100 count */ - 2977, /* 70.32 kPa 1101 count */ - 2970, /* 70.37 kPa 1102 count */ - 2964, /* 70.43 kPa 1103 count */ - 2958, /* 70.48 kPa 1104 count */ - 2952, /* 70.53 kPa 1105 count */ - 2946, /* 70.59 kPa 1106 count */ - 2940, /* 70.64 kPa 1107 count */ - 2934, /* 70.70 kPa 1108 count */ - 2928, /* 70.75 kPa 1109 count */ - 2922, /* 70.81 kPa 1110 count */ - 2916, /* 70.86 kPa 1111 count */ - 2910, /* 70.91 kPa 1112 count */ - 2904, /* 70.97 kPa 1113 count */ - 2898, /* 71.02 kPa 1114 count */ - 2892, /* 71.08 kPa 1115 count */ - 2886, /* 71.13 kPa 1116 count */ - 2880, /* 71.19 kPa 1117 count */ - 2874, /* 71.24 kPa 1118 count */ - 2868, /* 71.29 kPa 1119 count */ - 2862, /* 71.35 kPa 1120 count */ - 2856, /* 71.40 kPa 1121 count */ - 2850, /* 71.46 kPa 1122 count */ - 2844, /* 71.51 kPa 1123 count */ - 2838, /* 71.57 kPa 1124 count */ - 2832, /* 71.62 kPa 1125 count */ - 2826, /* 71.67 kPa 1126 count */ - 2820, /* 71.73 kPa 1127 count */ - 2814, /* 71.78 kPa 1128 count */ - 2808, /* 71.84 kPa 1129 count */ - 2802, /* 71.89 kPa 1130 count */ - 2796, /* 71.95 kPa 1131 count */ - 2790, /* 72.00 kPa 1132 count */ - 2784, /* 72.05 kPa 1133 count */ - 2778, /* 72.11 kPa 1134 count */ - 2772, /* 72.16 kPa 1135 count */ - 2766, /* 72.22 kPa 1136 count */ - 2760, /* 72.27 kPa 1137 count */ - 2754, /* 72.33 kPa 1138 count */ - 2748, /* 72.38 kPa 1139 count */ - 2743, /* 72.43 kPa 1140 count */ - 2737, /* 72.49 kPa 1141 count */ - 2731, /* 72.54 kPa 1142 count */ - 2725, /* 72.60 kPa 1143 count */ - 2719, /* 72.65 kPa 1144 count */ - 2713, /* 72.71 kPa 1145 count */ - 2707, /* 72.76 kPa 1146 count */ - 2701, /* 72.81 kPa 1147 count */ - 2695, /* 72.87 kPa 1148 count */ - 2689, /* 72.92 kPa 1149 count */ - 2683, /* 72.98 kPa 1150 count */ - 2678, /* 73.03 kPa 1151 count */ - 2672, /* 73.09 kPa 1152 count */ - 2666, /* 73.14 kPa 1153 count */ - 2660, /* 73.19 kPa 1154 count */ - 2654, /* 73.25 kPa 1155 count */ - 2648, /* 73.30 kPa 1156 count */ - 2642, /* 73.36 kPa 1157 count */ - 2636, /* 73.41 kPa 1158 count */ - 2631, /* 73.47 kPa 1159 count */ - 2625, /* 73.52 kPa 1160 count */ - 2619, /* 73.57 kPa 1161 count */ - 2613, /* 73.63 kPa 1162 count */ - 2607, /* 73.68 kPa 1163 count */ - 2601, /* 73.74 kPa 1164 count */ - 2595, /* 73.79 kPa 1165 count */ - 2590, /* 73.85 kPa 1166 count */ - 2584, /* 73.90 kPa 1167 count */ - 2578, /* 73.95 kPa 1168 count */ - 2572, /* 74.01 kPa 1169 count */ - 2566, /* 74.06 kPa 1170 count */ - 2560, /* 74.12 kPa 1171 count */ - 2555, /* 74.17 kPa 1172 count */ - 2549, /* 74.23 kPa 1173 count */ - 2543, /* 74.28 kPa 1174 count */ - 2537, /* 74.33 kPa 1175 count */ - 2531, /* 74.39 kPa 1176 count */ - 2526, /* 74.44 kPa 1177 count */ - 2520, /* 74.50 kPa 1178 count */ - 2514, /* 74.55 kPa 1179 count */ - 2508, /* 74.61 kPa 1180 count */ - 2502, /* 74.66 kPa 1181 count */ - 2497, /* 74.71 kPa 1182 count */ - 2491, /* 74.77 kPa 1183 count */ - 2485, /* 74.82 kPa 1184 count */ - 2479, /* 74.88 kPa 1185 count */ - 2473, /* 74.93 kPa 1186 count */ - 2468, /* 74.99 kPa 1187 count */ - 2462, /* 75.04 kPa 1188 count */ - 2456, /* 75.09 kPa 1189 count */ - 2450, /* 75.15 kPa 1190 count */ - 2445, /* 75.20 kPa 1191 count */ - 2439, /* 75.26 kPa 1192 count */ - 2433, /* 75.31 kPa 1193 count */ - 2427, /* 75.37 kPa 1194 count */ - 2422, /* 75.42 kPa 1195 count */ - 2416, /* 75.47 kPa 1196 count */ - 2410, /* 75.53 kPa 1197 count */ - 2405, /* 75.58 kPa 1198 count */ - 2399, /* 75.64 kPa 1199 count */ - 2393, /* 75.69 kPa 1200 count */ - 2387, /* 75.75 kPa 1201 count */ - 2382, /* 75.80 kPa 1202 count */ - 2376, /* 75.85 kPa 1203 count */ - 2370, /* 75.91 kPa 1204 count */ - 2364, /* 75.96 kPa 1205 count */ - 2359, /* 76.02 kPa 1206 count */ - 2353, /* 76.07 kPa 1207 count */ - 2347, /* 76.13 kPa 1208 count */ - 2342, /* 76.18 kPa 1209 count */ - 2336, /* 76.23 kPa 1210 count */ - 2330, /* 76.29 kPa 1211 count */ - 2325, /* 76.34 kPa 1212 count */ - 2319, /* 76.40 kPa 1213 count */ - 2313, /* 76.45 kPa 1214 count */ - 2308, /* 76.51 kPa 1215 count */ - 2302, /* 76.56 kPa 1216 count */ - 2296, /* 76.61 kPa 1217 count */ - 2291, /* 76.67 kPa 1218 count */ - 2285, /* 76.72 kPa 1219 count */ - 2279, /* 76.78 kPa 1220 count */ - 2274, /* 76.83 kPa 1221 count */ - 2268, /* 76.89 kPa 1222 count */ - 2262, /* 76.94 kPa 1223 count */ - 2257, /* 76.99 kPa 1224 count */ - 2251, /* 77.05 kPa 1225 count */ - 2245, /* 77.10 kPa 1226 count */ - 2240, /* 77.16 kPa 1227 count */ - 2234, /* 77.21 kPa 1228 count */ - 2228, /* 77.27 kPa 1229 count */ - 2223, /* 77.32 kPa 1230 count */ - 2217, /* 77.37 kPa 1231 count */ - 2212, /* 77.43 kPa 1232 count */ - 2206, /* 77.48 kPa 1233 count */ - 2200, /* 77.54 kPa 1234 count */ - 2195, /* 77.59 kPa 1235 count */ - 2189, /* 77.65 kPa 1236 count */ - 2184, /* 77.70 kPa 1237 count */ - 2178, /* 77.75 kPa 1238 count */ - 2172, /* 77.81 kPa 1239 count */ - 2167, /* 77.86 kPa 1240 count */ - 2161, /* 77.92 kPa 1241 count */ - 2156, /* 77.97 kPa 1242 count */ - 2150, /* 78.03 kPa 1243 count */ - 2144, /* 78.08 kPa 1244 count */ - 2139, /* 78.13 kPa 1245 count */ - 2133, /* 78.19 kPa 1246 count */ - 2128, /* 78.24 kPa 1247 count */ - 2122, /* 78.30 kPa 1248 count */ - 2117, /* 78.35 kPa 1249 count */ - 2111, /* 78.41 kPa 1250 count */ - 2105, /* 78.46 kPa 1251 count */ - 2100, /* 78.51 kPa 1252 count */ - 2094, /* 78.57 kPa 1253 count */ - 2089, /* 78.62 kPa 1254 count */ - 2083, /* 78.68 kPa 1255 count */ - 2078, /* 78.73 kPa 1256 count */ - 2072, /* 78.79 kPa 1257 count */ - 2067, /* 78.84 kPa 1258 count */ - 2061, /* 78.89 kPa 1259 count */ - 2056, /* 78.95 kPa 1260 count */ - 2050, /* 79.00 kPa 1261 count */ - 2045, /* 79.06 kPa 1262 count */ - 2039, /* 79.11 kPa 1263 count */ - 2033, /* 79.17 kPa 1264 count */ - 2028, /* 79.22 kPa 1265 count */ - 2022, /* 79.27 kPa 1266 count */ - 2017, /* 79.33 kPa 1267 count */ - 2011, /* 79.38 kPa 1268 count */ - 2006, /* 79.44 kPa 1269 count */ - 2000, /* 79.49 kPa 1270 count */ - 1995, /* 79.55 kPa 1271 count */ - 1989, /* 79.60 kPa 1272 count */ - 1984, /* 79.65 kPa 1273 count */ - 1978, /* 79.71 kPa 1274 count */ - 1973, /* 79.76 kPa 1275 count */ - 1967, /* 79.82 kPa 1276 count */ - 1962, /* 79.87 kPa 1277 count */ - 1957, /* 79.93 kPa 1278 count */ - 1951, /* 79.98 kPa 1279 count */ - 1946, /* 80.03 kPa 1280 count */ - 1940, /* 80.09 kPa 1281 count */ - 1935, /* 80.14 kPa 1282 count */ - 1929, /* 80.20 kPa 1283 count */ - 1924, /* 80.25 kPa 1284 count */ - 1918, /* 80.31 kPa 1285 count */ - 1913, /* 80.36 kPa 1286 count */ - 1907, /* 80.41 kPa 1287 count */ - 1902, /* 80.47 kPa 1288 count */ - 1896, /* 80.52 kPa 1289 count */ - 1891, /* 80.58 kPa 1290 count */ - 1886, /* 80.63 kPa 1291 count */ - 1880, /* 80.69 kPa 1292 count */ - 1875, /* 80.74 kPa 1293 count */ - 1869, /* 80.79 kPa 1294 count */ - 1864, /* 80.85 kPa 1295 count */ - 1858, /* 80.90 kPa 1296 count */ - 1853, /* 80.96 kPa 1297 count */ - 1848, /* 81.01 kPa 1298 count */ - 1842, /* 81.07 kPa 1299 count */ - 1837, /* 81.12 kPa 1300 count */ - 1831, /* 81.17 kPa 1301 count */ - 1826, /* 81.23 kPa 1302 count */ - 1821, /* 81.28 kPa 1303 count */ - 1815, /* 81.34 kPa 1304 count */ - 1810, /* 81.39 kPa 1305 count */ - 1804, /* 81.45 kPa 1306 count */ - 1799, /* 81.50 kPa 1307 count */ - 1794, /* 81.55 kPa 1308 count */ - 1788, /* 81.61 kPa 1309 count */ - 1783, /* 81.66 kPa 1310 count */ - 1777, /* 81.72 kPa 1311 count */ - 1772, /* 81.77 kPa 1312 count */ - 1767, /* 81.83 kPa 1313 count */ - 1761, /* 81.88 kPa 1314 count */ - 1756, /* 81.93 kPa 1315 count */ - 1751, /* 81.99 kPa 1316 count */ - 1745, /* 82.04 kPa 1317 count */ - 1740, /* 82.10 kPa 1318 count */ - 1735, /* 82.15 kPa 1319 count */ - 1729, /* 82.21 kPa 1320 count */ - 1724, /* 82.26 kPa 1321 count */ - 1718, /* 82.31 kPa 1322 count */ - 1713, /* 82.37 kPa 1323 count */ - 1708, /* 82.42 kPa 1324 count */ - 1702, /* 82.48 kPa 1325 count */ - 1697, /* 82.53 kPa 1326 count */ - 1692, /* 82.59 kPa 1327 count */ - 1686, /* 82.64 kPa 1328 count */ - 1681, /* 82.69 kPa 1329 count */ - 1676, /* 82.75 kPa 1330 count */ - 1670, /* 82.80 kPa 1331 count */ - 1665, /* 82.86 kPa 1332 count */ - 1660, /* 82.91 kPa 1333 count */ - 1655, /* 82.97 kPa 1334 count */ - 1649, /* 83.02 kPa 1335 count */ - 1644, /* 83.07 kPa 1336 count */ - 1639, /* 83.13 kPa 1337 count */ - 1633, /* 83.18 kPa 1338 count */ - 1628, /* 83.24 kPa 1339 count */ - 1623, /* 83.29 kPa 1340 count */ - 1617, /* 83.35 kPa 1341 count */ - 1612, /* 83.40 kPa 1342 count */ - 1607, /* 83.45 kPa 1343 count */ - 1602, /* 83.51 kPa 1344 count */ - 1596, /* 83.56 kPa 1345 count */ - 1591, /* 83.62 kPa 1346 count */ - 1586, /* 83.67 kPa 1347 count */ - 1580, /* 83.72 kPa 1348 count */ - 1575, /* 83.78 kPa 1349 count */ - 1570, /* 83.83 kPa 1350 count */ - 1565, /* 83.89 kPa 1351 count */ - 1559, /* 83.94 kPa 1352 count */ - 1554, /* 84.00 kPa 1353 count */ - 1549, /* 84.05 kPa 1354 count */ - 1544, /* 84.10 kPa 1355 count */ - 1538, /* 84.16 kPa 1356 count */ - 1533, /* 84.21 kPa 1357 count */ - 1528, /* 84.27 kPa 1358 count */ - 1523, /* 84.32 kPa 1359 count */ - 1517, /* 84.38 kPa 1360 count */ - 1512, /* 84.43 kPa 1361 count */ - 1507, /* 84.48 kPa 1362 count */ - 1502, /* 84.54 kPa 1363 count */ - 1496, /* 84.59 kPa 1364 count */ - 1491, /* 84.65 kPa 1365 count */ - 1486, /* 84.70 kPa 1366 count */ - 1481, /* 84.76 kPa 1367 count */ - 1475, /* 84.81 kPa 1368 count */ - 1470, /* 84.86 kPa 1369 count */ - 1465, /* 84.92 kPa 1370 count */ - 1460, /* 84.97 kPa 1371 count */ - 1455, /* 85.03 kPa 1372 count */ - 1449, /* 85.08 kPa 1373 count */ - 1444, /* 85.14 kPa 1374 count */ - 1439, /* 85.19 kPa 1375 count */ - 1434, /* 85.24 kPa 1376 count */ - 1429, /* 85.30 kPa 1377 count */ - 1423, /* 85.35 kPa 1378 count */ - 1418, /* 85.41 kPa 1379 count */ - 1413, /* 85.46 kPa 1380 count */ - 1408, /* 85.52 kPa 1381 count */ - 1403, /* 85.57 kPa 1382 count */ - 1398, /* 85.62 kPa 1383 count */ - 1392, /* 85.68 kPa 1384 count */ - 1387, /* 85.73 kPa 1385 count */ - 1382, /* 85.79 kPa 1386 count */ - 1377, /* 85.84 kPa 1387 count */ - 1372, /* 85.90 kPa 1388 count */ - 1366, /* 85.95 kPa 1389 count */ - 1361, /* 86.00 kPa 1390 count */ - 1356, /* 86.06 kPa 1391 count */ - 1351, /* 86.11 kPa 1392 count */ - 1346, /* 86.17 kPa 1393 count */ - 1341, /* 86.22 kPa 1394 count */ - 1336, /* 86.28 kPa 1395 count */ - 1330, /* 86.33 kPa 1396 count */ - 1325, /* 86.38 kPa 1397 count */ - 1320, /* 86.44 kPa 1398 count */ - 1315, /* 86.49 kPa 1399 count */ - 1310, /* 86.55 kPa 1400 count */ - 1305, /* 86.60 kPa 1401 count */ - 1300, /* 86.66 kPa 1402 count */ - 1294, /* 86.71 kPa 1403 count */ - 1289, /* 86.76 kPa 1404 count */ - 1284, /* 86.82 kPa 1405 count */ - 1279, /* 86.87 kPa 1406 count */ - 1274, /* 86.93 kPa 1407 count */ - 1269, /* 86.98 kPa 1408 count */ - 1264, /* 87.04 kPa 1409 count */ - 1259, /* 87.09 kPa 1410 count */ - 1254, /* 87.14 kPa 1411 count */ - 1248, /* 87.20 kPa 1412 count */ - 1243, /* 87.25 kPa 1413 count */ - 1238, /* 87.31 kPa 1414 count */ - 1233, /* 87.36 kPa 1415 count */ - 1228, /* 87.42 kPa 1416 count */ - 1223, /* 87.47 kPa 1417 count */ - 1218, /* 87.52 kPa 1418 count */ - 1213, /* 87.58 kPa 1419 count */ - 1208, /* 87.63 kPa 1420 count */ - 1203, /* 87.69 kPa 1421 count */ - 1198, /* 87.74 kPa 1422 count */ - 1192, /* 87.80 kPa 1423 count */ - 1187, /* 87.85 kPa 1424 count */ - 1182, /* 87.90 kPa 1425 count */ - 1177, /* 87.96 kPa 1426 count */ - 1172, /* 88.01 kPa 1427 count */ - 1167, /* 88.07 kPa 1428 count */ - 1162, /* 88.12 kPa 1429 count */ - 1157, /* 88.18 kPa 1430 count */ - 1152, /* 88.23 kPa 1431 count */ - 1147, /* 88.28 kPa 1432 count */ - 1142, /* 88.34 kPa 1433 count */ - 1137, /* 88.39 kPa 1434 count */ - 1132, /* 88.45 kPa 1435 count */ - 1127, /* 88.50 kPa 1436 count */ - 1122, /* 88.56 kPa 1437 count */ - 1117, /* 88.61 kPa 1438 count */ - 1112, /* 88.66 kPa 1439 count */ - 1107, /* 88.72 kPa 1440 count */ - 1102, /* 88.77 kPa 1441 count */ - 1097, /* 88.83 kPa 1442 count */ - 1091, /* 88.88 kPa 1443 count */ - 1086, /* 88.94 kPa 1444 count */ - 1081, /* 88.99 kPa 1445 count */ - 1076, /* 89.04 kPa 1446 count */ - 1071, /* 89.10 kPa 1447 count */ - 1066, /* 89.15 kPa 1448 count */ - 1061, /* 89.21 kPa 1449 count */ - 1056, /* 89.26 kPa 1450 count */ - 1051, /* 89.32 kPa 1451 count */ - 1046, /* 89.37 kPa 1452 count */ - 1041, /* 89.42 kPa 1453 count */ - 1036, /* 89.48 kPa 1454 count */ - 1031, /* 89.53 kPa 1455 count */ - 1026, /* 89.59 kPa 1456 count */ - 1021, /* 89.64 kPa 1457 count */ - 1016, /* 89.70 kPa 1458 count */ - 1011, /* 89.75 kPa 1459 count */ - 1006, /* 89.80 kPa 1460 count */ - 1001, /* 89.86 kPa 1461 count */ - 996, /* 89.91 kPa 1462 count */ - 992, /* 89.97 kPa 1463 count */ - 987, /* 90.02 kPa 1464 count */ - 982, /* 90.08 kPa 1465 count */ - 977, /* 90.13 kPa 1466 count */ - 972, /* 90.18 kPa 1467 count */ - 967, /* 90.24 kPa 1468 count */ - 962, /* 90.29 kPa 1469 count */ - 957, /* 90.35 kPa 1470 count */ - 952, /* 90.40 kPa 1471 count */ - 947, /* 90.46 kPa 1472 count */ - 942, /* 90.51 kPa 1473 count */ - 937, /* 90.56 kPa 1474 count */ - 932, /* 90.62 kPa 1475 count */ - 927, /* 90.67 kPa 1476 count */ - 922, /* 90.73 kPa 1477 count */ - 917, /* 90.78 kPa 1478 count */ - 912, /* 90.84 kPa 1479 count */ - 907, /* 90.89 kPa 1480 count */ - 902, /* 90.94 kPa 1481 count */ - 897, /* 91.00 kPa 1482 count */ - 892, /* 91.05 kPa 1483 count */ - 888, /* 91.11 kPa 1484 count */ - 883, /* 91.16 kPa 1485 count */ - 878, /* 91.22 kPa 1486 count */ - 873, /* 91.27 kPa 1487 count */ - 868, /* 91.32 kPa 1488 count */ - 863, /* 91.38 kPa 1489 count */ - 858, /* 91.43 kPa 1490 count */ - 853, /* 91.49 kPa 1491 count */ - 848, /* 91.54 kPa 1492 count */ - 843, /* 91.60 kPa 1493 count */ - 838, /* 91.65 kPa 1494 count */ - 834, /* 91.70 kPa 1495 count */ - 829, /* 91.76 kPa 1496 count */ - 824, /* 91.81 kPa 1497 count */ - 819, /* 91.87 kPa 1498 count */ - 814, /* 91.92 kPa 1499 count */ - 809, /* 91.98 kPa 1500 count */ - 804, /* 92.03 kPa 1501 count */ - 799, /* 92.08 kPa 1502 count */ - 794, /* 92.14 kPa 1503 count */ - 790, /* 92.19 kPa 1504 count */ - 785, /* 92.25 kPa 1505 count */ - 780, /* 92.30 kPa 1506 count */ - 775, /* 92.36 kPa 1507 count */ - 770, /* 92.41 kPa 1508 count */ - 765, /* 92.46 kPa 1509 count */ - 760, /* 92.52 kPa 1510 count */ - 755, /* 92.57 kPa 1511 count */ - 751, /* 92.63 kPa 1512 count */ - 746, /* 92.68 kPa 1513 count */ - 741, /* 92.74 kPa 1514 count */ - 736, /* 92.79 kPa 1515 count */ - 731, /* 92.84 kPa 1516 count */ - 726, /* 92.90 kPa 1517 count */ - 721, /* 92.95 kPa 1518 count */ - 717, /* 93.01 kPa 1519 count */ - 712, /* 93.06 kPa 1520 count */ - 707, /* 93.12 kPa 1521 count */ - 702, /* 93.17 kPa 1522 count */ - 697, /* 93.22 kPa 1523 count */ - 692, /* 93.28 kPa 1524 count */ - 688, /* 93.33 kPa 1525 count */ - 683, /* 93.39 kPa 1526 count */ - 678, /* 93.44 kPa 1527 count */ - 673, /* 93.50 kPa 1528 count */ - 668, /* 93.55 kPa 1529 count */ - 664, /* 93.60 kPa 1530 count */ - 659, /* 93.66 kPa 1531 count */ - 654, /* 93.71 kPa 1532 count */ - 649, /* 93.77 kPa 1533 count */ - 644, /* 93.82 kPa 1534 count */ - 639, /* 93.88 kPa 1535 count */ - 635, /* 93.93 kPa 1536 count */ - 630, /* 93.98 kPa 1537 count */ - 625, /* 94.04 kPa 1538 count */ - 620, /* 94.09 kPa 1539 count */ - 615, /* 94.15 kPa 1540 count */ - 611, /* 94.20 kPa 1541 count */ - 606, /* 94.26 kPa 1542 count */ - 601, /* 94.31 kPa 1543 count */ - 596, /* 94.36 kPa 1544 count */ - 591, /* 94.42 kPa 1545 count */ - 587, /* 94.47 kPa 1546 count */ - 582, /* 94.53 kPa 1547 count */ - 577, /* 94.58 kPa 1548 count */ - 572, /* 94.64 kPa 1549 count */ - 568, /* 94.69 kPa 1550 count */ - 563, /* 94.74 kPa 1551 count */ - 558, /* 94.80 kPa 1552 count */ - 553, /* 94.85 kPa 1553 count */ - 549, /* 94.91 kPa 1554 count */ - 544, /* 94.96 kPa 1555 count */ - 539, /* 95.02 kPa 1556 count */ - 534, /* 95.07 kPa 1557 count */ - 529, /* 95.12 kPa 1558 count */ - 525, /* 95.18 kPa 1559 count */ - 520, /* 95.23 kPa 1560 count */ - 515, /* 95.29 kPa 1561 count */ - 510, /* 95.34 kPa 1562 count */ - 506, /* 95.40 kPa 1563 count */ - 501, /* 95.45 kPa 1564 count */ - 496, /* 95.50 kPa 1565 count */ - 492, /* 95.56 kPa 1566 count */ - 487, /* 95.61 kPa 1567 count */ - 482, /* 95.67 kPa 1568 count */ - 477, /* 95.72 kPa 1569 count */ - 473, /* 95.78 kPa 1570 count */ - 468, /* 95.83 kPa 1571 count */ - 463, /* 95.88 kPa 1572 count */ - 458, /* 95.94 kPa 1573 count */ - 454, /* 95.99 kPa 1574 count */ - 449, /* 96.05 kPa 1575 count */ - 444, /* 96.10 kPa 1576 count */ - 440, /* 96.16 kPa 1577 count */ - 435, /* 96.21 kPa 1578 count */ - 430, /* 96.26 kPa 1579 count */ - 425, /* 96.32 kPa 1580 count */ - 421, /* 96.37 kPa 1581 count */ - 416, /* 96.43 kPa 1582 count */ - 411, /* 96.48 kPa 1583 count */ - 407, /* 96.54 kPa 1584 count */ - 402, /* 96.59 kPa 1585 count */ - 397, /* 96.64 kPa 1586 count */ - 392, /* 96.70 kPa 1587 count */ - 388, /* 96.75 kPa 1588 count */ - 383, /* 96.81 kPa 1589 count */ - 378, /* 96.86 kPa 1590 count */ - 374, /* 96.91 kPa 1591 count */ - 369, /* 96.97 kPa 1592 count */ - 364, /* 97.02 kPa 1593 count */ - 360, /* 97.08 kPa 1594 count */ - 355, /* 97.13 kPa 1595 count */ - 350, /* 97.19 kPa 1596 count */ - 346, /* 97.24 kPa 1597 count */ - 341, /* 97.29 kPa 1598 count */ - 336, /* 97.35 kPa 1599 count */ - 332, /* 97.40 kPa 1600 count */ - 327, /* 97.46 kPa 1601 count */ - 322, /* 97.51 kPa 1602 count */ - 318, /* 97.57 kPa 1603 count */ - 313, /* 97.62 kPa 1604 count */ - 308, /* 97.67 kPa 1605 count */ - 304, /* 97.73 kPa 1606 count */ - 299, /* 97.78 kPa 1607 count */ - 294, /* 97.84 kPa 1608 count */ - 290, /* 97.89 kPa 1609 count */ - 285, /* 97.95 kPa 1610 count */ - 280, /* 98.00 kPa 1611 count */ - 276, /* 98.05 kPa 1612 count */ - 271, /* 98.11 kPa 1613 count */ - 267, /* 98.16 kPa 1614 count */ - 262, /* 98.22 kPa 1615 count */ - 257, /* 98.27 kPa 1616 count */ - 253, /* 98.33 kPa 1617 count */ - 248, /* 98.38 kPa 1618 count */ - 243, /* 98.43 kPa 1619 count */ - 239, /* 98.49 kPa 1620 count */ - 234, /* 98.54 kPa 1621 count */ - 230, /* 98.60 kPa 1622 count */ - 225, /* 98.65 kPa 1623 count */ - 220, /* 98.71 kPa 1624 count */ - 216, /* 98.76 kPa 1625 count */ - 211, /* 98.81 kPa 1626 count */ - 206, /* 98.87 kPa 1627 count */ - 202, /* 98.92 kPa 1628 count */ - 197, /* 98.98 kPa 1629 count */ - 193, /* 99.03 kPa 1630 count */ - 188, /* 99.09 kPa 1631 count */ - 183, /* 99.14 kPa 1632 count */ - 179, /* 99.19 kPa 1633 count */ - 174, /* 99.25 kPa 1634 count */ - 170, /* 99.30 kPa 1635 count */ - 165, /* 99.36 kPa 1636 count */ - 160, /* 99.41 kPa 1637 count */ - 156, /* 99.47 kPa 1638 count */ - 151, /* 99.52 kPa 1639 count */ - 147, /* 99.57 kPa 1640 count */ - 142, /* 99.63 kPa 1641 count */ - 138, /* 99.68 kPa 1642 count */ - 133, /* 99.74 kPa 1643 count */ - 128, /* 99.79 kPa 1644 count */ - 124, /* 99.85 kPa 1645 count */ - 119, /* 99.90 kPa 1646 count */ - 115, /* 99.95 kPa 1647 count */ - 110, /* 100.01 kPa 1648 count */ - 106, /* 100.06 kPa 1649 count */ - 101, /* 100.12 kPa 1650 count */ - 96, /* 100.17 kPa 1651 count */ - 92, /* 100.23 kPa 1652 count */ - 87, /* 100.28 kPa 1653 count */ - 83, /* 100.33 kPa 1654 count */ - 78, /* 100.39 kPa 1655 count */ - 74, /* 100.44 kPa 1656 count */ - 69, /* 100.50 kPa 1657 count */ - 65, /* 100.55 kPa 1658 count */ - 60, /* 100.61 kPa 1659 count */ - 55, /* 100.66 kPa 1660 count */ - 51, /* 100.71 kPa 1661 count */ - 46, /* 100.77 kPa 1662 count */ - 42, /* 100.82 kPa 1663 count */ - 37, /* 100.88 kPa 1664 count */ - 33, /* 100.93 kPa 1665 count */ - 28, /* 100.99 kPa 1666 count */ - 24, /* 101.04 kPa 1667 count */ - 19, /* 101.09 kPa 1668 count */ - 15, /* 101.15 kPa 1669 count */ - 10, /* 101.20 kPa 1670 count */ - 6, /* 101.26 kPa 1671 count */ - 1, /* 101.31 kPa 1672 count */ - -3, /* 101.37 kPa 1673 count */ - -8, /* 101.42 kPa 1674 count */ - -12, /* 101.47 kPa 1675 count */ - -17, /* 101.53 kPa 1676 count */ - -21, /* 101.58 kPa 1677 count */ - -26, /* 101.64 kPa 1678 count */ - -30, /* 101.69 kPa 1679 count */ - -35, /* 101.75 kPa 1680 count */ - -39, /* 101.80 kPa 1681 count */ - -44, /* 101.85 kPa 1682 count */ - -48, /* 101.91 kPa 1683 count */ - -53, /* 101.96 kPa 1684 count */ - -57, /* 102.02 kPa 1685 count */ - -62, /* 102.07 kPa 1686 count */ - -66, /* 102.13 kPa 1687 count */ - -71, /* 102.18 kPa 1688 count */ - -75, /* 102.23 kPa 1689 count */ - -80, /* 102.29 kPa 1690 count */ - -84, /* 102.34 kPa 1691 count */ - -89, /* 102.40 kPa 1692 count */ - -93, /* 102.45 kPa 1693 count */ - -98, /* 102.51 kPa 1694 count */ - -102, /* 102.56 kPa 1695 count */ - -107, /* 102.61 kPa 1696 count */ - -111, /* 102.67 kPa 1697 count */ - -116, /* 102.72 kPa 1698 count */ - -120, /* 102.78 kPa 1699 count */ - -125, /* 102.83 kPa 1700 count */ - -129, /* 102.89 kPa 1701 count */ - -134, /* 102.94 kPa 1702 count */ - -138, /* 102.99 kPa 1703 count */ - -143, /* 103.05 kPa 1704 count */ - -147, /* 103.10 kPa 1705 count */ - -151, /* 103.16 kPa 1706 count */ - -156, /* 103.21 kPa 1707 count */ - -160, /* 103.27 kPa 1708 count */ - -165, /* 103.32 kPa 1709 count */ - -169, /* 103.37 kPa 1710 count */ - -174, /* 103.43 kPa 1711 count */ - -178, /* 103.48 kPa 1712 count */ - -183, /* 103.54 kPa 1713 count */ - -187, /* 103.59 kPa 1714 count */ - -191, /* 103.65 kPa 1715 count */ - -196, /* 103.70 kPa 1716 count */ - -200, /* 103.75 kPa 1717 count */ - -205, /* 103.81 kPa 1718 count */ - -209, /* 103.86 kPa 1719 count */ - -214, /* 103.92 kPa 1720 count */ - -218, /* 103.97 kPa 1721 count */ - -222, /* 104.03 kPa 1722 count */ - -227, /* 104.08 kPa 1723 count */ - -231, /* 104.13 kPa 1724 count */ - -236, /* 104.19 kPa 1725 count */ - -240, /* 104.24 kPa 1726 count */ - -245, /* 104.30 kPa 1727 count */ - -249, /* 104.35 kPa 1728 count */ - -253, /* 104.41 kPa 1729 count */ - -258, /* 104.46 kPa 1730 count */ - -262, /* 104.51 kPa 1731 count */ - -267, /* 104.57 kPa 1732 count */ - -271, /* 104.62 kPa 1733 count */ - -275, /* 104.68 kPa 1734 count */ - -280, /* 104.73 kPa 1735 count */ - -284, /* 104.79 kPa 1736 count */ - -289, /* 104.84 kPa 1737 count */ - -293, /* 104.89 kPa 1738 count */ - -297, /* 104.95 kPa 1739 count */ - -302, /* 105.00 kPa 1740 count */ - -306, /* 105.06 kPa 1741 count */ - -311, /* 105.11 kPa 1742 count */ - -315, /* 105.17 kPa 1743 count */ - -319, /* 105.22 kPa 1744 count */ - -324, /* 105.27 kPa 1745 count */ - -328, /* 105.33 kPa 1746 count */ - -332, /* 105.38 kPa 1747 count */ - -337, /* 105.44 kPa 1748 count */ - -341, /* 105.49 kPa 1749 count */ - -346, /* 105.55 kPa 1750 count */ - -350, /* 105.60 kPa 1751 count */ - -354, /* 105.65 kPa 1752 count */ - -359, /* 105.71 kPa 1753 count */ - -363, /* 105.76 kPa 1754 count */ - -367, /* 105.82 kPa 1755 count */ - -372, /* 105.87 kPa 1756 count */ - -376, /* 105.93 kPa 1757 count */ - -380, /* 105.98 kPa 1758 count */ - -385, /* 106.03 kPa 1759 count */ - -389, /* 106.09 kPa 1760 count */ - -394, /* 106.14 kPa 1761 count */ - -398, /* 106.20 kPa 1762 count */ - -402, /* 106.25 kPa 1763 count */ - -407, /* 106.31 kPa 1764 count */ - -411, /* 106.36 kPa 1765 count */ - -415, /* 106.41 kPa 1766 count */ - -420, /* 106.47 kPa 1767 count */ - -424, /* 106.52 kPa 1768 count */ - -428, /* 106.58 kPa 1769 count */ - -433, /* 106.63 kPa 1770 count */ - -437, /* 106.69 kPa 1771 count */ - -441, /* 106.74 kPa 1772 count */ - -446, /* 106.79 kPa 1773 count */ - -450, /* 106.85 kPa 1774 count */ - -454, /* 106.90 kPa 1775 count */ - -459, /* 106.96 kPa 1776 count */ - -463, /* 107.01 kPa 1777 count */ - -467, /* 107.07 kPa 1778 count */ - -472, /* 107.12 kPa 1779 count */ - -476, /* 107.17 kPa 1780 count */ - -480, /* 107.23 kPa 1781 count */ - -485, /* 107.28 kPa 1782 count */ - -489, /* 107.34 kPa 1783 count */ - -493, /* 107.39 kPa 1784 count */ - -497, /* 107.45 kPa 1785 count */ - -502, /* 107.50 kPa 1786 count */ - -506, /* 107.55 kPa 1787 count */ - -510, /* 107.61 kPa 1788 count */ - -515, /* 107.66 kPa 1789 count */ - -519, /* 107.72 kPa 1790 count */ - -523, /* 107.77 kPa 1791 count */ - -528, /* 107.83 kPa 1792 count */ - -532, /* 107.88 kPa 1793 count */ - -536, /* 107.93 kPa 1794 count */ - -540, /* 107.99 kPa 1795 count */ - -545, /* 108.04 kPa 1796 count */ - -549, /* 108.10 kPa 1797 count */ - -553, /* 108.15 kPa 1798 count */ - -558, /* 108.21 kPa 1799 count */ - -562, /* 108.26 kPa 1800 count */ - -566, /* 108.31 kPa 1801 count */ - -570, /* 108.37 kPa 1802 count */ - -575, /* 108.42 kPa 1803 count */ - -579, /* 108.48 kPa 1804 count */ - -583, /* 108.53 kPa 1805 count */ - -588, /* 108.59 kPa 1806 count */ - -592, /* 108.64 kPa 1807 count */ - -596, /* 108.69 kPa 1808 count */ - -600, /* 108.75 kPa 1809 count */ - -605, /* 108.80 kPa 1810 count */ - -609, /* 108.86 kPa 1811 count */ - -613, /* 108.91 kPa 1812 count */ - -617, /* 108.97 kPa 1813 count */ - -622, /* 109.02 kPa 1814 count */ - -626, /* 109.07 kPa 1815 count */ - -630, /* 109.13 kPa 1816 count */ - -634, /* 109.18 kPa 1817 count */ - -639, /* 109.24 kPa 1818 count */ - -643, /* 109.29 kPa 1819 count */ - -647, /* 109.35 kPa 1820 count */ - -651, /* 109.40 kPa 1821 count */ - -656, /* 109.45 kPa 1822 count */ - -660, /* 109.51 kPa 1823 count */ - -664, /* 109.56 kPa 1824 count */ - -668, /* 109.62 kPa 1825 count */ - -673, /* 109.67 kPa 1826 count */ - -677, /* 109.73 kPa 1827 count */ - -681, /* 109.78 kPa 1828 count */ - -685, /* 109.83 kPa 1829 count */ - -690, /* 109.89 kPa 1830 count */ - -694, /* 109.94 kPa 1831 count */ - -698, /* 110.00 kPa 1832 count */ - -702, /* 110.05 kPa 1833 count */ - -706, /* 110.11 kPa 1834 count */ - -711, /* 110.16 kPa 1835 count */ - -715, /* 110.21 kPa 1836 count */ - -719, /* 110.27 kPa 1837 count */ - -723, /* 110.32 kPa 1838 count */ - -728, /* 110.38 kPa 1839 count */ - -732, /* 110.43 kPa 1840 count */ - -736, /* 110.48 kPa 1841 count */ - -740, /* 110.54 kPa 1842 count */ - -744, /* 110.59 kPa 1843 count */ - -749, /* 110.65 kPa 1844 count */ - -753, /* 110.70 kPa 1845 count */ - -757, /* 110.76 kPa 1846 count */ - -761, /* 110.81 kPa 1847 count */ - -765, /* 110.86 kPa 1848 count */ - -770, /* 110.92 kPa 1849 count */ - -774, /* 110.97 kPa 1850 count */ - -778, /* 111.03 kPa 1851 count */ - -782, /* 111.08 kPa 1852 count */ - -786, /* 111.14 kPa 1853 count */ - -791, /* 111.19 kPa 1854 count */ - -795, /* 111.24 kPa 1855 count */ - -799, /* 111.30 kPa 1856 count */ - -803, /* 111.35 kPa 1857 count */ - -807, /* 111.41 kPa 1858 count */ - -812, /* 111.46 kPa 1859 count */ - -816, /* 111.52 kPa 1860 count */ - -820, /* 111.57 kPa 1861 count */ - -824, /* 111.62 kPa 1862 count */ - -828, /* 111.68 kPa 1863 count */ - -832, /* 111.73 kPa 1864 count */ - -837, /* 111.79 kPa 1865 count */ - -841, /* 111.84 kPa 1866 count */ - -845, /* 111.90 kPa 1867 count */ - -849, /* 111.95 kPa 1868 count */ - -853, /* 112.00 kPa 1869 count */ - -857, /* 112.06 kPa 1870 count */ - -862, /* 112.11 kPa 1871 count */ - -866, /* 112.17 kPa 1872 count */ - -870, /* 112.22 kPa 1873 count */ - -874, /* 112.28 kPa 1874 count */ - -878, /* 112.33 kPa 1875 count */ - -882, /* 112.38 kPa 1876 count */ - -887, /* 112.44 kPa 1877 count */ - -891, /* 112.49 kPa 1878 count */ - -895, /* 112.55 kPa 1879 count */ - -899, /* 112.60 kPa 1880 count */ - -903, /* 112.66 kPa 1881 count */ - -907, /* 112.71 kPa 1882 count */ - -911, /* 112.76 kPa 1883 count */ - -916, /* 112.82 kPa 1884 count */ - -920, /* 112.87 kPa 1885 count */ - -924, /* 112.93 kPa 1886 count */ - -928, /* 112.98 kPa 1887 count */ - -932, /* 113.04 kPa 1888 count */ - -936, /* 113.09 kPa 1889 count */ - -940, /* 113.14 kPa 1890 count */ - -945, /* 113.20 kPa 1891 count */ - -949, /* 113.25 kPa 1892 count */ - -953, /* 113.31 kPa 1893 count */ - -957, /* 113.36 kPa 1894 count */ - -961, /* 113.42 kPa 1895 count */ - -965, /* 113.47 kPa 1896 count */ - -969, /* 113.52 kPa 1897 count */ - -973, /* 113.58 kPa 1898 count */ - -978, /* 113.63 kPa 1899 count */ - -982, /* 113.69 kPa 1900 count */ - -986, /* 113.74 kPa 1901 count */ - -990, /* 113.80 kPa 1902 count */ - -994, /* 113.85 kPa 1903 count */ - -998, /* 113.90 kPa 1904 count */ - -1002, /* 113.96 kPa 1905 count */ - -1006, /* 114.01 kPa 1906 count */ - -1010, /* 114.07 kPa 1907 count */ - -1015, /* 114.12 kPa 1908 count */ - -1019, /* 114.18 kPa 1909 count */ - -1023, /* 114.23 kPa 1910 count */ - -1027, /* 114.28 kPa 1911 count */ - -1031, /* 114.34 kPa 1912 count */ - -1035, /* 114.39 kPa 1913 count */ - -1039, /* 114.45 kPa 1914 count */ - -1043, /* 114.50 kPa 1915 count */ - -1047, /* 114.56 kPa 1916 count */ - -1051, /* 114.61 kPa 1917 count */ - -1056, /* 114.66 kPa 1918 count */ - -1060, /* 114.72 kPa 1919 count */ - -1064, /* 114.77 kPa 1920 count */ - -1068, /* 114.83 kPa 1921 count */ - -1072, /* 114.88 kPa 1922 count */ - -1076, /* 114.94 kPa 1923 count */ - -1080, /* 114.99 kPa 1924 count */ - -1084, /* 115.04 kPa 1925 count */ - -1088, /* 115.10 kPa 1926 count */ - -1092, /* 115.15 kPa 1927 count */ - -1096, /* 115.21 kPa 1928 count */ - -1100, /* 115.26 kPa 1929 count */ - -1104, /* 115.32 kPa 1930 count */ - -1109, /* 115.37 kPa 1931 count */ - -1113, /* 115.42 kPa 1932 count */ - -1117, /* 115.48 kPa 1933 count */ - -1121, /* 115.53 kPa 1934 count */ - -1125, /* 115.59 kPa 1935 count */ - -1129, /* 115.64 kPa 1936 count */ - -1133, /* 115.70 kPa 1937 count */ - -1137, /* 115.75 kPa 1938 count */ - -1141, /* 115.80 kPa 1939 count */ - -1145, /* 115.86 kPa 1940 count */ - -1149, /* 115.91 kPa 1941 count */ - -1153, /* 115.97 kPa 1942 count */ - -1157, /* 116.02 kPa 1943 count */ - -1161, /* 116.08 kPa 1944 count */ - -1165, /* 116.13 kPa 1945 count */ - -1169, /* 116.18 kPa 1946 count */ - -1173, /* 116.24 kPa 1947 count */ - -1177, /* 116.29 kPa 1948 count */ - -1182, /* 116.35 kPa 1949 count */ - -1186, /* 116.40 kPa 1950 count */ - -1190, /* 116.46 kPa 1951 count */ - -1194, /* 116.51 kPa 1952 count */ - -1198, /* 116.56 kPa 1953 count */ - -1202, /* 116.62 kPa 1954 count */ - -1206, /* 116.67 kPa 1955 count */ - -1210, /* 116.73 kPa 1956 count */ - -1214, /* 116.78 kPa 1957 count */ - -1218, /* 116.84 kPa 1958 count */ - -1222, /* 116.89 kPa 1959 count */ - -1226, /* 116.94 kPa 1960 count */ - -1230, /* 117.00 kPa 1961 count */ - -1234, /* 117.05 kPa 1962 count */ - -1238, /* 117.11 kPa 1963 count */ - -1242, /* 117.16 kPa 1964 count */ - -1246, /* 117.22 kPa 1965 count */ - -1250, /* 117.27 kPa 1966 count */ - -1254, /* 117.32 kPa 1967 count */ - -1258, /* 117.38 kPa 1968 count */ - -1262, /* 117.43 kPa 1969 count */ - -1266, /* 117.49 kPa 1970 count */ - -1270, /* 117.54 kPa 1971 count */ - -1274, /* 117.60 kPa 1972 count */ - -1278, /* 117.65 kPa 1973 count */ - -1282, /* 117.70 kPa 1974 count */ - -1286, /* 117.76 kPa 1975 count */ - -1290, /* 117.81 kPa 1976 count */ - -1294, /* 117.87 kPa 1977 count */ - -1298, /* 117.92 kPa 1978 count */ - -1302, /* 117.98 kPa 1979 count */ - -1306, /* 118.03 kPa 1980 count */ - -1310, /* 118.08 kPa 1981 count */ - -1314, /* 118.14 kPa 1982 count */ - -1318, /* 118.19 kPa 1983 count */ - -1322, /* 118.25 kPa 1984 count */ - -1326, /* 118.30 kPa 1985 count */ - -1330, /* 118.36 kPa 1986 count */ - -1334, /* 118.41 kPa 1987 count */ - -1338, /* 118.46 kPa 1988 count */ - -1342, /* 118.52 kPa 1989 count */ - -1346, /* 118.57 kPa 1990 count */ - -1350, /* 118.63 kPa 1991 count */ - -1354, /* 118.68 kPa 1992 count */ - -1358, /* 118.74 kPa 1993 count */ - -1362, /* 118.79 kPa 1994 count */ - -1366, /* 118.84 kPa 1995 count */ - -1370, /* 118.90 kPa 1996 count */ - -1374, /* 118.95 kPa 1997 count */ - -1378, /* 119.01 kPa 1998 count */ - -1382, /* 119.06 kPa 1999 count */ - -1386, /* 119.12 kPa 2000 count */ - -1390, /* 119.17 kPa 2001 count */ - -1394, /* 119.22 kPa 2002 count */ - -1397, /* 119.28 kPa 2003 count */ - -1401, /* 119.33 kPa 2004 count */ - -1405, /* 119.39 kPa 2005 count */ - -1409, /* 119.44 kPa 2006 count */ - -1413, /* 119.50 kPa 2007 count */ - -1417, /* 119.55 kPa 2008 count */ - -1421, /* 119.60 kPa 2009 count */ - -1425, /* 119.66 kPa 2010 count */ - -1429, /* 119.71 kPa 2011 count */ - -1433, /* 119.77 kPa 2012 count */ - -1437, /* 119.82 kPa 2013 count */ - -1441, /* 119.88 kPa 2014 count */ - -1445, /* 119.93 kPa 2015 count */ - -1449, /* 119.98 kPa 2016 count */ - -1453, /* 120.04 kPa 2017 count */ - -1457, /* 120.09 kPa 2018 count */ - -1461, /* 120.15 kPa 2019 count */ - -1465, /* 120.20 kPa 2020 count */ - -1469, /* 120.26 kPa 2021 count */ - -1472, /* 120.31 kPa 2022 count */ - -1476, /* 120.36 kPa 2023 count */ - -1480, /* 120.42 kPa 2024 count */ - -1484, /* 120.47 kPa 2025 count */ - -1488, /* 120.53 kPa 2026 count */ - -1492, /* 120.58 kPa 2027 count */ - -1496, /* 120.64 kPa 2028 count */ - -1500, /* 120.69 kPa 2029 count */ - -1504, /* 120.74 kPa 2030 count */ - -1508, /* 120.80 kPa 2031 count */ - -1512, /* 120.85 kPa 2032 count */ - -1516, /* 120.91 kPa 2033 count */ - -1520, /* 120.96 kPa 2034 count */ - -1523, /* 121.02 kPa 2035 count */ - -1527, /* 121.07 kPa 2036 count */ - -1531, /* 121.12 kPa 2037 count */ - -1535, /* 121.18 kPa 2038 count */ - -1539, /* 121.23 kPa 2039 count */ - -1543, /* 121.29 kPa 2040 count */ - -1547, /* 121.34 kPa 2041 count */ - -1551, /* 121.40 kPa 2042 count */ - -1555, /* 121.45 kPa 2043 count */ - -1559, /* 121.50 kPa 2044 count */ - -1562, /* 121.56 kPa 2045 count */ - -1566, /* 121.61 kPa 2046 count */ - -1570, /* 121.67 kPa 2047 count */ +/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ +#define NALT 129 +#define ALT_FRAC_BITS 8 + 15835, /* 10.56 kPa 0.000% */ + 15332, /* 11.42 kPa 0.781% */ + 14868, /* 12.29 kPa 1.563% */ + 14435, /* 13.16 kPa 2.344% */ + 14030, /* 14.02 kPa 3.125% */ + 13649, /* 14.90 kPa 3.906% */ + 13290, /* 15.76 kPa 4.688% */ + 12950, /* 16.63 kPa 5.469% */ + 12627, /* 17.50 kPa 6.250% */ + 12320, /* 18.37 kPa 7.031% */ + 12027, /* 19.24 kPa 7.813% */ + 11747, /* 20.10 kPa 8.594% */ + 11479, /* 20.97 kPa 9.375% */ + 11222, /* 21.84 kPa 10.156% */ + 10975, /* 22.71 kPa 10.938% */ + 10736, /* 23.58 kPa 11.719% */ + 10504, /* 24.44 kPa 12.500% */ + 10278, /* 25.31 kPa 13.281% */ + 10059, /* 26.18 kPa 14.063% */ + 9846, /* 27.05 kPa 14.844% */ + 9638, /* 27.91 kPa 15.625% */ + 9435, /* 28.78 kPa 16.406% */ + 9237, /* 29.65 kPa 17.188% */ + 9044, /* 30.52 kPa 17.969% */ + 8855, /* 31.39 kPa 18.750% */ + 8670, /* 32.26 kPa 19.531% */ + 8490, /* 33.13 kPa 20.313% */ + 8313, /* 33.99 kPa 21.094% */ + 8140, /* 34.86 kPa 21.875% */ + 7970, /* 35.73 kPa 22.656% */ + 7803, /* 36.60 kPa 23.438% */ + 7640, /* 37.47 kPa 24.219% */ + 7480, /* 38.33 kPa 25.000% */ + 7322, /* 39.20 kPa 25.781% */ + 7168, /* 40.07 kPa 26.563% */ + 7016, /* 40.94 kPa 27.344% */ + 6867, /* 41.80 kPa 28.125% */ + 6720, /* 42.67 kPa 28.906% */ + 6575, /* 43.54 kPa 29.688% */ + 6433, /* 44.41 kPa 30.469% */ + 6294, /* 45.28 kPa 31.250% */ + 6156, /* 46.15 kPa 32.031% */ + 6020, /* 47.01 kPa 32.813% */ + 5887, /* 47.88 kPa 33.594% */ + 5755, /* 48.75 kPa 34.375% */ + 5625, /* 49.62 kPa 35.156% */ + 5497, /* 50.49 kPa 35.938% */ + 5371, /* 51.35 kPa 36.719% */ + 5247, /* 52.22 kPa 37.500% */ + 5124, /* 53.09 kPa 38.281% */ + 5003, /* 53.96 kPa 39.063% */ + 4883, /* 54.83 kPa 39.844% */ + 4765, /* 55.69 kPa 40.625% */ + 4648, /* 56.56 kPa 41.406% */ + 4533, /* 57.43 kPa 42.188% */ + 4419, /* 58.30 kPa 42.969% */ + 4307, /* 59.17 kPa 43.750% */ + 4196, /* 60.03 kPa 44.531% */ + 4086, /* 60.90 kPa 45.313% */ + 3977, /* 61.77 kPa 46.094% */ + 3870, /* 62.63 kPa 46.875% */ + 3764, /* 63.51 kPa 47.656% */ + 3659, /* 64.38 kPa 48.438% */ + 3555, /* 65.24 kPa 49.219% */ + 3453, /* 66.11 kPa 50.000% */ + 3351, /* 66.98 kPa 50.781% */ + 3250, /* 67.85 kPa 51.563% */ + 3151, /* 68.72 kPa 52.344% */ + 3052, /* 69.58 kPa 53.125% */ + 2955, /* 70.45 kPa 53.906% */ + 2858, /* 71.32 kPa 54.688% */ + 2763, /* 72.19 kPa 55.469% */ + 2668, /* 73.06 kPa 56.250% */ + 2574, /* 73.92 kPa 57.031% */ + 2482, /* 74.79 kPa 57.813% */ + 2390, /* 75.66 kPa 58.594% */ + 2298, /* 76.52 kPa 59.375% */ + 2208, /* 77.40 kPa 60.156% */ + 2119, /* 78.26 kPa 60.938% */ + 2030, /* 79.13 kPa 61.719% */ + 1942, /* 80.00 kPa 62.500% */ + 1855, /* 80.87 kPa 63.281% */ + 1769, /* 81.74 kPa 64.063% */ + 1683, /* 82.60 kPa 64.844% */ + 1598, /* 83.47 kPa 65.625% */ + 1514, /* 84.34 kPa 66.406% */ + 1430, /* 85.21 kPa 67.188% */ + 1347, /* 86.08 kPa 67.969% */ + 1265, /* 86.94 kPa 68.750% */ + 1184, /* 87.81 kPa 69.531% */ + 1103, /* 88.68 kPa 70.313% */ + 1023, /* 89.55 kPa 71.094% */ + 943, /* 90.41 kPa 71.875% */ + 864, /* 91.28 kPa 72.656% */ + 786, /* 92.15 kPa 73.438% */ + 708, /* 93.02 kPa 74.219% */ + 631, /* 93.89 kPa 75.000% */ + 554, /* 94.76 kPa 75.781% */ + 478, /* 95.63 kPa 76.563% */ + 403, /* 96.49 kPa 77.344% */ + 328, /* 97.36 kPa 78.125% */ + 254, /* 98.23 kPa 78.906% */ + 180, /* 99.10 kPa 79.688% */ + 106, /* 99.97 kPa 80.469% */ + 34, /* 100.83 kPa 81.250% */ + -39, /* 101.70 kPa 82.031% */ + -111, /* 102.57 kPa 82.813% */ + -182, /* 103.44 kPa 83.594% */ + -253, /* 104.30 kPa 84.375% */ + -323, /* 105.17 kPa 85.156% */ + -393, /* 106.04 kPa 85.938% */ + -462, /* 106.91 kPa 86.719% */ + -531, /* 107.78 kPa 87.500% */ + -600, /* 108.65 kPa 88.281% */ + -668, /* 109.51 kPa 89.063% */ + -736, /* 110.38 kPa 89.844% */ + -803, /* 111.25 kPa 90.625% */ + -870, /* 112.12 kPa 91.406% */ + -936, /* 112.99 kPa 92.188% */ + -1002, /* 113.85 kPa 92.969% */ + -1068, /* 114.72 kPa 93.750% */ + -1133, /* 115.59 kPa 94.531% */ + -1198, /* 116.46 kPa 95.313% */ + -1262, /* 117.33 kPa 96.094% */ + -1326, /* 118.19 kPa 96.875% */ + -1389, /* 119.06 kPa 97.656% */ + -1453, /* 119.93 kPa 98.438% */ + -1516, /* 120.80 kPa 99.219% */ + -1578, /* 121.67 kPa 100.000% */ diff --git a/src/ao_convert.c b/src/ao_convert.c index f29ce9e9..cec4c29f 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -15,40 +15,63 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifndef AO_CONVERT_TEST #include "ao.h" +#endif -static const int16_t altitude_table[2048] = { +static const int16_t altitude_table[] = { #include "altitude.h" }; +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + int16_t ao_pres_to_altitude(int16_t pres) __reentrant { - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } int16_t ao_altitude_to_pres(int16_t alt) __reentrant { - int16_t pres; + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; } -static __xdata uint8_t ao_temp_mutex; - int16_t ao_temp_to_dC(int16_t temp) __reentrant { int16_t ret; - ao_mutex_get(&ao_temp_mutex); /* Output voltage at 0°C = 0.755V * Coefficient = 0.00247V/°C * Reference voltage = 1.25V @@ -58,6 +81,5 @@ ao_temp_to_dC(int16_t temp) __reentrant * ≃ (value - 19791) * 1012 / 65536 */ ret = ((temp - 19791) * 1012L) >> 16; - ao_mutex_put(&ao_temp_mutex); return ret; } diff --git a/src/ao_convert_test.c b/src/ao_convert_test.c new file mode 100644 index 00000000..e2c28b73 --- /dev/null +++ b/src/ao_convert_test.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert.c" + +#define STEP 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int16_t p_to_a, p_to_a_to_p; + int16_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 32767 + STEP; i += STEP) { + if (i > 32767) + i = 32767; + p_to_a = ao_pres_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pres(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pres %d alt %d pres %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1578; i < 15835 + STEP; i += STEP) { + if (i > 15835) + i = 15835; + a_to_p = ao_altitude_to_pres(i); + a_to_p_to_a = ao_pres_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pres %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/make-altitude b/src/make-altitude index ac04e84f..716aa8a8 100644 --- a/src/make-altitude +++ b/src/make-altitude @@ -179,14 +179,105 @@ real meters_to_feet(real meters) real counts_per_kPa = 27 * 2047 / 3300; real counts_at_101_3kPa = 1674; -real count_to_kPa(real count) +real fraction_to_kPa(real fraction) { - return (count / 2047 + 0.095) / 0.009; + return (fraction + 0.095) / 0.009; } -for (real count = 0; count <= 2047; count++) { - real kPa = count_to_kPa(count); + +real count_to_kPa(real count) = fraction_to_kPa(count / 2047); + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real count_to_altitude(real count) { + return pressure_to_altitude(count_to_kPa(count) * 1000); +} + +real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); + +int num_samples = 1024; + +real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; + +int num_part = 128; +int seg_len = num_samples / num_part; + +line_t [dim(alt) / seg_len] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real count_to_fit_altitude(int count) { + int sub = count // seg_len; + int off = count % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = count * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_count = 0; +real total_error = 0; + +for (int count = 0; count < num_samples; count++) { + real kPa = fraction_to_kPa(count / (num_samples - 1)); real meters = pressure_to_altitude(kPa * 1000); - printf (" %d, /* %6.2g kPa %d count */\n", - floor (meters + 0.5), kPa, count); + + real meters_approx = count_to_fit_altitude(count); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_count = count; + } +# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", +# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); + +for (int i = 0; i < dim(alt_part); i++) { + real fraction = i / (dim(alt_part) - 1); + real kPa = fraction_to_kPa(fraction); + printf ("%9d, /* %6.2f kPa %7.3f%% */\n", + alt_part[i], kPa, fraction * 100); } -- cgit v1.2.3 From 84c93bb2fc4558a5e4654794ba90e730a84eaf67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:22:16 -0800 Subject: Change altos build process to support per-product compile-time changes This creates per-product subdirectories and recompiles everything for each product, allowing per-product compile-time changes for things like peripheral pin assignments and attached serial devices. Signed-off-by: Keith Packard --- src/Makefile | 306 ++------------------------------- src/Makefile.proto | 217 +++++++++++++++++++++++ src/ao.h | 38 ++-- src/ao_adc.c | 7 +- src/ao_config.c | 18 +- src/ao_dbg.c | 32 ++-- src/ao_host.h | 24 --- src/ao_packet.c | 8 + src/ao_packet_slave.c | 2 +- src/ao_pins.h | 144 ++++++++++++++++ src/ao_reboot.c | 28 +++ src/ao_stdio.c | 3 +- src/ao_teledongle.c | 5 +- src/ao_telemetrum.c | 6 +- src/ao_timer.c | 6 + src/teledongle-v0.1/Makefile | 1 + src/teledongle-v0.1/Makefile.defs | 9 + src/teledongle-v0.2/Makefile | 1 + src/teledongle-v0.2/Makefile.defs | 9 + src/telemetrum-v0.1-sirf/Makefile | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 11 ++ src/telemetrum-v0.1-sky/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 11 ++ src/telemetrum-v0.2/Makefile | 1 + src/telemetrum-v0.2/Makefile.defs | 11 ++ src/test/Makefile | 24 +++ src/tidongle/Makefile | 1 + src/tidongle/Makefile.defs | 8 + 28 files changed, 572 insertions(+), 361 deletions(-) create mode 100644 src/Makefile.proto create mode 100644 src/ao_pins.h create mode 100644 src/ao_reboot.c create mode 100644 src/teledongle-v0.1/Makefile create mode 100644 src/teledongle-v0.1/Makefile.defs create mode 100644 src/teledongle-v0.2/Makefile create mode 100644 src/teledongle-v0.2/Makefile.defs create mode 100644 src/telemetrum-v0.1-sirf/Makefile create mode 100644 src/telemetrum-v0.1-sirf/Makefile.defs create mode 100644 src/telemetrum-v0.1-sky/Makefile create mode 100644 src/telemetrum-v0.1-sky/Makefile.defs create mode 100644 src/telemetrum-v0.2/Makefile create mode 100644 src/telemetrum-v0.2/Makefile.defs create mode 100644 src/test/Makefile create mode 100644 src/tidongle/Makefile create mode 100644 src/tidongle/Makefile.defs diff --git a/src/Makefile b/src/Makefile index dcd41718..e2699ee6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,307 +4,23 @@ # CC=sdcc -ifndef VERSION -VERSION=$(shell git describe) -endif +SUBDIRS=telemetrum-v0.2 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test -CFLAGS=--model-small --debug --opt-code-speed +all: all-recursive -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ - --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff +RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive -INC = \ - ao.h \ - cc1111.h \ - altitude.h \ - 25lc1024.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ - ao_cmd.c \ - ao_dma.c \ - ao_mutex.c \ - ao_panic.c \ - ao_task.c \ - ao_timer.c \ - _bp.c - -# -# Shared AltOS drivers -# -ALTOS_DRIVER_SRC = \ - ao_beep.c \ - ao_config.c \ - ao_led.c \ - ao_radio.c \ - ao_stdio.c \ - ao_usb.c - -TELE_COMMON_SRC = \ - ao_packet.c \ - ao_packet_slave.c \ - ao_state.c - -# -# Receiver code -# -TELE_RECEIVER_SRC =\ - ao_monitor.c \ - ao_gps_print.c \ - ao_packet_master.c \ - ao_rssi.c - -# -# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) -# - -TELE_DRIVER_SRC = \ - ao_convert.c \ - ao_serial.c - -# -# Drivers for partially-flled boards (TT, TD and TI) -# -TELE_FAKE_SRC = \ - ao_adc_fake.c \ - ao_ee_fake.c - -# -# Debug dongle driver (only on TI) -# -DBG_DONGLE_SRC = \ - ao_dbg.c - -# -# Drivers only on TeleMetrum -# -TM_DRIVER_SRC = \ - ao_adc.c \ - ao_flash.c \ - ao_gps_report.c \ - ao_ignite.c - -# -# Drivers only on TeleMetrum -# -TM_SIRF_DRIVER_SRC = \ - ao_gps_sirf.c -# -# Drivers only on TeleMetrum -# -TM_SKY_DRIVER_SRC = \ - ao_gps_skytraq.c - -# -# Tasks run on TeleMetrum -# -TM_TASK_SRC = \ - ao_flight.c \ - ao_log.c \ - ao_report.c \ - ao_telemetry.c - -TM_MAIN_SRC = \ - ao_telemetrum.c - -# -# All sources for TeleMetrum -# -TM_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TM_DRIVER_SRC) \ - $(TM_TASK_SRC) \ - $(TM_MAIN_SRC) - -TM_SIRF_SRC = \ - $(TM_SRC) \ - $(TM_SIRF_DRIVER_SRC) - -TM_SKY_SRC = \ - $(TM_SRC) \ - $(TM_SKY_DRIVER_SRC) - -TI_MAIN_SRC = \ - ao_tidongle.c - -# -# All sources for the TI debug dongle -# -TI_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TI_MAIN_SRC) \ - $(DBG_DONGLE_SRC) - -TT_MAIN_SRC = \ - ao_teleterra.c -# -# All sources for TeleTerra -# -TT_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TT_MAIN_SRC) - - -# -# Sources for TeleDongle -# - -TD_MAIN_SRC = \ - ao_teledongle.c - -TD_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TD_MAIN_SRC) - -SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TM_DRIVER_SRC) \ - $(TM_SIRF_DRIVER_SRC) \ - $(TM_SKY_DRIVER_SRC) \ - $(TM_TASK_SRC) \ - $(TM_MAIN_SRC) \ - $(TI_MAIN_SRC) \ - $(TD_MAIN_SRC) \ - $(TT_MAIN_SRC) - -TM_SIRF_REL=$(TM_SIRF_SRC:.c=.rel) ao_product-telemetrum.rel -TM_SKY_REL=$(TM_SKY_SRC:.c=.rel) ao_product-telemetrum.rel -TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel -TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel -TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel - -PROD_REL=\ - ao_product-telemetrum.rel \ - ao_product-tidongle.rel \ - ao_product-teleterra.rel \ - ao_product-teledongle.rel - -REL=$(SRC:.c=.rel) $(PROD_REL) -ADB=$(REL:.rel=.adb) -ASM=$(REL:.rel=.asm) -LNK=$(REL:.rel=.lnk) -LST=$(REL:.rel=.lst) -RST=$(REL:.rel=.rst) -SYM=$(REL:.rel=.sym) - -PROGS= telemetrum-sirf.ihx telemetrum-sky.ihx tidongle.ihx \ - teleterra.ihx teledongle.ihx - -HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq - -PCDB=$(PROGS:.ihx=.cdb) -PLNK=$(PROGS:.ihx=.lnk) -PMAP=$(PROGS:.ihx=.map) -PMEM=$(PROGS:.ihx=.mem) -PAOM=$(PROGS:.ihx=) - -%.rel : %.c $(INC) - $(CC) -c $(CFLAGS) -o$*.rel $*.c - -all: $(PROGS) $(HOST_PROGS) - -telemetrum-sirf.ihx: $(TM_SIRF_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SIRF_REL) - sh check-stack ao.h telemetrum-sirf.mem - -telemetrum-sky.ihx: $(TM_SKY_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SKY_REL) - sh check-stack ao.h telemetrum-sky.mem - -telemetrum-sky.ihx: telemetrum-sirf.ihx - -tidongle.ihx: $(TI_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL) - sh check-stack ao.h tidongle.mem - -tidongle.ihx: telemetrum-sky.ihx - -teleterra.ihx: $(TT_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL) - sh check-stack ao.h teleterra.mem - -teleterra.ihx: tidongle.ihx - -teledongle.ihx: $(TD_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TD_REL) - sh check-stack ao.h teledongle.mem - -teledongle.ihx: teleterra.ihx - -altitude.h: make-altitude - nickle make-altitude > altitude.h - -TELEMETRUM_DEFS=ao-telemetrum.h -TELETERRA_DEFS=ao-teleterra.h -TELEDONGLE_DEFS=ao-teledongle.h -TIDONGLE_DEFS=ao-tidongle.h - -ALL_DEFS=$(TELEMETRUM_DEFS) $(TELETERRA_DEFS) \ - $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS) -ao_product-telemetrum.rel: ao_product.c $(TELEMETRUM_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEMETRUM_DEFS)\"' -o$@ ao_product.c - -ao_product-teleterra.rel: ao_product.c $(TELETERRA_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELETERRA_DEFS)\"' -o$@ ao_product.c - -ao_product-teledongle.rel: ao_product.c $(TELEDONGLE_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEDONGLE_DEFS)\"' -o$@ ao_product.c - -ao_product-tidongle.rel: ao_product.c $(TIDONGLE_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TIDONGLE_DEFS)\"' -o$@ ao_product.c - -$(TELEMETRUM_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleMetrum -v $(VERSION) > $@ - -$(TELETERRA_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleTerra -v $(VERSION) > $@ - -$(TELEDONGLE_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleDongle -v $(VERSION) > $@ - -$(TIDONGLE_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TIDongle -v $(VERSION) > $@ +$(RECURSIVE_TARGETS): + @target=`echo $@ | sed 's/-recursive//'`; \ + for subdir in $(SUBDIRS); do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + done distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f $(ALL_DEFS) $(HOST_PROGS) - rm -f $(TELEMETRUM_DEFS) $(TELETERRA_DEFS) $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS) +clean: clean-recursive -install: +install: install-recursive uninstall: - -ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h - cc -g -o $@ ao_flight_test.c - -ao_gps_test: ao_gps_sirf.c ao_gps_test.c ao_gps_print.c ao_host.h - cc -g -o $@ ao_gps_test.c - -ao_gps_test_skytraq: ao_gps_skytraq.c ao_gps_test_skytraq.c ao_gps_print.c ao_host.h - cc -g -o $@ ao_gps_test_skytraq.c diff --git a/src/Makefile.proto b/src/Makefile.proto new file mode 100644 index 00000000..958b7572 --- /dev/null +++ b/src/Makefile.proto @@ -0,0 +1,217 @@ +# +# AltOS build +# +# +vpath %.c .. +vpath %.h .. +vpath make-altitude .. +vpath ao-make-product.5c .. + +CC=sdcc + +ifndef VERSION +VERSION=$(shell git describe) +endif + +CFLAGS=--model-small --debug --opt-code-speed + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ + --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + 25lc1024.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_cmd.c \ + ao_dma.c \ + ao_mutex.c \ + ao_panic.c \ + ao_task.c \ + ao_timer.c \ + _bp.c + +# +# Shared AltOS drivers +# +ALTOS_DRIVER_SRC = \ + ao_beep.c \ + ao_config.c \ + ao_led.c \ + ao_radio.c \ + ao_stdio.c \ + ao_usb.c + +TELE_COMMON_SRC = \ + ao_packet.c \ + ao_packet_slave.c \ + ao_state.c + +# +# Receiver code +# +TELE_RECEIVER_SRC =\ + ao_monitor.c \ + ao_gps_print.c \ + ao_packet_master.c \ + ao_rssi.c + +# +# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) +# + +TELE_DRIVER_SRC = \ + ao_convert.c \ + ao_serial.c + +# +# Debug dongle driver (only on TI) +# +DBG_SRC = \ + ao_dbg.c + +# +# Drivers only on TeleMetrum +# +TM_DRIVER_SRC = \ + ao_adc.c \ + ao_gps_report.c \ + ao_ignite.c + +# +# 25LC1024 driver source +EE_DRIVER_SRC = \ + ao_ee.c + +# +# AT45DB161D driver source + +FLASH_DRIVER_SRC = \ + ao_flash.c + +# +# SiRF driver source +# +SIRF_DRIVER_SRC = \ + ao_gps_sirf.c +# +# Skytraq driver source +# +SKY_DRIVER_SRC = \ + ao_gps_skytraq.c + +# +# Tasks run on TeleMetrum +# +TM_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_report.c \ + ao_telemetry.c + +TM_MAIN_SRC = \ + ao_telemetrum.c + +# +# Base sources for TeleMetrum +# +TM_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TM_DRIVER_SRC) \ + $(TM_TASK_SRC) \ + $(TM_MAIN_SRC) + +TI_MAIN_SRC = \ + ao_tidongle.c + +# +# All sources for the TI debug dongle +# +TI_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TI_MAIN_SRC) \ + $(DBG_SRC) + +TT_MAIN_SRC = \ + ao_teleterra.c +# +# All sources for TeleTerra +# +TT_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TT_MAIN_SRC) + + +# +# Sources for TeleDongle +# + +TD_MAIN_SRC = \ + ao_teledongle.c + +TD_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TD_MAIN_SRC) + +include Makefile.defs + +REL=$(SRC:.c=.rel) ao_product.rel +ADB=$(REL:.rel=.adb) +ASM=$(REL:.rel=.asm) +LNK=$(REL:.rel=.lnk) +LST=$(REL:.rel=.lst) +RST=$(REL:.rel=.rst) +SYM=$(REL:.rel=.sym) + +PCDB=$(PROG:.ihx=.cdb) +PLNK=$(PROG:.ihx=.lnk) +PMAP=$(PROG:.ihx=.map) +PMEM=$(PROG:.ihx=.mem) +PAOM=$(PROG:.ihx=) + +%.rel : %.c $(INC) + $(CC) -c $(CFLAGS) -o$@ $< + +all: $(PROG) + +$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(REL) + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c + nickle $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/ao.h b/src/ao.h index d6be2223..b43f5ecd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -23,6 +23,7 @@ #include #include #include "cc1111.h" +#include "ao_pins.h" #define TRUE 1 #define FALSE 0 @@ -148,15 +149,7 @@ void ao_clock_init(void); /* - * ao_adc.c - */ - -#define AO_ADC_RING 32 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -/* - * One set of samples read from the A/D converter + * One set of samples read from the A/D converter or telemetry */ struct ao_adc { uint16_t tick; /* tick when the sample was read */ @@ -168,6 +161,20 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC +/* + * ao_adc.c + */ + +#define AO_ADC_RING 32 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + /* * A/D data is stored in a ring, with the next sample to be written * at ao_adc_head @@ -188,15 +195,16 @@ void ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ -#if !AO_NO_ADC_ISR + void ao_adc_isr(void) interrupt 1; -#endif /* Initialize the A/D converter */ void ao_adc_init(void); +#endif /* HAS_ADC */ + /* * ao_beep.c */ @@ -696,13 +704,16 @@ ao_dbg_init(void); * ao_serial.c */ -#if !AO_NO_SERIAL_ISR +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_1 void ao_serial_rx1_isr(void) interrupt 3; void ao_serial_tx1_isr(void) interrupt 14; -#endif char ao_serial_getchar(void) __critical; @@ -719,6 +730,7 @@ ao_serial_set_speed(uint8_t speed); void ao_serial_init(void); +#endif /* * ao_gps.c diff --git a/src/ao_adc.c b/src/ao_adc.c index 2b972e6c..50f96848 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pins.h" volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; @@ -52,11 +53,13 @@ ao_adc_isr(void) interrupt 1 a[0] = ADCL; a[1] = ADCH; if (sequence < 5) { +#if HAS_EXTERNAL_TEMP == 0 /* start next channel conversion */ /* v0.2 replaces external temp sensor with internal one */ if (sequence == 1) ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; else +#endif ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); } else { /* record this conversion series */ @@ -86,7 +89,9 @@ ao_adc_init(void) { ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ -/* (1 << 2) | v0.1 temperature */ +#if HAS_EXTERNAL_TEMP + (1 << 2) | /* v0.1 temperature */ +#endif (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ diff --git a/src/ao_config.c b/src/ao_config.c index 4349bca8..f8ea27fe 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -38,18 +38,22 @@ __xdata uint8_t ao_config_mutex; */ const uint32_t ao_radio_cal = 1186611; +#if HAS_EEPROM static void _ao_config_put(void) { ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config)); } +#endif static void _ao_config_get(void) { if (ao_config_loaded) return; +#if HAS_EEPROM ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config)); +#endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; ao_config.minor = AO_CONFIG_MINOR; @@ -149,6 +153,8 @@ ao_config_radio_channel_set(void) __reentrant ao_config_radio_channel_show(); } +#if HAS_ADC + void ao_config_main_deploy_show(void) __reentrant { @@ -259,6 +265,8 @@ ao_config_apogee_delay_set(void) __reentrant ao_config_apogee_delay_show(); } +#endif /* HAS_ADC */ + void ao_config_radio_cal_show(void) __reentrant { @@ -296,25 +304,31 @@ void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { +#if HAS_ADC { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, "d Set apogee igniter delay (in seconds)" }, +#endif /* HAS_ADC */ { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, +#if HAS_ADC { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, +#endif /* HAS_ADC */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, +#if HAS_EEPROM { 'w', ao_config_write, ao_config_write, "w Write current values to eeprom" }, +#endif { '?', ao_config_help, ao_config_help, "? Show available config variables" }, - { 0, ao_config_main_deploy_set, ao_config_main_deploy_show, + { 0, ao_config_help, ao_config_help, NULL }, }; @@ -359,6 +373,7 @@ ao_config_show(void) __reentrant (*ao_config_vars[cmd].show)(); } +#if HAS_EEPROM void ao_config_write(void) __reentrant { @@ -370,6 +385,7 @@ ao_config_write(void) __reentrant } ao_mutex_put(&ao_config_mutex); } +#endif __code struct ao_cmds ao_config_cmds[] = { { 'c', ao_config_set, "c Set config variable (? for help, s to show)" }, diff --git a/src/ao_dbg.c b/src/ao_dbg.c index b218897c..d0633f92 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -16,19 +16,12 @@ */ #include "ao.h" - -#define DBG_CLOCK (1 << 3) -#define DBG_DATA (1 << 4) -#define DBG_RESET_N (1 << 5) - -#define DBG_CLOCK_PIN (P0_3) -#define DBG_DATA_PIN (P0_4) -#define DBG_RESET_N_PIN (P0_5) +#include "ao_pins.h" static void ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { - P0 = (P0 & ~msk) | (val & msk); + DBG_PORT = (DBG_PORT & ~msk) | (val & msk); _asm nop nop @@ -40,8 +33,8 @@ ao_dbg_send_byte(uint8_t byte) { __xdata uint8_t b, d; - P0 |= DBG_DATA; - P0DIR |= DBG_DATA; + DBG_PORT |= DBG_DATA; + DBG_PORT_DIR |= DBG_DATA; for (b = 0; b < 8; b++) { d = 0; if (byte & 0x80) @@ -50,7 +43,7 @@ ao_dbg_send_byte(uint8_t byte) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); } - P0DIR &= ~DBG_DATA; + DBG_PORT_DIR &= ~DBG_DATA; } uint8_t @@ -171,20 +164,15 @@ ao_dbg_read_byte(void) static void ao_dbg_set_pins(void) { - /* Disable peripheral use of P0 */ - ADCCFG = 0; - P0SEL = 0; - - - /* make P0_4 tri-state */ - P0INP = DBG_DATA; - P2INP &= ~(P2INP_PDUP0_PULL_DOWN); + /* make DBG_DATA tri-state */ + DBG_PORT_INP |= DBG_DATA; /* Raise RESET_N and CLOCK */ - P0 = DBG_RESET_N | DBG_CLOCK; + DBG_PORT |= DBG_RESET_N | DBG_CLOCK; /* RESET_N and CLOCK are outputs now */ - P0DIR = DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR &= ~DBG_DATA; } static void diff --git a/src/ao_host.h b/src/ao_host.h index 6b42f9f9..fa03a910 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -117,30 +117,6 @@ struct ao_cmds { }; -static int16_t altitude_table[2048] = { -#include "altitude.h" -}; - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t pres; - - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; -} - struct ao_config { uint16_t main_deploy; int16_t accel_zero_g; diff --git a/src/ao_packet.c b/src/ao_packet.c index 98fdcb90..dcd1647c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -113,6 +113,11 @@ ao_packet_recv(void) return dma_done; } +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER void ao_packet_flush(void) { @@ -122,12 +127,15 @@ ao_packet_flush(void) if (ao_packet_tx_used && ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); } +#endif /* PACKET_HAS_MASTER */ void ao_packet_putchar(char c) __reentrant { while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER ao_packet_flush(); +#endif ao_sleep(&tx_data); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 122c4da0..4c947fbf 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -56,5 +56,5 @@ ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, - ao_packet_flush); + NULL); } diff --git a/src/ao_pins.h b/src/ao_pins.h new file mode 100644 index 00000000..84d8a1a1 --- /dev/null +++ b/src/ao_pins.h @@ -0,0 +1,144 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_0_2) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED) +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) +#endif + +#if defined(TIDONGLE) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED) +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/ao_reboot.c b/src/ao_reboot.c new file mode 100644 index 00000000..82ea32e0 --- /dev/null +++ b/src/ao_reboot.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +/* Use the watchdog timer to force a complete reboot + */ +void +ao_reboot(void) +{ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; + ao_sleep(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 7bc416e1..8add30b8 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -38,7 +38,8 @@ putchar(char c) void flush(void) { - stdios[ao_cur_stdio].flush(); + if (stdios[ao_cur_stdio].flush) + stdios[ao_cur_stdio].flush(); } __xdata uint8_t ao_stdin_ready; diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index e4828d80..b07b1746 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -15,8 +15,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#define AO_NO_SERIAL_ISR 1 -#define AO_NO_ADC_ISR 1 #include "ao.h" void @@ -35,6 +33,9 @@ main(void) ao_radio_init(); ao_packet_slave_init(); ao_packet_master_init(); +#if HAS_DBG + ao_dbg_init(); +#endif ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 89743837..fd0adae8 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pins.h" /* stub so as telemetrum doesn't have monitor mode */ void @@ -31,7 +32,7 @@ main(void) /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED); + ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); /* A hack -- look at the SPI clock pin, if it's sitting at @@ -59,6 +60,9 @@ main(void) ao_radio_init(); ao_packet_slave_init(); ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_timer.c b/src/ao_timer.c index e81f937d..d1731475 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -36,24 +36,30 @@ ao_delay(uint16_t ticks) #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ +#if HAS_ADC volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; +#endif void ao_timer_isr(void) interrupt 9 { ++ao_tick_count; +#if HAS_ADC if (++ao_adc_count == ao_adc_interval) { ao_adc_count = 0; ao_adc_poll(); } +#endif } +#if HAS_ADC void ao_timer_set_adc_interval(uint8_t interval) __critical { ao_adc_interval = interval; ao_adc_count = 0; } +#endif void ao_timer_init(void) diff --git a/src/teledongle-v0.1/Makefile b/src/teledongle-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/teledongle-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs new file mode 100644 index 00000000..3526b4c5 --- /dev/null +++ b/src/teledongle-v0.1/Makefile.defs @@ -0,0 +1,9 @@ +PROG = teledongle-v0.1.ihx + +SRC = \ + $(TD_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleDongle-v0.1 + +CFLAGS += -DTELEDONGLE_V_0_1 -I. diff --git a/src/teledongle-v0.2/Makefile b/src/teledongle-v0.2/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/teledongle-v0.2/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs new file mode 100644 index 00000000..faad4dce --- /dev/null +++ b/src/teledongle-v0.2/Makefile.defs @@ -0,0 +1,9 @@ +PROG = teledongle-v0.2.ihx + +SRC = \ + $(TD_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleDongle-v0.2 + +CFLAGS += -DTELEDONGLE_V_0_2 -I. diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs new file mode 100644 index 00000000..1157d679 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.1-sirf.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(EE_DRIVER_SRC) \ + $(SIRF_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.1-SiRF + +CFLAGS += -DTELEMETRUM_V_0_1 -I. diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.1-sky/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs new file mode 100644 index 00000000..ff7fd1bf --- /dev/null +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.1-sky.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(EE_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.1 + +CFLAGS += -DTELEMETRUM_V_0_1 -I. diff --git a/src/telemetrum-v0.2/Makefile b/src/telemetrum-v0.2/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.2/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs new file mode 100644 index 00000000..d5b0a962 --- /dev/null +++ b/src/telemetrum-v0.2/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.2.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.2 + +CFLAGS += -DTELEMETRUM_V_0_2 -I. diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 00000000..f6e9b9f5 --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,24 @@ +vpath % .. + +PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq ao_convert_test + +CFLAGS=-I.. -I. + +all: $(PROGS) + +clean: + rm -f $(PROGS) + +install: + +ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h + cc -g -o $@ $< + +ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h + cc -g -o $@ $< + +ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h + cc -g -o $@ $< + +ao_convert_test: ao_convert_test.c ao_convert.c altitude.h + cc -g -o $@ $< diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/tidongle/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs new file mode 100644 index 00000000..16762940 --- /dev/null +++ b/src/tidongle/Makefile.defs @@ -0,0 +1,8 @@ +PROG = tidongle.ihx + +SRC = \ + $(TI_SRC) + +PRODUCT=TIDongle + +CFLAGS += -DTIDONGLE -I. -- cgit v1.2.3 From 004c2a9b7a4b44ef71ca60482573e8e9d8c6ce93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:36:08 -0800 Subject: Update .gitignore files --- .gitignore | 7 ++----- debian/.gitignore | 6 ++++++ src/teledongle-v0.1/.gitignore | 2 ++ src/teledongle-v0.2/.gitignore | 2 ++ src/telemetrum-v0.1-sirf/.gitignore | 2 ++ src/telemetrum-v0.1-sky/.gitignore | 2 ++ src/telemetrum-v0.2/.gitignore | 2 ++ src/test/.gitignore | 4 ++++ src/tidongle/.gitignore | 2 ++ 9 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 debian/.gitignore create mode 100644 src/teledongle-v0.1/.gitignore create mode 100644 src/teledongle-v0.2/.gitignore create mode 100644 src/telemetrum-v0.1-sirf/.gitignore create mode 100644 src/telemetrum-v0.1-sky/.gitignore create mode 100644 src/telemetrum-v0.2/.gitignore create mode 100644 src/test/.gitignore create mode 100644 src/tidongle/.gitignore diff --git a/.gitignore b/.gitignore index a6f94439..eafee20f 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,8 @@ config.h.in config.h.in~ config.log config.status +build-stamp +configure-stamp configure depcomp install-sh @@ -47,8 +49,3 @@ Makefile.in missing stamp-h1 tags -teledongle -telemetrum-sirf -telemetrum-sky -teleterra -tidongle diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 00000000..850d7c20 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,6 @@ +altos.debhelper.log +altos.postinst.debhelper +altos.postrm.debhelper +altos.substvars +altos +files diff --git a/src/teledongle-v0.1/.gitignore b/src/teledongle-v0.1/.gitignore new file mode 100644 index 00000000..96c802bd --- /dev/null +++ b/src/teledongle-v0.1/.gitignore @@ -0,0 +1,2 @@ +teledongle-v0.1 +ao_product.h diff --git a/src/teledongle-v0.2/.gitignore b/src/teledongle-v0.2/.gitignore new file mode 100644 index 00000000..af79a766 --- /dev/null +++ b/src/teledongle-v0.2/.gitignore @@ -0,0 +1,2 @@ +teledongle-v0.2 +ao_product.h diff --git a/src/telemetrum-v0.1-sirf/.gitignore b/src/telemetrum-v0.1-sirf/.gitignore new file mode 100644 index 00000000..6d584f36 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sirf +ao_product.h diff --git a/src/telemetrum-v0.1-sky/.gitignore b/src/telemetrum-v0.1-sky/.gitignore new file mode 100644 index 00000000..5a9fafb5 --- /dev/null +++ b/src/telemetrum-v0.1-sky/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky +ao_product.h diff --git a/src/telemetrum-v0.2/.gitignore b/src/telemetrum-v0.2/.gitignore new file mode 100644 index 00000000..76228093 --- /dev/null +++ b/src/telemetrum-v0.2/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.2 +ao_product.h diff --git a/src/test/.gitignore b/src/test/.gitignore new file mode 100644 index 00000000..54b00096 --- /dev/null +++ b/src/test/.gitignore @@ -0,0 +1,4 @@ +ao_flight_test +ao_gps_test +ao_gps_test_skytraq +ao_convert_test diff --git a/src/tidongle/.gitignore b/src/tidongle/.gitignore new file mode 100644 index 00000000..3323f640 --- /dev/null +++ b/src/tidongle/.gitignore @@ -0,0 +1,2 @@ +tidongle +ao_product.h -- cgit v1.2.3 From 18eeb79026f7e5c54bf99435537c024427011a36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:05:45 -0800 Subject: Quiet make output. This borrows ideas from the notmuch project to reduce the command line clutter seen when compiling or linking stuff. Signed-off-by: Keith Packard --- src/Makefile.proto | 27 ++++++++++++++++++++------- src/teledongle-v0.1/Makefile.defs | 3 +-- src/teledongle-v0.2/Makefile.defs | 3 +-- src/telemetrum-v0.1-sirf/Makefile.defs | 3 +-- src/telemetrum-v0.1-sky/Makefile.defs | 3 +-- src/telemetrum-v0.2/Makefile.defs | 3 +-- src/tidongle/Makefile.defs | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 958b7572..c98abca6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -174,6 +174,10 @@ TD_SRC = \ include Makefile.defs +CFLAGS += $(PRODUCT_DEF) -I. + +NICKLE=nickle + REL=$(SRC:.c=.rel) ao_product.rel ADB=$(REL:.rel=.adb) ASM=$(REL:.rel=.asm) @@ -188,29 +192,38 @@ PMAP=$(PROG:.ihx=.map) PMEM=$(PROG:.ihx=.mem) PAOM=$(PROG:.ihx=) +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + %.rel : %.c $(INC) - $(CC) -c $(CFLAGS) -o$@ $< + $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< -all: $(PROG) +all: ../$(PROG) -$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(REL) +../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. ../altitude.h: make-altitude nickle $< > $@ ao_product.h: ao-make-product.5c - nickle $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ ao_product.rel: ao_product.c ao_product.h - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< distclean: clean clean: rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) rm -f ao_product.h + rm -f ../$(PROG) install: diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index 3526b4c5..06559b28 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -5,5 +5,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleDongle-v0.1 - -CFLAGS += -DTELEDONGLE_V_0_1 -I. +PRODUCT_DEF=-DTELEDONGLE_V_0_1 diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index faad4dce..23694fda 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -5,5 +5,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleDongle-v0.2 - -CFLAGS += -DTELEDONGLE_V_0_2 -I. +PRODUCT_DEF=-DTELEDONGLE_V_0_2 diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 1157d679..7306683e 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.1-SiRF - -CFLAGS += -DTELEMETRUM_V_0_1 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_1 diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index ff7fd1bf..df475baa 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.1 - -CFLAGS += -DTELEMETRUM_V_0_1 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_1 diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs index d5b0a962..eb11e7dc 100644 --- a/src/telemetrum-v0.2/Makefile.defs +++ b/src/telemetrum-v0.2/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.2 - -CFLAGS += -DTELEMETRUM_V_0_2 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_2 diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index 16762940..5b910b9b 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -5,4 +5,4 @@ SRC = \ PRODUCT=TIDongle -CFLAGS += -DTIDONGLE -I. +PRODUCT_DEF=-DTIDONGLE -- cgit v1.2.3 From a5215c2bd9249a285fc834db0c453fb3e7daed87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:20:05 -0800 Subject: Add back stack size checking to altos linking phase This verifies that the stack start specified during the compile will work with the resulting program Signed-off-by: Keith Packard --- src/Makefile.proto | 2 ++ src/check-stack | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index c98abca6..4f4252ad 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -177,6 +177,7 @@ include Makefile.defs CFLAGS += $(PRODUCT_DEF) -I. NICKLE=nickle +CHECK_STACK=sh ../check-stack REL=$(SRC:.c=.rel) ao_product.rel ADB=$(REL:.rel=.adb) @@ -207,6 +208,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. + $(call quiet,CHECK_STACK) ../ao.h $(@F:.ihx=.mem) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/check-stack b/src/check-stack index 82680b88..1e8044e0 100755 --- a/src/check-stack +++ b/src/check-stack @@ -2,12 +2,11 @@ HEADER=$1 MEM=$2 -HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER | nickle` -MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM | nickle` +HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` +MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then - MIN=0x`nickle -e "$MEM_STACK # 16"` - echo "Set AO_STACK_START to at least $MIN" + echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' exit 1 else exit 0 -- cgit v1.2.3 From 82fdbfe1229d1ea5e6906ea240d54b3da73d9a69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:35:43 -0800 Subject: Must install .map files for ao-load to work ao-load uses the .map files to rewrite the serial number and other config parameters into the program flash. Signed-off-by: Keith Packard --- src/Makefile.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 4f4252ad..6cb6e0de 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,8 +207,8 @@ quiet ?= $($1) all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. - $(call quiet,CHECK_STACK) ../ao.h $(@F:.ihx=.mem) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../ao.h $(PMEM) ../altitude.h: make-altitude nickle $< > $@ -- cgit v1.2.3 From 24912821b3230b8357b9e0094cd69fa0bccc5513 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 14:53:27 -0700 Subject: update changelogs for Debian build --- ChangeLog | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 31 ++++++++ 2 files changed, 262 insertions(+) diff --git a/ChangeLog b/ChangeLog index cee5bdee..263b41d1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,234 @@ +commit 82fdbfe1229d1ea5e6906ea240d54b3da73d9a69 +Author: Keith Packard +Date: Sat Feb 20 21:35:43 2010 -0800 + + Must install .map files for ao-load to work + + ao-load uses the .map files to rewrite the serial number and other + config parameters into the program flash. + + Signed-off-by: Keith Packard + +commit a5215c2bd9249a285fc834db0c453fb3e7daed87 +Author: Keith Packard +Date: Sat Feb 20 21:20:05 2010 -0800 + + Add back stack size checking to altos linking phase + + This verifies that the stack start specified during the compile + will work with the resulting program + + Signed-off-by: Keith Packard + +commit 18eeb79026f7e5c54bf99435537c024427011a36 +Author: Keith Packard +Date: Sat Feb 20 21:05:45 2010 -0800 + + Quiet make output. + + This borrows ideas from the notmuch project to reduce the command line + clutter seen when compiling or linking stuff. + + Signed-off-by: Keith Packard + +commit 004c2a9b7a4b44ef71ca60482573e8e9d8c6ce93 +Author: Keith Packard +Date: Sat Feb 20 20:36:08 2010 -0800 + + Update .gitignore files + +commit 84c93bb2fc4558a5e4654794ba90e730a84eaf67 +Author: Keith Packard +Date: Sat Feb 20 20:22:16 2010 -0800 + + Change altos build process to support per-product compile-time changes + + This creates per-product subdirectories and recompiles everything for + each product, allowing per-product compile-time changes for things + like peripheral pin assignments and attached serial devices. + + Signed-off-by: Keith Packard + +commit fd0a42e0e96dcb8ecc9e999f70bcf70692692af9 +Author: Keith Packard +Date: Sat Feb 20 20:21:07 2010 -0800 + + Change barometer conversion code to shrink conversion table + +commit 876e9a10b9096ead85fbe08ec9a6a0329cf7cbd4 +Author: Keith Packard +Date: Sat Feb 13 16:42:27 2010 -0800 + + Log GPS data on pad after boost detect. + + This wakes up the two GPS reporting tasks and gets them to report out + any existing GPS data to the log file. To make sure the timestamps in + that GPS data are accurate, this also records GPS time on receipt of + the GPS data instead of when that is logged. + + Signed-off-by: Keith Packard + +commit c83615567b4567f3dc45a7f7b894943b45fbb65c +Author: Keith Packard +Date: Sun Feb 7 00:25:22 2010 -0800 + + Pull in a bit more data for filtering the start of the boost + +commit f8967607b3dda0c0ce7afe8bb077da2da5ed3dcd +Author: Keith Packard +Date: Sun Feb 7 00:24:56 2010 -0800 + + Compute daytime using GPS as time base + +commit 2a6350149407c7d2e7d143906c40c5e331248aeb +Author: Keith Packard +Date: Thu Feb 11 18:48:56 2010 -0800 + + Missing ao_mutex_put in gps_dump + +commit 9856b7c4397afcecc8f541af9a83824e817b3612 +Author: Keith Packard +Date: Sun Jan 10 16:31:50 2010 -0800 + + Switch to using internal cc1111 temperature sensor + + v0.2 has no temperature sensor, and several of the v0.1 boards didn't + get a temperature sensor loaded. Use the internal temperature sensor + on the cc1111 in all cases instead. + + Signed-off-by: Keith Packard + +commit 0c2533be15858774ef9381aa8c8344356fd5b971 +Author: Keith Packard +Date: Sat Jan 9 22:06:19 2010 -0800 + + Force idle mode by shorting the SPI clock to ground at boot time. + + This allows you to override the flight mode detection code in case the + accelerometer calibration is broken somehow. Hold the SPI clock shoted + to ground until the LED comes on, then remove it. + + Signed-off-by: Keith Packard + +commit 28346736a7799c0767e54511d9949cd61d35e471 +Author: Keith Packard +Date: Sat Jan 9 20:57:48 2010 -0800 + + Add simple gps dump command 'g' + + This just dumps out the data in a very simple format to verify the GPS + receiver. + + Signed-off-by: Keith Packard + +commit a6082a8b4501ac4cb18584ace1f0c40e088e5484 +Author: Keith Packard +Date: Sat Jan 9 20:57:29 2010 -0800 + + Remove flash debugging printfs + + Signed-off-by: Keith Packard + +commit 05bb953830604721c9a49dd56256b86f3666b5ff +Author: Keith Packard +Date: Sat Jan 9 20:42:57 2010 -0800 + + Don't set ao_flash_setup_done until we're actually done. + + Because we're accessing this variable outside of the mutex, we need to + make sure it isn't set until the data it covers has been initialized. + + Signed-off-by: Keith Packard + +commit 327e5e782958e516a7b7a786ab6c176b0decb8b8 +Author: Keith Packard +Date: Sat Jan 9 20:04:42 2010 -0800 + + Dump config block from read/write config and flash_status commands + +commit 05e5bb2d330b755967d06fb859585c81f5f5fbb5 +Author: Keith Packard +Date: Sat Jan 9 19:46:46 2010 -0800 + + Dump more flash parameters for the flash_status command + +commit d4c8895b349998e02e03ed83466a0ca7afb3d99b +Author: Keith Packard +Date: Sat Jan 9 17:57:52 2010 -0800 + + Add 'f' command to display flash status register contents + + Signed-off-by: Keith Packard + +commit c1334f712f01543adb10809bc1a3ca120e27290b +Author: Keith Packard +Date: Sat Jan 9 09:55:04 2010 -0800 + + Add at45db161d.h header file for new flash part. + + Forgot to add this when I added the driver. + + Signed-off-by: Keith Packard + +commit a0d4c1b06d27e850d233f8ddf8fe32912bf0ec8f +Author: Keith Packard +Date: Sat Jan 9 01:29:41 2010 -0800 + + Remove green LED and temp sensor from v0.2 code + + Signed-off-by: Keith Packard + +commit dc8d18736239b14c2ec48a40a01515912c5c25e6 +Author: Keith Packard +Date: Sat Jan 9 01:22:06 2010 -0800 + + Add AT45DBxx1D driver + + This driver supports the AT45DB011D through AT45DB321D DataFlash + parts as found in TeleMetrum v0.2 + + Signed-off-by: Keith Packard + +commit 3bab7e66d25988f5d63ec139c8814a85b983f8f3 +Author: Keith Packard +Date: Sat Dec 19 20:32:18 2009 -0800 + + Remove dbg driver code from telemetrum/teledongle + + The only board with debug outputs is the TI dongle at this point, so + the debug modules were disabled in TM and TD some time + ago. Unfortunately, the code was not removed then. + + Signed-off-by: Keith Packard + +commit eddb82390a0ecb07ef83c04861993842906b03ab +Author: Keith Packard +Date: Sat Dec 19 15:31:36 2009 -0800 + + Ensure that ao_alarm waits at least the specified time + + Because the timer tick may happen soon, it's important to delay by + another tick to ensure that we don't wake up early. + + Signed-off-by: Keith Packard + +commit 598d168bd6552c3756e4b0267de44147eadab9f6 +Author: Keith Packard +Date: Sat Dec 19 14:03:11 2009 -0800 + + Disable monitor mode before attempting radio test. + + If monitor mode is left active, then the radio lock will not be able + to be acquired for the radio test. + + Signed-off-by: Keith Packard + +commit d4cf1446680d8b47396bcda338e8df7af395d102 +Author: Bdale Garbee +Date: Sat Dec 19 13:53:38 2009 -0700 + + update changelogs for Debian build + commit 10d1bbcd9709a5eee8d50989215242b16feb7232 Author: Keith Packard Date: Sat Dec 19 11:34:16 2009 -0800 diff --git a/debian/changelog b/debian/changelog index b988eea8..2f43f627 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,34 @@ +altos (0.6+85+g82fdbfe) unstable; urgency=low + + [ Keith Packard ] + * Disable monitor mode before attempting radio test. + * Ensure that ao_alarm waits at least the specified time + * Remove dbg driver code from telemetrum/teledongle + * Add AT45DBxx1D driver + * Remove green LED and temp sensor from v0.2 code + * Add at45db161d.h header file for new flash part. + * Add 'f' command to display flash status register contents + * Dump more flash parameters for the flash_status command + * Dump config block from read/write config and flash_status commands + * Don't set ao_flash_setup_done until we're actually done. + * Remove flash debugging printfs + * Add simple gps dump command 'g' + * Force idle mode by shorting the SPI clock to ground at boot time. + * Switch to using internal cc1111 temperature sensor + * Missing ao_mutex_put in gps_dump + * Compute daytime using GPS as time base + * Pull in a bit more data for filtering the start of the boost + * Log GPS data on pad after boost detect. + * Change barometer conversion code to shrink conversion table + * Change altos build process to support per-product compile-time + changes + * Update .gitignore files + * Quiet make output. + * Add back stack size checking to altos linking phase + * Must install .map files for ao-load to work + + -- Bdale Garbee Wed, 24 Feb 2010 14:53:01 -0700 + altos (0.6+60+g10d1bbc) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From ac45da6e61597dcdb119b976f7301b2cc7fdced4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 14:57:26 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 263b41d1..fa1cf175 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 24912821b3230b8357b9e0094cd69fa0bccc5513 +Author: Bdale Garbee +Date: Wed Feb 24 14:53:27 2010 -0700 + + update changelogs for Debian build + commit 82fdbfe1229d1ea5e6906ea240d54b3da73d9a69 Author: Keith Packard Date: Sat Feb 20 21:35:43 2010 -0800 diff --git a/debian/changelog b/debian/changelog index 2f43f627..e5a3d559 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+85+g82fdbfe) unstable; urgency=low +altos (0.6+86+g2491282) unstable; urgency=low [ Keith Packard ] * Disable monitor mode before attempting radio test. -- cgit v1.2.3 From deccc10f0305c0cd02bf6317d6dc9d2ae38c3dac Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 16:43:32 -0700 Subject: add gawk as a build dependency since strtonum is a gawk extension --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 63aa48df..7d21e602 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -Build-Depends: debhelper (>= 7), autoconf, automake, flite1-dev, libasound2-dev, libgconf2-dev, libglade2-dev, libgtk2.0-dev, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, libplplot-dev +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 Standards-Version: 3.8.3 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From cf091a7252eba09902a42a3cfe7b4d6a343907ce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 16:44:44 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index fa1cf175..dbcce6e5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit deccc10f0305c0cd02bf6317d6dc9d2ae38c3dac +Author: Bdale Garbee +Date: Wed Feb 24 16:43:32 2010 -0700 + + add gawk as a build dependency since strtonum is a gawk extension + +commit ac45da6e61597dcdb119b976f7301b2cc7fdced4 +Author: Bdale Garbee +Date: Wed Feb 24 14:57:26 2010 -0700 + + update changelogs for Debian build + commit 24912821b3230b8357b9e0094cd69fa0bccc5513 Author: Bdale Garbee Date: Wed Feb 24 14:53:27 2010 -0700 diff --git a/debian/changelog b/debian/changelog index e5a3d559..e489a560 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+88+gdeccc10) unstable; urgency=low + + * add gawk as a build dependency since strtonum is a gawk extension + + -- Bdale Garbee Wed, 24 Feb 2010 16:44:35 -0700 + altos (0.6+86+g2491282) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From c74958d3e8c5ce8006a9f9f6853238fce0c77432 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:13:29 -0700 Subject: move git-using variable declaration into the prebuild target --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 260ba773..343cd71a 100755 --- a/debian/rules +++ b/debian/rules @@ -3,10 +3,10 @@ export DH_VERBOSE=1 PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') -DEB_VERSION := $(shell git describe | tr - +) # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: + DEB_VERSION := $(shell git describe | tr - +) git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog git commit -n ChangeLog debian/changelog \ -- cgit v1.2.3 From 4b6b28530206c6fdbe46699b81746fbbcab5b148 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:22:20 -0700 Subject: see if this works --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 343cd71a..f4e9f840 100755 --- a/debian/rules +++ b/debian/rules @@ -3,10 +3,10 @@ export DH_VERBOSE=1 PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') +DEB_VERSION := $(shell -git describe | tr - +) # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: - DEB_VERSION := $(shell git describe | tr - +) git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog git commit -n ChangeLog debian/changelog \ -- cgit v1.2.3 From 54dd7a200e6956aace5a580d4c4d6a10a13c654b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:22:45 -0700 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index dbcce6e5..ba8ea240 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 4b6b28530206c6fdbe46699b81746fbbcab5b148 +Author: Bdale Garbee +Date: Wed Feb 24 17:22:20 2010 -0700 + + see if this works + +commit c74958d3e8c5ce8006a9f9f6853238fce0c77432 +Author: Bdale Garbee +Date: Wed Feb 24 17:13:29 2010 -0700 + + move git-using variable declaration into the prebuild target + +commit cf091a7252eba09902a42a3cfe7b4d6a343907ce +Author: Bdale Garbee +Date: Wed Feb 24 16:44:44 2010 -0700 + + update changelogs for Debian build + commit deccc10f0305c0cd02bf6317d6dc9d2ae38c3dac Author: Bdale Garbee Date: Wed Feb 24 16:43:32 2010 -0700 diff --git a/debian/changelog b/debian/changelog index e489a560..ed4b6271 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+88+gdeccc11) unstable; urgency=low + + * move git-using variable declaration into the prebuild target + * see if this works + + -- Bdale Garbee Wed, 24 Feb 2010 17:22:38 -0700 + altos (0.6+88+gdeccc10) unstable; urgency=low * add gawk as a build dependency since strtonum is a gawk extension -- cgit v1.2.3 From cdccd92f6ed97be7385e84de5694064cb8f43946 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:25:28 -0700 Subject: conditionalize use of git on executability of /usr/bin/git binary --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index f4e9f840..f6efe990 100755 --- a/debian/rules +++ b/debian/rules @@ -3,7 +3,7 @@ export DH_VERBOSE=1 PKG_VERSION := $(shell dpkg-parsechangelog | sed -ne 's/^Version: \(.*\)/\1/p') -DEB_VERSION := $(shell -git describe | tr - +) +DEB_VERSION := $(shell if [ -x /usr/bin/git ]; then git describe; else echo 0; fi | tr - +) # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: -- cgit v1.2.3 From 540f86678853e7ea80ae91f3f2ec0ec88c5b1ca7 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:27:51 -0700 Subject: debugging --- debian/rules | 1 + 1 file changed, 1 insertion(+) diff --git a/debian/rules b/debian/rules index f6efe990..780011b7 100755 --- a/debian/rules +++ b/debian/rules @@ -7,6 +7,7 @@ DEB_VERSION := $(shell if [ -x /usr/bin/git ]; then git describe; else echo 0; f # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: + echo $(DEB_VERSION) git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog git commit -n ChangeLog debian/changelog \ -- cgit v1.2.3 From 2f45953ee54034209a23c254e65da36e44cf075f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:29:47 -0700 Subject: un-muck changelog --- debian/changelog | 7 ------- 1 file changed, 7 deletions(-) diff --git a/debian/changelog b/debian/changelog index ed4b6271..e489a560 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,3 @@ -altos (0.6+88+gdeccc11) unstable; urgency=low - - * move git-using variable declaration into the prebuild target - * see if this works - - -- Bdale Garbee Wed, 24 Feb 2010 17:22:38 -0700 - altos (0.6+88+gdeccc10) unstable; urgency=low * add gawk as a build dependency since strtonum is a gawk extension -- cgit v1.2.3 From d7d551b0078acb1596a9b9023c3df6dbfa46213c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Feb 2010 17:30:23 -0700 Subject: update changelogs for Debian build --- ChangeLog | 24 ++++++++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 31 insertions(+) diff --git a/ChangeLog b/ChangeLog index ba8ea240..d365896f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +commit 2f45953ee54034209a23c254e65da36e44cf075f +Author: Bdale Garbee +Date: Wed Feb 24 17:29:47 2010 -0700 + + un-muck changelog + +commit 540f86678853e7ea80ae91f3f2ec0ec88c5b1ca7 +Author: Bdale Garbee +Date: Wed Feb 24 17:27:51 2010 -0700 + + debugging + +commit cdccd92f6ed97be7385e84de5694064cb8f43946 +Author: Bdale Garbee +Date: Wed Feb 24 17:25:28 2010 -0700 + + conditionalize use of git on executability of /usr/bin/git binary + +commit 54dd7a200e6956aace5a580d4c4d6a10a13c654b +Author: Bdale Garbee +Date: Wed Feb 24 17:22:45 2010 -0700 + + update changelogs for Debian build + commit 4b6b28530206c6fdbe46699b81746fbbcab5b148 Author: Bdale Garbee Date: Wed Feb 24 17:22:20 2010 -0700 diff --git a/debian/changelog b/debian/changelog index e489a560..b79ee067 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+95+g2f45953) unstable; urgency=low + + * update changelogs for Debian build + * conditionalize use of git on executability of /usr/bin/git binary + + -- Bdale Garbee Wed, 24 Feb 2010 17:30:00 -0700 + altos (0.6+88+gdeccc10) unstable; urgency=low * add gawk as a build dependency since strtonum is a gawk extension -- cgit v1.2.3 From f4d5790a284e2d02dd7568fbca90402fa5ed1aea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Feb 2010 16:32:57 -0800 Subject: Add ao_radio_xmit to help test boards without flashing them. Signed-off-by: Keith Packard --- ao-bringup/Makefile | 50 +++++++++ ao-bringup/ao_bringup.h | 33 ++++++ ao-bringup/ao_init.c | 28 +++++ ao-bringup/ao_radio_init.c | 251 +++++++++++++++++++++++++++++++++++++++++++++ ao-bringup/ao_radio_test.c | 18 ++++ ao-bringup/ao_radio_xmit.c | 28 +++++ 6 files changed, 408 insertions(+) create mode 100644 ao-bringup/Makefile create mode 100644 ao-bringup/ao_bringup.h create mode 100644 ao-bringup/ao_init.c create mode 100644 ao-bringup/ao_radio_init.c create mode 100644 ao-bringup/ao_radio_test.c create mode 100644 ao-bringup/ao_radio_xmit.c diff --git a/ao-bringup/Makefile b/ao-bringup/Makefile new file mode 100644 index 00000000..805b2550 --- /dev/null +++ b/ao-bringup/Makefile @@ -0,0 +1,50 @@ +CC=sdcc +DEBUG=--debug + +CFLAGS=--model-small --debug -I../src + +LDFLAGS=--out-fmt-ihx --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024 --iram-size 0xff + +INC = \ + ao_bringup.h + +BRINGUP_SRC = ao_init.c + +BRINGUP_REL=$(BRINGUP_SRC:.c=.rel) + +XMIT_SRC = \ + ao_radio_init.c \ + ao_radio_xmit.c +XMIT_REL=$(XMIT_SRC:.c=.rel) $(BRINGUP_REL) + +SRC=$(BRINGUP_SRC) $(XMIT_SRC) + +ADB=$(SRC:.c=.adb) +ASM=$(SRC:.c=.asm) +LNK=$(SRC:.c=.lnk) +LST=$(SRC:.c=.lst) +REL=$(SRC:.c=.rel) +RST=$(SRC:.c=.rst) +SYM=$(SRC:.c=.sym) + +PROGS=ao_radio_xmit.ihx + +PCDB=$(PROGS:.ihx=.cdb) +PLNK=$(PROGS:.ihx=.lnk) +PMAP=$(PROGS:.ihx=.map) +PMEM=$(PROGS:.ihx=.mem) +PAOM=$(PROGS:.ihx=) + +%.rel : %.c + $(CC) -c $(CFLAGS) -o$*.rel $< + +all: $(PROGS) + +ao_radio_xmit.ihx: $(XMIT_REL) + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(XMIT_REL) + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + +install: diff --git a/ao-bringup/ao_bringup.h b/ao-bringup/ao_bringup.h new file mode 100644 index 00000000..99fa4fba --- /dev/null +++ b/ao-bringup/ao_bringup.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BRINGUP_H_ +#define _AO_BRINGUP_H_ + +#include +#include + +void +ao_radio_init(void); + +void +ao_radio_idle(void); + +void +ao_init(void); + +#endif diff --git a/ao-bringup/ao_init.c b/ao-bringup/ao_init.c new file mode 100644 index 00000000..5dababde --- /dev/null +++ b/ao-bringup/ao_init.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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_bringup.h" + +void +ao_init(void) +{ + CLKCON = 0; + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + P1 = 0; + P1DIR = 3; +} diff --git a/ao-bringup/ao_radio_init.c b/ao-bringup/ao_radio_init.c new file mode 100644 index 00000000..11932506 --- /dev/null +++ b/ao-bringup/ao_radio_init.c @@ -0,0 +1,251 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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_bringup.h" + +/* Values from SmartRF® Studio for: + * + * Deviation: 20.507812 kHz + * Datarate: 38.360596 kBaud + * Modulation: GFSK + * RF Freq: 434.549927 MHz + * Channel: 99.975586 kHz + * Channel: 0 + * RX filter: 93.75 kHz + */ + +/* + * For 434.550MHz, the frequency value is: + * + * 434.550e6 / (24e6 / 2**16) = 1186611.2 + */ + +#define FREQ_CONTROL 1186611 + +/* + * For IF freq of 140.62kHz, the IF value is: + * + * 140.62e3 / (24e6 / 2**10) = 6 + */ + +#define IF_FREQ_CONTROL 6 + +/* + * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are + * + * BW = 24e6 / (8 * (4 + M) * 2 ** E) + * + * So, M = 0 and E = 3 + */ + +#define CHANBW_M 0 +#define CHANBW_E 3 + +/* + * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are: + * + * R = (256 + M) * 2** E * 24e6 / 2**28 + * + * So M is 163 and E is 10 + */ + +#define DRATE_E 10 +#define DRATE_M 163 + +/* + * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are: + * + * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E + * + * So M is 6 and E is 3 + */ + +#define DEVIATION_M 6 +#define DEVIATION_E 3 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), + * so the DRATE_E and DRATE_M values are: + * + * M is 94 and E is 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ + +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 94 +#define RDF_PACKET_LEN 50 + +/* + * RDF deviation should match the normal NFM value of 5kHz + * + * M is 6 and E is 1 + * + */ + +#define RDF_DEVIATION_M 6 +#define RDF_DEVIATION_E 1 + +/* This are from the table for 433MHz */ + +#define RF_POWER_M30_DBM 0x12 +#define RF_POWER_M20_DBM 0x0e +#define RF_POWER_M15_DBM 0x1d +#define RF_POWER_M10_DBM 0x34 +#define RF_POWER_M5_DBM 0x2c +#define RF_POWER_0_DBM 0x60 +#define RF_POWER_5_DBM 0x84 +#define RF_POWER_7_DBM 0xc8 +#define RF_POWER_10_DBM 0xc0 + +#define RF_POWER RF_POWER_10_DBM + +static __code uint8_t radio_setup[] = { + RF_PA_TABLE7_OFF, RF_POWER, + RF_PA_TABLE6_OFF, RF_POWER, + RF_PA_TABLE5_OFF, RF_POWER, + RF_PA_TABLE4_OFF, RF_POWER, + RF_PA_TABLE3_OFF, RF_POWER, + RF_PA_TABLE2_OFF, RF_POWER, + RF_PA_TABLE1_OFF, RF_POWER, + RF_PA_TABLE0_OFF, RF_POWER, + + RF_FREQ2_OFF, (FREQ_CONTROL >> 16) & 0xff, + RF_FREQ1_OFF, (FREQ_CONTROL >> 8) & 0xff, + RF_FREQ0_OFF, (FREQ_CONTROL) & 0xff, + + RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), + RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), + + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + RF_MDMCFG0_OFF, (17 << RF_MDMCFG0_CHANSPC_M_SHIFT), + + RF_CHANNR_OFF, 0, + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* SmartRF says set LODIV_BUF_CURRENT_TX to 0 + * And, we're not using power ramping, so use PA_POWER 0 + */ + RF_FREND0_OFF, ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) | + (0 << RF_FREND0_PA_POWER_SHIFT)), + + RF_FREND1_OFF, ((1 << RF_FREND1_LNA_CURRENT_SHIFT) | + (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) | + (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) | + (2 << RF_FREND1_MIX_CURRENT_SHIFT)), + + RF_FSCAL3_OFF, 0xE9, + RF_FSCAL2_OFF, 0x0A, + RF_FSCAL1_OFF, 0x00, + RF_FSCAL0_OFF, 0x1F, + + RF_TEST2_OFF, 0x88, + RF_TEST1_OFF, 0x31, + RF_TEST0_OFF, 0x09, + + /* default sync values */ + RF_SYNC1_OFF, 0xD3, + RF_SYNC0_OFF, 0x91, + + /* max packet length */ + RF_PKTLEN_OFF, 64, + + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), + RF_ADDR_OFF, 0x00, + RF_MCSM2_OFF, (RF_MCSM2_RX_TIME_END_OF_PACKET), + RF_MCSM1_OFF, (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING| + RF_MCSM1_RXOFF_MODE_IDLE| + RF_MCSM1_TXOFF_MODE_IDLE), + RF_MCSM0_OFF, (RF_MCSM0_FS_AUTOCAL_FROM_IDLE| + RF_MCSM0_MAGIC_3| + RF_MCSM0_CLOSE_IN_RX_0DB), + RF_FOCCFG_OFF, (RF_FOCCFG_FOC_PRE_K_3K, + RF_FOCCFG_FOC_POST_K_PRE_K, + RF_FOCCFG_FOC_LIMIT_BW_OVER_4), + RF_BSCFG_OFF, (RF_BSCFG_BS_PRE_K_2K| + RF_BSCFG_BS_PRE_KP_3KP| + RF_BSCFG_BS_POST_KI_PRE_KI| + RF_BSCFG_BS_POST_KP_PRE_KP| + RF_BSCFG_BS_LIMIT_0), + RF_AGCCTRL2_OFF, 0x43, + RF_AGCCTRL1_OFF, 0x40, + RF_AGCCTRL0_OFF, 0x91, + + RF_IOCFG2_OFF, 0x00, + RF_IOCFG1_OFF, 0x00, + RF_IOCFG0_OFF, 0x00, + + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* max packet length */ + RF_PKTLEN_OFF, 0xff, + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; + +void +ao_radio_idle(void) +{ + if (RF_MARCSTATE != RF_MARCSTATE_IDLE) + { + RFST = RFST_SIDLE; + do { + ; + } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); + } +} + +void +ao_radio_init(void) { + uint8_t i; + for (i = 0; i < sizeof (radio_setup); i += 2) + RF[radio_setup[i]] = radio_setup[i+1]; +} diff --git a/ao-bringup/ao_radio_test.c b/ao-bringup/ao_radio_test.c new file mode 100644 index 00000000..8efb03cc --- /dev/null +++ b/ao-bringup/ao_radio_test.c @@ -0,0 +1,18 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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_bringup.h" diff --git a/ao-bringup/ao_radio_xmit.c b/ao-bringup/ao_radio_xmit.c new file mode 100644 index 00000000..be3333af --- /dev/null +++ b/ao-bringup/ao_radio_xmit.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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_bringup.h" + +main () +{ + ao_init(); + ao_radio_init(); + ao_radio_idle(); + RFST = RFST_STX; + P1 = 1; + for (;;); +} -- cgit v1.2.3 From 1e60deca147c85a064719dfad14ccabd1049bbbd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Feb 2010 16:33:34 -0800 Subject: Allow product names to have suffixes (like board revisions) When looking for a board by product name, just look at the prefix of the name instead of requiring an exact match. This will allow products to have board version suffixes. Signed-off-by: Keith Packard --- ao-tools/lib/cc-usbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/lib/cc-usbdev.c b/ao-tools/lib/cc-usbdev.c index ed39c062..afa91d49 100644 --- a/ao-tools/lib/cc-usbdev.c +++ b/ao-tools/lib/cc-usbdev.c @@ -258,7 +258,7 @@ match_dev(char *product, int serial) return NULL; for (i = 0; i < devs->ndev; i++) { dev = devs->dev[i]; - if (product && strcmp (product, dev->product) != 0) + if (product && strncmp (product, dev->product, strlen(product)) != 0) continue; if (serial && serial != dev->serial) continue; -- cgit v1.2.3 From 5d7a3a5fbc0af4621c67a6fd51a9c9d5ae688fa5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Feb 2010 16:40:13 -0800 Subject: Fix and document the ao-rawload --run flag This allows ram-based programs to be loaded and executed easily. Signed-off-by: Keith Packard --- ao-tools/ao-rawload/ao-rawload.1 | 9 +++++++-- ao-tools/ao-rawload/ao-rawload.c | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ao-tools/ao-rawload/ao-rawload.1 b/ao-tools/ao-rawload/ao-rawload.1 index 6b6a6e2c..30d0467d 100644 --- a/ao-tools/ao-rawload/ao-rawload.1 +++ b/ao-tools/ao-rawload/ao-rawload.1 @@ -29,7 +29,7 @@ ao-rawload \- flash a program to a AltOS device .SH DESCRIPTION .I ao-rawload loads the specified .ihx file, without modification, into the target -device flash memory. +device flash or ram (depending on the base address of the .ihx file). .SH OPTIONS .TP \-T tty-device | --tty tty-device @@ -51,10 +51,15 @@ TeleMetrum Leaving out the product name will cause the tool to select a suitable product, leaving out the serial number will cause the tool to match one of the available devices. +.TP +\-r | --run +After the file has been loaded, set the PC to the base address of the +image and resume execution there. +the .ihx file. .SH USAGE .I ao-rawload reads the specified .ihx file into memory. It then connects to the specified target device and writes the program to the target device -flash memory. +memory and, optionally, starts the program executing. .SH AUTHOR Keith Packard diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index 0098b658..a4746b19 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -49,7 +49,7 @@ main (int argc, char **argv) int c; int run = 0; - while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "rT:D:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -67,7 +67,7 @@ main (int argc, char **argv) } filename = argv[optind]; if (filename == NULL) { - fprintf(stderr, "usage: %s \n", argv[0]); + usage(argv[0]); exit(1); } file = fopen(filename, "r"); -- cgit v1.2.3 From 461d4a1948e112ec7353caf88967391d876469dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Feb 2010 10:33:13 -0800 Subject: Add LED test --- ao-bringup/Makefile | 12 ++++++++++-- ao-bringup/ao_led_blink.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ ao-bringup/testplan | 17 ++++++++++++++++ 3 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 ao-bringup/ao_led_blink.c create mode 100644 ao-bringup/testplan diff --git a/ao-bringup/Makefile b/ao-bringup/Makefile index 805b2550..cacbc161 100644 --- a/ao-bringup/Makefile +++ b/ao-bringup/Makefile @@ -17,7 +17,12 @@ XMIT_SRC = \ ao_radio_xmit.c XMIT_REL=$(XMIT_SRC:.c=.rel) $(BRINGUP_REL) -SRC=$(BRINGUP_SRC) $(XMIT_SRC) +LED_SRC = \ + ao_led_blink.c + +LED_REL=$(LED_SRC:.c=.rel) $(BRINGUP_REL) + +SRC=$(BRINGUP_SRC) $(XMIT_SRC) $(LED_SRC) ADB=$(SRC:.c=.adb) ASM=$(SRC:.c=.asm) @@ -27,7 +32,7 @@ REL=$(SRC:.c=.rel) RST=$(SRC:.c=.rst) SYM=$(SRC:.c=.sym) -PROGS=ao_radio_xmit.ihx +PROGS=ao_radio_xmit.ihx ao_led_blink.ihx PCDB=$(PROGS:.ihx=.cdb) PLNK=$(PROGS:.ihx=.lnk) @@ -43,6 +48,9 @@ all: $(PROGS) ao_radio_xmit.ihx: $(XMIT_REL) $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(XMIT_REL) +ao_led_blink.ihx: $(LED_REL) + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(LED_REL) + clean: rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) diff --git a/ao-bringup/ao_led_blink.c b/ao-bringup/ao_led_blink.c new file mode 100644 index 00000000..1e4c143d --- /dev/null +++ b/ao-bringup/ao_led_blink.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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_bringup.h" + +#define nop() _asm nop _endasm; + +void +delay (unsigned char n) +{ + unsigned char i = 0, j = 0; + + n <<= 1; + while (--n != 0) + while (--j != 0) + while (--i != 0) + nop(); +} + +main() +{ + ao_init(); + /* Set p1_0 and p1_1 to output */ + P1DIR = 0x03; + P1INP = 0x00; + for (;;) { + P1 = 1; + delay(5); + P1 = 2; + delay(5); + P1 = 3; + delay(5); + P1 = 0; + delay(5); + } +} diff --git a/ao-bringup/testplan b/ao-bringup/testplan new file mode 100644 index 00000000..2c0e4e08 --- /dev/null +++ b/ao-bringup/testplan @@ -0,0 +1,17 @@ +Low level hardware tests + + * cpu + * barometer + * accelerometer + * flash + * gps + * igniter continuity + * igniters + * radio calibration + * led + +Higher level tests + + * USB serial communication + * memory flashing + * reading/writing eeprom -- cgit v1.2.3 From bbf8c9f1748af3f1fac08ddf80ae98da2e9b5727 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Feb 2010 15:21:12 -0700 Subject: create a turn on script for lighting up TeleDongle v0.2 boards --- ao-bringup/turnon_teledongle | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100755 ao-bringup/turnon_teledongle diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle new file mode 100755 index 00000000..1786f251 --- /dev/null +++ b/ao-bringup/turnon_teledongle @@ -0,0 +1,28 @@ +#!/bin/sh + +echo "TeleDongle v0.2 Turn-On and Calibration Program" +echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleDongle v0.2 powered from USB" +echo "\t\twith TIdongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from SMA to frequency counter" +echo +echo -n "TeleDongle serial number: " +read SERIAL + +../ao-tools/ao-rawload/ao-rawload -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +../ao-tools/ao-rawload/ao-rawload -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "ceil(434.55 / $FREQ * 1186611)"` + +echo "Programming flash with cal value " $CAL_VALUE +ao-load --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From f1956ebadd7bf46b84a05a0c383b6404ca26b344 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:10:16 -0800 Subject: Leave .ihx files in the build directory too - easier to debug that way sdcdb wants the .ihx and .cdb files in the same directory, so humor it by copying the .ihx files to the src directory instead of moving them. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 6cb6e0de..106333a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,7 +207,7 @@ quiet ?= $($1) all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) $(PMAP) .. + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../ao.h $(PMEM) ../altitude.h: make-altitude -- cgit v1.2.3 From 1d6d8d76ec65373ffee70add75d183f5c4168f61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:11:44 -0800 Subject: Eliminate deadlock when writing config from radio link Writing the 'Saved\r\n' string would fill the packet buffer and cause a flush to occur, which would need to wait for the radio link to receive and transmit a packet. The radio link always re-fetches the radio channel number when lighting up the radio, so it need to look in the config space. If the config mutex was held by the config writing process while the radio was trying to get the channel number, then we'd get a deadlock. Signed-off-by: Keith Packard --- src/ao_config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ao_config.c b/src/ao_config.c index f8ea27fe..8df994a6 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -377,13 +377,18 @@ ao_config_show(void) __reentrant void ao_config_write(void) __reentrant { + uint8_t saved = 0; ao_mutex_get(&ao_config_mutex); if (ao_config_dirty) { _ao_config_put(); ao_config_dirty = 0; - printf("Saved\n"); + saved = 1; } ao_mutex_put(&ao_config_mutex); + if (saved) + puts("Saved"); + else + puts("Nothing to save"); } #endif -- cgit v1.2.3 From 7aab73a265841aac817ea34235dd1eb819debf76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:14:04 -0800 Subject: Fix up LED colors for each product. Different products assign different color LEDs to the two available LED drivers (P1_0, P1_1). Make the LED color pin assignments per-product (in ao_pins.h), then deal with not always having a green LED. Signed-off-by: Keith Packard --- src/ao.h | 2 -- src/ao_led.c | 2 -- src/ao_packet.c | 4 ++++ src/ao_pins.h | 10 +++++++++- src/ao_teledongle.c | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/ao.h b/src/ao.h index b43f5ecd..aefefa46 100644 --- a/src/ao.h +++ b/src/ao.h @@ -263,8 +263,6 @@ ao_beep_init(void); */ #define AO_LED_NONE 0 -#define AO_LED_GREEN 1 -#define AO_LED_RED 2 /* Turn on the specified LEDs */ void diff --git a/src/ao_led.c b/src/ao_led.c index 6c698b4b..5beed58d 100644 --- a/src/ao_led.c +++ b/src/ao_led.c @@ -17,8 +17,6 @@ #include "ao.h" -#define AO_LED_ALL (AO_LED_GREEN|AO_LED_RED) - __pdata uint8_t ao_led_enable; void diff --git a/src/ao_packet.c b/src/ao_packet.c index dcd1647c..d52f2a68 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -67,7 +67,9 @@ ao_packet_recv(void) { uint8_t dma_done; +#ifdef AO_LED_GREEN ao_led_on(AO_LED_GREEN); +#endif ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, @@ -86,7 +88,9 @@ ao_packet_recv(void) ao_radio_abort(); dma_done = ao_radio_dma_done; ao_radio_put(); +#ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); +#endif if (dma_done & AO_DMA_DONE) { if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) diff --git a/src/ao_pins.h b/src/ao_pins.h index 84d8a1a1..771d9c7f 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,6 +28,7 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 #endif @@ -41,7 +42,9 @@ #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 - #define LEDS_AVAILABLE (AO_LED_RED) + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #endif #if defined(TELEMETRUM_V_0_1) @@ -53,6 +56,8 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 #endif @@ -66,6 +71,8 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #endif @@ -78,6 +85,7 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 #define LEDS_AVAILABLE (AO_LED_RED) #endif diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index b07b1746..505dc0cb 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -23,7 +23,7 @@ main(void) ao_clock_init(); /* Turn on the LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_timer_init(); ao_cmd_init(); -- cgit v1.2.3 From 901fce5fe3e2762406079ecaa787612b5ed4b34a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:18:47 -0800 Subject: Add .gitignore for ao-bringup Signed-off-by: Keith Packard --- ao-bringup/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 ao-bringup/.gitignore diff --git a/ao-bringup/.gitignore b/ao-bringup/.gitignore new file mode 100644 index 00000000..dc7beb52 --- /dev/null +++ b/ao-bringup/.gitignore @@ -0,0 +1,2 @@ +ao_led_blink +ao_radio_xmit -- cgit v1.2.3 From e4e17e6d3844ae682a0e7a9469a522359bac77b6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 27 Feb 2010 17:36:13 -0700 Subject: update changelogs for Debian build --- ChangeLog | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 17 ++++++++++ 2 files changed, 119 insertions(+) diff --git a/ChangeLog b/ChangeLog index d365896f..6a6fc7e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,105 @@ +commit a1478f65538fdaac7b58ffbd958a035b74956099 +Merge: 901fce5 bbf8c9f +Author: Keith Packard +Date: Sat Feb 27 15:19:33 2010 -0800 + + Merge remote branch 'origin/master' + +commit 901fce5fe3e2762406079ecaa787612b5ed4b34a +Author: Keith Packard +Date: Sat Feb 27 15:18:47 2010 -0800 + + Add .gitignore for ao-bringup + + Signed-off-by: Keith Packard + +commit 7aab73a265841aac817ea34235dd1eb819debf76 +Author: Keith Packard +Date: Sat Feb 27 15:14:04 2010 -0800 + + Fix up LED colors for each product. + + Different products assign different color LEDs to the two available + LED drivers (P1_0, P1_1). Make the LED color pin assignments + per-product (in ao_pins.h), then deal with not always having a green LED. + + Signed-off-by: Keith Packard + +commit 1d6d8d76ec65373ffee70add75d183f5c4168f61 +Author: Keith Packard +Date: Sat Feb 27 15:11:44 2010 -0800 + + Eliminate deadlock when writing config from radio link + + Writing the 'Saved\r\n' string would fill the packet buffer and cause + a flush to occur, which would need to wait for the radio link to + receive and transmit a packet. The radio link always re-fetches the + radio channel number when lighting up the radio, so it need to look in + the config space. If the config mutex was held by the config writing + process while the radio was trying to get the channel number, then + we'd get a deadlock. + + Signed-off-by: Keith Packard + +commit f1956ebadd7bf46b84a05a0c383b6404ca26b344 +Author: Keith Packard +Date: Sat Feb 27 15:10:16 2010 -0800 + + Leave .ihx files in the build directory too - easier to debug that way + + sdcdb wants the .ihx and .cdb files in the same directory, so humor it + by copying the .ihx files to the src directory instead of moving them. + + Signed-off-by: Keith Packard + +commit bbf8c9f1748af3f1fac08ddf80ae98da2e9b5727 +Author: Bdale Garbee +Date: Fri Feb 26 15:21:12 2010 -0700 + + create a turn on script for lighting up TeleDongle v0.2 boards + +commit 461d4a1948e112ec7353caf88967391d876469dd +Author: Keith Packard +Date: Fri Feb 26 10:33:13 2010 -0800 + + Add LED test + +commit 5d7a3a5fbc0af4621c67a6fd51a9c9d5ae688fa5 +Author: Keith Packard +Date: Thu Feb 25 16:40:13 2010 -0800 + + Fix and document the ao-rawload --run flag + + This allows ram-based programs to be loaded and executed easily. + + Signed-off-by: Keith Packard + +commit 1e60deca147c85a064719dfad14ccabd1049bbbd +Author: Keith Packard +Date: Thu Feb 25 16:33:34 2010 -0800 + + Allow product names to have suffixes (like board revisions) + + When looking for a board by product name, just look at the prefix of + the name instead of requiring an exact match. This will allow products + to have board version suffixes. + + Signed-off-by: Keith Packard + +commit f4d5790a284e2d02dd7568fbca90402fa5ed1aea +Author: Keith Packard +Date: Thu Feb 25 16:32:57 2010 -0800 + + Add ao_radio_xmit to help test boards without flashing them. + + Signed-off-by: Keith Packard + +commit d7d551b0078acb1596a9b9023c3df6dbfa46213c +Author: Bdale Garbee +Date: Wed Feb 24 17:30:23 2010 -0700 + + update changelogs for Debian build + commit 2f45953ee54034209a23c254e65da36e44cf075f Author: Bdale Garbee Date: Wed Feb 24 17:29:47 2010 -0700 diff --git a/debian/changelog b/debian/changelog index b79ee067..5201fe7d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +altos (0.6+106+ga1478f6) unstable; urgency=low + + [ Keith Packard ] + * Add ao_radio_xmit to help test boards without flashing them. + * Allow product names to have suffixes (like board revisions) + * Fix and document the ao-rawload --run flag + * Add LED test + * Leave .ihx files in the build directory too - easier to debug that way + * Eliminate deadlock when writing config from radio link + * Fix up LED colors for each product. + * Add .gitignore for ao-bringup + + [ Bdale Garbee ] + * create a turn on script for lighting up TeleDongle v0.2 boards + + -- Bdale Garbee Sat, 27 Feb 2010 17:35:32 -0700 + altos (0.6+95+g2f45953) unstable; urgency=low * update changelogs for Debian build -- cgit v1.2.3 From 6e61170d42936c18cd6efba6f4c14af616a30745 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Feb 2010 18:24:46 -0800 Subject: Need to duplicate new altitude conversion code in aoview. Altitude conversion is now done with a smaller table and interpolation instead of a giant table. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_convert.c | 44 ++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/ao-tools/ao-view/aoview_convert.c b/ao-tools/ao-view/aoview_convert.c index 02416647..8ee05e1d 100644 --- a/ao-tools/ao-view/aoview_convert.c +++ b/ao-tools/ao-view/aoview_convert.c @@ -17,26 +17,50 @@ #include "aoview.h" -static int16_t altitude_table[2048] = { +static int16_t altitude_table[] = { #include "altitude.h" }; +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + int16_t aoview_pres_to_altitude(int16_t pres) { - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } int16_t aoview_altitude_to_pres(int16_t alt) { - int16_t pres; + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; } -- cgit v1.2.3 From eda5e1166a97766aa22561beaa1086ba4e19ee16 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 4 Mar 2010 17:33:39 -0700 Subject: update changelogs for Debian build --- ChangeLog | 17 +++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6a6fc7e3..2a3c8fdb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +commit 6e61170d42936c18cd6efba6f4c14af616a30745 +Author: Keith Packard +Date: Sun Feb 28 18:24:46 2010 -0800 + + Need to duplicate new altitude conversion code in aoview. + + Altitude conversion is now done with a smaller table and interpolation + instead of a giant table. + + Signed-off-by: Keith Packard + +commit e4e17e6d3844ae682a0e7a9469a522359bac77b6 +Author: Bdale Garbee +Date: Sat Feb 27 17:36:13 2010 -0700 + + update changelogs for Debian build + commit a1478f65538fdaac7b58ffbd958a035b74956099 Merge: 901fce5 bbf8c9f Author: Keith Packard diff --git a/debian/changelog b/debian/changelog index 5201fe7d..90b79f26 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+108+g6e61170) unstable; urgency=low + + [ Keith Packard ] + * Need to duplicate new altitude conversion code in aoview. + + -- Bdale Garbee Thu, 04 Mar 2010 17:33:27 -0700 + altos (0.6+106+ga1478f6) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From a7042fe7d065d1da1252be5ad43e3c9856214dc8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 5 Mar 2010 19:11:11 -0800 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a3c8fdb..ea64f192 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit eda5e1166a97766aa22561beaa1086ba4e19ee16 +Author: Bdale Garbee +Date: Thu Mar 4 17:33:39 2010 -0700 + + update changelogs for Debian build + commit 6e61170d42936c18cd6efba6f4c14af616a30745 Author: Keith Packard Date: Sun Feb 28 18:24:46 2010 -0800 -- cgit v1.2.3 From 93df98898f8cd199ae13158bc4f65e3494c954ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Mar 2010 10:35:12 -0800 Subject: Round radio calibration value instead of truncating The radio calibration function in the bring-up code was truncating the radio calibration value which caused the resulting frequency to always measure above the target frequency, instead of trying to get as close as possible. This change will result in a closer frequency match, but may sometimes be below the target frequency. Signed-off-by: Keith Packard --- ao-bringup/turnon_teledongle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index 1786f251..97c1e419 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -19,7 +19,7 @@ sleep 5 echo -n "Generating RF carrier. Please enter measured frequency: " read FREQ -CAL_VALUE=`nickle -e "ceil(434.55 / $FREQ * 1186611)"` +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE ao-load --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2.ihx $SERIAL -- cgit v1.2.3 From 23da4f3bcdd1d780c9e1f6b68ad2fb309fcae6ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Mar 2010 10:37:32 -0800 Subject: Document the ao-dumplog '--remote' flag for radio-link downloads The --remote (or -R) flag uses TeleDongle to fetch data over the radio command link from TeleMetrum. It's been there for a while, but the man page failed to mention it. Signed-off-by: Keith Packard --- ao-tools/ao-dumplog/ao-dumplog.1 | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ao-tools/ao-dumplog/ao-dumplog.1 b/ao-tools/ao-dumplog/ao-dumplog.1 index 8c2df7c6..d381e335 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.1 +++ b/ao-tools/ao-dumplog/ao-dumplog.1 @@ -25,6 +25,8 @@ ao-dumplog \- Store flight log from TeleMetrum device [\--tty \fItty-device\fP] [\-D \fIaltos-device\fP] [\--device \fIaltos-device\fP] +[\--R\fP] +[\--remote\fP] .SH OPTIONS .TP \-T tty-device | --tty tty-device @@ -44,6 +46,10 @@ TeleMetrum Leaving out the product name will cause the tool to select a suitable product, leaving out the serial number will cause the tool to match one of the available devices. +.TP +\-R | --remote +This uses the command radio link to download the log from TeleMetrum +through a TeleDongle. .SH DESCRIPTION .I ao-dumplog downloads the flight log from a connected TeleMetrum device and stores -- cgit v1.2.3 From 9801ff7de21027935f52ccabaa3ff157e22d21ce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 15 Mar 2010 12:04:18 -0600 Subject: move gbp.conf into debian/ --- .gbp.conf | 46 -------------------------------------------- ao-bringup/turnon_teledongle | 26 ++++++++++++++++++++++--- debian/gbp.conf | 46 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 49 deletions(-) delete mode 100644 .gbp.conf create mode 100644 debian/gbp.conf diff --git a/.gbp.conf b/.gbp.conf deleted file mode 100644 index 9561fdfe..00000000 --- a/.gbp.conf +++ /dev/null @@ -1,46 +0,0 @@ -# Configuration file for git-buildpackage and friends - -[DEFAULT] -# the default build command: -#builder = debuild -i\.git/ -I.git -# the default clean command: -cleaner = debian/rules prebuild && debuild clean -# the default branch for upstream sources: -upstream-branch = upstream -# the default branch for the debian patch: -debian-branch = master -# the default tag formats used: -#upstream-tag = upstream/%(version)s -#debian-tag = debian/%(version)s -# use pristine-tar: -pristine-tar = True - -# Options only affecting git-buildpackage -[git-buildpackage] -#upstream-branch = dfsgclean -# uncomment this to automatically GPG sign tags -#sign-tags = True -# keyid to GPG sign tags with -#keyid = 0xdeadbeef -# push to a remote repository after a successful tag: -posttag = git push --mirror -# use this for more svn-buildpackage like behaviour: -export-dir = ../build-area/altos/ -#tarball-dir = ../tarballs/ - -# Options only affecting git-import-orig -[git-import-orig] -#upstream-branch = newupstream -#debian-branch = dfsgclean -#filter = .svn - -# Options only affecting git-import-dsc -[git-import-dsc] -#upstream-branch = svn-upstream -#filter = [ 'CVS', '.cvsignore' ] - -# Options only affecting git-dch -[git-dch] -#git-log = --no-merges -#snapshot-number = snapshot + 1 - diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index 1786f251..ea7a7b2a 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -1,5 +1,23 @@ #!/bin/sh +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + echo "TeleDongle v0.2 Turn-On and Calibration Program" echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" echo @@ -11,18 +29,20 @@ echo echo -n "TeleDongle serial number: " read SERIAL -../ao-tools/ao-rawload/ao-rawload -r ao_led_blink.ihx +echo $RAWLOAD + +$RAWLOAD -r ao_led_blink.ihx echo "LEDs should be blinking" sleep 5 -../ao-tools/ao-rawload/ao-rawload -r ao_radio_xmit.ihx +$RAWLOAD -r ao_radio_xmit.ihx echo -n "Generating RF carrier. Please enter measured frequency: " read FREQ CAL_VALUE=`nickle -e "ceil(434.55 / $FREQ * 1186611)"` echo "Programming flash with cal value " $CAL_VALUE -ao-load --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2.ihx $SERIAL +$AOLOAD --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/debian/gbp.conf b/debian/gbp.conf new file mode 100644 index 00000000..9561fdfe --- /dev/null +++ b/debian/gbp.conf @@ -0,0 +1,46 @@ +# Configuration file for git-buildpackage and friends + +[DEFAULT] +# the default build command: +#builder = debuild -i\.git/ -I.git +# the default clean command: +cleaner = debian/rules prebuild && debuild clean +# the default branch for upstream sources: +upstream-branch = upstream +# the default branch for the debian patch: +debian-branch = master +# the default tag formats used: +#upstream-tag = upstream/%(version)s +#debian-tag = debian/%(version)s +# use pristine-tar: +pristine-tar = True + +# Options only affecting git-buildpackage +[git-buildpackage] +#upstream-branch = dfsgclean +# uncomment this to automatically GPG sign tags +#sign-tags = True +# keyid to GPG sign tags with +#keyid = 0xdeadbeef +# push to a remote repository after a successful tag: +posttag = git push --mirror +# use this for more svn-buildpackage like behaviour: +export-dir = ../build-area/altos/ +#tarball-dir = ../tarballs/ + +# Options only affecting git-import-orig +[git-import-orig] +#upstream-branch = newupstream +#debian-branch = dfsgclean +#filter = .svn + +# Options only affecting git-import-dsc +[git-import-dsc] +#upstream-branch = svn-upstream +#filter = [ 'CVS', '.cvsignore' ] + +# Options only affecting git-dch +[git-dch] +#git-log = --no-merges +#snapshot-number = snapshot + 1 + -- cgit v1.2.3 From 20d4d410e0fc04fe192e309811eed6c0194fa5a8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:11:40 -0600 Subject: initial harness for documentation --- .gitignore | 3 +++ debian/control | 4 ++-- debian/docs | 2 ++ debian/rules | 1 + doc/Makefile | 25 +++++++++++++++++++++++++ doc/telemetrum.xsl | 44 ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 2 deletions(-) create mode 100644 doc/Makefile create mode 100644 doc/telemetrum.xsl diff --git a/.gitignore b/.gitignore index eafee20f..16ff1f7b 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,6 @@ Makefile.in missing stamp-h1 tags +doc/telemetrum.fo +doc/telemetrum.html +doc/telemetrum.pdf diff --git a/debian/control b/debian/control index 7d21e602..2ba1722d 100644 --- a/debian/control +++ b/debian/control @@ -3,8 +3,8 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 -Standards-Version: 3.8.3 +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.xsl +Standards-Version: 3.8.4 Homepage: http://altusmetrum.org/AltOS Package: altos diff --git a/debian/docs b/debian/docs index 50bd824b..d5af59c7 100644 --- a/debian/docs +++ b/debian/docs @@ -1,2 +1,4 @@ NEWS README +doc/telemetrum.html +doc/telemetrum.pdf diff --git a/debian/rules b/debian/rules index 780011b7..a7468b9f 100755 --- a/debian/rules +++ b/debian/rules @@ -26,6 +26,7 @@ build: build-stamp build-stamp: configure-stamp dh_testdir $(MAKE) VERSION=$(PKG_VERSION) + (cd doc ; $(MAKE)) touch $@ clean: diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 00000000..d3293900 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,25 @@ +# +# http://docbook.sourceforge.net/release/xsl/current/README +# + +all: telemetrum.html telemetrum.pdf + +telemetrum.html: telemetrum.xsl + xsltproc -o telemetrum.html \ + /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl \ + telemetrum.xsl + +telemetrum.fo: telemetrum.xsl + xsltproc -o telemetrum.fo \ + /usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl \ + telemetrum.xsl + +telemetrum.pdf: telemetrum.fo + fop -fo telemetrum.fo -pdf telemetrum.pdf + +clean: + rm -f telemetrum.html telemetrum.pdf telemetrum.fo + +indent: telemetrum.xsl + xmlindent -i 2 < telemetrum.xsl > telemetrum.new + diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl new file mode 100644 index 00000000..7d855318 --- /dev/null +++ b/doc/telemetrum.xsl @@ -0,0 +1,44 @@ + + + + + + Bdale + Garbee + + + Keith + Packard + + + 2010 + Bdale Garbee + + TeleMetrum + Owner's Manual for the TeleMetrum System + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.1 + 30 March 2010 + Initial content + + + + + Introduction + + Placeholder. + + + + -- cgit v1.2.3 From 28e40ccfcd80ab8764d4aa235257cea4d193a0c1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:14:47 -0600 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a3c8fdb..1b55a7f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 20d4d410e0fc04fe192e309811eed6c0194fa5a8 +Author: Bdale Garbee +Date: Tue Mar 30 23:11:40 2010 -0600 + + initial harness for documentation + +commit 9801ff7de21027935f52ccabaa3ff157e22d21ce +Author: Bdale Garbee +Date: Mon Mar 15 12:04:18 2010 -0600 + + move gbp.conf into debian/ + +commit eda5e1166a97766aa22561beaa1086ba4e19ee16 +Author: Bdale Garbee +Date: Thu Mar 4 17:33:39 2010 -0700 + + update changelogs for Debian build + commit 6e61170d42936c18cd6efba6f4c14af616a30745 Author: Keith Packard Date: Sun Feb 28 18:24:46 2010 -0800 diff --git a/debian/changelog b/debian/changelog index 90b79f26..66e72832 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+111+g20d4d41) unstable; urgency=low + + * move gbp.conf into debian/ + * initial harness for documentation + + -- Bdale Garbee Tue, 30 Mar 2010 23:13:02 -0600 + altos (0.6+108+g6e61170) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From f03ed0876c67b58624abf0c14bf73444b0322d3c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:18:37 -0600 Subject: update changelogs for Debian build --- ChangeLog | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- debian/changelog | 11 +++++++++-- 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1c9e127a..c70c5929 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,19 @@ -<<<<<<< HEAD +commit b41e617080fe825f7810ee5eee52ea37f7618ec6 +Merge: 28e40cc df7bda1 +Author: Bdale Garbee +Date: Tue Mar 30 23:15:32 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + + Conflicts: + ChangeLog + +commit 28e40ccfcd80ab8764d4aa235257cea4d193a0c1 +Author: Bdale Garbee +Date: Tue Mar 30 23:14:47 2010 -0600 + + update changelogs for Debian build + commit 20d4d410e0fc04fe192e309811eed6c0194fa5a8 Author: Bdale Garbee Date: Tue Mar 30 23:11:40 2010 -0600 @@ -11,8 +26,45 @@ Date: Mon Mar 15 12:04:18 2010 -0600 move gbp.conf into debian/ -======= ->>>>>>> df7bda1f32b0049c3878c325ea0b55999f3980e3 +commit df7bda1f32b0049c3878c325ea0b55999f3980e3 +Merge: 23da4f3 a7042fe +Author: Keith Packard +Date: Fri Mar 12 10:38:26 2010 -0800 + + Merge remote branch 'origin/master' + +commit 23da4f3bcdd1d780c9e1f6b68ad2fb309fcae6ba +Author: Keith Packard +Date: Fri Mar 12 10:37:32 2010 -0800 + + Document the ao-dumplog '--remote' flag for radio-link downloads + + The --remote (or -R) flag uses TeleDongle to fetch data over the radio + command link from TeleMetrum. It's been there for a while, but the man + page failed to mention it. + + Signed-off-by: Keith Packard + +commit 93df98898f8cd199ae13158bc4f65e3494c954ad +Author: Keith Packard +Date: Fri Mar 12 10:35:12 2010 -0800 + + Round radio calibration value instead of truncating + + The radio calibration function in the bring-up code was truncating the + radio calibration value which caused the resulting frequency to + always measure above the target frequency, instead of trying to get as + close as possible. This change will result in a closer frequency + match, but may sometimes be below the target frequency. + + Signed-off-by: Keith Packard + +commit a7042fe7d065d1da1252be5ad43e3c9856214dc8 +Author: Bdale Garbee +Date: Fri Mar 5 19:11:11 2010 -0800 + + update changelogs for Debian build + commit eda5e1166a97766aa22561beaa1086ba4e19ee16 Author: Bdale Garbee Date: Thu Mar 4 17:33:39 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 66e72832..75000f80 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,16 @@ -altos (0.6+111+g20d4d41) unstable; urgency=low +altos (0.6+117+gb41e617) unstable; urgency=low + [ Bdale Garbee ] + * update changelogs for Debian build * move gbp.conf into debian/ * initial harness for documentation - -- Bdale Garbee Tue, 30 Mar 2010 23:13:02 -0600 + [ Keith Packard ] + * Round radio calibration value instead of truncating + * Document the ao-dumplog '--remote' flag for radio-link downloads + + + -- Bdale Garbee Tue, 30 Mar 2010 23:18:08 -0600 altos (0.6+108+g6e61170) unstable; urgency=low -- cgit v1.2.3 From 00f49c8fb0aa38331360bdb85c32bcebe60dcdc3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:19:07 -0600 Subject: fix typo --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 2ba1722d..85074142 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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.xsl +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-xsl Standards-Version: 3.8.4 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From eb3cc3e9b60ec23acbb7d797affa743d671801ab Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:19:48 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 +++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c70c5929..618c4a51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 00f49c8fb0aa38331360bdb85c32bcebe60dcdc3 +Author: Bdale Garbee +Date: Tue Mar 30 23:19:07 2010 -0600 + + fix typo + +commit f03ed0876c67b58624abf0c14bf73444b0322d3c +Author: Bdale Garbee +Date: Tue Mar 30 23:18:37 2010 -0600 + + update changelogs for Debian build + commit b41e617080fe825f7810ee5eee52ea37f7618ec6 Merge: 28e40cc df7bda1 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 75000f80..f0fe4564 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,16 +1,16 @@ -altos (0.6+117+gb41e617) unstable; urgency=low +altos (0.6+119+g00f49c8) unstable; urgency=low [ Bdale Garbee ] * update changelogs for Debian build * move gbp.conf into debian/ * initial harness for documentation + * fix typo [ Keith Packard ] * Round radio calibration value instead of truncating * Document the ao-dumplog '--remote' flag for radio-link downloads - - -- Bdale Garbee Tue, 30 Mar 2010 23:18:08 -0600 + -- Bdale Garbee Tue, 30 Mar 2010 23:19:15 -0600 altos (0.6+108+g6e61170) unstable; urgency=low -- cgit v1.2.3 From 76768804e68ed09421d7a48cb0b390f102ce2d76 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Mar 2010 23:26:35 -0600 Subject: make lintian happy --- debian/source/format | 1 + 1 file changed, 1 insertion(+) create mode 100644 debian/source/format diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 00000000..89ae9db8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) -- cgit v1.2.3 From 7f233369e32c3254165ee251df0a3dbc21ea5a29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 31 Mar 2010 13:49:54 -0700 Subject: Start adding java-based UI --- ao-tools/altosui/AltosSerial.java | 149 ++++++++++++++++++++++ ao-tools/altosui/AltosSerialMonitor.java | 22 ++++ ao-tools/altosui/AltosUI.java | 209 +++++++++++++++++++++++++++++++ ao-tools/altosui/Makefile | 13 ++ 4 files changed, 393 insertions(+) create mode 100644 ao-tools/altosui/AltosSerial.java create mode 100644 ao-tools/altosui/AltosSerialMonitor.java create mode 100644 ao-tools/altosui/AltosUI.java create mode 100644 ao-tools/altosui/Makefile diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java new file mode 100644 index 00000000..82663eab --- /dev/null +++ b/ao-tools/altosui/AltosSerial.java @@ -0,0 +1,149 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Deal with TeleDongle on a serial port + */ + +package altosui; + +import java.lang.String; +import java.lang.System; +import java.lang.Character; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.util.concurrent.LinkedBlockingQueue; +import java.lang.InterruptedException; +import java.util.LinkedList; +import altosui.AltosSerialMonitor; +import java.util.Iterator; + +/* + * This class reads from the serial port and places each received + * line in a queue. Dealing with that queue is left up to other + * threads. + */ +class AltosSerialReader implements Runnable { + FileInputStream serial_in; + LinkedBlockingQueue monitor_queue; + LinkedBlockingQueue reply_queue; + String line; + + public void run () { + int c; + + try { + while ((c = serial_in.read()) != -1) { + if (c == '\r') + continue; + synchronized(this) { + if (c == '\n') { + if (line != "") { + if (line.startsWith("VERSION")) + monitor_queue.put(line); + else + reply_queue.put(line); + line = ""; + } + } else { + line = line + (char) c; + } + } + } + } catch (IOException e) { + } catch (InterruptedException e) { + } + } + + public String get_telem() { + try { + return monitor_queue.take(); + } catch (InterruptedException e) { + return ""; + } + } + + public String get_reply() { + try { + return reply_queue.take(); + } catch (InterruptedException e) { + return ""; + } + } + + public void flush () { + synchronized(this) { + if (!"VERSION".startsWith(line) && !line.startsWith("VERSION")) + line = ""; + reply_queue.clear(); + } + } + public AltosSerialReader (FileInputStream in) { + serial_in = in; + monitor_queue = new LinkedBlockingQueue (); + reply_queue = new LinkedBlockingQueue (); + line = ""; + } + +} + +public class AltosSerial implements Runnable { + FileInputStream serial_in = null; + FileOutputStream serial_out = null; + AltosSerialReader reader; + LinkedList callbacks; + + public void run() { + for (;;) { + String s = reader.get_reply(); + synchronized(callbacks) { + Iterator i = callbacks.iterator(); + while (i.hasNext()) { + i.next().data(s); + } + } + } + } + + public void start () { + try { + serial_out.write('?'); + serial_out.write('\r'); + } catch (IOException e) { + } + (new Thread(reader)).start(); + (new Thread(this)).start(); + } + + public void monitor(AltosSerialMonitor monitor) { + synchronized(callbacks) { + callbacks.add(monitor); + } + } + + public AltosSerial(String serial_name) { + try { + serial_in = new FileInputStream(serial_name); + serial_out = new FileOutputStream(serial_name); + reader = new AltosSerialReader(serial_in); + callbacks = new LinkedList(); + } catch (FileNotFoundException e) { + } + } +} diff --git a/ao-tools/altosui/AltosSerialMonitor.java b/ao-tools/altosui/AltosSerialMonitor.java new file mode 100644 index 00000000..ad0e9295 --- /dev/null +++ b/ao-tools/altosui/AltosSerialMonitor.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 interface AltosSerialMonitor { + void data(String data); +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java new file mode 100644 index 00000000..b731725c --- /dev/null +++ b/ao-tools/altosui/AltosUI.java @@ -0,0 +1,209 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JRadioButtonMenuItem; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.KeyStroke; +import javax.swing.table.TableCellEditor; +import javax.swing.table.DefaultTableCellRenderer; +import altosui.AltosSerial; +import altosui.AltosSerialMonitor; + +class AltosUIMonitor implements AltosSerialMonitor { + public void data(String data) { + System.out.println(data); + } +} + +public class AltosUI extends JFrame { + private int channel = -1; + + private JTable flightStatus; + private JTable flightInfo; + private AltosSerial serialLine; + + public AltosUI() { + + String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + Object[][] statusData = { { "0", "pad", "-50", "0" } }; + + flightStatus = new JTable(statusData, statusNames); + + flightStatus.setShowGrid(false); + + this.add(flightStatus); + + setTitle("AltOS"); + + createMenu(); + + serialLine = new AltosSerial("/dev/ttyACM0"); + serialLine.monitor(new AltosUIMonitor()); + serialLine.start(); + Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); + size.width = size.width*9/10; + size.height = size.height*9/10; + this.setSize(size); + this.validate(); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + } + + private void createMenu() { + JMenuBar menubar = new JMenuBar(); + JMenu menu; + JMenuItem item; + JRadioButtonMenuItem radioitem; + + // File menu + { + menu = new JMenu("File"); + menu.setMnemonic(KeyEvent.VK_F); + menubar.add(menu); + + item = new JMenuItem("Quit",KeyEvent.VK_Q); + item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, + ActionEvent.CTRL_MASK)); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + menu.add(item); + } + + // Device menu + { + menu = new JMenu("Device"); + menu.setMnemonic(KeyEvent.VK_D); + menubar.add(menu); + + item = new JMenuItem("Connect to Device",KeyEvent.VK_C); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + + item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + + menu.addSeparator(); + + item = new JMenuItem("Save Flight Data",KeyEvent.VK_S); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + + item = new JMenuItem("Replay",KeyEvent.VK_R); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + } + // Log menu + { + menu = new JMenu("Log"); + menu.setMnemonic(KeyEvent.VK_L); + menubar.add(menu); + + item = new JMenuItem("New Log",KeyEvent.VK_N); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + + item = new JMenuItem("Configure Log",KeyEvent.VK_C); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(item); + } + // Voice menu + { + menu = new JMenu("Voice", true); + menu.setMnemonic(KeyEvent.VK_V); + menubar.add(menu); + + radioitem = new JRadioButtonMenuItem("Enable Voice"); + radioitem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(radioitem); + } + + // Channel menu + { + menu = new JMenu("Channel", true); + menu.setMnemonic(KeyEvent.VK_C); + menubar.add(menu); + + for (int c = 0; c <= 9; c++) { + radioitem = new JRadioButtonMenuItem("Channel " + c + " (" + + (434.550 + c * .1) + ")", + c == 0); + radioitem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + } + }); + menu.add(radioitem); + } + } + + this.setJMenuBar(menubar); + + } + public static void main(final String[] args) { + AltosUI altosui = new AltosUI(); + altosui.setVisible(true); + } +} \ No newline at end of file diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile new file mode 100644 index 00000000..cb422df8 --- /dev/null +++ b/ao-tools/altosui/Makefile @@ -0,0 +1,13 @@ +.SUFFIXES: .java .class + +CLASSPATH=.. +CLASSFILES=AltosSerialMonitor.class AltosSerial.class AltosUI.class +JAVAFLAGS=-Xlint:unchecked + +all: $(CLASSFILES) + +.java.class: + javac -cp $(CLASSPATH) $(JAVAFLAGS) $*.java + +clean: + rm -f *.class \ No newline at end of file -- cgit v1.2.3 From a06bee96e648d9ded8776f3d6cba9505e7be1a60 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 31 Mar 2010 23:05:03 -0700 Subject: Add telemetry data parsing code --- ao-tools/altosui/.gitignore | 2 + ao-tools/altosui/AltosTelemetry.java | 287 +++++++++++++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 ao-tools/altosui/.gitignore create mode 100644 ao-tools/altosui/AltosTelemetry.java diff --git a/ao-tools/altosui/.gitignore b/ao-tools/altosui/.gitignore new file mode 100644 index 00000000..59913193 --- /dev/null +++ b/ao-tools/altosui/.gitignore @@ -0,0 +1,2 @@ +*.class +altosui diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java new file mode 100644 index 00000000..e072bb34 --- /dev/null +++ b/ao-tools/altosui/AltosTelemetry.java @@ -0,0 +1,287 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; + +/* + * Telemetry data contents + */ + +class AltosGPSTime { + int year; + int month; + int day; + int hour; + int minute; + int second; + + int parse_int(String v) throws ParseException { + try { + return Integer.parseInt(v); + } catch (NumberFormatException e) { + throw new ParseException(v, 0); + } + } + + public AltosGPSTime(String date, String time) throws ParseException { + String[] ymd = date.split("-"); + if (ymd.length != 3) { + System.out.println("Error parsing GPS date " + date + " got " + ymd.length); + throw new ParseException(date, 0); + } + year = parse_int(ymd[0]); + month = parse_int(ymd[1]); + day = parse_int(ymd[2]); + + String[] hms = time.split(":"); + if (hms.length != 3) { + System.out.println("Error parsing GPS time " + time + " got " + hms.length); + throw new ParseException(time, 0); + } + hour = parse_int(hms[0]); + minute = parse_int(hms[1]); + second = parse_int(hms[2]); + } + + public AltosGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } +}; + +class AltosGPS { + int nsat; + int gps_locked; + int gps_connected; + AltosGPSTime gps_time; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + + int gps_extended; /* has extra data */ + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless? */ + int h_error; /* m */ + int v_error; /* m */ + +} + +class AltosGPSSat { + int svid; + int c_n0; +} + +class AltosGPSTracking { + int channels; + AltosGPSSat[] cc_gps_sat; +} + +public class AltosTelemetry { + int version; + String callsign; + int serial; + int flight; + int rssi; + int status; + String state; + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + int flight_accel; + int ground_accel; + int flight_vel; + int flight_pres; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + AltosGPS gps; + AltosGPSTracking gps_tracking; + + int parse_int(String v) throws ParseException { + try { + return Integer.parseInt(v); + } catch (NumberFormatException e) { + System.out.println("error parsing int " + v); + throw new ParseException(v, 0); + } + } + + int parse_hex(String v) throws ParseException { + try { + return Integer.parseInt(v, 16); + } catch (NumberFormatException e) { + System.out.println("error parsing hex " + v); + throw new ParseException(v, 0); + } + } + + double parse_double(String v) throws ParseException { + try { + return Double.parseDouble(v); + } catch (NumberFormatException e) { + System.out.println("error parsing double " + v); + throw new ParseException(v, 0); + } + } + + double parse_coord(String coord) throws ParseException { + String[] dsf = coord.split("\\D+"); + + if (dsf.length != 3) { + System.out.println("error parsing coord " + coord); + throw new ParseException(coord, 0); + } + int deg = parse_int(dsf[0]); + int min = parse_int(dsf[1]); + int frac = parse_int(dsf[2]); + + double r = deg + (min + frac / 10000.0) / 60.0; + if (coord.endsWith("S") || coord.endsWith("W")) + r = -r; + return r; + } + + String strip_suffix(String v, String suffix) { + if (v.endsWith(suffix)) + return v.substring(0, v.length() - suffix.length()); + return v; + } + + void word(String v, String m) throws ParseException { + if (!v.equals(m)) { + System.out.println("error matching '" + v + "' '" + m + "'"); + throw new ParseException(v, 0); + } + } + + public AltosTelemetry(String line) throws ParseException { + String[] words = line.split("\\s+"); + + int i = 0; + + word (words[i++], "VERSION"); + version = parse_int(words[i++]); + + word (words[i++], "CALL"); + callsign = words[i++]; + + word (words[i++], "SERIAL"); + serial = parse_int(words[i++]); + + word (words[i++], "FLIGHT"); + flight = parse_int(words[i++]); + + word(words[i++], "RSSI"); + rssi = parse_int(words[i++]); + + word(words[i++], "STATUS"); + status = parse_hex(words[i++]); + + word(words[i++], "STATE"); + state = words[i++]; + + tick = parse_int(words[i++]); + + word(words[i++], "a:"); + accel = parse_int(words[i++]); + + word(words[i++], "p:"); + pres = parse_int(words[i++]); + + word(words[i++], "t:"); + temp = parse_int(words[i++]); + + word(words[i++], "v:"); + batt = parse_int(words[i++]); + + word(words[i++], "d:"); + drogue = parse_int(words[i++]); + + word(words[i++], "m:"); + main = parse_int(words[i++]); + + word(words[i++], "fa:"); + flight_accel = parse_int(words[i++]); + + word(words[i++], "ga:"); + ground_accel = parse_int(words[i++]); + + word(words[i++], "fv:"); + flight_vel = parse_int(words[i++]); + + word(words[i++], "fp:"); + flight_pres = parse_int(words[i++]); + + word(words[i++], "gp:"); + ground_pres = parse_int(words[i++]); + + word(words[i++], "a+:"); + accel_plus_g = parse_int(words[i++]); + + word(words[i++], "a-:"); + accel_minus_g = parse_int(words[i++]); + + word(words[i++], "GPS"); + gps = new AltosGPS(); + gps.nsat = parse_int(words[i++]); + word(words[i++], "sat"); + + gps.gps_connected = 0; + gps.gps_locked = 0; + gps.lat = gps.lon = 0; + gps.alt = 0; + if ((words[i]).equals("unlocked")) { + gps.gps_connected = 1; + gps.gps_time = new AltosGPSTime(); + i++; + } else if (words.length >= 40) { + gps.gps_locked = 1; + gps.gps_connected = 1; + + gps.gps_time = new AltosGPSTime(words[i], words[i+1]); i += 2; + gps.lat = parse_coord(words[i++]); + gps.lon = parse_coord(words[i++]); + gps.alt = parse_int(strip_suffix(words[i++], "m")); + gps.ground_speed = parse_double(strip_suffix(words[i++], "m/s(H)")); + gps.course = parse_int(strip_suffix(words[i++], "°")); + gps.climb_rate = parse_double(strip_suffix(words[i++], "m/s(V)")); + gps.hdop = parse_double(strip_suffix(words[i++], "(hdop)")); + gps.h_error = parse_int(strip_suffix(words[i++], "(herr)")); + gps.v_error = parse_int(strip_suffix(words[i++], "(verr)")); + } else { + gps.gps_time = new AltosGPSTime(); + } + word(words[i++], "SAT"); + gps_tracking = new AltosGPSTracking(); + gps_tracking.channels = parse_int(words[i++]); + gps_tracking.cc_gps_sat = new AltosGPSSat[gps_tracking.channels]; + for (int chan = 0; chan < gps_tracking.channels; chan++) { + gps_tracking.cc_gps_sat[chan] = new AltosGPSSat(); + gps_tracking.cc_gps_sat[chan].svid = parse_int(words[i++]); + gps_tracking.cc_gps_sat[chan].c_n0 = parse_int(words[i++]); + } + } +} -- cgit v1.2.3 From 584ab100640a07dec6e06829e73b7260d17d2232 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 1 Apr 2010 18:30:56 -0700 Subject: Add Windows install .inf file --- telemetrum.inf | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 telemetrum.inf diff --git a/telemetrum.inf b/telemetrum.inf new file mode 100644 index 00000000..2d0b8fab --- /dev/null +++ b/telemetrum.inf @@ -0,0 +1,41 @@ +[Version] +Signature = "$Windows NT$" +Class = Modem +ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318} +Provider = %ALTUSMETRUM% +DriverVer = 30/03/2010,1.0.0.0 + +; Copyright (C) 2010 Keith Packard (keithp@keithp.com) +; released under GNU General Public License version 2 + +[Manufacturer] +%ALTUSMETRUM%=TeleMetrumDeviceList + +[TeleMetrumDeviceList] +%TELEMETRUM%=TeleMetrum, USB\VID_FFFE&PID_000A + +[DestinationDirs] +DefaultDestDir=12 + +[ControlFlags] +ExcludeFromSelect=USB\VID_FFFE&PID_000A + +[Strings] +ALTUSMETRUM="altusmetrum.org" +TELEMETRUM="TeleMetrum/TeleDongle" + +[TeleMetrum.NT] +include=mdmcpq.inf +CopyFiles=FakeModemCopyFileSection +AddReg = Uninstall.AddReg + +[TeleMetrum.NT.HW] +include=mdmcpq.inf +AddReg=LowerFilterAddReg + +[TeleMetrum.NT.Services] +include=mdmcpq.inf +AddService=usbser, 0x00000000, LowerFilter_Service_Inst + +[Uninstall.AddReg] +HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TELEMETRUM%,DisplayName,,"%TELEMETRUM%" -- cgit v1.2.3 From 6454e309858aeef7912e862de8632618d89b4205 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 1 Apr 2010 18:31:14 -0700 Subject: Fix windows install file --- telemetrum.inf | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) mode change 100644 => 100755 telemetrum.inf diff --git a/telemetrum.inf b/telemetrum.inf old mode 100644 new mode 100755 index 2d0b8fab..4549cfba --- a/telemetrum.inf +++ b/telemetrum.inf @@ -1,41 +1,42 @@ -[Version] -Signature = "$Windows NT$" -Class = Modem -ClassGuid = {4D36E978-E325-11CE-BFC1-08002BE10318} -Provider = %ALTUSMETRUM% -DriverVer = 30/03/2010,1.0.0.0 - ; Copyright (C) 2010 Keith Packard (keithp@keithp.com) ; released under GNU General Public License version 2 +[Version] +Signature = "$Windows NT$" +Class = Ports +ClassGUID = {4d36e978-e325-11ce-bfc1-08002be10318} +Provider = %Mfg% +DriverVer = 30/03/2010,4.0.0.8 + [Manufacturer] -%ALTUSMETRUM%=TeleMetrumDeviceList +%Mfg% = Models -[TeleMetrumDeviceList] -%TELEMETRUM%=TeleMetrum, USB\VID_FFFE&PID_000A +[Models] +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A [DestinationDirs] -DefaultDestDir=12 +DefaultDestDir = 12 [ControlFlags] -ExcludeFromSelect=USB\VID_FFFE&PID_000A +ExcludeFromSelect=USB\VID_0BAF&PID_0303 [Strings] -ALTUSMETRUM="altusmetrum.org" -TELEMETRUM="TeleMetrum/TeleDongle" +Mfg = "altusmetrum.org" +TeleMetrum = "TeleMetrum/TeleDongle" -[TeleMetrum.NT] +[TELEMETRUM.NT] include=mdmcpq.inf CopyFiles=FakeModemCopyFileSection -AddReg = Uninstall.AddReg +AddReg=Uninstall -[TeleMetrum.NT.HW] -include=mdmcpq.inf +[TELEMETRUM.NT.HW] +Include=mdmcpq.inf AddReg=LowerFilterAddReg -[TeleMetrum.NT.Services] -include=mdmcpq.inf +[TELEMETRUM.NT.Services] +Include=mdmcpq.inf AddService=usbser, 0x00000000, LowerFilter_Service_Inst -[Uninstall.AddReg] -HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TELEMETRUM%,DisplayName,,"%TELEMETRUM%" +[Uninstall] +HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TeleMetrum%,DisplayName,,"%TeleMetrum%" + -- cgit v1.2.3 From 53ca3f98aeb70cb780031fee788de950e4388cf6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 1 Apr 2010 23:39:42 -0600 Subject: tweak copyright assertion --- doc/telemetrum.xsl | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 7d855318..97d8fb23 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -13,7 +13,7 @@ 2010 - Bdale Garbee + Bdale Garbee and Keith Packard TeleMetrum Owner's Manual for the TeleMetrum System @@ -35,7 +35,43 @@ - Introduction + Introduction and Overview + + Placeholder. + + + + Specifications + + Placeholder. + + + + Handling Precautions + + Placeholder. + + + + Hardware Overview + + Placeholder. + + + + Operation + + Placeholder. + + + + System Overview + + Placeholder. + + + + System Overview Placeholder. -- cgit v1.2.3 From 8c600abf87c95f8f214b5e56ff6eab955795dff5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 1 Apr 2010 23:56:47 -0600 Subject: crudely incorporate "day in the life" info from web page --- doc/telemetrum.xsl | 144 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 134 insertions(+), 10 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 97d8fb23..fb65ce01 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -65,16 +65,140 @@ - System Overview - - Placeholder. - - - - System Overview - - Placeholder. - + Using Altus Metrum Products +
+ Being Legal + + First off, in the US, you need an [amateur radio license](../Radio) or + other authorization to legally operate the radio transmitters that are part + of our products. + +
+ In the Rocket + + In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. + +
+
+ On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our [TeleDongle](../TeleDongle) units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + Right now, all of our application software is written for Linux. However, + because we understand that many people run Windows or MacOS, we are working + on a new ground station program written in Java that should work on all + operating systems. + + + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the + [Yaesu VX-6R](http://yaesu.com/indexVS.cfm?cmd=DisplayProducts&ProdCatID=111&encProdID=4C6F204F6FEBB5BAFA58BCC1C131EAC0&DivisionID=65&isArchived=0) + at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + [Arrow Antennas](http://www.arrowantennas.com/). The 440-3 and 440-5 are + both good choices for finding a TeleMetrum-equipped rocket when used with + a suitable 70cm HT. + +
+
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. + +
+
+ Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + + + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too... + +
+
-- cgit v1.2.3 From 02f2be90879b682b6e648cf2debc83223d127b9d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 13:37:52 -0700 Subject: Add telem parsing code --- ao-tools/altosui/AltosSerial.java | 152 ++++++++++++++++++++++++----------- ao-tools/altosui/AltosTelemetry.java | 52 +++++++----- ao-tools/altosui/AltosUI.java | 143 ++++++++++++++++++++++++-------- ao-tools/altosui/Makefile | 13 ++- 4 files changed, 260 insertions(+), 100 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 82663eab..9537f190 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -21,18 +21,12 @@ package altosui; -import java.lang.String; -import java.lang.System; -import java.lang.Character; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.FileNotFoundException; +import java.lang.*; +import java.io.*; import java.util.concurrent.LinkedBlockingQueue; -import java.lang.InterruptedException; import java.util.LinkedList; -import altosui.AltosSerialMonitor; import java.util.Iterator; +import altosui.AltosSerialMonitor; /* * This class reads from the serial port and places each received @@ -43,6 +37,7 @@ class AltosSerialReader implements Runnable { FileInputStream serial_in; LinkedBlockingQueue monitor_queue; LinkedBlockingQueue reply_queue; + Thread input_thread; String line; public void run () { @@ -71,20 +66,12 @@ class AltosSerialReader implements Runnable { } } - public String get_telem() { - try { - return monitor_queue.take(); - } catch (InterruptedException e) { - return ""; - } + public String get_telem() throws InterruptedException { + return monitor_queue.take(); } - public String get_reply() { - try { - return reply_queue.take(); - } catch (InterruptedException e) { - return ""; - } + public String get_reply() throws InterruptedException { + return reply_queue.take(); } public void flush () { @@ -94,56 +81,131 @@ class AltosSerialReader implements Runnable { reply_queue.clear(); } } - public AltosSerialReader (FileInputStream in) { - serial_in = in; + + public boolean opened() { + return serial_in != null; + } + + public void close() { + if (serial_in != null) { + try { + serial_in.close(); + } catch (IOException e) { + } + serial_in = null; + } + if (input_thread != null) { + try { + input_thread.join(); + } catch (InterruptedException e) { + } + input_thread = null; + } + } + + public void open(File name) throws FileNotFoundException { + close(); + serial_in = new FileInputStream(name); + input_thread = new Thread(this); + input_thread.start(); + } + public AltosSerialReader () { + serial_in = null; + input_thread = null; + line = ""; monitor_queue = new LinkedBlockingQueue (); reply_queue = new LinkedBlockingQueue (); - line = ""; } } public class AltosSerial implements Runnable { - FileInputStream serial_in = null; FileOutputStream serial_out = null; - AltosSerialReader reader; + Thread monitor_thread = null; + AltosSerialReader reader = null; LinkedList callbacks; public void run() { - for (;;) { - String s = reader.get_reply(); - synchronized(callbacks) { - Iterator i = callbacks.iterator(); - while (i.hasNext()) { - i.next().data(s); + try { + for (;;) { + String s = reader.get_telem(); + synchronized(callbacks) { + Iterator i = callbacks.iterator(); + while (i.hasNext()) { + i.next().data(s); + } } } + } catch (InterruptedException e) { } } - public void start () { - try { - serial_out.write('?'); - serial_out.write('\r'); - } catch (IOException e) { + boolean need_monitor() { + return reader.opened() && !callbacks.isEmpty(); + } + + void maybe_stop_monitor() { + if (!need_monitor() && monitor_thread != null) { + monitor_thread.interrupt(); + try { + monitor_thread.join(); + } catch (InterruptedException e) { + } finally { + monitor_thread = null; + } + } + } + + void maybe_start_monitor() { + if (need_monitor() && monitor_thread == null) { + monitor_thread = new Thread(this); + monitor_thread.start(); } - (new Thread(reader)).start(); - (new Thread(this)).start(); } public void monitor(AltosSerialMonitor monitor) { synchronized(callbacks) { callbacks.add(monitor); + maybe_start_monitor(); } } - public AltosSerial(String serial_name) { + + public void unmonitor(AltosSerialMonitor monitor) { + synchronized(callbacks) { + callbacks.remove(monitor); + maybe_stop_monitor(); + } + } + + public void close() { + synchronized(callbacks) { + reader.close(); + maybe_stop_monitor(); + } + } + + public void open(File serial_name) throws FileNotFoundException { + reader.open(serial_name); + serial_out = new FileOutputStream(serial_name); try { - serial_in = new FileInputStream(serial_name); - serial_out = new FileOutputStream(serial_name); - reader = new AltosSerialReader(serial_in); - callbacks = new LinkedList(); - } catch (FileNotFoundException e) { + serial_out.write('?'); + serial_out.write('\r'); + } catch (IOException e) { } } + + void init() { + reader = new AltosSerialReader(); + callbacks = new LinkedList(); + } + + public AltosSerial() { + init(); + } + + public AltosSerial(File serial_name) throws FileNotFoundException { + init(); + open(serial_name); + } } diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index e072bb34..99e82bbf 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -36,25 +36,21 @@ class AltosGPSTime { try { return Integer.parseInt(v); } catch (NumberFormatException e) { - throw new ParseException(v, 0); + throw new ParseException("error parsing GPS value " + v, 0); } } public AltosGPSTime(String date, String time) throws ParseException { String[] ymd = date.split("-"); - if (ymd.length != 3) { - System.out.println("Error parsing GPS date " + date + " got " + ymd.length); - throw new ParseException(date, 0); - } + if (ymd.length != 3) + throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0); year = parse_int(ymd[0]); month = parse_int(ymd[1]); day = parse_int(ymd[2]); String[] hms = time.split(":"); - if (hms.length != 3) { - System.out.println("Error parsing GPS time " + time + " got " + hms.length); - throw new ParseException(time, 0); - } + if (hms.length != 3) + throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); hour = parse_int(hms[0]); minute = parse_int(hms[1]); second = parse_int(hms[2]); @@ -95,6 +91,29 @@ class AltosGPSTracking { AltosGPSSat[] cc_gps_sat; } +/* + * The telemetry data stream is a bit of a mess at present, with no consistent + * formatting. In particular, the GPS data is formatted for viewing instead of parsing. + * However, the key feature is that every telemetry line contains all of the information + * necessary to describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + */ + public class AltosTelemetry { int version; String callsign; @@ -124,8 +143,7 @@ public class AltosTelemetry { try { return Integer.parseInt(v); } catch (NumberFormatException e) { - System.out.println("error parsing int " + v); - throw new ParseException(v, 0); + throw new ParseException("error parsing int " + v, 0); } } @@ -133,8 +151,7 @@ public class AltosTelemetry { try { return Integer.parseInt(v, 16); } catch (NumberFormatException e) { - System.out.println("error parsing hex " + v); - throw new ParseException(v, 0); + throw new ParseException("error parsing hex " + v, 0); } } @@ -142,8 +159,7 @@ public class AltosTelemetry { try { return Double.parseDouble(v); } catch (NumberFormatException e) { - System.out.println("error parsing double " + v); - throw new ParseException(v, 0); + throw new ParseException("error parsing double " + v, 0); } } @@ -151,8 +167,7 @@ public class AltosTelemetry { String[] dsf = coord.split("\\D+"); if (dsf.length != 3) { - System.out.println("error parsing coord " + coord); - throw new ParseException(coord, 0); + throw new ParseException("error parsing coord " + coord, 0); } int deg = parse_int(dsf[0]); int min = parse_int(dsf[1]); @@ -172,8 +187,7 @@ public class AltosTelemetry { void word(String v, String m) throws ParseException { if (!v.equals(m)) { - System.out.println("error matching '" + v + "' '" + m + "'"); - throw new ParseException(v, 0); + throw new ParseException("error matching '" + v + "' '" + m + "'", 0); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index b731725c..89eaac15 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -17,29 +17,14 @@ package altosui; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Font; -import java.awt.Toolkit; -import java.awt.Window; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.awt.event.MouseListener; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import javax.swing.JFrame; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JRadioButtonMenuItem; -import javax.swing.JSplitPane; -import javax.swing.JTable; -import javax.swing.KeyStroke; -import javax.swing.table.TableCellEditor; -import javax.swing.table.DefaultTableCellRenderer; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import java.io.*; +import java.util.*; +import java.text.*; +import gnu.io.CommPortIdentifier; + import altosui.AltosSerial; import altosui.AltosSerialMonitor; @@ -71,13 +56,10 @@ public class AltosUI extends JFrame { createMenu(); - serialLine = new AltosSerial("/dev/ttyACM0"); + serialLine = new AltosSerial(); serialLine.monitor(new AltosUIMonitor()); - serialLine.start(); - Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); - size.width = size.width*9/10; - size.height = size.height*9/10; - this.setSize(size); + int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); + this.setSize(new Dimension (dpi * 5, dpi * 4)); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -88,6 +70,94 @@ public class AltosUI extends JFrame { }); } + final JFileChooser deviceChooser = new JFileChooser(); + + private void PickSerialDevice() { + java.util.Enumeration port_list = CommPortIdentifier.getPortIdentifiers(); + while (port_list.hasMoreElements()) { + CommPortIdentifier identifier = port_list.nextElement(); + System.out.println("Serial port " + identifier.getName()); + } + } + + private void ConnectToDevice() { + PickSerialDevice(); + int returnVal = deviceChooser.showOpenDialog(AltosUI.this); + + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = deviceChooser.getSelectedFile(); + try { + serialLine.open(file); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + file.getName(), + "Cannot open serial port", + JOptionPane.ERROR_MESSAGE); + } + } + } + + String readline(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') + return line; + line = line + (char) c; + } + return null; + } + + private void Replay() { +// int returnVal = deviceChooser.showOpenDialog(AltosUI.this); + + /* if (returnVal == JFileChooser.APPROVE_OPTION) */ { +// File file = deviceChooser.getSelectedFile(); +// String filename = file.getName(); + String filename = "/home/keithp/src/cc1111/flights/2010-02-13-serial-051-flight-002.telem"; + try { +// FileInputStream replay = new FileInputStream(file); + FileInputStream replay = new FileInputStream(filename); + String line; + + try { + while ((line = readline(replay)) != null) { + try { + AltosTelemetry t = new AltosTelemetry(line); + System.out.println ("Version " + t.version + t.callsign); + } catch (ParseException pp) { + JOptionPane.showMessageDialog(AltosUI.this, + line, + "error parsing", + JOptionPane.ERROR_MESSAGE); + break; + } + } + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + filename, + "error reading", + JOptionPane.ERROR_MESSAGE); + } finally { + try { + replay.close(); + } catch (IOException e) {} + } + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + filename, + "Cannot open serial port", + JOptionPane.ERROR_MESSAGE); + } + } + } + + private void SaveFlightData() { + } + private void createMenu() { JMenuBar menubar = new JMenuBar(); JMenu menu; @@ -120,6 +190,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Connect to Device",KeyEvent.VK_C); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + ConnectToDevice(); } }); menu.add(item); @@ -127,6 +198,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + serialLine.close(); } }); menu.add(item); @@ -136,6 +208,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Save Flight Data",KeyEvent.VK_S); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + SaveFlightData(); } }); menu.add(item); @@ -143,6 +216,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Replay",KeyEvent.VK_R); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + Replay(); } }); menu.add(item); @@ -186,16 +260,21 @@ public class AltosUI extends JFrame { menu = new JMenu("Channel", true); menu.setMnemonic(KeyEvent.VK_C); menubar.add(menu); + ButtonGroup group = new ButtonGroup(); for (int c = 0; c <= 9; c++) { - radioitem = new JRadioButtonMenuItem("Channel " + c + " (" + - (434.550 + c * .1) + ")", - c == 0); + radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c, + 434.550 + c * 0.1), + c == 0); + radioitem.setActionCommand(String.format("%d", c)); radioitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + System.out.println("Command: " + e.getActionCommand() + " param: " + + e.paramString()); } }); menu.add(radioitem); + group.add(radioitem); } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index cb422df8..090911ef 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,13 +1,18 @@ .SUFFIXES: .java .class -CLASSPATH=.. -CLASSFILES=AltosSerialMonitor.class AltosSerial.class AltosUI.class +CLASSPATH=..:/usr/share/java/* +CLASSFILES=AltosSerialMonitor.class AltosSerial.class AltosTelemetry.class AltosUI.class JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) +all: $(CLASSFILES) altosui .java.class: - javac -cp $(CLASSPATH) $(JAVAFLAGS) $*.java + javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +altosui: Makefile + (echo '#!/bin/sh'; \ + echo exec java -cp '"$(CLASSPATH)"' altosui/AltosUI) > $@ + chmod +x $@ clean: rm -f *.class \ No newline at end of file -- cgit v1.2.3 From 65079f84ea64220fa928c3ad96652fed159bf74b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 16:07:40 -0700 Subject: Steal C code from ao-view --- ao-tools/altosui/AltosConvert.java | 245 ++++++++++++++++++++++++++++ ao-tools/altosui/AltosGPS.java | 118 ++++++++++++++ ao-tools/altosui/AltosGreatCircle.java | 66 ++++++++ ao-tools/altosui/AltosParse.java | 75 +++++++++ ao-tools/altosui/AltosState.java | 166 +++++++++++++++++++ ao-tools/altosui/AltosTelemetry.java | 290 ++++++++++----------------------- ao-tools/altosui/AltosUI.java | 76 ++++++++- ao-tools/altosui/Makefile | 12 +- 8 files changed, 837 insertions(+), 211 deletions(-) create mode 100644 ao-tools/altosui/AltosConvert.java create mode 100644 ao-tools/altosui/AltosGPS.java create mode 100644 ao-tools/altosui/AltosGreatCircle.java create mode 100644 ao-tools/altosui/AltosParse.java create mode 100644 ao-tools/altosui/AltosState.java diff --git a/ao-tools/altosui/AltosConvert.java b/ao-tools/altosui/AltosConvert.java new file mode 100644 index 00000000..3be0716c --- /dev/null +++ b/ao-tools/altosui/AltosConvert.java @@ -0,0 +1,245 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Sensor data conversion functions + */ +package altosui; + +public class AltosConvert { + /* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= Math.pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * Math.pow(base, exponent); + } + + return pressure; + } + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ + static double + cc_pressure_to_altitude(double pressure) + { + + double next_base_temperature = LAYER0_BASE_TEMPERATURE; + double next_base_pressure = LAYER0_BASE_PRESSURE; + + double altitude; + double base_pressure; + double base_temperature; + double base; /* base for function to determine base pressure of next layer */ + double exponent; /* exponent for function to determine base pressure + of next layer */ + double coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= Math.pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * Math.log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (Math.pow(base, exponent) - 1); + } + + return altitude; + } + + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + static final double counts_per_kPa = 27 * 2047 / 3300; + static final double counts_at_101_3kPa = 1674.0; + + static double + cc_barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + static double + cc_barometer_to_altitude(double baro) + { + double Pa = cc_barometer_to_pressure(baro); + return cc_pressure_to_altitude(Pa); + } + + static final double count_per_mss = 27.0; + + static double + cc_accelerometer_to_acceleration(double accel, double ground_accel) + { + return (ground_accel - accel) / count_per_mss; + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + static double + cc_thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + static double + cc_battery_to_voltage(double battery) + { + return battery / 32767.0 * 5.0; + } + + static double + cc_ignitor_to_voltage(double ignite) + { + return ignite / 32767 * 15.0; + } +} diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java new file mode 100644 index 00000000..d242ad57 --- /dev/null +++ b/ao-tools/altosui/AltosGPS.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import altosui.AltosParse; + + +public class AltosGPS { + public class AltosGPSTime { + int year; + int month; + int day; + int hour; + int minute; + int second; + + public AltosGPSTime(String date, String time) 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]); + + String[] hms = time.split(":"); + if (hms.length != 3) + throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); + hour = AltosParse.parse_int(hms[0]); + minute = AltosParse.parse_int(hms[1]); + second = AltosParse.parse_int(hms[2]); + } + + public AltosGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } + + } + + public class AltosGPSSat { + int svid; + int c_n0; + } + + int nsat; + boolean gps_locked; + boolean gps_connected; + AltosGPSTime gps_time; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + + int gps_extended; /* has extra data */ + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless? */ + int h_error; /* m */ + int v_error; /* m */ + + AltosGPSSat[] cc_gps_sat; /* tracking data */ + + public AltosGPS(String[] words, int i) throws ParseException { + AltosParse.word(words[i++], "GPS"); + nsat = AltosParse.parse_int(words[i++]); + AltosParse.word(words[i++], "sat"); + + gps_connected = false; + gps_locked = false; + lat = lon = 0; + alt = 0; + if ((words[i]).equals("unlocked")) { + gps_connected = true; + gps_time = new AltosGPSTime(); + i++; + } else if (words.length >= 40) { + gps_locked = true; + gps_connected = true; + + gps_time = new AltosGPSTime(words[i], words[i+1]); i += 2; + 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)")); + } else { + gps_time = new AltosGPSTime(); + } + AltosParse.word(words[i++], "SAT"); + int tracking_channels = AltosParse.parse_int(words[i++]); + cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; + for (int chan = 0; chan < tracking_channels; chan++) { + cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); + cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); + } + } +} diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java new file mode 100644 index 00000000..878da03e --- /dev/null +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -0,0 +1,66 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Math; + +public class AltosGreatCircle { + double distance; + double bearing; + + double sqr(double a) { return a * a; } + + 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) + { + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + + sqr(Math.cos(lat1) * Math.sin(lat2) - + Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); + double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); + double d = Math.atan2(vdn,vdd); + double course; + + if (Math.cos(lat1) < 1e-20) { + if (lat1 > 0) + course = Math.PI; + else + course = -Math.PI; + } else { + if (d < 1e-10) + course = 0; + else + course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / + (Math.sin(d)*Math.cos(lat1))); + if (Math.sin(lon2-lon1) > 0) + course = 2 * Math.PI-course; + } + distance = d * earth_radius; + bearing = course * 180/Math.PI; + } +} diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java new file mode 100644 index 00000000..a60dc694 --- /dev/null +++ b/ao-tools/altosui/AltosParse.java @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.lang.*; + +public class AltosParse { + static int parse_int(String v) throws ParseException { + try { + return Integer.parseInt(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); + } catch (NumberFormatException e) { + throw new ParseException("error parsing hex " + v, 0); + } + } + + static double parse_double(String v) throws ParseException { + try { + return Double.parseDouble(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing double " + v, 0); + } + } + + static double parse_coord(String coord) throws ParseException { + String[] dsf = coord.split("\\D+"); + + if (dsf.length != 3) { + throw new ParseException("error parsing coord " + coord, 0); + } + int deg = parse_int(dsf[0]); + int min = parse_int(dsf[1]); + int frac = parse_int(dsf[2]); + + double r = deg + (min + frac / 10000.0) / 60.0; + if (coord.endsWith("S") || coord.endsWith("W")) + r = -r; + return r; + } + + static String strip_suffix(String v, String suffix) { + if (v.endsWith(suffix)) + return v.substring(0, v.length() - suffix.length()); + return v; + } + + static void word(String v, String m) throws ParseException { + if (!v.equals(m)) { + throw new ParseException("error matching '" + v + "' '" + m + "'", 0); + } + } +} diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java new file mode 100644 index 00000000..da465c75 --- /dev/null +++ b/ao-tools/altosui/AltosState.java @@ -0,0 +1,166 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Track flight state from telemetry data stream + */ + +package altosui; + +import altosui.AltosTelemetry; +import altosui.AltosGPS; + +public class AltosState { + AltosTelemetry data; + AltosTelemetry prev_data; + + /* derived data */ + + double report_time; + + int state; + boolean ascent; /* going up? */ + + double ground_altitude; + double height; + double speed; + double acceleration; + double battery; + double temperature; + double main_sense; + double drogue_sense; + double baro_speed; + + double max_height; + double max_acceleration; + double max_speed; + + AltosGPS gps; + AltosGPSTracking gps_tracking; + + boolean gps_valid; + double pad_lat; + double pad_lon; + double pad_alt; + double pad_lat_total; + double pad_lon_total; + double pad_alt_total; + int npad; + int prev_npad; + + AltosGreatCircle from_pad; + + double gps_height; + + int speak_tick; + double speak_altitude; + + static double + aoview_time() + { + return System.currentTimeMillis() / 1000.0; + } + + public AltosState (AltosTelemetry cur, AltosTelemetry prev, int prev_npad) { + int i; + double new_height; + double height_change; + double time_change; + double accel_counts_per_mss; + int tick_count; + + data = cur; + prev_data = prev; + npad = prev_npad; + tick_count = data.tick; + if (tick_count < prev_data.tick) + tick_count += 65536; + time_change = (tick_count - prev_data.tick) / 100.0; + + report_time = aoview_time(); + + ground_altitude = AltosConvert.cc_pressure_to_altitude(data.ground_pres); + new_height = AltosConvert.cc_pressure_to_altitude(data.flight_pres) - ground_altitude; + height_change = new_height - height; + height = new_height; + if (time_change > 0) + baro_speed = (baro_speed * 3 + (height_change / time_change)) / 4.0; + accel_counts_per_mss = ((data.accel_minus_g - data.accel_plus_g) / 2.0) / 9.80665; + acceleration = (data.ground_accel - data.flight_accel) / accel_counts_per_mss; + speed = data.flight_vel / (accel_counts_per_mss * 100.0); + temperature = AltosConvert.cc_thermometer_to_temperature(data.temp); + drogue_sense = AltosConvert.cc_ignitor_to_voltage(data.drogue); + main_sense = AltosConvert.cc_ignitor_to_voltage(data.main); + battery = AltosConvert.cc_battery_to_voltage(data.batt); + state = data.state(); + if (state == AltosTelemetry.ao_flight_pad) { + if (data.gps.gps_locked && data.gps.nsat >= 4) { + npad++; + pad_lat_total += data.gps.lat; + pad_lon_total += data.gps.lon; + pad_alt_total += data.gps.alt; + if (npad > 1) { + pad_lat = (pad_lat * 31 + data.gps.lat) / 32.0; + pad_lon = (pad_lon * 31 + data.gps.lon) / 32.0; + pad_alt = (pad_alt * 31 + data.gps.alt) / 32.0; + } else { + pad_lat = data.gps.lat; + pad_lon = data.gps.lon; + pad_alt = data.gps.alt; + } + } + } + ascent = (AltosTelemetry.ao_flight_boost <= state && + state <= AltosTelemetry.ao_flight_coast); + + /* Only look at accelerometer data on the way up */ + if (ascent && acceleration > max_acceleration) + max_acceleration = acceleration; + if (ascent && speed > max_speed) + max_speed = speed; + + if (height > max_height) + max_height = height; + gps.gps_locked = data.gps.gps_locked; + gps.gps_connected = data.gps.gps_connected; + if (data.gps.gps_locked) { + gps = data.gps; + gps_valid = true; + if (npad > 0) + from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); + } + if (npad > 0) { + gps_height = gps.alt - pad_alt; + } else { + gps_height = 0; + } + } + + public AltosState(AltosTelemetry cur) { + this(cur, cur, 0); + } + + public AltosState (AltosTelemetry cur, AltosState prev) { + this(cur, prev.data, prev.npad); + if (gps == null) { + gps = prev.gps; + gps_valid = prev.gps_valid; + } + if (gps_tracking == null) + gps_tracking = prev.gps_tracking; + } +} diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index 99e82bbf..34b4099f 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -19,77 +19,14 @@ package altosui; import java.lang.*; import java.text.*; +import java.util.HashMap; +import altosui.AltosConvert; +import altosui.AltosGPS; /* * Telemetry data contents */ -class AltosGPSTime { - int year; - int month; - int day; - int hour; - int minute; - int second; - - int parse_int(String v) throws ParseException { - try { - return Integer.parseInt(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing GPS value " + v, 0); - } - } - - public AltosGPSTime(String date, String time) throws ParseException { - String[] ymd = date.split("-"); - if (ymd.length != 3) - throw new ParseException("error parsing GPS date " + date + " got " + ymd.length, 0); - year = parse_int(ymd[0]); - month = parse_int(ymd[1]); - day = parse_int(ymd[2]); - - String[] hms = time.split(":"); - if (hms.length != 3) - throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); - hour = parse_int(hms[0]); - minute = parse_int(hms[1]); - second = parse_int(hms[2]); - } - - public AltosGPSTime() { - year = month = day = 0; - hour = minute = second = 0; - } -}; - -class AltosGPS { - int nsat; - int gps_locked; - int gps_connected; - AltosGPSTime gps_time; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - - int gps_extended; /* has extra data */ - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless? */ - int h_error; /* m */ - int v_error; /* m */ - -} - -class AltosGPSSat { - int svid; - int c_n0; -} - -class AltosGPSTracking { - int channels; - AltosGPSSat[] cc_gps_sat; -} /* * The telemetry data stream is a bit of a mess at present, with no consistent @@ -137,58 +74,44 @@ public class AltosTelemetry { int accel_plus_g; int accel_minus_g; AltosGPS gps; - AltosGPSTracking gps_tracking; - - int parse_int(String v) throws ParseException { - try { - return Integer.parseInt(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing int " + v, 0); - } - } - int parse_hex(String v) throws ParseException { - try { - return Integer.parseInt(v, 16); - } catch (NumberFormatException e) { - throw new ParseException("error parsing hex " + v, 0); - } + public static final int ao_flight_startup = 0; + public static final int ao_flight_idle = 1; + public static final int ao_flight_pad = 2; + public static final int ao_flight_boost = 3; + public static final int ao_flight_fast = 4; + public static final int ao_flight_coast = 5; + public static final int ao_flight_drogue = 6; + public static final int ao_flight_main = 7; + public static final int ao_flight_landed = 8; + public static final int ao_flight_invalid = 9; + + static HashMap states = new HashMap(); + { + states.put("startup", ao_flight_startup); + states.put("idle", ao_flight_idle); + states.put("pad", ao_flight_pad); + states.put("boost", ao_flight_boost); + states.put("fast", ao_flight_fast); + states.put("coast", ao_flight_coast); + states.put("drogue", ao_flight_drogue); + states.put("main", ao_flight_main); + states.put("landed", ao_flight_landed); + states.put("invalid", ao_flight_invalid); } - double parse_double(String v) throws ParseException { - try { - return Double.parseDouble(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing double " + v, 0); - } - } - - double parse_coord(String coord) throws ParseException { - String[] dsf = coord.split("\\D+"); - - if (dsf.length != 3) { - throw new ParseException("error parsing coord " + coord, 0); - } - int deg = parse_int(dsf[0]); - int min = parse_int(dsf[1]); - int frac = parse_int(dsf[2]); - - double r = deg + (min + frac / 10000.0) / 60.0; - if (coord.endsWith("S") || coord.endsWith("W")) - r = -r; - return r; + public int state() { + if (states.containsKey(state)) + return states.get(state); + return ao_flight_invalid; } - String strip_suffix(String v, String suffix) { - if (v.endsWith(suffix)) - return v.substring(0, v.length() - suffix.length()); - return v; + public double altitude() { + return AltosConvert.cc_pressure_to_altitude(AltosConvert.cc_barometer_to_pressure(pres)); } - void word(String v, String m) throws ParseException { - if (!v.equals(m)) { - throw new ParseException("error matching '" + v + "' '" + m + "'", 0); - } + public double pad_altitude() { + return AltosConvert.cc_pressure_to_altitude(AltosConvert.cc_barometer_to_pressure(ground_pres)); } public AltosTelemetry(String line) throws ParseException { @@ -196,106 +119,67 @@ public class AltosTelemetry { int i = 0; - word (words[i++], "VERSION"); - version = parse_int(words[i++]); + AltosParse.word (words[i++], "VERSION"); + version = AltosParse.parse_int(words[i++]); - word (words[i++], "CALL"); + AltosParse.word (words[i++], "CALL"); callsign = words[i++]; - word (words[i++], "SERIAL"); - serial = parse_int(words[i++]); + AltosParse.word (words[i++], "SERIAL"); + serial = AltosParse.parse_int(words[i++]); - word (words[i++], "FLIGHT"); - flight = parse_int(words[i++]); + AltosParse.word (words[i++], "FLIGHT"); + flight = AltosParse.parse_int(words[i++]); - word(words[i++], "RSSI"); - rssi = parse_int(words[i++]); + AltosParse.word(words[i++], "RSSI"); + rssi = AltosParse.parse_int(words[i++]); - word(words[i++], "STATUS"); - status = parse_hex(words[i++]); + AltosParse.word(words[i++], "STATUS"); + status = AltosParse.parse_hex(words[i++]); - word(words[i++], "STATE"); + AltosParse.word(words[i++], "STATE"); state = words[i++]; - tick = parse_int(words[i++]); - - word(words[i++], "a:"); - accel = parse_int(words[i++]); - - word(words[i++], "p:"); - pres = parse_int(words[i++]); - - word(words[i++], "t:"); - temp = parse_int(words[i++]); - - word(words[i++], "v:"); - batt = parse_int(words[i++]); - - word(words[i++], "d:"); - drogue = parse_int(words[i++]); - - word(words[i++], "m:"); - main = parse_int(words[i++]); - - word(words[i++], "fa:"); - flight_accel = parse_int(words[i++]); - - word(words[i++], "ga:"); - ground_accel = parse_int(words[i++]); - - word(words[i++], "fv:"); - flight_vel = parse_int(words[i++]); - - word(words[i++], "fp:"); - flight_pres = parse_int(words[i++]); - - word(words[i++], "gp:"); - ground_pres = parse_int(words[i++]); - - word(words[i++], "a+:"); - accel_plus_g = parse_int(words[i++]); - - word(words[i++], "a-:"); - accel_minus_g = parse_int(words[i++]); - - word(words[i++], "GPS"); - gps = new AltosGPS(); - gps.nsat = parse_int(words[i++]); - word(words[i++], "sat"); - - gps.gps_connected = 0; - gps.gps_locked = 0; - gps.lat = gps.lon = 0; - gps.alt = 0; - if ((words[i]).equals("unlocked")) { - gps.gps_connected = 1; - gps.gps_time = new AltosGPSTime(); - i++; - } else if (words.length >= 40) { - gps.gps_locked = 1; - gps.gps_connected = 1; - - gps.gps_time = new AltosGPSTime(words[i], words[i+1]); i += 2; - gps.lat = parse_coord(words[i++]); - gps.lon = parse_coord(words[i++]); - gps.alt = parse_int(strip_suffix(words[i++], "m")); - gps.ground_speed = parse_double(strip_suffix(words[i++], "m/s(H)")); - gps.course = parse_int(strip_suffix(words[i++], "°")); - gps.climb_rate = parse_double(strip_suffix(words[i++], "m/s(V)")); - gps.hdop = parse_double(strip_suffix(words[i++], "(hdop)")); - gps.h_error = parse_int(strip_suffix(words[i++], "(herr)")); - gps.v_error = parse_int(strip_suffix(words[i++], "(verr)")); - } else { - gps.gps_time = new AltosGPSTime(); - } - word(words[i++], "SAT"); - gps_tracking = new AltosGPSTracking(); - gps_tracking.channels = parse_int(words[i++]); - gps_tracking.cc_gps_sat = new AltosGPSSat[gps_tracking.channels]; - for (int chan = 0; chan < gps_tracking.channels; chan++) { - gps_tracking.cc_gps_sat[chan] = new AltosGPSSat(); - gps_tracking.cc_gps_sat[chan].svid = parse_int(words[i++]); - gps_tracking.cc_gps_sat[chan].c_n0 = parse_int(words[i++]); - } + tick = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a:"); + accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "p:"); + pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "t:"); + temp = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "v:"); + batt = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "d:"); + drogue = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "m:"); + main = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fa:"); + flight_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "ga:"); + ground_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fv:"); + flight_vel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fp:"); + flight_pres = AltosParse.parse_int(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++]); + + AltosParse.word(words[i++], "a-:"); + accel_minus_g = AltosParse.parse_int(words[i++]); + } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 89eaac15..21c3e7a2 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -20,6 +20,8 @@ package altosui; import java.awt.*; import java.awt.event.*; import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.AbstractTableModel; import java.io.*; import java.util.*; import java.text.*; @@ -27,6 +29,8 @@ import gnu.io.CommPortIdentifier; import altosui.AltosSerial; import altosui.AltosSerialMonitor; +import altosui.AltosTelemetry; +import altosui.AltosState; class AltosUIMonitor implements AltosSerialMonitor { public void data(String data) { @@ -34,6 +38,32 @@ class AltosUIMonitor implements AltosSerialMonitor { } } +class AltosFlightStatusTableModel extends AbstractTableModel { + private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + private Object[] data = { 0, "idle", 0, 0 }; + + public int getColumnCount() { return columnNames.length; } + public int getRowCount() { return 1; } + public String getColumnName(int col) { return columnNames[col]; } + public Object getValueAt(int row, int col) { return data[col]; } + + public void setValueAt(Object value, int col) { + data[col] = value; + fireTableCellUpdated(0, col); + } + + public void setValueAt(Object value, int row, int col) { + setValueAt(value, col); + } + + public void set(AltosState state) { + setValueAt(state.height, 0); + setValueAt(state.data.state, 1); + setValueAt(state.data.rssi, 2); + setValueAt(state.speed, 3); + } +} + public class AltosUI extends JFrame { private int channel = -1; @@ -71,6 +101,31 @@ public class AltosUI extends JFrame { } final JFileChooser deviceChooser = new JFileChooser(); + final JFileChooser logdirChooser = new JFileChooser(); + final String logdirName = "TeleMetrum"; + File logdir = null; + + private void setLogdir() { + if (logdir == null) + logdir = new File(logdirChooser.getCurrentDirectory(), logdirName); + logdirChooser.setCurrentDirectory(logdir); + } + + private void makeLogdir() { + setLogdir(); + if (!logdir.exists()) { + if (!logdir.mkdirs()) + JOptionPane.showMessageDialog(AltosUI.this, + logdir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + } else if (!logdir.isDirectory()) { + JOptionPane.showMessageDialog(AltosUI.this, + logdir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + } + } private void PickSerialDevice() { java.util.Enumeration port_list = CommPortIdentifier.getPortIdentifiers(); @@ -111,16 +166,23 @@ public class AltosUI extends JFrame { return null; } + /* + * Open an existing telemetry file and replay it in realtime + */ + private void Replay() { -// int returnVal = deviceChooser.showOpenDialog(AltosUI.this); + setLogdir(); + logdirChooser.setDialogTitle("Select Telemetry File"); + logdirChooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); + int returnVal = logdirChooser.showOpenDialog(AltosUI.this); - /* if (returnVal == JFileChooser.APPROVE_OPTION) */ { -// File file = deviceChooser.getSelectedFile(); -// String filename = file.getName(); - String filename = "/home/keithp/src/cc1111/flights/2010-02-13-serial-051-flight-002.telem"; + if (returnVal == JFileChooser.APPROVE_OPTION) { + File file = logdirChooser.getSelectedFile(); + if (file == null) + System.out.println("No file selected?"); + String filename = file.getName(); try { -// FileInputStream replay = new FileInputStream(file); - FileInputStream replay = new FileInputStream(filename); + FileInputStream replay = new FileInputStream(file); String line; try { diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 090911ef..1fb964d6 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,7 +1,17 @@ .SUFFIXES: .java .class CLASSPATH=..:/usr/share/java/* -CLASSFILES=AltosSerialMonitor.class AltosSerial.class AltosTelemetry.class AltosUI.class +CLASSFILES=\ + AltosConvert.class \ + AltosGPS.class \ + AltosGreatCircle.class \ + AltosParse.class \ + AltosSerialMonitor.class \ + AltosSerial.class \ + AltosState.class \ + AltosTelemetry.class \ + AltosUI.class + JAVAFLAGS=-Xlint:unchecked all: $(CLASSFILES) altosui -- cgit v1.2.3 From a579402f428dd6a0529505069d1846f70b83ab5d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 18:10:59 -0700 Subject: Display table of flight info. gps is not working yet though --- ao-tools/altosui/AltosState.java | 30 ++-- ao-tools/altosui/AltosUI.java | 289 +++++++++++++++++++++++++++++++++++---- 2 files changed, 272 insertions(+), 47 deletions(-) diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index da465c75..b3054ce9 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -35,6 +35,8 @@ public class AltosState { int state; boolean ascent; /* going up? */ + double time_change; + double ground_altitude; double height; double speed; @@ -50,9 +52,7 @@ public class AltosState { double max_speed; AltosGPS gps; - AltosGPSTracking gps_tracking; - boolean gps_valid; double pad_lat; double pad_lon; double pad_alt; @@ -75,11 +75,10 @@ public class AltosState { return System.currentTimeMillis() / 1000.0; } - public AltosState (AltosTelemetry cur, AltosTelemetry prev, int prev_npad) { + void init (AltosTelemetry cur, AltosTelemetry prev, int prev_npad) { int i; double new_height; double height_change; - double time_change; double accel_counts_per_mss; int tick_count; @@ -108,7 +107,7 @@ public class AltosState { battery = AltosConvert.cc_battery_to_voltage(data.batt); state = data.state(); if (state == AltosTelemetry.ao_flight_pad) { - if (data.gps.gps_locked && data.gps.nsat >= 4) { + if (data.gps != null && data.gps.gps_locked && data.gps.nsat >= 4) { npad++; pad_lat_total += data.gps.lat; pad_lon_total += data.gps.lon; @@ -135,12 +134,9 @@ public class AltosState { if (height > max_height) max_height = height; - gps.gps_locked = data.gps.gps_locked; - gps.gps_connected = data.gps.gps_connected; - if (data.gps.gps_locked) { + if (data.gps != null) { gps = data.gps; - gps_valid = true; - if (npad > 0) + if (npad > 0 && gps.gps_locked) from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); } if (npad > 0) { @@ -151,16 +147,16 @@ public class AltosState { } public AltosState(AltosTelemetry cur) { - this(cur, cur, 0); + init(cur, cur, 0); } public AltosState (AltosTelemetry cur, AltosState prev) { - this(cur, prev.data, prev.npad); - if (gps == null) { - gps = prev.gps; - gps_valid = prev.gps_valid; + if (prev == null) + init(cur, cur, 0); + else { + init(cur, prev.data, prev.npad); + if (gps == null) + gps = prev.gps; } - if (gps_tracking == null) - gps_tracking = prev.gps_tracking; } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 21c3e7a2..47a03f4e 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -57,30 +57,114 @@ class AltosFlightStatusTableModel extends AbstractTableModel { } public void set(AltosState state) { - setValueAt(state.height, 0); + setValueAt(String.format("%1.0f", state.height), 0); setValueAt(state.data.state, 1); setValueAt(state.data.rssi, 2); - setValueAt(state.speed, 3); + double speed = state.baro_speed; + if (state.ascent) + speed = state.speed; + setValueAt(String.format("%1.0f", speed), 3); + } +} + +class AltosFlightInfoTableModel extends AbstractTableModel { + private String[] columnNames = {"Field", "Value"}; + + class InfoLine { + String name; + String value; + + public InfoLine(String n, String v) { + name = n; + value = v; + } + } + + private ArrayList rows = new ArrayList(); + + public int getColumnCount() { return columnNames.length; } + public String getColumnName(int col) { return columnNames[col]; } + + public int getRowCount() { return 20; } + + public Object getValueAt(int row, int col) { + if (row >= rows.size()) + return ""; + if (col == 0) + return rows.get(row).name; + else + return rows.get(row).value; + } + + int current_row = 0; + int prev_num_rows = 0; + + public void resetRow() { + current_row = 0; + } + public void addRow(String name, String value) { + if (current_row >= rows.size()) + rows.add(current_row, new InfoLine(name, value)); + else + rows.set(current_row, new InfoLine(name, value)); + current_row++; + } + public void finish() { + if (current_row > prev_num_rows) { + fireTableRowsInserted(prev_num_rows, current_row - 1); + prev_num_rows = current_row; + } + fireTableDataChanged(); } } public class AltosUI extends JFrame { private int channel = -1; + private AltosFlightStatusTableModel flightStatusModel; private JTable flightStatus; - private JTable flightInfo; + + static final int info_columns = 3; + + private AltosFlightInfoTableModel[] flightInfoModel; + private JTable[] flightInfo; private AltosSerial serialLine; + private Box[] ibox; + private Box vbox; + private Box hbox; public AltosUI() { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; - flightStatus = new JTable(statusData, statusNames); + vbox = Box.createVerticalBox(); + this.add(vbox); + + flightStatusModel = new AltosFlightStatusTableModel(); + flightStatus = new JTable(flightStatusModel); flightStatus.setShowGrid(false); - this.add(flightStatus); + flightInfo = new JTable[3]; + flightInfoModel = new AltosFlightInfoTableModel[3]; + ibox = new Box[3]; + + vbox.add(flightStatus.getTableHeader()); + vbox.add(flightStatus); + + hbox = Box.createHorizontalBox(); + vbox.add(hbox); + + for (int i = 0; i < info_columns; i++) { + ibox[i] = Box.createVerticalBox(); + flightInfoModel[i] = new AltosFlightInfoTableModel(); + flightInfo[i] = new JTable(flightInfoModel[i]); + flightInfo[i].setShowGrid(true); + ibox[i].add(flightInfo[i].getTableHeader()); + ibox[i].add(flightInfo[i]); + hbox.add(ibox[i]); + } setTitle("AltOS"); @@ -100,6 +184,131 @@ public class AltosUI extends JFrame { }); } + public void info_reset() { + for (int i = 0; i < info_columns; i++) + flightInfoModel[i].resetRow(); + } + + public void info_add_row(int col, String name, String value) { + flightInfoModel[col].addRow(name, value); + } + + public void info_add_row(int col, String name, String format, Object value) { + flightInfoModel[col].addRow(name, String.format(format, value)); + } + + public void info_add_row(int col, String name, String format, Object v1, Object v2) { + flightInfoModel[col].addRow(name, String.format(format, v1, v2)); + } + + public void info_add_row(int col, String name, String format, Object v1, Object v2, Object v3) { + flightInfoModel[col].addRow(name, String.format(format, v1, v2, v3)); + } + + public void info_add_deg(int col, String name, double v, int pos, int neg) { + int c = pos; + if (v < 0) { + c = neg; + v = -v; + } + double deg = Math.floor(v); + double min = (v - deg) * 60; + + flightInfoModel[col].addRow(name, String.format("%3.0f°%08.5f'", deg, min)); + } + + public void info_finish() { + for (int i = 0; i < info_columns; i++) + flightInfoModel[i].finish(); + } + + static final int MIN_PAD_SAMPLES = 10; + + public void show(AltosState state) { + flightStatusModel.set(state); + + info_reset(); + if (state.npad >= MIN_PAD_SAMPLES) + info_add_row(0, "Ground state", "%s", "ready"); + else + info_add_row(0, "Ground state", "waiting for gps (%d)", + MIN_PAD_SAMPLES - state.npad); + 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", "%d", state.data.serial); + info_add_row(0, "Rocket flight", "%d", state.data.flight); + + info_add_row(0, "RSSI", "%6ddBm", state.data.rssi); + info_add_row(0, "Height", "%6.0fm", state.height); + info_add_row(0, "Max height", "%6.0fm", state.max_height); + info_add_row(0, "Acceleration", "%7.1fm/s²", state.acceleration); + info_add_row(0, "Max acceleration", "%7.1fm/s²", state.max_acceleration); + info_add_row(0, "Speed", "%7.1fm/s", state.ascent ? state.speed : state.baro_speed); + info_add_row(0, "Max Speed", "%7.1fm/s", state.max_speed); + info_add_row(0, "Temperature", "%6.2f°C", state.temperature); + info_add_row(0, "Battery", "%5.2fV", state.battery); + info_add_row(0, "Drogue", "%5.2fV", state.drogue_sense); + info_add_row(0, "Main", "%5.2fV", state.main_sense); + info_add_row(0, "Pad altitude", "%6.0fm", state.ground_altitude); + if (state.gps != null) + info_add_row(1, "Satellites", "%d", state.gps.nsat); + else + info_add_row(1, "Satellites", "%d", 0); + if (state.gps != null && state.gps.gps_locked) { + info_add_row(1, "GPS", "locked"); + } else if (state.gps != null && state.gps.gps_connected) { + info_add_row(1, "GPS", "unlocked"); + } else { + info_add_row(1, "GPS", "not available"); + } + if (state.gps != null) { + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + info_add_row(1, "GPS altitude", "%d", state.gps.alt); + info_add_row(1, "GPS height", "%d", state.gps_height); + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.gps_time.year, + state.gps.gps_time.month, + state.gps.gps_time.day); + info_add_row(1, "GPS time", "%02d:%02d:%02d", + state.gps.gps_time.hour, + state.gps.gps_time.minute, + state.gps.gps_time.second); + info_add_row(1, "GPS ground speed", "%7.1fm/s %d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%7.1fm/s", + state.gps.climb_rate); + info_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)", + state.gps.hdop, state.gps.h_error, state.gps.v_error); + } + if (state.npad > 0) { + info_add_row(1, "Distance from pad", "%5.0fm", state.from_pad.distance); + info_add_row(1, "Direction from pad", "%4.0f°", state.from_pad.bearing); + info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); + info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); + info_add_row(1, "Pad GPS alt", "%gm", state.pad_alt); + } + if (state.gps != null && state.gps.gps_connected) { + int nsat_vis = 0; + int c; + + if (state.gps.cc_gps_sat == null) + info_add_row(2, "Satellites Visible", "%d", 0); + else { + info_add_row(2, "Satellites Visible", "%d", state.gps.cc_gps_sat.length); + for (c = 0; c < state.gps.cc_gps_sat.length; c++) { + info_add_row(2, "Satellite id,C/N0", + "%3d,%2d", + state.gps.cc_gps_sat[c].svid, + state.gps.cc_gps_sat[c].c_n0); + } + } + } + info_finish(); + } + + final JFileChooser deviceChooser = new JFileChooser(); final JFileChooser logdirChooser = new JFileChooser(); final String logdirName = "TeleMetrum"; @@ -170,6 +379,49 @@ public class AltosUI extends JFrame { * Open an existing telemetry file and replay it in realtime */ + class ReplayThread extends Thread { + FileInputStream replay; + String filename; + + ReplayThread(FileInputStream in, String name) { + replay = in; + filename = name; + } + + public void run() { + String line; + AltosState state = null; + try { + while ((line = readline(replay)) != null) { + try { + AltosTelemetry t = new AltosTelemetry(line); + state = new AltosState(t, state); + show(state); + try { + if (state.state > AltosTelemetry.ao_flight_pad) + Thread.sleep((int) (state.time_change * 1000)); + } catch (InterruptedException e) {} + } catch (ParseException pp) { + JOptionPane.showMessageDialog(AltosUI.this, + line, + "error parsing", + JOptionPane.ERROR_MESSAGE); + break; + } + } + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + filename, + "error reading", + JOptionPane.ERROR_MESSAGE); + } finally { + try { + replay.close(); + } catch (IOException e) {} + } + } + } + private void Replay() { setLogdir(); logdirChooser.setDialogTitle("Select Telemetry File"); @@ -183,31 +435,8 @@ public class AltosUI extends JFrame { String filename = file.getName(); try { FileInputStream replay = new FileInputStream(file); - String line; - - try { - while ((line = readline(replay)) != null) { - try { - AltosTelemetry t = new AltosTelemetry(line); - System.out.println ("Version " + t.version + t.callsign); - } catch (ParseException pp) { - JOptionPane.showMessageDialog(AltosUI.this, - line, - "error parsing", - JOptionPane.ERROR_MESSAGE); - break; - } - } - } catch (IOException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - filename, - "error reading", - JOptionPane.ERROR_MESSAGE); - } finally { - try { - replay.close(); - } catch (IOException e) {} - } + ReplayThread thread = new ReplayThread(replay, filename); + thread.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, -- cgit v1.2.3 From caa0bf49668344937483190d1c258bfa32971d19 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 21:44:00 -0700 Subject: Fix up table formatting --- ao-tools/altosui/AltosUI.java | 96 +++++++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 27 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 47a03f4e..7befe778 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -21,7 +21,7 @@ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.AbstractTableModel; +import javax.swing.table.*; import java.io.*; import java.util.*; import java.text.*; @@ -43,9 +43,12 @@ class AltosFlightStatusTableModel extends AbstractTableModel { private Object[] data = { 0, "idle", 0, 0 }; public int getColumnCount() { return columnNames.length; } - public int getRowCount() { return 1; } - public String getColumnName(int col) { return columnNames[col]; } - public Object getValueAt(int row, int col) { return data[col]; } + public int getRowCount() { return 2; } + public Object getValueAt(int row, int col) { + if (row == 0) + return columnNames[col]; + return data[col]; + } public void setValueAt(Object value, int col) { data[col] = value; @@ -67,6 +70,26 @@ class AltosFlightStatusTableModel extends AbstractTableModel { } } +class AltosFlightStatusCellRenderer extends DefaultTableCellRenderer { + + static Font statusFont = new Font("SansSerif", Font.BOLD, 24); + + @Override public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, + boolean hasFocus, int row, int column) + { + Component cell = super.getTableCellRendererComponent + (table, value, isSelected, hasFocus, row, column); + System.out.println("Selecting new font for cell " + row + " " + column + " " + statusFont); + cell.setFont(statusFont); + return cell; + } + + public AltosFlightStatusCellRenderer () { + super(); + System.out.println("Made a status cell renderer\n"); + } +} + class AltosFlightInfoTableModel extends AbstractTableModel { private String[] columnNames = {"Field", "Value"}; @@ -133,6 +156,10 @@ public class AltosUI extends JFrame { private Box vbox; private Box hbox; + private Font statusFont = new Font("SansSerif", Font.BOLD, 24); + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + public AltosUI() { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; @@ -143,23 +170,37 @@ public class AltosUI extends JFrame { flightStatusModel = new AltosFlightStatusTableModel(); flightStatus = new JTable(flightStatusModel); + flightStatus.setFont(statusFont); + TableColumnModel tcm = flightStatus.getColumnModel(); + for (int i = 0; i < flightStatusModel.getColumnCount(); i++) { + DefaultTableCellRenderer r = new DefaultTableCellRenderer(); + r.setFont(statusFont); + r.setHorizontalAlignment(SwingConstants.CENTER); + tcm.getColumn(i).setCellRenderer(r); + } + FontMetrics statusMetrics = flightStatus.getFontMetrics(statusFont); + int statusHeight = (statusMetrics.getHeight() + statusMetrics.getLeading()) * 15 / 10; + flightStatus.setRowHeight(statusHeight); flightStatus.setShowGrid(false); - flightInfo = new JTable[3]; - flightInfoModel = new AltosFlightInfoTableModel[3]; - ibox = new Box[3]; - - vbox.add(flightStatus.getTableHeader()); vbox.add(flightStatus); hbox = Box.createHorizontalBox(); vbox.add(hbox); + flightInfo = new JTable[3]; + flightInfoModel = new AltosFlightInfoTableModel[3]; + ibox = new Box[3]; + FontMetrics infoValueMetrics = flightStatus.getFontMetrics(infoValueFont); + int infoHeight = (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 20 / 10; + for (int i = 0; i < info_columns; i++) { ibox[i] = Box.createVerticalBox(); flightInfoModel[i] = new AltosFlightInfoTableModel(); flightInfo[i] = new JTable(flightInfoModel[i]); + flightInfo[i].setFont(infoValueFont); + flightInfo[i].setRowHeight(infoHeight); flightInfo[i].setShowGrid(true); ibox[i].add(flightInfo[i].getTableHeader()); ibox[i].add(flightInfo[i]); @@ -173,7 +214,8 @@ public class AltosUI extends JFrame { serialLine = new AltosSerial(); serialLine.monitor(new AltosUIMonitor()); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - this.setSize(new Dimension (dpi * 5, dpi * 4)); + this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 15, + statusHeight * 4 + infoHeight * 17)); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -235,25 +277,25 @@ public class AltosUI extends JFrame { MIN_PAD_SAMPLES - state.npad); 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", "%d", state.data.serial); - info_add_row(0, "Rocket flight", "%d", state.data.flight); - - info_add_row(0, "RSSI", "%6ddBm", state.data.rssi); - info_add_row(0, "Height", "%6.0fm", state.height); - info_add_row(0, "Max height", "%6.0fm", state.max_height); - info_add_row(0, "Acceleration", "%7.1fm/s²", state.acceleration); - info_add_row(0, "Max acceleration", "%7.1fm/s²", state.max_acceleration); - info_add_row(0, "Speed", "%7.1fm/s", state.ascent ? state.speed : state.baro_speed); - info_add_row(0, "Max Speed", "%7.1fm/s", state.max_speed); - info_add_row(0, "Temperature", "%6.2f°C", state.temperature); - info_add_row(0, "Battery", "%5.2fV", state.battery); - info_add_row(0, "Drogue", "%5.2fV", state.drogue_sense); - info_add_row(0, "Main", "%5.2fV", state.main_sense); - info_add_row(0, "Pad altitude", "%6.0fm", state.ground_altitude); + 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, "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); + info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); + info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); + info_add_row(0, "Temperature", "%9.2f °C", state.temperature); + info_add_row(0, "Battery", "%9.2f V", state.battery); + info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); + info_add_row(0, "Main", "%9.2f V", state.main_sense); + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); if (state.gps != null) - info_add_row(1, "Satellites", "%d", state.gps.nsat); + info_add_row(1, "Satellites", "%6d", state.gps.nsat); else - info_add_row(1, "Satellites", "%d", 0); + info_add_row(1, "Satellites", "%6d", 0); if (state.gps != null && state.gps.gps_locked) { info_add_row(1, "GPS", "locked"); } else if (state.gps != null && state.gps.gps_connected) { -- cgit v1.2.3 From 6d523ee4dad3b9890d3cf05852459101fe7e26ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 21:48:41 -0700 Subject: Fix status update --- ao-tools/altosui/AltosUI.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 7befe778..66c75487 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -52,7 +52,7 @@ class AltosFlightStatusTableModel extends AbstractTableModel { public void setValueAt(Object value, int col) { data[col] = value; - fireTableCellUpdated(0, col); + fireTableCellUpdated(1, col); } public void setValueAt(Object value, int row, int col) { @@ -273,7 +273,7 @@ public class AltosUI extends JFrame { if (state.npad >= MIN_PAD_SAMPLES) info_add_row(0, "Ground state", "%s", "ready"); else - info_add_row(0, "Ground state", "waiting for gps (%d)", + info_add_row(0, "Ground state", "wait (%d)", MIN_PAD_SAMPLES - state.npad); info_add_row(0, "Rocket state", "%s", state.data.state); info_add_row(0, "Callsign", "%s", state.data.callsign); -- cgit v1.2.3 From 9cc48698ec14c34d437baad7b6540edc31e9741c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 22:47:40 -0700 Subject: Fix state updates --- ao-tools/altosui/AltosGPS.java | 1 + ao-tools/altosui/AltosState.java | 86 ++++++++++++++++++++---------------- ao-tools/altosui/AltosTelemetry.java | 1 + ao-tools/altosui/AltosUI.java | 50 +++++++++++---------- 4 files changed, 76 insertions(+), 62 deletions(-) diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index d242ad57..92a17018 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -111,6 +111,7 @@ public class AltosGPS { int tracking_channels = AltosParse.parse_int(words[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++]); } diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index b3054ce9..aacddfdf 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -26,17 +26,17 @@ import altosui.AltosGPS; public class AltosState { AltosTelemetry data; - AltosTelemetry prev_data; /* derived data */ double report_time; + double time_change; + int tick; + int state; boolean ascent; /* going up? */ - double time_change; - double ground_altitude; double height; double speed; @@ -56,9 +56,6 @@ public class AltosState { double pad_lat; double pad_lon; double pad_alt; - double pad_lat_total; - double pad_lon_total; - double pad_alt_total; int npad; int prev_npad; @@ -75,29 +72,18 @@ public class AltosState { return System.currentTimeMillis() / 1000.0; } - void init (AltosTelemetry cur, AltosTelemetry prev, int prev_npad) { - int i; - double new_height; - double height_change; + void init (AltosTelemetry cur, AltosState prev_state) { + int i; + AltosTelemetry prev; double accel_counts_per_mss; - int tick_count; data = cur; - prev_data = prev; - npad = prev_npad; - tick_count = data.tick; - if (tick_count < prev_data.tick) - tick_count += 65536; - time_change = (tick_count - prev_data.tick) / 100.0; + + ground_altitude = AltosConvert.cc_barometer_to_altitude(data.ground_pres); + height = AltosConvert.cc_barometer_to_altitude(data.flight_pres) - ground_altitude; report_time = aoview_time(); - ground_altitude = AltosConvert.cc_pressure_to_altitude(data.ground_pres); - new_height = AltosConvert.cc_pressure_to_altitude(data.flight_pres) - ground_altitude; - height_change = new_height - height; - height = new_height; - if (time_change > 0) - baro_speed = (baro_speed * 3 + (height_change / time_change)) / 4.0; accel_counts_per_mss = ((data.accel_minus_g - data.accel_plus_g) / 2.0) / 9.80665; acceleration = (data.ground_accel - data.flight_accel) / accel_counts_per_mss; speed = data.flight_vel / (accel_counts_per_mss * 100.0); @@ -105,17 +91,46 @@ public class AltosState { drogue_sense = AltosConvert.cc_ignitor_to_voltage(data.drogue); main_sense = AltosConvert.cc_ignitor_to_voltage(data.main); battery = AltosConvert.cc_battery_to_voltage(data.batt); + tick = data.tick; state = data.state(); + + if (prev_state != null) { + + /* Preserve any existing gps data */ + npad = prev_state.npad; + gps = prev_state.gps; + pad_lat = prev_state.pad_lat; + pad_lon = prev_state.pad_lon; + pad_alt = prev_state.pad_alt; + + /* make sure the clock is monotonic */ + while (tick < prev_state.tick) + tick += 65536; + + time_change = (tick - prev_state.tick) / 100.0; + + /* compute barometric speed */ + + double height_change = height - prev_state.height; + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } else { + npad = 0; + gps = null; + baro_speed = 0; + time_change = 0; + } + if (state == AltosTelemetry.ao_flight_pad) { if (data.gps != null && data.gps.gps_locked && data.gps.nsat >= 4) { npad++; - pad_lat_total += data.gps.lat; - pad_lon_total += data.gps.lon; - pad_alt_total += data.gps.alt; if (npad > 1) { - pad_lat = (pad_lat * 31 + data.gps.lat) / 32.0; - pad_lon = (pad_lon * 31 + data.gps.lon) / 32.0; - pad_alt = (pad_alt * 31 + data.gps.alt) / 32.0; + /* filter pad position */ + pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; + pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; + pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; } else { pad_lat = data.gps.lat; pad_lon = data.gps.lon; @@ -135,7 +150,8 @@ public class AltosState { if (height > max_height) max_height = height; if (data.gps != null) { - gps = data.gps; + if (gps == null || !gps.gps_locked || data.gps.gps_locked) + gps = data.gps; if (npad > 0 && gps.gps_locked) from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); } @@ -147,16 +163,10 @@ public class AltosState { } public AltosState(AltosTelemetry cur) { - init(cur, cur, 0); + init(cur, null); } public AltosState (AltosTelemetry cur, AltosState prev) { - if (prev == null) - init(cur, cur, 0); - else { - init(cur, prev.data, prev.npad); - if (gps == null) - gps = prev.gps; - } + init(cur, prev); } } diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index 34b4099f..e13b42e2 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -181,5 +181,6 @@ public class AltosTelemetry { AltosParse.word(words[i++], "a-:"); accel_minus_g = AltosParse.parse_int(words[i++]); + gps = new AltosGPS(words, i); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 66c75487..1c6fd699 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -214,7 +214,7 @@ public class AltosUI extends JFrame { serialLine = new AltosSerial(); serialLine.monitor(new AltosUIMonitor()); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 15, + this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 20, statusHeight * 4 + infoHeight * 17)); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); @@ -292,22 +292,20 @@ public class AltosUI extends JFrame { info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); info_add_row(0, "Main", "%9.2f V", state.main_sense); info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); - if (state.gps != null) - info_add_row(1, "Satellites", "%6d", state.gps.nsat); - else - info_add_row(1, "Satellites", "%6d", 0); - if (state.gps != null && state.gps.gps_locked) { - info_add_row(1, "GPS", "locked"); - } else if (state.gps != null && state.gps.gps_connected) { - info_add_row(1, "GPS", "unlocked"); - } else { + if (state.gps == null) { info_add_row(1, "GPS", "not available"); - } - if (state.gps != null) { + } else { + if (state.gps.gps_locked) + info_add_row(1, "GPS", "locked"); + else if (state.gps.gps_connected) + info_add_row(1, "GPS", "unlocked"); + else + info_add_row(1, "GPS", "missing"); + info_add_row(1, "Satellites", "%6d", state.gps.nsat); info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); info_add_row(1, "GPS altitude", "%d", state.gps.alt); - info_add_row(1, "GPS height", "%d", state.gps_height); + info_add_row(1, "GPS height", "%6.0f", state.gps_height); info_add_row(1, "GPS date", "%04d-%02d-%02d", state.gps.gps_time.year, state.gps.gps_time.month, @@ -321,17 +319,21 @@ public class AltosUI extends JFrame { state.gps.course); info_add_row(1, "GPS climb rate", "%7.1fm/s", state.gps.climb_rate); - info_add_row(1, "GPS precision", "%4.1f(hdop) %3dm(h) %3dm(v)", - state.gps.hdop, state.gps.h_error, state.gps.v_error); - } - if (state.npad > 0) { - info_add_row(1, "Distance from pad", "%5.0fm", state.from_pad.distance); - info_add_row(1, "Direction from pad", "%4.0f°", state.from_pad.bearing); - info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); - info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); - info_add_row(1, "Pad GPS alt", "%gm", state.pad_alt); - } - if (state.gps != null && state.gps.gps_connected) { + info_add_row(1, "GPS hdop", "%4.1f", state.gps.hdop); + info_add_row(1, "GPS error", "%3dm(h) %3dm(v)", + state.gps.h_error, state.gps.v_error); + if (state.npad > 0) { + if (state.from_pad != null) { + info_add_row(1, "Distance from pad", "%5.0fm", state.from_pad.distance); + info_add_row(1, "Direction from pad", "%4.0f°", state.from_pad.bearing); + } else { + info_add_row(1, "Distance from pad", "unknown"); + info_add_row(1, "Direction 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'); + info_add_row(1, "Pad GPS alt", "%gm", state.pad_alt); + } int nsat_vis = 0; int c; -- cgit v1.2.3 From 3f9b66b307ee88172151e3bee58e50f5acbde109 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 23:00:30 -0700 Subject: Clean up GPS data formatting --- ao-tools/altosui/AltosUI.java | 48 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 1c6fd699..599c5aec 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -295,55 +295,55 @@ public class AltosUI extends JFrame { if (state.gps == null) { info_add_row(1, "GPS", "not available"); } else { - if (state.gps.gps_locked) - info_add_row(1, "GPS", "locked"); - else if (state.gps.gps_connected) - info_add_row(1, "GPS", "unlocked"); + if (state.data.gps.gps_locked) + info_add_row(1, "GPS", " locked"); + else if (state.data.gps.gps_connected) + info_add_row(1, "GPS", " unlocked"); else - info_add_row(1, "GPS", "missing"); + info_add_row(1, "GPS", " missing"); info_add_row(1, "Satellites", "%6d", state.gps.nsat); info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - info_add_row(1, "GPS altitude", "%d", state.gps.alt); + info_add_row(1, "GPS altitude", "%6d", state.gps.alt); info_add_row(1, "GPS height", "%6.0f", state.gps_height); - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.gps_time.year, - state.gps.gps_time.month, - state.gps.gps_time.day); - info_add_row(1, "GPS time", "%02d:%02d:%02d", - state.gps.gps_time.hour, - state.gps.gps_time.minute, - state.gps.gps_time.second); - info_add_row(1, "GPS ground speed", "%7.1fm/s %d°", + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", state.gps.ground_speed, state.gps.course); - info_add_row(1, "GPS climb rate", "%7.1fm/s", + info_add_row(1, "GPS climb rate", "%8.1f m/s", state.gps.climb_rate); - info_add_row(1, "GPS hdop", "%4.1f", state.gps.hdop); - info_add_row(1, "GPS error", "%3dm(h) %3dm(v)", + info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", state.gps.h_error, state.gps.v_error); if (state.npad > 0) { if (state.from_pad != null) { - info_add_row(1, "Distance from pad", "%5.0fm", state.from_pad.distance); - info_add_row(1, "Direction from pad", "%4.0f°", state.from_pad.bearing); + 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); } else { info_add_row(1, "Distance from pad", "unknown"); info_add_row(1, "Direction 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'); - info_add_row(1, "Pad GPS alt", "%gm", state.pad_alt); + info_add_row(1, "Pad GPS alt", "%9.2fm", state.pad_alt); } + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.gps_time.year, + state.gps.gps_time.month, + state.gps.gps_time.day); + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.gps_time.hour, + state.gps.gps_time.minute, + state.gps.gps_time.second); int nsat_vis = 0; int c; if (state.gps.cc_gps_sat == null) - info_add_row(2, "Satellites Visible", "%d", 0); + info_add_row(2, "Satellites Visible", "%4d", 0); else { - info_add_row(2, "Satellites Visible", "%d", state.gps.cc_gps_sat.length); + info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); for (c = 0; c < state.gps.cc_gps_sat.length; c++) { info_add_row(2, "Satellite id,C/N0", - "%3d,%2d", + "%4d, %4d", state.gps.cc_gps_sat[c].svid, state.gps.cc_gps_sat[c].c_n0); } -- cgit v1.2.3 From ebd49d4ec6b0b60c85b2de45cfe2e36add8fe9bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 23:05:40 -0700 Subject: Report current gps nsat, not last locked nsat --- ao-tools/altosui/AltosUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 599c5aec..2cf326fc 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -301,7 +301,7 @@ public class AltosUI extends JFrame { info_add_row(1, "GPS", " unlocked"); else info_add_row(1, "GPS", " missing"); - info_add_row(1, "Satellites", "%6d", state.gps.nsat); + info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); info_add_row(1, "GPS altitude", "%6d", state.gps.alt); -- cgit v1.2.3 From 4ad062969ae8a608b8428620579bbe114e580a11 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 23:20:38 -0700 Subject: Remove GPS data missing from skytraq. Save max height/accel/speed --- ao-tools/altosui/AltosState.java | 3 +++ ao-tools/altosui/AltosUI.java | 21 +++++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index aacddfdf..192011d0 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -102,6 +102,9 @@ public class AltosState { pad_lat = prev_state.pad_lat; pad_lon = prev_state.pad_lon; pad_alt = prev_state.pad_alt; + max_height = prev_state.max_height; + max_acceleration = prev_state.max_acceleration; + max_speed = prev_state.max_speed; /* make sure the clock is monotonic */ while (tick < prev_state.tick) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 2cf326fc..91278afe 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -306,14 +306,19 @@ public class AltosUI extends JFrame { info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); info_add_row(1, "GPS altitude", "%6d", state.gps.alt); info_add_row(1, "GPS height", "%6.0f", state.gps_height); - info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", - state.gps.ground_speed, - state.gps.course); - info_add_row(1, "GPS climb rate", "%8.1f m/s", - state.gps.climb_rate); + + /* The SkyTraq GPS doesn't report these values */ + if (false) { + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%8.1f m/s", + state.gps.climb_rate); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", + state.gps.h_error, state.gps.v_error); + } info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); - info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", - state.gps.h_error, state.gps.v_error); + if (state.npad > 0) { if (state.from_pad != null) { info_add_row(1, "Distance from pad", "%6.0f m", state.from_pad.distance); @@ -324,7 +329,7 @@ public class AltosUI extends JFrame { } info_add_deg(1, "Pad latitude", state.pad_lat, 'N', 'S'); info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); - info_add_row(1, "Pad GPS alt", "%9.2fm", state.pad_alt); + info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); } info_add_row(1, "GPS date", "%04d-%02d-%02d", state.gps.gps_time.year, -- cgit v1.2.3 From 4bea4c327e002ce8f88218f0d840af7c1521bc35 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 2 Apr 2010 23:25:02 -0700 Subject: Remove unused cell renderer class --- ao-tools/altosui/AltosUI.java | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 91278afe..8880618b 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -70,26 +70,6 @@ class AltosFlightStatusTableModel extends AbstractTableModel { } } -class AltosFlightStatusCellRenderer extends DefaultTableCellRenderer { - - static Font statusFont = new Font("SansSerif", Font.BOLD, 24); - - @Override public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, - boolean hasFocus, int row, int column) - { - Component cell = super.getTableCellRendererComponent - (table, value, isSelected, hasFocus, row, column); - System.out.println("Selecting new font for cell " + row + " " + column + " " + statusFont); - cell.setFont(statusFont); - return cell; - } - - public AltosFlightStatusCellRenderer () { - super(); - System.out.println("Made a status cell renderer\n"); - } -} - class AltosFlightInfoTableModel extends AbstractTableModel { private String[] columnNames = {"Field", "Value"}; @@ -437,8 +417,11 @@ public class AltosUI extends JFrame { filename = name; } + /* Run the replay in a separate thread + * so that the UI can update + */ public void run() { - String line; + String line; AltosState state = null; try { while ((line = readline(replay)) != null) { @@ -446,6 +429,8 @@ public class AltosUI extends JFrame { AltosTelemetry t = new AltosTelemetry(line); state = new AltosState(t, state); show(state); + + /* Make it run in realtime after the rocket leaves the pad */ try { if (state.state > AltosTelemetry.ao_flight_pad) Thread.sleep((int) (state.time_change * 1000)); -- cgit v1.2.3 From 3d34c488c5b71020d86f83156fd821fd860bf214 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 3 Apr 2010 00:02:44 -0700 Subject: Make .jar file --- ao-tools/altosui/Makefile | 13 ++++++++++--- ao-tools/altosui/Manifest.txt | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 ao-tools/altosui/Manifest.txt diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 1fb964d6..74b29f7f 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -10,11 +10,15 @@ CLASSFILES=\ AltosSerial.class \ AltosState.class \ AltosTelemetry.class \ - AltosUI.class + AltosUI.class \ + AltosDevice.class \ + AltosDeviceName.class \ + AltosDeviceLinux.class \ + AltosDeviceNameLinux.class JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) altosui +all: $(CLASSFILES) altosui altosui.jar .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java @@ -24,5 +28,8 @@ altosui: Makefile echo exec java -cp '"$(CLASSPATH)"' altosui/AltosUI) > $@ chmod +x $@ +altosui.jar: $(CLASSFILES) Manifest.txt + cd .. && jar cfm altosui/$@ altosui/Manifest.txt altosui/*.class + clean: - rm -f *.class \ No newline at end of file + rm -f *.class diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt new file mode 100644 index 00000000..0305fcfb --- /dev/null +++ b/ao-tools/altosui/Manifest.txt @@ -0,0 +1 @@ +Main-Class: altosui.AltosUI -- cgit v1.2.3 From c66eebad323e4572bb7cc23bc476ee144f03e9b8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 3 Apr 2010 08:02:44 -0600 Subject: rewrite urls in docbook format --- doc/telemetrum.xsl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index fb65ce01..f1525887 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -125,7 +125,10 @@ doesn't get you close enough because the rocket dropped into a canyon, or the wind is blowing it across a dry lake bed, or something like that... Keith and Bdale both currently own and use the - [Yaesu VX-6R](http://yaesu.com/indexVS.cfm?cmd=DisplayProducts&ProdCatID=111&encProdID=4C6F204F6FEBB5BAFA58BCC1C131EAC0&DivisionID=65&isArchived=0) + + Yaesu VX-6R + at launches. @@ -151,9 +154,11 @@ The best hand-held commercial directional antennas we've found for radio direction finding rockets are from - [Arrow Antennas](http://www.arrowantennas.com/). The 440-3 and 440-5 are - both good choices for finding a TeleMetrum-equipped rocket when used with - a suitable 70cm HT. + + Arrow Antennas. + +The 440-3 and 440-5 are both good choices for finding a +TeleMetrum-equipped rocket when used with a suitable 70cm HT.
-- cgit v1.2.3 From 0e7abc9fedec568b431c983d3df1b0b29f4f10e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 16:32:04 -0700 Subject: Use RXTX for serial comm. Add logdir preference saving --- ao-tools/altosui/AltosSerial.java | 34 ++++++++--- ao-tools/altosui/AltosUI.java | 124 ++++++++++++++++++++++++++++++-------- 2 files changed, 126 insertions(+), 32 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 9537f190..305222dc 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -26,6 +26,7 @@ import java.io.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.LinkedList; import java.util.Iterator; +import gnu.io.*; import altosui.AltosSerialMonitor; /* @@ -34,7 +35,7 @@ import altosui.AltosSerialMonitor; * threads. */ class AltosSerialReader implements Runnable { - FileInputStream serial_in; + InputStream serial_in; LinkedBlockingQueue monitor_queue; LinkedBlockingQueue reply_queue; Thread input_thread; @@ -109,6 +110,12 @@ class AltosSerialReader implements Runnable { input_thread = new Thread(this); input_thread.start(); } + public void open(CommPort c) throws IOException { + close(); + serial_in = c.getInputStream(); + input_thread = new Thread(this); + input_thread.start(); + } public AltosSerialReader () { serial_in = null; input_thread = null; @@ -120,7 +127,7 @@ class AltosSerialReader implements Runnable { } public class AltosSerial implements Runnable { - FileOutputStream serial_out = null; + OutputStream serial_out = null; Thread monitor_thread = null; AltosSerialReader reader = null; LinkedList callbacks; @@ -188,11 +195,19 @@ public class AltosSerial implements Runnable { public void open(File serial_name) throws FileNotFoundException { reader.open(serial_name); serial_out = new FileOutputStream(serial_name); - try { - serial_out.write('?'); - serial_out.write('\r'); - } catch (IOException e) { - } + } + + public void open(CommPort comm_port) throws IOException { + reader.open(comm_port); + serial_out = comm_port.getOutputStream(); + } + + public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException { + System.out.printf("Opening serial port %s\n", port_name); + CommPort comm_port = new RXTXPort(port_name); +// CommPortIdentifier port_identifier = CommPortIdentifier.getPortIdentifier(port_name); +// CommPort comm_port = port_identifier.open("Altos", 1000); + open(comm_port); } void init() { @@ -208,4 +223,9 @@ public class AltosSerial implements Runnable { init(); open(serial_name); } + + public AltosSerial(CommPort comm_port) throws IOException { + init(); + open(comm_port); + } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 8880618b..ab5f1828 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -25,7 +25,8 @@ import javax.swing.table.*; import java.io.*; import java.util.*; import java.text.*; -import gnu.io.CommPortIdentifier; +import java.util.prefs.*; +import gnu.io.*; import altosui.AltosSerial; import altosui.AltosSerialMonitor; @@ -337,32 +338,63 @@ public class AltosUI extends JFrame { info_finish(); } + /* User Preferences */ + Preferences altosui_preferences = Preferences.userNodeForPackage(this.getClass()); - final JFileChooser deviceChooser = new JFileChooser(); - final JFileChooser logdirChooser = new JFileChooser(); - final String logdirName = "TeleMetrum"; - File logdir = null; + /* Log directory */ + private File logdir = null; - private void setLogdir() { - if (logdir == null) - logdir = new File(logdirChooser.getCurrentDirectory(), logdirName); - logdirChooser.setCurrentDirectory(logdir); + /* logdir preference name */ + final static String logdirPreference = "LOGDIR"; + + /* Default logdir is ~/TeleMetrum */ + final static String logdirName = "TeleMetrum"; + + /* Initialize logdir from preferences */ + { + String logdir_string = altosui_preferences.get(logdirPreference, null); + if (logdir_string != null) + logdir = new File(logdir_string); + else + /* a hack -- make the file chooser tell us what the default directory + * would be and stick our logdir in a subdirectory of that. + */ + logdir = new File(new JFileChooser().getCurrentDirectory(), logdirName); + } + + private void set_logdir(File new_logdir) { + logdir = new_logdir; + System.out.printf("Set logdir to %s\n", logdir.toString()); + synchronized (altosui_preferences) { + altosui_preferences.put(logdirPreference, logdir.getPath()); + try { + altosui_preferences.flush(); + } catch (BackingStoreException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + altosui_preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + } + } } - private void makeLogdir() { - setLogdir(); - if (!logdir.exists()) { - if (!logdir.mkdirs()) + private boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { JOptionPane.showMessageDialog(AltosUI.this, - logdir.getName(), + dir.getName(), "Cannot create directory", JOptionPane.ERROR_MESSAGE); - } else if (!logdir.isDirectory()) { + return false; + } + } else if (!dir.isDirectory()) { JOptionPane.showMessageDialog(AltosUI.this, - logdir.getName(), + dir.getName(), "Is not a directory", JOptionPane.ERROR_MESSAGE); + return false; } + return true; } private void PickSerialDevice() { @@ -374,18 +406,33 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - PickSerialDevice(); - int returnVal = deviceChooser.showOpenDialog(AltosUI.this); + JFileChooser device_chooser = new JFileChooser(); + int returnVal = device_chooser.showOpenDialog(AltosUI.this); if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = deviceChooser.getSelectedFile(); + File file = device_chooser.getSelectedFile(); try { - serialLine.open(file); + serialLine.connect(file.getCanonicalPath()); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, file.getName(), "Cannot open serial port", JOptionPane.ERROR_MESSAGE); + } catch (NoSuchPortException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + file.getName(), + "No such serial port", + JOptionPane.ERROR_MESSAGE); + } catch (PortInUseException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + file.getName(), + "Port in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + file.getName(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); } } } @@ -456,14 +503,19 @@ public class AltosUI extends JFrame { } } + /* + * Replay a flight from telemetry data + */ private void Replay() { - setLogdir(); - logdirChooser.setDialogTitle("Select Telemetry File"); - logdirChooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); - int returnVal = logdirChooser.showOpenDialog(AltosUI.this); + JFileChooser logfile_chooser = new JFileChooser(); + + logfile_chooser.setDialogTitle("Select Telemetry File"); + logfile_chooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); + logfile_chooser.setCurrentDirectory(logdir); + int returnVal = logfile_chooser.showOpenDialog(AltosUI.this); if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = logdirChooser.getSelectedFile(); + File file = logfile_chooser.getSelectedFile(); if (file == null) System.out.println("No file selected?"); String filename = file.getName(); @@ -480,9 +532,30 @@ public class AltosUI extends JFrame { } } + /* + * Connect to TeleMetrum, either directly or through + * a TeleDongle over the packet link + */ private void SaveFlightData() { } + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + private void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setCurrentDirectory(logdir.getParentFile()); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(AltosUI.this, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + private void createMenu() { JMenuBar menubar = new JMenuBar(); JMenu menu; @@ -562,6 +635,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Configure Log",KeyEvent.VK_C); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + ConfigureLog(); } }); menu.add(item); -- cgit v1.2.3 From b0b99f30c4e00689e9faceb363a5c7284541c6be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 19:48:50 -0700 Subject: Make ao_radio_idle keep trying to get the radio to idle. Attempting to abort a radio operation could lead to a hang if the user of the radio jumped in and started using it again before the task attempting to abort woke up. This change just keeps smacking the radio until the radio goes idle long enough to detect it. --- src/ao_radio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index bb19c6a9..0849349e 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -317,8 +317,8 @@ ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) { - RFST = RFST_SIDLE; do { + RFST = RFST_SIDLE; ao_yield(); } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); } -- cgit v1.2.3 From 6251e89c6eea655769f77bc18e98e79c99cf3cad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 19:54:46 -0700 Subject: Don't abort the radio when enabling telemetry monitoring If telemetry monitoring is already on, then there isn't any point, and if it's not on, then presumably there isn't any radio work to abort. Signed-off-by: Keith Packard --- src/ao_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 628b6e67..f2f3fc2e 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -80,7 +80,8 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - ao_radio_abort(); + if (!ao_monitoring) + ao_radio_abort(); } static void -- cgit v1.2.3 From d22ba55ae0e056530a727df50f14ad853d79a2c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 20:55:18 -0700 Subject: Clean up some altosui comments --- ao-tools/altosui/AltosUI.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index ab5f1828..a51ca1eb 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -532,8 +532,7 @@ public class AltosUI extends JFrame { } } - /* - * Connect to TeleMetrum, either directly or through + /* Connect to TeleMetrum, either directly or through * a TeleDongle over the packet link */ private void SaveFlightData() { @@ -556,6 +555,8 @@ public class AltosUI extends JFrame { } } + /* Create the AltosUI menus + */ private void createMenu() { JMenuBar menubar = new JMenuBar(); JMenu menu; -- cgit v1.2.3 From c28646d72005daeadb70b95fd3b0050bd752cc55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 20:55:30 -0700 Subject: Switch TeleMetrum from v0.2 to v1.0 Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_pins.h | 2 +- src/telemetrum-v0.2/.gitignore | 2 -- src/telemetrum-v0.2/Makefile | 1 - src/telemetrum-v0.2/Makefile.defs | 10 ---------- src/telemetrum-v1.0/.gitignore | 2 ++ src/telemetrum-v1.0/Makefile | 1 + src/telemetrum-v1.0/Makefile.defs | 10 ++++++++++ 8 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 src/telemetrum-v0.2/.gitignore delete mode 100644 src/telemetrum-v0.2/Makefile delete mode 100644 src/telemetrum-v0.2/Makefile.defs create mode 100644 src/telemetrum-v1.0/.gitignore create mode 100644 src/telemetrum-v1.0/Makefile create mode 100644 src/telemetrum-v1.0/Makefile.defs diff --git a/src/Makefile b/src/Makefile index e2699ee6..24f562e1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ # CC=sdcc -SUBDIRS=telemetrum-v0.2 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test all: all-recursive diff --git a/src/ao_pins.h b/src/ao_pins.h index 771d9c7f..e9a265b0 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -18,7 +18,7 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#if defined(TELEMETRUM_V_0_2) +#if defined(TELEMETRUM_V_1_0) #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 diff --git a/src/telemetrum-v0.2/.gitignore b/src/telemetrum-v0.2/.gitignore deleted file mode 100644 index 76228093..00000000 --- a/src/telemetrum-v0.2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -telemetrum-v0.2 -ao_product.h diff --git a/src/telemetrum-v0.2/Makefile b/src/telemetrum-v0.2/Makefile deleted file mode 100644 index d8867b19..00000000 --- a/src/telemetrum-v0.2/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.proto diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs deleted file mode 100644 index eb11e7dc..00000000 --- a/src/telemetrum-v0.2/Makefile.defs +++ /dev/null @@ -1,10 +0,0 @@ -PROG = telemetrum-v0.2.ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(FLASH_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.2 -PRODUCT_DEF=-DTELEMETRUM_V_0_2 diff --git a/src/telemetrum-v1.0/.gitignore b/src/telemetrum-v1.0/.gitignore new file mode 100644 index 00000000..76228093 --- /dev/null +++ b/src/telemetrum-v1.0/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.2 +ao_product.h diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v1.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs new file mode 100644 index 00000000..e3cc5eb2 --- /dev/null +++ b/src/telemetrum-v1.0/Makefile.defs @@ -0,0 +1,10 @@ +PROG = telemetrum-v1.0.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v1.0 +PRODUCT_DEF=-DTELEMETRUM_V_1_0 -- cgit v1.2.3 From cc600a0389720bc7e435dbda8bec080ef19e0c58 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 Apr 2010 22:21:46 -0700 Subject: Add Linux device discovery AltosDeviceLinux.java scans /proc to locate suitable devices. This will be hooked up to the UI shortly. --- ao-tools/altosui/AltosDevice.java | 30 ++++++ ao-tools/altosui/AltosDeviceLinux.java | 171 +++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 4 + ao-tools/altosui/Makefile | 2 - 4 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 ao-tools/altosui/AltosDevice.java create mode 100644 ao-tools/altosui/AltosDeviceLinux.java diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java new file mode 100644 index 00000000..66800c5c --- /dev/null +++ b/ao-tools/altosui/AltosDevice.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; + +public class AltosDevice { + String tty; /* suitable to be passed to AltosSerial.connect */ + String manufacturer; + String product; + int serial; + int idProduct; + int idVendor; + +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosDeviceLinux.java b/ao-tools/altosui/AltosDeviceLinux.java new file mode 100644 index 00000000..b7774627 --- /dev/null +++ b/ao-tools/altosui/AltosDeviceLinux.java @@ -0,0 +1,171 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; +import altosui.AltosDeviceName; +import altosui.AltosDeviceNameLinux; +import altosui.AltosDevice; + +public class AltosDeviceLinux extends AltosDevice { + + String load_string(File file) { + try { + FileInputStream in = new FileInputStream(file); + String result = ""; + int c; + try { + while ((c = in.read()) != -1) { + if (c == '\n') + break; + result = result + (char) c; + } + return result; + } catch (IOException ee) { + return ""; + } + } catch (FileNotFoundException ee) { + return ""; + } + } + String load_string(File dir, String name) { + return load_string(new File(dir, name)); + } + + int load_hex(File file) { + try { + return Integer.parseInt(load_string(file).trim(), 16); + } catch (NumberFormatException ee) { + return -1; + } + } + + int load_hex(File dir, String name) { + return load_hex(new File(dir, name)); + } + + int load_dec(File file) { + try { + return Integer.parseInt(load_string(file).trim()); + } catch (NumberFormatException ee) { + return -1; + } + } + + int load_dec(File dir, String name) { + return load_dec(new File(dir, name)); + } + + String usb_tty(File sys_dir) { + String base = sys_dir.getName(); + int num_configs = load_hex(sys_dir, "bNumConfigurations"); + int num_inters = load_hex(sys_dir, "bNumInterfaces"); + for (int config = 1; config <= num_configs; config++) { + for (int inter = 0; inter < num_inters; inter++) { + String endpoint_base = String.format("%s:%d.%d", + base, config, inter); + File endpoint_full = new File(sys_dir, endpoint_base); + + File[] namelist; + + /* Check for tty:ttyACMx style names */ + class tty_colon_filter implements FilenameFilter { + public boolean accept(File dir, String name) { + return name.startsWith("tty:"); + } + } + namelist = endpoint_full.listFiles(new tty_colon_filter()); + if (namelist != null && namelist.length > 0) + return new File ("/dev", namelist[0].getName().substring(4)).getPath(); + + /* Check for tty/ttyACMx style names */ + class tty_filter implements FilenameFilter { + public boolean accept(File dir, String name) { + return name.startsWith("tty"); + } + } + File tty_dir = new File(endpoint_full, "tty"); + namelist = tty_dir.listFiles(new tty_filter()); + if (namelist != null && namelist.length > 0) + return new File ("/dev", namelist[0].getName()).getPath(); + } + } + return null; + } + + public AltosDeviceLinux (File sys) { + sys = sys; + manufacturer = load_string(sys, "manufacturer"); + product = load_string(sys, "product"); + serial = load_dec(sys, "serial"); + idProduct = load_hex(sys, "idProduct"); + idVendor = load_hex(sys, "idVendor"); + tty = usb_tty(sys); + } + + public String toString() { + return manufacturer + " " + product + " " + serial + " " + idProduct + " " + idVendor + " " + tty; + } + static public AltosDeviceLinux[] list() { + LinkedList devices = new LinkedList(); + + class dev_filter implements FilenameFilter{ + public boolean accept(File dir, String name) { + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (Character.isDigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && i != 1) + continue; + return false; + } + return true; + } + } + + File usb_devices = new File("/sys/bus/usb/devices"); + File[] devs = usb_devices.listFiles(new dev_filter()); + if (devs != null) { + for (int e = 0; e < devs.length; e++) { + AltosDeviceLinux dev = new AltosDeviceLinux(devs[e]); + if (dev.idVendor == 0xfffe && dev.tty != null) { + devices.add(dev); + } + } + } + AltosDeviceLinux[] foo = new AltosDeviceLinux[devices.size()]; + for (int e = 0; e < devices.size(); e++) { + foo[e] = devices.get(e); + System.out.println("Device " + foo[e]); + } + return foo; + } + + static public AltosDeviceLinux[] list(String model) { + AltosDeviceLinux[] devices = list(); + LinkedList subset = new LinkedList(); + for (int i = 0; i < devices.length; i++) { + if (devices[i].product.startsWith(model)) + subset.add(devices[i]); + } + return (AltosDeviceLinux[]) subset.toArray(); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index a51ca1eb..54016ac5 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -682,6 +682,10 @@ public class AltosUI extends JFrame { } public static void main(final String[] args) { + AltosDevice[] devices = AltosDeviceLinux.list(); + for (int i = 0; i < devices.length; i++) + System.out.printf("Model: %s Serial: %d Tty: %s\n", + devices[i].product, devices[i].serial, devices[i].tty); AltosUI altosui = new AltosUI(); altosui.setVisible(true); } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 74b29f7f..fcb259eb 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -12,9 +12,7 @@ CLASSFILES=\ AltosTelemetry.class \ AltosUI.class \ AltosDevice.class \ - AltosDeviceName.class \ AltosDeviceLinux.class \ - AltosDeviceNameLinux.class JAVAFLAGS=-Xlint:unchecked -- cgit v1.2.3 From c099a67d9ea37e731e0eca318102560281ac240f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 Apr 2010 22:42:05 -0700 Subject: Interrupt running replay thread when starting another replay Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 54016ac5..b2305a21 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -481,7 +481,9 @@ public class AltosUI extends JFrame { try { if (state.state > AltosTelemetry.ao_flight_pad) Thread.sleep((int) (state.time_change * 1000)); - } catch (InterruptedException e) {} + } catch (InterruptedException e) { + break; + } } catch (ParseException pp) { JOptionPane.showMessageDialog(AltosUI.this, line, @@ -503,6 +505,7 @@ public class AltosUI extends JFrame { } } + ReplayThread replay_thread; /* * Replay a flight from telemetry data */ @@ -522,7 +525,10 @@ public class AltosUI extends JFrame { try { FileInputStream replay = new FileInputStream(file); ReplayThread thread = new ReplayThread(replay, filename); - thread.start(); + if (thread != null && replay_thread != null && replay_thread.isAlive()) + replay_thread.interrupt(); + replay_thread = thread; + replay_thread.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, -- cgit v1.2.3 From e064d05da87926c19fb665b40fb280fb59328183 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Apr 2010 00:54:52 -0700 Subject: serial port read function cannot be interrupted. poll every 1 second --- ao-tools/altosui/AltosSerial.java | 95 ++++++++++++--------------------------- 1 file changed, 29 insertions(+), 66 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 305222dc..e4cedde2 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -45,7 +45,12 @@ class AltosSerialReader implements Runnable { int c; try { - while ((c = serial_in.read()) != -1) { + for (;;) { + c = serial_in.read(); + if (Thread.interrupted()) + break; + if (c == -1) + continue; if (c == '\r') continue; synchronized(this) { @@ -68,7 +73,9 @@ class AltosSerialReader implements Runnable { } public String get_telem() throws InterruptedException { - return monitor_queue.take(); + String s = monitor_queue.take(); + System.out.println(s); + return s; } public String get_reply() throws InterruptedException { @@ -97,6 +104,7 @@ class AltosSerialReader implements Runnable { } if (input_thread != null) { try { + input_thread.interrupt(); input_thread.join(); } catch (InterruptedException e) { } @@ -112,6 +120,10 @@ class AltosSerialReader implements Runnable { } public void open(CommPort c) throws IOException { close(); + try { + c.enableReceiveTimeout(1000); /* icky. the read method cannot be interrupted */ + } catch (UnsupportedCommOperationException ee) { + } serial_in = c.getInputStream(); input_thread = new Thread(this); input_thread.start(); @@ -126,69 +138,24 @@ class AltosSerialReader implements Runnable { } -public class AltosSerial implements Runnable { +public class AltosSerial { OutputStream serial_out = null; - Thread monitor_thread = null; AltosSerialReader reader = null; - LinkedList callbacks; - - public void run() { - try { - for (;;) { - String s = reader.get_telem(); - synchronized(callbacks) { - Iterator i = callbacks.iterator(); - while (i.hasNext()) { - i.next().data(s); - } - } - } - } catch (InterruptedException e) { - } - } - - boolean need_monitor() { - return reader.opened() && !callbacks.isEmpty(); - } - - void maybe_stop_monitor() { - if (!need_monitor() && monitor_thread != null) { - monitor_thread.interrupt(); - try { - monitor_thread.join(); - } catch (InterruptedException e) { - } finally { - monitor_thread = null; - } - } - } - - void maybe_start_monitor() { - if (need_monitor() && monitor_thread == null) { - monitor_thread = new Thread(this); - monitor_thread.start(); - } - } - public void monitor(AltosSerialMonitor monitor) { - synchronized(callbacks) { - callbacks.add(monitor); - maybe_start_monitor(); - } + public String get_telem() throws InterruptedException { + return reader.get_telem(); } - - public void unmonitor(AltosSerialMonitor monitor) { - synchronized(callbacks) { - callbacks.remove(monitor); - maybe_stop_monitor(); - } - } + CommPort comm_port = null; public void close() { - synchronized(callbacks) { - reader.close(); - maybe_stop_monitor(); + try { + serial_out.close(); + } catch (IOException ee) { + } + reader.close(); + if (comm_port != null) { + comm_port.close(); } } @@ -197,22 +164,18 @@ public class AltosSerial implements Runnable { serial_out = new FileOutputStream(serial_name); } - public void open(CommPort comm_port) throws IOException { - reader.open(comm_port); - serial_out = comm_port.getOutputStream(); + public void open(CommPort c) throws IOException { + reader.open(c); + serial_out = c.getOutputStream(); } public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException { - System.out.printf("Opening serial port %s\n", port_name); - CommPort comm_port = new RXTXPort(port_name); -// CommPortIdentifier port_identifier = CommPortIdentifier.getPortIdentifier(port_name); -// CommPort comm_port = port_identifier.open("Altos", 1000); + comm_port = new RXTXPort(port_name); open(comm_port); } void init() { reader = new AltosSerialReader(); - callbacks = new LinkedList(); } public AltosSerial() { -- cgit v1.2.3 From a7fc7901cd591c93d9d0cffeec2977ebb17554d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Apr 2010 00:55:19 -0700 Subject: TD reports "not-connected" when GPS has 0 sats --- ao-tools/altosui/AltosGPS.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index 92a17018..c3b368e2 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -108,7 +108,12 @@ public class AltosGPS { gps_time = new AltosGPSTime(); } AltosParse.word(words[i++], "SAT"); - int tracking_channels = AltosParse.parse_int(words[i++]); + 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(); -- cgit v1.2.3 From 9e10e43eff9de3f034da49c4f88728fb933f5035 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Apr 2010 00:56:57 -0700 Subject: Tasks may move in task structure as a result of ao_exit Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_task.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index aefefa46..97cb75ae 100644 --- a/src/ao.h +++ b/src/ao.h @@ -43,7 +43,7 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ uint8_t stack_count; /* amount of saved stack */ - uint8_t task_id; /* index in the task array */ + uint8_t task_id; /* unique id */ __code char *name; /* task name */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; diff --git a/src/ao_task.c b/src/ao_task.c index 4a78766e..72c9d7d6 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -28,10 +28,19 @@ void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } ao_tasks[ao_num_tasks++] = task; - task->task_id = ao_num_tasks; + task->task_id = task_id; task->name = name; /* * Construct a stack frame so that it will 'return' -- cgit v1.2.3 From 10330d23518c94a8b791193a97a6cc07b1c9a97c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Apr 2010 00:58:00 -0700 Subject: Enable telemetry monitoring Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDeviceDialog.java | 45 +++++++++ ao-tools/altosui/AltosDeviceLinux.java | 23 ++--- ao-tools/altosui/AltosUI.java | 157 ++++++++++++++++++++------------ ao-tools/altosui/Makefile | 1 + 4 files changed, 157 insertions(+), 69 deletions(-) create mode 100644 ao-tools/altosui/AltosDeviceDialog.java diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java new file mode 100644 index 00000000..cb1eef8b --- /dev/null +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import javax.swing.*; +import altosui.AltosDevice; +import altosui.AltosDeviceLinux; + +public class AltosDeviceDialog { + + static AltosDevice show (JFrame frame, String product) { + AltosDevice[] devices = null; + if (System.getProperty("os.name").startsWith("Linux")) + devices = AltosDeviceLinux.list(product); + if (devices != null & devices.length > 0) { + Object o = JOptionPane.showInputDialog(frame, + "Select a device", + "Device Selection", + JOptionPane.PLAIN_MESSAGE, + null, + devices, + devices[0]); + return (AltosDevice) o; + } else { + return null; + } + } +} diff --git a/ao-tools/altosui/AltosDeviceLinux.java b/ao-tools/altosui/AltosDeviceLinux.java index b7774627..ffc70aff 100644 --- a/ao-tools/altosui/AltosDeviceLinux.java +++ b/ao-tools/altosui/AltosDeviceLinux.java @@ -19,8 +19,6 @@ package altosui; import java.lang.*; import java.io.*; import java.util.*; -import altosui.AltosDeviceName; -import altosui.AltosDeviceNameLinux; import altosui.AltosDevice; public class AltosDeviceLinux extends AltosDevice { @@ -120,7 +118,7 @@ public class AltosDeviceLinux extends AltosDevice { } public String toString() { - return manufacturer + " " + product + " " + serial + " " + idProduct + " " + idVendor + " " + tty; + return String.format("%-20s %6d %-15s", product, serial, tty == null ? "" : tty); } static public AltosDeviceLinux[] list() { LinkedList devices = new LinkedList(); @@ -152,20 +150,23 @@ public class AltosDeviceLinux extends AltosDevice { } } AltosDeviceLinux[] foo = new AltosDeviceLinux[devices.size()]; - for (int e = 0; e < devices.size(); e++) { + for (int e = 0; e < devices.size(); e++) foo[e] = devices.get(e); - System.out.println("Device " + foo[e]); - } return foo; } static public AltosDeviceLinux[] list(String model) { AltosDeviceLinux[] devices = list(); - LinkedList subset = new LinkedList(); - for (int i = 0; i < devices.length; i++) { - if (devices[i].product.startsWith(model)) - subset.add(devices[i]); + if (model != null) { + LinkedList subset = new LinkedList(); + for (int i = 0; i < devices.length; i++) { + if (devices[i].product.startsWith(model)) + subset.add(devices[i]); + } + devices = new AltosDeviceLinux[subset.size()]; + for (int e = 0; e < subset.size(); e++) + devices[e] = subset.get(e); } - return (AltosDeviceLinux[]) subset.toArray(); + return devices; } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index b2305a21..7f008f3a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -32,12 +32,7 @@ import altosui.AltosSerial; import altosui.AltosSerialMonitor; import altosui.AltosTelemetry; import altosui.AltosState; - -class AltosUIMonitor implements AltosSerialMonitor { - public void data(String data) { - System.out.println(data); - } -} +import altosui.AltosDeviceDialog; class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; @@ -193,7 +188,6 @@ public class AltosUI extends JFrame { createMenu(); serialLine = new AltosSerial(); - serialLine.monitor(new AltosUIMonitor()); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 20, statusHeight * 4 + infoHeight * 17)); @@ -405,38 +399,94 @@ public class AltosUI extends JFrame { } } + class DisplayThread extends Thread { + String read() throws InterruptedException { return null; } + + void close() { } + + void update(AltosState state) throws InterruptedException { } + + public void run() { + String line; + AltosState state = null; + + info_reset(); + info_finish(); + try { + while ((line = read()) != null) { + try { + AltosTelemetry t = new AltosTelemetry(line); + state = new AltosState(t, state); + update(state); + show(state); + } catch (ParseException pp) { + System.out.printf("Parse error on %s\n", line); + System.out.println("exception " + pp); + } + } + } catch (InterruptedException ee) { + } finally { + close(); + } + } + } + + class DeviceThread extends DisplayThread { + AltosSerial serial; + + String read() throws InterruptedException { + System.out.println("Waiting for telemetry"); + String s = serial.get_telem(); + System.out.println("Got telemetry " + s); + return s; + } + + void close() { + serial.close(); + System.out.println("DisplayThread done"); + } + + public DeviceThread(AltosSerial s) { + serial = s; + } + } + private void ConnectToDevice() { - JFileChooser device_chooser = new JFileChooser(); - int returnVal = device_chooser.showOpenDialog(AltosUI.this); + AltosDevice device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = device_chooser.getSelectedFile(); + if (device != null) { try { - serialLine.connect(file.getCanonicalPath()); + serialLine.connect(device.tty); + DeviceThread thread = new DeviceThread(serialLine); + run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - file.getName(), + device.tty, "Cannot open serial port", JOptionPane.ERROR_MESSAGE); } catch (NoSuchPortException ee) { JOptionPane.showMessageDialog(AltosUI.this, - file.getName(), + device.tty, "No such serial port", JOptionPane.ERROR_MESSAGE); } catch (PortInUseException ee) { JOptionPane.showMessageDialog(AltosUI.this, - file.getName(), + device.tty, "Port in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - file.getName(), + device.tty, "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); } } } + void DisconnectFromDevice () { + stop_display(); + } + String readline(FileInputStream s) throws IOException { int c; String line = ""; @@ -455,7 +505,7 @@ public class AltosUI extends JFrame { * Open an existing telemetry file and replay it in realtime */ - class ReplayThread extends Thread { + class ReplayThread extends DisplayThread { FileInputStream replay; String filename; @@ -464,48 +514,46 @@ public class AltosUI extends JFrame { filename = name; } - /* Run the replay in a separate thread - * so that the UI can update - */ - public void run() { - String line; - AltosState state = null; + String read() { try { - while ((line = readline(replay)) != null) { - try { - AltosTelemetry t = new AltosTelemetry(line); - state = new AltosState(t, state); - show(state); - - /* Make it run in realtime after the rocket leaves the pad */ - try { - if (state.state > AltosTelemetry.ao_flight_pad) - Thread.sleep((int) (state.time_change * 1000)); - } catch (InterruptedException e) { - break; - } - } catch (ParseException pp) { - JOptionPane.showMessageDialog(AltosUI.this, - line, - "error parsing", - JOptionPane.ERROR_MESSAGE); - break; - } - } + return readline(replay); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, "error reading", JOptionPane.ERROR_MESSAGE); - } finally { - try { - replay.close(); - } catch (IOException e) {} + } + return null; + } + + void close () { + try { + replay.close(); + } catch (IOException ee) { } } + + void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > AltosTelemetry.ao_flight_pad) + Thread.sleep((int) (state.time_change * 1000)); + } + } + + Thread display_thread; + + private void stop_display() { + if (display_thread != null && display_thread.isAlive()) + display_thread.interrupt(); + display_thread = null; + } + + private void run_display(Thread thread) { + stop_display(); + display_thread = thread; + display_thread.start(); } - ReplayThread replay_thread; /* * Replay a flight from telemetry data */ @@ -525,10 +573,7 @@ public class AltosUI extends JFrame { try { FileInputStream replay = new FileInputStream(file); ReplayThread thread = new ReplayThread(replay, filename); - if (thread != null && replay_thread != null && replay_thread.isAlive()) - replay_thread.interrupt(); - replay_thread = thread; - replay_thread.start(); + run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, @@ -603,7 +648,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - serialLine.close(); + DisconnectFromDevice(); } }); menu.add(item); @@ -688,10 +733,6 @@ public class AltosUI extends JFrame { } public static void main(final String[] args) { - AltosDevice[] devices = AltosDeviceLinux.list(); - for (int i = 0; i < devices.length; i++) - System.out.printf("Model: %s Serial: %d Tty: %s\n", - devices[i].product, devices[i].serial, devices[i].tty); AltosUI altosui = new AltosUI(); altosui.setVisible(true); } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index fcb259eb..fbe0a5eb 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -13,6 +13,7 @@ CLASSFILES=\ AltosUI.class \ AltosDevice.class \ AltosDeviceLinux.class \ + AltosDeviceDialog.class JAVAFLAGS=-Xlint:unchecked -- cgit v1.2.3 From 8f1d47e9cd61738e516d15fc97d5730d80611e87 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:28:20 -0600 Subject: update changelogs for Debian build --- ChangeLog | 30 ++++++++++++++++++++++++++++++ debian/changelog | 9 +++++++++ 2 files changed, 39 insertions(+) diff --git a/ChangeLog b/ChangeLog index 618c4a51..8a1bc2fa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +commit c66eebad323e4572bb7cc23bc476ee144f03e9b8 +Author: Bdale Garbee +Date: Sat Apr 3 08:02:44 2010 -0600 + + rewrite urls in docbook format + +commit 8c600abf87c95f8f214b5e56ff6eab955795dff5 +Author: Bdale Garbee +Date: Thu Apr 1 23:56:47 2010 -0600 + + crudely incorporate "day in the life" info from web page + +commit 53ca3f98aeb70cb780031fee788de950e4388cf6 +Author: Bdale Garbee +Date: Thu Apr 1 23:39:42 2010 -0600 + + tweak copyright assertion + +commit 76768804e68ed09421d7a48cb0b390f102ce2d76 +Author: Bdale Garbee +Date: Tue Mar 30 23:26:35 2010 -0600 + + make lintian happy + +commit eb3cc3e9b60ec23acbb7d797affa743d671801ab +Author: Bdale Garbee +Date: Tue Mar 30 23:19:48 2010 -0600 + + update changelogs for Debian build + commit 00f49c8fb0aa38331360bdb85c32bcebe60dcdc3 Author: Bdale Garbee Date: Tue Mar 30 23:19:07 2010 -0600 diff --git a/debian/changelog b/debian/changelog index f0fe4564..f825bbd9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +altos (0.6+124+gc66eeba) unstable; urgency=low + + * make lintian happy + * tweak copyright assertion + * crudely incorporate "day in the life" info from web page + * rewrite urls in docbook format + + -- Bdale Garbee Thu, 08 Apr 2010 12:28:04 -0600 + altos (0.6+119+g00f49c8) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 6fbdc7037db185f03bd5ff96b9d9320646572df7 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:28:49 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 8a1bc2fa..45156966 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 8f1d47e9cd61738e516d15fc97d5730d80611e87 +Author: Bdale Garbee +Date: Thu Apr 8 12:28:20 2010 -0600 + + update changelogs for Debian build + commit c66eebad323e4572bb7cc23bc476ee144f03e9b8 Author: Bdale Garbee Date: Sat Apr 3 08:02:44 2010 -0600 diff --git a/debian/changelog b/debian/changelog index f825bbd9..59605688 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+124+gc66eeba) unstable; urgency=low +altos (0.6+125+g8f1d47e) unstable; urgency=low * make lintian happy * tweak copyright assertion -- cgit v1.2.3 From 05ad58389fa3814ecb56344bf4ec3a3e025920a2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:34:54 -0600 Subject: need another build dep --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 85074142..ff6c12e7 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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-xsl +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 Standards-Version: 3.8.4 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 8a067cd0eebbec313fc39086747ef618f2d1cf37 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:36:18 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 45156966..71c1eaf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 05ad58389fa3814ecb56344bf4ec3a3e025920a2 +Author: Bdale Garbee +Date: Thu Apr 8 12:34:54 2010 -0600 + + need another build dep + +commit 6fbdc7037db185f03bd5ff96b9d9320646572df7 +Author: Bdale Garbee +Date: Thu Apr 8 12:28:49 2010 -0600 + + update changelogs for Debian build + commit 8f1d47e9cd61738e516d15fc97d5730d80611e87 Author: Bdale Garbee Date: Thu Apr 8 12:28:20 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 59605688..8e35bec8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+127+g05ad583) unstable; urgency=low + + * need another build dep + + -- Bdale Garbee Thu, 08 Apr 2010 12:35:04 -0600 + altos (0.6+125+g8f1d47e) unstable; urgency=low * make lintian happy -- cgit v1.2.3 From 934434ffb3514fe9ff95692784750d7c5217a5d3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:41:28 -0600 Subject: fix typo in url --- doc/telemetrum.xsl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index f1525887..bfa19ab4 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -125,8 +125,7 @@ doesn't get you close enough because the rocket dropped into a canyon, or the wind is blowing it across a dry lake bed, or something like that... Keith and Bdale both currently own and use the - + Yaesu VX-6R at launches. -- cgit v1.2.3 From a1539a075a0cc79c9122fea878d9a20ee722a18c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:41:42 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 71c1eaf8..2eee2bd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 934434ffb3514fe9ff95692784750d7c5217a5d3 +Author: Bdale Garbee +Date: Thu Apr 8 12:41:28 2010 -0600 + + fix typo in url + +commit 8a067cd0eebbec313fc39086747ef618f2d1cf37 +Author: Bdale Garbee +Date: Thu Apr 8 12:36:18 2010 -0600 + + update changelogs for Debian build + commit 05ad58389fa3814ecb56344bf4ec3a3e025920a2 Author: Bdale Garbee Date: Thu Apr 8 12:34:54 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 8e35bec8..8405b26e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+129+g934434f) unstable; urgency=low + + * fix typo in url + + -- Bdale Garbee Thu, 08 Apr 2010 12:41:38 -0600 + altos (0.6+127+g05ad583) unstable; urgency=low * need another build dep -- cgit v1.2.3 From 6629ec52def8917ad033847812a1adc4c3e9c947 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:42:47 -0600 Subject: lose the url entirely for now --- doc/telemetrum.xsl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index bfa19ab4..b0c5e94f 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -124,11 +124,7 @@ if the rocket is hiding in sage brush or a tree, or if the last GPS position doesn't get you close enough because the rocket dropped into a canyon, or the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the - - Yaesu VX-6R - - at launches. + and Bdale both currently own and use the Yaesu VX-6R at launches. So, to recap, on the ground the hardware you'll need includes: -- cgit v1.2.3 From dec9971d70f17067ba0051206851b49c7604ac85 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 12:43:03 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2eee2bd5..2fdb01db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 6629ec52def8917ad033847812a1adc4c3e9c947 +Author: Bdale Garbee +Date: Thu Apr 8 12:42:47 2010 -0600 + + lose the url entirely for now + +commit a1539a075a0cc79c9122fea878d9a20ee722a18c +Author: Bdale Garbee +Date: Thu Apr 8 12:41:42 2010 -0600 + + update changelogs for Debian build + commit 934434ffb3514fe9ff95692784750d7c5217a5d3 Author: Bdale Garbee Date: Thu Apr 8 12:41:28 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 8405b26e..81dfc7e1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+131+g6629ec5) unstable; urgency=low + + * lose the url entirely for now + + -- Bdale Garbee Thu, 08 Apr 2010 12:43:01 -0600 + altos (0.6+129+g934434f) unstable; urgency=low * fix typo in url -- cgit v1.2.3 From a4356b9bcf679c4d7b88fbbad77a98ecb0f80098 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 8 Apr 2010 13:30:16 -0700 Subject: Use 16-bit flite voice (which appears to have changed symbols recently) --- ao-tools/ao-view/aoview_flite.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c index bc702b0f..00e6c9de 100644 --- a/ao-tools/ao-view/aoview_flite.c +++ b/ao-tools/ao-view/aoview_flite.c @@ -20,7 +20,7 @@ #include "aoview.h" #include -cst_voice *register_cmu_us_kal(); +cst_voice *register_cmu_us_kal16(); static cst_voice *voice; static FILE *pipe_write; @@ -118,7 +118,7 @@ aoview_flite_start(void) if (!once) { flite_init(); - voice = register_cmu_us_kal(); + voice = register_cmu_us_kal16(); if (!voice) { perror("register voice"); exit(1); -- cgit v1.2.3 From f93c9bf3695862db31f2c3b3bc5a7bb24ef3766c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 8 Apr 2010 17:28:17 -0700 Subject: When changing RESET line, delay 20ms The GPS data sheet suggests a 1uF cap on the reset line to ensure it is held low long enough for the power supply to come up to voltage. TM v1.0 loads a 0.001uF cap there, but in case that isn't large enough, it could be replaced with the larger one. This change makes sure that even with that larger value, the debugging link will be able to reset the target. Signed-off-by: Keith Packard --- src/ao_dbg.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index d0633f92..2fc266e3 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -184,6 +184,12 @@ ao_dbg_long_delay(void) _asm nop _endasm; } +static void +ao_dbg_reset_delay(void) +{ + ao_delay(AO_MS_TO_TICKS(20)); +} + void ao_dbg_debug_mode(void) { @@ -192,7 +198,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); @@ -200,7 +206,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); } void @@ -211,7 +217,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); @@ -219,7 +225,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); } static void -- cgit v1.2.3 From 01e524f11a67390a8ea1f20aa2d611909b4da363 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 19:55:05 -0600 Subject: choose a better set of docbook xsl files --- doc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index d3293900..55b7a548 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -6,12 +6,12 @@ all: telemetrum.html telemetrum.pdf telemetrum.html: telemetrum.xsl xsltproc -o telemetrum.html \ - /usr/share/xml/docbook/stylesheet/nwalsh/html/docbook.xsl \ + /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl \ telemetrum.xsl telemetrum.fo: telemetrum.xsl xsltproc -o telemetrum.fo \ - /usr/share/xml/docbook/stylesheet/nwalsh/fo/docbook.xsl \ + /usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl \ telemetrum.xsl telemetrum.pdf: telemetrum.fo -- cgit v1.2.3 From 5c3b6e2d1989bcaa19ae3e294f297ec3e5648a53 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 19:56:40 -0600 Subject: update changelogs for Debian build --- ChangeLog | 224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 38 ++++++++++ 2 files changed, 262 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2fdb01db..97f83539 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,50 @@ +commit 01e524f11a67390a8ea1f20aa2d611909b4da363 +Author: Bdale Garbee +Date: Thu Apr 8 19:55:05 2010 -0600 + + choose a better set of docbook xsl files + +commit f93c9bf3695862db31f2c3b3bc5a7bb24ef3766c +Author: Keith Packard +Date: Thu Apr 8 17:28:17 2010 -0700 + + When changing RESET line, delay 20ms + + The GPS data sheet suggests a 1uF cap on the reset line to ensure it + is held low long enough for the power supply to come up to voltage. TM + v1.0 loads a 0.001uF cap there, but in case that isn't large enough, + it could be replaced with the larger one. This change makes sure that + even with that larger value, the debugging link will be able to reset + the target. + + Signed-off-by: Keith Packard + +commit baaaac499cfbc1286ae55374cfdc796d32983b92 +Merge: a4356b9 dec9971 +Author: Keith Packard +Date: Thu Apr 8 13:31:23 2010 -0700 + + Merge remote branch 'origin/master' + +commit a4356b9bcf679c4d7b88fbbad77a98ecb0f80098 +Author: Keith Packard +Date: Thu Apr 8 13:30:16 2010 -0700 + + Use 16-bit flite voice (which appears to have changed symbols recently) + +commit 447c121fc1ceb878e45718ad1364a5349965a59a +Merge: 10330d2 53ca3f9 +Author: Keith Packard +Date: Thu Apr 8 11:46:56 2010 -0700 + + Merge remote branch 'origin/master' into altosui + +commit dec9971d70f17067ba0051206851b49c7604ac85 +Author: Bdale Garbee +Date: Thu Apr 8 12:43:03 2010 -0600 + + update changelogs for Debian build + commit 6629ec52def8917ad033847812a1adc4c3e9c947 Author: Bdale Garbee Date: Thu Apr 8 12:42:47 2010 -0600 @@ -40,12 +87,165 @@ Date: Thu Apr 8 12:28:20 2010 -0600 update changelogs for Debian build +commit 10330d23518c94a8b791193a97a6cc07b1c9a97c +Author: Keith Packard +Date: Tue Apr 6 00:58:00 2010 -0700 + + Enable telemetry monitoring + + Signed-off-by: Keith Packard + +commit 9e10e43eff9de3f034da49c4f88728fb933f5035 +Author: Keith Packard +Date: Tue Apr 6 00:56:57 2010 -0700 + + Tasks may move in task structure as a result of ao_exit + + Signed-off-by: Keith Packard + +commit a7fc7901cd591c93d9d0cffeec2977ebb17554d4 +Author: Keith Packard +Date: Tue Apr 6 00:55:19 2010 -0700 + + TD reports "not-connected" when GPS has 0 sats + +commit e064d05da87926c19fb665b40fb280fb59328183 +Author: Keith Packard +Date: Tue Apr 6 00:54:52 2010 -0700 + + serial port read function cannot be interrupted. poll every 1 second + +commit c099a67d9ea37e731e0eca318102560281ac240f +Author: Keith Packard +Date: Mon Apr 5 22:42:05 2010 -0700 + + Interrupt running replay thread when starting another replay + + Signed-off-by: Keith Packard + +commit cc600a0389720bc7e435dbda8bec080ef19e0c58 +Author: Keith Packard +Date: Mon Apr 5 22:21:46 2010 -0700 + + Add Linux device discovery + + AltosDeviceLinux.java scans /proc to locate suitable devices. This + will be hooked up to the UI shortly. + +commit c28646d72005daeadb70b95fd3b0050bd752cc55 +Author: Keith Packard +Date: Sun Apr 4 20:55:30 2010 -0700 + + Switch TeleMetrum from v0.2 to v1.0 + + Signed-off-by: Keith Packard + +commit d22ba55ae0e056530a727df50f14ad853d79a2c8 +Author: Keith Packard +Date: Sun Apr 4 20:55:18 2010 -0700 + + Clean up some altosui comments + +commit 6251e89c6eea655769f77bc18e98e79c99cf3cad +Author: Keith Packard +Date: Sun Apr 4 19:54:46 2010 -0700 + + Don't abort the radio when enabling telemetry monitoring + + If telemetry monitoring is already on, then there isn't any point, and + if it's not on, then presumably there isn't any radio work to abort. + + Signed-off-by: Keith Packard + +commit b0b99f30c4e00689e9faceb363a5c7284541c6be +Author: Keith Packard +Date: Sun Apr 4 19:48:50 2010 -0700 + + Make ao_radio_idle keep trying to get the radio to idle. + + Attempting to abort a radio operation could lead to a hang if the user + of the radio jumped in and started using it again before the task + attempting to abort woke up. This change just keeps smacking the radio + until the radio goes idle long enough to detect it. + +commit 0e7abc9fedec568b431c983d3df1b0b29f4f10e3 +Author: Keith Packard +Date: Sun Apr 4 16:32:04 2010 -0700 + + Use RXTX for serial comm. Add logdir preference saving + commit c66eebad323e4572bb7cc23bc476ee144f03e9b8 Author: Bdale Garbee Date: Sat Apr 3 08:02:44 2010 -0600 rewrite urls in docbook format +commit 3d34c488c5b71020d86f83156fd821fd860bf214 +Author: Keith Packard +Date: Sat Apr 3 00:02:44 2010 -0700 + + Make .jar file + +commit 4bea4c327e002ce8f88218f0d840af7c1521bc35 +Author: Keith Packard +Date: Fri Apr 2 23:25:02 2010 -0700 + + Remove unused cell renderer class + +commit 4ad062969ae8a608b8428620579bbe114e580a11 +Author: Keith Packard +Date: Fri Apr 2 23:20:38 2010 -0700 + + Remove GPS data missing from skytraq. Save max height/accel/speed + +commit ebd49d4ec6b0b60c85b2de45cfe2e36add8fe9bf +Author: Keith Packard +Date: Fri Apr 2 23:05:40 2010 -0700 + + Report current gps nsat, not last locked nsat + +commit 3f9b66b307ee88172151e3bee58e50f5acbde109 +Author: Keith Packard +Date: Fri Apr 2 23:00:30 2010 -0700 + + Clean up GPS data formatting + +commit 9cc48698ec14c34d437baad7b6540edc31e9741c +Author: Keith Packard +Date: Fri Apr 2 22:47:40 2010 -0700 + + Fix state updates + +commit 6d523ee4dad3b9890d3cf05852459101fe7e26ea +Author: Keith Packard +Date: Fri Apr 2 21:48:41 2010 -0700 + + Fix status update + +commit caa0bf49668344937483190d1c258bfa32971d19 +Author: Keith Packard +Date: Fri Apr 2 21:44:00 2010 -0700 + + Fix up table formatting + +commit a579402f428dd6a0529505069d1846f70b83ab5d +Author: Keith Packard +Date: Fri Apr 2 18:10:59 2010 -0700 + + Display table of flight info. gps is not working yet though + +commit 65079f84ea64220fa928c3ad96652fed159bf74b +Author: Keith Packard +Date: Fri Apr 2 16:07:40 2010 -0700 + + Steal C code from ao-view + +commit 02f2be90879b682b6e648cf2debc83223d127b9d +Author: Keith Packard +Date: Fri Apr 2 13:37:52 2010 -0700 + + Add telem parsing code + commit 8c600abf87c95f8f214b5e56ff6eab955795dff5 Author: Bdale Garbee Date: Thu Apr 1 23:56:47 2010 -0600 @@ -58,6 +258,30 @@ Date: Thu Apr 1 23:39:42 2010 -0600 tweak copyright assertion +commit 6454e309858aeef7912e862de8632618d89b4205 +Author: Keith Packard +Date: Thu Apr 1 18:31:14 2010 -0700 + + Fix windows install file + +commit 584ab100640a07dec6e06829e73b7260d17d2232 +Author: Keith Packard +Date: Thu Apr 1 18:30:56 2010 -0700 + + Add Windows install .inf file + +commit a06bee96e648d9ded8776f3d6cba9505e7be1a60 +Author: Keith Packard +Date: Wed Mar 31 23:05:03 2010 -0700 + + Add telemetry data parsing code + +commit 7f233369e32c3254165ee251df0a3dbc21ea5a29 +Author: Keith Packard +Date: Wed Mar 31 13:49:54 2010 -0700 + + Start adding java-based UI + commit 76768804e68ed09421d7a48cb0b390f102ce2d76 Author: Bdale Garbee Date: Tue Mar 30 23:26:35 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 81dfc7e1..d8f4a833 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,41 @@ +altos (0.6+163+g01e524f) unstable; urgency=low + + [ Keith Packard ] + * Start adding java-based UI + * Add telemetry data parsing code + * Add Windows install .inf file + * Fix windows install file + * Add telem parsing code + * Steal C code from ao-view + * Display table of flight info. gps is not working yet though + * Fix up table formatting + * Fix status update + * Fix state updates + * Clean up GPS data formatting + * Report current gps nsat, not last locked nsat + * Remove GPS data missing from skytraq. Save max height/accel/speed + * Remove unused cell renderer class + * Make .jar file + * Use RXTX for serial comm. Add logdir preference saving + * Make ao_radio_idle keep trying to get the radio to idle. + * Don't abort the radio when enabling telemetry monitoring + * Clean up some altosui comments + * Switch TeleMetrum from v0.2 to v1.0 + * Add Linux device discovery + * Interrupt running replay thread when starting another replay + * serial port read function cannot be interrupted. poll every 1 second + * TD reports "not-connected" when GPS has 0 sats + * Tasks may move in task structure as a result of ao_exit + * Enable telemetry monitoring + * Use 16-bit flite voice (which appears to have changed symbols + recently) + * When changing RESET line, delay 20ms + + [ Bdale Garbee ] + * choose a better set of docbook xsl files + + -- Bdale Garbee Thu, 08 Apr 2010 19:56:27 -0600 + altos (0.6+131+g6629ec5) unstable; urgency=low * lose the url entirely for now -- cgit v1.2.3 From 4b02f293e9c32a568fad89558274f21157e7d473 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 8 Apr 2010 20:08:07 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 97f83539..5a866157 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 5c3b6e2d1989bcaa19ae3e294f297ec3e5648a53 +Author: Bdale Garbee +Date: Thu Apr 8 19:56:40 2010 -0600 + + update changelogs for Debian build + commit 01e524f11a67390a8ea1f20aa2d611909b4da363 Author: Bdale Garbee Date: Thu Apr 8 19:55:05 2010 -0600 diff --git a/debian/changelog b/debian/changelog index d8f4a833..6d10c414 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+163+g01e524f) unstable; urgency=low +altos (0.6+164+g5c3b6e2) unstable; urgency=low [ Keith Packard ] * Start adding java-based UI -- cgit v1.2.3 From ea5d4f01d18d93d032f05933041b7b6881289780 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 8 Apr 2010 22:45:04 -0700 Subject: libflite may forget to reference libasound --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 77699fba..d4ddda18 100644 --- a/configure.ac +++ b/configure.ac @@ -44,11 +44,11 @@ fi AC_SUBST(WARN_CFLAGS) AC_CHECK_HEADERS(flite/flite.h,HAVE_FLITE_H=yes,HAVE_FLITE_H=no) -AC_CHECK_LIB(flite, flite_init,HAVE_LIBFLITE=yes,HAVE_LIBFLITE=no,-lm) +AC_CHECK_LIB(flite, flite_init,HAVE_LIBFLITE=yes,HAVE_LIBFLITE=no,-lasound -lm) if test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes"; then AC_DEFINE(HAVE_FLITE,1,[Define if the flite library is usable]) - AC_SUBST(FLITE_LIBS,"-lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite -lm") + AC_SUBST(FLITE_LIBS,"-lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite -lasound -lm") AC_SUBST(FLITE_INCS,-Iflite) fi AM_CONDITIONAL(USE_FLITE,test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes") -- cgit v1.2.3 From 25e69ebfec94560e0714cf2cc623dc9697b4ea99 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 9 Apr 2010 00:08:32 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5a866157..7857137a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit ea5d4f01d18d93d032f05933041b7b6881289780 +Author: Keith Packard +Date: Thu Apr 8 22:45:04 2010 -0700 + + libflite may forget to reference libasound + +commit 4b02f293e9c32a568fad89558274f21157e7d473 +Author: Bdale Garbee +Date: Thu Apr 8 20:08:07 2010 -0600 + + update changelogs for Debian build + commit 5c3b6e2d1989bcaa19ae3e294f297ec3e5648a53 Author: Bdale Garbee Date: Thu Apr 8 19:56:40 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 6d10c414..f11cf8c1 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+166+gea5d4f0) unstable; urgency=low + + [ Keith Packard ] + * libflite may forget to reference libasound + + -- Bdale Garbee Fri, 09 Apr 2010 00:08:24 -0600 + altos (0.6+164+g5c3b6e2) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From c0ee1ae25e1d18138d8372f47085de48ffada344 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 9 Apr 2010 00:09:21 -0600 Subject: file changed by auto tools --- INSTALL | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/INSTALL b/INSTALL index 2550dab7..7d1c323b 100644 --- a/INSTALL +++ b/INSTALL @@ -4,8 +4,10 @@ Installation Instructions Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. - This file is free documentation; the Free Software Foundation gives -unlimited permission to copy, distribute and modify it. + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. Basic Installation ================== @@ -13,7 +15,11 @@ Basic Installation Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for -instructions specific to this package. +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses @@ -42,7 +48,7 @@ may remove or edit it. you want to change it or regenerate `configure' using a newer version of `autoconf'. -The simplest way to compile this package is: + The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. @@ -53,12 +59,22 @@ The simplest way to compile this package is: 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with - the package. + the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and - documentation. - - 5. You can remove the program binaries and object files from the + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is @@ -67,8 +83,15 @@ The simplest way to compile this package is: all sorts of other programs in order to regenerate files that came with the distribution. - 6. Often, you can also type `make uninstall' to remove the installed - files again. + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. Compilers and Options ===================== @@ -93,7 +116,8 @@ same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. +source code in the directory that `configure' is in and in `..'. This +is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have @@ -120,7 +144,8 @@ Installation Names By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving -`configure' the option `--prefix=PREFIX'. +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you @@ -131,15 +156,46 @@ Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories -you can set and what kinds of files go in them. +you can set and what kinds of files go in them. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. -Optional Features -================= - Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE @@ -152,6 +208,13 @@ find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + Particular systems ================== @@ -288,7 +351,7 @@ operates. `configure' can determine that directory automatically. `--prefix=DIR' - Use DIR as the installation prefix. *Note Installation Names:: + Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. -- cgit v1.2.3 From a832c7e9d9e9e420e1281136188bd53b34c56464 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 9 Apr 2010 00:10:03 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7857137a..a76c8dc4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit c0ee1ae25e1d18138d8372f47085de48ffada344 +Author: Bdale Garbee +Date: Fri Apr 9 00:09:21 2010 -0600 + + file changed by auto tools + +commit 25e69ebfec94560e0714cf2cc623dc9697b4ea99 +Author: Bdale Garbee +Date: Fri Apr 9 00:08:32 2010 -0600 + + update changelogs for Debian build + commit ea5d4f01d18d93d032f05933041b7b6881289780 Author: Keith Packard Date: Thu Apr 8 22:45:04 2010 -0700 diff --git a/debian/changelog b/debian/changelog index f11cf8c1..05274a80 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,7 @@ -altos (0.6+166+gea5d4f0) unstable; urgency=low +altos (0.6+168+gc0ee1ae) unstable; urgency=low + + [ Bdale Garbee ] + * INSTALL file changed by auto tools [ Keith Packard ] * libflite may forget to reference libasound -- cgit v1.2.3 From ce39372a3aeffff1a08d609e63164a00cf974663 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 9 Apr 2010 13:50:49 -0600 Subject: wrong Yaesu model --- doc/telemetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index b0c5e94f..55eda3bd 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -124,7 +124,7 @@ if the rocket is hiding in sage brush or a tree, or if the last GPS position doesn't get you close enough because the rocket dropped into a canyon, or the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-6R at launches. + and Bdale both currently own and use the Yaesu VX-7R at launches. So, to recap, on the ground the hardware you'll need includes: -- cgit v1.2.3 From 9394393c24c0a96b94319f2d0aa78fb498a121c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Apr 2010 17:51:01 -0700 Subject: Only have the slave return a packet if it received one. When the receive is aborted to switch modes, it's important to not immediately re-acquire the radio and try to send a packet as the aborting thread won't know to kick the receiver again. This prevents the 'C' command from locking up as it tries to stop the packet slave before turning on the transmitter. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 4c947fbf..e03ebdc3 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,12 +20,15 @@ void ao_packet_slave(void) { + uint8_t status; + ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_packet_recv(); - ao_packet_send(); + status = ao_packet_recv(); + if (status & AO_DMA_DONE) + ao_packet_send(); } ao_exit(); } -- cgit v1.2.3 From b3a2e1221735d54dc3f2b97b4e75ed6f33ab8227 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 10 Apr 2010 15:01:14 -0600 Subject: update changelogs for Debian build --- ChangeLog | 27 +++++++++++++++++++++++++++ debian/changelog | 10 ++++++++++ 2 files changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index a76c8dc4..e26b3c4e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +commit 9394393c24c0a96b94319f2d0aa78fb498a121c9 +Author: Keith Packard +Date: Fri Apr 9 17:51:01 2010 -0700 + + Only have the slave return a packet if it received one. + + When the receive is aborted to switch modes, it's important to not + immediately re-acquire the radio and try to send a packet as the + aborting thread won't know to kick the receiver again. + + This prevents the 'C' command from locking up as it tries to stop the + packet slave before turning on the transmitter. + + Signed-off-by: Keith Packard + +commit ce39372a3aeffff1a08d609e63164a00cf974663 +Author: Bdale Garbee +Date: Fri Apr 9 13:50:49 2010 -0600 + + wrong Yaesu model + +commit a832c7e9d9e9e420e1281136188bd53b34c56464 +Author: Bdale Garbee +Date: Fri Apr 9 00:10:03 2010 -0600 + + update changelogs for Debian build + commit c0ee1ae25e1d18138d8372f47085de48ffada344 Author: Bdale Garbee Date: Fri Apr 9 00:09:21 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 05274a80..562466c7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,13 @@ +altos (0.6+171+g9394393) unstable; urgency=low + + [ Bdale Garbee ] + * wrong Yaesu model + + [ Keith Packard ] + * Only have the slave return a packet if it received one. + + -- Bdale Garbee Sat, 10 Apr 2010 15:01:04 -0600 + altos (0.6+168+gc0ee1ae) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From c879b178d83c9a9a521f42a960b10e19b11cee92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Apr 2010 22:09:57 -0700 Subject: Increase reset switch time to 100ms Signed-off-by: Keith Packard --- src/ao_dbg.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 2fc266e3..e7fbd7ad 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -184,11 +184,8 @@ ao_dbg_long_delay(void) _asm nop _endasm; } -static void -ao_dbg_reset_delay(void) -{ - ao_delay(AO_MS_TO_TICKS(20)); -} +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) void ao_dbg_debug_mode(void) @@ -198,7 +195,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_LOW_DELAY); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); @@ -206,7 +203,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_HIGH_DELAY); } void @@ -217,7 +214,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_LOW_DELAY); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); @@ -225,7 +222,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_HIGH_DELAY); } static void -- cgit v1.2.3 From 5f93cf8c73555f43c14b1b0757f264bde69e9b8a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 18 Apr 2010 08:35:43 -0600 Subject: capture work done on SFO->DEN flight --- doc/telemetrum.xsl | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 169 insertions(+), 6 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 55eda3bd..6e4320e1 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -37,25 +37,188 @@ Introduction and Overview - Placeholder. + Welcome to the Altus Metrum community! Our circuits and software reflect + our passion for both hobby rocketry and Free Software. We hope their + capabilities and performance will delight you in every way, but by + releasing all of our hardware and software designs under open licenses, + we also hope to empower you to take as active a role in our collective + future as you wish! + + + The focal point of our community is TeleMetrum, a dual deploy altimeter + with fully integrated GPS and radio telemetry as standard features, and + a "companion interface" that will support optional capabilities in the + future. + + + Complementing TeleMetrum is TeleDongle, a USB to RF interface for + communicating with TeleMetrum. Combined with your choice of antenna and + notebook computer, TeleDongle and our associated user interface software + form a complete ground station capable of logging and displaying in-flight + telemetry, aiding rocket recovery, then processing and archiving flight + data for analysis and review. Specifications - - Placeholder. - + + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + Handling Precautions - Placeholder. + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver extraordinary results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe's see-through + plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. Hardware Overview - Placeholder. + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. + + + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard e-matches + from companies like [insert company and product names for e-matches we've + tried and like] and with Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide by default and so may be the most familiar + option. You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. -- cgit v1.2.3 From e7dc7fab787df63a4de72c8450e94092eb04d7db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Apr 2010 14:53:44 -0700 Subject: Add optional 's' command to packet slave to enable/disable slave mode This option has been selected for teledongle so that you can use slave mode and hook two teledongles together over the RF link. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 26 ++++++++++++++++++++++++-- src/ao_pins.h | 3 ++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e03ebdc3..3c4ffb92 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -36,8 +36,10 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } } void @@ -54,10 +56,30 @@ ao_packet_slave_stop(void) } } +#ifdef PACKET_HAS_SLAVE_CMD +void +ao_packet_slave_control(void) +{ + ao_cmd_hex(); + if (ao_cmd_lex_i) + ao_packet_slave_start(); + else + ao_packet_slave_stop(); +} + +__code struct ao_cmds ao_packet_slave_cmds[] = { + { 's', ao_packet_slave_control, "s Remote packet link slave" }, + { 0, ao_packet_slave_control, NULL }, +}; +#endif + void ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); +#ifdef PACKET_HAS_SLAVE_CMD + ao_cmd_register(&ao_packet_slave_cmds[0]); +#endif } diff --git a/src/ao_pins.h b/src/ao_pins.h index e9a265b0..5a0b4318 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -41,7 +41,8 @@ #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 + #define PACKET_HAS_SLAVE 1 + #define PACKET_HAS_SLAVE_CMD 1 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) -- cgit v1.2.3 From 97f4874d19ec05c81a04a3ecd06abffcf7fbfafc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Apr 2010 16:25:35 -0700 Subject: More ALtosUI changes --- ao-tools/altosui/AltosSerial.java | 39 ++++++++++++++++++++++++--------------- ao-tools/altosui/AltosUI.java | 18 ++++++------------ ao-tools/altosui/Makefile | 3 +++ 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index e4cedde2..03ab28c5 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -36,7 +36,7 @@ import altosui.AltosSerialMonitor; */ class AltosSerialReader implements Runnable { InputStream serial_in; - LinkedBlockingQueue monitor_queue; + LinkedList> monitors; LinkedBlockingQueue reply_queue; Thread input_thread; String line; @@ -56,9 +56,12 @@ class AltosSerialReader implements Runnable { synchronized(this) { if (c == '\n') { if (line != "") { - if (line.startsWith("VERSION")) - monitor_queue.put(line); - else + if (line.startsWith("VERSION")) { + for (int e = 0; e < monitors.size(); e++) { + LinkedBlockingQueue q = monitors.get(e); + q.put(line); + } + } else reply_queue.put(line); line = ""; } @@ -72,16 +75,18 @@ class AltosSerialReader implements Runnable { } } - public String get_telem() throws InterruptedException { - String s = monitor_queue.take(); - System.out.println(s); - return s; - } - public String get_reply() throws InterruptedException { return reply_queue.take(); } + public void add_monitor(LinkedBlockingQueue q) { + monitors.add(q); + } + + public void remove_monitor(LinkedBlockingQueue q) { + monitors.remove(q); + } + public void flush () { synchronized(this) { if (!"VERSION".startsWith(line) && !line.startsWith("VERSION")) @@ -132,7 +137,7 @@ class AltosSerialReader implements Runnable { serial_in = null; input_thread = null; line = ""; - monitor_queue = new LinkedBlockingQueue (); + monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); } @@ -142,10 +147,6 @@ public class AltosSerial { OutputStream serial_out = null; AltosSerialReader reader = null; - public String get_telem() throws InterruptedException { - return reader.get_telem(); - } - CommPort comm_port = null; public void close() { @@ -178,6 +179,14 @@ public class AltosSerial { reader = new AltosSerialReader(); } + public void add_monitor(LinkedBlockingQueue q) { + reader.add_monitor(q); + } + + public void remove_monitor(LinkedBlockingQueue q) { + reader.remove_monitor(q); + } + public AltosSerial() { init(); } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 7f008f3a..2952fcc0 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -26,6 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; import gnu.io.*; import altosui.AltosSerial; @@ -391,14 +392,6 @@ public class AltosUI extends JFrame { return true; } - private void PickSerialDevice() { - java.util.Enumeration port_list = CommPortIdentifier.getPortIdentifiers(); - while (port_list.hasMoreElements()) { - CommPortIdentifier identifier = port_list.nextElement(); - System.out.println("Serial port " + identifier.getName()); - } - } - class DisplayThread extends Thread { String read() throws InterruptedException { return null; } @@ -433,21 +426,22 @@ public class AltosUI extends JFrame { class DeviceThread extends DisplayThread { AltosSerial serial; + LinkedBlockingQueue telem; String read() throws InterruptedException { - System.out.println("Waiting for telemetry"); - String s = serial.get_telem(); - System.out.println("Got telemetry " + s); - return s; + return telem.take(); } void close() { serial.close(); + serial.remove_monitor(telem); System.out.println("DisplayThread done"); } public DeviceThread(AltosSerial s) { serial = s; + telem = new LinkedBlockingQueue(); + serial.add_monitor(telem); } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index fbe0a5eb..b9f025da 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -3,9 +3,12 @@ CLASSPATH=..:/usr/share/java/* CLASSFILES=\ AltosConvert.class \ + AltosFile.class \ AltosGPS.class \ AltosGreatCircle.class \ + AltosLog.class \ AltosParse.class \ + AltosPreferences.class \ AltosSerialMonitor.class \ AltosSerial.class \ AltosState.class \ -- cgit v1.2.3 From 75d8ffd4eadf31d50b2f58c021530c17ff1bdc66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Apr 2010 13:53:25 -0700 Subject: Autodetect flite voice registration function Old versions of flite exported the function 'register_cmu_us_kal' while new ones export 'register_cmu_us_kal16'. This patch just checks which one is available and uses that. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_flite.c | 8 ++++++++ configure.ac | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/ao-tools/ao-view/aoview_flite.c b/ao-tools/ao-view/aoview_flite.c index 00e6c9de..abcdc491 100644 --- a/ao-tools/ao-view/aoview_flite.c +++ b/ao-tools/ao-view/aoview_flite.c @@ -21,6 +21,8 @@ #include cst_voice *register_cmu_us_kal16(); +cst_voice *register_cmu_us_kal(); + static cst_voice *voice; static FILE *pipe_write; @@ -118,7 +120,13 @@ aoview_flite_start(void) if (!once) { flite_init(); +#if HAVE_REGISTER_CMU_US_KAL16 voice = register_cmu_us_kal16(); +#else +#if HAVE_REGISTER_CMU_US_KAL + voice = register_cmu_us_kal(); +#endif +#endif if (!voice) { perror("register voice"); exit(1); diff --git a/configure.ac b/configure.ac index d4ddda18..d6c8682b 100644 --- a/configure.ac +++ b/configure.ac @@ -50,6 +50,10 @@ if test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes"; then AC_DEFINE(HAVE_FLITE,1,[Define if the flite library is usable]) AC_SUBST(FLITE_LIBS,"-lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite -lasound -lm") AC_SUBST(FLITE_INCS,-Iflite) + save_LIBS="$LIBS" + LIBS="$LIBS $FLITE_LIBS" + AC_CHECK_FUNCS([register_cmu_us_kal16 register_cmu_us_kal],break) + LIBS="$save_LIBS" fi AM_CONDITIONAL(USE_FLITE,test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes") -- cgit v1.2.3 From 641e76c5d419dab057298541b3a7546877643198 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 27 Apr 2010 00:17:15 -0600 Subject: add some RF usage information from an email reply sent today, and re-indent --- doc/telemetrum.xsl | 123 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 44 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 6e4320e1..70a78693 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -61,64 +61,63 @@ Specifications - - - Recording altimeter for model rocketry. - + + Recording altimeter for model rocketry. + - - Supports dual deployment (can fire 2 ejection charges). - + + Supports dual deployment (can fire 2 ejection charges). + - - 70cm ham-band transceiver for telemetry downlink. - + + 70cm ham-band transceiver for telemetry downlink. + - - Barometric pressure sensor good to 45k feet MSL. - + + Barometric pressure sensor good to 45k feet MSL. + - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + - - On-board, integrated GPS receiver with 5hz update rate capability. - + + On-board, integrated GPS receiver with 5hz update rate capability. + - - On-board 1 megabyte non-volatile memory for flight data storage. - + + On-board 1 megabyte non-volatile memory for flight data storage. + - - USB interface for battery charging, configuration, and data recovery. - + + USB interface for battery charging, configuration, and data recovery. + - - Fully integrated support for LiPo rechargeable batteries. - + + Fully integrated support for LiPo rechargeable batteries. + - - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. - + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + @@ -223,9 +222,45 @@ Operation - - Placeholder. - +
+ Radio Link + + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we have to decide how to manage the + link... + + + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + + We don't use a 'normal packet radio' mode because they're just too + inefficient. GFSK is just FSK with the baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had a test flight above 12k AGL with good reception, and my calculations + say we should be good to 40k AGL or more with just a 5-element yagi on + the ground. I expect to push 30k with a 54mm minimum airframe I'm + working on now, so we'll hopefully have further practical confirmation + of our link margin in a few months. + + + Placeholder. + +
Using Altus Metrum Products @@ -312,11 +347,11 @@ The best hand-held commercial directional antennas we've found for radio direction finding rockets are from - - Arrow Antennas. - -The 440-3 and 440-5 are both good choices for finding a -TeleMetrum-equipped rocket when used with a suitable 70cm HT. + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT.
-- cgit v1.2.3 From af0613ffc178b9b1f011c315923f92f2581fe53e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 27 Apr 2010 00:18:43 -0600 Subject: update changelogs for Debian build --- ChangeLog | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 16 +++++++++++++ 2 files changed, 85 insertions(+) diff --git a/ChangeLog b/ChangeLog index e26b3c4e..7094d996 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,72 @@ +commit 99094f02bf4849ba1f6b9842ded6c39d894320f7 +Merge: 641e76c 75d8ffd +Author: Bdale Garbee +Date: Tue Apr 27 00:17:37 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 641e76c5d419dab057298541b3a7546877643198 +Author: Bdale Garbee +Date: Tue Apr 27 00:17:15 2010 -0600 + + add some RF usage information from an email reply sent today, and re-indent + +commit 75d8ffd4eadf31d50b2f58c021530c17ff1bdc66 +Author: Keith Packard +Date: Fri Apr 23 13:53:25 2010 -0700 + + Autodetect flite voice registration function + + Old versions of flite exported the function 'register_cmu_us_kal' + while new ones export 'register_cmu_us_kal16'. This patch just checks + which one is available and uses that. + + Signed-off-by: Keith Packard + +commit 97f4874d19ec05c81a04a3ecd06abffcf7fbfafc +Author: Keith Packard +Date: Thu Apr 22 16:25:35 2010 -0700 + + More ALtosUI changes + +commit e7dc7fab787df63a4de72c8450e94092eb04d7db +Author: Keith Packard +Date: Thu Apr 22 14:53:44 2010 -0700 + + Add optional 's' command to packet slave to enable/disable slave mode + + This option has been selected for teledongle so that you can use slave + mode and hook two teledongles together over the RF link. + + Signed-off-by: Keith Packard + +commit f4383394b5d2b275b21e3ce8040d8cb9e48bb375 +Merge: 5f93cf8 c879b17 +Author: Bdale Garbee +Date: Sun Apr 18 08:36:07 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 5f93cf8c73555f43c14b1b0757f264bde69e9b8a +Author: Bdale Garbee +Date: Sun Apr 18 08:35:43 2010 -0600 + + capture work done on SFO->DEN flight + +commit c879b178d83c9a9a521f42a960b10e19b11cee92 +Author: Keith Packard +Date: Sat Apr 10 22:09:57 2010 -0700 + + Increase reset switch time to 100ms + + Signed-off-by: Keith Packard + +commit b3a2e1221735d54dc3f2b97b4e75ed6f33ab8227 +Author: Bdale Garbee +Date: Sat Apr 10 15:01:14 2010 -0600 + + update changelogs for Debian build + commit 9394393c24c0a96b94319f2d0aa78fb498a121c9 Author: Keith Packard Date: Fri Apr 9 17:51:01 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 562466c7..be14fb89 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +altos (0.6+180+g99094f0) unstable; urgency=low + + [ Keith Packard ] + * Increase reset switch time to 100ms + * Add optional 's' command to packet slave to enable/disable slave + mode + * More ALtosUI changes + * Autodetect flite voice registration function + + [ Bdale Garbee ] + * capture work done on SFO->DEN flight + * add some RF usage information from an email reply sent today, and + re-indent + + -- Bdale Garbee Tue, 27 Apr 2010 00:17:57 -0600 + altos (0.6+171+g9394393) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 8c95f33686f69da717013ec2c25dbcd99c03aa45 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Apr 2010 17:48:44 -0600 Subject: more text created during SFO->DEN flight --- doc/telemetrum.xsl | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 70a78693..793347f9 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -222,6 +222,97 @@ Operation +
+ Firmware Modes + + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. + + + In flight mode, TeleMetrum turns on the GPS system, engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" on the beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates [FIXME] apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. + + + In idle mode, the normal flight state machine is disengaged, and thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can thus be issues to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. + + + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! + +
+
+ GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! + + + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. + +
+
+ Ground Testing + + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! + + + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. + +
Radio Link @@ -397,6 +488,14 @@
+
+ + How GPS Works + + + Placeholder. + +
-- cgit v1.2.3 From aa9ff021d683764a43800eaa18ea0c9be5134939 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 4 May 2010 21:42:54 -0700 Subject: Revert "Add optional 's' command to packet slave to enable/disable slave mode" This reverts commit e7dc7fab787df63a4de72c8450e94092eb04d7db. This patch didn't work, and magically appears to break flashing TM from TD. --- src/ao_packet_slave.c | 26 ++------------------------ src/ao_pins.h | 3 +-- 2 files changed, 3 insertions(+), 26 deletions(-) diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 3c4ffb92..e03ebdc3 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -36,10 +36,8 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - if (!ao_packet_enable) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - } + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); } void @@ -56,30 +54,10 @@ ao_packet_slave_stop(void) } } -#ifdef PACKET_HAS_SLAVE_CMD -void -ao_packet_slave_control(void) -{ - ao_cmd_hex(); - if (ao_cmd_lex_i) - ao_packet_slave_start(); - else - ao_packet_slave_stop(); -} - -__code struct ao_cmds ao_packet_slave_cmds[] = { - { 's', ao_packet_slave_control, "s Remote packet link slave" }, - { 0, ao_packet_slave_control, NULL }, -}; -#endif - void ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); -#ifdef PACKET_HAS_SLAVE_CMD - ao_cmd_register(&ao_packet_slave_cmds[0]); -#endif } diff --git a/src/ao_pins.h b/src/ao_pins.h index 5a0b4318..e9a265b0 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -41,8 +41,7 @@ #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 1 - #define PACKET_HAS_SLAVE_CMD 1 + #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) -- cgit v1.2.3 From f7ff3278bb670df59d7425a014cfe8e3718fea3f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 00:44:42 -0700 Subject: Disable interrupts while reading from stdin With multiple input source support, there is a lag between asking a device if it has data and then waiting for more data to appear. If an interrupt signalling additional input arrives in this interval, we'll go to sleep with input available. This patch uses a big hammer by just disabling interrupts for the whole process. Signed-off-by: Keith Packard --- src/ao_stdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 8add30b8..045dff09 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -50,6 +50,7 @@ getchar(void) __reentrant char c; int8_t stdio = ao_cur_stdio; + EA = 0; for (;;) { c = stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) @@ -59,6 +60,7 @@ getchar(void) __reentrant if (stdio == ao_cur_stdio) ao_sleep(&ao_stdin_ready); } + EA = 1; ao_cur_stdio = stdio; return c; } -- cgit v1.2.3 From 45a1c2d2dfb69e5269ef2756fcd0f734b48d41cb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 5 May 2010 01:54:33 -0600 Subject: update changelogs for Debian build --- ChangeLog | 39 +++++++++++++++++++++++++++++++++++++++ debian/changelog | 12 ++++++++++++ 2 files changed, 51 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7094d996..873a2ab5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,42 @@ +commit f7ff3278bb670df59d7425a014cfe8e3718fea3f +Author: Keith Packard +Date: Wed May 5 00:44:42 2010 -0700 + + Disable interrupts while reading from stdin + + With multiple input source support, there is a lag between asking a + device if it has data and then waiting for more data to appear. If an + interrupt signalling additional input arrives in this interval, we'll + go to sleep with input available. + + This patch uses a big hammer by just disabling interrupts for the + whole process. + + Signed-off-by: Keith Packard + +commit aa9ff021d683764a43800eaa18ea0c9be5134939 +Author: Keith Packard +Date: Tue May 4 21:42:54 2010 -0700 + + Revert "Add optional 's' command to packet slave to enable/disable slave mode" + + This reverts commit e7dc7fab787df63a4de72c8450e94092eb04d7db. + + This patch didn't work, and magically appears to break flashing TM + from TD. + +commit 8c95f33686f69da717013ec2c25dbcd99c03aa45 +Author: Bdale Garbee +Date: Thu Apr 29 17:48:44 2010 -0600 + + more text created during SFO->DEN flight + +commit af0613ffc178b9b1f011c315923f92f2581fe53e +Author: Bdale Garbee +Date: Tue Apr 27 00:18:43 2010 -0600 + + update changelogs for Debian build + commit 99094f02bf4849ba1f6b9842ded6c39d894320f7 Merge: 641e76c 75d8ffd Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index be14fb89..b5734f6b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +altos (0.6+184+gf7ff327) unstable; urgency=low + + [ Bdale Garbee ] + * more text created during SFO->DEN flight + + [ Keith Packard ] + * Revert "Add optional 's' command to packet slave to enable/disable + slave mode" + * Disable interrupts while reading from stdin + + -- Bdale Garbee Wed, 05 May 2010 01:52:27 -0600 + altos (0.6+180+g99094f0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 01cefa181b04e53c20109ef8f3ffff633744da73 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 5 May 2010 01:56:51 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 873a2ab5..00e3e449 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 45a1c2d2dfb69e5269ef2756fcd0f734b48d41cb +Author: Bdale Garbee +Date: Wed May 5 01:54:33 2010 -0600 + + update changelogs for Debian build + commit f7ff3278bb670df59d7425a014cfe8e3718fea3f Author: Keith Packard Date: Wed May 5 00:44:42 2010 -0700 diff --git a/debian/changelog b/debian/changelog index b5734f6b..0650c9d4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+184+gf7ff327) unstable; urgency=low +altos (0.6+185+g45a1c2d) unstable; urgency=low [ Bdale Garbee ] * more text created during SFO->DEN flight -- cgit v1.2.3 From 8702f497c4278648303eced1aed5bd76d559521a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 5 May 2010 01:57:11 -0600 Subject: initial attempt at a telemetrum turn on script .. needs work --- ao-bringup/turnon_telemetrum | 48 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 ao-bringup/turnon_telemetrum diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum new file mode 100755 index 00000000..e4badcfd --- /dev/null +++ b/ao-bringup/turnon_telemetrum @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleMetrum v1.0 Turn-On and Calibration Program" +echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleMetrum v1.0 powered from USB" +echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from UHF to frequency counter" +echo +echo -n "TeleMetrum serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +$RAWLOAD -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` + +echo "Programming flash with cal value " $CAL_VALUE +$AOLOAD --cal $CAL_VALUE /usr/share/altos/telemetrum-v1.0.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From ff03cdf746b83542ebcca00d32e6cc69ccfc122d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 5 May 2010 01:57:54 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 00e3e449..682a78a7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 8702f497c4278648303eced1aed5bd76d559521a +Author: Bdale Garbee +Date: Wed May 5 01:57:11 2010 -0600 + + initial attempt at a telemetrum turn on script .. needs work + +commit 01cefa181b04e53c20109ef8f3ffff633744da73 +Author: Bdale Garbee +Date: Wed May 5 01:56:51 2010 -0600 + + update changelogs for Debian build + commit 45a1c2d2dfb69e5269ef2756fcd0f734b48d41cb Author: Bdale Garbee Date: Wed May 5 01:54:33 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 0650c9d4..dd97cb28 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,8 @@ -altos (0.6+185+g45a1c2d) unstable; urgency=low +altos (0.6+187+g8702f49) unstable; urgency=low [ Bdale Garbee ] * more text created during SFO->DEN flight + * initial attempt at a telemetrum turn on script .. needs work [ Keith Packard ] * Revert "Add optional 's' command to packet slave to enable/disable -- cgit v1.2.3 From e6bb80975fde20928a830170f0821d59a8c72690 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 01:31:57 -0700 Subject: Fix all stdio reading functions to be __critical Oh, right SDCC has '__critical' to mark sections of code that need to run with interrupts disabled; no need to use EA = 0 and EA = 1. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 2 +- src/ao_stdio.c | 4 +--- src/ao_usb.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index a499ce59..ef86fa28 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -18,7 +18,7 @@ #include "ao.h" static char -ao_packet_getchar(void) +ao_packet_getchar(void) __critical { char c; while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 045dff09..78bbd3c3 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -45,12 +45,11 @@ flush(void) __xdata uint8_t ao_stdin_ready; char -getchar(void) __reentrant +getchar(void) __reentrant __critical { char c; int8_t stdio = ao_cur_stdio; - EA = 0; for (;;) { c = stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) @@ -60,7 +59,6 @@ getchar(void) __reentrant if (stdio == ao_cur_stdio) ao_sleep(&ao_stdin_ready); } - EA = 1; ao_cur_stdio = stdio; return c; } diff --git a/src/ao_usb.c b/src/ao_usb.c index 527e9b30..e4af8e45 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -395,7 +395,7 @@ ao_usb_pollchar(void) __critical } char -ao_usb_getchar(void) +ao_usb_getchar(void) __critical { char c; -- cgit v1.2.3 From 8b6767e24a88482dbd3d4c4c969a0be08917d22b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 01:32:46 -0700 Subject: Use ao_delay to sleep for 2 seconds instead of trying ao_sleep ao_sleep doesn't delay for a specified time interval as much as one might want it to. --- src/ao_cmd.c | 2 +- src/ao_reboot.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ao_cmd.c b/src/ao_cmd.c index b6d2b886..4a68fba4 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -208,7 +208,7 @@ ao_reboot(void) if (!ao_match_word("eboot")) return; WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_sleep(AO_SEC_TO_TICKS(2)); + ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); } diff --git a/src/ao_reboot.c b/src/ao_reboot.c index 82ea32e0..8c47b893 100644 --- a/src/ao_reboot.c +++ b/src/ao_reboot.c @@ -23,6 +23,6 @@ void ao_reboot(void) { WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; - ao_sleep(AO_SEC_TO_TICKS(2)); + ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); } -- cgit v1.2.3 From fa77db2ffd8a749c93767db5a6311131e00473ae Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 5 May 2010 02:34:41 -0600 Subject: update changelogs for Debian build --- ChangeLog | 26 ++++++++++++++++++++++++++ debian/changelog | 8 ++++++++ 2 files changed, 34 insertions(+) diff --git a/ChangeLog b/ChangeLog index 682a78a7..5fcf8d70 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +commit 8b6767e24a88482dbd3d4c4c969a0be08917d22b +Author: Keith Packard +Date: Wed May 5 01:32:46 2010 -0700 + + Use ao_delay to sleep for 2 seconds instead of trying ao_sleep + + ao_sleep doesn't delay for a specified time interval as much as one + might want it to. + +commit e6bb80975fde20928a830170f0821d59a8c72690 +Author: Keith Packard +Date: Wed May 5 01:31:57 2010 -0700 + + Fix all stdio reading functions to be __critical + + Oh, right SDCC has '__critical' to mark sections of code that need to + run with interrupts disabled; no need to use EA = 0 and EA = 1. + + Signed-off-by: Keith Packard + +commit ff03cdf746b83542ebcca00d32e6cc69ccfc122d +Author: Bdale Garbee +Date: Wed May 5 01:57:54 2010 -0600 + + update changelogs for Debian build + commit 8702f497c4278648303eced1aed5bd76d559521a Author: Bdale Garbee Date: Wed May 5 01:57:11 2010 -0600 diff --git a/debian/changelog b/debian/changelog index dd97cb28..7d9ad670 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,11 @@ +altos (0.6+190+g8b6767e) unstable; urgency=low + + [ Keith Packard ] + * Fix all stdio reading functions to be __critical + * Use ao_delay to sleep for 2 seconds instead of trying ao_sleep + + -- Bdale Garbee Wed, 05 May 2010 02:34:06 -0600 + altos (0.6+187+g8702f49) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 823fc0ac27b8df9b4ba1ca0f229b431baf5b46dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 12:50:39 -0700 Subject: Don't change dbg clock while changing reset_n. Use 20ms everywhere This changes the reset code to be more conservative about changing things at the same time, and also sets all timings to 20ms to make debugging with the scope easier. Signed-off-by: Keith Packard --- src/ao_dbg.c | 54 +++++++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index e7fbd7ad..2988aed4 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -175,54 +175,30 @@ ao_dbg_set_pins(void) DBG_PORT_DIR &= ~DBG_DATA; } -static void -ao_dbg_long_delay(void) -{ - uint8_t n; - - for (n = 0; n < 20; n++) - _asm nop _endasm; -} - -#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) -#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) +#define ao_reset_delay() ao_delay(AO_MS_TO_TICKS(20)) void ao_dbg_debug_mode(void) { - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); + ao_dbg_set_pins(); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); } void ao_dbg_reset(void) { - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); + ao_dbg_set_pins(); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); } static void -- cgit v1.2.3 From 8be04df7e1e0a369ffb1137c6e2ec63585e3c935 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 6 May 2010 12:48:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 25 +++++++++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5fcf8d70..b65681ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +commit 314d27a73c903fef2968dabac3d5313573713460 +Merge: fa77db2 823fc0a +Author: Bdale Garbee +Date: Thu May 6 12:47:30 2010 -0600 + + Merge remote branch 'remotes/origin/fix-reset' + +commit 823fc0ac27b8df9b4ba1ca0f229b431baf5b46dd +Author: Keith Packard +Date: Wed May 5 12:50:39 2010 -0700 + + Don't change dbg clock while changing reset_n. Use 20ms everywhere + + This changes the reset code to be more conservative about changing + things at the same time, and also sets all timings to 20ms to make + debugging with the scope easier. + + Signed-off-by: Keith Packard + +commit fa77db2ffd8a749c93767db5a6311131e00473ae +Author: Bdale Garbee +Date: Wed May 5 02:34:41 2010 -0600 + + update changelogs for Debian build + commit 8b6767e24a88482dbd3d4c4c969a0be08917d22b Author: Keith Packard Date: Wed May 5 01:32:46 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 7d9ad670..5f037f2d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+193+g314d27a) unstable; urgency=low + + [ Keith Packard ] + * Don't change dbg clock while changing reset_n. Use 20ms everywhere + + -- Bdale Garbee Thu, 06 May 2010 12:47:51 -0600 + altos (0.6+190+g8b6767e) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From cde60f16f6ab2cdd5010a0e106ae312d144947cf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 6 May 2010 13:58:31 -0600 Subject: Revert "Merge remote branch 'remotes/origin/fix-reset'" This reverts commit 314d27a73c903fef2968dabac3d5313573713460, reversing changes made to fa77db2ffd8a749c93767db5a6311131e00473ae. For whatever reason, this is utterly not doing the right things today! --- src/ao_dbg.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 2988aed4..e7fbd7ad 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -175,30 +175,54 @@ ao_dbg_set_pins(void) DBG_PORT_DIR &= ~DBG_DATA; } -#define ao_reset_delay() ao_delay(AO_MS_TO_TICKS(20)) +static void +ao_dbg_long_delay(void) +{ + uint8_t n; + + for (n = 0; n < 20; n++) + _asm nop _endasm; +} + +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) void ao_dbg_debug_mode(void) { - ao_dbg_set_pins(); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); } void ao_dbg_reset(void) { - ao_dbg_set_pins(); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); } static void -- cgit v1.2.3 From 53b9a9bc28a9278249ff37f92110c21380e93cda Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 6 May 2010 13:59:23 -0600 Subject: update changelogs for Debian build --- ChangeLog | 17 +++++++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 23 insertions(+) diff --git a/ChangeLog b/ChangeLog index b65681ad..42b8155d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +commit cde60f16f6ab2cdd5010a0e106ae312d144947cf +Author: Bdale Garbee +Date: Thu May 6 13:58:31 2010 -0600 + + Revert "Merge remote branch 'remotes/origin/fix-reset'" + + This reverts commit 314d27a73c903fef2968dabac3d5313573713460, reversing + changes made to fa77db2ffd8a749c93767db5a6311131e00473ae. + + For whatever reason, this is utterly not doing the right things today! + +commit 8be04df7e1e0a369ffb1137c6e2ec63585e3c935 +Author: Bdale Garbee +Date: Thu May 6 12:48:00 2010 -0600 + + update changelogs for Debian build + commit 314d27a73c903fef2968dabac3d5313573713460 Merge: fa77db2 823fc0a Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 5f037f2d..a0790bf6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+195+gcde60f1) unstable; urgency=low + + * Revert "Merge remote branch 'remotes/origin/fix-reset'" + + -- Bdale Garbee Thu, 06 May 2010 13:59:16 -0600 + altos (0.6+193+g314d27a) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 1b8671bd0a00cec6ae4ccf442cd007b18af82fb0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 9 May 2010 01:41:00 -0600 Subject: lots of updates --- doc/telemetrum.xsl | 184 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 164 insertions(+), 20 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 793347f9..26634d1a 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -125,7 +125,7 @@ Handling Precautions TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver extraordinary results. + properly installed in an airframe, it will deliver impressive results. However, like all electronic devices, there are some precautions you must take. @@ -182,9 +182,9 @@
By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard e-matches - from companies like [insert company and product names for e-matches we've - tried and like] and with Quest Q2G2 igniters. However, if you + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you want or need to use a separate pyro battery, you can do so by adding a second 2mm connector to position B2 on the board and cutting the thick pcb trace connecting the LiPo battery to the pyro circuit between @@ -203,7 +203,7 @@ connectors. If the airframe will not support this much height or if you want to be able to directly attach e-match leads to the board, we offer a screw terminal block. This is very similar to what most other - altimeter vendors provide by default and so may be the most familiar + altimeter vendors provide and so may be the most familiar option. You'll need a very small straight blade screwdriver to connect and disconnect the board in this case, such as you might find in a jeweler's screwdriver set. Finally, you can forego both options and @@ -234,23 +234,31 @@ if the rocket is more or less horizontal, the firmware instead enters idle mode. + + At power on, you will hear three beeps ("S" in Morse code for startup) + and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. + In flight mode, TeleMetrum turns on the GPS system, engages the flight state machine, goes into transmit-only mode on the RF link sending telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" on the beeper, followed by + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates [FIXME] apogee continuity, two beeps indicate + One beep indicates apogee continuity, two beeps indicate main continuity, three beeps indicate both apogee and main continuity, and one longer "brap" sound indicates no continuity. For a dual deploy flight, make sure you're getting three beeps before launching! For apogee-only or motor eject flights, do what makes sense. - In idle mode, the normal flight state machine is disengaged, and thus + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus no ejection charges will fire. TeleMetrum also listens on the RF link when in idle mode for packet mode requests sent from TeleDongle. - Commands can thus be issues to a TeleMetrum in idle mode over either + Commands can be issued to a TeleMetrum in idle mode over either USB or the RF link equivalently. Idle mode is useful for configuring TeleMetrum, for extracting data from the on-board storage chip after flight, and for ground testing @@ -312,14 +320,23 @@ P command from a safe distance. You can now command TeleMetrum to fire the apogee or main charges to complete your testing. + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. +
Radio Link The chip our boards are based on incorporates an RF transceiver, but it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we have to decide how to manage the - link... + receiving at any given moment. So we had to decide how to manage the + link. By design, TeleMetrum firmware listens for an RF connection when @@ -336,22 +353,149 @@ We don't use a 'normal packet radio' mode because they're just too - inefficient. GFSK is just FSK with the baseband pulses passed through a + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a Gaussian filter before they go into the modulator to limit the transmitted bandwidth. When combined with the hardware forward error correction support in the cc1111 chip, this allows us to have a very robust 38.4 kilobit data link with only 10 milliwatts of transmit power, a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had a test flight above 12k AGL with good reception, and my calculations - say we should be good to 40k AGL or more with just a 5-element yagi on - the ground. I expect to push 30k with a 54mm minimum airframe I'm - working on now, so we'll hopefully have further practical confirmation - of our link margin in a few months. - - - Placeholder. + had a test flight above 12k AGL with good reception, and calculations + suggest we should be good to 40k AGL or more with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights!
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. + +
+ Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Main Deployment Altitude + + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. + + + To set the main deployment altitude, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+
+ Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor. + +
+
Using Altus Metrum Products -- cgit v1.2.3 From 3cc1dad3b497524ffef61190dd68908cb19e8c35 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 16:28:35 -0600 Subject: add initial package build scripts for Arch Linux from Bob Finch --- contrib/arch-linux/PKGBUILD-git.altos | 53 ++++++++++++++++++++++++++++++++++ contrib/arch-linux/PKGBUILD-git.nickle | 43 +++++++++++++++++++++++++++ contrib/arch-linux/README | 5 ++++ 3 files changed, 101 insertions(+) create mode 100644 contrib/arch-linux/PKGBUILD-git.altos create mode 100644 contrib/arch-linux/PKGBUILD-git.nickle create mode 100644 contrib/arch-linux/README diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos new file mode 100644 index 00000000..f0fe45fa --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -0,0 +1,53 @@ +# Contributor: Bob Finch +pkgname=altos-git +pkgver=VERSION +pkgrel=1 +pkgdesc="Software solutions for high powered rocketry avionics" +arch=('i686' 'x86_64') +url="http://www.altusmetrum.org/AltOS/" +license=('GPL') +depends=('openssl>=1.0.0' 'libusb-BETA' 'plplot-svn' 'sdcc' 'nickle' 'flite' 'kernel26>=2.6.33') +makedepends=('git') +optdepends=('uucp: cu is included and is a bare boned terminal to serial program' + 'cutemon: gui-based minimal terminal to serial program' + 'google-earth: useful for viewing the kml files of the flight path' + 'docbook-xsl: for making an html doc file from the xsl source' + 'fop: for making a pdf doc file from the xsl source') +source=(altos.desktop) +md5sums=('7308c5b015991046b195d1a2c0987004') + +_gitroot="git://git.gag.com/fw/altos" +_gitname="altos" + +build() { + cd "$srcdir" +# msg "Connecting to GIT server...." + + if [ -d $_gitname ] ; then + cd $_gitname && git pull origin +# msg "The local files are updated." + else + git clone $_gitroot + fi + +# msg "GIT checkout done or server timeout" +# msg "Starting make..." + + rm -rf "$srcdir/$_gitname-build" + git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build" + cd "$srcdir/$_gitname-build" + + # + # BUILD HERE + # + + ./autogen.sh + ./configure --prefix=/usr + make || return 1 + make DESTDIR="$pkgdir/" install + + mkdir -p $startdir/pkg/usr/share/pixmaps + mkdir -p $startdir/pkg/usr/share/applications + install -m644 debian/*.xpm $startdir/pkg/usr/share/pixmaps + install -m644 ../*.desktop $startdir/pkg/usr/share/applications +} diff --git a/contrib/arch-linux/PKGBUILD-git.nickle b/contrib/arch-linux/PKGBUILD-git.nickle new file mode 100644 index 00000000..2f1515ea --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.nickle @@ -0,0 +1,43 @@ +# Contributor: Bob Finch +pkgname=nickle-git +pkgver=20100507 +pkgrel=1 +pkgdesc="A desk calculator language with powerful programming and scripting capabilities." +arch=('i686' 'x86_64') +url="http://keithp.com/git-repository/" +license=('custom') +makedepends=('git') + +_gitroot="git://keithp.com/git/nickle" +_gitname="nickle" + +build() { + cd "$srcdir" +# msg "Connecting to GIT server...." + + if [ -d $_gitname ] ; then + cd $_gitname && git pull origin +# msg "The local files are updated." + else + git clone $_gitroot + fi + +# msg "GIT checkout done or server timeout" +# msg "Starting make..." + + rm -rf "$srcdir/$_gitname-build" + git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build" + cd "$srcdir/$_gitname-build" + + # + # BUILD HERE + # + + ./autogen.sh + ./configure --prefix=/usr + make || return 1 + make DESTDIR="$pkgdir/" install + + install -D -m 644 $startdir/src/COPYING\ + $startdir/pkg/usr/share/licenses/$pkgname/COPYING.txt +} diff --git a/contrib/arch-linux/README b/contrib/arch-linux/README new file mode 100644 index 00000000..5282d4f4 --- /dev/null +++ b/contrib/arch-linux/README @@ -0,0 +1,5 @@ +These files were contributed by Bob Finch , and demonstrate +how to build packages for the Arch Linux distribution: + + http://www.archlinux.org/ + -- cgit v1.2.3 From 9d3d09578381bb6e6f88c39b0e945371bbc22c5a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 16:34:49 -0600 Subject: add desktop file provided by Bob Finch --- debian/altos.install | 1 + debian/dirs | 1 + 2 files changed, 2 insertions(+) diff --git a/debian/altos.install b/debian/altos.install index 57f9b02a..8d8a1987 100644 --- a/debian/altos.install +++ b/debian/altos.install @@ -1,3 +1,4 @@ +debian/altos.desktop usr/share/applications debian/altos.list etc/apt/sources.list.d src/*.ihx usr/share/altos src/*.map usr/share/altos diff --git a/debian/dirs b/debian/dirs index 3a4a3418..29840efb 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,4 +1,5 @@ etc/apt/sources.list.d usr/bin usr/share/altos +usr/share/applications usr/share/pixmaps -- cgit v1.2.3 From 68eaaa694bb7bf20642ad11eac8a13c1c8e21b7d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 16:44:14 -0600 Subject: add desktop file --- debian/altos.desktop | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 debian/altos.desktop diff --git a/debian/altos.desktop b/debian/altos.desktop new file mode 100644 index 00000000..d43f9a28 --- /dev/null +++ b/debian/altos.desktop @@ -0,0 +1,12 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=AltOS-View +GenericName=TeleMetrum-telemetry-viewer +Comment=View and log downlink data from TeleMetrum +Exec=/usr/bin/ao-view %f +Terminal=false +MultipleArgs=false +Type=Application +Icon=/usr/share/pixmaps/altusmetrum.xpm +Categories=Application;Network +MimeType=text/plain -- cgit v1.2.3 From 7191d74e680a63728f5eb139069a674fef969e6c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 16:45:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 30 ++++++++++++++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 37 insertions(+) diff --git a/ChangeLog b/ChangeLog index 42b8155d..84929a2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +commit 68eaaa694bb7bf20642ad11eac8a13c1c8e21b7d +Author: Bdale Garbee +Date: Wed May 12 16:44:14 2010 -0600 + + add desktop file + +commit 9d3d09578381bb6e6f88c39b0e945371bbc22c5a +Author: Bdale Garbee +Date: Wed May 12 16:34:49 2010 -0600 + + add desktop file provided by Bob Finch + +commit 3cc1dad3b497524ffef61190dd68908cb19e8c35 +Author: Bdale Garbee +Date: Wed May 12 16:28:35 2010 -0600 + + add initial package build scripts for Arch Linux from Bob Finch + +commit 1b8671bd0a00cec6ae4ccf442cd007b18af82fb0 +Author: Bdale Garbee +Date: Sun May 9 01:41:00 2010 -0600 + + lots of updates + +commit 53b9a9bc28a9278249ff37f92110c21380e93cda +Author: Bdale Garbee +Date: Thu May 6 13:59:23 2010 -0600 + + update changelogs for Debian build + commit cde60f16f6ab2cdd5010a0e106ae312d144947cf Author: Bdale Garbee Date: Thu May 6 13:58:31 2010 -0600 diff --git a/debian/changelog b/debian/changelog index a0790bf6..0d1cfd44 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+200+g68eaaa6) unstable; urgency=low + + * add initial package build scripts for Arch Linux from Bob Finch + * add desktop file provided by Bob Finch + + -- Bdale Garbee Wed, 12 May 2010 16:44:27 -0600 + altos (0.6+195+gcde60f1) unstable; urgency=low * Revert "Merge remote branch 'remotes/origin/fix-reset'" -- cgit v1.2.3 From ae6854df00579ea1c3486f1bf8f19443d5ac9498 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 17:04:13 -0600 Subject: update desktop file for conformance with current standards --- debian/altos.desktop | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/debian/altos.desktop b/debian/altos.desktop index d43f9a28..8fa1247e 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -1,12 +1,10 @@ [Desktop Entry] -Encoding=UTF-8 -Name=AltOS-View -GenericName=TeleMetrum-telemetry-viewer +Type=Application +Name="AltOS View" +GenericName="TeleMetrum Telemetry Viewer" Comment=View and log downlink data from TeleMetrum +Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/ao-view %f Terminal=false -MultipleArgs=false -Type=Application -Icon=/usr/share/pixmaps/altusmetrum.xpm -Categories=Application;Network -MimeType=text/plain +MimeType=text/plain; +Categories=Viewer;Network; -- cgit v1.2.3 From d639144b9bb840fbbced199738787ec054eddf12 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 17:04:41 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 84929a2e..ec0e1f77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit ae6854df00579ea1c3486f1bf8f19443d5ac9498 +Author: Bdale Garbee +Date: Wed May 12 17:04:13 2010 -0600 + + update desktop file for conformance with current standards + +commit 7191d74e680a63728f5eb139069a674fef969e6c +Author: Bdale Garbee +Date: Wed May 12 16:45:00 2010 -0600 + + update changelogs for Debian build + commit 68eaaa694bb7bf20642ad11eac8a13c1c8e21b7d Author: Bdale Garbee Date: Wed May 12 16:44:14 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 0d1cfd44..027877e5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+202+gae6854d) unstable; urgency=low + + * update desktop file for conformance with current standards + + -- Bdale Garbee Wed, 12 May 2010 17:04:31 -0600 + altos (0.6+200+g68eaaa6) unstable; urgency=low * add initial package build scripts for Arch Linux from Bob Finch -- cgit v1.2.3 From 6bd85138c1bfbc1d8b78dce1501870a65a64db36 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 19:53:40 -0600 Subject: lose the quotes since they apparently aren't necessary --- debian/altos.desktop | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/altos.desktop b/debian/altos.desktop index 8fa1247e..ae9bdc63 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Type=Application -Name="AltOS View" -GenericName="TeleMetrum Telemetry Viewer" +Name=AltOS View +GenericName=TeleMetrum Telemetry Viewer Comment=View and log downlink data from TeleMetrum Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/ao-view %f -- cgit v1.2.3 From 0f05cf06e3f1ec510b11d993d9038211ac66c97b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 12 May 2010 19:54:04 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index ec0e1f77..63cba5ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 6bd85138c1bfbc1d8b78dce1501870a65a64db36 +Author: Bdale Garbee +Date: Wed May 12 19:53:40 2010 -0600 + + lose the quotes since they apparently aren't necessary + +commit d639144b9bb840fbbced199738787ec054eddf12 +Author: Bdale Garbee +Date: Wed May 12 17:04:41 2010 -0600 + + update changelogs for Debian build + commit ae6854df00579ea1c3486f1bf8f19443d5ac9498 Author: Bdale Garbee Date: Wed May 12 17:04:13 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 027877e5..71dc6f59 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+204+g6bd8513) unstable; urgency=low + + * lose the quotes since they apparently aren't necessary + + -- Bdale Garbee Wed, 12 May 2010 19:53:58 -0600 + altos (0.6+202+gae6854d) unstable; urgency=low * update desktop file for conformance with current standards -- cgit v1.2.3 From f0433c83d76e90d78fb86a1f4a2f145f3c57fb25 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 13 May 2010 01:27:39 -0600 Subject: updates from Bob --- contrib/arch-linux/PKGBUILD-git.altos | 20 ++++++++++++++++---- contrib/arch-linux/PKGBUILD-git.nickle | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos index f0fe45fa..88590d98 100644 --- a/contrib/arch-linux/PKGBUILD-git.altos +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -1,6 +1,6 @@ # Contributor: Bob Finch pkgname=altos-git -pkgver=VERSION +pkgver=20100507 pkgrel=1 pkgdesc="Software solutions for high powered rocketry avionics" arch=('i686' 'x86_64') @@ -13,8 +13,6 @@ optdepends=('uucp: cu is included and is a bare boned terminal to serial program 'google-earth: useful for viewing the kml files of the flight path' 'docbook-xsl: for making an html doc file from the xsl source' 'fop: for making a pdf doc file from the xsl source') -source=(altos.desktop) -md5sums=('7308c5b015991046b195d1a2c0987004') _gitroot="git://git.gag.com/fw/altos" _gitname="altos" @@ -49,5 +47,19 @@ build() { mkdir -p $startdir/pkg/usr/share/pixmaps mkdir -p $startdir/pkg/usr/share/applications install -m644 debian/*.xpm $startdir/pkg/usr/share/pixmaps - install -m644 ../*.desktop $startdir/pkg/usr/share/applications + install -m644 debian/*.desktop $startdir/pkg/usr/share/applications + + # + # OPTIONAL DOC BUILD - *** UNCOMMENT TO INSTALL DOCUMENTATION + # + +# xsltproc -o telemetrum.html /usr/share/xml/docbook/xsl-stylesheets-1.74.0/html/docbook.xsl\ +# doc/telemetrum.xml +# xsltproc -o telemetrum.fo /usr/share/xml/docbook/xsl-stylesheets-1.74.0/fo/docbook.xsl\ +# doc/telemetrum.xml +# fop -fo telemetrum.fo -pdf telemetrum.pd +# +# mkdir -p $startdir/pkg/usr/share/altos/doc +# install -m 644 *.html $startdir/pkg/usr/share/altos/doc/ +# install -m 644 *.pdf $startdir/pkg/usr/share/altos/doc/ } diff --git a/contrib/arch-linux/PKGBUILD-git.nickle b/contrib/arch-linux/PKGBUILD-git.nickle index 2f1515ea..9ed65466 100644 --- a/contrib/arch-linux/PKGBUILD-git.nickle +++ b/contrib/arch-linux/PKGBUILD-git.nickle @@ -38,6 +38,6 @@ build() { make || return 1 make DESTDIR="$pkgdir/" install - install -D -m 644 $startdir/src/COPYING\ - $startdir/pkg/usr/share/licenses/$pkgname/COPYING.txt + install -D -m 644 COPYING\ + $startdir/pkg/usr/share/licenses/nickle/COPYING.txt } -- cgit v1.2.3 From 3c2211ad7877d622435bc9e8c9c0b01d62be6ff0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 13 May 2010 15:37:37 -0600 Subject: typo fix from Bob --- contrib/arch-linux/PKGBUILD-git.altos | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos index 88590d98..6fa82a36 100644 --- a/contrib/arch-linux/PKGBUILD-git.altos +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -57,7 +57,7 @@ build() { # doc/telemetrum.xml # xsltproc -o telemetrum.fo /usr/share/xml/docbook/xsl-stylesheets-1.74.0/fo/docbook.xsl\ # doc/telemetrum.xml -# fop -fo telemetrum.fo -pdf telemetrum.pd +# fop -fo telemetrum.fo -pdf telemetrum.pdf # # mkdir -p $startdir/pkg/usr/share/altos/doc # install -m 644 *.html $startdir/pkg/usr/share/altos/doc/ -- cgit v1.2.3 From cc002c0a43a02845ba67d1a61828be382f307b2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 May 2010 22:31:23 -0700 Subject: Fix telemetrum.inf, tested by Adrian and Keithp --- telemetrum.inf | 57 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/telemetrum.inf b/telemetrum.inf index 4549cfba..8a12b857 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -3,31 +3,42 @@ [Version] Signature = "$Windows NT$" -Class = Ports -ClassGUID = {4d36e978-e325-11ce-bfc1-08002be10318} +Class = Modem +ClassGUID ={4D36E96D-E325-11CE-BFC1-08002BE10318} Provider = %Mfg% -DriverVer = 30/03/2010,4.0.0.8 +DriverVer = 08/05/2010,3.1.0.41 [Manufacturer] -%Mfg% = Models +%Mfg% = Models, NTx86, NTamd64, NTia64 -[Models] -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +[Models.NTx86] +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A + +[Models.NTamd64] +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A + +[Models.NTia64] +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A [DestinationDirs] -DefaultDestDir = 12 +DefaultDestDir=12 [ControlFlags] -ExcludeFromSelect=USB\VID_0BAF&PID_0303 +ExcludeFromSelect=USB\VID_FFFE&PID_000A [Strings] Mfg = "altusmetrum.org" -TeleMetrum = "TeleMetrum/TeleDongle" +TeleMetrum = "TeleMetrum/TeleDongle" + + +;---------------------------------------------------------------------------- +; Installation sections +;---------------------------------------------------------------------------- [TELEMETRUM.NT] include=mdmcpq.inf CopyFiles=FakeModemCopyFileSection -AddReg=Uninstall +AddReg = All, mfglt, Modem.AddReg, VerboseResultCodes, Uninstall.AddReg [TELEMETRUM.NT.HW] Include=mdmcpq.inf @@ -37,6 +48,30 @@ AddReg=LowerFilterAddReg Include=mdmcpq.inf AddService=usbser, 0x00000000, LowerFilter_Service_Inst -[Uninstall] + +;---------------------------------------------------------------------------- +; AddReg sections +;---------------------------------------------------------------------------- +[Modem.AddReg] +HKR,, Properties, 1, C0,01,00,00, 00,00,00,00, FF,00,00,00, 07,00,00,00, 0F,00,00,00, F7,0F,00,00, 00,84,03,00, C0,DA,00,00 + + +;---------------------------------------------------------------------------- +; Common Registry Sections +; +; The [All] section is installed for all modems. +; +;---------------------------------------------------------------------------- +[All] +HKR,,FriendlyDriver,,Unimodem.vxd +HKR,,DevLoader,,*vcomm +HKR,,PortSubClass,1,02 +HKR,,ConfigDialog,,modemui.dll +HKR,,EnumPropPages,,"modemui.dll,EnumPropPages" +HKR,,DeviceType,1,01 +HKR,,OCM2KXP,1,01 +HKR,, DCB, 1, 1c,00,00,00, 00,C2,01,00, 15,20,00,00, 00,00, 0a,00, 0a,00, 08, 00, 00, 11, 13, 00, 00, 00 + +[Uninstall.AddReg] HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TeleMetrum%,DisplayName,,"%TeleMetrum%" -- cgit v1.2.3 From 563a9dcdfef42718370c49f16cc2271642b3e055 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 May 2010 21:30:57 -0700 Subject: Finish basic flight monitoring UI with voice using FreeTTS This captures telemetry data to log files and presents flight status information in audio form using FreeTTS. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFile.java | 37 ++++++++ ao-tools/altosui/AltosLog.java | 104 ++++++++++++++++++++++ ao-tools/altosui/AltosPreferences.java | 117 +++++++++++++++++++++++++ ao-tools/altosui/AltosState.java | 9 +- ao-tools/altosui/AltosUI.java | 152 ++++++++++++++++++--------------- ao-tools/altosui/AltosVoice.java | 69 +++++++++++++++ ao-tools/altosui/Makefile | 5 +- ao-tools/altosui/voices.txt | 1 + 8 files changed, 415 insertions(+), 79 deletions(-) create mode 100644 ao-tools/altosui/AltosFile.java create mode 100644 ao-tools/altosui/AltosLog.java create mode 100644 ao-tools/altosui/AltosPreferences.java create mode 100644 ao-tools/altosui/AltosVoice.java create mode 100644 ao-tools/altosui/voices.txt diff --git a/ao-tools/altosui/AltosFile.java b/ao-tools/altosui/AltosFile.java new file mode 100644 index 00000000..c7ee8679 --- /dev/null +++ b/ao-tools/altosui/AltosFile.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.File; +import java.util.*; +import altosui.AltosTelemetry; +import altosui.AltosPreferences; + +class AltosFile extends File { + public AltosFile(AltosTelemetry telem) { + super (AltosPreferences.logdir(), + String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + Calendar.getInstance().get(Calendar.YEAR), + Calendar.getInstance().get(Calendar.MONTH), + Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + telem.serial, + telem.flight, + "telem")); + } +} diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java new file mode 100644 index 00000000..ec868b9c --- /dev/null +++ b/ao-tools/altosui/AltosLog.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.lang.*; +import java.util.*; +import java.text.ParseException; +import java.util.concurrent.LinkedBlockingQueue; +import altosui.AltosSerial; +import altosui.AltosFile; + +/* + * This creates a thread to capture telemetry data and write it to + * a log file + */ +class AltosLog implements Runnable { + + LinkedBlockingQueue input_queue; + LinkedBlockingQueue pending_queue; + int serial; + int flight; + FileWriter log_file; + Thread log_thread; + + void close() throws IOException { + if (log_file != null) + log_file.close(); + } + + boolean open (AltosTelemetry telem) throws IOException { + AltosFile a = new AltosFile(telem); + + log_file = new FileWriter(a, true); + if (log_file != null) { + while (!pending_queue.isEmpty()) { + try { + String s = pending_queue.take(); + log_file.write(s); + log_file.write('\n'); + } catch (InterruptedException ie) { + } + } + log_file.flush(); + } + return log_file != null; + } + + public void run () { + try { + for (;;) { + String line = input_queue.take(); + try { + AltosTelemetry telem = new AltosTelemetry(line); + if (telem.serial != serial || telem.flight != flight || log_file == null) { + close(); + serial = telem.serial; + flight = telem.flight; + open(telem); + } + } catch (ParseException pe) { + } + if (log_file != null) { + log_file.write(line); + log_file.write('\n'); + log_file.flush(); + } else + pending_queue.put(line); + } + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + try { + close(); + } catch (IOException ie) { + } + } + + public AltosLog (AltosSerial s) { + pending_queue = new LinkedBlockingQueue (); + input_queue = new LinkedBlockingQueue (); + s.add_monitor(input_queue); + serial = -1; + flight = -1; + log_file = null; + log_thread = new Thread(this); + log_thread.start(); + } +} diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java new file mode 100644 index 00000000..0296d935 --- /dev/null +++ b/ao-tools/altosui/AltosPreferences.java @@ -0,0 +1,117 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.awt.Component; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; + +class AltosPreferences { + static Preferences preferences; + + /* logdir preference name */ + final static String logdirPreference = "LOGDIR"; + + /* Default logdir is ~/TeleMetrum */ + final static String logdirName = "TeleMetrum"; + + /* UI Component to pop dialogs up */ + static Component component; + + /* Log directory */ + static File logdir; + + public static void init(Component ui) { + preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + + component = ui; + + /* Initialize logdir from preferences */ + String logdir_string = preferences.get(logdirPreference, null); + if (logdir_string != null) + logdir = new File(logdir_string); + else { + /* Use the file system view default directory */ + logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); + if (!logdir.exists()) + logdir.mkdirs(); + } + } + + static void flush_preferences() { + try { + preferences.flush(); + } catch (BackingStoreException ee) { + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + } + } + + public static void set_logdir(File new_logdir) { + logdir = new_logdir; + synchronized (preferences) { + preferences.put(logdirPreference, logdir.getPath()); + flush_preferences(); + } + } + + private static boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + } else if (!dir.isDirectory()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + public static void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + + public static File logdir() { + return logdir; + } +} diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 192011d0..59a1999e 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -29,7 +29,7 @@ public class AltosState { /* derived data */ - double report_time; + long report_time; double time_change; int tick; @@ -66,11 +66,6 @@ public class AltosState { int speak_tick; double speak_altitude; - static double - aoview_time() - { - return System.currentTimeMillis() / 1000.0; - } void init (AltosTelemetry cur, AltosState prev_state) { int i; @@ -82,7 +77,7 @@ public class AltosState { ground_altitude = AltosConvert.cc_barometer_to_altitude(data.ground_pres); height = AltosConvert.cc_barometer_to_altitude(data.flight_pres) - ground_altitude; - report_time = aoview_time(); + report_time = System.currentTimeMillis(); accel_counts_per_mss = ((data.accel_minus_g - data.accel_plus_g) / 2.0) / 9.80665; acceleration = (data.ground_accel - data.flight_accel) / accel_counts_per_mss; diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 2952fcc0..43c40799 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -34,6 +34,9 @@ import altosui.AltosSerialMonitor; import altosui.AltosTelemetry; import altosui.AltosState; import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; @@ -128,7 +131,8 @@ public class AltosUI extends JFrame { private AltosFlightInfoTableModel[] flightInfoModel; private JTable[] flightInfo; - private AltosSerial serialLine; + private AltosSerial serial_line; + private AltosLog altos_log; private Box[] ibox; private Box vbox; private Box hbox; @@ -137,11 +141,15 @@ public class AltosUI extends JFrame { private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + public AltosVoice voice = new AltosVoice(); + public AltosUI() { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; + AltosPreferences.init(this); + vbox = Box.createVerticalBox(); this.add(vbox); @@ -188,7 +196,8 @@ public class AltosUI extends JFrame { createMenu(); - serialLine = new AltosSerial(); + serial_line = new AltosSerial(); + altos_log = new AltosLog(serial_line); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 20, statusHeight * 4 + infoHeight * 17)); @@ -333,63 +342,76 @@ public class AltosUI extends JFrame { info_finish(); } - /* User Preferences */ - Preferences altosui_preferences = Preferences.userNodeForPackage(this.getClass()); - - /* Log directory */ - private File logdir = null; + class IdleThread extends Thread { - /* logdir preference name */ - final static String logdirPreference = "LOGDIR"; + private AltosState state; - /* Default logdir is ~/TeleMetrum */ - final static String logdirName = "TeleMetrum"; - - /* Initialize logdir from preferences */ - { - String logdir_string = altosui_preferences.get(logdirPreference, null); - if (logdir_string != null) - logdir = new File(logdir_string); - else - /* a hack -- make the file chooser tell us what the default directory - * would be and stick our logdir in a subdirectory of that. - */ - logdir = new File(new JFileChooser().getCurrentDirectory(), logdirName); - } + public void run () { + int reported_landing = 0; - private void set_logdir(File new_logdir) { - logdir = new_logdir; - System.out.printf("Set logdir to %s\n", logdir.toString()); - synchronized (altosui_preferences) { - altosui_preferences.put(logdirPreference, logdir.getPath()); + state = null; try { - altosui_preferences.flush(); - } catch (BackingStoreException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - altosui_preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); + for (;;) { + Thread.sleep(10000); + if (state == null) + continue; + + /* reset the landing count once we hear about a new flight */ + if (state.state < AltosTelemetry.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) + continue; + + /* If the rocket isn't on the pad, then report height */ + if (state.state > AltosTelemetry.ao_flight_pad) { + voice.speak(String.format("%d meters", (int) (state.height + 0.5))); + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (!state.ascent && + (System.currentTimeMillis() - state.report_time > 10000 || + state.state == AltosTelemetry.ao_flight_landed)) + { + if (Math.abs(state.baro_speed) < 20 && state.height < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.gps != null) + voice.speak(String.format("bearing %d degrees, range %d meters", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5))); + ++reported_landing; + } + } + } catch (InterruptedException ie) { } } + + public void notice(AltosState new_state) { + state = new_state; + } } - private boolean check_dir(File dir) { - if (!dir.exists()) { - if (!dir.mkdirs()) { - JOptionPane.showMessageDialog(AltosUI.this, - dir.getName(), - "Cannot create directory", - JOptionPane.ERROR_MESSAGE); - return false; + private void tell(AltosState state, AltosState old_state) { + if (old_state == null || old_state.state != state.state) { + voice.speak(state.data.state); + switch (state.state) { + case AltosTelemetry.ao_flight_fast: + voice.speak(String.format("max speed %d meters per second", + (int) (state.max_speed + 0.5))); + break; + case AltosTelemetry.ao_flight_drogue: + voice.speak(String.format("max height %d meters", + (int) (state.max_height + 0.5))); + break; } - } else if (!dir.isDirectory()) { - JOptionPane.showMessageDialog(AltosUI.this, - dir.getName(), - "Is not a directory", - JOptionPane.ERROR_MESSAGE); - return false; } - return true; + old_state = state; } class DisplayThread extends Thread { @@ -402,16 +424,22 @@ public class AltosUI extends JFrame { public void run() { String line; AltosState state = null; + AltosState old_state = null; + IdleThread idle_thread = new IdleThread(); info_reset(); info_finish(); + idle_thread.start(); try { while ((line = read()) != null) { try { AltosTelemetry t = new AltosTelemetry(line); + old_state = state; state = new AltosState(t, state); update(state); show(state); + tell(state, old_state); + idle_thread.notice(state); } catch (ParseException pp) { System.out.printf("Parse error on %s\n", line); System.out.println("exception " + pp); @@ -420,6 +448,7 @@ public class AltosUI extends JFrame { } catch (InterruptedException ee) { } finally { close(); + idle_thread.interrupt(); } } } @@ -450,8 +479,8 @@ public class AltosUI extends JFrame { if (device != null) { try { - serialLine.connect(device.tty); - DeviceThread thread = new DeviceThread(serialLine); + serial_line.connect(device.tty); + DeviceThread thread = new DeviceThread(serial_line); run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, @@ -556,7 +585,7 @@ public class AltosUI extends JFrame { logfile_chooser.setDialogTitle("Select Telemetry File"); logfile_chooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); - logfile_chooser.setCurrentDirectory(logdir); + logfile_chooser.setCurrentDirectory(AltosPreferences.logdir()); int returnVal = logfile_chooser.showOpenDialog(AltosUI.this); if (returnVal == JFileChooser.APPROVE_OPTION) { @@ -583,23 +612,6 @@ public class AltosUI extends JFrame { private void SaveFlightData() { } - /* Configure the log directory. This is where all telemetry and eeprom files - * will be written to, and where replay will look for telemetry files - */ - private void ConfigureLog() { - JFileChooser logdir_chooser = new JFileChooser(); - - logdir_chooser.setDialogTitle("Configure Data Logging Directory"); - logdir_chooser.setCurrentDirectory(logdir.getParentFile()); - logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - if (logdir_chooser.showDialog(AltosUI.this, "Select Directory") == JFileChooser.APPROVE_OPTION) { - File dir = logdir_chooser.getSelectedFile(); - if (check_dir(dir)) - set_logdir(dir); - } - } - /* Create the AltosUI menus */ private void createMenu() { @@ -681,7 +693,7 @@ public class AltosUI extends JFrame { item = new JMenuItem("Configure Log",KeyEvent.VK_C); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - ConfigureLog(); + AltosPreferences.ConfigureLog(); } }); menu.add(item); diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java new file mode 100644 index 00000000..e4ea99a2 --- /dev/null +++ b/ao-tools/altosui/AltosVoice.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 com.sun.speech.freetts.Voice; +import com.sun.speech.freetts.VoiceManager; +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; +import java.util.concurrent.LinkedBlockingQueue; + +public class AltosVoice implements Runnable { + VoiceManager voice_manager; + Voice voice; + LinkedBlockingQueue phrases; + Thread thread; + + final static String voice_name = "kevin16"; + + public void run() { + try { + for (;;) { + String s = phrases.take(); + voice.speak(s); + } + } catch (InterruptedException e) { + } + } + public void speak(String s) { + try { + if (voice != null) + phrases.put(s); + } catch (InterruptedException e) { + } + } + + public AltosVoice () { + voice_manager = VoiceManager.getInstance(); + voice = voice_manager.getVoice(voice_name); + if (voice != null) { + voice.allocate(); + phrases = new LinkedBlockingQueue (); + thread = new Thread(this); + thread.start(); + speak("Rocket Flight Monitor Ready"); + } else { + System.out.printf("Voice manager failed to open %s\n", voice_name); + Voice[] voices = voice_manager.getVoices(); + System.out.printf("Available voices:\n"); + for (int i = 0; i < voices.length; i++) { + System.out.println(" " + voices[i].getName() + + " (" + voices[i].getDomain() + " domain)"); + } + } + } +} diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index b9f025da..57c889b8 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:/usr/share/java/* +CLASSPATH=..:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -16,7 +16,8 @@ CLASSFILES=\ AltosUI.class \ AltosDevice.class \ AltosDeviceLinux.class \ - AltosDeviceDialog.class + AltosDeviceDialog.class \ + AltosVoice.class JAVAFLAGS=-Xlint:unchecked diff --git a/ao-tools/altosui/voices.txt b/ao-tools/altosui/voices.txt new file mode 100644 index 00000000..e8825fc3 --- /dev/null +++ b/ao-tools/altosui/voices.txt @@ -0,0 +1 @@ +com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory -- cgit v1.2.3 From 32e430b8a5f93b312f6359b4d553bad92ed37b19 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 17 May 2010 22:43:19 -0600 Subject: merge in a derivative of Bob Finch's mere mortals guide as a getting started chapter --- doc/telemetrum.xsl | 1280 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 758 insertions(+), 522 deletions(-) diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl index 26634d1a..b09e0295 100644 --- a/doc/telemetrum.xsl +++ b/doc/telemetrum.xsl @@ -2,6 +2,8 @@ + TeleMetrum + Owner's Manual for the TeleMetrum System Bdale @@ -15,8 +17,6 @@ 2010 Bdale Garbee and Keith Packard - TeleMetrum - Owner's Manual for the TeleMetrum System This document is released under the terms of the @@ -60,586 +60,822 @@ - Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - - - - Handling Precautions + Getting Started - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. + This chapter began as "The Mere-Mortals Quick Start/Usage Guide to + the Altus Metrum Starter Kit" by Bob Finch, W9YA, NAR 12965, TRA 12350, + w9ya@amsat.org. Bob was one of our first customers for a production + TeleMetrum, and the enthusiasm that led to his contribution of this + section is immensely gratifying and highy appreciated! - The Lithium Polymer rechargeable batteries used with TeleMetrum have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. + The first thing to do after you check the inventory of parts in your + "starter kit" is to charge the battery by plugging it into the + corresponding socket of the TeleMetrum and then using the USB A to B + cable to plug the Telemetrum into your computer's USB socket. The + TeleMetrum circuitry will charge the battery whenever it is plugged + into the usb socket. The TeleMetrum's on-off switch does NOT control + the charging circuitry. When the GPS chip is initially searching for + satellites, the unit will pull more current than it can pull from the + usb port, so the battery must be plugged in order to get a good + satellite lock. Once GPS is locked the current consumption goes back + down enough to enable charging while + running. So it's a good idea to fully charge the battery as your + first item of business so there is no issue getting and maintaining + satellite lock. The yellow charge indicator led will go out when the + battery is nearly full and the charger goes to trickle charge. - The TeleMetrum barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe's see-through - plastic payload bay. + The other active device in the starter kit is the half-duplex TeleDongle + rf link. If you plug it in to your computer it should "just work", + showing up as a serial port device. If you are using Linux and are + having problems, try moving to a fresher kernel (2.6.33 or newer), as + there were some ugly USB serial driver bugs in earlier versions. - The TeleMetrum barometric sensor sampling port must be able to "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. + Next you should obtain and install the AltOS utilities. The first + generation sofware was written for Linux only. New software is coming + soon that will also run on Windows and Mac. For now, we'll concentrate + on Linux. If you are using Debian, an 'altos' package already exists, + see http://altusmetrum.org/AltOS for details on how to install it. + User-contributed directions for building packages on ArchLinux may be + found in the contrib/arch-linux directory as PKGBUILD files. + Between the debian/rules file and the PKGBUILD files in + contrib, you should find enough information to learn how to build the + software for any other version of Linux. - As with all other rocketry electronics, TeleMetrum must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. + When you have successfully installed the software suite (either from + compiled source code or as the pre-built Debian package) you will + have 10 executable programs all of which have names beginning with 'ao-'. + ('ao-view' is the lone GUI-based program. + The rest are command-line based.) You will also + have 10 man pages, that give you basic info on each program. + And you will also get this documentation in two file types, + telemetrum.pdf and telemetrum.html. + Finally you will have a couple of control files that allow the ao-view + GUI-based program to appear in your menu of programs (under + the 'Internet' category). - - - Hardware Overview - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. + Both Telemetrum and TeleDongle can be directly communicated + with using USB ports. The first thing you should try after getting + both units plugged into to your computer's usb port(s) is to run + 'ao-list' from a terminal-window (I use konsole for this,) to see what + port-device-name each device has been assigned by the operating system. + You will need this information to access the devices via their + respective on-board firmware and data using other command line + programs in the AltOS software suite. - A typical TeleMetrum installation using the on-board GPS antenna and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. + To access the device's firmware for configuration you need a terminal + program such as you would use to talk to a modem. The software + authors prefer using the program 'cu' which comes from the UUCP package + on most Unix-like systems such as Linux. An example command line for + cu might be 'cu -l /dev/ttyACM0', substituting the correct number + indicated from running the + ao-list program. Another reasonable terminal program for Linux is + 'cutecom'. The default 'escape' + character used by CU (i.e. the character you use to + issue commands to cu itself instead of sending the command as input + to the connected device) is a '~'. You will need this for use in + only two different ways during normal operations. First is to exit + the program by sending a '~.' which is called a 'escape-disconnect' + and allows you to close-out from 'cu'. The + second use will be outlined later. - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] + Both TeleMetrum and TeleDongle share the concept of a two level + command set in their + firmware. The first layer has several single letter commands. Once + you are using 'cu' (or 'cutecom') sending (typing) a '?' + returns a full list of these + commands. The second level are configuration sub-commands accessed + using the 'c' command, for + instance typing 'c?' will give you this second level of commands + (all of which require the + letter 'c' to access). Please note that most configuration options + are stored only in DataFlash memory, and only TeleMetrum has this + memory to save the various values entered like the channel number + and your callsign when powered off. TeleDongle requires that you + set these each time you plug it in, which ao-view can help with. - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar - option. You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. + Try setting these config ('c' or second level menu) values. A good + place to start is by setting your call sign. By default, the boards + use 'N0CALL' which is cute, but not exactly legal! + Spend a few minutes getting comfortable with the units, their + firmware, 'cu' (and possibly 'cutecom') For instance, try to send + (type) a 'cr2' and verify the channel change by sending a 'cs'. + Verify you can connect and disconnect from the units while in 'cu' + by sending the escape-disconnect mentioned above. - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. + Note that the 'reboot' command, which is very useful on TeleMetrum, + will likely just cause problems with the dongle. The *correct* way + to reset the dongle is just to unplug and re-plug it. + + + A fun thing to do at the launch site and something you can do while + learning how to use these units is to play with the rf-link access + of the TeleMetrum from the TeleDongle. Be aware that you *must* create + some physical separation between the devices, otherwise the link will + not function due to signal overload in the receivers in each device. + + + Now might be a good time to take a break and read the rest of this + manual, particularly about the two "modes" that the TeleMetrum + can be placed in and how the position of the TeleMetrum when booting + up will determine whether the unit is in "pad" or "idle" mode. + + + You can access a TeleMetrum in idle mode from the Teledongle's USB + connection using the rf link + by issuing a 'p' command to the TeleDongle. Practice connecting and + disconnecting ('~~' while using 'cu') from the TeleMetrum. If + you cannot escape out of the "p" command, (by using a '~~' when in + CU) then it is likely that your kernel has issues. Try a newer version. + + + Using this rf link allows you to configure the TeleMetrum, test + fire e-matches and igniters from the flight line, check pyro-match + continuity and so forth. You can leave the unit turned on while it + is in 'idle mode' and then place the + rocket vertically on the launch pad, walk away and then issue a + reboot command. The TeleMetrum will reboot and start sending data + having changed to the "pad" mode. If the TeleDongle is not receiving + this data, you can disconnect 'cu' from the Teledongle using the + procedures mentioned above and THEN connect to the TeleDongle from + inside 'ao-view'. If this doesn't work, disconnect from the + TeleDongle, unplug it, and try again after plugging it back in. + + + Eventually the GPS will find enough satellites, lock in on them, + and 'ao-view' will both auditorially announce and visually indicate + that GPS is ready. + Now you can launch knowing that you have a good data path and + good satellite lock for flight data and recovery. Remember + you MUST tell ao-view to connect to the TeleDongle explicitly in + order for ao-view to be able to receive data. + + + Both RDF (radio direction finding) tones from the TeleMetrum and + GPS trekking data are available and together are very useful in + locating the rocket once it has landed. (The last good GPS data + received before touch-down will be on the data screen of 'ao-view'.) + + + Once you have recovered the rocket you can download the eeprom + contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over + either a USB cable or over the radio link using TeleDongle. + And by following the man page for 'ao-postflight' you can create + various data output reports, graphs, and even kml data to see the + flight trajectory in google-earth. (Moving the viewing angle making + sure to connect the yellow lines while in google-earth is the proper + technique.) + + + As for ao-view.... some things are in the menu but don't do anything + very useful. The developers have stopped working on ao-view to focus + on a new, cross-platform ground station program. Mostly you just use + the Log and Device menus. It has a wonderful display of the incoming + flight data and I am sure you will enjoy what it has to say to you + once you enable the voice output! - - - Operation -
- Firmware Modes - - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. - - - At power on, you will hear three beeps ("S" in Morse code for startup) - and then a pause while - TeleMetrum completes initialization and self tests, and decides which - mode to enter next. - - - In flight mode, TeleMetrum turns on the GPS system, engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when TeleMetrum is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! - -
-
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. - -
-
- Ground Testing - - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! - - - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. - - - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. - -
- Radio Link + FAQ - The chip our boards are based on incorporates an RF transceiver, but - it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we had to decide how to manage the - link. + The altimeter (TeleMetrum) seems to shut off when disconnected from the + computer. Make sure the battery is adequately charged. Remember the + unit will pull more power than the USB port can deliver before the + GPS enters "locked" mode. The battery charges best when TeleMetrum + is turned off. - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which - allows us to use the RF link to configure the rocket, do things like - ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only - transmits and doesn't listen at all. That's because we want to put - ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract - data later... + It's impossible to stop the TeleDongle when it's in "p" mode, I have + to unplug the USB cable? Make sure you have tried to "escape out" of + this mode. If this doesn't work the reboot procedure for the + TeleDongle *is* to simply unplug it. 'cu' however will retain it's + outgoing buffer IF your "escape out" ('~~') does not work. + At this point using either 'ao-view' (or possibly + 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed + communication. - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a - Gaussian filter before they go into the modulator to limit the - transmitted bandwidth. When combined with the hardware forward error - correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had a test flight above 12k AGL with good reception, and calculations - suggest we should be good to 40k AGL or more with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! + The amber LED (on the TeleMetrum/altimeter) lights up when both + battery and USB are connected. Does this mean it's charging? + Yes, the yellow LED indicates the charging at the 'regular' rate. + If the led is out but the unit is still plugged into a USB port, + then the battery is being charged at a 'trickle' rate. + + + There are no "dit-dah-dah-dit" sound like the manual mentions? + That's the "pad" mode. Weak batteries might be the problem. + It is also possible that the unit is horizontal and the output + is instead a "dit-dit" meaning 'idle'. + + + It's unclear how to use 'ao-view' and other programs when 'cu' + is running. You cannot have more than one program connected to + the TeleDongle at one time without apparent data loss as the + incoming data will not make it to both programs intact. + Disconnect whatever programs aren't currently being used. + + + How do I save flight data? + Live telemetry is written to file(s) whenever 'ao-view' is connected + to the TeleDongle. The file area defaults to ~/altos + but is easily changed using the menus in 'ao-view'. The files that + are written end in '.telem'. The after-flight + data-dumped files will end in .eeprom and represent continuous data + unlike the rf-linked .telem files that are subject to the + turnarounds/data-packaging time slots in the half-duplex rf data path. + See the above instructions on what and how to save the eeprom stored + data after physically retrieving your TeleMetrum. + +
+
+ + Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + + + + Handling Precautions + + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe's see-through + plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + + Hardware Overview + + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. - -
- Configurable Parameters - - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. - -
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Apogee Delay - - Apogee delay is the number of seconds after TeleMetrum detects flight - apogee that the drogue charge should be fired. In most cases, this - should be left at the default of 0. However, if you are flying - redundant electronics such as for an L3 certification, you may wish - to set one of your altimeters to a positive delay so that both - primary and backup pyrotechnic charges do not fire simultaneously. - - - To set the apogee delay, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Main Deployment Altitude - - By default, TeleMetrum will fire the main deployment charge at an - elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this - to suit. In particular, if you are flying two altimeters, you may - wish to set the - deployment elevation for the backup altimeter to be something lower - than the primary so that both pyrotechnic charges don't fire - simultaneously. - - - To set the main deployment altitude, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
-
- Calibration - - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. - -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 Mhz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Accelerometer - - The accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - -
-
-
- - Using Altus Metrum Products -
- Being Legal - First off, in the US, you need an [amateur radio license](../Radio) or - other authorization to legally operate the radio transmitters that are part - of our products. + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide and so may be the most familiar + option. You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. + + + + Operation
- In the Rocket + Firmware Modes - In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. - By default, we ship TeleMetrum with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, - which is opaque to RF signals, you may choose to have an SMA connector - installed so that you can run a coaxial cable to an antenna mounted - elsewhere in the rocket. + At power on, you will hear three beeps ("S" in Morse code for startup) + and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. -
-
- On the Ground - To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our [TeleDongle](../TeleDongle) units. The - TeleDongle in turn plugs directly into the USB port on a notebook - computer. Because TeleDongle looks like a simple serial port, your computer - does not require special device drivers... just plug it in. + In flight mode, TeleMetrum turns on the GPS system, engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. - Right now, all of our application software is written for Linux. However, - because we understand that many people run Windows or MacOS, we are working - on a new ground station program written in Java that should work on all - operating systems. + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. - After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the - TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo - battery, so you'll want one of those anyway... the same cable used by lots - of digital cameras and other modern electronic stuff will work fine. + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! + +
+
+ GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! - If your rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket - position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. +
+
+ Ground Testing - You may also enjoy having a ham radio "HT" that covers the 70cm band... you - can use that with your antenna to direction-find the rocket on the ground - the same way you can use a Walston or Beeline tracker. This can be handy - if the rocket is hiding in sage brush or a tree, or if the last GPS position - doesn't get you close enough because the rocket dropped into a canyon, or - the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-7R at launches. + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! - So, to recap, on the ground the hardware you'll need includes: - - - an antenna and feedline - - - a TeleDongle - - - a notebook computer - - - optionally, a handheld GPS receiver - - - optionally, an HT or receiver covering 435 Mhz - - + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. - The best hand-held commercial directional antennas we've found for radio - direction finding rockets are from - - Arrow Antennas. - - The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'.
- Data Analysis + Radio Link - Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum - board. Once this data is on your computer, our postflight tools make it - easy to quickly get to the numbers everyone wants, like apogee altitude, - max acceleration, and max velocity. You can also generate and view a - standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file - useable with Google Maps and Google Earth for visualizing the flight path - in two or three dimensions! + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we had to decide how to manage the + link. - Our ultimate goal is to emit a set of files for each flight that can be - published as a web page per flight, or just viewed on your local disk with - a web browser. + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + We don't use a 'normal packet radio' mode because they're just too + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had a test flight above 12k AGL with good reception, and calculations + suggest we should be good to 40k AGL or more with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights! + +
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. + +
+ Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Main Deployment Altitude + + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. + + + To set the main deployment altitude, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
- Future Plans + Calibration - In the future, we intend to offer "companion boards" for the rocket that will - plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor. + +
+
+
+ + Using Altus Metrum Products +
+ Being Legal - We are also working on the design of a hand-held ground terminal that will - allow monitoring the rocket's status, collecting data during flight, and - logging data after flight without the need for a notebook computer on the - flight line. Particularly since it is so difficult to read most notebook - screens in direct sunlight, we think this will be a great thing to have. + First off, in the US, you need an [amateur radio license](../Radio) or + other authorization to legally operate the radio transmitters that are part + of our products. +
+ In the Rocket + + In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. + +
+
+ On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our [TeleDongle](../TeleDongle) units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + Right now, all of our application software is written for Linux. However, + because we understand that many people run Windows or MacOS, we are working + on a new ground station program written in Java that should work on all + operating systems. + + + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the Yaesu VX-7R at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT. + +
+
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. + +
+
+ Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + + + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too... + +
+
+
+ + How GPS Works + - Because all of our work is open, both the hardware designs and the software, - if you have some great idea for an addition to the current Altus Metrum family, - feel free to dive in and help! Or let us know what you'd like to see that - we aren't already working on, and maybe we'll get excited about it too... + Placeholder.
-
-
- - How GPS Works - - - Placeholder. - -
-
- - + + + -- cgit v1.2.3 From bc89d962c87b50e5487628f8ca25e4443ac4823d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 May 2010 00:24:03 -0600 Subject: merge the altusmetrum-themes package --- debian/altos.install | 8 +++++ debian/control | 4 ++- debian/dirs | 2 ++ debian/rules | 5 ---- themes/background.png | Bin 0 -> 3309056 bytes themes/background.xcf | Bin 0 -> 7648194 bytes themes/gdm/GdmGreeterTheme.desktop | 7 +++++ themes/gdm/altusmetrum.xml | 60 +++++++++++++++++++++++++++++++++++++ themes/gdm/screenshot.png | Bin 0 -> 38754 bytes themes/slim/panel.png | Bin 0 -> 25395 bytes themes/slim/slim.theme | 37 +++++++++++++++++++++++ 11 files changed, 117 insertions(+), 6 deletions(-) create mode 100644 themes/background.png create mode 100644 themes/background.xcf create mode 100644 themes/gdm/GdmGreeterTheme.desktop create mode 100644 themes/gdm/altusmetrum.xml create mode 100644 themes/gdm/screenshot.png create mode 100644 themes/slim/panel.png create mode 100644 themes/slim/slim.theme diff --git a/debian/altos.install b/debian/altos.install index 8d8a1987..8be48ca3 100644 --- a/debian/altos.install +++ b/debian/altos.install @@ -1,4 +1,12 @@ debian/altos.desktop usr/share/applications debian/altos.list etc/apt/sources.list.d +debian/altusmetrum.xpm usr/share/pixmaps src/*.ihx usr/share/altos src/*.map usr/share/altos +themes/background.png usr/share/slim/themes/altusmetrum +themes/slim/panel.png usr/share/slim/themes/altusmetrum +themes/slim/slim.theme usr/share/slim/themes/altusmetrum +themes/background.png usr/share/gdm/themes/altusmetrum +themes/gdm/altusmetrum.xml /usr/share/gdm/themes/altusmetrum +themes/gdm/GdmGreeterTheme.desktop /usr/share/gdm/themes/altusmetrum +themes/gdm/screenshot.png /usr/share/gdm/themes/altusmetrum diff --git a/debian/control b/debian/control index ff6c12e7..fb620e3d 100644 --- a/debian/control +++ b/debian/control @@ -10,7 +10,9 @@ Homepage: http://altusmetrum.org/AltOS Package: altos Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends}, nickle, plplot9-driver-cairo -Suggests: slim-altusmetrum +Suggests: slim | gdm +Replaces: altusmetrum-themes, slim-altusmetrum +Conflicts: altusmetrum-themes, slim-altusmetrum Description: Altus Metrum firmware and utilities Firmware and utilities needed to support the TeleMetrum dual-deploy recording altimeter for high power model rocketry. diff --git a/debian/dirs b/debian/dirs index 29840efb..db75fea7 100644 --- a/debian/dirs +++ b/debian/dirs @@ -2,4 +2,6 @@ etc/apt/sources.list.d usr/bin usr/share/altos usr/share/applications +usr/share/gdm/themes/altusmetrum usr/share/pixmaps +usr/share/slim/themes/altusmetrum diff --git a/debian/rules b/debian/rules index a7468b9f..53a8a340 100755 --- a/debian/rules +++ b/debian/rules @@ -43,14 +43,9 @@ install: build dh_installdirs $(MAKE) DESTDIR=$(CURDIR)/debian/altos install - install -o root -g root -m 0644 debian/altusmetrum.xpm \ - $(CURDIR)/debian/altos/usr/share/pixmaps/altusmetrum.xpm -# Build architecture-independent files here. binary-indep: install -# We have nothing to do by default. -# Build architecture-dependent files here. binary-arch: install dh_testdir dh_testroot diff --git a/themes/background.png b/themes/background.png new file mode 100644 index 00000000..a3c78f36 Binary files /dev/null and b/themes/background.png differ diff --git a/themes/background.xcf b/themes/background.xcf new file mode 100644 index 00000000..92c17093 Binary files /dev/null and b/themes/background.xcf differ diff --git a/themes/gdm/GdmGreeterTheme.desktop b/themes/gdm/GdmGreeterTheme.desktop new file mode 100644 index 00000000..b0fa34b9 --- /dev/null +++ b/themes/gdm/GdmGreeterTheme.desktop @@ -0,0 +1,7 @@ +[GdmGreeterTheme] +Greeter=altusmetrum.xml +Name=AltusMetrum +Description=altusmetrum.org +Author=Bdale Garbee +Copyright=Bdale Garbee +Screenshot=screenshot.png diff --git a/themes/gdm/altusmetrum.xml b/themes/gdm/altusmetrum.xml new file mode 100644 index 00000000..e2755e8e --- /dev/null +++ b/themes/gdm/altusmetrum.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %n | %c + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/themes/gdm/screenshot.png b/themes/gdm/screenshot.png new file mode 100644 index 00000000..5c49ec1c Binary files /dev/null and b/themes/gdm/screenshot.png differ diff --git a/themes/slim/panel.png b/themes/slim/panel.png new file mode 100644 index 00000000..f61bafe3 Binary files /dev/null and b/themes/slim/panel.png differ diff --git a/themes/slim/slim.theme b/themes/slim/slim.theme new file mode 100644 index 00000000..1eeef966 --- /dev/null +++ b/themes/slim/slim.theme @@ -0,0 +1,37 @@ +# altusmetrum theme for SLiM +# by Bdale Garbee + +# Messages (ie: shutdown) +msg_color #000000 +msg_font Verdana:size=18:bold:dpi=75 +msg_x 50% +msg_y 40% +msg_shadow_color #FFFFFF +msg_shadow_xoffset 1 +msg_shadow_yoffset 1 + +# valid values: stretch, tile +background_style stretch +background_color #eedddd + +# Input controls +input_panel_x 50% +input_panel_y 70% +input_name_x 59 +input_name_y 161 +input_font Verdana:size=12:dpi=75 +input_fgcolor #000000 + +# Username / password request +username_font Verdana:size=14:bold:dpi=75 +username_color #000000 +username_x 50% +username_y 122 +password_x 50% +password_y 122 +username_shadow_color #FFFFFF +username_shadow_xoffset 1 +username_shadow_yoffset 1 + +username_msg Username: +password_msg Password: -- cgit v1.2.3 From 16c4cae7ebed7bd3ee0f12b8872bf950574f17e8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 May 2010 00:26:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 13 ++++++++++++ 2 files changed, 75 insertions(+) diff --git a/ChangeLog b/ChangeLog index 63cba5ad..04a8a96d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,65 @@ +commit bc89d962c87b50e5487628f8ca25e4443ac4823d +Author: Bdale Garbee +Date: Tue May 18 00:24:03 2010 -0600 + + merge the altusmetrum-themes package + +commit 0c6cf621dfd8339b8bc3915750a3147235f1331b +Merge: 32e430b 563a9dc +Author: Bdale Garbee +Date: Mon May 17 23:59:43 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 32e430b8a5f93b312f6359b4d553bad92ed37b19 +Author: Bdale Garbee +Date: Mon May 17 22:43:19 2010 -0600 + + merge in a derivative of Bob Finch's mere mortals guide as a getting started + chapter + +commit 563a9dcdfef42718370c49f16cc2271642b3e055 +Author: Keith Packard +Date: Mon May 17 21:30:57 2010 -0700 + + Finish basic flight monitoring UI with voice using FreeTTS + + This captures telemetry data to log files and presents flight status + information in audio form using FreeTTS. + + Signed-off-by: Keith Packard + +commit 69092ffd23ac1928d5c84413fd00c2423f313fc2 +Merge: 3c2211a cc002c0 +Author: Bdale Garbee +Date: Mon May 17 20:10:46 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit cc002c0a43a02845ba67d1a61828be382f307b2e +Author: Keith Packard +Date: Sun May 16 22:31:23 2010 -0700 + + Fix telemetrum.inf, tested by Adrian and Keithp + +commit 3c2211ad7877d622435bc9e8c9c0b01d62be6ff0 +Author: Bdale Garbee +Date: Thu May 13 15:37:37 2010 -0600 + + typo fix from Bob + +commit f0433c83d76e90d78fb86a1f4a2f145f3c57fb25 +Author: Bdale Garbee +Date: Thu May 13 01:27:39 2010 -0600 + + updates from Bob + +commit 0f05cf06e3f1ec510b11d993d9038211ac66c97b +Author: Bdale Garbee +Date: Wed May 12 19:54:04 2010 -0600 + + update changelogs for Debian build + commit 6bd85138c1bfbc1d8b78dce1501870a65a64db36 Author: Bdale Garbee Date: Wed May 12 19:53:40 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 71dc6f59..aadf50ca 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +altos (0.6+213+gbc89d96) unstable; urgency=low + + [ Bdale Garbee ] + * updates including a typo fix from Bob Finch to the PKGBUILD-git.altos + * merge a derivative of Bob Finch's mere mortals guide as getting started + * merge the altusmetrum-themes package + + [ Keith Packard ] + * Fix telemetrum.inf, tested by Adrian and Keithp + * Finish basic flight monitoring UI with voice using FreeTTS + + -- Bdale Garbee Tue, 18 May 2010 00:24:40 -0600 + altos (0.6+204+g6bd8513) unstable; urgency=low * lose the quotes since they apparently aren't necessary -- cgit v1.2.3 From bb46c9a1da5788a082e4483e576a5a6d3963507b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 May 2010 00:26:28 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 04a8a96d..02813e47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 16c4cae7ebed7bd3ee0f12b8872bf950574f17e8 +Author: Bdale Garbee +Date: Tue May 18 00:26:00 2010 -0600 + + update changelogs for Debian build + commit bc89d962c87b50e5487628f8ca25e4443ac4823d Author: Bdale Garbee Date: Tue May 18 00:24:03 2010 -0600 diff --git a/debian/changelog b/debian/changelog index aadf50ca..23dca4a5 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+213+gbc89d96) unstable; urgency=low +altos (0.6+214+g16c4cae) unstable; urgency=low [ Bdale Garbee ] * updates including a typo fix from Bob Finch to the PKGBUILD-git.altos -- cgit v1.2.3 From 93c1e29b07c331a5ca6e0f647b9d2e9266ed3014 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 May 2010 23:12:45 -0600 Subject: updates from Bob --- contrib/arch-linux/PKGBUILD-git.altos | 45 +++++++++++++++++----------------- contrib/arch-linux/PKGBUILD-git.nickle | 17 +++++++------ 2 files changed, 32 insertions(+), 30 deletions(-) diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos index 6fa82a36..ff2c66ca 100644 --- a/contrib/arch-linux/PKGBUILD-git.altos +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -1,35 +1,37 @@ -# Contributor: Bob Finch +# Original contributor: Bob Finch pkgname=altos-git -pkgver=20100507 +pkgver=20100518 pkgrel=1 pkgdesc="Software solutions for high powered rocketry avionics" arch=('i686' 'x86_64') url="http://www.altusmetrum.org/AltOS/" license=('GPL') -depends=('openssl>=1.0.0' 'libusb-BETA' 'plplot-svn' 'sdcc' 'nickle' 'flite' 'kernel26>=2.6.33') +provides=('altos') +conflicts=('altos') +depends=('openssl>=1.0.0' 'libusb-beta' 'plplot-svn' 'sdcc' 'nickle'\ + 'flite' 'kernel26>=2.6.33' 'gconf' 'alsa-lib' 'libglade'\ + 'docbook-xsl' 'fop') makedepends=('git') -optdepends=('uucp: cu is included and is a bare boned terminal to serial program' +optdepends=('uucp: cu is included & is a bare boned terminal 2 serial program' 'cutemon: gui-based minimal terminal to serial program' - 'google-earth: useful for viewing the kml files of the flight path' - 'docbook-xsl: for making an html doc file from the xsl source' - 'fop: for making a pdf doc file from the xsl source') + 'google-earth: useful for viewing the kml files of the flight path') _gitroot="git://git.gag.com/fw/altos" _gitname="altos" build() { cd "$srcdir" -# msg "Connecting to GIT server...." + msg "Connecting to GIT server...." if [ -d $_gitname ] ; then cd $_gitname && git pull origin -# msg "The local files are updated." + msg "The local files are updated." else git clone $_gitroot fi -# msg "GIT checkout done or server timeout" -# msg "Starting make..." + msg "GIT checkout done or server timeout" + msg "Starting make..." rm -rf "$srcdir/$_gitname-build" git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build" @@ -49,17 +51,14 @@ build() { install -m644 debian/*.xpm $startdir/pkg/usr/share/pixmaps install -m644 debian/*.desktop $startdir/pkg/usr/share/applications - # - # OPTIONAL DOC BUILD - *** UNCOMMENT TO INSTALL DOCUMENTATION - # -# xsltproc -o telemetrum.html /usr/share/xml/docbook/xsl-stylesheets-1.74.0/html/docbook.xsl\ -# doc/telemetrum.xml -# xsltproc -o telemetrum.fo /usr/share/xml/docbook/xsl-stylesheets-1.74.0/fo/docbook.xsl\ -# doc/telemetrum.xml -# fop -fo telemetrum.fo -pdf telemetrum.pdf -# -# mkdir -p $startdir/pkg/usr/share/altos/doc -# install -m 644 *.html $startdir/pkg/usr/share/altos/doc/ -# install -m 644 *.pdf $startdir/pkg/usr/share/altos/doc/ + xsltproc -o telemetrum.html /usr/share/xml/docbook/xsl-stylesheets-1.74.0/html/docbook.xsl\ + doc/telemetrum.xsl + xsltproc -o telemetrum.fo /usr/share/xml/docbook/xsl-stylesheets-1.74.0/fo/docbook.xsl\ + doc/telemetrum.xsl + fop -fo telemetrum.fo -pdf telemetrum.pdf + + mkdir -p $startdir/pkg/usr/share/altos/doc + install -m 644 *.html $startdir/pkg/usr/share/altos/doc/ + install -m 644 *.pdf $startdir/pkg/usr/share/altos/doc/ } diff --git a/contrib/arch-linux/PKGBUILD-git.nickle b/contrib/arch-linux/PKGBUILD-git.nickle index 9ed65466..fe6c2a76 100644 --- a/contrib/arch-linux/PKGBUILD-git.nickle +++ b/contrib/arch-linux/PKGBUILD-git.nickle @@ -1,11 +1,14 @@ -# Contributor: Bob Finch +# Original contributor: Bob Finch pkgname=nickle-git -pkgver=20100507 +pkgver=20100518 pkgrel=1 pkgdesc="A desk calculator language with powerful programming and scripting capabilities." arch=('i686' 'x86_64') url="http://keithp.com/git-repository/" license=('custom') +provides=('nickle') +conflicts=('nickle') +depends=('readline') makedepends=('git') _gitroot="git://keithp.com/git/nickle" @@ -13,17 +16,17 @@ _gitname="nickle" build() { cd "$srcdir" -# msg "Connecting to GIT server...." + msg "Connecting to GIT server...." if [ -d $_gitname ] ; then cd $_gitname && git pull origin -# msg "The local files are updated." + msg "The local files are updated." else git clone $_gitroot fi -# msg "GIT checkout done or server timeout" -# msg "Starting make..." + msg "GIT checkout done or server timeout" + msg "Starting make..." rm -rf "$srcdir/$_gitname-build" git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build" @@ -39,5 +42,5 @@ build() { make DESTDIR="$pkgdir/" install install -D -m 644 COPYING\ - $startdir/pkg/usr/share/licenses/nickle/COPYING.txt + $startdir/pkg/usr/share/licenses/$_gitname/COPYING.txt } -- cgit v1.2.3 From 24393eab0ea085f2d0224b59fdc3c00693e5d3a9 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 17 Jun 2010 14:04:01 +1200 Subject: Extension to KML output format, and minor bug fix Extended KML output by breaking flight into coloured segments representing flight state. Add extra statistical information to description bubbles visible in Google Earth when clicking on links in My Places. Fix Bugs: * output kml to file provided as argument. * move kml coordinate output code to take advantage of nsat calculation * remove superfluous %9.2f format specifier from raw_file output. Signed-off-by: Mike Beattie --- ao-tools/ao-postflight/ao-postflight.c | 169 ++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 43 deletions(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index cbf9c047..bf427d3b 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -39,6 +39,19 @@ static const char *state_names[] = { "invalid" }; +static const char *kml_state_colours[] = { + "FF000000", + "FF000000", + "FF000000", + "FF0000FF", + "FF4080FF", + "FF00FFFF", + "FFFF0000", + "FF00FF00", + "FF000000", + "FFFFFFFF" +}; + static int plot_colors[3][3] = { { 0, 0x90, 0 }, /* height */ { 0xa0, 0, 0 }, /* speed */ @@ -161,28 +174,48 @@ merge_data(struct cc_perioddata *first, struct cc_perioddata *last, double split return pd; } -static const char kml_header[] = +static const char kml_header_start[] = "\n" - "\n" + "\n" + "\n" + " %s\n" + " \n"; +static const char kml_header_end[] = + " \n" + " 0\n"; + +static const char kml_style_start[] = + " \n"; + +static const char kml_placemark_start[] = " \n" - " gps\n" - " \n" - " \n" - " \n" - " 1\n" - " absolute\n" - " \n"; + " %s\n" + " #ao-flightstate-%s\n" + " \n" + " 1\n" + " absolute\n" + " \n"; + +static const char kml_coord_fmt[] = + " %12.7f, %12.7f, %12.7f \n"; + +static const char kml_placemark_end[] = + " \n" + " \n" + " \n"; static const char kml_footer[] = - "\n" + " \n" " \n" - " \n" - "\n" + " \n" + "\n" "\n"; static unsigned @@ -272,22 +305,33 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, double state_start, state_stop; struct cc_flightcooked *cooked; double apogee; + char buf[128]; + + if (kml_file) { + snprintf(buf, sizeof (buf), "AO Flight#%d S/N: %03d", f->flight, f->serial); + fprintf(kml_file, kml_header_start, buf); + } fprintf(summary_file, "Serial: %9d\n" "Flight: %9d\n", f->serial, f->flight); + if (f->year) { - fprintf(summary_file, + snprintf(buf, sizeof (buf), "Date: %04d-%02d-%02d\n", f->year, f->month, f->day); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } if (f->gps.num) { - fprintf(summary_file, + snprintf(buf, sizeof (buf), "Time: %2d:%02d:%02d\n", f->gps.data[0].hour, f->gps.data[0].minute, f->gps.data[0].second); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } boost_start = f->accel.data[0].time; boost_stop = f->accel.data[f->accel.num-1].time; @@ -309,10 +353,12 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, min_pres = f->pres.data[pres_i].value; height = cc_barometer_to_altitude(min_pres) - cc_barometer_to_altitude(f->ground_pres); - fprintf(summary_file, "Max height: %9.2fm %9.2fft %9.2fs\n", + apogee = f->pres.data[pres_i].time; + snprintf(buf, sizeof (buf), "Max height: %9.2fm %9.2fft %9.2fs\n", height, height * 100 / 2.54 / 12, (f->pres.data[pres_i].time - boost_start) / 100.0); - apogee = f->pres.data[pres_i].time; + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } cooked = cc_flight_cook(f); @@ -320,9 +366,11 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, speed_i = cc_perioddata_max(&cooked->accel_speed, boost_start, boost_stop); if (speed_i >= 0) { speed = cooked->accel_speed.data[speed_i]; - fprintf(summary_file, "Max speed: %9.2fm/s %9.2fft/s %9.2fs\n", + snprintf(buf, sizeof (buf), "Max speed: %9.2fm/s %9.2fft/s %9.2fs\n", speed, speed * 100 / 2.4 / 12.0, (cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } } accel_i = cc_timedata_min(&f->accel, boost_start, boost_stop); @@ -330,11 +378,16 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, { accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, f->ground_accel); - fprintf(summary_file, "Max accel: %9.2fm/s² %9.2fg %9.2fs\n", + snprintf(buf, sizeof (buf), "Max accel: %9.2fm/s² %9.2fg %9.2fs\n", accel, accel / 9.80665, (f->accel.data[accel_i].time - boost_start) / 100.0); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } + if (kml_file) + fprintf(kml_file, "%s", kml_header_end); + for (i = 0; i < f->state.num; i++) { state = f->state.data[i].value; state_start = f->state.data[i].time; @@ -347,14 +400,23 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, fprintf(summary_file, "State: %s\n", state_names[state]); fprintf(summary_file, "\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); fprintf(summary_file, "\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); + if (kml_file) { + fprintf(kml_file, kml_style_start, state_names[state], kml_state_colours[state]); + fprintf(kml_file, "\tState: %s\n", state_names[state]); + fprintf(kml_file, "\tStart: %9.2fs\n", (state_start - boost_start) / 100.0); + fprintf(kml_file, "\tDuration: %9.2fs\n", (state_stop - state_start) / 100.0); + } + accel_i = cc_timedata_min(&f->accel, state_start, state_stop); if (accel_i >= 0) { accel = cc_accelerometer_to_acceleration(f->accel.data[accel_i].value, f->ground_accel); - fprintf(summary_file, "\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", + snprintf(buf, sizeof (buf), "\tMax accel: %9.2fm/s² %9.2fg %9.2fs\n", accel, accel / 9.80665, (f->accel.data[accel_i].time - boost_start) / 100.0); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } if (cooked) { @@ -371,11 +433,16 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, } if (speed_i >= 0) { - fprintf(summary_file, "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n", + snprintf(buf, sizeof (buf), "\tMax speed: %9.2fm/s %9.2fft/s %9.2fs\n", speed, speed * 100 / 2.4 / 12.0, (cooked->accel_speed.start + speed_i * cooked->accel_speed.step - boost_start) / 100.0); - fprintf(summary_file, "\tAvg speed: %9.2fm/s %9.2fft/s\n", + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); + + snprintf(buf, sizeof (buf), "\tAvg speed: %9.2fm/s %9.2fft/s\n", avg_speed, avg_speed * 100 / 2.4 / 12.0); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } } pres_i = cc_timedata_min(&f->pres, state_start, state_stop); @@ -384,10 +451,13 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, min_pres = f->pres.data[pres_i].value; height = cc_barometer_to_altitude(min_pres) - cc_barometer_to_altitude(f->ground_pres); - fprintf(summary_file, "\tMax height: %9.2fm %9.2fft %9.2fs\n", + snprintf(buf, sizeof (buf), "\tMax height: %9.2fm %9.2fft %9.2fs\n", height, height * 100 / 2.54 / 12, (f->pres.data[pres_i].time - boost_start) / 100.0); + fprintf(summary_file, "%s", buf); + if (kml_file) fprintf(kml_file, "%s", buf); } + if (kml_file) fprintf(kml_file, "%s", kml_style_end); } if (cooked && detail_file) { double max_height = 0; @@ -431,7 +501,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, daytime = compute_daytime_ms(time, &f->gps); else daytime = 0; - fprintf(raw_file, "%9.2f %9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n", + fprintf(raw_file, "%9.2f %9.2f %9.2f %02d:%02d:%02d.%03d\n", time, pres, accel, daytime_hour(daytime), daytime_minute(daytime), @@ -443,13 +513,17 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, int j = 0, baro_pos; double baro_offset; double baro = 0.0; + int state_idx = 0; if (gps_file) fprintf(gps_file, "%2s %2s %2s %9s %12s %12s %9s %8s %5s\n", "hr", "mn", "sc", "time", "lat", "lon", "alt", "baro", "nsat"); if (kml_file) - fprintf(kml_file, "%s", kml_header); + fprintf(kml_file, kml_placemark_start, + state_names[(int)f->state.data[state_idx].value], + state_names[(int)f->state.data[state_idx].value]); + if (f->gps.num) baro_offset = f->gps.data[0].alt; else @@ -484,19 +558,6 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, f->gps.data[i].lon, f->gps.data[i].alt, baro + baro_offset); - if (kml_file) { - fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", - f->gps.data[i].lon, - f->gps.data[i].lat, - baro + baro_offset, - f->gps.data[i].alt, - (f->gps.data[i].time - boost_start) / 100.0, - nsat); - if (i < f->gps.num - 1) - fprintf(kml_file, ",\n"); - else - fprintf(kml_file, "\n"); - } nsat = 0; if (f->gps.sats) { @@ -516,6 +577,28 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, fprintf(gps_file, "\n"); } } + + if (kml_file) { + snprintf(buf, sizeof (buf), kml_coord_fmt, + f->gps.data[i].lon, + f->gps.data[i].lat, + baro + baro_offset, + f->gps.data[i].alt, + (f->gps.data[i].time - boost_start) / 100.0, + nsat); + fprintf(kml_file, "%s", buf); + if (state_idx + 1 <= f->state.num && f->state.data[state_idx + 1].time <= f->gps.data[i].time) { + state_idx++; + if (f->state.data[state_idx - 1].value != f->state.data[state_idx].value) { + fprintf(kml_file, "%s", kml_placemark_end); + fprintf(kml_file, kml_placemark_start, + state_names[(int)f->state.data[state_idx].value], + state_names[(int)f->state.data[state_idx].value]); + fprintf(kml_file, "%s", buf); + } + } + } + } if (kml_file) fprintf(kml_file, "%s", kml_footer); @@ -705,7 +788,7 @@ main (int argc, char **argv) if (has_gps && !gps_file) gps_file = open_output(gps_name, argv[i], ".gps"); if (has_kml && !kml_file) - kml_file = open_output(gps_name, argv[i], ".kml"); + kml_file = open_output(kml_name, argv[i], ".kml"); s = strstr(argv[i], "-serial-"); if (s) serial = atoi(s + 8); -- cgit v1.2.3 From 50ae347bf9de49ccfc92d26888f36e155fb406a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Jun 2010 21:48:04 -0700 Subject: ao-view: disable radio telemetry monitoring during channel change This makes ao-view disable the radio so that the channel change has an immediate effect rather than waiting for a packet on the old channel. Note that this should also be fixed in the TM code itself so that this change wouldn't be required. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_monitor.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 4d7e7a9f..1f9937b2 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -83,8 +83,11 @@ aoview_monitor_callback(gpointer user_data, void aoview_monitor_set_channel(int channel) { - if (monitor_serial) + if (monitor_serial) { + aoview_serial_printf(monitor_serial, "m 0\n"); aoview_serial_printf(monitor_serial, "c r %d\n", channel); + aoview_serial_printf(monitor_serial, "m 1\n"); + } } gboolean @@ -98,9 +101,7 @@ aoview_monitor_connect(char *tty) aoview_table_clear(); aoview_state_reset(); channel = aoview_channel_current(); - if (channel >= 0) - aoview_monitor_set_channel(channel); - aoview_serial_printf(monitor_serial, "m 1\n"); + aoview_monitor_set_channel(channel); aoview_serial_set_callback(monitor_serial, aoview_monitor_callback); return TRUE; -- cgit v1.2.3 From 267923e56e22b3635a21f42ef77a3a36158bc273 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Jun 2010 21:49:43 -0700 Subject: Add special code for USB panic's. The USB system may panic if the hardware isn't ready for IN data when the driver thinks it should be. This adds a special panic code to make figuring this out easier. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_usb.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index 97cb75ae..a2dfadd0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -110,6 +110,7 @@ ao_start_scheduler(void); #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ #define AO_PANIC_REBOOT 8 /* Reboot failed */ #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ +#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_usb.c b/src/ao_usb.c index e4af8e45..d071fe6f 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -85,7 +85,7 @@ ao_usb_ep0_flush(void) USBINDEX = 0; cs0 = USBCS0; if (cs0 & USBCS0_INPKT_RDY) - ao_panic(0); + ao_panic(AO_PANIC_USB); this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) -- cgit v1.2.3 From 5933eaa44fe45027b856f1303dd657b974eb53e7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Jun 2010 11:44:32 -0700 Subject: ao-postflight: was walking off state.data array --- ao-tools/ao-postflight/ao-postflight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index bf427d3b..e5b55665 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -587,7 +587,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, (f->gps.data[i].time - boost_start) / 100.0, nsat); fprintf(kml_file, "%s", buf); - if (state_idx + 1 <= f->state.num && f->state.data[state_idx + 1].time <= f->gps.data[i].time) { + if (state_idx + 1 < f->state.num && f->state.data[state_idx + 1].time <= f->gps.data[i].time) { state_idx++; if (f->state.data[state_idx - 1].value != f->state.data[state_idx].value) { fprintf(kml_file, "%s", kml_placemark_end); -- cgit v1.2.3 From 52834517c0706b1f16fb81643a42dc1c1997e00a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Jun 2010 15:53:33 -0700 Subject: Abort any in-progress radio operation when changing radio channel In monitor mode, the current receive operation must be aborted so that the radio channel change can take effect without receiving a telemetry packet on the old channel. Aborting any in-progress radio operation will make sure that happens. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_config.c b/src/ao_config.c index 8df994a6..cbd639a5 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -151,6 +151,7 @@ ao_config_radio_channel_set(void) __reentrant ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_channel_show(); + ao_radio_abort(); } #if HAS_ADC -- cgit v1.2.3 From 4766b13d1241fa585907c6f77707d2d4b3ccff75 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 24 Jun 2010 12:37:55 -0700 Subject: update changelogs for Debian build --- ChangeLog | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 16 +++++++++++ 2 files changed, 104 insertions(+) diff --git a/ChangeLog b/ChangeLog index 02813e47..236c5bdb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,91 @@ +commit 52834517c0706b1f16fb81643a42dc1c1997e00a +Author: Keith Packard +Date: Mon Jun 21 15:53:33 2010 -0700 + + Abort any in-progress radio operation when changing radio channel + + In monitor mode, the current receive operation must be aborted so that + the radio channel change can take effect without receiving a + telemetry packet on the old channel. Aborting any in-progress radio + operation will make sure that happens. + + Signed-off-by: Keith Packard + +commit 5933eaa44fe45027b856f1303dd657b974eb53e7 +Author: Keith Packard +Date: Mon Jun 21 11:44:32 2010 -0700 + + ao-postflight: was walking off state.data array + +commit 11d155d558d0b121b66f089adee0a47d71f65a78 +Merge: 544003a 24393ea +Author: Keith Packard +Date: Wed Jun 16 21:54:06 2010 -0700 + + Merge remote branch 'mjb/master' + +commit 544003a8da0248fd6f3c62ded86af74ab7cdadf6 +Merge: 267923e 93c1e29 +Author: Keith Packard +Date: Wed Jun 16 21:52:23 2010 -0700 + + Merge remote branch 'origin/master' + +commit 267923e56e22b3635a21f42ef77a3a36158bc273 +Author: Keith Packard +Date: Wed Jun 16 21:49:43 2010 -0700 + + Add special code for USB panic's. + + The USB system may panic if the hardware isn't ready for IN data when + the driver thinks it should be. This adds a special panic code to make + figuring this out easier. + + Signed-off-by: Keith Packard + +commit 50ae347bf9de49ccfc92d26888f36e155fb406a3 +Author: Keith Packard +Date: Wed Jun 16 21:48:04 2010 -0700 + + ao-view: disable radio telemetry monitoring during channel change + + This makes ao-view disable the radio so that the channel change has an + immediate effect rather than waiting for a packet on the old channel. + + Note that this should also be fixed in the TM code itself so that this + change wouldn't be required. + + Signed-off-by: Keith Packard + +commit 24393eab0ea085f2d0224b59fdc3c00693e5d3a9 +Author: Mike Beattie +Date: Thu Jun 17 14:04:01 2010 +1200 + + Extension to KML output format, and minor bug fix + + Extended KML output by breaking flight into coloured segments representing + flight state. Add extra statistical information to description bubbles + visible in Google Earth when clicking on links in My Places. + + Fix Bugs: + * output kml to file provided as argument. + * move kml coordinate output code to take advantage of nsat calculation + * remove superfluous %9.2f format specifier from raw_file output. + + Signed-off-by: Mike Beattie + +commit 93c1e29b07c331a5ca6e0f647b9d2e9266ed3014 +Author: Bdale Garbee +Date: Tue May 18 23:12:45 2010 -0600 + + updates from Bob + +commit bb46c9a1da5788a082e4483e576a5a6d3963507b +Author: Bdale Garbee +Date: Tue May 18 00:26:28 2010 -0600 + + update changelogs for Debian build + commit 16c4cae7ebed7bd3ee0f12b8872bf950574f17e8 Author: Bdale Garbee Date: Tue May 18 00:26:00 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 23dca4a5..9062c51b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +altos (0.6+223+g5283451) unstable; urgency=low + + [ Bdale Garbee ] + * documentation updates from Bob + + [ Mike Beattie ] + * Extension to KML output format, and minor bug fix + + [ Keith Packard ] + * ao-view: disable radio telemetry monitoring during channel change + * Add special code for USB panic's. + * ao-postflight: was walking off state.data array + * Abort any in-progress radio operation when changing radio channel + + -- Bdale Garbee Thu, 24 Jun 2010 12:37:34 -0700 + altos (0.6+214+g16c4cae) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 62294ea3830d3ea261a8761edc9fa6f98201d321 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 24 Jun 2010 12:38:23 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 236c5bdb..0ac6eabb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 4766b13d1241fa585907c6f77707d2d4b3ccff75 +Author: Bdale Garbee +Date: Thu Jun 24 12:37:55 2010 -0700 + + update changelogs for Debian build + commit 52834517c0706b1f16fb81643a42dc1c1997e00a Author: Keith Packard Date: Mon Jun 21 15:53:33 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 9062c51b..c209bcc0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+223+g5283451) unstable; urgency=low +altos (0.6+224+g4766b13) unstable; urgency=low [ Bdale Garbee ] * documentation updates from Bob -- cgit v1.2.3 From a9ec6be0e92dee01f7aac006ef6f7779c1da1b36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 3 Jul 2010 17:42:36 -0400 Subject: Telemetry code was mis-computing RSSI The RSSI data from the hardware reports in 1/2 dBm increments, and so must be divided to report plain RSSI numbers. Signed-off-by: Keith Packard --- ao-tools/lib/cc-telem.c | 4 ++++ configure.ac | 2 ++ src/ao.h | 2 +- src/ao_monitor.c | 10 +++++++--- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index ccd40ac2..aa52b7c5 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -101,6 +101,10 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) telem->flight = 0; cc_parse_int(&telem->rssi, words[5]); + if (version <= 2) { + /* Older telemetry versions mis-computed the rssi value */ + telem->rssi = (telem->rssi + 74) / 2 - 74; + } cc_parse_string(telem->state, sizeof (telem->state), words[9]); cc_parse_int(&telem->tick, words[10]); cc_parse_int(&telem->accel, words[12]); diff --git a/configure.ac b/configure.ac index d6c8682b..fafc6b34 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,8 @@ PKG_CHECK_MODULES([ALSA], [alsa]) PKG_CHECK_MODULES([PLPLOT], [plplotd]) +PKG_CHECK_MODULES([SNDFILE], [sndfile]) + AC_OUTPUT([ Makefile ao-tools/Makefile diff --git a/src/ao.h b/src/ao.h index a2dfadd0..dfff8a8d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -804,7 +804,7 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 2 +#define AO_TELEMETRY_VERSION 3 struct ao_telemetry { uint8_t addr; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index f2f3fc2e..f019d3b4 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,6 +26,7 @@ ao_monitor(void) __xdata struct ao_radio_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; uint8_t state; + int16_t rssi; for (;;) { __critical while (!ao_monitoring) @@ -33,6 +34,9 @@ ao_monitor(void) if (!ao_radio_recv(&recv)) continue; state = recv.telemetry.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv.rssi >> 1) - 74; memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; @@ -42,7 +46,7 @@ ao_monitor(void) callsign, recv.telemetry.addr, recv.telemetry.flight, - (int) recv.rssi - 74, recv.status, + rssi, recv.status, ao_state_names[state]); printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", @@ -64,9 +68,9 @@ ao_monitor(void) putchar(' '); ao_gps_tracking_print(&recv.telemetry.gps_tracking); putchar('\n'); - ao_rssi_set((int) recv.rssi - 74); + ao_rssi_set(rssi); } else { - printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74); + printf("CRC INVALID RSSI %3d\n", rssi); } ao_usb_flush(); ao_led_toggle(ao_monitor_led); -- cgit v1.2.3 From 695879dbccfc5ec6b79698653c58814158f91686 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 14 Jul 2010 19:07:02 -0700 Subject: Switch DBG pins to GPIO when using any debug commands. Reboot to restore. If you want to use TeleMetrum as a debug dongle, you need to flip the three pins used to talk to the remote debug port from SPI mode to GPIO mode. This patch doesn't provide any way to get back to SPI mode, so you'll have to reboot the TeleMetrum to write out config parameters or log flight data after using any debug commands. Signed-off-by: Keith Packard --- src/ao_dbg.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index e7fbd7ad..0d9ec8c0 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -164,6 +164,12 @@ ao_dbg_read_byte(void) static void ao_dbg_set_pins(void) { + /* Make the DBG pins GPIOs. On TeleMetrum, this will + * disable the SPI link, so don't expect SPI to work after + * using the debugger. + */ + DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); + /* make DBG_DATA tri-state */ DBG_PORT_INP |= DBG_DATA; -- cgit v1.2.3 From bd40a5b431847c071f5c486d754eca5627e5e3b9 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 02:12:03 -0600 Subject: significant update --- doc/Makefile | 30 +- doc/telemetrum-doc.xsl | 909 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/telemetrum.xsl | 881 ----------------------------------------------- 3 files changed, 927 insertions(+), 893 deletions(-) create mode 100644 doc/telemetrum-doc.xsl delete mode 100644 doc/telemetrum.xsl diff --git a/doc/Makefile b/doc/Makefile index 55b7a548..f8048dce 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,24 +2,30 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -all: telemetrum.html telemetrum.pdf +all: telemetrum-doc.html telemetrum-doc.pdf -telemetrum.html: telemetrum.xsl - xsltproc -o telemetrum.html \ +publish: all + cp telemetrum-doc.html \ + telemetrum-doc.pdf /home/bdale/web/altusmetrum/TeleMetrum/doc/ + (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/TeleMetrum/doc/* ; git push) + + +telemetrum-doc.html: telemetrum-doc.xsl + xsltproc -o telemetrum-doc.html \ /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl \ - telemetrum.xsl + telemetrum-doc.xsl -telemetrum.fo: telemetrum.xsl - xsltproc -o telemetrum.fo \ +telemetrum-doc.fo: telemetrum-doc.xsl + xsltproc -o telemetrum-doc.fo \ /usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl \ - telemetrum.xsl + telemetrum-doc.xsl -telemetrum.pdf: telemetrum.fo - fop -fo telemetrum.fo -pdf telemetrum.pdf +telemetrum-doc.pdf: telemetrum-doc.fo + fop -fo telemetrum-doc.fo -pdf telemetrum-doc.pdf clean: - rm -f telemetrum.html telemetrum.pdf telemetrum.fo + rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo -indent: telemetrum.xsl - xmlindent -i 2 < telemetrum.xsl > telemetrum.new +indent: telemetrum-doc.xsl + xmlindent -i 2 < telemetrum-doc.xsl > telemetrum-doc.new diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl new file mode 100644 index 00000000..b7963aec --- /dev/null +++ b/doc/telemetrum-doc.xsl @@ -0,0 +1,909 @@ + + + + TeleMetrum + Owner's Manual for the TeleMetrum System + + + Bdale + Garbee + + + Keith + Packard + + + 2010 + Bdale Garbee and Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.2 + 18 July 2010 + Significant update + + + 0.1 + 30 March 2010 + Initial content + + + + + Introduction and Overview + + Welcome to the Altus Metrum community! Our circuits and software reflect + our passion for both hobby rocketry and Free Software. We hope their + capabilities and performance will delight you in every way, but by + releasing all of our hardware and software designs under open licenses, + we also hope to empower you to take as active a role in our collective + future as you wish! + + + The focal point of our community is TeleMetrum, a dual deploy altimeter + with fully integrated GPS and radio telemetry as standard features, and + a "companion interface" that will support optional capabilities in the + future. + + + Complementing TeleMetrum is TeleDongle, a USB to RF interface for + communicating with TeleMetrum. Combined with your choice of antenna and + notebook computer, TeleDongle and our associated user interface software + form a complete ground station capable of logging and displaying in-flight + telemetry, aiding rocket recovery, then processing and archiving flight + data for analysis and review. + + + More products will be added to the Altus Metrum family over time, and + we currently envision that this will be a single, comprehensive manual + for the entire product family. + + + + Getting Started + + This chapter began as "The Mere-Mortals Quick Start/Usage Guide to + the Altus Metrum Starter Kit" by Bob Finch, W9YA, NAR 12965, TRA 12350, + w9ya@amsat.org. Bob was one of our first customers for a production + TeleMetrum, and the enthusiasm that led to his contribution of this + section is immensely gratifying and highy appreciated! + + + The first thing to do after you check the inventory of parts in your + "starter kit" is to charge the battery by plugging it into the + corresponding socket of the TeleMetrum and then using the USB A to B + cable to plug the Telemetrum into your computer's USB socket. The + TeleMetrum circuitry will charge the battery whenever it is plugged + into the usb socket. The TeleMetrum's on-off switch does NOT control + the charging circuitry. When the GPS chip is initially searching for + satellites, the unit will pull more current than it can pull from the + usb port, so the battery must be plugged in order to get a good + satellite lock. Once GPS is locked the current consumption goes back + down enough to enable charging while + running. So it's a good idea to fully charge the battery as your + first item of business so there is no issue getting and maintaining + satellite lock. The yellow charge indicator led will go out when the + battery is nearly full and the charger goes to trickle charge. + + + The other active device in the starter kit is the half-duplex TeleDongle + rf link. If you plug it in to your computer it should "just work", + showing up as a serial port device. If you are using Linux and are + having problems, try moving to a fresher kernel (2.6.33 or newer), as + there were some ugly USB serial driver bugs in earlier versions. + + + Next you should obtain and install the AltOS utilities. The first + generation sofware was written for Linux only. New software is coming + soon that will also run on Windows and Mac. For now, we'll concentrate + on Linux. If you are using Debian, an 'altos' package already exists, + see http://altusmetrum.org/AltOS for details on how to install it. + User-contributed directions for building packages on ArchLinux may be + found in the contrib/arch-linux directory as PKGBUILD files. + Between the debian/rules file and the PKGBUILD files in + contrib, you should find enough information to learn how to build the + software for any other version of Linux. + + + When you have successfully installed the software suite (either from + compiled source code or as the pre-built Debian package) you will + have 10 or so executable programs all of which have names beginning + with 'ao-'. + ('ao-view' is the lone GUI-based program, the rest are command-line + oriented.) You will also have man pages, that give you basic info + on each program. + You will also get this documentation in two file types in the doc/ +directory, telemetrum-doc.pdf and telemetrum-doc.html. + Finally you will have a couple control files that allow the ao-view + GUI-based program to appear in your menu of programs (under + the 'Internet' category). + + + Both Telemetrum and TeleDongle can be directly communicated + with using USB ports. The first thing you should try after getting + both units plugged into to your computer's usb port(s) is to run + 'ao-list' from a terminal-window to see what port-device-name each + device has been assigned by the operating system. + You will need this information to access the devices via their + respective on-board firmware and data using other command line + programs in the AltOS software suite. + + + To access the device's firmware for configuration you need a terminal + program such as you would use to talk to a modem. The software + authors prefer using the program 'cu' which comes from the UUCP package + on most Unix-like systems such as Linux. An example command line for + cu might be 'cu -l /dev/ttyACM0', substituting the correct number + indicated from running the + ao-list program. Another reasonable terminal program for Linux is + 'cutecom'. The default 'escape' + character used by CU (i.e. the character you use to + issue commands to cu itself instead of sending the command as input + to the connected device) is a '~'. You will need this for use in + only two different ways during normal operations. First is to exit + the program by sending a '~.' which is called a 'escape-disconnect' + and allows you to close-out from 'cu'. The + second use will be outlined later. + + + Both TeleMetrum and TeleDongle share the concept of a two level + command set in their firmware. + The first layer has several single letter commands. Once + you are using 'cu' (or 'cutecom') sending (typing) a '?' + returns a full list of these + commands. The second level are configuration sub-commands accessed + using the 'c' command, for + instance typing 'c?' will give you this second level of commands + (all of which require the + letter 'c' to access). Please note that most configuration options + are stored only in DataFlash memory, and only TeleMetrum has this + memory to save the various values entered like the channel number + and your callsign when powered off. TeleDongle requires that you + set these each time you plug it in, which ao-view can help with. + + + Try setting these config ('c' or second level menu) values. A good + place to start is by setting your call sign. By default, the boards + use 'N0CALL' which is cute, but not exactly legal! + Spend a few minutes getting comfortable with the units, their + firmware, and 'cu' (or possibly 'cutecom'). + For instance, try to send + (type) a 'c r 2' and verify the channel change by sending a 'c s'. + Verify you can connect and disconnect from the units while in your + terminal program by sending the escape-disconnect mentioned above. + + + Note that the 'reboot' command, which is very useful on TeleMetrum, + will likely just cause problems with the dongle. The *correct* way + to reset the dongle is just to unplug and re-plug it. + + + A fun thing to do at the launch site and something you can do while + learning how to use these units is to play with the rf-link access + of the TeleMetrum from the TeleDongle. Be aware that you *must* create + some physical separation between the devices, otherwise the link will + not function due to signal overload in the receivers in each device. + + + Now might be a good time to take a break and read the rest of this + manual, particularly about the two "modes" that the TeleMetrum + can be placed in and how the position of the TeleMetrum when booting + up will determine whether the unit is in "pad" or "idle" mode. + + + You can access a TeleMetrum in idle mode from the Teledongle's USB + connection using the rf link + by issuing a 'p' command to the TeleDongle. Practice connecting and + disconnecting ('~~' while using 'cu') from the TeleMetrum. If + you cannot escape out of the "p" command, (by using a '~~' when in + CU) then it is likely that your kernel has issues. Try a newer version. + + + Using this rf link allows you to configure the TeleMetrum, test + fire e-matches and igniters from the flight line, check pyro-match + continuity and so forth. You can leave the unit turned on while it + is in 'idle mode' and then place the + rocket vertically on the launch pad, walk away and then issue a + reboot command. The TeleMetrum will reboot and start sending data + having changed to the "pad" mode. If the TeleDongle is not receiving + this data, you can disconnect 'cu' from the Teledongle using the + procedures mentioned above and THEN connect to the TeleDongle from + inside 'ao-view'. If this doesn't work, disconnect from the + TeleDongle, unplug it, and try again after plugging it back in. + + + Eventually the GPS will find enough satellites, lock in on them, + and 'ao-view' will both auditorially announce and visually indicate + that GPS is ready. + Now you can launch knowing that you have a good data path and + good satellite lock for flight data and recovery. Remember + you MUST tell ao-view to connect to the TeleDongle explicitly in + order for ao-view to be able to receive data. + + + Both RDF (radio direction finding) tones from the TeleMetrum and + GPS trekking data are available and together are very useful in + locating the rocket once it has landed. (The last good GPS data + received before touch-down will be on the data screen of 'ao-view'.) + + + Once you have recovered the rocket you can download the eeprom + contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over + either a USB cable or over the radio link using TeleDongle. + And by following the man page for 'ao-postflight' you can create + various data output reports, graphs, and even kml data to see the + flight trajectory in google-earth. (Moving the viewing angle making + sure to connect the yellow lines while in google-earth is the proper + technique.) + + + As for ao-view.... some things are in the menu but don't do anything + very useful. The developers have stopped working on ao-view to focus + on a new, cross-platform ground station program. So ao-view may or + may not be updated in the future. Mostly you just use + the Log and Device menus. It has a wonderful display of the incoming + flight data and I am sure you will enjoy what it has to say to you + once you enable the voice output! + +
+ FAQ + + The altimeter (TeleMetrum) seems to shut off when disconnected from the + computer. Make sure the battery is adequately charged. Remember the + unit will pull more power than the USB port can deliver before the + GPS enters "locked" mode. The battery charges best when TeleMetrum + is turned off. + + + It's impossible to stop the TeleDongle when it's in "p" mode, I have + to unplug the USB cable? Make sure you have tried to "escape out" of + this mode. If this doesn't work the reboot procedure for the + TeleDongle *is* to simply unplug it. 'cu' however will retain it's + outgoing buffer IF your "escape out" ('~~') does not work. + At this point using either 'ao-view' (or possibly + 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed + communication. + + + The amber LED (on the TeleMetrum/altimeter) lights up when both + battery and USB are connected. Does this mean it's charging? + Yes, the yellow LED indicates the charging at the 'regular' rate. + If the led is out but the unit is still plugged into a USB port, + then the battery is being charged at a 'trickle' rate. + + + There are no "dit-dah-dah-dit" sound like the manual mentions? + That's the "pad" mode. Weak batteries might be the problem. + It is also possible that the unit is horizontal and the output + is instead a "dit-dit" meaning 'idle'. + + + It's unclear how to use 'ao-view' and other programs when 'cu' + is running. You cannot have more than one program connected to + the TeleDongle at one time without apparent data loss as the + incoming data will not make it to both programs intact. + Disconnect whatever programs aren't currently being used. + + + How do I save flight data? + Live telemetry is written to file(s) whenever 'ao-view' is connected + to the TeleDongle. The file area defaults to ~/altos + but is easily changed using the menus in 'ao-view'. The files that + are written end in '.telem'. The after-flight + data-dumped files will end in .eeprom and represent continuous data + unlike the rf-linked .telem files that are subject to the + turnarounds/data-packaging time slots in the half-duplex rf data path. + See the above instructions on what and how to save the eeprom stored + data after physically retrieving your TeleMetrum. Make sure to save + the on-board data after each flight, as the current firmware will + over-write any previous flight data during a new flight. + +
+
+ + Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + + + + Handling Precautions + + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe with a + see-through plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to + "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + + Hardware Overview + + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. + + + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide and so may be the most familiar option. + You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. + + + + Operation +
+ Firmware Modes + + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. + + + At power on, you will hear three beeps + ("S" in Morse code for startup) and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. + + + In flight or "pad" mode, TeleMetrum turns on the GPS system, + engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. + + + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. + + + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! + +
+
+ GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! + + + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. + +
+
+ Ground Testing + + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! + + + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. + + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. + +
+
+ Radio Link + + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we had to decide how to manage the + link. + + + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + + We don't use a 'normal packet radio' mode because they're just too + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had flights to above 21k feet AGL with good reception, and calculations + suggest we should be good to well over 40k feet AGL with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights! + +
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. + +
+ Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip on + your TeleMetrum board if you want the change to stay in place across reboots. + +
+
+ Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + Please note that the TeleMetrum apogee detection algorithm always + fires a fraction of a second *after* apogee. If you are also flying + an altimeter like the PerfectFlite MAWD, which only supports selecting + 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 + seconds delay and set the TeleMetrum to fire your backup 2 or 3 + seconds later to avoid any chance of both charges firing + simultaneously. We've flown several airframes this way quite happily, + including Keith's successful L3 cert. + +
+
+ Main Deployment Altitude + + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. + + + To set the main deployment altitude, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+
+ Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor. + +
+
+
+ + Using Altus Metrum Products +
+ Being Legal + + First off, in the US, you need an [amateur radio license](../Radio) or + other authorization to legally operate the radio transmitters that are part + of our products. + +
+ In the Rocket + + In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. + +
+
+ On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our [TeleDongle](../TeleDongle) units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + Right now, all of our application software is written for Linux. However, + because we understand that many people run Windows or MacOS, we are working + on a new ground station program written in Java that should work on all + operating systems. + + + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the Yaesu VX-7R at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT. + +
+
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. + +
+
+ Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + + + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too... + +
+
+
+ + How GPS Works + + + Placeholder. + +
+
+
+ diff --git a/doc/telemetrum.xsl b/doc/telemetrum.xsl deleted file mode 100644 index b09e0295..00000000 --- a/doc/telemetrum.xsl +++ /dev/null @@ -1,881 +0,0 @@ - - - - TeleMetrum - Owner's Manual for the TeleMetrum System - - - Bdale - Garbee - - - Keith - Packard - - - 2010 - Bdale Garbee and Keith Packard - - - - This document is released under the terms of the - - Creative Commons ShareAlike 3.0 - - license. - - - - - 0.1 - 30 March 2010 - Initial content - - - - - Introduction and Overview - - Welcome to the Altus Metrum community! Our circuits and software reflect - our passion for both hobby rocketry and Free Software. We hope their - capabilities and performance will delight you in every way, but by - releasing all of our hardware and software designs under open licenses, - we also hope to empower you to take as active a role in our collective - future as you wish! - - - The focal point of our community is TeleMetrum, a dual deploy altimeter - with fully integrated GPS and radio telemetry as standard features, and - a "companion interface" that will support optional capabilities in the - future. - - - Complementing TeleMetrum is TeleDongle, a USB to RF interface for - communicating with TeleMetrum. Combined with your choice of antenna and - notebook computer, TeleDongle and our associated user interface software - form a complete ground station capable of logging and displaying in-flight - telemetry, aiding rocket recovery, then processing and archiving flight - data for analysis and review. - - - - Getting Started - - This chapter began as "The Mere-Mortals Quick Start/Usage Guide to - the Altus Metrum Starter Kit" by Bob Finch, W9YA, NAR 12965, TRA 12350, - w9ya@amsat.org. Bob was one of our first customers for a production - TeleMetrum, and the enthusiasm that led to his contribution of this - section is immensely gratifying and highy appreciated! - - - The first thing to do after you check the inventory of parts in your - "starter kit" is to charge the battery by plugging it into the - corresponding socket of the TeleMetrum and then using the USB A to B - cable to plug the Telemetrum into your computer's USB socket. The - TeleMetrum circuitry will charge the battery whenever it is plugged - into the usb socket. The TeleMetrum's on-off switch does NOT control - the charging circuitry. When the GPS chip is initially searching for - satellites, the unit will pull more current than it can pull from the - usb port, so the battery must be plugged in order to get a good - satellite lock. Once GPS is locked the current consumption goes back - down enough to enable charging while - running. So it's a good idea to fully charge the battery as your - first item of business so there is no issue getting and maintaining - satellite lock. The yellow charge indicator led will go out when the - battery is nearly full and the charger goes to trickle charge. - - - The other active device in the starter kit is the half-duplex TeleDongle - rf link. If you plug it in to your computer it should "just work", - showing up as a serial port device. If you are using Linux and are - having problems, try moving to a fresher kernel (2.6.33 or newer), as - there were some ugly USB serial driver bugs in earlier versions. - - - Next you should obtain and install the AltOS utilities. The first - generation sofware was written for Linux only. New software is coming - soon that will also run on Windows and Mac. For now, we'll concentrate - on Linux. If you are using Debian, an 'altos' package already exists, - see http://altusmetrum.org/AltOS for details on how to install it. - User-contributed directions for building packages on ArchLinux may be - found in the contrib/arch-linux directory as PKGBUILD files. - Between the debian/rules file and the PKGBUILD files in - contrib, you should find enough information to learn how to build the - software for any other version of Linux. - - - When you have successfully installed the software suite (either from - compiled source code or as the pre-built Debian package) you will - have 10 executable programs all of which have names beginning with 'ao-'. - ('ao-view' is the lone GUI-based program. - The rest are command-line based.) You will also - have 10 man pages, that give you basic info on each program. - And you will also get this documentation in two file types, - telemetrum.pdf and telemetrum.html. - Finally you will have a couple of control files that allow the ao-view - GUI-based program to appear in your menu of programs (under - the 'Internet' category). - - - Both Telemetrum and TeleDongle can be directly communicated - with using USB ports. The first thing you should try after getting - both units plugged into to your computer's usb port(s) is to run - 'ao-list' from a terminal-window (I use konsole for this,) to see what - port-device-name each device has been assigned by the operating system. - You will need this information to access the devices via their - respective on-board firmware and data using other command line - programs in the AltOS software suite. - - - To access the device's firmware for configuration you need a terminal - program such as you would use to talk to a modem. The software - authors prefer using the program 'cu' which comes from the UUCP package - on most Unix-like systems such as Linux. An example command line for - cu might be 'cu -l /dev/ttyACM0', substituting the correct number - indicated from running the - ao-list program. Another reasonable terminal program for Linux is - 'cutecom'. The default 'escape' - character used by CU (i.e. the character you use to - issue commands to cu itself instead of sending the command as input - to the connected device) is a '~'. You will need this for use in - only two different ways during normal operations. First is to exit - the program by sending a '~.' which is called a 'escape-disconnect' - and allows you to close-out from 'cu'. The - second use will be outlined later. - - - Both TeleMetrum and TeleDongle share the concept of a two level - command set in their - firmware. The first layer has several single letter commands. Once - you are using 'cu' (or 'cutecom') sending (typing) a '?' - returns a full list of these - commands. The second level are configuration sub-commands accessed - using the 'c' command, for - instance typing 'c?' will give you this second level of commands - (all of which require the - letter 'c' to access). Please note that most configuration options - are stored only in DataFlash memory, and only TeleMetrum has this - memory to save the various values entered like the channel number - and your callsign when powered off. TeleDongle requires that you - set these each time you plug it in, which ao-view can help with. - - - Try setting these config ('c' or second level menu) values. A good - place to start is by setting your call sign. By default, the boards - use 'N0CALL' which is cute, but not exactly legal! - Spend a few minutes getting comfortable with the units, their - firmware, 'cu' (and possibly 'cutecom') For instance, try to send - (type) a 'cr2' and verify the channel change by sending a 'cs'. - Verify you can connect and disconnect from the units while in 'cu' - by sending the escape-disconnect mentioned above. - - - Note that the 'reboot' command, which is very useful on TeleMetrum, - will likely just cause problems with the dongle. The *correct* way - to reset the dongle is just to unplug and re-plug it. - - - A fun thing to do at the launch site and something you can do while - learning how to use these units is to play with the rf-link access - of the TeleMetrum from the TeleDongle. Be aware that you *must* create - some physical separation between the devices, otherwise the link will - not function due to signal overload in the receivers in each device. - - - Now might be a good time to take a break and read the rest of this - manual, particularly about the two "modes" that the TeleMetrum - can be placed in and how the position of the TeleMetrum when booting - up will determine whether the unit is in "pad" or "idle" mode. - - - You can access a TeleMetrum in idle mode from the Teledongle's USB - connection using the rf link - by issuing a 'p' command to the TeleDongle. Practice connecting and - disconnecting ('~~' while using 'cu') from the TeleMetrum. If - you cannot escape out of the "p" command, (by using a '~~' when in - CU) then it is likely that your kernel has issues. Try a newer version. - - - Using this rf link allows you to configure the TeleMetrum, test - fire e-matches and igniters from the flight line, check pyro-match - continuity and so forth. You can leave the unit turned on while it - is in 'idle mode' and then place the - rocket vertically on the launch pad, walk away and then issue a - reboot command. The TeleMetrum will reboot and start sending data - having changed to the "pad" mode. If the TeleDongle is not receiving - this data, you can disconnect 'cu' from the Teledongle using the - procedures mentioned above and THEN connect to the TeleDongle from - inside 'ao-view'. If this doesn't work, disconnect from the - TeleDongle, unplug it, and try again after plugging it back in. - - - Eventually the GPS will find enough satellites, lock in on them, - and 'ao-view' will both auditorially announce and visually indicate - that GPS is ready. - Now you can launch knowing that you have a good data path and - good satellite lock for flight data and recovery. Remember - you MUST tell ao-view to connect to the TeleDongle explicitly in - order for ao-view to be able to receive data. - - - Both RDF (radio direction finding) tones from the TeleMetrum and - GPS trekking data are available and together are very useful in - locating the rocket once it has landed. (The last good GPS data - received before touch-down will be on the data screen of 'ao-view'.) - - - Once you have recovered the rocket you can download the eeprom - contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over - either a USB cable or over the radio link using TeleDongle. - And by following the man page for 'ao-postflight' you can create - various data output reports, graphs, and even kml data to see the - flight trajectory in google-earth. (Moving the viewing angle making - sure to connect the yellow lines while in google-earth is the proper - technique.) - - - As for ao-view.... some things are in the menu but don't do anything - very useful. The developers have stopped working on ao-view to focus - on a new, cross-platform ground station program. Mostly you just use - the Log and Device menus. It has a wonderful display of the incoming - flight data and I am sure you will enjoy what it has to say to you - once you enable the voice output! - -
- FAQ - - The altimeter (TeleMetrum) seems to shut off when disconnected from the - computer. Make sure the battery is adequately charged. Remember the - unit will pull more power than the USB port can deliver before the - GPS enters "locked" mode. The battery charges best when TeleMetrum - is turned off. - - - It's impossible to stop the TeleDongle when it's in "p" mode, I have - to unplug the USB cable? Make sure you have tried to "escape out" of - this mode. If this doesn't work the reboot procedure for the - TeleDongle *is* to simply unplug it. 'cu' however will retain it's - outgoing buffer IF your "escape out" ('~~') does not work. - At this point using either 'ao-view' (or possibly - 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed - communication. - - - The amber LED (on the TeleMetrum/altimeter) lights up when both - battery and USB are connected. Does this mean it's charging? - Yes, the yellow LED indicates the charging at the 'regular' rate. - If the led is out but the unit is still plugged into a USB port, - then the battery is being charged at a 'trickle' rate. - - - There are no "dit-dah-dah-dit" sound like the manual mentions? - That's the "pad" mode. Weak batteries might be the problem. - It is also possible that the unit is horizontal and the output - is instead a "dit-dit" meaning 'idle'. - - - It's unclear how to use 'ao-view' and other programs when 'cu' - is running. You cannot have more than one program connected to - the TeleDongle at one time without apparent data loss as the - incoming data will not make it to both programs intact. - Disconnect whatever programs aren't currently being used. - - - How do I save flight data? - Live telemetry is written to file(s) whenever 'ao-view' is connected - to the TeleDongle. The file area defaults to ~/altos - but is easily changed using the menus in 'ao-view'. The files that - are written end in '.telem'. The after-flight - data-dumped files will end in .eeprom and represent continuous data - unlike the rf-linked .telem files that are subject to the - turnarounds/data-packaging time slots in the half-duplex rf data path. - See the above instructions on what and how to save the eeprom stored - data after physically retrieving your TeleMetrum. - -
-
- - Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - - - - Handling Precautions - - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. - - - The Lithium Polymer rechargeable batteries used with TeleMetrum have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. - - - The TeleMetrum barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe's see-through - plastic payload bay. - - - The TeleMetrum barometric sensor sampling port must be able to "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. - - - As with all other rocketry electronics, TeleMetrum must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. - - - - Hardware Overview - - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. - - - A typical TeleMetrum installation using the on-board GPS antenna and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. - - - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] - - - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar - option. You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. - - - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. - - - - Operation -
- Firmware Modes - - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. - - - At power on, you will hear three beeps ("S" in Morse code for startup) - and then a pause while - TeleMetrum completes initialization and self tests, and decides which - mode to enter next. - - - In flight mode, TeleMetrum turns on the GPS system, engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when TeleMetrum is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! - -
-
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. - -
-
- Ground Testing - - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! - - - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. - - - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. - -
-
- Radio Link - - The chip our boards are based on incorporates an RF transceiver, but - it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we had to decide how to manage the - link. - - - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which - allows us to use the RF link to configure the rocket, do things like - ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only - transmits and doesn't listen at all. That's because we want to put - ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract - data later... - - - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a - Gaussian filter before they go into the modulator to limit the - transmitted bandwidth. When combined with the hardware forward error - correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had a test flight above 12k AGL with good reception, and calculations - suggest we should be good to 40k AGL or more with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! - -
-
- Configurable Parameters - - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. - -
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Apogee Delay - - Apogee delay is the number of seconds after TeleMetrum detects flight - apogee that the drogue charge should be fired. In most cases, this - should be left at the default of 0. However, if you are flying - redundant electronics such as for an L3 certification, you may wish - to set one of your altimeters to a positive delay so that both - primary and backup pyrotechnic charges do not fire simultaneously. - - - To set the apogee delay, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Main Deployment Altitude - - By default, TeleMetrum will fire the main deployment charge at an - elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this - to suit. In particular, if you are flying two altimeters, you may - wish to set the - deployment elevation for the backup altimeter to be something lower - than the primary so that both pyrotechnic charges don't fire - simultaneously. - - - To set the main deployment altitude, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
-
- Calibration - - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. - -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 Mhz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Accelerometer - - The accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - -
-
-
- - Using Altus Metrum Products -
- Being Legal - - First off, in the US, you need an [amateur radio license](../Radio) or - other authorization to legally operate the radio transmitters that are part - of our products. - -
- In the Rocket - - In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. - - - By default, we ship TeleMetrum with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, - which is opaque to RF signals, you may choose to have an SMA connector - installed so that you can run a coaxial cable to an antenna mounted - elsewhere in the rocket. - -
-
- On the Ground - - To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our [TeleDongle](../TeleDongle) units. The - TeleDongle in turn plugs directly into the USB port on a notebook - computer. Because TeleDongle looks like a simple serial port, your computer - does not require special device drivers... just plug it in. - - - Right now, all of our application software is written for Linux. However, - because we understand that many people run Windows or MacOS, we are working - on a new ground station program written in Java that should work on all - operating systems. - - - After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the - TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo - battery, so you'll want one of those anyway... the same cable used by lots - of digital cameras and other modern electronic stuff will work fine. - - - If your rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket - position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. - - - You may also enjoy having a ham radio "HT" that covers the 70cm band... you - can use that with your antenna to direction-find the rocket on the ground - the same way you can use a Walston or Beeline tracker. This can be handy - if the rocket is hiding in sage brush or a tree, or if the last GPS position - doesn't get you close enough because the rocket dropped into a canyon, or - the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-7R at launches. - - - So, to recap, on the ground the hardware you'll need includes: - - - an antenna and feedline - - - a TeleDongle - - - a notebook computer - - - optionally, a handheld GPS receiver - - - optionally, an HT or receiver covering 435 Mhz - - - - - The best hand-held commercial directional antennas we've found for radio - direction finding rockets are from - - Arrow Antennas. - - The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. - -
-
- Data Analysis - - Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum - board. Once this data is on your computer, our postflight tools make it - easy to quickly get to the numbers everyone wants, like apogee altitude, - max acceleration, and max velocity. You can also generate and view a - standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file - useable with Google Maps and Google Earth for visualizing the flight path - in two or three dimensions! - - - Our ultimate goal is to emit a set of files for each flight that can be - published as a web page per flight, or just viewed on your local disk with - a web browser. - -
-
- Future Plans - - In the future, we intend to offer "companion boards" for the rocket that will - plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. - - - We are also working on the design of a hand-held ground terminal that will - allow monitoring the rocket's status, collecting data during flight, and - logging data after flight without the need for a notebook computer on the - flight line. Particularly since it is so difficult to read most notebook - screens in direct sunlight, we think this will be a great thing to have. - - - Because all of our work is open, both the hardware designs and the software, - if you have some great idea for an addition to the current Altus Metrum family, - feel free to dive in and help! Or let us know what you'd like to see that - we aren't already working on, and maybe we'll get excited about it too... - -
-
-
- - How GPS Works - - - Placeholder. - -
-
-
- -- cgit v1.2.3 From 15a6791ba8f8313b6b55752c3fa7dc254d56dd5c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:08:56 -0600 Subject: update changelogs for Debian build --- ChangeLog | 46 ++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 12 ++++++++++++ 2 files changed, 58 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0ac6eabb..79d801d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +commit e747954b6a9e71705f619684df8a118a909b1039 +Merge: bd40a5b 695879d +Author: Bdale Garbee +Date: Tue Jul 20 22:07:22 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit bd40a5b431847c071f5c486d754eca5627e5e3b9 +Author: Bdale Garbee +Date: Tue Jul 20 02:12:03 2010 -0600 + + significant update + +commit 695879dbccfc5ec6b79698653c58814158f91686 +Author: Keith Packard +Date: Wed Jul 14 19:07:02 2010 -0700 + + Switch DBG pins to GPIO when using any debug commands. Reboot to restore. + + If you want to use TeleMetrum as a debug dongle, you need to flip the + three pins used to talk to the remote debug port from SPI mode to GPIO + mode. + + This patch doesn't provide any way to get back to SPI mode, so you'll + have to reboot the TeleMetrum to write out config parameters or log + flight data after using any debug commands. + + Signed-off-by: Keith Packard + +commit a9ec6be0e92dee01f7aac006ef6f7779c1da1b36 +Author: Keith Packard +Date: Sat Jul 3 17:42:36 2010 -0400 + + Telemetry code was mis-computing RSSI + + The RSSI data from the hardware reports in 1/2 dBm increments, and so + must be divided to report plain RSSI numbers. + + Signed-off-by: Keith Packard + +commit 62294ea3830d3ea261a8761edc9fa6f98201d321 +Author: Bdale Garbee +Date: Thu Jun 24 12:38:23 2010 -0700 + + update changelogs for Debian build + commit 4766b13d1241fa585907c6f77707d2d4b3ccff75 Author: Bdale Garbee Date: Thu Jun 24 12:37:55 2010 -0700 diff --git a/debian/changelog b/debian/changelog index c209bcc0..6640a674 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +altos (0.6+229+ge747954) unstable; urgency=low + + [ Keith Packard ] + * Telemetry code was mis-computing RSSI + * Switch DBG pins to GPIO when using any debug commands. Reboot to + restore. + + [ Bdale Garbee ] + * significant documentation update + + -- Bdale Garbee Tue, 20 Jul 2010 22:08:06 -0600 + altos (0.6+224+g4766b13) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 0794ab1e13313fa49b7caf01aef20b052ad78a88 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:10:01 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 79d801d9..d941a732 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 15a6791ba8f8313b6b55752c3fa7dc254d56dd5c +Author: Bdale Garbee +Date: Tue Jul 20 22:08:56 2010 -0600 + + update changelogs for Debian build + commit e747954b6a9e71705f619684df8a118a909b1039 Merge: bd40a5b 695879d Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 6640a674..21740201 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+229+ge747954) unstable; urgency=low +altos (0.6+230+g15a6791) unstable; urgency=low [ Keith Packard ] * Telemetry code was mis-computing RSSI -- cgit v1.2.3 From 74c67fc466118b86b4eb5173f7a6886ae220a985 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:14:27 -0600 Subject: add build dep for sndfile --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index fb620e3d..3d572de7 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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 Standards-Version: 3.8.4 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 2cf1ef555a7feceeb1c333b273c19dd848e8d03f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:15:47 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index d941a732..0b780009 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 74c67fc466118b86b4eb5173f7a6886ae220a985 +Author: Bdale Garbee +Date: Tue Jul 20 22:14:27 2010 -0600 + + add build dep for sndfile + +commit 0794ab1e13313fa49b7caf01aef20b052ad78a88 +Author: Bdale Garbee +Date: Tue Jul 20 22:10:01 2010 -0600 + + update changelogs for Debian build + commit 15a6791ba8f8313b6b55752c3fa7dc254d56dd5c Author: Bdale Garbee Date: Tue Jul 20 22:08:56 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 21740201..516067d4 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+230+g15a6791) unstable; urgency=low +altos (0.6+232+g74c67fc) unstable; urgency=low [ Keith Packard ] * Telemetry code was mis-computing RSSI @@ -7,6 +7,7 @@ altos (0.6+230+g15a6791) unstable; urgency=low [ Bdale Garbee ] * significant documentation update + * add build dep for sndfile -- Bdale Garbee Tue, 20 Jul 2010 22:08:06 -0600 -- cgit v1.2.3 From 8f1933717e3acfbcb09191da6e79a7944f91f9d9 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:19:27 -0600 Subject: reflect documentation file name change --- debian/docs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/docs b/debian/docs index d5af59c7..6eac4541 100644 --- a/debian/docs +++ b/debian/docs @@ -1,4 +1,4 @@ NEWS README -doc/telemetrum.html -doc/telemetrum.pdf +doc/telemetrum-doc.html +doc/telemetrum-doc.pdf -- cgit v1.2.3 From 3284c7516e302e6db403d18866924ad926ffb2a7 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:20:08 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0b780009..1426bc35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 8f1933717e3acfbcb09191da6e79a7944f91f9d9 +Author: Bdale Garbee +Date: Tue Jul 20 22:19:27 2010 -0600 + + reflect documentation file name change + +commit 2cf1ef555a7feceeb1c333b273c19dd848e8d03f +Author: Bdale Garbee +Date: Tue Jul 20 22:15:47 2010 -0600 + + update changelogs for Debian build + commit 74c67fc466118b86b4eb5173f7a6886ae220a985 Author: Bdale Garbee Date: Tue Jul 20 22:14:27 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 516067d4..0c52afb2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+232+g74c67fc) unstable; urgency=low +altos (0.6+234+g8f19337) unstable; urgency=low [ Keith Packard ] * Telemetry code was mis-computing RSSI @@ -8,6 +8,7 @@ altos (0.6+232+g74c67fc) unstable; urgency=low [ Bdale Garbee ] * significant documentation update * add build dep for sndfile + * reflect documentation file name change -- Bdale Garbee Tue, 20 Jul 2010 22:08:06 -0600 -- cgit v1.2.3 From cd8aa79de72b8b6b3a26d0c2522e94c621b70f13 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:24:01 -0600 Subject: update to latest Debian standards version --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 3d572de7..590b7650 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard 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 -Standards-Version: 3.8.4 +Standards-Version: 3.9.0 Homepage: http://altusmetrum.org/AltOS Package: altos -- cgit v1.2.3 From 8eda9fe94a7fd40cb84f50e17e64956f1584ebdc Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 20 Jul 2010 22:24:32 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1426bc35..92b79ae3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit cd8aa79de72b8b6b3a26d0c2522e94c621b70f13 +Author: Bdale Garbee +Date: Tue Jul 20 22:24:01 2010 -0600 + + update to latest Debian standards version + +commit 3284c7516e302e6db403d18866924ad926ffb2a7 +Author: Bdale Garbee +Date: Tue Jul 20 22:20:08 2010 -0600 + + update changelogs for Debian build + commit 8f1933717e3acfbcb09191da6e79a7944f91f9d9 Author: Bdale Garbee Date: Tue Jul 20 22:19:27 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 0c52afb2..528ec25a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+234+g8f19337) unstable; urgency=low +altos (0.6+236+gcd8aa79) unstable; urgency=low [ Keith Packard ] * Telemetry code was mis-computing RSSI @@ -9,8 +9,9 @@ altos (0.6+234+g8f19337) unstable; urgency=low * significant documentation update * add build dep for sndfile * reflect documentation file name change + * update to latest Debian standards version - -- Bdale Garbee Tue, 20 Jul 2010 22:08:06 -0600 + -- Bdale Garbee Tue, 20 Jul 2010 22:24:14 -0600 altos (0.6+224+g4766b13) unstable; urgency=low -- cgit v1.2.3 From d0647950b76bfa9942e4f8cf87353f2b724099f4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 21 Jul 2010 14:26:36 -0600 Subject: fix text since TM only has one led to blink --- ao-bringup/turnon_telemetrum | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index e4badcfd..4086a1a8 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -32,7 +32,7 @@ read SERIAL echo $RAWLOAD $RAWLOAD -r ao_led_blink.ihx -echo "LEDs should be blinking" +echo "the red LED should be blinking" sleep 5 $RAWLOAD -r ao_radio_xmit.ihx -- cgit v1.2.3 From 05111d5be4d37bedaaee6415d6ee27347e6a112c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 12:52:17 -0700 Subject: When the EP0 IN buffer is full, don't panic, just skip sending another If the host doesn't pull the IN packet out of EP0 before sending another SETUP command along, the IN buffer will still be busy when we try to reply to the SETUP command. While I don't quite understand why this would ever happen, there's no need to panic about it, just drop the reply packet on the floor. Signed-off-by: Keith Packard --- src/ao_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ao_usb.c b/src/ao_usb.c index d071fe6f..f6e0fcf9 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -82,10 +82,11 @@ ao_usb_ep0_flush(void) __xdata uint8_t this_len; __xdata uint8_t cs0; + /* If the IN packet hasn't been picked up, just return */ USBINDEX = 0; cs0 = USBCS0; if (cs0 & USBCS0_INPKT_RDY) - ao_panic(AO_PANIC_USB); + return; this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) -- cgit v1.2.3 From c726d8f6eb861801d7543552beab6ee2c920c96f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 15:41:39 -0700 Subject: Add libaltos which talks to USB connected altos devices --- ao-tools/libaltos/Makefile | 61 ++++++ ao-tools/libaltos/cjnitest.c | 25 +++ ao-tools/libaltos/libaltos.c | 479 ++++++++++++++++++++++++++++++++++++++++++ ao-tools/libaltos/libaltos.h | 54 +++++ ao-tools/libaltos/libaltos.i0 | 5 + 5 files changed, 624 insertions(+) create mode 100644 ao-tools/libaltos/Makefile create mode 100644 ao-tools/libaltos/cjnitest.c create mode 100644 ao-tools/libaltos/libaltos.c create mode 100644 ao-tools/libaltos/libaltos.h create mode 100644 ao-tools/libaltos/libaltos.i0 diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile new file mode 100644 index 00000000..5ffbdadf --- /dev/null +++ b/ao-tools/libaltos/Makefile @@ -0,0 +1,61 @@ +.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 + +LIBEXT=dylib + +JAVAFILES=\ + $(JNI_SRCS) + +CLASSFILES = $(JAVAFILES:%.java=%.class) + +JAVAFLAGS=-Xlint:unchecked + +all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) + +.java.class: + javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + +DARWIN_CFLAGS=\ + -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -I/System/Library/Frameworks/IOKit.framework/Headers \ + -I/System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +CFLAGS = $(DARWIN_CFLAGS) -I. -O0 -g + +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) + +libaltos.$(LIBEXT): $(OBJS) + gcc -shared -o $@ $(OBJS) $(LIBS) + +clean: + rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest + +$(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) diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c new file mode 100644 index 00000000..cd3898ed --- /dev/null +++ b/ao-tools/libaltos/cjnitest.c @@ -0,0 +1,25 @@ +#include +#include "libaltos.h" + +main () +{ + struct altos_device device; + struct altos_list *list; + + altos_init(); + list = altos_list_start(); + while (altos_list_next(list, &device)) { + struct altos_file *file; + int c; + + file = altos_open(&device); + altos_putchar(file, '?'); altos_putchar(file, '\n'); altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar (c); + } + printf ("getchar returns %d\n", c); + altos_close(file); + } + altos_list_finish(list); + altos_fini(); +} diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c new file mode 100644 index 00000000..417c8fe5 --- /dev/null +++ b/ao-tools/libaltos/libaltos.c @@ -0,0 +1,479 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "libaltos.h" + +#define USE_DARWIN + +#ifdef USE_DARWIN + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct altos_list { + io_iterator_t iterator; +}; + +static int +get_string(io_object_t object, CFStringRef entry, char *result, int result_len) +{ + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); + + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; +} + +int +altos_init(void) +{ + return 1; +} + +void +altos_fini(void) +{ +} + +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); + + IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + + CFRelease(vendor_ref); + CFRelease(product_ref); + return list; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + io_object_t object; + char serial_string[128]; + + for (;;) { + object = IOIteratorNext(list->iterator); + if (!object) + return 0; + + if (get_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 Serial Number"), serial_string, sizeof (serial_string))) { + device->serial = atoi(serial_string); + return 1; + } + } +} + +void +altos_list_finish(struct altos_list *list) +{ + IOObjectRelease (list->iterator); + free(list); +} + + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +void +altos_test(char *path) +{ + int n; + char buf[16]; + int fd; + struct termios term; + + fd = open(path, O_RDWR | O_NOCTTY); + if (fd < 0) { + perror(path); + return; + } + if (ioctl(fd, TIOCEXCL, (char *) 0) < 0) { + perror("TIOCEXCL"); + close (fd); + return; + } + + n = tcgetattr(fd, &term); + if (n < 0) { + perror("tcgetattr"); + close(fd); + return; + } + cfmakeraw(&term); + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; + n = tcsetattr(fd, TCSAFLUSH, &term); + if (n < 0) { + perror("tcsetattr"); + close(fd); + return; + } + write(fd, "\n?\n", 3); + for (;;) { + n = read(fd, buf, sizeof (buf)); + if (n < 0) { + perror("read"); + break; + } + if (n == 0) + break; + write(1, buf, n); + } + close(fd); +} + +struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + int ret; + struct termios term; + + if (!file) + return NULL; + + file->fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->fd < 0) { + perror(device->path); + free(file); + return NULL; + } + ret = tcgetattr(file->fd, &term); + if (ret < 0) { + perror("tcgetattr"); + close(file->fd); + free(file); + return NULL; + } + cfmakeraw(&term); + term.c_cc[VMIN] = 0; + term.c_cc[VTIME] = 1; + ret = tcsetattr(file->fd, TCSAFLUSH, &term); + if (ret < 0) { + perror("tcsetattr"); + close(file->fd); + free(file); + return NULL; + } + return file; +} + +void +altos_close(struct altos_file *file) +{ + close(file->fd); + 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 +altos_flush(struct altos_file *file) +{ + while (file->out_used) { + int ret; + + ret = write (file->fd, file->out_data, file->out_used); + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + while (file->in_read == file->in_used) { + int ret; + + altos_flush(file); + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) + return -errno; + file->in_read = 0; + file->in_used = ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* USE_DARWIN */ + +#ifdef USE_LIBUSB +#include +#include +#include +#include + +libusb_context *usb_context; + +int altos_init(void) +{ + int ret; + ret = libusb_init(&usb_context); + if (ret) + return ret; + libusb_set_debug(usb_context, 3); + return 0; +} + +void altos_fini(void) +{ + libusb_exit(usb_context); + usb_context = NULL; +} + +static libusb_device **list; +static ssize_t num, current; + +int altos_list_start(void) +{ + if (list) + altos_list_finish(); + current = 0; + num = libusb_get_device_list(usb_context, &list); + if (num == 0) { + current = num = 0; + list = NULL; + return 0; + } + return 1; +} + +int altos_list_next(struct altos_device *device) +{ + while (current < num) { + struct libusb_device_descriptor descriptor; + libusb_device *usb_device = list[current++]; + + if (libusb_get_device_descriptor(usb_device, &descriptor) == 0) { + if (descriptor.idVendor == 0xfffe) + { + libusb_device_handle *handle; + if (libusb_open(usb_device, &handle) == 0) { + char serial_number[256]; + libusb_get_string_descriptor_ascii(handle, descriptor.iProduct, + device->product, + sizeof(device->product)); + libusb_get_string_descriptor_ascii(handle, descriptor.iSerialNumber, + serial_number, + sizeof (serial_number)); + libusb_close(handle); + device->serial = atoi(serial_number); + device->device = usb_device; + return 1; + } + } + } + } + return 0; +} + +void altos_list_finish(void) +{ + if (list) { + libusb_free_device_list(list, 1); + list = NULL; + } +} + +#define USB_BUF_SIZE 64 + +struct altos_file { + struct libusb_device *device; + struct libusb_device_handle *handle; + int out_ep; + int out_size; + int in_ep; + int in_size; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file; + struct libusb_device_handle *handle; + if (libusb_open(device->device, &handle) == 0) { + int ret; + + ret = libusb_claim_interface(handle, 1); +#if 0 + if (ret) { + libusb_close(handle); + return NULL; + } +#endif + ret = libusb_detach_kernel_driver(handle, 1); +#if 0 + if (ret) { + libusb_close(handle); + return NULL; + } +#endif + + file = calloc(sizeof (struct altos_file), 1); + file->device = libusb_ref_device(device->device); + file->handle = handle; + /* XXX should get these from the endpoint descriptors */ + file->out_ep = 4 | LIBUSB_ENDPOINT_OUT; + file->out_size = 64; + file->in_ep = 5 | LIBUSB_ENDPOINT_IN; + file->in_size = 64; + + return file; + } + return NULL; +} + +void +altos_close(struct altos_file *file) +{ + libusb_close(file->handle); + libusb_unref_device(file->device); + file->handle = NULL; + free(file); +} + +int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == file->out_size) { + ret = altos_flush(file); + if (ret) + return ret; + } + file->out_data[file->out_used++] = c; + if (file->out_used == file->out_size) + return altos_flush(file); + return 0; +} + +int +altos_flush(struct altos_file *file) +{ + while (file->out_used) { + int transferred; + int ret; + + ret = libusb_bulk_transfer(file->handle, + file->out_ep, + file->out_data, + file->out_used, + &transferred, + 0); + if (ret) + return ret; + if (transferred) { + memmove(file->out_data, file->out_data + transferred, + file->out_used - transferred); + file->out_used -= transferred; + } + } +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + while (file->in_read == file->in_used) { + int ret; + int transferred; + + altos_flush(file); + ret = libusb_bulk_transfer(file->handle, + file->in_ep, + file->in_data, + file->in_size, + &transferred, + (unsigned int) timeout); + if (ret) + return ret; + file->in_read = 0; + file->in_used = transferred; + } + return file->in_data[file->in_read++]; +} + +#endif /* USE_LIBUSB */ diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h new file mode 100644 index 00000000..782f244e --- /dev/null +++ b/ao-tools/libaltos/libaltos.h @@ -0,0 +1,54 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _LIBALTOS_H_ +#define _LIBALTOS_H_ + +struct altos_device { + //%immutable; + char product[256]; + int serial; + char path[256]; + //%mutable; +}; + +int altos_init(void); + +void altos_fini(void); + +struct altos_list * +altos_list_start(void); + +int altos_list_next(struct altos_list *list, struct altos_device *device); + +void altos_list_finish(struct altos_list *list); + +struct altos_file * +altos_open(struct altos_device *device); + +void altos_close(struct altos_file *file); + +int +altos_putchar(struct altos_file *file, char c); + +int +altos_flush(struct altos_file *file); + +int +altos_getchar(struct altos_file *file, int timeout); + +#endif /* _LIBALTOS_H_ */ diff --git a/ao-tools/libaltos/libaltos.i0 b/ao-tools/libaltos/libaltos.i0 new file mode 100644 index 00000000..d06468f5 --- /dev/null +++ b/ao-tools/libaltos/libaltos.i0 @@ -0,0 +1,5 @@ +%module libaltos +%{ +#include "libaltos.h" +%} + -- cgit v1.2.3 From 005e2d6a7bb3b0546b0c1273296875621632ec6d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 15:42:48 -0700 Subject: Switch AltosUI to libaltos for device access Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDevice.java | 35 +++++-- ao-tools/altosui/AltosDeviceDialog.java | 14 +-- ao-tools/altosui/AltosDeviceLinux.java | 172 -------------------------------- ao-tools/altosui/AltosGPS.java | 4 + ao-tools/altosui/AltosSerial.java | 72 ++++--------- ao-tools/altosui/AltosUI.java | 21 ++-- ao-tools/altosui/AltosVoice.java | 20 ++-- ao-tools/altosui/Makefile | 12 +-- 8 files changed, 78 insertions(+), 272 deletions(-) delete mode 100644 ao-tools/altosui/AltosDeviceLinux.java diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 66800c5c..8ebd3b99 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -18,13 +18,36 @@ package altosui; import java.lang.*; import java.util.*; +import libaltosJNI.*; public class AltosDevice { - String tty; /* suitable to be passed to AltosSerial.connect */ - String manufacturer; - String product; - int serial; - int idProduct; - int idVendor; + static { + System.loadLibrary("altos"); + libaltos.altos_init(); + } + static altos_device[] list(String product) { + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + SWIGTYPE_p_altos_file file; + + for (;;) { + altos_device device = new altos_device(); + if (libaltos.altos_list_next(list, device) == 0) + break; + System.out.printf("Found device %s %d %s\n", + device.getProduct(), device.getSerial(), device.getPath()); + + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + altos_device[] devices = new altos_device[device_list.size()]; + for (int i = 0; i < device_list.size(); i++) + devices[i] = device_list.get(i); + return devices; + } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index cb1eef8b..b3a0f9be 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -20,15 +20,17 @@ package altosui; import java.lang.*; import java.util.*; import javax.swing.*; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; import altosui.AltosDevice; -import altosui.AltosDeviceLinux; public class AltosDeviceDialog { - static AltosDevice show (JFrame frame, String product) { - AltosDevice[] devices = null; - if (System.getProperty("os.name").startsWith("Linux")) - devices = AltosDeviceLinux.list(product); + static altos_device show (JFrame frame, String product) { + altos_device[] devices = null; + devices = AltosDevice.list(product); if (devices != null & devices.length > 0) { Object o = JOptionPane.showInputDialog(frame, "Select a device", @@ -37,7 +39,7 @@ public class AltosDeviceDialog { null, devices, devices[0]); - return (AltosDevice) o; + return (altos_device) o; } else { return null; } diff --git a/ao-tools/altosui/AltosDeviceLinux.java b/ao-tools/altosui/AltosDeviceLinux.java deleted file mode 100644 index ffc70aff..00000000 --- a/ao-tools/altosui/AltosDeviceLinux.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; -import altosui.AltosDevice; - -public class AltosDeviceLinux extends AltosDevice { - - String load_string(File file) { - try { - FileInputStream in = new FileInputStream(file); - String result = ""; - int c; - try { - while ((c = in.read()) != -1) { - if (c == '\n') - break; - result = result + (char) c; - } - return result; - } catch (IOException ee) { - return ""; - } - } catch (FileNotFoundException ee) { - return ""; - } - } - String load_string(File dir, String name) { - return load_string(new File(dir, name)); - } - - int load_hex(File file) { - try { - return Integer.parseInt(load_string(file).trim(), 16); - } catch (NumberFormatException ee) { - return -1; - } - } - - int load_hex(File dir, String name) { - return load_hex(new File(dir, name)); - } - - int load_dec(File file) { - try { - return Integer.parseInt(load_string(file).trim()); - } catch (NumberFormatException ee) { - return -1; - } - } - - int load_dec(File dir, String name) { - return load_dec(new File(dir, name)); - } - - String usb_tty(File sys_dir) { - String base = sys_dir.getName(); - int num_configs = load_hex(sys_dir, "bNumConfigurations"); - int num_inters = load_hex(sys_dir, "bNumInterfaces"); - for (int config = 1; config <= num_configs; config++) { - for (int inter = 0; inter < num_inters; inter++) { - String endpoint_base = String.format("%s:%d.%d", - base, config, inter); - File endpoint_full = new File(sys_dir, endpoint_base); - - File[] namelist; - - /* Check for tty:ttyACMx style names */ - class tty_colon_filter implements FilenameFilter { - public boolean accept(File dir, String name) { - return name.startsWith("tty:"); - } - } - namelist = endpoint_full.listFiles(new tty_colon_filter()); - if (namelist != null && namelist.length > 0) - return new File ("/dev", namelist[0].getName().substring(4)).getPath(); - - /* Check for tty/ttyACMx style names */ - class tty_filter implements FilenameFilter { - public boolean accept(File dir, String name) { - return name.startsWith("tty"); - } - } - File tty_dir = new File(endpoint_full, "tty"); - namelist = tty_dir.listFiles(new tty_filter()); - if (namelist != null && namelist.length > 0) - return new File ("/dev", namelist[0].getName()).getPath(); - } - } - return null; - } - - public AltosDeviceLinux (File sys) { - sys = sys; - manufacturer = load_string(sys, "manufacturer"); - product = load_string(sys, "product"); - serial = load_dec(sys, "serial"); - idProduct = load_hex(sys, "idProduct"); - idVendor = load_hex(sys, "idVendor"); - tty = usb_tty(sys); - } - - public String toString() { - return String.format("%-20s %6d %-15s", product, serial, tty == null ? "" : tty); - } - static public AltosDeviceLinux[] list() { - LinkedList devices = new LinkedList(); - - class dev_filter implements FilenameFilter{ - public boolean accept(File dir, String name) { - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (Character.isDigit(c)) - continue; - if (c == '-') - continue; - if (c == '.' && i != 1) - continue; - return false; - } - return true; - } - } - - File usb_devices = new File("/sys/bus/usb/devices"); - File[] devs = usb_devices.listFiles(new dev_filter()); - if (devs != null) { - for (int e = 0; e < devs.length; e++) { - AltosDeviceLinux dev = new AltosDeviceLinux(devs[e]); - if (dev.idVendor == 0xfffe && dev.tty != null) { - devices.add(dev); - } - } - } - AltosDeviceLinux[] foo = new AltosDeviceLinux[devices.size()]; - for (int e = 0; e < devices.size(); e++) - foo[e] = devices.get(e); - return foo; - } - - static public AltosDeviceLinux[] list(String model) { - AltosDeviceLinux[] devices = list(); - if (model != null) { - LinkedList subset = new LinkedList(); - for (int i = 0; i < devices.length; i++) { - if (devices[i].product.startsWith(model)) - subset.add(devices[i]); - } - devices = new AltosDeviceLinux[subset.size()]; - for (int e = 0; e < subset.size(); e++) - devices[e] = subset.get(e); - } - return devices; - } -} diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index c3b368e2..f8eb5f48 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -90,6 +90,9 @@ public class AltosGPS { gps_connected = true; gps_time = new AltosGPSTime(); i++; + } else if ((words[i]).equals("not-connected")) { + gps_time = new AltosGPSTime(); + i++; } else if (words.length >= 40) { gps_locked = true; gps_connected = true; @@ -106,6 +109,7 @@ public class AltosGPS { v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)")); } else { gps_time = new AltosGPSTime(); + i++; } AltosParse.word(words[i++], "SAT"); int tracking_channels = 0; diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 03ab28c5..073bfb78 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -26,8 +26,11 @@ import java.io.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.LinkedList; import java.util.Iterator; -import gnu.io.*; import altosui.AltosSerialMonitor; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; /* * This class reads from the serial port and places each received @@ -35,7 +38,7 @@ import altosui.AltosSerialMonitor; * threads. */ class AltosSerialReader implements Runnable { - InputStream serial_in; + SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; Thread input_thread; @@ -46,7 +49,7 @@ class AltosSerialReader implements Runnable { try { for (;;) { - c = serial_in.read(); + c = libaltos.altos_getchar(altos, 0); if (Thread.interrupted()) break; if (c == -1) @@ -70,7 +73,6 @@ class AltosSerialReader implements Runnable { } } } - } catch (IOException e) { } catch (InterruptedException e) { } } @@ -96,16 +98,13 @@ class AltosSerialReader implements Runnable { } public boolean opened() { - return serial_in != null; + return altos != null; } public void close() { - if (serial_in != null) { - try { - serial_in.close(); - } catch (IOException e) { - } - serial_in = null; + if (altos != null) { + libaltos.altos_close(altos); + altos = null; } if (input_thread != null) { try { @@ -117,62 +116,30 @@ class AltosSerialReader implements Runnable { } } - public void open(File name) throws FileNotFoundException { - close(); - serial_in = new FileInputStream(name); - input_thread = new Thread(this); - input_thread.start(); - } - public void open(CommPort c) throws IOException { + public void open(altos_device device) throws FileNotFoundException { close(); - try { - c.enableReceiveTimeout(1000); /* icky. the read method cannot be interrupted */ - } catch (UnsupportedCommOperationException ee) { - } - serial_in = c.getInputStream(); + altos = libaltos.altos_open(device); input_thread = new Thread(this); input_thread.start(); } public AltosSerialReader () { - serial_in = null; + altos = null; input_thread = null; line = ""; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); } - } public class AltosSerial { - OutputStream serial_out = null; AltosSerialReader reader = null; - CommPort comm_port = null; - public void close() { - try { - serial_out.close(); - } catch (IOException ee) { - } reader.close(); - if (comm_port != null) { - comm_port.close(); - } - } - - public void open(File serial_name) throws FileNotFoundException { - reader.open(serial_name); - serial_out = new FileOutputStream(serial_name); } - public void open(CommPort c) throws IOException { - reader.open(c); - serial_out = c.getOutputStream(); - } - - public void connect(String port_name) throws IOException, NoSuchPortException, PortInUseException { - comm_port = new RXTXPort(port_name); - open(comm_port); + public void open(altos_device device) throws FileNotFoundException { + reader.open(device); } void init() { @@ -191,13 +158,8 @@ public class AltosSerial { init(); } - public AltosSerial(File serial_name) throws FileNotFoundException { - init(); - open(serial_name); - } - - public AltosSerial(CommPort comm_port) throws IOException { + public AltosSerial(altos_device device) throws FileNotFoundException { init(); - open(comm_port); + open(device); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 43c40799..33ed2c90 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -27,7 +27,6 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import gnu.io.*; import altosui.AltosSerial; import altosui.AltosSerialMonitor; @@ -38,6 +37,8 @@ import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; +import libaltosJNI.*; + class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; private Object[] data = { 0, "idle", 0, 0 }; @@ -475,31 +476,21 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - AltosDevice device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); + altos_device device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); if (device != null) { try { - serial_line.connect(device.tty); + serial_line.open(device); DeviceThread thread = new DeviceThread(serial_line); run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.tty, + device.getPath(), "Cannot open serial port", JOptionPane.ERROR_MESSAGE); - } catch (NoSuchPortException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.tty, - "No such serial port", - JOptionPane.ERROR_MESSAGE); - } catch (PortInUseException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.tty, - "Port in use", - JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.tty, + device.getPath(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index e4ea99a2..0c34795c 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -17,14 +17,16 @@ package altosui; -import com.sun.speech.freetts.Voice; +/*import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; -import com.sun.speech.freetts.audio.JavaClipAudioPlayer; +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; */ import java.util.concurrent.LinkedBlockingQueue; public class AltosVoice implements Runnable { +/* VoiceManager voice_manager; Voice voice; +*/ LinkedBlockingQueue phrases; Thread thread; @@ -34,29 +36,29 @@ public class AltosVoice implements Runnable { try { for (;;) { String s = phrases.take(); - voice.speak(s); +/* voice.speak(s); */ } } catch (InterruptedException e) { } } public void speak(String s) { try { - if (voice != null) +/* if (voice != null) */ phrases.put(s); } catch (InterruptedException e) { } } public AltosVoice () { - voice_manager = VoiceManager.getInstance(); +/* voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); - if (voice != null) { - voice.allocate(); + if (voice != null) */ { +/* voice.allocate(); */ phrases = new LinkedBlockingQueue (); thread = new Thread(this); thread.start(); speak("Rocket Flight Monitor Ready"); - } else { + } /* else { System.out.printf("Voice manager failed to open %s\n", voice_name); Voice[] voices = voice_manager.getVoices(); System.out.printf("Available voices:\n"); @@ -64,6 +66,6 @@ public class AltosVoice implements Runnable { System.out.println(" " + voices[i].getName() + " (" + voices[i].getDomain() + " domain)"); } - } + } */ } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 57c889b8..1c49ba11 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 +CLASSPATH=..:../libaltos:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -15,24 +15,18 @@ CLASSFILES=\ AltosTelemetry.class \ AltosUI.class \ AltosDevice.class \ - AltosDeviceLinux.class \ AltosDeviceDialog.class \ AltosVoice.class JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) altosui altosui.jar +all: $(CLASSFILES) altosui.jar .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui: Makefile - (echo '#!/bin/sh'; \ - echo exec java -cp '"$(CLASSPATH)"' altosui/AltosUI) > $@ - chmod +x $@ - altosui.jar: $(CLASSFILES) Manifest.txt - cd .. && jar cfm altosui/$@ altosui/Manifest.txt altosui/*.class + jar cfm $@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class clean: rm -f *.class -- cgit v1.2.3 From 17188f36fe18c23bc2eb877ac9a01b7693f4b863 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 17:03:47 -0700 Subject: Present list of altos devices in nice format --- ao-tools/altosui/AltosDevice.java | 18 ++++++++++-------- ao-tools/altosui/AltosDeviceDialog.java | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 8ebd3b99..0e7d01da 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -20,32 +20,34 @@ import java.lang.*; import java.util.*; import libaltosJNI.*; -public class AltosDevice { +public class AltosDevice extends altos_device { + + public String toString() { + return String.format("%-20.20s %4d %s", + getProduct(), getSerial(), getPath()); + } static { System.loadLibrary("altos"); libaltos.altos_init(); } - static altos_device[] list(String product) { + static AltosDevice[] list(String product) { SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - ArrayList device_list = new ArrayList(); + ArrayList device_list = new ArrayList(); if (list != null) { SWIGTYPE_p_altos_file file; for (;;) { - altos_device device = new altos_device(); + AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; - System.out.printf("Found device %s %d %s\n", - device.getProduct(), device.getSerial(), device.getPath()); - device_list.add(device); } libaltos.altos_list_finish(list); } - altos_device[] devices = new altos_device[device_list.size()]; + AltosDevice[] devices = new AltosDevice[device_list.size()]; for (int i = 0; i < device_list.size(); i++) devices[i] = device_list.get(i); return devices; diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index b3a0f9be..eb70877c 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -29,7 +29,7 @@ import altosui.AltosDevice; public class AltosDeviceDialog { static altos_device show (JFrame frame, String product) { - altos_device[] devices = null; + AltosDevice[] devices; devices = AltosDevice.list(product); if (devices != null & devices.length > 0) { Object o = JOptionPane.showInputDialog(frame, -- cgit v1.2.3 From e9153c4f2c71ed965822fcfe5112d2bc38506baf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 17:04:04 -0700 Subject: Re-enable freetts --- ao-tools/altosui/AltosVoice.java | 20 +++++++++----------- ao-tools/altosui/Makefile | 2 +- ao-tools/altosui/Manifest.txt | 1 + 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index 0c34795c..e4ea99a2 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -17,16 +17,14 @@ package altosui; -/*import com.sun.speech.freetts.Voice; +import com.sun.speech.freetts.Voice; import com.sun.speech.freetts.VoiceManager; -import com.sun.speech.freetts.audio.JavaClipAudioPlayer; */ +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; import java.util.concurrent.LinkedBlockingQueue; public class AltosVoice implements Runnable { -/* VoiceManager voice_manager; Voice voice; -*/ LinkedBlockingQueue phrases; Thread thread; @@ -36,29 +34,29 @@ public class AltosVoice implements Runnable { try { for (;;) { String s = phrases.take(); -/* voice.speak(s); */ + voice.speak(s); } } catch (InterruptedException e) { } } public void speak(String s) { try { -/* if (voice != null) */ + if (voice != null) phrases.put(s); } catch (InterruptedException e) { } } public AltosVoice () { -/* voice_manager = VoiceManager.getInstance(); + voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); - if (voice != null) */ { -/* voice.allocate(); */ + if (voice != null) { + voice.allocate(); phrases = new LinkedBlockingQueue (); thread = new Thread(this); thread.start(); speak("Rocket Flight Monitor Ready"); - } /* else { + } else { System.out.printf("Voice manager failed to open %s\n", voice_name); Voice[] voices = voice_manager.getVoices(); System.out.printf("Available voices:\n"); @@ -66,6 +64,6 @@ public class AltosVoice implements Runnable { System.out.println(" " + voices[i].getName() + " (" + voices[i].getDomain() + " domain)"); } - } */ + } } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 1c49ba11..4068eebe 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:../libaltos:/usr/share/java/*:/home/keithp/src/freetts/freetts-1.2.2 +CLASSPATH=..:../libaltos:/usr/share/java/*:/Users/keithp/freetts-1.2.2/lib/* CLASSFILES=\ AltosConvert.class \ AltosFile.class \ diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 0305fcfb..251ce2a0 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1 +1,2 @@ Main-Class: altosui.AltosUI +Class-Path: freetts.jar -- cgit v1.2.3 From b51497597868a40df039dd3ca11b35a6258bbbb3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 18:04:10 -0700 Subject: Re-enable Linux support for altosui. This steals code from cc-usbdev for scanning the USB tree and uses the same tty code as on Darwin Signed-off-by: Keith Packard --- ao-tools/altosui/Manifest.txt | 2 +- ao-tools/libaltos/Makefile | 39 +++- ao-tools/libaltos/libaltos.c | 476 +++++++++++++++++++++++++++++++++++------- 3 files changed, 430 insertions(+), 87 deletions(-) diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 251ce2a0..7dbaafff 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: freetts.jar +Class-Path: /home/keithp/src/freetts/freetts-1.2.2/lib/freetts.jar diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 5ffbdadf..5cdc0fa7 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,3 +1,29 @@ +OS:=$(shell uname) + +ifeq ($(OS),Linux) + +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -I. + +OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +LIBEXT=so + +endif + +ifeq ($(OS),Darwin) + +DARWIN_CFLAGS=\ + -I/System/Library/Frameworks/JavaVM.framework/Headers \ + -I/System/Library/Frameworks/IOKit.framework/Headers \ + -I/System/Library/Frameworks/CoreFoundation.framework/Headers +DARWIN_LIBS=\ + -framework IOKit -framework CoreFoundation + +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY +LIBEXT=dylib + +endif + .SUFFIXES: .java .class CLASSPATH=".:jnitest/*:libaltosJNI:/usr/share/java/*" @@ -14,8 +40,6 @@ JNI_SRCS=$(JNI_FILE) \ $(JNI_DIR)/altos_device.java \ $(JNI_DIR)/libaltos.java -LIBEXT=dylib - JAVAFILES=\ $(JNI_SRCS) @@ -28,14 +52,7 @@ all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -DARWIN_CFLAGS=\ - -I/System/Library/Frameworks/JavaVM.framework/Headers \ - -I/System/Library/Frameworks/IOKit.framework/Headers \ - -I/System/Library/Frameworks/CoreFoundation.framework/Headers -DARWIN_LIBS=\ - -framework IOKit -framework CoreFoundation - -CFLAGS = $(DARWIN_CFLAGS) -I. -O0 -g +CFLAGS=$(OS_CFLAGS) -O0 -g HEADERS=libaltos.h SRCS = libaltos.c $(SWIG_WRAP) @@ -46,7 +63,7 @@ cjnitest: cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) libaltos.$(LIBEXT): $(OBJS) - gcc -shared -o $@ $(OBJS) $(LIBS) + gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) clean: rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 417c8fe5..7d471f38 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -16,10 +16,379 @@ */ #include "libaltos.h" +#include +#include +#include + +static int +match_dev(char *product, int serial, struct altos_device *device) +{ + struct altos_list *list; + int i; + + list = altos_list_start(); + if (!list) + return 0; + while ((i = altos_list_next(list, device)) != 0) { + if (product && strncmp (product, device->product, strlen(product)) != 0) + continue; + if (serial && serial != device->serial) + continue; + break; + } + altos_list_finish(list); + return i; +} + +int +altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) +{ + char *product; + int serial; + char *end; + char *colon; + int ret; + + if (arg) + { + /* check for */ + serial = strtol(arg, &end, 0); + if (end != arg) { + if (*end != '\0') + return 0; + product = NULL; + } else { + /* check for : */ + colon = strchr(arg, ':'); + if (colon) { + product = strndup(arg, colon - arg); + serial = strtol(colon + 1, &end, 0); + if (*end != '\0') + return 0; + } else { + product = arg; + serial = 0; + } + } + } else { + product = NULL; + serial = 0; + } + if (!product && default_product) + ret = match_dev(default_product, serial, device); + if (!ret) + ret = match_dev(product, serial, device); + if (product && product != arg) + free(product); + return ret; +} + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} -#define USE_DARWIN +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; -#ifdef USE_DARWIN +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product = load_string(sys, "product"); + usbdev->serial = load_dec(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +static void +usbdev_free(struct altos_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct altos_list { + struct altos_usbdev **dev; + int current; + int ndev; +}; + +int +altos_init(void) +{ + return 1; +} + +void +altos_fini(void) +{ +} + +struct altos_list * +altos_list_start(void) +{ + int e; + struct dirent **ents; + char *dir; + struct altos_usbdev *dev; + struct altos_list *devs; + int n; + + devs = calloc(1, sizeof (struct altos_list)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (dev->idVendor == 0xfffe && dev->tty) { + if (devs->dev) + devs->dev = realloc(devs->dev, + devs->ndev + 1 * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + } + free(ents); + devs->current = 0; + return devs; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + struct altos_usbdev *dev; + if (list->current >= list->ndev) + return 0; + dev = list->dev[list->current]; + strcpy(device->product, dev->product); + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +#endif + +#ifdef DARWIN #include #include @@ -30,36 +399,32 @@ #include #include #include -#include -#include -#include -#include struct altos_list { - io_iterator_t iterator; + io_iterator_t iterator; }; static int get_string(io_object_t object, CFStringRef entry, char *result, int result_len) { - CFTypeRef entry_as_string; - Boolean got_string; - - entry_as_string = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_string) { - got_string = CFStringGetCString(entry_as_string, - result, result_len, - kCFStringEncodingASCII); + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); - CFRelease(entry_as_string); - if (got_string) - return 1; - } - return 0; + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; } int @@ -117,10 +482,19 @@ altos_list_next(struct altos_list *list, struct altos_device *device) void altos_list_finish(struct altos_list *list) { - IOObjectRelease (list->iterator); - free(list); + IOObjectRelease (list->iterator); + free(list); } +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include #define USB_BUF_SIZE 64 @@ -133,54 +507,6 @@ struct altos_file { int in_read; }; -void -altos_test(char *path) -{ - int n; - char buf[16]; - int fd; - struct termios term; - - fd = open(path, O_RDWR | O_NOCTTY); - if (fd < 0) { - perror(path); - return; - } - if (ioctl(fd, TIOCEXCL, (char *) 0) < 0) { - perror("TIOCEXCL"); - close (fd); - return; - } - - n = tcgetattr(fd, &term); - if (n < 0) { - perror("tcgetattr"); - close(fd); - return; - } - cfmakeraw(&term); - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; - n = tcsetattr(fd, TCSAFLUSH, &term); - if (n < 0) { - perror("tcsetattr"); - close(fd); - return; - } - write(fd, "\n?\n", 3); - for (;;) { - n = read(fd, buf, sizeof (buf)); - if (n < 0) { - perror("read"); - break; - } - if (n == 0) - break; - write(1, buf, n); - } - close(fd); -} - struct altos_file * altos_open(struct altos_device *device) { @@ -273,7 +599,7 @@ altos_getchar(struct altos_file *file, int timeout) return file->in_data[file->in_read++]; } -#endif /* USE_DARWIN */ +#endif /* POSIX_TTY */ #ifdef USE_LIBUSB #include -- cgit v1.2.3 From 0a782026f6b19e84ffd44f1ae1b466363474bd30 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 18:10:07 -0700 Subject: Darwin doesn't have strndup. This provides a private version of this GNU extension. Signed-off-by: Keith Packard --- ao-tools/libaltos/libaltos.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 7d471f38..df0d5b2e 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -40,6 +40,26 @@ match_dev(char *product, int serial, struct altos_device *device) return i; } +#ifdef DARWIN +/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */ +static char * +altos_strndup (const char *s, size_t n) +{ + size_t len = strlen (s); + char *ret; + + if (len <= n) + return strdup (s); + ret = malloc(n + 1); + strncpy(ret, s, n); + ret[n] = '\0'; + return ret; +} + +#else +#define altos_strndup strndup +#endif + int altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) { @@ -61,7 +81,7 @@ altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) /* check for : */ colon = strchr(arg, ':'); if (colon) { - product = strndup(arg, colon - arg); + product = altos_strndup(arg, colon - arg); serial = strtol(colon + 1, &end, 0); if (*end != '\0') return 0; -- cgit v1.2.3 From fb8507975c6e081de2e909eca6faaa8f868b609e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:08:38 -0700 Subject: libaltos needs -I. on all systems Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 5cdc0fa7..7ed45b78 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -2,7 +2,7 @@ OS:=$(shell uname) ifeq ($(OS),Linux) -JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -I. +JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) @@ -52,7 +52,7 @@ all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -CFLAGS=$(OS_CFLAGS) -O0 -g +CFLAGS=$(OS_CFLAGS) -O0 -g -I. HEADERS=libaltos.h SRCS = libaltos.c $(SWIG_WRAP) -- cgit v1.2.3 From 4e3285575e0c7d029e799258587e965779990099 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:09:18 -0700 Subject: libaltos: make clean remove all built files Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 7ed45b78..7463a95c 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -66,7 +66,8 @@ libaltos.$(LIBEXT): $(OBJS) gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) clean: - rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest + rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o + rm -rf swig_bindings libaltosJNI $(JNI_FILE): libaltos.i0 $(HEADERS) mkdir -p $(SWIG_DIR) -- cgit v1.2.3 From a58c44cd904e5429b807e5c23913051ed6484edc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:09:41 -0700 Subject: libaltos: build fat 10.5-compatible library Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 7463a95c..0bbd304c 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -13,13 +13,14 @@ endif ifeq ($(OS),Darwin) DARWIN_CFLAGS=\ - -I/System/Library/Frameworks/JavaVM.framework/Headers \ - -I/System/Library/Frameworks/IOKit.framework/Headers \ - -I/System/Library/Frameworks/CoreFoundation.framework/Headers + --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 DARWIN_LIBS=\ -framework IOKit -framework CoreFoundation -OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY +OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 LIBEXT=dylib endif @@ -63,7 +64,7 @@ cjnitest: cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) libaltos.$(LIBEXT): $(OBJS) - gcc -shared -o $@ $(CFLAGS) $(OBJS) $(LIBS) + gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) clean: rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o -- cgit v1.2.3 From 2c273710ea9b76ebee4101893f9fe84be8a02354 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:11:58 -0700 Subject: Add Mac OS X packaging files for altosui --- .../libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml | 1 + ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml | 1 + ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml | 1 + 3 files changed, 3 insertions(+) create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml create mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml new file mode 100644 index 00000000..e19a1e4c --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml new file mode 100644 index 00000000..5d84e5f0 --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml @@ -0,0 +1 @@ +org.altusmetrum.altosUi.AltosUI.pkg1.0/Users/keithp/AltosUI.app/Applications/AltosUI.appinstallTo.pathparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml new file mode 100644 index 00000000..1277db62 --- /dev/null +++ b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml @@ -0,0 +1 @@ +AltOS UI/Users/keithp/Documents/AltosUI.pkgorg.altusmetrum01altosui.xmlproperties.title \ No newline at end of file -- cgit v1.2.3 From 3784578a40dcc61f447435cfdf22e13c409cb9c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 00:16:15 -0700 Subject: Add application icons for Mac OS X --- ao-tools/altosui/AltosUIIcon.icns | Bin 0 -> 129010 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 ao-tools/altosui/AltosUIIcon.icns diff --git a/ao-tools/altosui/AltosUIIcon.icns b/ao-tools/altosui/AltosUIIcon.icns new file mode 100644 index 00000000..fe49f362 Binary files /dev/null and b/ao-tools/altosui/AltosUIIcon.icns differ -- cgit v1.2.3 From 809feb75e2155e84aebfcc431867edcfd9054670 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 01:22:56 -0700 Subject: Clean up altosui build a bit --- ao-tools/Makefile.am | 2 +- ao-tools/altosui/Makefile | 35 +++++++++++++++++++++++++++++++---- ao-tools/altosui/Manifest.txt | 2 +- ao-tools/altosui/voices.txt | 1 - 4 files changed, 33 insertions(+), 7 deletions(-) delete mode 100644 ao-tools/altosui/voices.txt diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 2850e909..54dc777a 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view libaltos altosui diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 4068eebe..aa0278a8 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=..:../libaltos:/usr/share/java/*:/Users/keithp/freetts-1.2.2/lib/* +CLASSPATH=classes:./* CLASSFILES=\ AltosConvert.class \ AltosFile.class \ @@ -18,15 +18,42 @@ CLASSFILES=\ AltosDeviceDialog.class \ AltosVoice.class +FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2 +FREETTSLIB=$(FREETTSSRC)/lib +FREETTSJAR= \ + cmudict04.jar \ + cmulex.jar \ + cmu_time_awb.jar \ + cmutimelex.jar \ + cmu_us_kal.jar \ + en_us.jar \ + freetts.jar \ + freetts-jsapi10.jar \ + jsapi.jar + JAVAFLAGS=-Xlint:unchecked -all: $(CLASSFILES) altosui.jar +all: altosui.jar + +$(CLASSFILES): classes/altosui classes/libaltosJNI $(FREETTSJAR) .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java altosui.jar: $(CLASSFILES) Manifest.txt - jar cfm $@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class + cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class + +classes/altosui: + mkdir -p classes + ln -s .. classes/altosui + +classes/libaltosJNI: + mkdir -p classes + ln -s ../../libaltos/libaltosJNI classes/libaltosJNI + +$(FREETTSJAR): + ln -s $(FREETTSLIB)/$@ . clean: - rm -f *.class + rm -f *.class $(FREETTSJAR) altosui.jar + rm -rf classes diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 7dbaafff..251ce2a0 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: /home/keithp/src/freetts/freetts-1.2.2/lib/freetts.jar +Class-Path: freetts.jar diff --git a/ao-tools/altosui/voices.txt b/ao-tools/altosui/voices.txt deleted file mode 100644 index e8825fc3..00000000 --- a/ao-tools/altosui/voices.txt +++ /dev/null @@ -1 +0,0 @@ -com.sun.speech.freetts.en.us.cmu_us_kal.KevinVoiceDirectory -- cgit v1.2.3 From 734cd15ccff691f851359518ce6118f29dc9f88d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 10:18:09 -0700 Subject: Remove directories as .class file dependencies; it makes them get rebuilt all the time --- ao-tools/altosui/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index aa0278a8..cd123023 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -35,12 +35,12 @@ JAVAFLAGS=-Xlint:unchecked all: altosui.jar -$(CLASSFILES): classes/altosui classes/libaltosJNI $(FREETTSJAR) +$(CLASSFILES): .java.class: javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui.jar: $(CLASSFILES) Manifest.txt +altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Manifest.txt cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class classes/altosui: -- cgit v1.2.3 From 8f2f38f2a9fb0c106e2c6b60cdc205292ce329ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 10:18:20 -0700 Subject: Java clean ups -- use varargs where possible, remove AltosSerialReader Add methods that format stuff using String.format for voice and serial link, remove AltosSerialReader class and just embed that in the AltosSerial class directly. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 53 +++++++++++++-------------------------- ao-tools/altosui/AltosUI.java | 28 ++++++++------------- ao-tools/altosui/AltosVoice.java | 4 +++ 3 files changed, 32 insertions(+), 53 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 073bfb78..e84f5b63 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -37,7 +37,9 @@ import libaltosJNI.SWIGTYPE_p_altos_list; * line in a queue. Dealing with that queue is left up to other * threads. */ -class AltosSerialReader implements Runnable { + +public class AltosSerial implements Runnable { + SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; @@ -116,13 +118,27 @@ class AltosSerialReader implements Runnable { } } + public void putc(char c) { + libaltos.altos_putchar(altos, c); + } + + public void print(String data) { + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); + } + + public void printf(String format, Object ... arguments) { + print(String.format(format, arguments)); + } + public void open(altos_device device) throws FileNotFoundException { close(); altos = libaltos.altos_open(device); input_thread = new Thread(this); input_thread.start(); } - public AltosSerialReader () { + + public AltosSerial() { altos = null; input_thread = null; line = ""; @@ -130,36 +146,3 @@ class AltosSerialReader implements Runnable { reply_queue = new LinkedBlockingQueue (); } } - -public class AltosSerial { - AltosSerialReader reader = null; - - public void close() { - reader.close(); - } - - public void open(altos_device device) throws FileNotFoundException { - reader.open(device); - } - - void init() { - reader = new AltosSerialReader(); - } - - public void add_monitor(LinkedBlockingQueue q) { - reader.add_monitor(q); - } - - public void remove_monitor(LinkedBlockingQueue q) { - reader.remove_monitor(q); - } - - public AltosSerial() { - init(); - } - - public AltosSerial(altos_device device) throws FileNotFoundException { - init(); - open(device); - } -} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 33ed2c90..43aae295 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -221,16 +221,8 @@ public class AltosUI extends JFrame { flightInfoModel[col].addRow(name, value); } - public void info_add_row(int col, String name, String format, Object value) { - flightInfoModel[col].addRow(name, String.format(format, value)); - } - - public void info_add_row(int col, String name, String format, Object v1, Object v2) { - flightInfoModel[col].addRow(name, String.format(format, v1, v2)); - } - - public void info_add_row(int col, String name, String format, Object v1, Object v2, Object v3) { - flightInfoModel[col].addRow(name, String.format(format, v1, v2, v3)); + public void info_add_row(int col, String name, String format, Object... parameters) { + flightInfoModel[col].addRow(name, String.format(format, parameters)); } public void info_add_deg(int col, String name, double v, int pos, int neg) { @@ -367,7 +359,7 @@ public class AltosUI extends JFrame { /* If the rocket isn't on the pad, then report height */ if (state.state > AltosTelemetry.ao_flight_pad) { - voice.speak(String.format("%d meters", (int) (state.height + 0.5))); + voice.speak("%d meters", (int) (state.height + 0.5)); } /* If the rocket is coming down, check to see if it has landed; @@ -383,9 +375,9 @@ public class AltosUI extends JFrame { else voice.speak("rocket may have crashed"); if (state.gps != null) - voice.speak(String.format("bearing %d degrees, range %d meters", - (int) (state.from_pad.bearing + 0.5), - (int) (state.from_pad.distance + 0.5))); + voice.speak("bearing %d degrees, range %d meters", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5)); ++reported_landing; } } @@ -403,12 +395,12 @@ public class AltosUI extends JFrame { voice.speak(state.data.state); switch (state.state) { case AltosTelemetry.ao_flight_fast: - voice.speak(String.format("max speed %d meters per second", - (int) (state.max_speed + 0.5))); + voice.speak("max speed %d meters per second", + (int) (state.max_speed + 0.5)); break; case AltosTelemetry.ao_flight_drogue: - voice.speak(String.format("max height %d meters", - (int) (state.max_height + 0.5))); + voice.speak("max height %d meters", + (int) (state.max_height + 0.5)); break; } } diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index e4ea99a2..c39bfb9b 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -47,6 +47,10 @@ public class AltosVoice implements Runnable { } } + public void speak(String format, Object... parameters) { + speak(String.format(format, parameters)); + } + public AltosVoice () { voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); -- cgit v1.2.3 From 81bf2042ca39eb106b789e5a08647c3114669358 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 15:29:28 -0700 Subject: Java voice reporting cleanups. Make sure it says something at the end of a log file replay. Make sure it reports max speed after motor burn out, and max height after apogee. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 110 ++++++++++++++++++++++++------------------ 1 file changed, 64 insertions(+), 46 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 43aae295..3dfc8952 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -338,48 +338,57 @@ public class AltosUI extends JFrame { class IdleThread extends Thread { private AltosState state; + int reported_landing; + + public void report(boolean last) { + if (state == null) + return; + + /* reset the landing count once we hear about a new flight */ + if (state.state < AltosTelemetry.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) { + return; + } + + /* If the rocket isn't on the pad, then report height */ + if (state.state > AltosTelemetry.ao_flight_pad) { + voice.speak("%d meters", (int) (state.height + 0.5)); + } else { + reported_landing = 0; + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (!state.ascent && + (last || + System.currentTimeMillis() - state.report_time >= 15000 || + state.state == AltosTelemetry.ao_flight_landed)) + { + if (Math.abs(state.baro_speed) < 20 && state.height < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.gps != null) + voice.speak("bearing %d degrees, range %d meters", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5)); + ++reported_landing; + } + } public void run () { - int reported_landing = 0; + reported_landing = 0; state = null; try { for (;;) { Thread.sleep(10000); - if (state == null) - continue; - - /* reset the landing count once we hear about a new flight */ - if (state.state < AltosTelemetry.ao_flight_drogue) - reported_landing = 0; - - /* Shut up once the rocket is on the ground */ - if (reported_landing > 2) - continue; - - /* If the rocket isn't on the pad, then report height */ - if (state.state > AltosTelemetry.ao_flight_pad) { - voice.speak("%d meters", (int) (state.height + 0.5)); - } - - /* If the rocket is coming down, check to see if it has landed; - * either we've got a landed report or we haven't heard from it in - * a long time - */ - if (!state.ascent && - (System.currentTimeMillis() - state.report_time > 10000 || - state.state == AltosTelemetry.ao_flight_landed)) - { - if (Math.abs(state.baro_speed) < 20 && state.height < 100) - voice.speak("rocket landed safely"); - else - voice.speak("rocket may have crashed"); - if (state.gps != null) - voice.speak("bearing %d degrees, range %d meters", - (int) (state.from_pad.bearing + 0.5), - (int) (state.from_pad.distance + 0.5)); - ++reported_landing; - } + report(false); } } catch (InterruptedException ie) { } @@ -393,21 +402,22 @@ public class AltosUI extends JFrame { private void tell(AltosState state, AltosState old_state) { if (old_state == null || old_state.state != state.state) { voice.speak(state.data.state); - switch (state.state) { - case AltosTelemetry.ao_flight_fast: - voice.speak("max speed %d meters per second", + if ((old_state == null || old_state.state <= AltosTelemetry.ao_flight_boost) && + state.state > AltosTelemetry.ao_flight_boost) { + voice.speak("max speed: %d meters per second.", (int) (state.max_speed + 0.5)); - break; - case AltosTelemetry.ao_flight_drogue: - voice.speak("max height %d meters", + } else if ((old_state == null || old_state.state < AltosTelemetry.ao_flight_drogue) && + state.state >= AltosTelemetry.ao_flight_drogue) { + voice.speak("max height: %d meters.", (int) (state.max_height + 0.5)); - break; } } old_state = state; } class DisplayThread extends Thread { + IdleThread idle_thread; + String read() throws InterruptedException { return null; } void close() { } @@ -418,7 +428,8 @@ public class AltosUI extends JFrame { String line; AltosState state = null; AltosState old_state = null; - IdleThread idle_thread = new IdleThread(); + + idle_thread = new IdleThread(); info_reset(); info_finish(); @@ -444,6 +455,11 @@ public class AltosUI extends JFrame { idle_thread.interrupt(); } } + + public void report() { + if (idle_thread != null) + idle_thread.report(true); + } } class DeviceThread extends DisplayThread { @@ -500,8 +516,9 @@ public class AltosUI extends JFrame { while ((c = s.read()) != -1) { if (c == '\r') continue; - if (c == '\n') + if (c == '\n') { return line; + } line = line + (char) c; } return null; @@ -537,12 +554,13 @@ public class AltosUI extends JFrame { replay.close(); } catch (IOException ee) { } + report(); } void update(AltosState state) throws InterruptedException { /* Make it run in realtime after the rocket leaves the pad */ if (state.state > AltosTelemetry.ao_flight_pad) - Thread.sleep((int) (state.time_change * 1000)); + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); } } @@ -583,7 +601,7 @@ public class AltosUI extends JFrame { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, filename, - "Cannot open serial port", + "Cannot open telemetry file", JOptionPane.ERROR_MESSAGE); } } -- cgit v1.2.3 From 554a97ef455c801dcab825815f44520f96f4c3f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jul 2010 19:29:38 -0700 Subject: Force java source encoding to UTF-8 --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 4068eebe..39d1a70c 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -23,7 +23,7 @@ JAVAFLAGS=-Xlint:unchecked all: $(CLASSFILES) altosui.jar .java.class: - javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java altosui.jar: $(CLASSFILES) Manifest.txt jar cfm $@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class -- cgit v1.2.3 From f2a006fd98045066bdf429cc142d033e9feb0a8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 09:31:09 -0700 Subject: Make ao_log_data re-entrant as it is used for both sensor and GPS logs Because ao_log_data is called from two different threads, failing to make it re-entrant would cause the 'log' pointer parameter to get overwritten if another thread asked to log data while the eeprom was busy writing out a block. This would cause the second thread to re-writing data from the first thread's address, but without re-checksumming the data as the checksum is computed before the log mutex is taken. The bug can be seen by log blocks with invalid checksums. Here's what happens with the ao_gps_tracking_report and ao_log threads: ao_gps_tracking_report ao_log Writes a bunch of records *blocks* in the eeprom flush sets ao_log_data 'log' to global 'log' computes checksum for 'log' block *blocks* on ao_log_mutex Wakes up sets ao_log_data 'log' to 'gps_log' writes remaining records 'gps_log' is left with svid = 0 *blocks* on ao_gps_tracking_data writes data, reading from the current ao_log_data 'log' pointer which points at 'gps_log' Making ao_log_data re-entrant fixes this by ensuring that the 'ao_log' thread has its own copy of the ao_log_data 'log' parameter. I made this function take an __xdata restricted pointer so that it could be passed in the dptr register instead of needing to go on the stack. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_log.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index dfff8a8d..5dd756da 100644 --- a/src/ao.h +++ b/src/ao.h @@ -562,7 +562,7 @@ struct ao_log_record { /* Write a record to the eeprom log */ void -ao_log_data(struct ao_log_record *log); +ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the log */ void diff --git a/src/ao_log.c b/src/ao_log.c index 44ce90e0..d550d408 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -23,7 +23,7 @@ static __xdata uint8_t ao_log_running; static __xdata uint8_t ao_log_mutex; static uint8_t -ao_log_csum(uint8_t *b) +ao_log_csum(__xdata uint8_t *b) __reentrant { uint8_t sum = 0x5a; uint8_t i; @@ -34,11 +34,11 @@ ao_log_csum(uint8_t *b) } void -ao_log_data(struct ao_log_record *log) +ao_log_data(__xdata struct ao_log_record *log) __reentrant { /* set checksum */ log->csum = 0; - log->csum = ao_log_csum((uint8_t *) log); + log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { if (ao_log_running) { ao_ee_write(ao_log_current_pos, -- cgit v1.2.3 From e76b9cc32bbcc5176d9bdd6f8d79778024627382 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 12:24:53 -0700 Subject: altosui: Catch errors opening USB devices. Limit list to relevant devices Avoids a segfault when failing to open a device. Limit listed telemetry devices to just TeleDongle units. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDevice.java | 3 ++- ao-tools/altosui/AltosDeviceDialog.java | 4 ++++ ao-tools/altosui/AltosSerial.java | 2 ++ ao-tools/altosui/AltosUI.java | 5 +++-- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 0e7d01da..f488174c 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -42,7 +42,8 @@ public class AltosDevice extends altos_device { AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; - device_list.add(device); + if (product == null || device.getProduct().startsWith(product)) + device_list.add(device); } libaltos.altos_list_finish(list); } diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index eb70877c..08921c3d 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -41,6 +41,10 @@ public class AltosDeviceDialog { devices[0]); return (altos_device) o; } else { + JOptionPane.showMessageDialog(frame, + "No AltOS devices available", + "No AltOS devices", + JOptionPane.ERROR_MESSAGE); return null; } } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index e84f5b63..b016c1d6 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -134,6 +134,8 @@ public class AltosSerial implements Runnable { public void open(altos_device device) throws FileNotFoundException { close(); altos = libaltos.altos_open(device); + if (altos == null) + throw new FileNotFoundException(device.getPath()); input_thread = new Thread(this); input_thread.start(); } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 3dfc8952..5c92b9b4 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -493,8 +493,9 @@ public class AltosUI extends JFrame { run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.getPath(), - "Cannot open serial port", + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, -- cgit v1.2.3 From 71da54a5ce255395376a44586782ab8b6f3b289f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 13:01:52 -0700 Subject: Make voice and channel menus work. Stores voice and channel data to preferences. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosPreferences.java | 40 ++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosSerial.java | 14 +++++++++++- ao-tools/altosui/AltosUI.java | 18 +++++++++++---- ao-tools/altosui/AltosVoice.java | 9 ++++++-- 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java index 0296d935..297e1aae 100644 --- a/ao-tools/altosui/AltosPreferences.java +++ b/ao-tools/altosui/AltosPreferences.java @@ -31,6 +31,12 @@ class AltosPreferences { /* logdir preference name */ final static String logdirPreference = "LOGDIR"; + /* channel preference name */ + final static String channelPreference = "CHANNEL"; + + /* voice preference name */ + final static String voicePreference = "VOICE"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -40,6 +46,12 @@ class AltosPreferences { /* Log directory */ static File logdir; + /* Telemetry channel */ + static int channel; + + /* Voice preference */ + static boolean voice; + public static void init(Component ui) { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -55,6 +67,10 @@ class AltosPreferences { if (!logdir.exists()) logdir.mkdirs(); } + + channel = preferences.getInt(channelPreference, 0); + + voice = preferences.getBoolean(voicePreference, true); } static void flush_preferences() { @@ -114,4 +130,28 @@ class AltosPreferences { public static File logdir() { return logdir; } + + public static void set_channel(int new_channel) { + channel = new_channel; + synchronized (preferences) { + preferences.putInt(channelPreference, channel); + flush_preferences(); + } + } + + public static int channel() { + return channel; + } + + public static void set_voice(boolean new_voice) { + voice = new_voice; + synchronized (preferences) { + preferences.putBoolean(voicePreference, voice); + flush_preferences(); + } + } + + public static boolean voice() { + return voice; + } } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index b016c1d6..f12b31b3 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -119,7 +119,8 @@ public class AltosSerial implements Runnable { } public void putc(char c) { - libaltos.altos_putchar(altos, c); + if (altos != null) + libaltos.altos_putchar(altos, c); } public void print(String data) { @@ -138,6 +139,17 @@ public class AltosSerial implements Runnable { throw new FileNotFoundException(device.getPath()); input_thread = new Thread(this); input_thread.start(); + print("\nE 0\nm 1\n"); + try { + Thread.sleep(200); + } catch (InterruptedException e) { + } + flush(); + } + + public void set_channel(int channel) { + if (altos != null) + printf("m 0\nc r %d\nm 1\n", channel); } public AltosSerial() { diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 5c92b9b4..511c3709 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -210,6 +210,7 @@ public class AltosUI extends JFrame { System.exit(0); } }); + voice.speak("Rocket flight monitor ready."); } public void info_reset() { @@ -490,6 +491,7 @@ public class AltosUI extends JFrame { try { serial_line.open(device); DeviceThread thread = new DeviceThread(serial_line); + serial_line.set_channel(AltosPreferences.channel()); run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, @@ -706,9 +708,16 @@ public class AltosUI extends JFrame { menu.setMnemonic(KeyEvent.VK_V); menubar.add(menu); - radioitem = new JRadioButtonMenuItem("Enable Voice"); + radioitem = new JRadioButtonMenuItem("Enable Voice", AltosPreferences.voice()); radioitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource(); + boolean enabled = item.isSelected(); + AltosPreferences.set_voice(enabled); + if (enabled) + voice.speak_always("Enable voice."); + else + voice.speak_always("Disable voice."); } }); menu.add(radioitem); @@ -724,12 +733,13 @@ public class AltosUI extends JFrame { for (int c = 0; c <= 9; c++) { radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1), - c == 0); + c == AltosPreferences.channel()); radioitem.setActionCommand(String.format("%d", c)); radioitem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - System.out.println("Command: " + e.getActionCommand() + " param: " + - e.paramString()); + int new_channel = Integer.parseInt(e.getActionCommand()); + AltosPreferences.set_channel(new_channel); + serial_line.set_channel(new_channel); } }); menu.add(radioitem); diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index c39bfb9b..ebe9d5a8 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -39,7 +39,8 @@ public class AltosVoice implements Runnable { } catch (InterruptedException e) { } } - public void speak(String s) { + + public void speak_always(String s) { try { if (voice != null) phrases.put(s); @@ -47,6 +48,11 @@ public class AltosVoice implements Runnable { } } + public void speak(String s) { + if (AltosPreferences.voice()) + speak_always(s); + } + public void speak(String format, Object... parameters) { speak(String.format(format, parameters)); } @@ -59,7 +65,6 @@ public class AltosVoice implements Runnable { phrases = new LinkedBlockingQueue (); thread = new Thread(this); thread.start(); - speak("Rocket Flight Monitor Ready"); } else { System.out.printf("Voice manager failed to open %s\n", voice_name); Voice[] voices = voice_manager.getVoices(); -- cgit v1.2.3 From 826061eaca88c0dd75051a6006ef6703c91af595 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 13:10:11 -0700 Subject: Add voice test command for help in adjusting volume. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 511c3709..e1697ee1 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -721,6 +721,13 @@ public class AltosUI extends JFrame { } }); menu.add(radioitem); + item = new JMenuItem("Test Voice",KeyEvent.VK_T); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + voice.speak("That's one small step for man; one giant leap for mankind."); + } + }); + menu.add(item); } // Channel menu -- cgit v1.2.3 From 024d077302f91bdb17abe70d3211ab0949dab8b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 13:29:21 -0700 Subject: Remove debug printf Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index e1697ee1..ecacffe5 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -474,7 +474,6 @@ public class AltosUI extends JFrame { void close() { serial.close(); serial.remove_monitor(telem); - System.out.println("DisplayThread done"); } public DeviceThread(AltosSerial s) { -- cgit v1.2.3 From 6599e9576c3da9325a1731144c1b8bc4943184c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 15:41:34 -0700 Subject: altosui: Add eeprom data capture function. No UI yet. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEeprom.java | 264 ++++++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosFile.java | 23 +++- ao-tools/altosui/AltosSerial.java | 2 +- ao-tools/altosui/AltosUI.java | 1 + ao-tools/altosui/Makefile | 1 + 5 files changed, 283 insertions(+), 8 deletions(-) create mode 100644 ao-tools/altosui/AltosEeprom.java diff --git a/ao-tools/altosui/AltosEeprom.java b/ao-tools/altosui/AltosEeprom.java new file mode 100644 index 00000000..54e0bbc4 --- /dev/null +++ b/ao-tools/altosui/AltosEeprom.java @@ -0,0 +1,264 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; + +import libaltosJNI.*; + +public class AltosEeprom { + + static final int AO_LOG_FLIGHT = 'F'; + static final int AO_LOG_SENSOR = 'A'; + static final int AO_LOG_TEMP_VOLT = 'T'; + static final int AO_LOG_DEPLOY = 'D'; + static final int AO_LOG_STATE = 'S'; + static final int AO_LOG_GPS_TIME = 'G'; + static final int AO_LOG_GPS_LAT = 'N'; + static final int AO_LOG_GPS_LON = 'W'; + static final int AO_LOG_GPS_ALT = 'H'; + static final int AO_LOG_GPS_SAT = 'V'; + static final int AO_LOG_GPS_DATE = 'Y'; + + static final int ao_flight_startup = 0; + static final int ao_flight_idle = 1; + static final int ao_flight_pad = 2; + static final int ao_flight_boost = 3; + static final int ao_flight_fast = 4; + static final int ao_flight_coast = 5; + static final int ao_flight_drogue = 6; + static final int ao_flight_main = 7; + static final int ao_flight_landed = 8; + static final int ao_flight_invalid = 9; + + static String[] state_names = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + static int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + static int checksum(int[] line) { + int csum = 0x5a; + for (int i = 1; i < line.length; i++) + csum += line[i]; + return csum & 0xff; + } + + static void FlushPending(FileWriter file, LinkedList pending) throws IOException { + while (!pending.isEmpty()) { + file.write(pending.remove()); + } + } + + static void CaptureLog(AltosSerial serial_line) throws IOException, InterruptedException { + int serial = 0; + int block; + int addr; + int flight = 0; + int year = 0, month = 0, day = 0; + int state = 0; + boolean done = false; + boolean want_file = false; + boolean any_valid; + FileWriter eeprom_file = null; + AltosFile eeprom_name; + LinkedList eeprom_pending = new LinkedList(); + + serial_line.printf("v\n"); + + /* Pull the serial number out of the version information */ + + for (;;) { + String line = serial_line.get_reply(); + + if (line.startsWith("serial-number")) { + try { + serial = Integer.parseInt(line.substring(13).trim()); + eeprom_pending.add(String.format("%s\n", line)); + } catch (NumberFormatException ne) { + serial = 0; + } + } + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + if (serial == 0) + throw new IOException("no serial number found"); + + /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + + for (block = 0; !done && block < 511; block++) { + serial_line.printf("e %x\n", block); + any_valid = false; + for (addr = 0; addr < 0x100;) { + String line = serial_line.get_reply(); + int[] values = ParseHex(line); + + if (values == null) { + System.out.printf("invalid line: %s\n", line); + } else if (values[0] != addr) { + System.out.printf("data address out of sync at 0x%x\n", + block * 256 + values[0]); + } else if (checksum(values) != 0) { + System.out.printf("invalid checksum at 0x%x\n", + block * 256 + values[0]); + } else { + any_valid = true; + int cmd = values[1]; + int tick = values[3] + (values[4] << 8); + int a = values[5] + (values[6] << 8); + int b = values[7] + (values[8] << 8); + + if (cmd == AO_LOG_FLIGHT) + flight = b; + + /* Monitor state transitions to update display */ + if (cmd == AO_LOG_STATE && a <= ao_flight_landed) { + System.out.printf ("%s\n", state_names[a]); + if (a > ao_flight_pad) + want_file = true; + state = a; + } + + if (cmd == AO_LOG_GPS_DATE) { + year = 2000 + (a & 0xff); + month = (a >> 8) & 0xff; + day = (b & 0xff); + want_file = true; + } + + if (eeprom_file == null) { + if (serial != 0 && flight != 0 && want_file) { + if (year != 0 && month != 0 && day != 0) + eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom-new"); + else + eeprom_name = new AltosFile(serial, flight, "eeprom-new"); + + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + eeprom_pending = null; + } + } + } + + String log_line = String.format("%c %4x %4x %4x\n", + cmd, tick, a, b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + + if (cmd == AO_LOG_STATE && a == ao_flight_landed) { + done = true; + } + } + addr += 8; + } + if (!any_valid) + done = true; + } + if (eeprom_file == null) { + eeprom_name = new AltosFile(serial,flight,"eeprom-new"); + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + } + } + if (eeprom_file != null) { + eeprom_file.flush(); + eeprom_file.close(); + } + } + + public static void SaveFlightData (JFrame frame) { + altos_device device = AltosDeviceDialog.show(frame, null); + boolean remote = false; + AltosSerial serial_line = new AltosSerial(); + + if (device == null) + return; + try { + serial_line.open(device); + if (!device.getProduct().startsWith("TeleMetrum")) + remote = true; + + if (remote) { + serial_line.printf("m 0\n"); + serial_line.set_channel(AltosPreferences.channel()); + serial_line.printf("p\n"); + } + CaptureLog(serial_line); + if (remote) + serial_line.printf("~"); + serial_line.close(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.getPath(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + } + } +} diff --git a/ao-tools/altosui/AltosFile.java b/ao-tools/altosui/AltosFile.java index c7ee8679..7f65381f 100644 --- a/ao-tools/altosui/AltosFile.java +++ b/ao-tools/altosui/AltosFile.java @@ -24,14 +24,23 @@ import altosui.AltosTelemetry; import altosui.AltosPreferences; class AltosFile extends File { - public AltosFile(AltosTelemetry telem) { + + public AltosFile(int year, int month, int day, int serial, int flight, String extension) { super (AltosPreferences.logdir(), String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - Calendar.getInstance().get(Calendar.YEAR), - Calendar.getInstance().get(Calendar.MONTH), - Calendar.getInstance().get(Calendar.DAY_OF_MONTH), - telem.serial, - telem.flight, - "telem")); + year, month, day, serial, flight, extension)); + } + + public AltosFile(int serial, int flight, String extension) { + this(Calendar.getInstance().get(Calendar.YEAR), + Calendar.getInstance().get(Calendar.MONTH) + 1, + Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + serial, + flight, + extension); + } + + public AltosFile(AltosTelemetry telem) { + this(telem.serial, telem.flight, "telem"); } } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index f12b31b3..a5566ab8 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -139,7 +139,7 @@ public class AltosSerial implements Runnable { throw new FileNotFoundException(device.getPath()); input_thread = new Thread(this); input_thread.start(); - print("\nE 0\nm 1\n"); + print("\nE 0\n"); try { Thread.sleep(200); } catch (InterruptedException e) { diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index ecacffe5..92c3d0a3 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -613,6 +613,7 @@ public class AltosUI extends JFrame { * a TeleDongle over the packet link */ private void SaveFlightData() { + AltosEeprom.SaveFlightData(AltosUI.this); } /* Create the AltosUI menus diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 0613a494..2a91d657 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -3,6 +3,7 @@ CLASSPATH=classes:./* CLASSFILES=\ AltosConvert.class \ + AltosEeprom.class \ AltosFile.class \ AltosGPS.class \ AltosGreatCircle.class \ -- cgit v1.2.3 From ce90f3fe2aa6e23695ccccb36a8e6e614a08ba31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 17:08:42 -0700 Subject: altosui: Add progress bar for eeprom downloading status This has a progress bar tracking the state and block count while downloading stuff from telemetrum. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEeprom.java | 87 +++++++++++++++-------- ao-tools/altosui/AltosEepromMonitor.java | 118 +++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 2 +- ao-tools/altosui/Makefile | 1 + 4 files changed, 178 insertions(+), 30 deletions(-) create mode 100644 ao-tools/altosui/AltosEepromMonitor.java diff --git a/ao-tools/altosui/AltosEeprom.java b/ao-tools/altosui/AltosEeprom.java index 54e0bbc4..63698407 100644 --- a/ao-tools/altosui/AltosEeprom.java +++ b/ao-tools/altosui/AltosEeprom.java @@ -36,10 +36,11 @@ import altosui.AltosDeviceDialog; import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; +import altosui.AltosEepromMonitor; import libaltosJNI.*; -public class AltosEeprom { +public class AltosEeprom implements Runnable { static final int AO_LOG_FLIGHT = 'F'; static final int AO_LOG_SENSOR = 'A'; @@ -103,9 +104,9 @@ public class AltosEeprom { } } - static void CaptureLog(AltosSerial serial_line) throws IOException, InterruptedException { + static void CaptureLog(JFrame frame, AltosSerial serial_line) throws IOException, InterruptedException { int serial = 0; - int block; + int block, state_block = 0; int addr; int flight = 0; int year = 0, month = 0, day = 0; @@ -116,6 +117,7 @@ public class AltosEeprom { FileWriter eeprom_file = null; AltosFile eeprom_name; LinkedList eeprom_pending = new LinkedList(); + AltosEepromMonitor monitor = new AltosEepromMonitor(frame, ao_flight_boost, ao_flight_landed); serial_line.printf("v\n"); @@ -140,11 +142,14 @@ public class AltosEeprom { if (serial == 0) throw new IOException("no serial number found"); + monitor.set_serial(serial); /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + state = 0; state_block = 0; for (block = 0; !done && block < 511; block++) { serial_line.printf("e %x\n", block); any_valid = false; + monitor.set_value(state_names[state], state, block - state_block); for (addr = 0; addr < 0x100;) { String line = serial_line.get_reply(); int[] values = ParseHex(line); @@ -164,14 +169,18 @@ public class AltosEeprom { int a = values[5] + (values[6] << 8); int b = values[7] + (values[8] << 8); - if (cmd == AO_LOG_FLIGHT) + if (cmd == AO_LOG_FLIGHT) { flight = b; + monitor.set_flight(flight); + } /* Monitor state transitions to update display */ if (cmd == AO_LOG_STATE && a <= ao_flight_landed) { System.out.printf ("%s\n", state_names[a]); if (a > ao_flight_pad) want_file = true; + if (a > state) + state_block = block; state = a; } @@ -189,6 +198,7 @@ public class AltosEeprom { else eeprom_name = new AltosFile(serial, flight, "eeprom-new"); + monitor.set_file(eeprom_name.getName()); eeprom_file = new FileWriter(eeprom_name); if (eeprom_file != null) { FlushPending(eeprom_file, eeprom_pending); @@ -224,35 +234,23 @@ public class AltosEeprom { eeprom_file.flush(); eeprom_file.close(); } + monitor.done(); } - public static void SaveFlightData (JFrame frame) { - altos_device device = AltosDeviceDialog.show(frame, null); - boolean remote = false; - AltosSerial serial_line = new AltosSerial(); + JFrame frame; + altos_device device; + AltosSerial serial_line; + boolean remote; + Thread eeprom_thread; - if (device == null) - return; + public void run () { + if (remote) { + serial_line.printf("m 0\n"); + serial_line.set_channel(AltosPreferences.channel()); + serial_line.printf("p\n"); + } try { - serial_line.open(device); - if (!device.getProduct().startsWith("TeleMetrum")) - remote = true; - - if (remote) { - serial_line.printf("m 0\n"); - serial_line.set_channel(AltosPreferences.channel()); - serial_line.printf("p\n"); - } - CaptureLog(serial_line); - if (remote) - serial_line.printf("~"); - serial_line.close(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.getPath()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); + CaptureLog(frame, serial_line); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, device.getPath(), @@ -260,5 +258,36 @@ public class AltosEeprom { JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { } + if (remote) + serial_line.printf("~"); + serial_line.close(); + } + + public AltosEeprom(JFrame given_frame) { + frame = given_frame; + device = AltosDeviceDialog.show(frame, null); + serial_line = new AltosSerial(); + remote = false; + + if (device != null) { + try { + serial_line.open(device); + if (!device.getProduct().startsWith("TeleMetrum")) + remote = true; + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.getPath(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } } } diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java new file mode 100644 index 00000000..a7b1dd3e --- /dev/null +++ b/ao-tools/altosui/AltosEepromMonitor.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; + +public class AltosEepromMonitor extends JDialog { + + JPanel panel; + Box box; + JLabel serial_label; + JLabel flight_label; + JLabel file_label; + JProgressBar pbar; + int min_state, max_state; + + public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { + super (owner, "Download Flight Data"); + + box = Box.createVerticalBox(); + + serial_label = new JLabel("Serial:"); + box.add(serial_label); + flight_label = new JLabel("Flight:"); + box.add(flight_label); + file_label = new JLabel("File:"); + box.add(file_label); + + min_state = in_min_state; + max_state = in_max_state; + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum((max_state - min_state) * 100); + pbar.setValue(0); + pbar.setString("startup"); + pbar.setStringPainted(true); + box.add(pbar); + + panel = new JPanel(); + panel.add(box); + + add(panel); + + setMinimumSize(new Dimension(600, 0)); + setContentPane(panel); + pack(); + setVisible(true); + } + + public void set_value(String state_name, int in_state, int in_block) { + int block = in_block; + int state = in_state; + + if (block > 100) + block = 100; + if (state < min_state) state = min_state; + if (state >= max_state) state = max_state - 1; + state -= min_state; + + int pos = state * 100 + block; + + System.out.printf ("State %s (%d + %d) = %d\n", + state_name, in_state, in_block, pos); + + pbar.setString(state_name); + pbar.setValue(pos); + } + + public void set_serial(int serial) { + serial_label.setText(String.format("Serial: %d", serial)); + } + + public void set_flight(int flight) { + flight_label.setText(String.format("Flight: %d", flight)); + } + + public void set_file(String file) { + file_label.setText(String.format("File: %s", file)); + } + + public void done() { + setVisible(false); + dispose(); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 92c3d0a3..863d173e 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -613,7 +613,7 @@ public class AltosUI extends JFrame { * a TeleDongle over the packet link */ private void SaveFlightData() { - AltosEeprom.SaveFlightData(AltosUI.this); + new AltosEeprom(AltosUI.this); } /* Create the AltosUI menus diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 2a91d657..2c284aaa 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -4,6 +4,7 @@ CLASSPATH=classes:./* CLASSFILES=\ AltosConvert.class \ AltosEeprom.class \ + AltosEepromMonitor.class \ AltosFile.class \ AltosGPS.class \ AltosGreatCircle.class \ -- cgit v1.2.3 From ea32290704a8ca468f01172166b561833b20c954 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 19:37:02 -0700 Subject: altosui: Fix Save flight data monitor layout, add cancel Use GridBagLayout to improve the appearance of the flight data monitor widget, add a cancel button to stop loading data (useful if the connection is wedged). Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEeprom.java | 37 ++++++----- ao-tools/altosui/AltosEepromMonitor.java | 106 +++++++++++++++++++++++++------ 2 files changed, 108 insertions(+), 35 deletions(-) diff --git a/ao-tools/altosui/AltosEeprom.java b/ao-tools/altosui/AltosEeprom.java index 63698407..6162521f 100644 --- a/ao-tools/altosui/AltosEeprom.java +++ b/ao-tools/altosui/AltosEeprom.java @@ -65,7 +65,7 @@ public class AltosEeprom implements Runnable { static final int ao_flight_landed = 8; static final int ao_flight_invalid = 9; - static String[] state_names = { + static final String[] state_names = { "startup", "idle", "pad", @@ -78,7 +78,7 @@ public class AltosEeprom implements Runnable { "invalid", }; - static int[] ParseHex(String line) { + int[] ParseHex(String line) { String[] tokens = line.split("\\s+"); int[] array = new int[tokens.length]; @@ -91,20 +91,27 @@ public class AltosEeprom implements Runnable { return array; } - static int checksum(int[] line) { + int checksum(int[] line) { int csum = 0x5a; for (int i = 1; i < line.length; i++) csum += line[i]; return csum & 0xff; } - static void FlushPending(FileWriter file, LinkedList pending) throws IOException { + void FlushPending(FileWriter file, LinkedList pending) throws IOException { while (!pending.isEmpty()) { file.write(pending.remove()); } } - static void CaptureLog(JFrame frame, AltosSerial serial_line) throws IOException, InterruptedException { + JFrame frame; + altos_device device; + AltosSerial serial_line; + boolean remote; + Thread eeprom_thread; + AltosEepromMonitor monitor; + + void CaptureLog() throws IOException, InterruptedException { int serial = 0; int block, state_block = 0; int addr; @@ -117,7 +124,6 @@ public class AltosEeprom implements Runnable { FileWriter eeprom_file = null; AltosFile eeprom_name; LinkedList eeprom_pending = new LinkedList(); - AltosEepromMonitor monitor = new AltosEepromMonitor(frame, ao_flight_boost, ao_flight_landed); serial_line.printf("v\n"); @@ -176,7 +182,6 @@ public class AltosEeprom implements Runnable { /* Monitor state transitions to update display */ if (cmd == AO_LOG_STATE && a <= ao_flight_landed) { - System.out.printf ("%s\n", state_names[a]); if (a > ao_flight_pad) want_file = true; if (a > state) @@ -234,23 +239,23 @@ public class AltosEeprom implements Runnable { eeprom_file.flush(); eeprom_file.close(); } - monitor.done(); } - JFrame frame; - altos_device device; - AltosSerial serial_line; - boolean remote; - Thread eeprom_thread; - public void run () { if (remote) { serial_line.printf("m 0\n"); serial_line.set_channel(AltosPreferences.channel()); serial_line.printf("p\n"); } + + monitor = new AltosEepromMonitor(frame, ao_flight_boost, ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + eeprom_thread.interrupt(); + } + }); try { - CaptureLog(frame, serial_line); + CaptureLog(); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, device.getPath(), @@ -260,12 +265,14 @@ public class AltosEeprom implements Runnable { } if (remote) serial_line.printf("~"); + monitor.done(); serial_line.close(); } public AltosEeprom(JFrame given_frame) { frame = given_frame; device = AltosDeviceDialog.show(frame, null); + serial_line = new AltosSerial(); remote = false; diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java index a7b1dd3e..9eb3f0d0 100644 --- a/ao-tools/altosui/AltosEepromMonitor.java +++ b/ao-tools/altosui/AltosEepromMonitor.java @@ -39,25 +39,78 @@ import altosui.AltosVoice; public class AltosEepromMonitor extends JDialog { - JPanel panel; + Container pane; Box box; JLabel serial_label; JLabel flight_label; JLabel file_label; + JLabel serial_value; + JLabel flight_value; + JLabel file_value; + JButton cancel; JProgressBar pbar; int min_state, max_state; public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { - super (owner, "Download Flight Data"); + super (owner, "Download Flight Data", false); - box = Box.createVerticalBox(); + GridBagConstraints c; + Insets il = new Insets(4,0,4,4); + Insets ir = new Insets(4,4,4,0); + 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:"); - box.add(serial_label); + 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; flight_label = new JLabel("Flight:"); - box.add(flight_label); + pane.add(flight_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; + flight_value = new JLabel(""); + pane.add(flight_value, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.gridx = 0; c.gridy = 2; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; file_label = new JLabel("File:"); - box.add(file_label); + pane.add(file_label, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridx = 1; c.gridy = 2; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + file_value = new JLabel(""); + pane.add(file_value, c); min_state = in_min_state; max_state = in_max_state; @@ -67,19 +120,35 @@ public class AltosEepromMonitor extends JDialog { pbar.setValue(0); pbar.setString("startup"); pbar.setStringPainted(true); - box.add(pbar); - - panel = new JPanel(); - panel.add(box); - - add(panel); + pbar.setPreferredSize(new Dimension(600, 20)); + c = new GridBagConstraints(); + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; c.gridy = 3; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ib = new Insets(4,0,4,0); + 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 = 4; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); - setMinimumSize(new Dimension(600, 0)); - setContentPane(panel); pack(); setVisible(true); } + public void addActionListener (ActionListener l) { + cancel.addActionListener(l); + } + public void set_value(String state_name, int in_state, int in_block) { int block = in_block; int state = in_state; @@ -92,23 +161,20 @@ public class AltosEepromMonitor extends JDialog { int pos = state * 100 + block; - System.out.printf ("State %s (%d + %d) = %d\n", - state_name, in_state, in_block, pos); - pbar.setString(state_name); pbar.setValue(pos); } public void set_serial(int serial) { - serial_label.setText(String.format("Serial: %d", serial)); + serial_value.setText(String.format("%d", serial)); } public void set_flight(int flight) { - flight_label.setText(String.format("Flight: %d", flight)); + flight_value.setText(String.format("%d", flight)); } public void set_file(String file) { - file_label.setText(String.format("File: %s", file)); + file_value.setText(String.format("%s", file)); } public void done() { -- cgit v1.2.3 From d2d772164af95a35ea0f5d2413a5be67de9a210f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 20:18:36 -0700 Subject: altosui: Replace device dialog. Center eeprom monitor. This adds a custom dialog for selecting device, which makes it look much nicer on the screen and allows the user to double-click on an entry to select it. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDeviceDialog.java | 131 ++++++++++++++++++++++++++++--- ao-tools/altosui/AltosEepromMonitor.java | 7 +- 2 files changed, 125 insertions(+), 13 deletions(-) diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index 08921c3d..536a8057 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -20,26 +20,34 @@ package altosui; import java.lang.*; import java.util.*; import javax.swing.*; +import java.awt.*; +import java.awt.event.*; import libaltosJNI.libaltos; import libaltosJNI.altos_device; import libaltosJNI.SWIGTYPE_p_altos_file; import libaltosJNI.SWIGTYPE_p_altos_list; import altosui.AltosDevice; -public class AltosDeviceDialog { +public class AltosDeviceDialog extends JDialog implements ActionListener { - static altos_device show (JFrame frame, String product) { + private static AltosDeviceDialog dialog; + private static altos_device value = null; + private JList list; + + public static altos_device show (Component frameComp, String product) { + + Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosDevice[] devices; devices = AltosDevice.list(product); + if (devices != null & devices.length > 0) { - Object o = JOptionPane.showInputDialog(frame, - "Select a device", - "Device Selection", - JOptionPane.PLAIN_MESSAGE, - null, - devices, - devices[0]); - return (altos_device) o; + value = null; + dialog = new AltosDeviceDialog(frame, frameComp, + devices, + devices[0]); + + dialog.setVisible(true); + return value; } else { JOptionPane.showMessageDialog(frame, "No AltOS devices available", @@ -48,4 +56,107 @@ public class AltosDeviceDialog { return null; } } + + private AltosDeviceDialog (Frame frame, Component location, + AltosDevice[] devices, + AltosDevice initial) { + super(frame, "Device Selection", true); + + value = null; + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(this); + + final JButton selectButton = new JButton("Select"); + selectButton.setActionCommand("select"); + selectButton.addActionListener(this); + getRootPane().setDefaultButton(selectButton); + + list = new JList(devices) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + selectButton.doClick(); //emulate button click + } + } + }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + //Lay out the buttons from left to right. + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancelButton); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(selectButton); + + //Put everything together, using the content pane's BorderLayout. + Container contentPane = getContentPane(); + contentPane.add(listPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + //Initialize values. + list.setSelectedValue(initial, true); + pack(); + setLocationRelativeTo(location); + } + + //Handle clicks on the Set and Cancel buttons. + public void actionPerformed(ActionEvent e) { + if ("select".equals(e.getActionCommand())) { + System.out.printf("got select action\n"); + AltosDeviceDialog.value = (altos_device)(list.getSelectedValue()); + } + AltosDeviceDialog.dialog.setVisible(false); + } + } diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java index 9eb3f0d0..e110a354 100644 --- a/ao-tools/altosui/AltosEepromMonitor.java +++ b/ao-tools/altosui/AltosEepromMonitor.java @@ -55,8 +55,8 @@ public class AltosEepromMonitor extends JDialog { super (owner, "Download Flight Data", false); GridBagConstraints c; - Insets il = new Insets(4,0,4,4); - Insets ir = new Insets(4,4,4,0); + Insets il = new Insets(4,4,4,4); + Insets ir = new Insets(4,4,4,4); pane = getContentPane(); pane.setLayout(new GridBagLayout()); @@ -126,7 +126,7 @@ public class AltosEepromMonitor extends JDialog { c.anchor = GridBagConstraints.CENTER; c.gridx = 0; c.gridy = 3; c.gridwidth = GridBagConstraints.REMAINDER; - Insets ib = new Insets(4,0,4,0); + Insets ib = new Insets(4,4,4,4); c.insets = ib; pane.add(pbar, c); @@ -142,6 +142,7 @@ public class AltosEepromMonitor extends JDialog { pane.add(cancel, c); pack(); + setLocationRelativeTo(owner); setVisible(true); } -- cgit v1.2.3 From 5fd225c3a52445ecdc7c04fac5e3d9a0db177c66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 21:01:41 -0700 Subject: altosui: report rocket ground bearing at landing only if known if state.from_pad is null, then there isn't any data to report. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 863d173e..5c771df2 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -374,7 +374,7 @@ public class AltosUI extends JFrame { voice.speak("rocket landed safely"); else voice.speak("rocket may have crashed"); - if (state.gps != null) + if (state.from_pad != null) voice.speak("bearing %d degrees, range %d meters", (int) (state.from_pad.bearing + 0.5), (int) (state.from_pad.distance + 0.5)); -- cgit v1.2.3 From d0fd53bdab2f480cd43b6d7010c2094f4fccda91 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 21:49:23 -0700 Subject: Reset GPS ready status when GPS comes unlocked on the pad If GPS becomes unlocked, then report that in the UI and via voice. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosState.java | 15 ++++++++++++++- ao-tools/altosui/AltosUI.java | 12 ++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 59a1999e..9aa10a08 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -56,8 +56,12 @@ public class AltosState { double pad_lat; double pad_lon; double pad_alt; + + static final int MIN_PAD_SAMPLES = 10; + int npad; - int prev_npad; + int gps_waiting; + boolean gps_ready; AltosGreatCircle from_pad; @@ -134,8 +138,17 @@ public class AltosState { pad_lon = data.gps.lon; pad_alt = data.gps.alt; } + } else { + npad = 0; } } + + gps_waiting = MIN_PAD_SAMPLES - npad; + if (gps_waiting < 0) + gps_waiting = 0; + + gps_ready = gps_waiting == 0; + ascent = (AltosTelemetry.ao_flight_boost <= state && state <= AltosTelemetry.ao_flight_coast); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 5c771df2..4994f093 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -243,17 +243,15 @@ public class AltosUI extends JFrame { flightInfoModel[i].finish(); } - static final int MIN_PAD_SAMPLES = 10; - public void show(AltosState state) { flightStatusModel.set(state); info_reset(); - if (state.npad >= MIN_PAD_SAMPLES) + if (state.gps_ready) info_add_row(0, "Ground state", "%s", "ready"); else info_add_row(0, "Ground state", "wait (%d)", - MIN_PAD_SAMPLES - state.npad); + 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); @@ -413,6 +411,12 @@ public class AltosUI extends JFrame { (int) (state.max_height + 0.5)); } } + if (old_state == null || old_state.gps_ready != state.gps_ready) { + if (state.gps_ready) + voice.speak("GPS ready"); + else if (old_state != null) + voice.speak("GPS lost"); + } old_state = state; } -- cgit v1.2.3 From adf6cbcba23e24a3824f7e242ec37baa2750ab94 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 10:59:18 -0600 Subject: update changelogs for Debian build --- ChangeLog | 309 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 42 ++++++++ 2 files changed, 351 insertions(+) diff --git a/ChangeLog b/ChangeLog index 92b79ae3..bf47de72 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,312 @@ +commit d0fd53bdab2f480cd43b6d7010c2094f4fccda91 +Author: Keith Packard +Date: Wed Jul 28 21:49:23 2010 -0700 + + Reset GPS ready status when GPS comes unlocked on the pad + + If GPS becomes unlocked, then report that in the UI and via + voice. + + Signed-off-by: Keith Packard + +commit 5fd225c3a52445ecdc7c04fac5e3d9a0db177c66 +Author: Keith Packard +Date: Wed Jul 28 21:01:41 2010 -0700 + + altosui: report rocket ground bearing at landing only if known + + if state.from_pad is null, then there isn't any data to report. + + Signed-off-by: Keith Packard + +commit d2d772164af95a35ea0f5d2413a5be67de9a210f +Author: Keith Packard +Date: Wed Jul 28 20:18:36 2010 -0700 + + altosui: Replace device dialog. Center eeprom monitor. + + This adds a custom dialog for selecting device, which makes it look + much nicer on the screen and allows the user to double-click on an + entry to select it. + + Signed-off-by: Keith Packard + +commit ea32290704a8ca468f01172166b561833b20c954 +Author: Keith Packard +Date: Wed Jul 28 19:37:02 2010 -0700 + + altosui: Fix Save flight data monitor layout, add cancel + + Use GridBagLayout to improve the appearance of the flight data monitor + widget, add a cancel button to stop loading data (useful if the + connection is wedged). + + Signed-off-by: Keith Packard + +commit ce90f3fe2aa6e23695ccccb36a8e6e614a08ba31 +Author: Keith Packard +Date: Wed Jul 28 17:08:42 2010 -0700 + + altosui: Add progress bar for eeprom downloading status + + This has a progress bar tracking the state and block count while + downloading stuff from telemetrum. + + Signed-off-by: Keith Packard + +commit 6599e9576c3da9325a1731144c1b8bc4943184c0 +Author: Keith Packard +Date: Wed Jul 28 15:41:34 2010 -0700 + + altosui: Add eeprom data capture function. No UI yet. + + Signed-off-by: Keith Packard + +commit 8a6040e143ecc7830cc1c0114de85f3b72c067eb +Merge: 024d077 554a97e +Author: Keith Packard +Date: Wed Jul 28 13:29:51 2010 -0700 + + Merge remote branch 'keithp/macos' + +commit 024d077302f91bdb17abe70d3211ab0949dab8b9 +Author: Keith Packard +Date: Wed Jul 28 13:29:21 2010 -0700 + + Remove debug printf + + Signed-off-by: Keith Packard + +commit 826061eaca88c0dd75051a6006ef6703c91af595 +Author: Keith Packard +Date: Wed Jul 28 13:10:11 2010 -0700 + + Add voice test command for help in adjusting volume. + + Signed-off-by: Keith Packard + +commit 71da54a5ce255395376a44586782ab8b6f3b289f +Author: Keith Packard +Date: Wed Jul 28 13:01:52 2010 -0700 + + Make voice and channel menus work. + + Stores voice and channel data to preferences. + + Signed-off-by: Keith Packard + +commit e76b9cc32bbcc5176d9bdd6f8d79778024627382 +Author: Keith Packard +Date: Wed Jul 28 12:24:53 2010 -0700 + + altosui: Catch errors opening USB devices. Limit list to relevant devices + + Avoids a segfault when failing to open a device. Limit listed telemetry + devices to just TeleDongle units. + + Signed-off-by: Keith Packard + +commit 172a2817dde6718724f2b5fad5a7761801446fa0 +Merge: f2a006f 81bf204 +Author: Keith Packard +Date: Wed Jul 28 11:20:22 2010 -0700 + + Merge branch 'macos' + +commit f2a006fd98045066bdf429cc142d033e9feb0a8f +Author: Keith Packard +Date: Wed Jul 28 09:31:09 2010 -0700 + + Make ao_log_data re-entrant as it is used for both sensor and GPS logs + + Because ao_log_data is called from two different threads, failing to + make it re-entrant would cause the 'log' pointer parameter to get + overwritten if another thread asked to log data while the eeprom was + busy writing out a block. + + This would cause the second thread to re-writing data from the first + thread's address, but without re-checksumming the data as the checksum + is computed before the log mutex is taken. + + The bug can be seen by log blocks with invalid checksums. + + Here's what happens with the ao_gps_tracking_report and ao_log threads: + + ao_gps_tracking_report ao_log + + Writes a bunch of records + *blocks* in the eeprom flush + sets ao_log_data 'log' to global 'log' + computes checksum for 'log' block + *blocks* on ao_log_mutex + Wakes up + sets ao_log_data 'log' to 'gps_log' + writes remaining records + 'gps_log' is left with svid = 0 + *blocks* on ao_gps_tracking_data + writes data, reading from + the current ao_log_data 'log' + pointer which points at 'gps_log' + + Making ao_log_data re-entrant fixes this by ensuring that the 'ao_log' + thread has its own copy of the ao_log_data 'log' parameter. + + I made this function take an __xdata restricted pointer so that it + could be passed in the dptr register instead of needing to go on the stack. + + Signed-off-by: Keith Packard + +commit 554a97ef455c801dcab825815f44520f96f4c3f3 +Author: Keith Packard +Date: Tue Jul 27 19:29:38 2010 -0700 + + Force java source encoding to UTF-8 + +commit 81bf2042ca39eb106b789e5a08647c3114669358 +Author: Keith Packard +Date: Tue Jul 27 15:29:28 2010 -0700 + + Java voice reporting cleanups. + + Make sure it says something at the end of a log file replay. + Make sure it reports max speed after motor burn out, and max height + after apogee. + + Signed-off-by: Keith Packard + +commit 8f2f38f2a9fb0c106e2c6b60cdc205292ce329ea +Author: Keith Packard +Date: Tue Jul 27 10:18:20 2010 -0700 + + Java clean ups -- use varargs where possible, remove AltosSerialReader + + Add methods that format stuff using String.format for voice and serial + link, remove AltosSerialReader class and just embed that in the + AltosSerial class directly. + + Signed-off-by: Keith Packard + +commit 734cd15ccff691f851359518ce6118f29dc9f88d +Author: Keith Packard +Date: Tue Jul 27 10:18:09 2010 -0700 + + Remove directories as .class file dependencies; it makes them get rebuilt all the time + +commit 809feb75e2155e84aebfcc431867edcfd9054670 +Author: Keith Packard +Date: Tue Jul 27 01:22:56 2010 -0700 + + Clean up altosui build a bit + +commit 3784578a40dcc61f447435cfdf22e13c409cb9c0 +Author: Keith Packard +Date: Tue Jul 27 00:16:15 2010 -0700 + + Add application icons for Mac OS X + +commit 2c273710ea9b76ebee4101893f9fe84be8a02354 +Author: Keith Packard +Date: Tue Jul 27 00:11:58 2010 -0700 + + Add Mac OS X packaging files for altosui + +commit a58c44cd904e5429b807e5c23913051ed6484edc +Author: Keith Packard +Date: Tue Jul 27 00:09:41 2010 -0700 + + libaltos: build fat 10.5-compatible library + + Signed-off-by: Keith Packard + +commit 4e3285575e0c7d029e799258587e965779990099 +Author: Keith Packard +Date: Tue Jul 27 00:09:18 2010 -0700 + + libaltos: make clean remove all built files + + Signed-off-by: Keith Packard + +commit fb8507975c6e081de2e909eca6faaa8f868b609e +Author: Keith Packard +Date: Tue Jul 27 00:08:38 2010 -0700 + + libaltos needs -I. on all systems + + Signed-off-by: Keith Packard + +commit 0a782026f6b19e84ffd44f1ae1b466363474bd30 +Author: Keith Packard +Date: Mon Jul 26 18:10:07 2010 -0700 + + Darwin doesn't have strndup. + + This provides a private version of this GNU extension. + + Signed-off-by: Keith Packard + +commit b51497597868a40df039dd3ca11b35a6258bbbb3 +Author: Keith Packard +Date: Mon Jul 26 18:04:10 2010 -0700 + + Re-enable Linux support for altosui. + + This steals code from cc-usbdev for scanning the USB tree and uses the + same tty code as on Darwin + + Signed-off-by: Keith Packard + +commit e9153c4f2c71ed965822fcfe5112d2bc38506baf +Author: Keith Packard +Date: Mon Jul 26 17:04:04 2010 -0700 + + Re-enable freetts + +commit 17188f36fe18c23bc2eb877ac9a01b7693f4b863 +Author: Keith Packard +Date: Mon Jul 26 17:03:47 2010 -0700 + + Present list of altos devices in nice format + +commit 005e2d6a7bb3b0546b0c1273296875621632ec6d +Author: Keith Packard +Date: Mon Jul 26 15:42:48 2010 -0700 + + Switch AltosUI to libaltos for device access + + Signed-off-by: Keith Packard + +commit c726d8f6eb861801d7543552beab6ee2c920c96f +Author: Keith Packard +Date: Mon Jul 26 15:41:39 2010 -0700 + + Add libaltos which talks to USB connected altos devices + +commit 05111d5be4d37bedaaee6415d6ee27347e6a112c +Author: Keith Packard +Date: Mon Jul 26 12:52:17 2010 -0700 + + When the EP0 IN buffer is full, don't panic, just skip sending another + + If the host doesn't pull the IN packet out of EP0 before sending + another SETUP command along, the IN buffer will still be busy when we + try to reply to the SETUP command. While I don't quite understand why + this would ever happen, there's no need to panic about it, just drop + the reply packet on the floor. + + Signed-off-by: Keith Packard + +commit d0647950b76bfa9942e4f8cf87353f2b724099f4 +Author: Bdale Garbee +Date: Wed Jul 21 14:26:36 2010 -0600 + + fix text since TM only has one led to blink + +commit 8eda9fe94a7fd40cb84f50e17e64956f1584ebdc +Author: Bdale Garbee +Date: Tue Jul 20 22:24:32 2010 -0600 + + update changelogs for Debian build + commit cd8aa79de72b8b6b3a26d0c2522e94c621b70f13 Author: Bdale Garbee Date: Tue Jul 20 22:24:01 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 528ec25a..e5cff4de 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,45 @@ +altos (0.6+268+gd0fd53b) unstable; urgency=low + + [ Bdale Garbee ] + * fix text since TM only has one led to blink + + [ Keith Packard ] + * When the EP0 IN buffer is full, don't panic, just skip sending + another + * Add libaltos which talks to USB connected altos devices + * Switch AltosUI to libaltos for device access + * Present list of altos devices in nice format + * Re-enable freetts + * Re-enable Linux support for altosui. + * Darwin doesn't have strndup. + * libaltos needs -I. on all systems + * libaltos: make clean remove all built files + * libaltos: build fat 10.5-compatible library + * Add Mac OS X packaging files for altosui + * Add application icons for Mac OS X + * Clean up altosui build a bit + * Remove directories as .class file dependencies; it makes them get + rebuilt all the time + * Java clean ups -- use varargs where possible, remove + AltosSerialReader + * Java voice reporting cleanups. + * Force java source encoding to UTF-8 + * Make ao_log_data re-entrant as it is used for both sensor and GPS + logs + * altosui: Catch errors opening USB devices. Limit list to relevant + devices + * Make voice and channel menus work. + * Add voice test command for help in adjusting volume. + * Remove debug printf + * altosui: Add eeprom data capture function. No UI yet. + * altosui: Add progress bar for eeprom downloading status + * altosui: Fix Save flight data monitor layout, add cancel + * altosui: Replace device dialog. Center eeprom monitor. + * altosui: report rocket ground bearing at landing only if known + * Reset GPS ready status when GPS comes unlocked on the pad + + -- Bdale Garbee Thu, 29 Jul 2010 10:57:54 -0600 + altos (0.6+236+gcd8aa79) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 537492dc961ee6a1945b1041ee3cc0d3f519a42c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 11:01:21 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index bf47de72..b7bc0cde 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit adf6cbcba23e24a3824f7e242ec37baa2750ab94 +Author: Bdale Garbee +Date: Thu Jul 29 10:59:18 2010 -0600 + + update changelogs for Debian build + commit d0fd53bdab2f480cd43b6d7010c2094f4fccda91 Author: Keith Packard Date: Wed Jul 28 21:49:23 2010 -0700 diff --git a/debian/changelog b/debian/changelog index e5cff4de..df4d0a4e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+268+gd0fd53b) unstable; urgency=low +altos (0.6+269+gadf6cbc) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink -- cgit v1.2.3 From 27a2d0c00acf78628428c20ab68e2bfba06340da Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 11:02:38 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index b7bc0cde..7d02e0d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 537492dc961ee6a1945b1041ee3cc0d3f519a42c +Author: Bdale Garbee +Date: Thu Jul 29 11:01:21 2010 -0600 + + update changelogs for Debian build + commit adf6cbcba23e24a3824f7e242ec37baa2750ab94 Author: Bdale Garbee Date: Thu Jul 29 10:59:18 2010 -0600 diff --git a/debian/changelog b/debian/changelog index df4d0a4e..6f8b6386 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+269+gadf6cbc) unstable; urgency=low +altos (0.6+270+g537492d) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink -- cgit v1.2.3 From e33dbbba94ce42295e9fed9f4ba7e46f9eff1517 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 10:24:09 -0700 Subject: altosui: check for closed serial device before reading Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index a5566ab8..96e8b61f 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -51,6 +51,8 @@ public class AltosSerial implements Runnable { try { for (;;) { + if (altos == null) + break; c = libaltos.altos_getchar(altos, 0); if (Thread.interrupted()) break; -- cgit v1.2.3 From b8bc9994d8bfde6116c8a509e70ddf45fc4decce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 10:24:59 -0700 Subject: altosui: Remove unnecessary freetts .jar files Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 2c284aaa..a2d70c18 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -29,9 +29,7 @@ FREETTSJAR= \ cmutimelex.jar \ cmu_us_kal.jar \ en_us.jar \ - freetts.jar \ - freetts-jsapi10.jar \ - jsapi.jar + freetts.jar JAVAFLAGS=-Xlint:unchecked -- cgit v1.2.3 From 53c279b9e96da8b69837ae84038a78ca5707f2a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 10:45:02 -0700 Subject: altosui: Close serial, join reader thread, free altos_file Separating out the close and free actions ensures that the reader thread will not access freed memory or dereference a null pointer while shutting down the connection to the serial device. Otherwise, a race condition exists between the serial close and the thread join. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 10 +++++----- ao-tools/libaltos/libaltos.c | 12 ++++++++++++ ao-tools/libaltos/libaltos.h | 2 ++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 96e8b61f..efa63f68 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -51,8 +51,6 @@ public class AltosSerial implements Runnable { try { for (;;) { - if (altos == null) - break; c = libaltos.altos_getchar(altos, 0); if (Thread.interrupted()) break; @@ -106,10 +104,8 @@ public class AltosSerial implements Runnable { } public void close() { - if (altos != null) { + if (altos != null) libaltos.altos_close(altos); - altos = null; - } if (input_thread != null) { try { input_thread.interrupt(); @@ -118,6 +114,10 @@ public class AltosSerial implements Runnable { } input_thread = null; } + if (altos != null) { + libaltos.altos_free(altos); + altos = null; + } } public void putc(char c) { diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index df0d5b2e..00fb2125 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -567,6 +567,14 @@ void altos_close(struct altos_file *file) { close(file->fd); + file->fd = -1; +} + +void +altos_free(struct altos_file *file) +{ + if (file->fd != -1) + close(file->fd); free(file); } @@ -592,6 +600,8 @@ altos_flush(struct altos_file *file) while (file->out_used) { int ret; + if (file->fd < 0) + return -EBADF; ret = write (file->fd, file->out_data, file->out_used); if (ret < 0) return -errno; @@ -610,6 +620,8 @@ altos_getchar(struct altos_file *file, int timeout) int ret; altos_flush(file); + if (file->fd < 0) + return -EBADF; ret = read(file->fd, file->in_data, USB_BUF_SIZE); if (ret < 0) return -errno; diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h index 782f244e..53026e0a 100644 --- a/ao-tools/libaltos/libaltos.h +++ b/ao-tools/libaltos/libaltos.h @@ -42,6 +42,8 @@ altos_open(struct altos_device *device); void altos_close(struct altos_file *file); +void altos_free(struct altos_file *file); + int altos_putchar(struct altos_file *file, char c); -- cgit v1.2.3 From efa0e034a161f4852947cbac06537d6ba4422a0e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 10:48:25 -0700 Subject: altosui: remove debug printf Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDeviceDialog.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index 536a8057..c60bd7c3 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -152,10 +152,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { //Handle clicks on the Set and Cancel buttons. public void actionPerformed(ActionEvent e) { - if ("select".equals(e.getActionCommand())) { - System.out.printf("got select action\n"); + if ("select".equals(e.getActionCommand())) AltosDeviceDialog.value = (altos_device)(list.getSelectedValue()); - } AltosDeviceDialog.dialog.setVisible(false); } -- cgit v1.2.3 From 669c5f52abb972a82ed6efbee7a8c7d20afb5cd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 10:48:52 -0700 Subject: libaltos: build with java src encoding UTF8 Signed-off-by: Keith Packard --- ao-tools/libaltos/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 0bbd304c..fa5127eb 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -51,7 +51,7 @@ JAVAFLAGS=-Xlint:unchecked all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) .java.class: - javac -cp "$(CLASSPATH)" $(JAVAFLAGS) $*.java + javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java CFLAGS=$(OS_CFLAGS) -O0 -g -I. -- cgit v1.2.3 From 950f0a8c54e5835ee5d8b0aea360bd8362c21bc5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 11:09:19 -0700 Subject: altosui: construct Darwin application directory This adds the necessary files and build steps to construct AltosUI.app on a Darwin system. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.app/Contents/Info.plist | 38 +++++++++++++++++++++ .../AltosUI.app/Contents/MacOS/JavaApplicationStub | Bin 0 -> 61296 bytes ao-tools/altosui/AltosUI.app/Contents/PkgInfo | 1 + .../Contents/Resources/AltosUIIcon.icns | Bin 0 -> 129010 bytes ao-tools/altosui/AltosUIIcon.icns | Bin 129010 -> 0 bytes ao-tools/altosui/Makefile | 28 ++++++++++++++- 6 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 ao-tools/altosui/AltosUI.app/Contents/Info.plist create mode 100755 ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub create mode 100644 ao-tools/altosui/AltosUI.app/Contents/PkgInfo create mode 100644 ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns delete mode 100644 ao-tools/altosui/AltosUIIcon.icns diff --git a/ao-tools/altosui/AltosUI.app/Contents/Info.plist b/ao-tools/altosui/AltosUI.app/Contents/Info.plist new file mode 100644 index 00000000..97b1b59c --- /dev/null +++ b/ao-tools/altosui/AltosUI.app/Contents/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleName + altosui + CFBundleVersion + 100.0 + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleGetInfoString + AltOS UI version 0.7 + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + AltosUIIcon.icns + Java + + MainClass + altosui.AltosUI + JVMVersion + 1.5+ + ClassPath + + $JAVAROOT/altosui.jar + $JAVAROOT/freetts.jar + + + + diff --git a/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub new file mode 100755 index 00000000..c661d3e1 Binary files /dev/null and b/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub differ diff --git a/ao-tools/altosui/AltosUI.app/Contents/PkgInfo b/ao-tools/altosui/AltosUI.app/Contents/PkgInfo new file mode 100644 index 00000000..8a43480f --- /dev/null +++ b/ao-tools/altosui/AltosUI.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPLAM.O diff --git a/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns new file mode 100644 index 00000000..fe49f362 Binary files /dev/null and b/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns differ diff --git a/ao-tools/altosui/AltosUIIcon.icns b/ao-tools/altosui/AltosUIIcon.icns deleted file mode 100644 index fe49f362..00000000 Binary files a/ao-tools/altosui/AltosUIIcon.icns and /dev/null differ diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index a2d70c18..51a85a13 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -33,7 +33,17 @@ FREETTSJAR= \ JAVAFLAGS=-Xlint:unchecked -all: altosui.jar +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): @@ -54,6 +64,22 @@ 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" >> $@ +endif + clean: rm -f *.class $(FREETTSJAR) altosui.jar + rm -f AltosUI.app/Contents/Resources/Java/* rm -rf classes -- cgit v1.2.3 From 6f86db5e0360bef26b21336769b7635e3a11e160 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 11:24:47 -0700 Subject: Add Mac OS X packaging bits Signed-off-by: Keith Packard --- .../01altosui-contents.xml | 1 + .../AltOS Package Configuration.pmdoc/01altosui.xml | 1 + .../altosui/AltOS Package Configuration.pmdoc/index.xml | 1 + ao-tools/altosui/altusmetrum.jpg | Bin 0 -> 72868 bytes 4 files changed, 3 insertions(+) create mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml create mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml create mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml create mode 100644 ao-tools/altosui/altusmetrum.jpg diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml new file mode 100644 index 00000000..18e00fe4 --- /dev/null +++ b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml new file mode 100644 index 00000000..09fa7123 --- /dev/null +++ b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml @@ -0,0 +1 @@ +org.altusmetrum.altosUi.AltosUI.pkg1.0AltosUI.app/Applications/AltosUI.appinstallTo.pathinstallFrom.isRelativeTypeparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml new file mode 100644 index 00000000..03d0f59f --- /dev/null +++ b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml @@ -0,0 +1 @@ +AltOS UI/Users/keithp/altos/ao-tools/altosui/AltosUI.pkgorg.altusmetrumInstall AltOS User Interfacealtusmetrum.jpg01altosui.xmlproperties.titleproperties.customizeOptiondescriptionproperties.userDomainproperties.systemDomain \ No newline at end of file diff --git a/ao-tools/altosui/altusmetrum.jpg b/ao-tools/altosui/altusmetrum.jpg new file mode 100644 index 00000000..04027921 Binary files /dev/null and b/ao-tools/altosui/altusmetrum.jpg differ -- cgit v1.2.3 From 62b4cc51a0f54ef363cbff46caef80a0afecdea2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:40:25 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7d02e0d4..dbb563fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 27a2d0c00acf78628428c20ab68e2bfba06340da +Author: Bdale Garbee +Date: Thu Jul 29 11:02:38 2010 -0600 + + update changelogs for Debian build + commit 537492dc961ee6a1945b1041ee3cc0d3f519a42c Author: Bdale Garbee Date: Thu Jul 29 11:01:21 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 6f8b6386..1ca3b6fe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+270+g537492d) unstable; urgency=low +altos (0.6+271+g27a2d0c) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink -- cgit v1.2.3 From 33ffd89d5a64c991d28bd7369b61e1faa18f605b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:40:52 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index dbb563fb..2b63c00e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 62b4cc51a0f54ef363cbff46caef80a0afecdea2 +Author: Bdale Garbee +Date: Thu Jul 29 12:40:25 2010 -0600 + + update changelogs for Debian build + commit 27a2d0c00acf78628428c20ab68e2bfba06340da Author: Bdale Garbee Date: Thu Jul 29 11:02:38 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 1ca3b6fe..e8c9b350 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+271+g27a2d0c) unstable; urgency=low +altos (0.6+272+g62b4cc5) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink -- cgit v1.2.3 From 91d75fb3919f606a1956bf8c6423a8012d99a56a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 11:45:12 -0700 Subject: altosui: Switch eeprom extension back to .eeprom --- ao-tools/altosui/AltosEeprom.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosEeprom.java b/ao-tools/altosui/AltosEeprom.java index 6162521f..4c537a89 100644 --- a/ao-tools/altosui/AltosEeprom.java +++ b/ao-tools/altosui/AltosEeprom.java @@ -199,9 +199,9 @@ public class AltosEeprom implements Runnable { if (eeprom_file == null) { if (serial != 0 && flight != 0 && want_file) { if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom-new"); + eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); else - eeprom_name = new AltosFile(serial, flight, "eeprom-new"); + eeprom_name = new AltosFile(serial, flight, "eeprom"); monitor.set_file(eeprom_name.getName()); eeprom_file = new FileWriter(eeprom_name); @@ -229,7 +229,7 @@ public class AltosEeprom implements Runnable { done = true; } if (eeprom_file == null) { - eeprom_name = new AltosFile(serial,flight,"eeprom-new"); + eeprom_name = new AltosFile(serial,flight,"eeprom"); eeprom_file = new FileWriter(eeprom_name); if (eeprom_file != null) { FlushPending(eeprom_file, eeprom_pending); -- cgit v1.2.3 From 865d5cdf8931ffc796f608e3e12d7c5a70832825 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:45:18 -0600 Subject: add swig as a build dep --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 590b7650..ef669663 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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 Standards-Version: 3.9.0 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 6fb8546575f6d99676dbb1dce190b0b7cf24b657 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 11:45:56 -0700 Subject: Moved Mac OS packaging to altosui dir --- .../libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml | 1 - ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml | 1 - ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml | 1 - 3 files changed, 3 deletions(-) delete mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml delete mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml delete mode 100644 ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml deleted file mode 100644 index e19a1e4c..00000000 --- a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui-contents.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml deleted file mode 100644 index 5d84e5f0..00000000 --- a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/01altosui.xml +++ /dev/null @@ -1 +0,0 @@ -org.altusmetrum.altosUi.AltosUI.pkg1.0/Users/keithp/AltosUI.app/Applications/AltosUI.appinstallTo.pathparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml deleted file mode 100644 index 1277db62..00000000 --- a/ao-tools/libaltos/AltOS Package Configuration.pmdoc/index.xml +++ /dev/null @@ -1 +0,0 @@ -AltOS UI/Users/keithp/Documents/AltosUI.pkgorg.altusmetrum01altosui.xmlproperties.title \ No newline at end of file -- cgit v1.2.3 From 89109f9dff3ce855d80da166e3362375282f745d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:47:37 -0600 Subject: ugh, fixing failure due to aborted build --- debian/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index e8c9b350..60c87f0a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,7 +1,8 @@ -altos (0.6+272+g62b4cc5) unstable; urgency=low +altos (0.6+274+g865d5cd) UNRELEASED; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink + * add swig as a build dep [ Keith Packard ] * When the EP0 IN buffer is full, don't panic, just skip sending -- cgit v1.2.3 From 2e797b18f0724caf7aaf96f45997998c7416f34e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:50:57 -0600 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 4 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b63c00e..4655b589 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 89109f9dff3ce855d80da166e3362375282f745d +Author: Bdale Garbee +Date: Thu Jul 29 12:47:37 2010 -0600 + + ugh, fixing failure due to aborted build + +commit 865d5cdf8931ffc796f608e3e12d7c5a70832825 +Author: Bdale Garbee +Date: Thu Jul 29 12:45:18 2010 -0600 + + add swig as a build dep + +commit 33ffd89d5a64c991d28bd7369b61e1faa18f605b +Author: Bdale Garbee +Date: Thu Jul 29 12:40:52 2010 -0600 + + update changelogs for Debian build + commit 62b4cc51a0f54ef363cbff46caef80a0afecdea2 Author: Bdale Garbee Date: Thu Jul 29 12:40:25 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 60c87f0a..4c88d43f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+274+g865d5cd) UNRELEASED; urgency=low +altos (0.6+275+g89109f9) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink @@ -39,7 +39,7 @@ altos (0.6+274+g865d5cd) UNRELEASED; urgency=low * altosui: report rocket ground bearing at landing only if known * Reset GPS ready status when GPS comes unlocked on the pad - -- Bdale Garbee Thu, 29 Jul 2010 10:57:54 -0600 + -- Bdale Garbee Thu, 29 Jul 2010 12:50:40 -0600 altos (0.6+236+gcd8aa79) unstable; urgency=low -- cgit v1.2.3 From 9ad4984124b6c05114feac4c4ac078dc248ce16a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 11:56:24 -0700 Subject: altosui: remove option to install to alternate volume --- ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml | 2 +- ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml index 09fa7123..6170931b 100644 --- a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml +++ b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml @@ -1 +1 @@ -org.altusmetrum.altosUi.AltosUI.pkg1.0AltosUI.app/Applications/AltosUI.appinstallTo.pathinstallFrom.isRelativeTypeparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file +org.altusmetrum.altosUi.AltosUI.pkg0.7AltosUI.app/Applications/AltosUI.appinstallTo.pathinstallFrom.isRelativeTypeversionparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml index 03d0f59f..fabe54a6 100644 --- a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml +++ b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml @@ -1 +1 @@ -AltOS UI/Users/keithp/altos/ao-tools/altosui/AltosUI.pkgorg.altusmetrumInstall AltOS User Interfacealtusmetrum.jpg01altosui.xmlproperties.titleproperties.customizeOptiondescriptionproperties.userDomainproperties.systemDomain \ No newline at end of file +AltOS UI/Users/keithp/altos/ao-tools/altosui/AltosUI.pkgorg.altusmetrumInstall AltOS User Interfacealtusmetrum.jpg01altosui.xmlproperties.anywhereDomainproperties.titleproperties.customizeOptiondescriptionproperties.userDomainproperties.systemDomain \ No newline at end of file -- cgit v1.2.3 From d1848193d8208388e4ccdfbed4e5663a9ba04dd3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:56:59 -0600 Subject: add a jdk to the build deps --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index ef669663..ba9354b8 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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 Standards-Version: 3.9.0 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 4cf39b13a574cb656999cf329f5b08e7f910604b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 12:57:31 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4655b589..8f4ee8e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit d1848193d8208388e4ccdfbed4e5663a9ba04dd3 +Author: Bdale Garbee +Date: Thu Jul 29 12:56:59 2010 -0600 + + add a jdk to the build deps + +commit 2e797b18f0724caf7aaf96f45997998c7416f34e +Author: Bdale Garbee +Date: Thu Jul 29 12:50:57 2010 -0600 + + update changelogs for Debian build + commit 89109f9dff3ce855d80da166e3362375282f745d Author: Bdale Garbee Date: Thu Jul 29 12:47:37 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 4c88d43f..8d6412f0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,9 @@ -altos (0.6+275+g89109f9) unstable; urgency=low +altos (0.6+277+gd184819) unstable; urgency=low [ Bdale Garbee ] * fix text since TM only has one led to blink * add swig as a build dep + * add a jdk to the build deps [ Keith Packard ] * When the EP0 IN buffer is full, don't panic, just skip sending -- cgit v1.2.3 From c71061a37d3d3be2855b61cde33d2371989d7681 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Jul 2010 12:06:06 -0700 Subject: Make altosui test script executable --- ao-tools/altosui/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 51a85a13..790aecda 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -77,6 +77,7 @@ ifeq ($(OS),Linux) altosui: echo "#!/bin/sh" > $@ echo "exec java -Djava.library.path=../libaltos -jar altosui.jar" >> $@ + chmod +x ./altosui endif clean: -- cgit v1.2.3 From 2f114c7ff6b0deddb790d34139bb11ac37f8c0da Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 29 Jul 2010 13:30:36 -0600 Subject: update changelogs for Debian build --- ChangeLog | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 17 ++++++++++ 2 files changed, 118 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8f4ee8e6..40fd5fe4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,34 @@ +commit 7877496d47ce6d25210c0e1c6500666dbfc0876c +Merge: c71061a 4cf39b1 +Author: Keith Packard +Date: Thu Jul 29 12:07:49 2010 -0700 + + Merge remote branch 'origin/master' + +commit c71061a37d3d3be2855b61cde33d2371989d7681 +Author: Keith Packard +Date: Thu Jul 29 12:06:06 2010 -0700 + + Make altosui test script executable + +commit 4cf39b13a574cb656999cf329f5b08e7f910604b +Author: Bdale Garbee +Date: Thu Jul 29 12:57:31 2010 -0600 + + update changelogs for Debian build + commit d1848193d8208388e4ccdfbed4e5663a9ba04dd3 Author: Bdale Garbee Date: Thu Jul 29 12:56:59 2010 -0600 add a jdk to the build deps +commit 9ad4984124b6c05114feac4c4ac078dc248ce16a +Author: Keith Packard +Date: Thu Jul 29 11:56:24 2010 -0700 + + altosui: remove option to install to alternate volume + commit 2e797b18f0724caf7aaf96f45997998c7416f34e Author: Bdale Garbee Date: Thu Jul 29 12:50:57 2010 -0600 @@ -16,12 +41,24 @@ Date: Thu Jul 29 12:47:37 2010 -0600 ugh, fixing failure due to aborted build +commit 6fb8546575f6d99676dbb1dce190b0b7cf24b657 +Author: Keith Packard +Date: Thu Jul 29 11:45:56 2010 -0700 + + Moved Mac OS packaging to altosui dir + commit 865d5cdf8931ffc796f608e3e12d7c5a70832825 Author: Bdale Garbee Date: Thu Jul 29 12:45:18 2010 -0600 add swig as a build dep +commit 91d75fb3919f606a1956bf8c6423a8012d99a56a +Author: Keith Packard +Date: Thu Jul 29 11:45:12 2010 -0700 + + altosui: Switch eeprom extension back to .eeprom + commit 33ffd89d5a64c991d28bd7369b61e1faa18f605b Author: Bdale Garbee Date: Thu Jul 29 12:40:52 2010 -0600 @@ -34,6 +71,70 @@ Date: Thu Jul 29 12:40:25 2010 -0600 update changelogs for Debian build +commit 6f86db5e0360bef26b21336769b7635e3a11e160 +Author: Keith Packard +Date: Thu Jul 29 11:24:47 2010 -0700 + + Add Mac OS X packaging bits + + Signed-off-by: Keith Packard + +commit 950f0a8c54e5835ee5d8b0aea360bd8362c21bc5 +Author: Keith Packard +Date: Thu Jul 29 11:09:19 2010 -0700 + + altosui: construct Darwin application directory + + This adds the necessary files and build steps to construct + AltosUI.app on a Darwin system. + + Signed-off-by: Keith Packard + +commit 669c5f52abb972a82ed6efbee7a8c7d20afb5cd0 +Author: Keith Packard +Date: Thu Jul 29 10:48:52 2010 -0700 + + libaltos: build with java src encoding UTF8 + + Signed-off-by: Keith Packard + +commit efa0e034a161f4852947cbac06537d6ba4422a0e +Author: Keith Packard +Date: Thu Jul 29 10:48:25 2010 -0700 + + altosui: remove debug printf + + Signed-off-by: Keith Packard + +commit 53c279b9e96da8b69837ae84038a78ca5707f2a5 +Author: Keith Packard +Date: Thu Jul 29 10:45:02 2010 -0700 + + altosui: Close serial, join reader thread, free altos_file + + Separating out the close and free actions ensures that the reader thread will not + access freed memory or dereference a null pointer while shutting down the + connection to the serial device. Otherwise, a race condition exists between the + serial close and the thread join. + + Signed-off-by: Keith Packard + +commit b8bc9994d8bfde6116c8a509e70ddf45fc4decce +Author: Keith Packard +Date: Thu Jul 29 10:24:59 2010 -0700 + + altosui: Remove unnecessary freetts .jar files + + Signed-off-by: Keith Packard + +commit e33dbbba94ce42295e9fed9f4ba7e46f9eff1517 +Author: Keith Packard +Date: Thu Jul 29 10:24:09 2010 -0700 + + altosui: check for closed serial device before reading + + Signed-off-by: Keith Packard + commit 27a2d0c00acf78628428c20ab68e2bfba06340da Author: Bdale Garbee Date: Thu Jul 29 11:02:38 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 8d6412f0..106941d9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +altos (0.6+290+g7877496) unstable; urgency=low + + [ Keith Packard ] + * altosui: check for closed serial device before reading + * altosui: Remove unnecessary freetts .jar files + * altosui: Close serial, join reader thread, free altos_file + * altosui: remove debug printf + * libaltos: build with java src encoding UTF8 + * altosui: construct Darwin application directory + * Add Mac OS X packaging bits + * altosui: Switch eeprom extension back to .eeprom + * Moved Mac OS packaging to altosui dir + * altosui: remove option to install to alternate volume + * Make altosui test script executable + + -- Bdale Garbee Thu, 29 Jul 2010 13:30:19 -0600 + altos (0.6+277+gd184819) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 8fc261c2b77bb8aab201a0649a84b5ffa236ce26 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Jul 2010 10:55:07 -0600 Subject: see if my new freetts package works --- ao-tools/altosui/Manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 251ce2a0..1f313a13 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: freetts.jar +Class-Path: /usr/share/java/freetts-1.2.2.jar -- cgit v1.2.3 From e3a9e3815db3f290e28b40ae02aa654f515cfc37 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Jul 2010 10:55:27 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 40fd5fe4..4acfeae4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 8fc261c2b77bb8aab201a0649a84b5ffa236ce26 +Author: Bdale Garbee +Date: Sat Jul 31 10:55:07 2010 -0600 + + see if my new freetts package works + +commit 2f114c7ff6b0deddb790d34139bb11ac37f8c0da +Author: Bdale Garbee +Date: Thu Jul 29 13:30:36 2010 -0600 + + update changelogs for Debian build + commit 7877496d47ce6d25210c0e1c6500666dbfc0876c Merge: c71061a 4cf39b1 Author: Keith Packard diff --git a/debian/changelog b/debian/changelog index 106941d9..5d07e30d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+292+g8fc261c) unstable; urgency=low + + * see if my new freetts package works + + -- Bdale Garbee Sat, 31 Jul 2010 10:55:21 -0600 + altos (0.6+290+g7877496) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From e286eb61ad2a90746c1c31f95d26d5edb48738d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Jul 2010 09:57:49 -0700 Subject: 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 --- ao-tools/altosui/Altos.java | 94 ++++++++++ ao-tools/altosui/AltosEeprom.java | 300 ------------------------------ ao-tools/altosui/AltosEepromDownload.java | 278 +++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 17 +- 4 files changed, 381 insertions(+), 308 deletions(-) create mode 100644 ao-tools/altosui/Altos.java delete mode 100644 ao-tools/altosui/AltosEeprom.java create mode 100644 ao-tools/altosui/AltosEepromDownload.java diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java new file mode 100644 index 00000000..bda4080e --- /dev/null +++ b/ao-tools/altosui/Altos.java @@ -0,0 +1,94 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import java.text.*; + +public class Altos { + /* EEProm command letters */ + static final int AO_LOG_FLIGHT = 'F'; + static final int AO_LOG_SENSOR = 'A'; + static final int AO_LOG_TEMP_VOLT = 'T'; + static final int AO_LOG_DEPLOY = 'D'; + static final int AO_LOG_STATE = 'S'; + static final int AO_LOG_GPS_TIME = 'G'; + static final int AO_LOG_GPS_LAT = 'N'; + static final int AO_LOG_GPS_LON = 'W'; + static final int AO_LOG_GPS_ALT = 'H'; + static final int AO_LOG_GPS_SAT = 'V'; + static final int AO_LOG_GPS_DATE = 'Y'; + + /* Added for 'serial-number' entry in eeprom files */ + static final int AO_LOG_SERIAL_NUMBER = 1000; + + /* Added to flag invalid records */ + static final int AO_LOG_INVALID = -1; + + /* Flight state numbers and names */ + static final int ao_flight_startup = 0; + static final int ao_flight_idle = 1; + static final int ao_flight_pad = 2; + static final int ao_flight_boost = 3; + static final int ao_flight_fast = 4; + static final int ao_flight_coast = 5; + static final int ao_flight_drogue = 6; + static final int ao_flight_main = 7; + static final int ao_flight_landed = 8; + static final int ao_flight_invalid = 9; + + static HashMap string_to_state = new HashMap(); + { + string_to_state.put("startup", ao_flight_startup); + string_to_state.put("idle", ao_flight_idle); + string_to_state.put("pad", ao_flight_pad); + string_to_state.put("boost", ao_flight_boost); + string_to_state.put("fast", ao_flight_fast); + string_to_state.put("coast", ao_flight_coast); + string_to_state.put("drogue", ao_flight_drogue); + string_to_state.put("main", ao_flight_main); + string_to_state.put("landed", ao_flight_landed); + string_to_state.put("invalid", ao_flight_invalid); + } + + static String[] state_to_string = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + static public int state(String state) { + if (string_to_state.containsKey(state)) + return string_to_state.get(state); + return ao_flight_invalid; + } + + static public String state_name(int state) { + if (state < 0 || state_to_string.length <= state) + return "invalid"; + return state_to_string[state]; + } +} diff --git a/ao-tools/altosui/AltosEeprom.java b/ao-tools/altosui/AltosEeprom.java deleted file mode 100644 index 4c537a89..00000000 --- a/ao-tools/altosui/AltosEeprom.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - -import libaltosJNI.*; - -public class AltosEeprom implements Runnable { - - static final int AO_LOG_FLIGHT = 'F'; - static final int AO_LOG_SENSOR = 'A'; - static final int AO_LOG_TEMP_VOLT = 'T'; - static final int AO_LOG_DEPLOY = 'D'; - static final int AO_LOG_STATE = 'S'; - static final int AO_LOG_GPS_TIME = 'G'; - static final int AO_LOG_GPS_LAT = 'N'; - static final int AO_LOG_GPS_LON = 'W'; - static final int AO_LOG_GPS_ALT = 'H'; - static final int AO_LOG_GPS_SAT = 'V'; - static final int AO_LOG_GPS_DATE = 'Y'; - - static final int ao_flight_startup = 0; - static final int ao_flight_idle = 1; - static final int ao_flight_pad = 2; - static final int ao_flight_boost = 3; - static final int ao_flight_fast = 4; - static final int ao_flight_coast = 5; - static final int ao_flight_drogue = 6; - static final int ao_flight_main = 7; - static final int ao_flight_landed = 8; - static final int ao_flight_invalid = 9; - - static final String[] state_names = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - int checksum(int[] line) { - int csum = 0x5a; - for (int i = 1; i < line.length; i++) - csum += line[i]; - return csum & 0xff; - } - - void FlushPending(FileWriter file, LinkedList pending) throws IOException { - while (!pending.isEmpty()) { - file.write(pending.remove()); - } - } - - JFrame frame; - altos_device device; - AltosSerial serial_line; - boolean remote; - Thread eeprom_thread; - AltosEepromMonitor monitor; - - void CaptureLog() throws IOException, InterruptedException { - int serial = 0; - int block, state_block = 0; - int addr; - int flight = 0; - int year = 0, month = 0, day = 0; - int state = 0; - boolean done = false; - boolean want_file = false; - boolean any_valid; - FileWriter eeprom_file = null; - AltosFile eeprom_name; - LinkedList eeprom_pending = new LinkedList(); - - serial_line.printf("v\n"); - - /* Pull the serial number out of the version information */ - - for (;;) { - String line = serial_line.get_reply(); - - if (line.startsWith("serial-number")) { - try { - serial = Integer.parseInt(line.substring(13).trim()); - eeprom_pending.add(String.format("%s\n", line)); - } catch (NumberFormatException ne) { - serial = 0; - } - } - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } - if (serial == 0) - throw new IOException("no serial number found"); - - monitor.set_serial(serial); - /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - - state = 0; state_block = 0; - for (block = 0; !done && block < 511; block++) { - serial_line.printf("e %x\n", block); - any_valid = false; - monitor.set_value(state_names[state], state, block - state_block); - for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(); - int[] values = ParseHex(line); - - if (values == null) { - System.out.printf("invalid line: %s\n", line); - } else if (values[0] != addr) { - System.out.printf("data address out of sync at 0x%x\n", - block * 256 + values[0]); - } else if (checksum(values) != 0) { - System.out.printf("invalid checksum at 0x%x\n", - block * 256 + values[0]); - } else { - any_valid = true; - int cmd = values[1]; - int tick = values[3] + (values[4] << 8); - int a = values[5] + (values[6] << 8); - int b = values[7] + (values[8] << 8); - - if (cmd == AO_LOG_FLIGHT) { - flight = b; - monitor.set_flight(flight); - } - - /* Monitor state transitions to update display */ - if (cmd == AO_LOG_STATE && a <= ao_flight_landed) { - if (a > ao_flight_pad) - want_file = true; - if (a > state) - state_block = block; - state = a; - } - - if (cmd == AO_LOG_GPS_DATE) { - year = 2000 + (a & 0xff); - month = (a >> 8) & 0xff; - day = (b & 0xff); - want_file = true; - } - - if (eeprom_file == null) { - if (serial != 0 && flight != 0 && want_file) { - if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); - else - eeprom_name = new AltosFile(serial, flight, "eeprom"); - - monitor.set_file(eeprom_name.getName()); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - eeprom_pending = null; - } - } - } - - String log_line = String.format("%c %4x %4x %4x\n", - cmd, tick, a, b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - - if (cmd == AO_LOG_STATE && a == ao_flight_landed) { - done = true; - } - } - addr += 8; - } - if (!any_valid) - done = true; - } - if (eeprom_file == null) { - eeprom_name = new AltosFile(serial,flight,"eeprom"); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - } - } - if (eeprom_file != null) { - eeprom_file.flush(); - eeprom_file.close(); - } - } - - public void run () { - if (remote) { - serial_line.printf("m 0\n"); - serial_line.set_channel(AltosPreferences.channel()); - serial_line.printf("p\n"); - } - - monitor = new AltosEepromMonitor(frame, ao_flight_boost, ao_flight_landed); - monitor.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - eeprom_thread.interrupt(); - } - }); - try { - CaptureLog(); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.getPath(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException ie) { - } - if (remote) - serial_line.printf("~"); - monitor.done(); - serial_line.close(); - } - - public AltosEeprom(JFrame given_frame) { - frame = given_frame; - device = AltosDeviceDialog.show(frame, null); - - serial_line = new AltosSerial(); - remote = false; - - if (device != null) { - try { - serial_line.open(device); - if (!device.getProduct().startsWith("TeleMetrum")) - remote = true; - eeprom_thread = new Thread(this); - eeprom_thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.getPath()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.getPath(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } - } -} diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java new file mode 100644 index 00000000..756b82d1 --- /dev/null +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -0,0 +1,278 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Altos; +import altosui.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosEepromMonitor; + +import libaltosJNI.*; + +public class AltosEepromDownload implements Runnable { + + static final String[] state_names = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + int checksum(int[] line) { + int csum = 0x5a; + for (int i = 1; i < line.length; i++) + csum += line[i]; + return csum & 0xff; + } + + void FlushPending(FileWriter file, LinkedList pending) throws IOException { + while (!pending.isEmpty()) { + file.write(pending.remove()); + } + } + + JFrame frame; + altos_device device; + AltosSerial serial_line; + boolean remote; + Thread eeprom_thread; + AltosEepromMonitor monitor; + + void CaptureLog() throws IOException, InterruptedException { + int serial = 0; + int block, state_block = 0; + int addr; + int flight = 0; + int year = 0, month = 0, day = 0; + int state = 0; + boolean done = false; + boolean want_file = false; + boolean any_valid; + FileWriter eeprom_file = null; + AltosFile eeprom_name; + LinkedList eeprom_pending = new LinkedList(); + + serial_line.printf("v\n"); + + /* Pull the serial number out of the version information */ + + for (;;) { + String line = serial_line.get_reply(); + + if (line.startsWith("serial-number")) { + try { + serial = Integer.parseInt(line.substring(13).trim()); + eeprom_pending.add(String.format("%s\n", line)); + } catch (NumberFormatException ne) { + serial = 0; + } + } + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + if (serial == 0) + throw new IOException("no serial number found"); + + monitor.set_serial(serial); + /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + + state = 0; state_block = 0; + for (block = 0; !done && block < 511; block++) { + serial_line.printf("e %x\n", block); + any_valid = false; + monitor.set_value(state_names[state], state, block - state_block); + for (addr = 0; addr < 0x100;) { + String line = serial_line.get_reply(); + int[] values = ParseHex(line); + + if (values == null) { + System.out.printf("invalid line: %s\n", line); + } else if (values[0] != addr) { + System.out.printf("data address out of sync at 0x%x\n", + block * 256 + values[0]); + } else if (checksum(values) != 0) { + System.out.printf("invalid checksum at 0x%x\n", + block * 256 + values[0]); + } else { + any_valid = true; + int cmd = values[1]; + int tick = values[3] + (values[4] << 8); + int a = values[5] + (values[6] << 8); + int b = values[7] + (values[8] << 8); + + if (cmd == Altos.AO_LOG_FLIGHT) { + flight = b; + monitor.set_flight(flight); + } + + /* Monitor state transitions to update display */ + if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { + if (a > Altos.ao_flight_pad) + want_file = true; + if (a > state) + state_block = block; + state = a; + } + + if (cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (a & 0xff); + month = (a >> 8) & 0xff; + day = (b & 0xff); + want_file = true; + } + + if (eeprom_file == null) { + if (serial != 0 && flight != 0 && want_file) { + if (year != 0 && month != 0 && day != 0) + eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); + else + eeprom_name = new AltosFile(serial, flight, "eeprom"); + + monitor.set_file(eeprom_name.getName()); + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + eeprom_pending = null; + } + } + } + + String log_line = String.format("%c %4x %4x %4x\n", + cmd, tick, a, b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + + if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { + done = true; + } + } + addr += 8; + } + if (!any_valid) + done = true; + } + if (eeprom_file == null) { + eeprom_name = new AltosFile(serial,flight,"eeprom"); + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + } + } + if (eeprom_file != null) { + eeprom_file.flush(); + eeprom_file.close(); + } + } + + public void run () { + if (remote) { + serial_line.printf("m 0\n"); + serial_line.set_channel(AltosPreferences.channel()); + serial_line.printf("p\n"); + } + + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + eeprom_thread.interrupt(); + } + }); + try { + CaptureLog(); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.getPath(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + } + if (remote) + serial_line.printf("~"); + monitor.done(); + serial_line.close(); + } + + public AltosEepromDownload(JFrame given_frame) { + frame = given_frame; + device = AltosDeviceDialog.show(frame, null); + + serial_line = new AltosSerial(); + remote = false; + + if (device != null) { + try { + serial_line.open(device); + if (!device.getProduct().startsWith("TeleMetrum")) + remote = true; + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.getPath(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 4994f093..824e4b5b 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -28,6 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import altosui.Altos; import altosui.AltosSerial; import altosui.AltosSerialMonitor; import altosui.AltosTelemetry; @@ -344,7 +345,7 @@ public class AltosUI extends JFrame { return; /* reset the landing count once we hear about a new flight */ - if (state.state < AltosTelemetry.ao_flight_drogue) + if (state.state < Altos.ao_flight_drogue) reported_landing = 0; /* Shut up once the rocket is on the ground */ @@ -353,7 +354,7 @@ public class AltosUI extends JFrame { } /* If the rocket isn't on the pad, then report height */ - if (state.state > AltosTelemetry.ao_flight_pad) { + if (state.state > Altos.ao_flight_pad) { voice.speak("%d meters", (int) (state.height + 0.5)); } else { reported_landing = 0; @@ -366,7 +367,7 @@ public class AltosUI extends JFrame { if (!state.ascent && (last || System.currentTimeMillis() - state.report_time >= 15000 || - state.state == AltosTelemetry.ao_flight_landed)) + state.state == Altos.ao_flight_landed)) { if (Math.abs(state.baro_speed) < 20 && state.height < 100) voice.speak("rocket landed safely"); @@ -401,12 +402,12 @@ public class AltosUI extends JFrame { private void tell(AltosState state, AltosState old_state) { if (old_state == null || old_state.state != state.state) { voice.speak(state.data.state); - if ((old_state == null || old_state.state <= AltosTelemetry.ao_flight_boost) && - state.state > AltosTelemetry.ao_flight_boost) { + 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)); - } else if ((old_state == null || old_state.state < AltosTelemetry.ao_flight_drogue) && - state.state >= AltosTelemetry.ao_flight_drogue) { + } 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)); } @@ -617,7 +618,7 @@ public class AltosUI extends JFrame { * a TeleDongle over the packet link */ private void SaveFlightData() { - new AltosEeprom(AltosUI.this); + new AltosEepromDownload(AltosUI.this); } /* Create the AltosUI menus -- cgit v1.2.3 From 1c3b2fe357d6acf28f48aeddd91693f10381be51 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Jul 2010 10:05:15 -0700 Subject: 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 --- ao-tools/altosui/AltosEepromDownload.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 756b82d1..1f4a278f 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -103,7 +103,7 @@ public class AltosEepromDownload implements Runnable { AltosFile eeprom_name; LinkedList eeprom_pending = new LinkedList(); - serial_line.printf("v\n"); + serial_line.printf("\nc s\nv\n"); /* Pull the serial number out of the version information */ @@ -113,12 +113,13 @@ public class AltosEepromDownload implements Runnable { if (line.startsWith("serial-number")) { try { serial = Integer.parseInt(line.substring(13).trim()); - eeprom_pending.add(String.format("%s\n", line)); } catch (NumberFormatException ne) { serial = 0; } } + eeprom_pending.add(String.format("%s\n", line)); + /* signals the end of the version info */ if (line.startsWith("software-version")) break; -- cgit v1.2.3 From 88e0137a60d7a13ddb7781befa76650e13ad44ae Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Jul 2010 10:07:38 -0700 Subject: 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 --- ao-tools/altosui/AltosGPS.java | 113 ++++++++++++++++++++++++++++------------- ao-tools/altosui/AltosUI.java | 12 ++--- 2 files changed, 83 insertions(+), 42 deletions(-) diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index f8eb5f48..42f4dc83 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -23,37 +23,6 @@ import altosui.AltosParse; public class AltosGPS { - public class AltosGPSTime { - int year; - int month; - int day; - int hour; - int minute; - int second; - - public AltosGPSTime(String date, String time) 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]); - - String[] hms = time.split(":"); - if (hms.length != 3) - throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); - hour = AltosParse.parse_int(hms[0]); - minute = AltosParse.parse_int(hms[1]); - second = AltosParse.parse_int(hms[2]); - } - - public AltosGPSTime() { - year = month = day = 0; - hour = minute = second = 0; - } - - } - public class AltosGPSSat { int svid; int c_n0; @@ -62,10 +31,15 @@ public class AltosGPS { int nsat; boolean gps_locked; boolean gps_connected; - AltosGPSTime gps_time; double lat; /* degrees (+N -S) */ double lon; /* degrees (+E -W) */ int alt; /* m */ + int year; + int month; + int day; + int hour; + int minute; + int second; int gps_extended; /* has extra data */ double ground_speed; /* m/s */ @@ -77,6 +51,27 @@ public class AltosGPS { AltosGPSSat[] cc_gps_sat; /* tracking data */ + void ParseGPSTime(String date, String time) 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]); + + String[] hms = time.split(":"); + if (hms.length != 3) + throw new ParseException("Error parsing GPS time " + time + " got " + hms.length, 0); + hour = AltosParse.parse_int(hms[0]); + minute = AltosParse.parse_int(hms[1]); + second = AltosParse.parse_int(hms[2]); + } + + void ClearGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } + public AltosGPS(String[] words, int i) throws ParseException { AltosParse.word(words[i++], "GPS"); nsat = AltosParse.parse_int(words[i++]); @@ -86,18 +81,17 @@ public class AltosGPS { gps_locked = false; lat = lon = 0; alt = 0; + ClearGPSTime(); if ((words[i]).equals("unlocked")) { gps_connected = true; - gps_time = new AltosGPSTime(); i++; } else if ((words[i]).equals("not-connected")) { - gps_time = new AltosGPSTime(); i++; } else if (words.length >= 40) { gps_locked = true; gps_connected = true; - gps_time = new AltosGPSTime(words[i], words[i+1]); i += 2; + ParseGPSTime(words[i], words[i+1]); i += 2; lat = AltosParse.parse_coord(words[i++]); lon = AltosParse.parse_coord(words[i++]); alt = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "m")); @@ -108,7 +102,6 @@ public class AltosGPS { h_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(herr)")); v_error = AltosParse.parse_int(AltosParse.strip_suffix(words[i++], "(verr)")); } else { - gps_time = new AltosGPSTime(); i++; } AltosParse.word(words[i++], "SAT"); @@ -125,4 +118,52 @@ public class AltosGPS { cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); } } + + public void set_latitude(int in_lat) { + lat = in_lat / 10.0e7; + } + + public void set_longitude(int in_lon) { + lon = in_lon / 10.0e7; + } + + public void set_time(int hour, int minute, int second) { + hour = hour; + minute = minute; + second = second; + } + + public void set_date(int year, int month, int day) { + year = year; + month = month; + day = day; + } + + public void set_flags(int flags) { + flags = flags; + } + + public void set_altitude(int altitude) { + altitude = altitude; + } + + public void add_sat(int svid, int c_n0) { + if (cc_gps_sat == null) { + cc_gps_sat = new AltosGPS.AltosGPSSat[1]; + } else { + AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1]; + for (int i = 0; i < cc_gps_sat.length; i++) + new_gps_sat[i] = cc_gps_sat[i]; + cc_gps_sat = new_gps_sat; + } + AltosGPS.AltosGPSSat sat = new AltosGPS.AltosGPSSat(); + sat.svid = svid; + sat.c_n0 = c_n0; + cc_gps_sat[cc_gps_sat.length - 1] = sat; + } + + public AltosGPS() { + ClearGPSTime(); + cc_gps_sat = null; + } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 824e4b5b..fa5a9ade 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -310,13 +310,13 @@ public class AltosUI extends JFrame { info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); } info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.gps_time.year, - state.gps.gps_time.month, - state.gps.gps_time.day); + state.gps.year, + state.gps.month, + state.gps.day); info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.gps_time.hour, - state.gps.gps_time.minute, - state.gps.gps_time.second); + state.gps.hour, + state.gps.minute, + state.gps.second); int nsat_vis = 0; int c; -- cgit v1.2.3 From 9c9b35254c693b3ade42b24d1e29eaf31e6ba2aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Jul 2010 10:24:56 -0700 Subject: altosui: Clear displayed data rows as needed. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index fa5a9ade..faa20469 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -92,8 +92,11 @@ class AltosFlightInfoTableModel extends AbstractTableModel { public int getRowCount() { return 20; } + int current_row = 0; + int prev_num_rows = 0; + public Object getValueAt(int row, int col) { - if (row >= rows.size()) + if (row >= prev_num_rows) return ""; if (col == 0) return rows.get(row).name; @@ -101,9 +104,6 @@ class AltosFlightInfoTableModel extends AbstractTableModel { return rows.get(row).value; } - int current_row = 0; - int prev_num_rows = 0; - public void resetRow() { current_row = 0; } @@ -115,10 +115,9 @@ class AltosFlightInfoTableModel extends AbstractTableModel { current_row++; } public void finish() { - if (current_row > prev_num_rows) { + if (current_row > prev_num_rows) fireTableRowsInserted(prev_num_rows, current_row - 1); - prev_num_rows = current_row; - } + prev_num_rows = current_row; fireTableDataChanged(); } } -- cgit v1.2.3 From 9e8f7f75442303f9bfa99a0435984f5d36863ae6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Jul 2010 10:34:21 -0700 Subject: 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 --- ao-tools/altosui/AltosFlightInfoTableModel.java | 81 ++++++++++++++++++++++ ao-tools/altosui/AltosFlightStatusTableModel.java | 61 ++++++++++++++++ ao-tools/altosui/AltosUI.java | 84 +---------------------- ao-tools/altosui/Makefile | 2 + 4 files changed, 146 insertions(+), 82 deletions(-) create mode 100644 ao-tools/altosui/AltosFlightInfoTableModel.java create mode 100644 ao-tools/altosui/AltosFlightStatusTableModel.java diff --git a/ao-tools/altosui/AltosFlightInfoTableModel.java b/ao-tools/altosui/AltosFlightInfoTableModel.java new file mode 100644 index 00000000..2a22e3e5 --- /dev/null +++ b/ao-tools/altosui/AltosFlightInfoTableModel.java @@ -0,0 +1,81 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightInfoTableModel extends AbstractTableModel { + private String[] columnNames = {"Field", "Value"}; + + class InfoLine { + String name; + String value; + + public InfoLine(String n, String v) { + name = n; + value = v; + } + } + + private ArrayList rows = new ArrayList(); + + public int getColumnCount() { return columnNames.length; } + public String getColumnName(int col) { return columnNames[col]; } + + public int getRowCount() { return 20; } + + int current_row = 0; + int prev_num_rows = 0; + + public Object getValueAt(int row, int col) { + if (row >= rows.size()) + return ""; + if (col == 0) + return rows.get(row).name; + else + return rows.get(row).value; + } + + public void resetRow() { + current_row = 0; + } + public void addRow(String name, String value) { + if (current_row >= rows.size()) + rows.add(current_row, new InfoLine(name, value)); + else + rows.set(current_row, new InfoLine(name, value)); + current_row++; + } + public void finish() { + if (current_row > prev_num_rows) + fireTableRowsInserted(prev_num_rows, current_row - 1); + while (rows.size() > current_row) + rows.remove(rows.size() - 1); + prev_num_rows = current_row; + fireTableDataChanged(); + } +} diff --git a/ao-tools/altosui/AltosFlightStatusTableModel.java b/ao-tools/altosui/AltosFlightStatusTableModel.java new file mode 100644 index 00000000..174dd42c --- /dev/null +++ b/ao-tools/altosui/AltosFlightStatusTableModel.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightStatusTableModel extends AbstractTableModel { + private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + private Object[] data = { 0, "idle", 0, 0 }; + + public int getColumnCount() { return columnNames.length; } + public int getRowCount() { return 2; } + public Object getValueAt(int row, int col) { + if (row == 0) + return columnNames[col]; + return data[col]; + } + + public void setValueAt(Object value, int col) { + data[col] = value; + fireTableCellUpdated(1, col); + } + + public void setValueAt(Object value, int row, int col) { + setValueAt(value, col); + } + + public void set(AltosState state) { + setValueAt(String.format("%1.0f", state.height), 0); + setValueAt(state.data.state, 1); + setValueAt(state.data.rssi, 2); + double speed = state.baro_speed; + if (state.ascent) + speed = state.speed; + setValueAt(String.format("%1.0f", speed), 3); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index faa20469..58f39de5 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -37,91 +37,11 @@ import altosui.AltosDeviceDialog; import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; +import altosui.AltosFlightStatusTableModel; +import altosui.AltosFlightInfoTableModel; import libaltosJNI.*; -class AltosFlightStatusTableModel extends AbstractTableModel { - private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; - private Object[] data = { 0, "idle", 0, 0 }; - - public int getColumnCount() { return columnNames.length; } - public int getRowCount() { return 2; } - public Object getValueAt(int row, int col) { - if (row == 0) - return columnNames[col]; - return data[col]; - } - - public void setValueAt(Object value, int col) { - data[col] = value; - fireTableCellUpdated(1, col); - } - - public void setValueAt(Object value, int row, int col) { - setValueAt(value, col); - } - - public void set(AltosState state) { - setValueAt(String.format("%1.0f", state.height), 0); - setValueAt(state.data.state, 1); - setValueAt(state.data.rssi, 2); - double speed = state.baro_speed; - if (state.ascent) - speed = state.speed; - setValueAt(String.format("%1.0f", speed), 3); - } -} - -class AltosFlightInfoTableModel extends AbstractTableModel { - private String[] columnNames = {"Field", "Value"}; - - class InfoLine { - String name; - String value; - - public InfoLine(String n, String v) { - name = n; - value = v; - } - } - - private ArrayList rows = new ArrayList(); - - public int getColumnCount() { return columnNames.length; } - public String getColumnName(int col) { return columnNames[col]; } - - public int getRowCount() { return 20; } - - int current_row = 0; - int prev_num_rows = 0; - - public Object getValueAt(int row, int col) { - if (row >= prev_num_rows) - return ""; - if (col == 0) - return rows.get(row).name; - else - return rows.get(row).value; - } - - public void resetRow() { - current_row = 0; - } - public void addRow(String name, String value) { - if (current_row >= rows.size()) - rows.add(current_row, new InfoLine(name, value)); - else - rows.set(current_row, new InfoLine(name, value)); - current_row++; - } - public void finish() { - if (current_row > prev_num_rows) - fireTableRowsInserted(prev_num_rows, current_row - 1); - prev_num_rows = current_row; - fireTableDataChanged(); - } -} - public class AltosUI extends JFrame { private int channel = -1; diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 790aecda..3b88e1c1 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -6,6 +6,8 @@ CLASSFILES=\ AltosEeprom.class \ AltosEepromMonitor.class \ AltosFile.class \ + AltosFlightInfoTableModel.class \ + AltosFlightStatusTableModel.class \ AltosGPS.class \ AltosGreatCircle.class \ AltosLog.class \ -- cgit v1.2.3 From 02f17f2cd26189e2676a9dc0d86bd959ed0bc3f4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 00:54:05 -0400 Subject: move to science menu --- debian/altos.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/altos.desktop b/debian/altos.desktop index ae9bdc63..106e34a0 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -7,4 +7,4 @@ Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/ao-view %f Terminal=false MimeType=text/plain; -Categories=Viewer;Network; +Categories=Science; -- cgit v1.2.3 From 85a670b5a904d6750d0f179ae307baeb8fc7cbd2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Aug 2010 13:40:17 -0400 Subject: 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 --- ao-tools/altosui/Altos.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index bda4080e..6ea7b43c 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -54,6 +54,10 @@ public class Altos { static final int ao_flight_invalid = 9; static HashMap string_to_state = new HashMap(); + + static boolean map_initialized = false; + + static void initialize_map() { string_to_state.put("startup", ao_flight_startup); string_to_state.put("idle", ao_flight_idle); @@ -65,6 +69,7 @@ public class Altos { string_to_state.put("main", ao_flight_main); string_to_state.put("landed", ao_flight_landed); string_to_state.put("invalid", ao_flight_invalid); + map_initialized = true; } static String[] state_to_string = { @@ -81,6 +86,8 @@ public class Altos { }; static public int state(String state) { + if (!map_initialized) + initialize_map(); if (string_to_state.containsKey(state)) return string_to_state.get(state); return ao_flight_invalid; -- cgit v1.2.3 From d8bf05f7ad55964c9bce0551e58f4ef6c9f721ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Aug 2010 13:50:18 -0400 Subject: 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 --- ao-tools/altosui/AltosConvert.java | 57 +------- ao-tools/altosui/AltosEepromDownload.java | 1 + ao-tools/altosui/AltosEepromMonitor.java | 1 + ao-tools/altosui/AltosEepromReader.java | 120 +++++++++++++++++ ao-tools/altosui/AltosEepromRecord.java | 70 ++++++++++ ao-tools/altosui/AltosGPS.java | 30 +++++ ao-tools/altosui/AltosRecord.java | 208 ++++++++++++++++++++++++++++++ ao-tools/altosui/AltosState.java | 38 +++--- ao-tools/altosui/AltosTelemetry.java | 66 +--------- ao-tools/altosui/AltosUI.java | 93 ++++++++----- ao-tools/altosui/Makefile | 6 +- ao-tools/altosui/Manifest.txt | 2 +- 12 files changed, 517 insertions(+), 175 deletions(-) create mode 100644 ao-tools/altosui/AltosEepromReader.java create mode 100644 ao-tools/altosui/AltosEepromRecord.java create mode 100644 ao-tools/altosui/AltosRecord.java diff --git a/ao-tools/altosui/AltosConvert.java b/ao-tools/altosui/AltosConvert.java index 3be0716c..8cc1df27 100644 --- a/ao-tools/altosui/AltosConvert.java +++ b/ao-tools/altosui/AltosConvert.java @@ -62,7 +62,7 @@ public class AltosConvert { * altitudes are measured with respect to the mean sea level */ static double - cc_altitude_to_pressure(double altitude) + altitude_to_pressure(double altitude) { double base_temperature = LAYER0_BASE_TEMPERATURE; double base_pressure = LAYER0_BASE_PRESSURE; @@ -115,7 +115,7 @@ public class AltosConvert { /* outputs the altitude associated with the given pressure. the altitude returned is measured with respect to the mean sea level */ static double - cc_pressure_to_altitude(double pressure) + pressure_to_altitude(double pressure) { double next_base_temperature = LAYER0_BASE_TEMPERATURE; @@ -178,59 +178,6 @@ public class AltosConvert { return altitude; } - /* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - - static final double counts_per_kPa = 27 * 2047 / 3300; - static final double counts_at_101_3kPa = 1674.0; - - static double - cc_barometer_to_pressure(double count) - { - return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; - } - - static double - cc_barometer_to_altitude(double baro) - { - double Pa = cc_barometer_to_pressure(baro); - return cc_pressure_to_altitude(Pa); - } - - static final double count_per_mss = 27.0; - - static double - cc_accelerometer_to_acceleration(double accel, double ground_accel) - { - return (ground_accel - accel) / count_per_mss; - } - - /* Value for the CC1111 built-in temperature sensor - * Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - */ - - static double - cc_thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - static double cc_battery_to_voltage(double battery) { diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 1f4a278f..f2fcd09e 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -31,6 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue; import altosui.Altos; import altosui.AltosSerial; import altosui.AltosSerialMonitor; +import altosui.AltosRecord; import altosui.AltosTelemetry; import altosui.AltosState; import altosui.AltosDeviceDialog; diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java index e110a354..b88fdd29 100644 --- a/ao-tools/altosui/AltosEepromMonitor.java +++ b/ao-tools/altosui/AltosEepromMonitor.java @@ -30,6 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; import altosui.AltosSerial; import altosui.AltosSerialMonitor; +import altosui.AltosRecord; import altosui.AltosTelemetry; import altosui.AltosState; import altosui.AltosDeviceDialog; diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java new file mode 100644 index 00000000..6fe9bfe4 --- /dev/null +++ b/ao-tools/altosui/AltosEepromReader.java @@ -0,0 +1,120 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosRecord; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosEepromMonitor; + +public class AltosEepromReader { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + + static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; + + static final int seen_gps_time = 16; + + AltosRecord state; + AltosEepromRecord record; + + int seen; + + int tick; + + boolean done; + + FileInputStream input; + + public AltosRecord read() throws IOException, ParseException { + for (;;) { + if (record == null) { + record = new AltosEepromRecord(AltosRecord.gets(input)); + if (record == null) { + if (done) + return null; + return state; + } + + /* eeprom only records low 16 bits of tick count */ + int tick = record.tick | (state.tick & ~0xffff); + + if (tick < state.tick) { + if (state.tick - tick > 0x8000) + tick += 0x10000; + else + tick = state.tick; + } + + /* Accumulate data in the state record while + * the time stamp is not increasing + */ + + if ((seen & seen_basic) == seen_basic && tick > state.tick) + return new AltosRecord(state); + } + + state.tick = tick; + switch (record.cmd) { + case Altos.AO_LOG_FLIGHT: + state.ground_accel = record.a; + state.flight = record.b; + break; + case Altos.AO_LOG_SENSOR: + state.accel = record.a; + state.pres = record.b; + break; + case Altos.AO_LOG_TEMP_VOLT: + state.temp = record.a; + state.batt = record.b; + break; + case Altos.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + break; + case Altos.AO_LOG_GPS_TIME: + break; + } + record = null; + } + } + + public AltosEepromReader (FileInputStream in_input) { + state = new AltosRecord(); + input = in_input; + seen = 0; + done = false; + } +} diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java new file mode 100644 index 00000000..5b359352 --- /dev/null +++ b/ao-tools/altosui/AltosEepromRecord.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosRecord; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosEepromMonitor; + +public class AltosEepromRecord { + public int cmd; + public int tick; + public int a; + public int b; + + public AltosEepromRecord (String line) throws ParseException { + if (line == null) { + cmd = Altos.AO_LOG_INVALID; + } else { + String[] tokens = line.split("\\s+"); + + if (tokens[0].equals("serial-number")) { + cmd = Altos.AO_LOG_SERIAL_NUMBER; + tick = 0; + a = Integer.parseInt(tokens[1]); + b = 0; + } else { + if (tokens.length != 4) + throw new ParseException(line, 0); + cmd = tokens[0].codePointAt(0); + tick = Integer.parseInt(tokens[1]); + a = Integer.parseInt(tokens[2]); + b = Integer.parseInt(tokens[3]); + } + } + } + +} diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index 42f4dc83..6b84d7a5 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -166,4 +166,34 @@ public class AltosGPS { ClearGPSTime(); cc_gps_sat = null; } + + public AltosGPS(AltosGPS old) { + nsat = old.nsat; + gps_locked = old.gps_locked; + gps_connected = old.gps_connected; + lat = old.lat; /* degrees (+N -S) */ + lon = old.lon; /* degrees (+E -W) */ + alt = old.alt; /* m */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + gps_extended = old.gps_extended; /* has extra data */ + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + AltosGPSSat[] cc_gps_sat; /* tracking data */ + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } + } } diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java new file mode 100644 index 00000000..c3e9d211 --- /dev/null +++ b/ao-tools/altosui/AltosRecord.java @@ -0,0 +1,208 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; +import java.io.*; +import altosui.AltosConvert; +import altosui.AltosGPS; + +public class AltosRecord { + int version; + String callsign; + int serial; + int flight; + int rssi; + int status; + String state; + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + int flight_accel; + int ground_accel; + int flight_vel; + int flight_pres; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + AltosGPS gps; + + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + static final double counts_per_kPa = 27 * 2047 / 3300; + static final double counts_at_101_3kPa = 1674.0; + + static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + public double pressure() { + return barometer_to_pressure(pres); + } + + public double ground_pressure() { + return barometer_to_pressure(ground_pres); + } + + public double altitude() { + return AltosConvert.pressure_to_altitude(pressure()); + } + + public double ground_altitude() { + return AltosConvert.pressure_to_altitude(ground_pressure()); + } + + public double height() { + return altitude() - ground_altitude(); + } + + public double battery_voltage() { + return AltosConvert.cc_battery_to_voltage(batt); + } + + public double main_voltage() { + return AltosConvert.cc_ignitor_to_voltage(main); + } + + public double drogue_voltage() { + return AltosConvert.cc_ignitor_to_voltage(drogue); + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public double temperature() { + return thermometer_to_temperature(temp); + } + + double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + public double acceleration() { + return (accel_plus_g - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + double speed = flight_vel / (accel_counts_per_mss() * 100.0); + return speed; + } + + public int state() { + System.out.printf("state: %s -> %d\n", state, Altos.state(state)); + return Altos.state(state); + } + + public static String gets(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') { + return line; + } + line = line + (char) c; + } + return null; + } + + public AltosRecord(AltosRecord old) { + version = old.version; + callsign = old.callsign; + serial = old.serial; + flight = old.flight; + rssi = old.rssi; + status = old.status; + state = old.state; + tick = old.tick; + accel = old.accel; + pres = old.pres; + temp = old.temp; + batt = old.batt; + drogue = old.drogue; + main = old.main; + flight_accel = old.flight_accel; + ground_accel = old.ground_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + gps = new AltosGPS(old.gps); + } + + public AltosRecord() { + version = 0; + callsign = "N0CALL"; + serial = 0; + flight = 0; + rssi = 0; + status = 0; + state = "startup"; + tick = 0; + accel = 0; + pres = 0; + temp = 0; + batt = 0; + drogue = 0; + main = 0; + flight_accel = 0; + ground_accel = 0; + flight_vel = 0; + flight_pres = 0; + ground_pres = 0; + accel_plus_g = 0; + accel_minus_g = 0; + gps = new AltosGPS(); + } +} diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 9aa10a08..fc06f839 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -16,16 +16,16 @@ */ /* - * Track flight state from telemetry data stream + * Track flight state from telemetry or eeprom data stream */ package altosui; -import altosui.AltosTelemetry; +import altosui.AltosRecord; import altosui.AltosGPS; public class AltosState { - AltosTelemetry data; + AltosRecord data; /* derived data */ @@ -71,25 +71,23 @@ public class AltosState { double speak_altitude; - void init (AltosTelemetry cur, AltosState prev_state) { + void init (AltosRecord cur, AltosState prev_state) { int i; - AltosTelemetry prev; - double accel_counts_per_mss; + AltosRecord prev; data = cur; - ground_altitude = AltosConvert.cc_barometer_to_altitude(data.ground_pres); - height = AltosConvert.cc_barometer_to_altitude(data.flight_pres) - ground_altitude; + ground_altitude = data.ground_altitude(); + height = data.altitude() - ground_altitude; report_time = System.currentTimeMillis(); - accel_counts_per_mss = ((data.accel_minus_g - data.accel_plus_g) / 2.0) / 9.80665; - acceleration = (data.ground_accel - data.flight_accel) / accel_counts_per_mss; - speed = data.flight_vel / (accel_counts_per_mss * 100.0); - temperature = AltosConvert.cc_thermometer_to_temperature(data.temp); - drogue_sense = AltosConvert.cc_ignitor_to_voltage(data.drogue); - main_sense = AltosConvert.cc_ignitor_to_voltage(data.main); - battery = AltosConvert.cc_battery_to_voltage(data.batt); + acceleration = data.acceleration(); + speed = data.accel_speed(); + temperature = data.temperature(); + drogue_sense = data.drogue_voltage(); + main_sense = data.main_voltage(); + battery = data.battery_voltage(); tick = data.tick; state = data.state(); @@ -125,7 +123,7 @@ public class AltosState { time_change = 0; } - if (state == AltosTelemetry.ao_flight_pad) { + if (state == Altos.ao_flight_pad) { if (data.gps != null && data.gps.gps_locked && data.gps.nsat >= 4) { npad++; if (npad > 1) { @@ -149,8 +147,8 @@ public class AltosState { gps_ready = gps_waiting == 0; - ascent = (AltosTelemetry.ao_flight_boost <= state && - state <= AltosTelemetry.ao_flight_coast); + ascent = (Altos.ao_flight_boost <= state && + state <= Altos.ao_flight_coast); /* Only look at accelerometer data on the way up */ if (ascent && acceleration > max_acceleration) @@ -173,11 +171,11 @@ public class AltosState { } } - public AltosState(AltosTelemetry cur) { + public AltosState(AltosRecord cur) { init(cur, null); } - public AltosState (AltosTelemetry cur, AltosState prev) { + public AltosState (AltosRecord cur, AltosState prev) { init(cur, prev); } } diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index e13b42e2..f495be1d 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -21,6 +21,7 @@ import java.lang.*; import java.text.*; import java.util.HashMap; import altosui.AltosConvert; +import altosui.AltosRecord; import altosui.AltosGPS; /* @@ -51,72 +52,9 @@ import altosui.AltosGPS; * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 */ -public class AltosTelemetry { - int version; - String callsign; - int serial; - int flight; - int rssi; - int status; - String state; - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - int flight_accel; - int ground_accel; - int flight_vel; - int flight_pres; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - AltosGPS gps; - - public static final int ao_flight_startup = 0; - public static final int ao_flight_idle = 1; - public static final int ao_flight_pad = 2; - public static final int ao_flight_boost = 3; - public static final int ao_flight_fast = 4; - public static final int ao_flight_coast = 5; - public static final int ao_flight_drogue = 6; - public static final int ao_flight_main = 7; - public static final int ao_flight_landed = 8; - public static final int ao_flight_invalid = 9; - - static HashMap states = new HashMap(); - { - states.put("startup", ao_flight_startup); - states.put("idle", ao_flight_idle); - states.put("pad", ao_flight_pad); - states.put("boost", ao_flight_boost); - states.put("fast", ao_flight_fast); - states.put("coast", ao_flight_coast); - states.put("drogue", ao_flight_drogue); - states.put("main", ao_flight_main); - states.put("landed", ao_flight_landed); - states.put("invalid", ao_flight_invalid); - } - - public int state() { - if (states.containsKey(state)) - return states.get(state); - return ao_flight_invalid; - } - - public double altitude() { - return AltosConvert.cc_pressure_to_altitude(AltosConvert.cc_barometer_to_pressure(pres)); - } - - public double pad_altitude() { - return AltosConvert.cc_pressure_to_altitude(AltosConvert.cc_barometer_to_pressure(ground_pres)); - } - +public class AltosTelemetry extends AltosRecord { public AltosTelemetry(String line) throws ParseException { String[] words = line.split("\\s+"); - int i = 0; AltosParse.word (words[i++], "VERSION"); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 58f39de5..40663882 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -31,6 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue; import altosui.Altos; import altosui.AltosSerial; import altosui.AltosSerialMonitor; +import altosui.AltosRecord; import altosui.AltosTelemetry; import altosui.AltosState; import altosui.AltosDeviceDialog; @@ -343,7 +344,9 @@ public class AltosUI extends JFrame { class DisplayThread extends Thread { IdleThread idle_thread; - String read() throws InterruptedException { return null; } + String name; + + AltosRecord read() throws InterruptedException, ParseException { return null; } void close() { } @@ -360,18 +363,19 @@ public class AltosUI extends JFrame { info_finish(); idle_thread.start(); try { - while ((line = read()) != null) { + for (;;) { try { - AltosTelemetry t = new AltosTelemetry(line); + AltosRecord record = read(); + if (record == null) + break; old_state = state; - state = new AltosState(t, state); + state = new AltosState(record, state); update(state); show(state); tell(state, old_state); idle_thread.notice(state); } catch (ParseException pp) { - System.out.printf("Parse error on %s\n", line); - System.out.println("exception " + pp); + System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); } } } catch (InterruptedException ee) { @@ -387,11 +391,20 @@ public class AltosUI extends JFrame { } } - class DeviceThread extends DisplayThread { + class TelemetryThread extends DisplayThread { + + String readline() throws InterruptedException { return null; } + + AltosRecord read() throws InterruptedException, ParseException { + return new AltosTelemetry(readline()); + } + } + + class DeviceThread extends TelemetryThread { AltosSerial serial; LinkedBlockingQueue telem; - String read() throws InterruptedException { + String readline() throws InterruptedException { return telem.take(); } @@ -404,6 +417,7 @@ public class AltosUI extends JFrame { serial = s; telem = new LinkedBlockingQueue(); serial.add_monitor(telem); + name = "telemetry"; } } @@ -435,40 +449,26 @@ public class AltosUI extends JFrame { stop_display(); } - String readline(FileInputStream s) throws IOException { - int c; - String line = ""; - - while ((c = s.read()) != -1) { - if (c == '\r') - continue; - if (c == '\n') { - return line; - } - line = line + (char) c; - } - return null; - } - /* * Open an existing telemetry file and replay it in realtime */ - class ReplayThread extends DisplayThread { + class ReplayTelemetryThread extends TelemetryThread { FileInputStream replay; - String filename; - ReplayThread(FileInputStream in, String name) { + ReplayTelemetryThread(FileInputStream in, String in_name) { replay = in; - filename = name; + name = in_name; } - String read() { + String readline() { try { - return readline(replay); + String line = AltosRecord.gets(replay); + System.out.printf("telemetry line %s\n", line); + return line; } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - filename, + name, "error reading", JOptionPane.ERROR_MESSAGE); } @@ -485,11 +485,32 @@ public class AltosUI extends JFrame { void update(AltosState state) throws InterruptedException { /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > AltosTelemetry.ao_flight_pad) + if (state.state > Altos.ao_flight_pad) Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); } } + class ReplayEepromThread extends DisplayThread { + FileInputStream replay; + + AltosRecord read () { + return null; + } + + void close () { + try { + replay.close(); + } catch (IOException ee) { + } + report(); + } + + ReplayEepromThread(FileInputStream in, String in_name) { + replay = in; + name = in_name; + } + } + Thread display_thread; private void stop_display() { @@ -510,8 +531,8 @@ public class AltosUI extends JFrame { private void Replay() { JFileChooser logfile_chooser = new JFileChooser(); - logfile_chooser.setDialogTitle("Select Telemetry File"); - logfile_chooser.setFileFilter(new FileNameExtensionFilter("Telemetry file", "telem")); + 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); @@ -522,7 +543,11 @@ public class AltosUI extends JFrame { String filename = file.getName(); try { FileInputStream replay = new FileInputStream(file); - ReplayThread thread = new ReplayThread(replay, filename); + 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, diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 3b88e1c1..3f55db0b 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -2,9 +2,12 @@ CLASSPATH=classes:./* CLASSFILES=\ + Altos.class \ AltosConvert.class \ - AltosEeprom.class \ + AltosEepromDownload.class \ AltosEepromMonitor.class \ + AltosEepromReader.class \ + AltosEepromRecord.class \ AltosFile.class \ AltosFlightInfoTableModel.class \ AltosFlightStatusTableModel.class \ @@ -13,6 +16,7 @@ CLASSFILES=\ AltosLog.class \ AltosParse.class \ AltosPreferences.class \ + AltosRecord.class \ AltosSerialMonitor.class \ AltosSerial.class \ AltosState.class \ diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 251ce2a0..504d0de3 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: freetts.jar +Class-Path: /usr/share/java/freetts.jar -- cgit v1.2.3 From aed55ef1ce45b0f6e6fefeebf50be97607b31d65 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:00:15 -0400 Subject: working on java packaging details --- ao-tools/altosui/Makefile | 33 +++++++++++++++++---------------- ao-tools/altosui/Manifest.txt | 2 +- debian/altos.desktop | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 790aecda..bae42c9a 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=classes:./* +CLASSPATH=classes:./*:/usr/share/java/* CLASSFILES=\ AltosConvert.class \ AltosEeprom.class \ @@ -20,16 +20,17 @@ CLASSFILES=\ AltosDeviceDialog.class \ AltosVoice.class -FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2 -FREETTSLIB=$(FREETTSSRC)/lib -FREETTSJAR= \ - cmudict04.jar \ - cmulex.jar \ - cmu_time_awb.jar \ - cmutimelex.jar \ - cmu_us_kal.jar \ - en_us.jar \ - freetts.jar +#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 @@ -55,14 +56,14 @@ altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Man classes/altosui: mkdir -p classes - ln -s .. classes/altosui + ln -sf .. classes/altosui classes/libaltosJNI: mkdir -p classes - ln -s ../../libaltos/libaltosJNI classes/libaltosJNI + ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI -$(FREETTSJAR): - ln -s $(FREETTSLIB)/$@ . +#$(FREETTSJAR): +# ln -s $(FREETTSLIB)/$@ . ifeq ($(OS),Darwin) RESOURCES=altosui.jar $(FREETTSJAR) ../libaltos/libaltos.dylib @@ -81,6 +82,6 @@ altosui: endif clean: - rm -f *.class $(FREETTSJAR) altosui.jar + rm -f *.class altosui.jar rm -f AltosUI.app/Contents/Resources/Java/* rm -rf classes diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 1f313a13..504d0de3 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: /usr/share/java/freetts-1.2.2.jar +Class-Path: /usr/share/java/freetts.jar diff --git a/debian/altos.desktop b/debian/altos.desktop index 106e34a0..4281ad3a 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -7,4 +7,4 @@ Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/ao-view %f Terminal=false MimeType=text/plain; -Categories=Science; +Categories=Education;Science; -- cgit v1.2.3 From d091099753d9cae01c4805812425ebea19ec09cf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:00:46 -0400 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4acfeae4..04e360b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit aed55ef1ce45b0f6e6fefeebf50be97607b31d65 +Author: Bdale Garbee +Date: Thu Aug 5 15:00:15 2010 -0400 + + working on java packaging details + +commit 02f17f2cd26189e2676a9dc0d86bd959ed0bc3f4 +Author: Bdale Garbee +Date: Thu Aug 5 00:54:05 2010 -0400 + + move to science menu + +commit e3a9e3815db3f290e28b40ae02aa654f515cfc37 +Author: Bdale Garbee +Date: Sat Jul 31 10:55:27 2010 -0600 + + update changelogs for Debian build + commit 8fc261c2b77bb8aab201a0649a84b5ffa236ce26 Author: Bdale Garbee Date: Sat Jul 31 10:55:07 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 5d07e30d..9c807101 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.6+295+gaed55ef) unstable; urgency=low + + * move to science menu + * working on java packaging details + + -- Bdale Garbee Thu, 05 Aug 2010 15:00:37 -0400 + altos (0.6+292+g8fc261c) unstable; urgency=low * see if my new freetts package works -- cgit v1.2.3 From 0b85160c44d934f3d1352c1c07c296d01ceffc32 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:02:17 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 04e360b4..69a49f42 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit d091099753d9cae01c4805812425ebea19ec09cf +Author: Bdale Garbee +Date: Thu Aug 5 15:00:46 2010 -0400 + + update changelogs for Debian build + commit aed55ef1ce45b0f6e6fefeebf50be97607b31d65 Author: Bdale Garbee Date: Thu Aug 5 15:00:15 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 9c807101..3f8a079f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+295+gaed55ef) unstable; urgency=low +altos (0.6+296+gd091099) unstable; urgency=low * move to science menu * working on java packaging details -- cgit v1.2.3 From 410de62715a0830f03b0a65d6c7730dff51e6ef4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:15:04 -0400 Subject: add freetts as a build dep --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index ba9354b8..cc8fda94 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From e075b8623533965b1b77b77d38c2df32f5f77fce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:16:24 -0400 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 69a49f42..1fd15a41 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 410de62715a0830f03b0a65d6c7730dff51e6ef4 +Author: Bdale Garbee +Date: Thu Aug 5 15:15:04 2010 -0400 + + add freetts as a build dep + +commit 0b85160c44d934f3d1352c1c07c296d01ceffc32 +Author: Bdale Garbee +Date: Thu Aug 5 15:02:17 2010 -0400 + + update changelogs for Debian build + commit d091099753d9cae01c4805812425ebea19ec09cf Author: Bdale Garbee Date: Thu Aug 5 15:00:46 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 3f8a079f..8185ed0f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+298+g410de62) unstable; urgency=low + + * add freetts as a build dep + + -- Bdale Garbee Thu, 05 Aug 2010 15:16:07 -0400 + altos (0.6+296+gd091099) unstable; urgency=low * move to science menu -- cgit v1.2.3 From a0a9b445a4d379730b67720f8d7b682d5206a582 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:16:48 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 7 +------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1fd15a41..3b2af868 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit e075b8623533965b1b77b77d38c2df32f5f77fce +Author: Bdale Garbee +Date: Thu Aug 5 15:16:24 2010 -0400 + + update changelogs for Debian build + commit 410de62715a0830f03b0a65d6c7730dff51e6ef4 Author: Bdale Garbee Date: Thu Aug 5 15:15:04 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 8185ed0f..23a4cf8b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,11 +1,6 @@ -altos (0.6+298+g410de62) unstable; urgency=low +altos (0.6+299+ge075b86) unstable; urgency=low * add freetts as a build dep - - -- Bdale Garbee Thu, 05 Aug 2010 15:16:07 -0400 - -altos (0.6+296+gd091099) unstable; urgency=low - * move to science menu * working on java packaging details -- cgit v1.2.3 From 0e917f3ff822616adb147517ac961422e5fedbfd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Aug 2010 22:49:53 -0400 Subject: altosui: Compute flight state from eeprom data This lets eeprom files be used to replay flights. Signed-off-by: Keith Packard --- ao-tools/altosui/Altos.java | 20 ++- ao-tools/altosui/AltosEepromReader.java | 178 +++++++++++++++++++--- ao-tools/altosui/AltosEepromRecord.java | 56 ++++++- ao-tools/altosui/AltosFlightStatusTableModel.java | 2 +- ao-tools/altosui/AltosGPS.java | 31 ++-- ao-tools/altosui/AltosRecord.java | 11 +- ao-tools/altosui/AltosState.java | 13 +- ao-tools/altosui/AltosTelemetry.java | 2 +- ao-tools/altosui/AltosUI.java | 34 +++-- 9 files changed, 277 insertions(+), 70 deletions(-) diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 6ea7b43c..53359e23 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -35,8 +35,18 @@ public class Altos { static final int AO_LOG_GPS_SAT = 'V'; static final int AO_LOG_GPS_DATE = 'Y'; - /* Added for 'serial-number' entry in eeprom files */ - static final int AO_LOG_SERIAL_NUMBER = 1000; + /* Added for header fields in eeprom files */ + static final int AO_LOG_CONFIG_VERSION = 1000; + static final int AO_LOG_MAIN_DEPLOY = 1001; + static final int AO_LOG_APOGEE_DELAY = 1002; + static final int AO_LOG_RADIO_CHANNEL = 1003; + static final int AO_LOG_CALLSIGN = 1004; + static final int AO_LOG_ACCEL_CAL = 1005; + static final int AO_LOG_RADIO_CAL = 1006; + static final int AO_LOG_MANUFACTURER = 1007; + static final int AO_LOG_PRODUCT = 1008; + static final int AO_LOG_SERIAL_NUMBER = 1009; + static final int AO_LOG_SOFTWARE_VERSION = 1010; /* Added to flag invalid records */ static final int AO_LOG_INVALID = -1; @@ -98,4 +108,10 @@ public class Altos { return "invalid"; return state_to_string[state]; } + + static final int AO_GPS_VALID = (1 << 4); + static final int AO_GPS_RUNNING = (1 << 5); + 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; } diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 6fe9bfe4..7a8ff5b0 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -36,75 +36,181 @@ import altosui.AltosLog; import altosui.AltosVoice; import altosui.AltosEepromMonitor; +class AltosOrderedRecord extends AltosEepromRecord implements Comparable { + + int index; + + public AltosOrderedRecord(String line, int in_index, int prev_tick) + throws ParseException { + super(line); + int new_tick = tick | (prev_tick & ~0xffff); + if (new_tick < prev_tick) { + if (prev_tick - new_tick > 0x8000) + new_tick += 0x10000; + } + tick = new_tick; + index = in_index; + } + + public int compareTo(AltosOrderedRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} + public class AltosEepromReader { static final int seen_flight = 1; static final int seen_sensor = 2; static final int seen_temp_volt = 4; static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; - static final int seen_gps_time = 16; - AltosRecord state; - AltosEepromRecord record; + AltosOrderedRecord record; + + TreeSet records; + + Iterator record_iterator; int seen; - int tick; + int index; + + boolean last_reported; + + double ground_pres; + double ground_accel; + + int n_pad_samples; - boolean done; + int gps_tick; FileInputStream input; public AltosRecord read() throws IOException, ParseException { for (;;) { if (record == null) { - record = new AltosEepromRecord(AltosRecord.gets(input)); - if (record == null) { - if (done) + if (!record_iterator.hasNext()) { + if (last_reported) return null; + last_reported = true; return state; } + record = record_iterator.next(); - /* eeprom only records low 16 bits of tick count */ - int tick = record.tick | (state.tick & ~0xffff); - - if (tick < state.tick) { - if (state.tick - tick > 0x8000) - tick += 0x10000; - else - tick = state.tick; - } - - /* Accumulate data in the state record while - * the time stamp is not increasing - */ - - if ((seen & seen_basic) == seen_basic && tick > state.tick) + if ((seen & seen_basic) == seen_basic && record.tick != state.tick) return new AltosRecord(state); } - state.tick = tick; + state.tick = record.tick; switch (record.cmd) { case Altos.AO_LOG_FLIGHT: state.ground_accel = record.a; state.flight = record.b; + seen |= seen_flight; break; case Altos.AO_LOG_SENSOR: state.accel = record.a; state.pres = record.b; + if (state.state < Altos.ao_flight_boost) { + n_pad_samples++; + 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; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + state.flight_vel += (state.accel_plus_g - state.accel); + } + seen |= seen_sensor; break; case Altos.AO_LOG_TEMP_VOLT: state.temp = record.a; state.batt = record.b; + seen |= seen_temp_volt; break; case Altos.AO_LOG_DEPLOY: state.drogue = record.a; state.main = record.b; + 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; + state.gps = new AltosGPS(); + state.gps.hour = (record.a & 0xff); + state.gps.minute = (record.a >> 8); + state.gps.second = (record.b & 0xff); + int flags = (record.b >> 8); + state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; + state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; + state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> + Altos.AO_GPS_NUM_SAT_SHIFT; + break; + case Altos.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case Altos.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case Altos.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case Altos.AO_LOG_GPS_SAT: + if (state.tick == gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case Altos.AO_LOG_GPS_DATE: + state.gps.year = record.a & 0xff; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case Altos.AO_LOG_CONFIG_VERSION: + break; + case Altos.AO_LOG_MAIN_DEPLOY: + break; + case Altos.AO_LOG_APOGEE_DELAY: + break; + case Altos.AO_LOG_RADIO_CHANNEL: + break; + case Altos.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case Altos.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case Altos.AO_LOG_RADIO_CAL: + break; + case Altos.AO_LOG_MANUFACTURER: + break; + case Altos.AO_LOG_PRODUCT: + break; + case Altos.AO_LOG_SERIAL_NUMBER: + break; + case Altos.AO_LOG_SOFTWARE_VERSION: break; } record = null; @@ -113,8 +219,30 @@ public class AltosEepromReader { public AltosEepromReader (FileInputStream in_input) { state = new AltosRecord(); + state.state = Altos.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; input = in_input; seen = 0; - done = false; + records = new TreeSet(); + + int index = 0; + int tick = 0; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, tick); + if (record == null) + break; + tick = record.tick; + records.add(record); + } + } catch (IOException io) { + } catch (ParseException pe) { + } + record_iterator = records.iterator(); } } diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java index 5b359352..86ac1fd2 100644 --- a/ao-tools/altosui/AltosEepromRecord.java +++ b/ao-tools/altosui/AltosEepromRecord.java @@ -44,25 +44,65 @@ public class AltosEepromRecord { public int tick; public int a; public int b; + String data; + public boolean tick_valid; public AltosEepromRecord (String line) throws ParseException { + tick_valid = false; + tick = 0; + a = 0; + b = 0; + data = null; if (line == null) { cmd = Altos.AO_LOG_INVALID; } else { String[] tokens = line.split("\\s+"); - if (tokens[0].equals("serial-number")) { - cmd = Altos.AO_LOG_SERIAL_NUMBER; - tick = 0; - a = Integer.parseInt(tokens[1]); - b = 0; - } else { + if (tokens[0].length() == 1) { if (tokens.length != 4) throw new ParseException(line, 0); cmd = tokens[0].codePointAt(0); - tick = Integer.parseInt(tokens[1]); + 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]); - b = Integer.parseInt(tokens[3]); + } 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; } } } diff --git a/ao-tools/altosui/AltosFlightStatusTableModel.java b/ao-tools/altosui/AltosFlightStatusTableModel.java index 174dd42c..4c24b6ac 100644 --- a/ao-tools/altosui/AltosFlightStatusTableModel.java +++ b/ao-tools/altosui/AltosFlightStatusTableModel.java @@ -51,7 +51,7 @@ public class AltosFlightStatusTableModel extends AbstractTableModel { public void set(AltosState state) { setValueAt(String.format("%1.0f", state.height), 0); - setValueAt(state.data.state, 1); + setValueAt(state.data.state(), 1); setValueAt(state.data.rssi, 2); double speed = state.baro_speed; if (state.ascent) diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index 6b84d7a5..b3ee67e8 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -29,8 +29,9 @@ public class AltosGPS { } int nsat; - boolean gps_locked; - boolean gps_connected; + boolean locked; + boolean connected; + boolean date_valid; double lat; /* degrees (+N -S) */ double lon; /* degrees (+E -W) */ int alt; /* m */ @@ -77,19 +78,19 @@ public class AltosGPS { nsat = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "sat"); - gps_connected = false; - gps_locked = false; + connected = false; + locked = false; lat = lon = 0; alt = 0; ClearGPSTime(); if ((words[i]).equals("unlocked")) { - gps_connected = true; + connected = true; i++; } else if ((words[i]).equals("not-connected")) { i++; } else if (words.length >= 40) { - gps_locked = true; - gps_connected = true; + locked = true; + connected = true; ParseGPSTime(words[i], words[i+1]); i += 2; lat = AltosParse.parse_coord(words[i++]); @@ -169,8 +170,8 @@ public class AltosGPS { public AltosGPS(AltosGPS old) { nsat = old.nsat; - gps_locked = old.gps_locked; - gps_connected = old.gps_connected; + locked = old.locked; + connected = old.connected; lat = old.lat; /* degrees (+N -S) */ lon = old.lon; /* degrees (+E -W) */ alt = old.alt; /* m */ @@ -189,11 +190,13 @@ public class AltosGPS { h_error = old.h_error; /* m */ v_error = old.v_error; /* m */ - AltosGPSSat[] cc_gps_sat; /* tracking data */ - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } } } } diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java index c3e9d211..3440d935 100644 --- a/ao-tools/altosui/AltosRecord.java +++ b/ao-tools/altosui/AltosRecord.java @@ -31,7 +31,7 @@ public class AltosRecord { int flight; int rssi; int status; - String state; + int state; int tick; int accel; int pres; @@ -72,7 +72,7 @@ public class AltosRecord { } public double pressure() { - return barometer_to_pressure(pres); + return barometer_to_pressure(flight_pres); } public double ground_pressure() { @@ -136,9 +136,8 @@ public class AltosRecord { return speed; } - public int state() { - System.out.printf("state: %s -> %d\n", state, Altos.state(state)); - return Altos.state(state); + public String state() { + return Altos.state_name(state); } public static String gets(FileInputStream s) throws IOException { @@ -188,7 +187,7 @@ public class AltosRecord { flight = 0; rssi = 0; status = 0; - state = "startup"; + state = Altos.ao_flight_startup; tick = 0; accel = 0; pres = 0; diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index fc06f839..deeb4c77 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -89,7 +89,7 @@ public class AltosState { main_sense = data.main_voltage(); battery = data.battery_voltage(); tick = data.tick; - state = data.state(); + state = data.state; if (prev_state != null) { @@ -124,7 +124,12 @@ public class AltosState { } if (state == Altos.ao_flight_pad) { - if (data.gps != null && data.gps.gps_locked && data.gps.nsat >= 4) { + 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) { npad++; if (npad > 1) { /* filter pad position */ @@ -159,9 +164,9 @@ public class AltosState { if (height > max_height) max_height = height; if (data.gps != null) { - if (gps == null || !gps.gps_locked || data.gps.gps_locked) + if (gps == null || !gps.locked || data.gps.locked) gps = data.gps; - if (npad > 0 && gps.gps_locked) + if (npad > 0 && gps.locked) from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); } if (npad > 0) { diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index f495be1d..af29b8c0 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -76,7 +76,7 @@ public class AltosTelemetry extends AltosRecord { status = AltosParse.parse_hex(words[i++]); AltosParse.word(words[i++], "STATE"); - state = words[i++]; + state = Altos.state(words[i++]); tick = AltosParse.parse_int(words[i++]); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 40663882..2cb0c479 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -173,7 +173,7 @@ public class AltosUI extends JFrame { 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, "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); @@ -193,9 +193,9 @@ public class AltosUI extends JFrame { if (state.gps == null) { info_add_row(1, "GPS", "not available"); } else { - if (state.data.gps.gps_locked) + if (state.data.gps.locked) info_add_row(1, "GPS", " locked"); - else if (state.data.gps.gps_connected) + else if (state.data.gps.connected) info_add_row(1, "GPS", " unlocked"); else info_add_row(1, "GPS", " missing"); @@ -321,7 +321,7 @@ public class AltosUI extends JFrame { private void tell(AltosState state, AltosState old_state) { if (old_state == null || old_state.state != state.state) { - voice.speak(state.data.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.", @@ -493,7 +493,23 @@ public class AltosUI extends JFrame { class ReplayEepromThread extends DisplayThread { FileInputStream replay; - AltosRecord read () { + AltosEepromReader reader; + + ReplayEepromThread(FileInputStream in, String in_name) { + replay = in; + name = in_name; + reader = new AltosEepromReader (in); + } + + AltosRecord read () throws ParseException { + try { + return reader.read(); + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + name, + "error reading", + JOptionPane.ERROR_MESSAGE); + } return null; } @@ -504,10 +520,10 @@ public class AltosUI extends JFrame { } report(); } - - ReplayEepromThread(FileInputStream in, String in_name) { - replay = in; - name = in_name; + void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > Altos.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); } } -- cgit v1.2.3 From b7699a5907e64bc7547fcc27e73f4a35bbaabfff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Aug 2010 13:09:21 -0400 Subject: altosui: Add comments to Eeprom reader --- ao-tools/altosui/AltosEepromReader.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 7a8ff5b0..9b928abb 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -36,6 +36,10 @@ import altosui.AltosLog; import altosui.AltosVoice; import altosui.AltosEepromMonitor; +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ class AltosOrderedRecord extends AltosEepromRecord implements Comparable { int index; @@ -217,6 +221,13 @@ public class AltosEepromReader { } } + /* + * Read the whole file, dumping records into a RB tree so + * we can enumerate them in time order -- the eeprom data + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ public AltosEepromReader (FileInputStream in_input) { state = new AltosRecord(); state.state = Altos.ao_flight_pad; -- cgit v1.2.3 From 4738cb2fc639adb1d9237e6c903479f0690dd81a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Aug 2010 00:40:59 -0400 Subject: 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 --- src/ao.h | 3 ++- src/ao_packet_master.c | 2 ++ src/ao_packet_slave.c | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 5dd756da..5f2b8339 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1034,7 +1034,7 @@ struct ao_fifo { * Packet-based command interface */ -#define AO_PACKET_MAX 8 +#define AO_PACKET_MAX 64 #define AO_PACKET_SYN (uint8_t) 0xff struct ao_packet { @@ -1043,6 +1043,7 @@ struct ao_packet { uint8_t seq; uint8_t ack; uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; }; struct ao_packet_recv { diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index ef86fa28..72bb908a 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -77,12 +77,14 @@ ao_packet_master(void) { uint8_t status; + ao_config_get(); ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; ao_packet_master_time = ao_time(); ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { + memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e03ebdc3..9b78767f 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -27,8 +27,10 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { status = ao_packet_recv(); - if (status & AO_DMA_DONE) + if (status & AO_DMA_DONE) { + memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); ao_packet_send(); + } } ao_exit(); } -- cgit v1.2.3 From f317f1324b69b4241f4bb192e164b33d712d5a43 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Aug 2010 00:42:25 -0400 Subject: 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 --- ao-tools/altosui/AltosCSV.java | 115 +++++++++++++++++++++++++++++ ao-tools/altosui/AltosEepromReader.java | 68 +++++++++++++++-- ao-tools/altosui/AltosReader.java | 28 +++++++ ao-tools/altosui/AltosRecord.java | 2 + ao-tools/altosui/AltosTelemetryReader.java | 71 ++++++++++++++++++ ao-tools/altosui/AltosUI.java | 81 ++++++-------------- ao-tools/altosui/Makefile | 2 + 7 files changed, 301 insertions(+), 66 deletions(-) create mode 100644 ao-tools/altosui/AltosCSV.java create mode 100644 ao-tools/altosui/AltosReader.java create mode 100644 ao-tools/altosui/AltosTelemetryReader.java diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java new file mode 100644 index 00000000..24936758 --- /dev/null +++ b/ao-tools/altosui/AltosCSV.java @@ -0,0 +1,115 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 altosui.AltosRecord; + +public class AltosCSV { + File name; + PrintStream out; + boolean header_written; + + static final int ALTOS_CSV_VERSION = 1; + + /* Version 1 format: + * + * General info + * version number + * serial number + * flight number + * callsign + * time (seconds since boost) + * + * Flight status + * state + * state name + * + * Basic sensors + * acceleration (m/s²) + * pressure (mBar) + * altitude (m) + * accelerometer speed (m/s) + * barometer speed (m/s) + * temp (°C) + * battery (V) + * drogue (V) + * main (V) + * + * GPS data + * connected (1/0) + * locked (1/0) + * nsat (used for solution) + * latitude (°) + * longitude (°) + * altitude (m) + * year (e.g. 2010) + * month (1-12) + * day (1-31) + * hour (0-23) + * minute (0-59) + * second (0-59) + * + * GPS Sat data + * hdop + * C/N0 data for all 32 valid SDIDs + */ + + void write_general_header() { + out.printf("version serial flight call time"); + } + + void write_general(AltosRecord record) { + out.printf("%s,%d,%d,%s,%d", + record.version, record.serial, record.flight, record.callsign, record.tick); + } + + void write_flight_header() { + out.printf("state state_name"); + } + + void write_flight(AltosRecord record) { + out.printf("%d,%s", record.state, record.state()); + } + + void write_header() { + out.printf("# "); write_general_header(); + out.printf(" "); write_flight_header(); + out.printf ("\n"); + } + + public void write(AltosRecord record) { + if (!header_written) { + write_header(); + header_written = true; + } + write_general(record); out.printf(","); + write_flight(record); + out.printf ("\n"); + } + + public PrintStream out() { + return out; + } + + public AltosCSV(File in_name) throws FileNotFoundException { + name = in_name; + out = new PrintStream(name); + } +} diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 9b928abb..c29fd90b 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -64,7 +64,7 @@ class AltosOrderedRecord extends AltosEepromRecord implements Comparable iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedRecord record = iterator.next(); + switch (record.cmd) { + case Altos.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case Altos.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case Altos.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case Altos.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case Altos.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case Altos.AO_LOG_ACCEL_CAL: + 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); + break; + case Altos.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case Altos.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case Altos.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case Altos.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + } + } + } + /* * Read the whole file, dumping records into a RB tree so * we can enumerate them in time order -- the eeprom data @@ -228,12 +275,11 @@ public class AltosEepromReader { * matching the first packet out of the GPS unit but not * written until the final GPS packet has been received. */ - public AltosEepromReader (FileInputStream in_input) { + public AltosEepromReader (FileInputStream input) { state = new AltosRecord(); state.state = Altos.ao_flight_pad; state.accel_plus_g = 15758; state.accel_minus_g = 16294; - input = in_input; seen = 0; records = new TreeSet(); @@ -249,11 +295,21 @@ public class AltosEepromReader { if (record == null) break; 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; + } records.add(record); } } catch (IOException io) { } catch (ParseException pe) { } record_iterator = records.iterator(); + try { + input.close(); + } catch (IOException ie) { + } } } diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java new file mode 100644 index 00000000..81779e2b --- /dev/null +++ b/ao-tools/altosui/AltosReader.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; + +import altosui.AltosRecord; + +public class AltosReader { + public AltosRecord read() throws IOException, ParseException { return null; } +} diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java index 3440d935..b670ee37 100644 --- a/ao-tools/altosui/AltosRecord.java +++ b/ao-tools/altosui/AltosRecord.java @@ -48,6 +48,8 @@ public class AltosRecord { int accel_minus_g; AltosGPS gps; + double time; /* seconds since boost */ + /* * Values for our MP3H6115A pressure sensor * diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java new file mode 100644 index 00000000..f1f6788c --- /dev/null +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -0,0 +1,71 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import altosui.AltosTelemetry; + +public class AltosTelemetryReader extends AltosReader { + LinkedList records; + + Iterator record_iterator; + + int boost_tick; + + public AltosRecord read() throws IOException, ParseException { + AltosRecord r; + if (!record_iterator.hasNext()) + return null; + + r = record_iterator.next(); + r.time = (r.tick - boost_tick) / 100.0; + return r; + } + + public AltosTelemetryReader (FileInputStream input) { + boolean saw_boost = false; + + records = new LinkedList (); + + try { + for (;;) { + String line = AltosRecord.gets(input); + 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); + } + } catch (IOException io) { + } catch (ParseException pe) { + } + record_iterator = records.iterator(); + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 2cb0c479..7d5ac93a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -391,21 +391,12 @@ public class AltosUI extends JFrame { } } - class TelemetryThread extends DisplayThread { - - String readline() throws InterruptedException { return null; } - - AltosRecord read() throws InterruptedException, ParseException { - return new AltosTelemetry(readline()); - } - } - - class DeviceThread extends TelemetryThread { + class DeviceThread extends DisplayThread { AltosSerial serial; LinkedBlockingQueue telem; - String readline() throws InterruptedException { - return telem.take(); + AltosRecord read() throws InterruptedException, ParseException { + return new AltosTelemetry(telem.take()); } void close() { @@ -453,36 +444,30 @@ public class AltosUI extends JFrame { * Open an existing telemetry file and replay it in realtime */ - class ReplayTelemetryThread extends TelemetryThread { - FileInputStream replay; - - ReplayTelemetryThread(FileInputStream in, String in_name) { - replay = in; - name = in_name; - } + class ReplayThread extends DisplayThread { + AltosReader reader; + String name; - String readline() { + public AltosRecord read() { try { - String line = AltosRecord.gets(replay); - System.out.printf("telemetry line %s\n", line); - return line; - } catch (IOException ee) { + return reader.read(); + } catch (IOException ie) { JOptionPane.showMessageDialog(AltosUI.this, name, "error reading", JOptionPane.ERROR_MESSAGE); + } catch (ParseException pe) { } return null; } - void close () { - try { - replay.close(); - } catch (IOException ee) { - } + public void close () { report(); } + public ReplayThread(AltosReader in_reader, String in_name) { + reader = in_reader; + } void update(AltosState state) throws InterruptedException { /* Make it run in realtime after the rocket leaves the pad */ if (state.state > Altos.ao_flight_pad) @@ -490,40 +475,16 @@ public class AltosUI extends JFrame { } } - class ReplayEepromThread extends DisplayThread { - FileInputStream replay; - - AltosEepromReader reader; - - ReplayEepromThread(FileInputStream in, String in_name) { - replay = in; - name = in_name; - reader = new AltosEepromReader (in); + class ReplayTelemetryThread extends ReplayThread { + ReplayTelemetryThread(FileInputStream in, String in_name) { + super(new AltosTelemetryReader(in), in_name); } - AltosRecord read () throws ParseException { - try { - return reader.read(); - } catch (IOException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - name, - "error reading", - JOptionPane.ERROR_MESSAGE); - } - return null; - } + } - void close () { - try { - replay.close(); - } catch (IOException ee) { - } - report(); - } - void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > Altos.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + class ReplayEepromThread extends ReplayThread { + ReplayEepromThread(FileInputStream in, String in_name) { + super(new AltosEepromReader(in), in_name); } } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 3f55db0b..8c9e9642 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -4,6 +4,7 @@ CLASSPATH=classes:./* CLASSFILES=\ Altos.class \ AltosConvert.class \ + AltosCSV.class \ AltosEepromDownload.class \ AltosEepromMonitor.class \ AltosEepromReader.class \ @@ -21,6 +22,7 @@ CLASSFILES=\ AltosSerial.class \ AltosState.class \ AltosTelemetry.class \ + AltosTelemetryReader.class \ AltosUI.class \ AltosDevice.class \ AltosDeviceDialog.class \ -- cgit v1.2.3 From 294d9c7db21eaf1e71504dbcca5040371abcce55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Aug 2010 22:30:55 -0400 Subject: 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 --- ao-tools/ao-dumplog/ao-dumplog.c | 9 +++++++-- ao-tools/lib/cc-usb.c | 5 +++-- ao-tools/lib/cc-usb.h | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index 440a02b5..57c43290 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -30,12 +30,13 @@ 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 = "channel", .has_arg = 1, .val = 'C' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] [-R]\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [--remote] [--channel ]\n", program); exit(1); } @@ -75,6 +76,7 @@ main (int argc, char **argv) FILE *out; char *filename; int serial_number = 0; + int channel = 0; int flight = 0; char cmd; int tick, a, b; @@ -100,6 +102,9 @@ main (int argc, char **argv) case 'R': remote = 1; break; + case 'C': + channel = atoi(optarg); + break; default: usage(argv[0]); break; @@ -119,7 +124,7 @@ main (int argc, char **argv) if (!cc) exit(1); if (remote) - cc_usb_open_remote(cc); + cc_usb_open_remote(cc, channel); /* send a 'version' command followed by a 'log' command */ cc_usb_printf(cc, "v\n"); out = NULL; diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 53a50741..1580c6d9 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -375,10 +375,11 @@ cc_usb_reset(struct cc_usb *cc) } void -cc_usb_open_remote(struct cc_usb *cc) +cc_usb_open_remote(struct cc_usb *cc, int channel) { if (!cc->remote) { - cc_usb_printf(cc, "\np\nE 0\n"); + printf ("channel %d\n", channel); + cc_usb_printf(cc, "\nc r %d\np\nE 0\n", channel); do { cc->in_count = cc->in_pos = 0; _cc_usb_sync(cc, 100); diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h index 627f1b5d..d3539281 100644 --- a/ao-tools/lib/cc-usb.h +++ b/ao-tools/lib/cc-usb.h @@ -63,7 +63,7 @@ void cc_usb_printf(struct cc_usb *cc, char *format, ...); void -cc_usb_open_remote(struct cc_usb *cc); +cc_usb_open_remote(struct cc_usb *cc, int channel); void cc_usb_close_remote(struct cc_usb *cc); -- cgit v1.2.3 From f63f16a70e4d0535667a6364cafcbff026ee6a8c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 11 Aug 2010 08:36:59 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3b2af868..c8e2417e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit a0a9b445a4d379730b67720f8d7b682d5206a582 +Author: Bdale Garbee +Date: Thu Aug 5 15:16:48 2010 -0400 + + update changelogs for Debian build + commit e075b8623533965b1b77b77d38c2df32f5f77fce Author: Bdale Garbee Date: Thu Aug 5 15:16:24 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 23a4cf8b..b252d601 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+299+ge075b86) unstable; urgency=low +altos (0.6+300+ga0a9b44) unstable; urgency=low * add freetts as a build dep * move to science menu -- cgit v1.2.3 From 4918f73fd0a0f3f5d52907f95a0ec385e901d447 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 11 Aug 2010 08:50:27 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c8e2417e..5dcedb2a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit f63f16a70e4d0535667a6364cafcbff026ee6a8c +Author: Bdale Garbee +Date: Wed Aug 11 08:36:59 2010 -0400 + + update changelogs for Debian build + commit a0a9b445a4d379730b67720f8d7b682d5206a582 Author: Bdale Garbee Date: Thu Aug 5 15:16:48 2010 -0400 diff --git a/debian/changelog b/debian/changelog index b252d601..09e1b6cb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+300+ga0a9b44) unstable; urgency=low +altos (0.6+301+gf63f16a) unstable; urgency=low * add freetts as a build dep * move to science menu -- cgit v1.2.3 From b6da90b4627dde1fe88240c38c51559d8f781dd0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 11 Aug 2010 17:15:39 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 5dcedb2a..e4570404 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 4918f73fd0a0f3f5d52907f95a0ec385e901d447 +Author: Bdale Garbee +Date: Wed Aug 11 08:50:27 2010 -0400 + + update changelogs for Debian build + commit f63f16a70e4d0535667a6364cafcbff026ee6a8c Author: Bdale Garbee Date: Wed Aug 11 08:36:59 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 09e1b6cb..f14342d8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.6+301+gf63f16a) unstable; urgency=low +altos (0.6+302+g4918f73) unstable; urgency=low * add freetts as a build dep * move to science menu -- cgit v1.2.3 From 9d1b27fa147fc8b765d5be165ebef7ee0f85bd37 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 11 Aug 2010 22:11:50 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e4570404..33986884 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit b6da90b4627dde1fe88240c38c51559d8f781dd0 +Author: Bdale Garbee +Date: Wed Aug 11 17:15:39 2010 -0400 + + update changelogs for Debian build + commit 4918f73fd0a0f3f5d52907f95a0ec385e901d447 Author: Bdale Garbee Date: Wed Aug 11 08:50:27 2010 -0400 diff --git a/debian/changelog b/debian/changelog index f14342d8..6a47c8a7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -altos (0.6+302+g4918f73) unstable; urgency=low +altos (0.6+303+gb6da90b) unstable; urgency=low * add freetts as a build dep * move to science menu * working on java packaging details - -- Bdale Garbee Thu, 05 Aug 2010 15:00:37 -0400 + -- Bdale Garbee Wed, 11 Aug 2010 22:11:28 -0400 altos (0.6+292+g8fc261c) unstable; urgency=low -- cgit v1.2.3 From d14c96663a1027164fa30ed89b53f5a9d3fdb82b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Aug 2010 18:19:43 -0700 Subject: 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 --- ao-tools/libaltos/Makefile | 53 ++++- ao-tools/libaltos/cjnitest.c | 21 +- ao-tools/libaltos/libaltos.c | 501 +++++++++++++++++++++++-------------------- ao-tools/libaltos/libaltos.h | 68 ++++-- 4 files changed, 383 insertions(+), 260 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index fa5127eb..a251e54e 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,27 +1,56 @@ OS:=$(shell uname) +# +# Linux +# ifeq ($(OS),Linux) JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) -LIBEXT=so +OS_LDFLAGS= + +LIBNAME=libaltos.so +EXEEXT= endif +# +# Darwin (Mac OS X) +# ifeq ($(OS),Darwin) -DARWIN_CFLAGS=\ +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 -DARWIN_LIBS=\ + +OS_LDFLAGS =\ -framework IOKit -framework CoreFoundation -OS_CFLAGS = $(DARWIN_CFLAGS) -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 -LIBEXT=dylib +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 @@ -48,26 +77,30 @@ CLASSFILES = $(JAVAFILES:%.java=%.class) JAVAFLAGS=-Xlint:unchecked -all: libaltos.$(LIBEXT) cjnitest $(CLASSFILES) +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) +$(CJNITEST): cjnitest.o $(OBJS) cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) -libaltos.$(LIBEXT): $(OBJS) - gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) +$(LIBNAME): $(OBJS) + gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) clean: - rm -f $(CLASSFILES) $(OBJS) libaltos.$(LIBEXT) cjnitest cjnitest.o + rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o rm -rf swig_bindings libaltosJNI $(JNI_FILE): libaltos.i0 $(HEADERS) diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c index cd3898ed..93d1f376 100644 --- a/ao-tools/libaltos/cjnitest.c +++ b/ao-tools/libaltos/cjnitest.c @@ -1,6 +1,15 @@ #include #include "libaltos.h" +static void +altos_puts(struct altos_file *file, char *string) +{ + char c; + + while ((c = *string++)) + altos_putchar(file, c); +} + main () { struct altos_device device; @@ -12,12 +21,20 @@ main () struct altos_file *file; int c; + printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, + device.name, device.serial, device.path); + file = altos_open(&device); - altos_putchar(file, '?'); altos_putchar(file, '\n'); altos_flush(file); + if (!file) { + printf("altos_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); while ((c = altos_getchar(file, 100)) >= 0) { putchar (c); } - printf ("getchar returns %d\n", c); + if (c != LIBALTOS_TIMEOUT) + printf ("getchar returns %d\n", c); altos_close(file); } altos_list_finish(list); diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 00fb2125..3e8485e4 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -15,29 +15,21 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#define BUILD_DLL #include "libaltos.h" #include #include #include -static int -match_dev(char *product, int serial, struct altos_device *device) +PUBLIC int +altos_init(void) { - struct altos_list *list; - int i; + return LIBALTOS_SUCCESS; +} - list = altos_list_start(); - if (!list) - return 0; - while ((i = altos_list_next(list, device)) != 0) { - if (product && strncmp (product, device->product, strlen(product)) != 0) - continue; - if (serial && serial != device->serial) - continue; - break; - } - altos_list_finish(list); - return i; +PUBLIC void +altos_fini(void) +{ } #ifdef DARWIN @@ -60,48 +52,9 @@ altos_strndup (const char *s, size_t n) #define altos_strndup strndup #endif -int -altos_find_by_arg(char *arg, char *default_product, struct altos_device *device) -{ - char *product; - int serial; - char *end; - char *colon; - int ret; - - if (arg) - { - /* check for */ - serial = strtol(arg, &end, 0); - if (end != arg) { - if (*end != '\0') - return 0; - product = NULL; - } else { - /* check for : */ - colon = strchr(arg, ':'); - if (colon) { - product = altos_strndup(arg, colon - arg); - serial = strtol(colon + 1, &end, 0); - if (*end != '\0') - return 0; - } else { - product = arg; - serial = 0; - } - } - } else { - product = NULL; - serial = 0; - } - if (!product && default_product) - ret = match_dev(default_product, serial, device); - if (!ret) - ret = match_dev(product, serial, device); - if (product && product != arg) - free(product); - return ret; -} +/* + * Scan for Altus Metrum devices by looking through /sys + */ #ifdef LINUX @@ -216,7 +169,7 @@ struct altos_usbdev { char *sys; char *tty; char *manufacturer; - char *product; + char *product_name; int serial; /* AltOS always uses simple integer serial numbers */ int idProduct; int idVendor; @@ -286,7 +239,7 @@ usb_scan_device(char *sys) return NULL; usbdev->sys = strdup(sys); usbdev->manufacturer = load_string(sys, "manufacturer"); - usbdev->product = load_string(sys, "product"); + usbdev->product_name = load_string(sys, "product"); usbdev->serial = load_dec(sys, "serial"); usbdev->idProduct = load_hex(sys, "idProduct"); usbdev->idVendor = load_hex(sys, "idVendor"); @@ -299,7 +252,7 @@ usbdev_free(struct altos_usbdev *usbdev) { free(usbdev->sys); free(usbdev->manufacturer); - free(usbdev->product); + free(usbdev->product_name); /* this can get used as a return value */ if (usbdev->tty) free(usbdev->tty); @@ -332,17 +285,6 @@ struct altos_list { int ndev; }; -int -altos_init(void) -{ - return 1; -} - -void -altos_fini(void) -{ -} - struct altos_list * altos_list_start(void) { @@ -366,7 +308,7 @@ altos_list_start(void) dir = cc_fullname(USB_DEVICES, ents[e]->d_name); dev = usb_scan_device(dir); free(dir); - if (dev->idVendor == 0xfffe && dev->tty) { + if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { if (devs->dev) devs->dev = realloc(devs->dev, devs->ndev + 1 * sizeof (struct usbdev *)); @@ -387,7 +329,9 @@ altos_list_next(struct altos_list *list, struct altos_device *device) if (list->current >= list->ndev) return 0; dev = list->dev[list->current]; - strcpy(device->product, dev->product); + strcpy(device->name, dev->product_name); + device->vendor = dev->idVendor; + device->product = dev->idProduct; strcpy(device->path, dev->tty); device->serial = dev->serial; list->current++; @@ -447,17 +391,6 @@ get_string(io_object_t object, CFStringRef entry, char *result, int result_len) return 0; } -int -altos_init(void) -{ - return 1; -} - -void -altos_fini(void) -{ -} - struct altos_list * altos_list_start(void) { @@ -566,15 +499,16 @@ altos_open(struct altos_device *device) void altos_close(struct altos_file *file) { - close(file->fd); - file->fd = -1; + if (file->fd != -1) { + close(file->fd); + file->fd = -1; + } } void altos_free(struct altos_file *file) { - if (file->fd != -1) - close(file->fd); + altos_close(file); free(file); } @@ -613,6 +547,8 @@ altos_flush(struct altos_file *file) } } +#include + int altos_getchar(struct altos_file *file, int timeout) { @@ -622,9 +558,18 @@ altos_getchar(struct altos_file *file, int timeout) altos_flush(file); 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_TIMEOUT; + } ret = read(file->fd, file->in_data, USB_BUF_SIZE); if (ret < 0) - return -errno; + return LIBALTOS_ERROR; file->in_read = 0; file->in_used = ret; } @@ -633,143 +578,255 @@ altos_getchar(struct altos_file *file, int timeout) #endif /* POSIX_TTY */ -#ifdef USE_LIBUSB -#include -#include -#include -#include +#ifdef WINDOWS -libusb_context *usb_context; +#include +#include -int altos_init(void) -{ - int ret; - ret = libusb_init(&usb_context); - if (ret) - return ret; - libusb_set_debug(usb_context, 3); - return 0; -} +struct altos_list { + HDEVINFO dev_info; + int index; +}; -void altos_fini(void) -{ - libusb_exit(usb_context); - usb_context = NULL; -} +#define USB_BUF_SIZE 64 -static libusb_device **list; -static ssize_t num, current; +struct altos_file { + HANDLE handle; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; -int altos_list_start(void) + +PUBLIC struct altos_list * +altos_list_start(void) { - if (list) - altos_list_finish(); - current = 0; - num = libusb_get_device_list(usb_context, &list); - if (num == 0) { - current = num = 0; - list = NULL; - return 0; + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + printf("SetupDiGetClassDevs failed %d\n", GetLastError()); + free(list); + return NULL; } - return 1; + list->index = 0; + return list; } -int altos_list_next(struct altos_device *device) -{ - while (current < num) { - struct libusb_device_descriptor descriptor; - libusb_device *usb_device = list[current++]; - - if (libusb_get_device_descriptor(usb_device, &descriptor) == 0) { - if (descriptor.idVendor == 0xfffe) - { - libusb_device_handle *handle; - if (libusb_open(usb_device, &handle) == 0) { - char serial_number[256]; - libusb_get_string_descriptor_ascii(handle, descriptor.iProduct, - device->product, - sizeof(device->product)); - libusb_get_string_descriptor_ascii(handle, descriptor.iSerialNumber, - serial_number, - sizeof (serial_number)); - libusb_close(handle); - device->serial = atoi(serial_number); - device->device = usb_device; - return 1; - } - } +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + SP_DEVINFO_DATA dev_info_data; + char port[128]; + DWORD port_len; + char location[256]; + char symbolic[256]; + DWORD symbolic_len; + HKEY dev_key; + int vid, pid; + int serial; + HRESULT result; + DWORD location_type; + DWORD location_len; + + dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); + while(SetupDiEnumDeviceInfo(list->dev_info, list->index, + &dev_info_data)) + { + list->index++; + + dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, + DICS_FLAG_GLOBAL, 0, DIREG_DEV, + KEY_READ); + if (dev_key == INVALID_HANDLE_VALUE) { + printf("cannot open device registry key\n"); + continue; } + + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, + symbolic, &symbolic_len); + if (result != 0) { + printf("cannot find SymbolicName value\n"); + RegCloseKey(dev_key); + continue; + } + vid = pid = serial = 0; + sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + 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; + } + + /* Fetch the com port name */ + port_len = sizeof (port); + result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, + port, &port_len); + RegCloseKey(dev_key); + if (result != 0) { + printf("failed to get PortName\n"); + continue; + } + + /* Fetch the 'location information' which is the device name, + * at least on XP */ + location_len = sizeof (location); + if(!SetupDiGetDeviceRegistryProperty(list->dev_info, + &dev_info_data, + SPDRP_LOCATION_INFORMATION, + &location_type, + (BYTE *)location, + sizeof(location), + &location_len)) + { + printf("Failed to get location\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->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(); + if (result != ERROR_NO_MORE_ITEMS) + printf ("SetupDiEnumDeviceInfo failed error %d\n", result); return 0; } -void altos_list_finish(void) +PUBLIC void +altos_list_finish(struct altos_list *list) +{ + SetupDiDestroyDeviceInfoList(list->dev_info); + free(list); +} + +static int +altos_fill(struct altos_file *file, int timeout) { - if (list) { - libusb_free_device_list(list, 1); - list = NULL; + DWORD result; + DWORD got; + COMMTIMEOUTS timeouts; + + if (file->in_read < file->in_used) + return LIBALTOS_SUCCESS; + file->in_read = file->in_used = 0; + + if (timeout) { + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = timeout; + } else { + timeouts.ReadIntervalTimeout = 0; + timeouts.ReadTotalTimeoutMultiplier = 0; + timeouts.ReadTotalTimeoutConstant = 0; + } + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + + if (!SetCommTimeouts(file->handle, &timeouts)) { + printf("SetCommTimeouts failed %d\n", GetLastError()); } + + if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) { + result = GetLastError(); + printf ("read failed %d\n", result); + return LIBALTOS_ERROR; + got = 0; + } + if (got) + return LIBALTOS_SUCCESS; + return LIBALTOS_TIMEOUT; } -#define USB_BUF_SIZE 64 +PUBLIC int +altos_flush(struct altos_file *file) +{ + DWORD put; + char *data = file->out_data; + char used = file->out_used; + DWORD result; -struct altos_file { - struct libusb_device *device; - struct libusb_device_handle *handle; - int out_ep; - int out_size; - int in_ep; - int in_size; - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; -}; + while (used) { + if (!WriteFile(file->handle, data, used, &put, NULL)) { + result = GetLastError(); + printf ("write failed %d\n", result); + return LIBALTOS_ERROR; + } + data += put; + used -= put; + } + file->out_used = 0; + return LIBALTOS_SUCCESS; +} -struct altos_file * +PUBLIC struct altos_file * altos_open(struct altos_device *device) { - struct altos_file *file; - struct libusb_device_handle *handle; - if (libusb_open(device->device, &handle) == 0) { - int ret; + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + char full_name[64]; - ret = libusb_claim_interface(handle, 1); -#if 0 - if (ret) { - libusb_close(handle); - return NULL; - } -#endif - ret = libusb_detach_kernel_driver(handle, 1); -#if 0 - if (ret) { - libusb_close(handle); - return NULL; - } -#endif + if (!file) + return NULL; - file = calloc(sizeof (struct altos_file), 1); - file->device = libusb_ref_device(device->device); - file->handle = handle; - /* XXX should get these from the endpoint descriptors */ - file->out_ep = 4 | LIBUSB_ENDPOINT_OUT; - file->out_size = 64; - file->in_ep = 5 | LIBUSB_ENDPOINT_IN; - file->in_size = 64; + strcpy(full_name, "\\\\.\\"); + strcat(full_name, device->path); + file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + if (file->handle == INVALID_HANDLE_VALUE) { + free(file); + return NULL; + } - return file; + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + timeouts.ReadTotalTimeoutConstant = 100; + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 10000; + if (!SetCommTimeouts(file->handle, &timeouts)) { + printf("SetCommTimeouts failed %d\n", GetLastError()); } - return NULL; + + return file; } -void +PUBLIC void altos_close(struct altos_file *file) { - libusb_close(file->handle); - libusb_unref_device(file->device); - file->handle = NULL; + if (file->handle != INVALID_HANDLE_VALUE) { + CloseHandle(file->handle); + file->handle = INVALID_HANDLE_VALUE; + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); free(file); } @@ -778,60 +835,32 @@ altos_putchar(struct altos_file *file, char c) { int ret; - if (file->out_used == file->out_size) { + 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 == file->out_size) + if (file->out_used == USB_BUF_SIZE) return altos_flush(file); - return 0; -} - -int -altos_flush(struct altos_file *file) -{ - while (file->out_used) { - int transferred; - int ret; - - ret = libusb_bulk_transfer(file->handle, - file->out_ep, - file->out_data, - file->out_used, - &transferred, - 0); - if (ret) - return ret; - if (transferred) { - memmove(file->out_data, file->out_data + transferred, - file->out_used - transferred); - file->out_used -= transferred; - } - } + return LIBALTOS_SUCCESS; } int altos_getchar(struct altos_file *file, int timeout) { + int ret; while (file->in_read == file->in_used) { - int ret; - int transferred; - - altos_flush(file); - ret = libusb_bulk_transfer(file->handle, - file->in_ep, - file->in_data, - file->in_size, - &transferred, - (unsigned int) timeout); + ret = altos_flush(file); + if (ret) + return ret; + if (file->handle == INVALID_HANDLE_VALUE) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); if (ret) return ret; - file->in_read = 0; - file->in_used = transferred; } return file->in_data[file->in_read++]; } -#endif /* USE_LIBUSB */ +#endif diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h index 53026e0a..fe2c483c 100644 --- a/ao-tools/libaltos/libaltos.h +++ b/ao-tools/libaltos/libaltos.h @@ -18,39 +18,83 @@ #ifndef _LIBALTOS_H_ #define _LIBALTOS_H_ +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef BUILD_STATIC +# ifdef BUILD_DLL +# define PUBLIC __declspec(dllexport) +# else +# define PUBLIC __declspec(dllimport) +# endif +# endif /* BUILD_STATIC */ +#endif + +#ifndef PUBLIC +# define PUBLIC +#endif + +#define USB_VENDOR_FSF 0xfffe +#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF +#define USB_PRODUCT_ALTUSMETRUM 0x000a +#define USB_PRODUCT_TELEMETRUM 0x000b +#define USB_PRODUCT_TELEDONGLE 0x000c +#define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 + +#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ + (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ + (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) + struct altos_device { //%immutable; - char product[256]; + int vendor; + int product; int serial; + char name[256]; char path[256]; //%mutable; }; -int altos_init(void); +#define LIBALTOS_SUCCESS 0 +#define LIBALTOS_ERROR -1 +#define LIBALTOS_TIMEOUT -2 + +/* Returns 0 for success, < 0 on error */ +PUBLIC int +altos_init(void); -void altos_fini(void); +PUBLIC void +altos_fini(void); -struct altos_list * +PUBLIC struct altos_list * altos_list_start(void); -int altos_list_next(struct altos_list *list, struct altos_device *device); +/* Returns 1 for success, zero on end of list */ +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device); -void altos_list_finish(struct altos_list *list); +PUBLIC void +altos_list_finish(struct altos_list *list); -struct altos_file * +PUBLIC struct altos_file * altos_open(struct altos_device *device); -void altos_close(struct altos_file *file); +PUBLIC void +altos_close(struct altos_file *file); -void altos_free(struct altos_file *file); +PUBLIC void +altos_free(struct altos_file *file); -int +/* Returns < 0 for error */ +PUBLIC int altos_putchar(struct altos_file *file, char c); -int +/* Returns < 0 for error */ +PUBLIC int altos_flush(struct altos_file *file); -int +/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ +PUBLIC int altos_getchar(struct altos_file *file, int timeout); #endif /* _LIBALTOS_H_ */ -- cgit v1.2.3 From 22800dc094797e1e0ad99124198809d0360f7556 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Aug 2010 18:22:28 -0700 Subject: 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 --- ao-tools/altosui/AltosDevice.java | 72 ++++++++++++++++++++++++++++--- ao-tools/altosui/AltosDeviceDialog.java | 8 ++-- ao-tools/altosui/AltosEepromDownload.java | 7 +-- ao-tools/altosui/AltosUI.java | 2 +- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index f488174c..3daf0742 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -22,16 +22,76 @@ import libaltosJNI.*; public class AltosDevice extends altos_device { + static boolean initialized = false; + static { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + initialized = true; + } catch (UnsatisfiedLinkError e) { + System.err.println("Native library failed to load.\n" + e); + } + } + 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 final static int Any = 0x10000; + public final static int BaseStation = 0x10000 + 1; + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; return String.format("%-20.20s %4d %s", - getProduct(), getSerial(), getPath()); + getName(), getSerial(), getPath()); } - static { - System.loadLibrary("altos"); - libaltos.altos_init(); + public boolean isAltusMetrum() { + if (getVendor() != libaltosConstants.USB_VENDOR_ALTUSMETRUM) + return false; + if (getProduct() < libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN) + return false; + if (getProduct() > libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX) + return false; + return true; } - static AltosDevice[] list(String product) { + + public boolean matchProduct(int want_product) { + + 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) + return true; + + if (have_product != libaltosConstants.USB_PRODUCT_ALTUSMETRUM) + return false; + + String name = getName(); + + 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; + } + + static AltosDevice[] list(int product) { + if (!initialized) + return null; + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); ArrayList device_list = new ArrayList(); @@ -42,7 +102,7 @@ public class AltosDevice extends altos_device { AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; - if (product == null || device.getProduct().startsWith(product)) + if (device.matchProduct(product)) device_list.add(device); } libaltos.altos_list_finish(list); diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index c60bd7c3..3df4c6eb 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -31,16 +31,16 @@ import altosui.AltosDevice; public class AltosDeviceDialog extends JDialog implements ActionListener { private static AltosDeviceDialog dialog; - private static altos_device value = null; + private static AltosDevice value = null; private JList list; - public static altos_device show (Component frameComp, String product) { + public static AltosDevice show (Component frameComp, int product) { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosDevice[] devices; devices = AltosDevice.list(product); - if (devices != null & devices.length > 0) { + if (devices != null && devices.length > 0) { value = null; dialog = new AltosDeviceDialog(frame, frameComp, devices, @@ -153,7 +153,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { //Handle clicks on the Set and Cancel buttons. public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) - AltosDeviceDialog.value = (altos_device)(list.getSelectedValue()); + AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue()); AltosDeviceDialog.dialog.setVisible(false); } diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index f2fcd09e..c2a8d25e 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -84,7 +84,7 @@ public class AltosEepromDownload implements Runnable { } JFrame frame; - altos_device device; + AltosDevice device; AltosSerial serial_line; boolean remote; Thread eeprom_thread; @@ -251,7 +251,7 @@ public class AltosEepromDownload implements Runnable { public AltosEepromDownload(JFrame given_frame) { frame = given_frame; - device = AltosDeviceDialog.show(frame, null); + device = AltosDeviceDialog.show(frame, AltosDevice.Any); serial_line = new AltosSerial(); remote = false; @@ -259,7 +259,8 @@ public class AltosEepromDownload implements Runnable { if (device != null) { try { serial_line.open(device); - if (!device.getProduct().startsWith("TeleMetrum")) + String name = device.getName(); + if (!device.matchProduct(AltosDevice.TeleMetrum)) remote = true; eeprom_thread = new Thread(this); eeprom_thread.start(); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 7d5ac93a..b96e16a6 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -413,7 +413,7 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - altos_device device = AltosDeviceDialog.show(AltosUI.this, "TeleDongle"); + AltosDevice device = AltosDeviceDialog.show(AltosUI.this, AltosDevice.BaseStation); if (device != null) { try { -- cgit v1.2.3 From 09252ec22d58e946494e4ca2cf367bf3bbe1cc50 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Aug 2010 17:09:41 -0700 Subject: 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 --- src/Makefile.proto | 2 +- src/ao-make-product.5c | 15 +++++++++++++++ src/ao_product.c | 2 +- src/teledongle-v0.1/Makefile.defs | 1 + src/teledongle-v0.2/Makefile.defs | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 1 + src/telemetrum-v1.0/Makefile.defs | 1 + src/tidongle/Makefile.defs | 1 + 9 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 106333a6..eedb878a 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,7 +214,7 @@ all: ../$(PROG) nickle $< > $@ ao_product.h: ao-make-product.5c - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c index 933032dd..5f2eb8e8 100644 --- a/src/ao-make-product.5c +++ b/src/ao-make-product.5c @@ -37,11 +37,19 @@ write_int(int a, string description) printf ("#define AO_%s_NUMBER %d\n\n", description, a); } +void +write_hex(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); +} + string manufacturer = "altusmetrum.org"; string product = "TeleMetrum"; string version = "0.0"; int serial = 1; int user_argind = 0; +int id_product = 0x000a; argdesc argd = { .args = { @@ -57,6 +65,12 @@ argdesc argd = { .name = "product", .expr_name = "prod", .desc = "Product name." }, + { + .var = { .arg_int = &id_product }, + .abbr = 'i', + .name = "id_product", + .expr_name = "id_p", + .desc = "Product ID." }, { .var = { .arg_int = &serial }, .abbr = 's', @@ -82,6 +96,7 @@ main() write_ucs2(product, "iProduct"); write_ucs2(sprintf("%06d", serial), "iSerial"); write_int(serial, "iSerial"); + write_hex(id_product, "idProduct"); write_string(version, "iVersion"); } diff --git a/src/ao_product.c b/src/ao_product.c index b42e62c0..2bd0b59c 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -40,7 +40,7 @@ const uint8_t ao_usb_descriptors [] = 0x00, /* bDeviceProtocol */ AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ LE_WORD(0xFFFE), /* idVendor */ - LE_WORD(0x000A), /* idProduct */ + LE_WORD(AO_idProduct_NUMBER), /* idProduct */ LE_WORD(0x0100), /* bcdDevice */ 0x01, /* iManufacturer */ 0x02, /* iProduct */ diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index 06559b28..be7741d8 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleDongle-v0.1 PRODUCT_DEF=-DTELEDONGLE_V_0_1 +IDPRODUCT=0x000c diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index 23694fda..cbec7805 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleDongle-v0.2 PRODUCT_DEF=-DTELEDONGLE_V_0_2 +IDPRODUCT=0x000c diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 7306683e..2ce6e6ed 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v0.1-SiRF PRODUCT_DEF=-DTELEMETRUM_V_0_1 +IDPRODUCT=0x000b diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index df475baa..098ac547 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v0.1 PRODUCT_DEF=-DTELEMETRUM_V_0_1 +IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index e3cc5eb2..624ce6e8 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v1.0 PRODUCT_DEF=-DTELEMETRUM_V_1_0 +IDPRODUCT=0x000b diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index 5b910b9b..fdd51732 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TIDongle PRODUCT_DEF=-DTIDONGLE +IDPRODUCT=0x000a -- cgit v1.2.3 From e1463d8e265dfd42c824d90088cd2a51b4cf8131 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Aug 2010 17:57:31 -0700 Subject: altosui: Make teledongle callsign configurable Teledongle uses the callsign in packet mode; this provides a way to set that. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosPreferences.java | 19 ++++++++++++++++ ao-tools/altosui/AltosSerial.java | 5 +++++ ao-tools/altosui/AltosUI.java | 40 ++++++++++++++++++++++++++-------- 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java index 297e1aae..690f8f1e 100644 --- a/ao-tools/altosui/AltosPreferences.java +++ b/ao-tools/altosui/AltosPreferences.java @@ -37,6 +37,9 @@ class AltosPreferences { /* voice preference name */ final static String voicePreference = "VOICE"; + /* callsign preference name */ + final static String callsignPreference = "CALLSIGN"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -52,6 +55,8 @@ class AltosPreferences { /* Voice preference */ static boolean voice; + static String callsign; + public static void init(Component ui) { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -71,6 +76,8 @@ class AltosPreferences { channel = preferences.getInt(channelPreference, 0); voice = preferences.getBoolean(voicePreference, true); + + callsign = preferences.get(callsignPreference,"N0CALL"); } static void flush_preferences() { @@ -154,4 +161,16 @@ class AltosPreferences { public static boolean voice() { return voice; } + + public static void set_callsign(String new_callsign) { + callsign = new_callsign; + synchronized(preferences) { + preferences.put(callsignPreference, callsign); + flush_preferences(); + } + } + + public static String callsign() { + return callsign; + } } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index efa63f68..ba00b55e 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -154,6 +154,11 @@ public class AltosSerial implements Runnable { printf("m 0\nc r %d\nm 1\n", channel); } + public void set_callsign(String callsign) { + if (altos != null) + printf ("c c %s\n", callsign); + } + public AltosSerial() { altos = null; input_thread = null; diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index b96e16a6..33ce274a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -420,6 +420,7 @@ public class AltosUI extends JFrame { serial_line.open(device); DeviceThread thread = new DeviceThread(serial_line); serial_line.set_channel(AltosPreferences.channel()); + serial_line.set_callsign(AltosPreferences.callsign()); run_display(thread); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, @@ -440,6 +441,18 @@ public class AltosUI extends JFrame { stop_display(); } + void ConfigureCallsign() { + String result; + result = JOptionPane.showInputDialog(AltosUI.this, + "Configure Callsign", + AltosPreferences.callsign()); + if (result != null) { + AltosPreferences.set_callsign(result); + if (serial_line != null) + serial_line.set_callsign(result); + } + } + /* * Open an existing telemetry file and replay it in realtime */ @@ -556,6 +569,22 @@ public class AltosUI extends JFrame { menu.setMnemonic(KeyEvent.VK_F); menubar.add(menu); + item = new JMenuItem("Replay File",KeyEvent.VK_R); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Replay(); + } + }); + menu.add(item); + + item = new JMenuItem("Save Flight Data",KeyEvent.VK_S); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SaveFlightData(); + } + }); + menu.add(item); + item = new JMenuItem("Quit",KeyEvent.VK_Q); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)); @@ -591,20 +620,13 @@ public class AltosUI extends JFrame { menu.addSeparator(); - item = new JMenuItem("Save Flight Data",KeyEvent.VK_S); + item = new JMenuItem("Set Callsign",KeyEvent.VK_S); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - SaveFlightData(); + ConfigureCallsign(); } }); - menu.add(item); - item = new JMenuItem("Replay",KeyEvent.VK_R); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Replay(); - } - }); menu.add(item); } // Log menu -- cgit v1.2.3 From 953bc3438b10b21f3d65d292356c4ab2de23cddd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Aug 2010 23:05:20 -0700 Subject: 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 --- ao-tools/altosui/AltosChannelMenu.java | 70 ++++++ ao-tools/altosui/AltosConfig.java | 264 ++++++++++++++++++++ ao-tools/altosui/AltosConfigUI.java | 423 +++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 33 +-- ao-tools/altosui/Makefile | 5 +- 5 files changed, 779 insertions(+), 16 deletions(-) create mode 100644 ao-tools/altosui/AltosChannelMenu.java create mode 100644 ao-tools/altosui/AltosConfig.java create mode 100644 ao-tools/altosui/AltosConfigUI.java diff --git a/ao-tools/altosui/AltosChannelMenu.java b/ao-tools/altosui/AltosChannelMenu.java new file mode 100644 index 00000000..504c13c6 --- /dev/null +++ b/ao-tools/altosui/AltosChannelMenu.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosChannelMenu extends JMenu implements ActionListener { + ButtonGroup group; + int channel; + LinkedList listeners; + + public void addActionListener(ActionListener l) { + listeners.add(l); + } + + public void actionPerformed(ActionEvent e) { + channel = Integer.parseInt(e.getActionCommand()); + + ListIterator i = listeners.listIterator(); + + ActionEvent newe = new ActionEvent(this, channel, e.getActionCommand()); + while (i.hasNext()) { + ActionListener listener = i.next(); + listener.actionPerformed(newe); + } + } + + public AltosChannelMenu(int current_channel) { + super("Channel", true); + group = new ButtonGroup(); + + channel = current_channel; + + listeners = new LinkedList(); + for (int c = 0; c <= 9; c++) { + JRadioButtonMenuItem radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c, + 434.550 + c * 0.1), + c == channel); + radioitem.setActionCommand(String.format("%d", c)); + radioitem.addActionListener(this); + add(radioitem); + group.add(radioitem); + } + } + +} diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java new file mode 100644 index 00000000..ac73e7c5 --- /dev/null +++ b/ao-tools/altosui/AltosConfig.java @@ -0,0 +1,264 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Altos; +import altosui.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosRecord; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosFlightStatusTableModel; +import altosui.AltosFlightInfoTableModel; +import altosui.AltosConfigUI; + +import libaltosJNI.*; + +public class AltosConfig implements Runnable, ActionListener { + + class int_ref { + int value; + + public int get() { + return value; + } + public void set(int i) { + value = i; + } + public int_ref(int i) { + value = i; + } + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref(String i) { + value = i; + } + } + + JFrame owner; + AltosDevice device; + AltosSerial serial_line; + boolean remote; + Thread config_thread; + int_ref serial; + int_ref main_deploy; + int_ref apogee_delay; + int_ref radio_channel; + string_ref version; + string_ref product; + string_ref callsign; + AltosConfigUI config_ui; + + + boolean get_int(String line, String label, int_ref x) { + if (line.startsWith(label)) { + try { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) { + int i = Integer.parseInt(tokens[0]); + x.set(i); + return true; + } + } catch (NumberFormatException ne) { + } + } + return false; + } + + boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + 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"); + } + } + + void stop_serial() throws InterruptedException { + if (remote) { + serial_line.printf("~\n"); + serial_line.flush(); + } + } + + void get_data() throws InterruptedException { + try { + start_serial(); + serial_line.printf("c s\nv\n"); + for (;;) { + String line = serial_line.get_reply(); + get_int(line, "serial-number", serial); + get_int(line, "Main deploy:", main_deploy); + get_int(line, "Apogee delay:", apogee_delay); + get_int(line, "Radio channel:", radio_channel); + get_string(line, "Callsign:", callsign); + get_string(line,"software-version", version); + get_string(line,"product", product); + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + } finally { + stop_serial(); + } + } + + void init_ui () { + config_ui = new AltosConfigUI(owner); + config_ui.addActionListener(this); + set_ui(); + } + + void set_ui() { + try { + if (serial_line != null) + get_data(); + config_ui.set_serial(serial.get()); + config_ui.set_product(product.get()); + config_ui.set_version(version.get()); + config_ui.set_main_deploy(main_deploy.get()); + config_ui.set_apogee_delay(apogee_delay.get()); + config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_callsign(callsign.get()); + config_ui.set_clean(); + } catch (InterruptedException ie) { + } + } + + void run_dialog() { + } + + void save_data() { + main_deploy.set(config_ui.main_deploy()); + apogee_delay.set(config_ui.apogee_delay()); + radio_channel.set(config_ui.radio_channel()); + callsign.set(config_ui.callsign()); + try { + start_serial(); + serial_line.printf("c m %d\n", main_deploy.get()); + serial_line.printf("c d %d\n", apogee_delay.get()); + serial_line.printf("c r %d\n", radio_channel.get()); + serial_line.printf("c c %s\n", callsign.get()); + serial_line.printf("c w\n"); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd.equals("save")) { + save_data(); + set_ui(); + } else if (cmd.equals("reset")) { + set_ui(); + } else if (cmd.equals("close")) { + if (serial_line != null) + serial_line.close(); + } + } + + public void run () { + try { + init_ui(); + config_ui.make_visible(); +// } catch (InterruptedException ie) { + } finally { + } + } + + public AltosConfig(JFrame given_owner) { + owner = given_owner; + + serial = new int_ref(0); + main_deploy = new int_ref(250); + apogee_delay = new int_ref(0); + radio_channel = new int_ref(0); + callsign = new string_ref("N0CALL"); + version = new string_ref("unknown"); + product = new string_ref("unknown"); + + device = AltosDeviceDialog.show(owner, AltosDevice.Any); + serial_line = new AltosSerial(); + if (device != null) { + try { + serial_line.open(device); + if (!device.matchProduct(AltosDevice.TeleMetrum)) + remote = true; + config_thread = new Thread(this); + config_thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.getPath(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java new file mode 100644 index 00000000..1d8c579a --- /dev/null +++ b/ao-tools/altosui/AltosConfigUI.java @@ -0,0 +1,423 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.LinkedBlockingQueue; + +import altosui.Altos; +import altosui.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosRecord; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosFlightStatusTableModel; +import altosui.AltosFlightInfoTableModel; + +import libaltosJNI.*; + +public class AltosConfigUI extends JDialog implements ActionListener, ItemListener, DocumentListener { + + Container pane; + Box box; + JLabel product_label; + JLabel version_label; + JLabel serial_label; + JLabel main_deploy_label; + JLabel apogee_delay_label; + JLabel radio_channel_label; + JLabel callsign_label; + + public boolean dirty; + + JFrame owner; + JLabel product_value; + JLabel version_value; + JLabel serial_value; + JComboBox main_deploy_value; + JComboBox apogee_delay_value; + JComboBox radio_channel_value; + JTextField callsign_value; + + JButton save; + JButton reset; + JButton close; + + ActionListener listener; + + static String[] main_deploy_values = { + "100", "150", "200", "250", "300", "350", + "400", "450", "500" + }; + + static String[] apogee_delay_values = { + "0", "1", "2", "3", "4", "5" + }; + + static String[] radio_channel_values = new String[10]; + { + for (int i = 0; i <= 9; i++) + radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)", + i, 434.550 + i * 0.1); + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosConfigUI ui; + + public ConfigListener(AltosConfigUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + /* Build the UI using a grid bag */ + public AltosConfigUI(JFrame in_owner) { + super (in_owner, "Configure TeleMetrum", false); + + 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()); + + /* Product */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + product_label = new JLabel("Product:"); + pane.add(product_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; + product_value = new JLabel(""); + pane.add(product_value, c); + + /* Version */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 1; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + version_label = new JLabel("Software version:"); + pane.add(version_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; + version_value = new JLabel(""); + pane.add(version_value, c); + + /* Serial */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 2; + 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 = 2; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + /* Main deploy */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 3; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 3; + main_deploy_label = new JLabel("Main Deploy Altitude(m):"); + pane.add(main_deploy_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 3; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + main_deploy_value = new JComboBox(main_deploy_values); + main_deploy_value.setEditable(true); + main_deploy_value.addItemListener(this); + pane.add(main_deploy_value, c); + + /* Apogee delay */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 4; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + apogee_delay_label = new JLabel("Apogee Delay(s):"); + pane.add(apogee_delay_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 4; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + apogee_delay_value = new JComboBox(apogee_delay_values); + apogee_delay_value.setEditable(true); + apogee_delay_value.addItemListener(this); + pane.add(apogee_delay_value, c); + + /* Radio channel */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 5; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_channel_label = new JLabel("Radio Channel:"); + pane.add(radio_channel_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 5; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_channel_value = new JComboBox(radio_channel_values); + radio_channel_value.setEditable(false); + radio_channel_value.addItemListener(this); + pane.add(radio_channel_value, c); + + /* Callsign */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 6; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + callsign_label = new JLabel("Callsign:"); + pane.add(callsign_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 6; + c.gridwidth = 3; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + callsign_value = new JTextField("N0CALL"); + callsign_value.getDocument().addDocumentListener(this); + pane.add(callsign_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 7; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + save = new JButton("Save"); + pane.add(save, c); + save.addActionListener(this); + save.setActionCommand("save"); + + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = 7; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + reset = new JButton("Reset"); + pane.add(reset, c); + reset.addActionListener(this); + reset.setActionCommand("reset"); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 7; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_END; + c.insets = il; + close = new JButton("Close"); + pane.add(close, c); + close.addActionListener(this); + close.setActionCommand("close"); + + addWindowListener(new ConfigListener(this)); + } + + /* Once the initial values are set, the config code will show the dialog */ + public void make_visible() { + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } + + /* If any values have been changed, confirm before closing */ + public boolean check_dirty() { + if (dirty) { + Object[] options = { "Close anyway", "Keep editing" }; + int i; + i = JOptionPane.showOptionDialog(this, + "Configuration modified, close anyway?", + "Configuration Modified", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, options, options[1]); + if (i != 0) + return false; + } + return true; + } + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) + if (!check_dirty()) + return; + listener.actionPerformed(e); + if (cmd.equals("close")) { + setVisible(false); + dispose(); + } + dirty = false; + } + + /* ItemListener interface method */ + public void itemStateChanged(ItemEvent e) { + dirty = true; + } + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + dirty = true; + } + + public void insertUpdate(DocumentEvent e) { + dirty = true; + } + + public void removeUpdate(DocumentEvent e) { + dirty = true; + } + + /* Let the config code hook on a listener */ + public void addActionListener(ActionListener l) { + listener = l; + } + + /* set and get all of the dialog values */ + public void set_product(String product) { + product_value.setText(product); + } + + public void set_version(String version) { + version_value.setText(version); + } + + public void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + public void set_main_deploy(int new_main_deploy) { + main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy)); + } + + public int main_deploy() { + return Integer.parseInt(main_deploy_value.getSelectedItem().toString()); + } + + public void set_apogee_delay(int new_apogee_delay) { + apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); + } + + public int apogee_delay() { + return Integer.parseInt(apogee_delay_value.getSelectedItem().toString()); + } + + public void set_radio_channel(int new_radio_channel) { + radio_channel_value.setSelectedIndex(new_radio_channel); + } + + public int radio_channel() { + return radio_channel_value.getSelectedIndex(); + } + + public void set_callsign(String new_callsign) { + callsign_value.setText(new_callsign); + } + + public String callsign() { + return callsign_value.getText(); + } + + public void set_clean() { + dirty = false; + } + + } \ No newline at end of file diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 33ce274a..49d1f11a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -40,6 +40,7 @@ import altosui.AltosLog; import altosui.AltosVoice; import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; +import altosui.AltosChannelMenu; import libaltosJNI.*; @@ -453,6 +454,9 @@ public class AltosUI extends JFrame { } } + void ConfigureTeleMetrum() { + new AltosConfig(AltosUI.this); + } /* * Open an existing telemetry file and replay it in realtime */ @@ -628,6 +632,15 @@ public class AltosUI extends JFrame { }); menu.add(item); + + item = new JMenuItem("Configure TeleMetrum device",KeyEvent.VK_T); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConfigureTeleMetrum(); + } + }); + + menu.add(item); } // Log menu { @@ -680,26 +693,16 @@ public class AltosUI extends JFrame { // Channel menu { - menu = new JMenu("Channel", true); - menu.setMnemonic(KeyEvent.VK_C); - menubar.add(menu); - ButtonGroup group = new ButtonGroup(); - - for (int c = 0; c <= 9; c++) { - radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c, - 434.550 + c * 0.1), - c == AltosPreferences.channel()); - radioitem.setActionCommand(String.format("%d", c)); - radioitem.addActionListener(new ActionListener() { + menu = new AltosChannelMenu(AltosPreferences.channel()); + menu.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int new_channel = Integer.parseInt(e.getActionCommand()); AltosPreferences.set_channel(new_channel); serial_line.set_channel(new_channel); } - }); - menu.add(radioitem); - group.add(radioitem); - } + }); + menu.setMnemonic(KeyEvent.VK_C); + menubar.add(menu); } this.setJMenuBar(menubar); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 8c9e9642..541b89e3 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -3,6 +3,9 @@ CLASSPATH=classes:./* CLASSFILES=\ Altos.class \ + AltosChannelMenu.class \ + AltosConfig.class \ + AltosConfigUI.class \ AltosConvert.class \ AltosCSV.class \ AltosEepromDownload.class \ @@ -39,7 +42,7 @@ FREETTSJAR= \ en_us.jar \ freetts.jar -JAVAFLAGS=-Xlint:unchecked +JAVAFLAGS=-Xlint:unchecked -Xlint:deprecation OS:=$(shell uname) -- cgit v1.2.3 From 0e17853c08f77debef3e8cf82e9cdb6a5079fc9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Aug 2010 23:06:15 -0700 Subject: 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 --- ao-tools/altosui/AltosEepromDownload.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index c2a8d25e..02a71118 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -225,6 +225,7 @@ public class AltosEepromDownload implements Runnable { 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"); } @@ -259,7 +260,6 @@ public class AltosEepromDownload implements Runnable { if (device != null) { try { serial_line.open(device); - String name = device.getName(); if (!device.matchProduct(AltosDevice.TeleMetrum)) remote = true; eeprom_thread = new Thread(this); -- cgit v1.2.3 From 44b26dd550eef789e70082ccaa46d7d430c67bce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:15:04 -0400 Subject: add freetts as a build dep --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index ba9354b8..cc8fda94 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 2007288da8a83e3aa925e11cc196f1c65aab2e5c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 5 Aug 2010 15:00:15 -0400 Subject: working on java packaging details --- ao-tools/altosui/Makefile | 33 +++++++++++++++++---------------- debian/altos.desktop | 2 +- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 541b89e3..63359fbb 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -1,6 +1,6 @@ .SUFFIXES: .java .class -CLASSPATH=classes:./* +CLASSPATH=classes:./*:/usr/share/java/* CLASSFILES=\ Altos.class \ AltosChannelMenu.class \ @@ -31,16 +31,17 @@ CLASSFILES=\ AltosDeviceDialog.class \ AltosVoice.class -FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2 -FREETTSLIB=$(FREETTSSRC)/lib -FREETTSJAR= \ - cmudict04.jar \ - cmulex.jar \ - cmu_time_awb.jar \ - cmutimelex.jar \ - cmu_us_kal.jar \ - en_us.jar \ - freetts.jar +#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 @@ -66,14 +67,14 @@ altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Man classes/altosui: mkdir -p classes - ln -s .. classes/altosui + ln -sf .. classes/altosui classes/libaltosJNI: mkdir -p classes - ln -s ../../libaltos/libaltosJNI classes/libaltosJNI + ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI -$(FREETTSJAR): - ln -s $(FREETTSLIB)/$@ . +#$(FREETTSJAR): +# ln -s $(FREETTSLIB)/$@ . ifeq ($(OS),Darwin) RESOURCES=altosui.jar $(FREETTSJAR) ../libaltos/libaltos.dylib @@ -92,6 +93,6 @@ altosui: endif clean: - rm -f *.class $(FREETTSJAR) altosui.jar + rm -f *.class altosui.jar rm -f AltosUI.app/Contents/Resources/Java/* rm -rf classes diff --git a/debian/altos.desktop b/debian/altos.desktop index ae9bdc63..4281ad3a 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -7,4 +7,4 @@ Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/ao-view %f Terminal=false MimeType=text/plain; -Categories=Viewer;Network; +Categories=Education;Science; -- cgit v1.2.3 From 7f8d7978606abe544b1b9b6065c5480ed813b8ec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 11:53:19 -0700 Subject: altosui: Add .ihx file reading code and stub out flashing UI Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlash.java | 78 ++++++++++++ ao-tools/altosui/AltosHexfile.java | 248 +++++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 14 +++ ao-tools/altosui/Makefile | 2 + 4 files changed, 342 insertions(+) create mode 100644 ao-tools/altosui/AltosFlash.java create mode 100644 ao-tools/altosui/AltosHexfile.java diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java new file mode 100644 index 00000000..ac9e81df --- /dev/null +++ b/ao-tools/altosui/AltosFlash.java @@ -0,0 +1,78 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 implements Runnable { + File file; + FileInputStream input; + Thread thread; + AltosHexfile image; + JFrame frame; + + public void run() { + try { + image = new AltosHexfile(input); + System.out.printf("read file start %d length %d\n", + image.address, image.data.length); + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, + file, + e.getMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + + public AltosFlash(JFrame in_frame) { + frame = in_frame; + + 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) { + file = hexfile_chooser.getSelectedFile(); + if (file != null) { + try { + input = new FileInputStream(file); + thread = new Thread(this); + thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + file, + "Cannot open flash file", + JOptionPane.ERROR_MESSAGE); + } + } + } + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java new file mode 100644 index 00000000..c7078877 --- /dev/null +++ b/ao-tools/altosui/AltosHexfile.java @@ -0,0 +1,248 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 AltosHexfile(FileInputStream file) throws IOException { + HexFileInputStream input = new HexFileInputStream(file); + LinkedList record_list = new LinkedList(); + 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 diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 49d1f11a..565866ea 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -41,6 +41,7 @@ import altosui.AltosVoice; import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; +import altosui.AltosFlash; import libaltosJNI.*; @@ -457,6 +458,11 @@ public class AltosUI extends JFrame { void ConfigureTeleMetrum() { new AltosConfig(AltosUI.this); } + + void FlashImage() { + new AltosFlash(AltosUI.this); + } + /* * Open an existing telemetry file and replay it in realtime */ @@ -589,6 +595,14 @@ public class AltosUI extends JFrame { }); 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("Quit",KeyEvent.VK_Q); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 541b89e3..ebe59644 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -13,10 +13,12 @@ CLASSFILES=\ AltosEepromReader.class \ AltosEepromRecord.class \ AltosFile.class \ + AltosFlash.class \ AltosFlightInfoTableModel.class \ AltosFlightStatusTableModel.class \ AltosGPS.class \ AltosGreatCircle.class \ + AltosHexfile.class \ AltosLog.class \ AltosParse.class \ AltosPreferences.class \ -- cgit v1.2.3 From ebeb13688a9a5442c838641ede6ba0dc92c9a1a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 14:32:58 -0700 Subject: 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 --- ao-tools/altosui/AltosConfigUI.java | 5 +- ao-tools/altosui/AltosDebug.java | 231 +++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosFlash.java | 60 ++++----- ao-tools/altosui/AltosFlashUI.java | 92 +++++++++++++ ao-tools/altosui/AltosHexfile.java | 6 + ao-tools/altosui/AltosRomconfig.java | 110 ++++++++++++++++ ao-tools/altosui/AltosRomconfigUI.java | 160 +++++++++++++++++++++++ ao-tools/altosui/AltosSerial.java | 4 + ao-tools/altosui/AltosUI.java | 4 +- ao-tools/altosui/Makefile | 4 + 10 files changed, 640 insertions(+), 36 deletions(-) create mode 100644 ao-tools/altosui/AltosDebug.java create mode 100644 ao-tools/altosui/AltosFlashUI.java create mode 100644 ao-tools/altosui/AltosRomconfig.java create mode 100644 ao-tools/altosui/AltosRomconfigUI.java diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index 1d8c579a..6825b9a9 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -44,7 +44,10 @@ import altosui.AltosFlightInfoTableModel; import libaltosJNI.*; -public class AltosConfigUI extends JDialog implements ActionListener, ItemListener, DocumentListener { +public class AltosConfigUI + extends JDialog + implements ActionListener, ItemListener, DocumentListener +{ Container pane; Box box; diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java new file mode 100644 index 00000000..7bd3a5cd --- /dev/null +++ b/ao-tools/altosui/AltosDebug.java @@ -0,0 +1,231 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 { + + static final byte WR_CONFIG = 0x1d; + static final byte RD_CONFIG = 0x24; + static final byte CONFIG_TIMERS_OFF = (1 << 3); + static final byte CONFIG_DMA_PAUSE = (1 << 2); + static final byte CONFIG_TIMER_SUSPEND = (1 << 1); + static final byte SET_FLASH_INFO_PAGE = (1 << 0); + + static final byte GET_PC = 0x28; + static final byte READ_STATUS = 0x34; + static final byte STATUS_CHIP_ERASE_DONE = (byte) (1 << 7); + static final byte STATUS_PCON_IDLE = (1 << 6); + static final byte STATUS_CPU_HALTED = (1 << 5); + static final byte STATUS_POWER_MODE_0 = (1 << 4); + static final byte STATUS_HALT_STATUS = (1 << 3); + static final byte STATUS_DEBUG_LOCKED = (1 << 2); + static final byte STATUS_OSCILLATOR_STABLE = (1 << 1); + static final byte STATUS_STACK_OVERFLOW = (1 << 0); + + static final byte SET_HW_BRKPNT = 0x3b; + static byte HW_BRKPNT_N(byte n) { return (byte) ((n) << 3); } + static final byte HW_BRKPNT_N_MASK = (0x3 << 3); + static final byte HW_BRKPNT_ENABLE = (1 << 2); + + static final byte HALT = 0x44; + static final byte RESUME = 0x4c; + static byte DEBUG_INSTR(byte n) { return (byte) (0x54|(n)); } + static final byte STEP_INSTR = 0x5c; + static byte STEP_REPLACE(byte n) { return (byte) (0x64|(n)); } + static final byte GET_CHIP_ID = 0x68; + + + 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 boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + 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; + } + + boolean debug_mode; + + void ensure_debug_mode() { + if (!debug_mode) { + printf("D\n"); + debug_mode = true; + } + } + + /* + * Write target memory + */ + public void write_memory(int address, byte[] bytes) { + ensure_debug_mode(); + printf("O %x %x\n", bytes.length, address); + for (int i = 0; i < bytes.length; i++) + printf("%02x", bytes[i]); + } + + /* + * Read target memory + */ + public byte[] read_memory(int address, int length) + throws IOException, InterruptedException { + byte[] data = new byte[length]; + + flush_reply(); + ensure_debug_mode(); + printf("I %x %x\n", length, address); + int i = 0; + while (i < length) { + String line = get_reply().trim(); + if (!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[j] = (byte) ((fromhex(line.charAt(j*2)) << 4) + + fromhex(line.charAt(j*2+1))); + i += this_time; + } + + 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_reply(); + 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 (!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_status() throws IOException, InterruptedException { + write_byte(READ_STATUS); + return read_bytes(2)[0]; + } + + public boolean check_connection() throws IOException, InterruptedException { + byte reply = read_status(); + System.out.printf("status %x\n", reply); + 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 diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index ac9e81df..bab60c1f 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -30,49 +30,43 @@ import java.util.concurrent.LinkedBlockingQueue; import altosui.AltosHexfile; -public class AltosFlash implements Runnable { +public class AltosFlash { File file; FileInputStream input; Thread thread; AltosHexfile image; JFrame frame; + AltosDevice debug_dongle; + AltosDebug debug; + AltosRomconfig rom_config; - public void run() { - try { - image = new AltosHexfile(input); - System.out.printf("read file start %d length %d\n", - image.address, image.data.length); - } catch (IOException e) { - JOptionPane.showMessageDialog(frame, - file, - e.getMessage(), - JOptionPane.ERROR_MESSAGE); - } + public void flash() throws IOException, FileNotFoundException, InterruptedException { + if (!check_rom_config()) + throw new IOException("Invalid rom config settings"); + rom_config.write(image); } - public AltosFlash(JFrame in_frame) { - frame = in_frame; + public boolean check_rom_config() { + if (rom_config == null) + rom_config = debug.romconfig(); + return rom_config != null && rom_config.valid(); + } - JFileChooser hexfile_chooser = new JFileChooser(); + public void set_romconfig (AltosRomconfig romconfig) { + rom_config = romconfig; + } - hexfile_chooser.setDialogTitle("Select Flash Image"); - hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx")); - int returnVal = hexfile_chooser.showOpenDialog(frame); + 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"); + } - if (returnVal == JFileChooser.APPROVE_OPTION) { - file = hexfile_chooser.getSelectedFile(); - if (file != null) { - try { - input = new FileInputStream(file); - thread = new Thread(this); - thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - file, - "Cannot open flash file", - JOptionPane.ERROR_MESSAGE); - } - } - } + 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 diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java new file mode 100644 index 00000000..5cae4756 --- /dev/null +++ b/ao-tools/altosui/AltosFlashUI.java @@ -0,0 +1,92 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 implements Runnable { + File file; + Thread thread; + JFrame frame; + AltosDevice debug_dongle; + AltosFlash flash; + + public void run() { + flash = new AltosFlash(file, debug_dongle); + try { + flash.open(); + if (!flash.check_rom_config()) { + AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); + romconfig_ui.showDialog(); + AltosRomconfig romconfig = romconfig_ui.romconfig(); + if (romconfig == null) + return; + flash.set_romconfig(romconfig); + } + flash.flash(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + "Cannot open image", + file.toString(), + JOptionPane.ERROR_MESSAGE); + return; + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, + e.getMessage(), + file.toString(), + JOptionPane.ERROR_MESSAGE); + return; + } catch (InterruptedException ie) { + } + } + + public AltosFlashUI(JFrame in_frame) { + frame = in_frame; + + 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 diff --git a/ao-tools/altosui/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java index c7078877..360e24ad 100644 --- a/ao-tools/altosui/AltosHexfile.java +++ b/ao-tools/altosui/AltosHexfile.java @@ -214,6 +214,10 @@ 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 record_list = new LinkedList(); @@ -244,5 +248,7 @@ public class AltosHexfile { data[records[i].address - base + j] = records[i].data[j]; } } + for (int i = 0xa0; i < 0xaa; i++) + System.out.printf ("%04x: %02x\n", i, get_byte(i)); } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java new file mode 100644 index 00000000..5a2df313 --- /dev/null +++ b/ao-tools/altosui/AltosRomconfig.java @@ -0,0 +1,110 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + } + } + + 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 1: + serial_number = get_int(bytes, offset + 4, 2); + radio_calibration = get_int(bytes, offset + 6, 4); + valid = true; + break; + } + } + System.out.printf("version 0x%x check 0x%x valid %s serial %d cal %d\n", + version, check, valid ? "true" : "false", + serial_number, radio_calibration); + } + + 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 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); + new AltosRomconfig(hexfile); + } + + 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; + } +} diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java new file mode 100644 index 00000000..21c34ef4 --- /dev/null +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -0,0 +1,160 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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")) + selected = true; + setVisible(false); + } + + int serial() { + return Integer.parseInt(serial_value.getText()); + } + + int radio_calibration() { + return Integer.parseInt(radio_calibration_value.getText()); + } + + public AltosRomconfig romconfig() { + return new AltosRomconfig(serial(), radio_calibration()); + } + + public AltosRomconfig showDialog() { + setVisible(true); + if (selected) + return romconfig(); + return null; + } +} diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index ba00b55e..a62f1225 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -79,6 +79,10 @@ public class AltosSerial implements Runnable { } } + public void flush_reply() { + reply_queue.clear(); + } + public String get_reply() throws InterruptedException { return reply_queue.take(); } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 565866ea..9fd47ea7 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -41,7 +41,7 @@ import altosui.AltosVoice; import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; -import altosui.AltosFlash; +import altosui.AltosFlashUI; import libaltosJNI.*; @@ -460,7 +460,7 @@ public class AltosUI extends JFrame { } void FlashImage() { - new AltosFlash(AltosUI.this); + new AltosFlashUI(AltosUI.this); } /* diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index ebe59644..affbac39 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -8,12 +8,14 @@ CLASSFILES=\ AltosConfigUI.class \ AltosConvert.class \ AltosCSV.class \ + AltosDebug.class \ AltosEepromDownload.class \ AltosEepromMonitor.class \ AltosEepromReader.class \ AltosEepromRecord.class \ AltosFile.class \ AltosFlash.class \ + AltosFlashUI.class \ AltosFlightInfoTableModel.class \ AltosFlightStatusTableModel.class \ AltosGPS.class \ @@ -31,6 +33,8 @@ CLASSFILES=\ AltosUI.class \ AltosDevice.class \ AltosDeviceDialog.class \ + AltosRomconfig.class \ + AltosRomconfigUI.class \ AltosVoice.class FREETTSSRC=/home/keithp/src/freetts/freetts-1.2.2 -- cgit v1.2.3 From b8519b8669ff54741dd738ac343fbd2424451247 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 21:53:37 -0700 Subject: ao-dumplog: Fix --remote and --channel options to actually work --- ao-tools/ao-dumplog/ao-dumplog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-dumplog/ao-dumplog.c b/ao-tools/ao-dumplog/ao-dumplog.c index 57c43290..6d4fa5bf 100644 --- a/ao-tools/ao-dumplog/ao-dumplog.c +++ b/ao-tools/ao-dumplog/ao-dumplog.c @@ -29,7 +29,7 @@ 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}, }; @@ -91,7 +91,7 @@ main (int argc, char **argv) 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; -- cgit v1.2.3 From 86f7b9314b042f2e512fdf35067817e68532867b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 21:54:47 -0700 Subject: altosui: pad TM config dialog values to avoid clipping descenders --- ao-tools/altosui/AltosConfigUI.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index 6825b9a9..605ccc8b 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -147,6 +147,7 @@ public class AltosConfigUI 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); @@ -157,6 +158,7 @@ public class AltosConfigUI c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; c.insets = ir; + c.ipady = 5; version_value = new JLabel(""); pane.add(version_value, c); @@ -167,6 +169,7 @@ public class AltosConfigUI 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); @@ -177,6 +180,7 @@ public class AltosConfigUI c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; c.insets = ir; + c.ipady = 5; serial_value = new JLabel(""); pane.add(serial_value, c); @@ -187,7 +191,7 @@ public class AltosConfigUI 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); @@ -278,7 +282,7 @@ public class AltosConfigUI /* 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; @@ -288,8 +292,8 @@ public class AltosConfigUI 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; @@ -299,8 +303,8 @@ public class AltosConfigUI 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; -- cgit v1.2.3 From f9e80f39bc39e5882bfe75f959b6501cb3277cd2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 21:55:49 -0700 Subject: libaltos: use pipe to wake up getchar on close. use mutexes --- ao-tools/libaltos/libaltos.c | 121 +++++++++++++++++++++++++++++-------------- 1 file changed, 83 insertions(+), 38 deletions(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 3e8485e4..ffdb2366 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -448,16 +448,20 @@ altos_list_finish(struct altos_list *list) #include #include #include +#include #define USB_BUF_SIZE 64 struct altos_file { int fd; + int pipe[2]; unsigned char out_data[USB_BUF_SIZE]; int out_used; unsigned char in_data[USB_BUF_SIZE]; int in_used; int in_read; + pthread_mutex_t putc_mutex; + pthread_mutex_t getc_mutex; }; struct altos_file * @@ -470,6 +474,7 @@ altos_open(struct altos_device *device) if (!file) return NULL; + pipe(file->pipe); file->fd = open(device->path, O_RDWR | O_NOCTTY); if (file->fd < 0) { perror(device->path); @@ -484,8 +489,8 @@ altos_open(struct altos_device *device) return NULL; } cfmakeraw(&term); - term.c_cc[VMIN] = 0; - term.c_cc[VTIME] = 1; + term.c_cc[VMIN] = 1; + term.c_cc[VTIME] = 0; ret = tcsetattr(file->fd, TCSAFLUSH, &term); if (ret < 0) { perror("tcsetattr"); @@ -493,6 +498,8 @@ altos_open(struct altos_device *device) free(file); return NULL; } + pthread_mutex_init(&file->putc_mutex,NULL); + pthread_mutex_init(&file->getc_mutex,NULL); return file; } @@ -500,8 +507,10 @@ void altos_close(struct altos_file *file) { if (file->fd != -1) { - close(file->fd); + int fd = file->fd; file->fd = -1; + write(file->pipe[1], "\r", 1); + close(fd); } } @@ -512,68 +521,104 @@ altos_free(struct altos_file *file) free(file); } +static int +_altos_flush(struct altos_file *file) +{ + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; + fflush(stdout); + ret = write (file->fd, file->out_data, file->out_used); + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } +} + int altos_putchar(struct altos_file *file, char c) { int ret; + pthread_mutex_lock(&file->putc_mutex); if (file->out_used == USB_BUF_SIZE) { - ret = altos_flush(file); - if (ret) + ret = _altos_flush(file); + if (ret) { + pthread_mutex_unlock(&file->putc_mutex); return ret; + } } file->out_data[file->out_used++] = c; + ret = 0; if (file->out_used == USB_BUF_SIZE) - return altos_flush(file); + ret = _altos_flush(file); + pthread_mutex_unlock(&file->putc_mutex); return 0; } int altos_flush(struct altos_file *file) { - while (file->out_used) { - int ret; - - if (file->fd < 0) - return -EBADF; - ret = write (file->fd, file->out_data, file->out_used); - if (ret < 0) - return -errno; - if (ret) { - memmove(file->out_data, file->out_data + ret, - file->out_used - ret); - file->out_used -= ret; - } - } + int ret; + pthread_mutex_lock(&file->putc_mutex); + ret = _altos_flush(file); + pthread_mutex_unlock(&file->putc_mutex); + return ret; } + #include int altos_getchar(struct altos_file *file, int timeout) { - while (file->in_read == file->in_used) { - int ret; + int ret; + struct pollfd fd[2]; - altos_flush(file); - 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_TIMEOUT; + if (timeout == 0) + timeout = -1; + pthread_mutex_lock(&file->getc_mutex); + fd[0].fd = file->fd; + fd[0].events = POLLIN; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + while (file->in_read == file->in_used) { + if (file->fd < 0) { + pthread_mutex_unlock(&file->getc_mutex); + return LIBALTOS_ERROR; } - ret = read(file->fd, file->in_data, USB_BUF_SIZE); - if (ret < 0) + altos_flush(file); + + ret = poll(fd, 2, timeout); + if (ret < 0) { + perror("altos_getchar"); + pthread_mutex_unlock(&file->getc_mutex); return LIBALTOS_ERROR; - file->in_read = 0; - file->in_used = ret; + } + if (ret == 0) { + pthread_mutex_unlock(&file->getc_mutex); + return LIBALTOS_TIMEOUT; + } + if (fd[0].revents & POLLIN) { + ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret < 0) { + perror("altos_getchar"); + pthread_mutex_unlock(&file->getc_mutex); + return LIBALTOS_ERROR; + } + file->in_read = 0; + file->in_used = ret; + } } - return file->in_data[file->in_read++]; + ret = file->in_data[file->in_read++]; + pthread_mutex_unlock(&file->getc_mutex); + return ret; } #endif /* POSIX_TTY */ -- cgit v1.2.3 From b1758be01397fd49c441f40852f3558fe9343a2d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 21:58:50 -0700 Subject: altosui: Add lots more cc1111 debug interface functions These are sufficient to program the flash. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDebug.java | 139 +++++++++++++++++++++++++++++---------- 1 file changed, 103 insertions(+), 36 deletions(-) diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 7bd3a5cd..83ea5bcb 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -27,35 +27,35 @@ import altosui.AltosRomconfig; public class AltosDebug extends AltosSerial { - static final byte WR_CONFIG = 0x1d; - static final byte RD_CONFIG = 0x24; - static final byte CONFIG_TIMERS_OFF = (1 << 3); - static final byte CONFIG_DMA_PAUSE = (1 << 2); - static final byte CONFIG_TIMER_SUSPEND = (1 << 1); - static final byte SET_FLASH_INFO_PAGE = (1 << 0); - - static final byte GET_PC = 0x28; - static final byte READ_STATUS = 0x34; - static final byte STATUS_CHIP_ERASE_DONE = (byte) (1 << 7); - static final byte STATUS_PCON_IDLE = (1 << 6); - static final byte STATUS_CPU_HALTED = (1 << 5); - static final byte STATUS_POWER_MODE_0 = (1 << 4); - static final byte STATUS_HALT_STATUS = (1 << 3); - static final byte STATUS_DEBUG_LOCKED = (1 << 2); - static final byte STATUS_OSCILLATOR_STABLE = (1 << 1); - static final byte STATUS_STACK_OVERFLOW = (1 << 0); - - static final byte SET_HW_BRKPNT = 0x3b; - static byte HW_BRKPNT_N(byte n) { return (byte) ((n) << 3); } - static final byte HW_BRKPNT_N_MASK = (0x3 << 3); - static final byte HW_BRKPNT_ENABLE = (1 << 2); - - static final byte HALT = 0x44; - static final byte RESUME = 0x4c; - static byte DEBUG_INSTR(byte n) { return (byte) (0x54|(n)); } - static final byte STEP_INSTR = 0x5c; - static byte STEP_REPLACE(byte n) { return (byte) (0x64|(n)); } - static final byte GET_CHIP_ID = 0x68; + 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; static boolean ishex(int c) { @@ -102,14 +102,32 @@ public class AltosDebug extends AltosSerial { } } + 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) { + public void write_memory(int address, byte[] bytes, int start, int len) { ensure_debug_mode(); - printf("O %x %x\n", bytes.length, address); - for (int i = 0; i < bytes.length; i++) - printf("%02x", bytes[i]); +// 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); } /* @@ -123,6 +141,7 @@ public class AltosDebug extends AltosSerial { 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 (!ishex(line) || line.length() % 2 != 0) @@ -131,10 +150,12 @@ public class AltosDebug extends AltosSerial { ("Invalid reply \"%s\"", line)); int this_time = line.length() / 2; for (int j = 0; j < this_time; j++) - data[j] = (byte) ((fromhex(line.charAt(j*2)) << 4) + + data[start + j] = (byte) ((fromhex(line.charAt(j*2)) << 4) + fromhex(line.charAt(j*2+1))); + start += this_time; i += this_time; } +// dump_memory("read_memory", address, data, 0, length); return data; } @@ -195,14 +216,60 @@ public class AltosDebug extends AltosSerial { 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_bytes(2)[0]; + 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(); - System.out.printf("status %x\n", reply); if ((reply & STATUS_CHIP_ERASE_DONE) == 0) return false; if ((reply & STATUS_PCON_IDLE) != 0) -- cgit v1.2.3 From 8857ac5e43eac6db8d5594b8864df497a712242b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:00:16 -0700 Subject: altosui: remove debug printf from AltosHexfile --- ao-tools/altosui/AltosHexfile.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/ao-tools/altosui/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java index 360e24ad..19e35ae1 100644 --- a/ao-tools/altosui/AltosHexfile.java +++ b/ao-tools/altosui/AltosHexfile.java @@ -248,7 +248,5 @@ public class AltosHexfile { data[records[i].address - base + j] = records[i].data[j]; } } - for (int i = 0xa0; i < 0xaa; i++) - System.out.printf ("%04x: %02x\n", i, get_byte(i)); } } \ No newline at end of file -- cgit v1.2.3 From c3f57ffdb6c74de90d982eacd604e658ce9b00a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:01:11 -0700 Subject: altosui: flush serial output before waiting for reply --- ao-tools/altosui/AltosSerial.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index a62f1225..d02e25a9 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -84,7 +84,9 @@ public class AltosSerial implements Runnable { } public String get_reply() throws InterruptedException { - return reply_queue.take(); + libaltos.altos_flush(altos); + String line = reply_queue.take(); + return line; } public void add_monitor(LinkedBlockingQueue q) { -- cgit v1.2.3 From bd2b44ddd61fadd8bf8ee6bf783ce019b1be7cc0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:01:38 -0700 Subject: altosui: Remove debug printf from AltosRomconfig --- ao-tools/altosui/AltosRomconfig.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 5a2df313..844da7c4 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -59,9 +59,6 @@ public class AltosRomconfig { break; } } - System.out.printf("version 0x%x check 0x%x valid %s serial %d cal %d\n", - version, check, valid ? "true" : "false", - serial_number, radio_calibration); } public AltosRomconfig(AltosHexfile hexfile) { -- cgit v1.2.3 From 4c0c099716197ef7539be0cf55bbb164f6804958 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:02:21 -0700 Subject: altosui: Finish device programming code Altosui can now reprogram Altusmetrum devices. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlash.java | 263 ++++++++++++++++++++++++++++++++++++- ao-tools/altosui/AltosFlashUI.java | 115 +++++++++++++++- 2 files changed, 376 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index bab60c1f..0f92d6e7 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -33,17 +33,274 @@ import altosui.AltosHexfile; public class AltosFlash { File file; FileInputStream input; - Thread thread; 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; + do { + status = debug.debug_instr(get_sleep); + } while ((status & SLEEP_XOSC_STB) == 0); + } + + 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); + } 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(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); + + debug.set_pc(flash_prog); + int pc = debug.get_pc(); + debug.resume(); + Thread.sleep(100); + for (int times = 0; times < 10; times++) { + byte status = debug.read_status(); + if ((status & AltosDebug.STATUS_CPU_HALTED) != 0) + break; + Thread.sleep(100); + } + + 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() { @@ -56,6 +313,10 @@ public class AltosFlash { rom_config = romconfig; } + public AltosRomconfig romconfig() { + return rom_config; + } + public void open() throws IOException, FileNotFoundException, InterruptedException { input = new FileInputStream(file); image = new AltosHexfile(input); diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 5cae4756..0c2041e3 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -31,15 +31,43 @@ import java.util.concurrent.LinkedBlockingQueue; import altosui.AltosHexfile; import altosui.AltosFlash; -public class AltosFlashUI implements Runnable { +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")) + dispose(); + else { + pbar.setValue(e.getID()); + pbar.setString(cmd); + } + } + } + public void run() { flash = new AltosFlash(file, debug_dongle); + flash.addActionListener(this); try { flash.open(); if (!flash.check_rom_config()) { @@ -50,6 +78,10 @@ public class AltosFlashUI implements Runnable { return; flash.set_romconfig(romconfig); } + serial_value.setText(String.format("%d", + flash.romconfig().serial_number)); + file_value.setText(file.toString()); + setVisible(true); flash.flash(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, @@ -67,9 +99,90 @@ public class AltosFlashUI implements Runnable { } } + 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) -- cgit v1.2.3 From 56b906f535ac2f86bcab71addbbcd376d74f6a73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:03:36 -0700 Subject: 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 --- src/Makefile.proto | 1 + src/ao.h | 12 +++++++++++- src/ao_config.c | 10 ---------- src/ao_product.c | 1 - src/ao_romconfig.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 src/ao_romconfig.c diff --git a/src/Makefile.proto b/src/Makefile.proto index eedb878a..8bc8b0e1 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -35,6 +35,7 @@ ALTOS_SRC = \ ao_panic.c \ ao_task.c \ ao_timer.c \ + ao_romconfig.c \ _bp.c # diff --git a/src/ao.h b/src/ao.h index 5f2b8339..9c418db2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -289,6 +289,17 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; void ao_led_init(uint8_t enable); +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 1 + +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; + /* * ao_usb.c */ @@ -998,7 +1009,6 @@ ao_rssi_init(uint8_t rssi_led); */ extern const uint8_t ao_usb_descriptors []; -extern const uint16_t ao_serial_number; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_config.c b/src/ao_config.c index cbd639a5..88b52dc0 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,16 +27,6 @@ __xdata uint8_t ao_config_mutex; #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 diff --git a/src/ao_product.c b/src/ao_product.c index 2bd0b59c..f0eb4c07 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -21,7 +21,6 @@ /* 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; diff --git a/src/ao_romconfig.c b/src/ao_romconfig.c new file mode 100644 index 00000000..f3fe61b1 --- /dev/null +++ b/src/ao_romconfig.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; -- cgit v1.2.3 From ef8376c4dd8262a34e02b6bb9e19e907ac2f4330 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:08:30 -0700 Subject: altosui: make default Manifest look for built-in freetts --- ao-tools/altosui/Manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt index 504d0de3..251ce2a0 100644 --- a/ao-tools/altosui/Manifest.txt +++ b/ao-tools/altosui/Manifest.txt @@ -1,2 +1,2 @@ Main-Class: altosui.AltosUI -Class-Path: /usr/share/java/freetts.jar +Class-Path: freetts.jar -- cgit v1.2.3 From a55b132668a819cc26478a609cb79bd9190deb9d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 23:01:36 -0700 Subject: 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 --- ao-tools/altosui/AltosLogfileChooser.java | 52 +++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 14 +++------ ao-tools/altosui/Makefile | 1 + 3 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 ao-tools/altosui/AltosLogfileChooser.java diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java new file mode 100644 index 00000000..72d21fc8 --- /dev/null +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLogfileChooser extends JFileChooser { + JFrame frame; + + public File runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) + return getSelectedFile(); + return null; + } + + public AltosLogfileChooser(JFrame in_frame) { + in_frame = frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "eeprom", + "telem")); + setCurrentDirectory(AltosPreferences.logdir()); + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 9fd47ea7..64f96cdd 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -42,6 +42,7 @@ import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; import altosui.AltosFlashUI; +import altosui.AltosLogfileChooser; import libaltosJNI.*; @@ -529,17 +530,12 @@ public class AltosUI extends JFrame { * Replay a flight from telemetry data */ private void Replay() { - JFileChooser logfile_chooser = new JFileChooser(); + AltosLogfileChooser chooser = new AltosLogfileChooser( + AltosUI.this); - 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); + File file = chooser.runDialog(); - if (returnVal == JFileChooser.APPROVE_OPTION) { - File file = logfile_chooser.getSelectedFile(); - if (file == null) - System.out.println("No file selected?"); + if (file != null) { String filename = file.getName(); try { FileInputStream replay = new FileInputStream(file); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index affbac39..de78b765 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -22,6 +22,7 @@ CLASSFILES=\ AltosGreatCircle.class \ AltosHexfile.class \ AltosLog.class \ + AltosLogfileChooser.class \ AltosParse.class \ AltosPreferences.class \ AltosRecord.class \ -- cgit v1.2.3 From 634a550149e7c344a22a637ba484f115592b1018 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 23:15:05 -0700 Subject: 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 --- ao-tools/altosui/AltosLogfileChooser.java | 32 ++++++++++++++++++++++++++++--- ao-tools/altosui/AltosUI.java | 24 ++++------------------- 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java index 72d21fc8..3e9e4892 100644 --- a/ao-tools/altosui/AltosLogfileChooser.java +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -28,16 +28,42 @@ 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; - public File runDialog() { + public String filename() { + return filename; + } + + public AltosReader runDialog() { int ret; ret = showOpenDialog(frame); - if (ret == APPROVE_OPTION) - return getSelectedFile(); + if (ret == APPROVE_OPTION) { + File 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; } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 64f96cdd..8a4c753f 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -532,26 +532,10 @@ public class AltosUI extends JFrame { private void Replay() { AltosLogfileChooser chooser = new AltosLogfileChooser( AltosUI.this); - - File file = chooser.runDialog(); - - if (file != null) { - 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); - } - } + AltosReader reader = chooser.runDialog(); + if (reader != null) + run_display(new ReplayThread(reader, + chooser.filename())); } /* Connect to TeleMetrum, either directly or through -- cgit v1.2.3 From 7bd220dfd9b3fb0e42eb90c3b37eb7b4169eb21b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 00:29:11 -0700 Subject: 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 --- ao-tools/altosui/AltosCSV.java | 120 +++++++++++++++++++++++++++--- ao-tools/altosui/AltosCSVUI.java | 83 +++++++++++++++++++++ ao-tools/altosui/AltosEepromReader.java | 4 +- ao-tools/altosui/AltosLogfileChooser.java | 9 ++- ao-tools/altosui/AltosReader.java | 2 + ao-tools/altosui/AltosUI.java | 17 +++++ ao-tools/altosui/Makefile | 1 + 7 files changed, 224 insertions(+), 12 deletions(-) create mode 100644 ao-tools/altosui/AltosCSVUI.java diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 24936758..f12c0348 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -19,12 +19,20 @@ package altosui; 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 pad_records; + AltosState state; static final int ALTOS_CSV_VERSION = 1; @@ -45,6 +53,7 @@ public class AltosCSV { * acceleration (m/s²) * pressure (mBar) * altitude (m) + * height (m) * accelerometer speed (m/s) * barometer speed (m/s) * temp (°C) @@ -76,8 +85,9 @@ public class AltosCSV { } 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", + record.version, record.serial, record.flight, record.callsign, + (double) (record.tick - boost_tick) / 100.0); } void write_flight_header() { @@ -85,31 +95,123 @@ public class AltosCSV { } 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"); + } + + void write_gps(AltosRecord record) { + AltosGPS gps = record.gps; + if (gps == null) + gps = new AltosGPS(); + + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d", + 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); } 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) { + } catch (ParseException pe) { + } + } + public AltosCSV(File in_name) throws FileNotFoundException { name = in_name; out = new PrintStream(name); + pad_records = new LinkedList(); } } diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java new file mode 100644 index 00000000..2d812361 --- /dev/null +++ b/ao-tools/altosui/AltosCSVUI.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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(); + } +} diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index c29fd90b..deab2167 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -218,6 +218,7 @@ public class AltosEepromReader extends AltosReader { case Altos.AO_LOG_PRODUCT: break; case Altos.AO_LOG_SERIAL_NUMBER: + state.serial = record.a; break; case Altos.AO_LOG_SOFTWARE_VERSION: break; @@ -228,6 +229,7 @@ public class AltosEepromReader extends AltosReader { public void write_comments(PrintStream out) { Iterator iterator = records.iterator(); + out.printf("# Comments\n"); while (iterator.hasNext()) { AltosOrderedRecord record = iterator.next(); switch (record.cmd) { @@ -250,7 +252,7 @@ public class AltosEepromReader extends AltosReader { 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); diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java index 3e9e4892..36b51de6 100644 --- a/ao-tools/altosui/AltosLogfileChooser.java +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -35,17 +35,22 @@ 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 file = getSelectedFile(); + file = getSelectedFile(); if (file == null) return null; filename = file.getName(); @@ -68,7 +73,7 @@ public class AltosLogfileChooser extends JFileChooser { } public AltosLogfileChooser(JFrame in_frame) { - in_frame = frame; + frame = in_frame; setDialogTitle("Select Flight Record File"); setFileFilter(new FileNameExtensionFilter("Flight data file", "eeprom", diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java index 81779e2b..5be8795d 100644 --- a/ao-tools/altosui/AltosReader.java +++ b/ao-tools/altosui/AltosReader.java @@ -25,4 +25,6 @@ import altosui.AltosRecord; public class AltosReader { public AltosRecord read() throws IOException, ParseException { return null; } + public void close() { } + public void write_comments(PrintStream out) { } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 8a4c753f..63cb486c 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -43,6 +43,7 @@ import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; import altosui.AltosFlashUI; import altosui.AltosLogfileChooser; +import altosui.AltosCSVUI; import libaltosJNI.*; @@ -545,6 +546,14 @@ public class AltosUI extends JFrame { 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() { @@ -583,6 +592,14 @@ public class AltosUI extends JFrame { }); 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)); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index de78b765..1273e7d4 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -8,6 +8,7 @@ CLASSFILES=\ AltosConfigUI.class \ AltosConvert.class \ AltosCSV.class \ + AltosCSVUI.class \ AltosDebug.class \ AltosEepromDownload.class \ AltosEepromMonitor.class \ -- cgit v1.2.3 From 7d44cbd621d2b113ac2b802ef17e3d8a660ce7f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 03:58:00 -0700 Subject: altosui: disable radio monitoring while using serial line for debugging --- ao-tools/altosui/AltosDebug.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 83ea5bcb..df40410a 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -97,7 +97,7 @@ public class AltosDebug extends AltosSerial { void ensure_debug_mode() { if (!debug_mode) { - printf("D\n"); + printf("m 0\nD\n"); debug_mode = true; } } -- cgit v1.2.3 From d93787284c8e514a929edb9f944c98ae0206a33f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 03:59:09 -0700 Subject: 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 --- ao-tools/altosui/AltosFlash.java | 1 + ao-tools/altosui/AltosFlashUI.java | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index 0f92d6e7..7aeab89a 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -247,6 +247,7 @@ public class AltosFlash { 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; diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 0c2041e3..b88a16b3 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -57,8 +57,10 @@ public class AltosFlashUI } else { String cmd = e.getActionCommand(); if (cmd.equals("done")) - dispose(); - else { + ; + else if (cmd.equals("start")) { + setVisible(true); + } else { pbar.setValue(e.getID()); pbar.setString(cmd); } @@ -88,15 +90,14 @@ public class AltosFlashUI "Cannot open image", file.toString(), JOptionPane.ERROR_MESSAGE); - return; } catch (IOException e) { JOptionPane.showMessageDialog(frame, e.getMessage(), file.toString(), JOptionPane.ERROR_MESSAGE); - return; } catch (InterruptedException ie) { } + dispose(); } public void abort() { -- cgit v1.2.3 From f62b2aa08ebfd912b3c732397d43ff9f6162ec88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 04:01:14 -0700 Subject: altosui: fetch existing romconfig for flashing --- ao-tools/altosui/AltosFlash.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index 7aeab89a..b7018555 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -315,6 +315,8 @@ public class AltosFlash { } public AltosRomconfig romconfig() { + if (!check_rom_config()) + return null; return rom_config; } -- cgit v1.2.3 From 220f3afdaa432c65f8ad45be7cdbe5c8a3616db3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 04:01:47 -0700 Subject: altosui: always display romconfig ui while flashing --- ao-tools/altosui/AltosFlashUI.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index b88a16b3..73a97a6b 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -72,14 +72,15 @@ public class AltosFlashUI flash.addActionListener(this); try { flash.open(); - if (!flash.check_rom_config()) { - AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); - romconfig_ui.showDialog(); - AltosRomconfig romconfig = romconfig_ui.romconfig(); - if (romconfig == null) - return; - flash.set_romconfig(romconfig); - } + AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); + + romconfig_ui.set(flash.romconfig()); + romconfig_ui.showDialog(); + + AltosRomconfig romconfig = romconfig_ui.romconfig(); + if (romconfig == null || !romconfig.valid()) + return; + flash.set_romconfig(romconfig); serial_value.setText(String.format("%d", flash.romconfig().serial_number)); file_value.setText(file.toString()); -- cgit v1.2.3 From ba086cc77273efe5397f60dcaccd1e3771441481 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 04:02:27 -0700 Subject: 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 --- ao-tools/altosui/AltosRomconfig.java | 49 +++++++++++++++++++++++++++++++++- ao-tools/altosui/AltosRomconfigUI.java | 21 ++++++++++++++- src/ao.h | 5 ++-- src/ao_product.c | 2 +- 4 files changed, 72 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 844da7c4..8c9cb27a 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -47,14 +47,57 @@ public class AltosRomconfig { } } + 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; + System.out.printf("Put usb serial %d\n", value); + + 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; + } + System.out.printf("offset %d content %d\n", + offset, bytes[offset]); + if (offset >= bytes.length || bytes[offset] == 0) + return; + int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; + String fmt = String.format("%%0%dd", len); + System.out.printf("existing serial length %d format %s\n", len, fmt); + + 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); + System.out.printf("version %d check %d\n", version, check); 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); + System.out.printf("serial %d cal %d\n", serial_number, radio_calibration); valid = true; break; } @@ -77,6 +120,8 @@ public class AltosRomconfig { 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); @@ -86,7 +131,9 @@ public class AltosRomconfig { public void write (AltosHexfile hexfile) throws IOException { write(hexfile.data, 0xa0 - hexfile.address); - new AltosRomconfig(hexfile); + 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) { diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 21c34ef4..bc511865 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -143,12 +143,31 @@ public class AltosRomconfigUI 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); + } + } + public AltosRomconfig romconfig() { - return new AltosRomconfig(serial(), radio_calibration()); + try { + return new AltosRomconfig(serial(), radio_calibration()); + } catch (NumberFormatException ne) { + return null; + } } public AltosRomconfig showDialog() { diff --git a/src/ao.h b/src/ao.h index 9c418db2..d289ced1 100644 --- a/src/ao.h +++ b/src/ao.h @@ -293,12 +293,13 @@ ao_led_init(uint8_t enable); * ao_romconfig.c */ -#define AO_ROMCONFIG_VERSION 1 +#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 @@ -1008,7 +1009,7 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -extern const uint8_t ao_usb_descriptors []; +extern __code __at(0x00aa) uint8_t ao_usb_descriptors []; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_product.c b/src/ao_product.c index f0eb4c07..82d6298f 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -28,7 +28,7 @@ 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, -- cgit v1.2.3 From 99400fdc0f19ef538fc362dde5c3ab5b7cdac409 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 16:43:38 -0700 Subject: 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 --- ao-tools/altosui/AltosDebug.java | 1 + ao-tools/altosui/AltosSerial.java | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index df40410a..06c9a0bd 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -98,6 +98,7 @@ public class AltosDebug extends AltosSerial { void ensure_debug_mode() { if (!debug_mode) { printf("m 0\nD\n"); + flush_reply(); debug_mode = true; } } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index d02e25a9..3684f253 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -66,8 +66,10 @@ public class AltosSerial implements Runnable { LinkedBlockingQueue q = monitors.get(e); q.put(line); } - } else + } else { +// System.out.printf("GOT: %s\n", line); reply_queue.put(line); + } line = ""; } } else { @@ -80,6 +82,11 @@ public class AltosSerial implements Runnable { } public void flush_reply() { + libaltos.altos_flush(altos); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } reply_queue.clear(); } @@ -132,6 +139,7 @@ public class AltosSerial implements Runnable { } public void print(String data) { +// System.out.printf("\"%s\" ", data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } -- cgit v1.2.3 From 34055129b4008f6a9833887b12dee39ffa408002 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 15:57:09 -0700 Subject: 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 --- src/Makefile.proto | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 8bc8b0e1..59a3b8a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,9 +214,11 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ -ao_product.h: ao-make-product.5c +ao_product.h: ao-make-product.5c always $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +always: + ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< -- cgit v1.2.3 From aa6c27df5db6bdae59d00affccb891854a6caa18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 15:59:09 -0700 Subject: altos: print GPS state flags in GPS 'g' command Having the GPS state information can help with GPS debugging. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ae8c7ef7..c822f7fa 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -422,6 +422,7 @@ gps_dump(void) __reentrant 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); } -- cgit v1.2.3 From 68b2b66d7574dfd0bd5e3571b8ffad32ca5d2b73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:37:29 -0700 Subject: 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 --- src/ao.h | 3 ++- src/ao_gps_report.c | 4 ++-- src/ao_log.c | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index d289ced1..8db22799 100644 --- a/src/ao.h +++ b/src/ao.h @@ -564,6 +564,7 @@ struct ao_log_record { uint8_t year; uint8_t month; uint8_t day; + uint8_t extra; } gps_date; struct { uint16_t d0; @@ -573,7 +574,7 @@ struct ao_log_record { }; /* Write a record to the eeprom log */ -void +uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the log */ diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index cceb79ff..7abc93f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -51,12 +51,12 @@ ao_gps_report(void) 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); } } } diff --git a/src/ao_log.c b/src/ao_log.c index d550d408..18bdb8c8 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -33,14 +33,16 @@ ao_log_csum(__xdata uint8_t *b) __reentrant 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)); @@ -51,6 +53,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant ao_log_running = 0; } } ao_mutex_put(&ao_log_mutex); + return wrote; } void -- cgit v1.2.3 From f0fd423d0bf83bc5c3f9d39e9c09397fbe8caed2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:41:26 -0700 Subject: altosui: Move number parsing code to Altos general class This moves these shared functions to the global shared class. Signed-off-by: Keith Packard --- ao-tools/altosui/Altos.java | 86 ++++++++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosDebug.java | 43 ++------------------ ao-tools/altosui/AltosParse.java | 10 ++++- 3 files changed, 98 insertions(+), 41 deletions(-) diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 53359e23..07bd01ae 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -114,4 +114,90 @@ public class Altos { 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; + } } diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 06c9a0bd..ca2e5a90 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -58,41 +58,6 @@ public class AltosDebug extends AltosSerial { public static final byte GET_CHIP_ID = 0x68; - 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 boolean isspace(int c) { - switch (c) { - case ' ': - case '\t': - return true; - } - return false; - } - - 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; - } - boolean debug_mode; void ensure_debug_mode() { @@ -145,14 +110,14 @@ public class AltosDebug extends AltosSerial { int start = 0; while (i < length) { String line = get_reply().trim(); - if (!ishex(line) || line.length() % 2 != 0) + 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) ((fromhex(line.charAt(j*2)) << 4) + - fromhex(line.charAt(j*2+1))); + data[start + j] = (byte) ((Altos.fromhex(line.charAt(j*2)) << 4) + + Altos.fromhex(line.charAt(j*2+1))); start += this_time; i += this_time; } @@ -199,7 +164,7 @@ public class AltosDebug extends AltosSerial { String line = get_reply().trim(); String tokens[] = line.split("\\s+"); for (int j = 0; j < tokens.length; j++) { - if (!ishex(tokens[j]) || + if (!Altos.ishex(tokens[j]) || tokens[j].length() != 2) throw new IOException( String.format diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java index a60dc694..4d82de78 100644 --- a/ao-tools/altosui/AltosParse.java +++ b/ao-tools/altosui/AltosParse.java @@ -20,10 +20,16 @@ package altosui; 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); } @@ -31,7 +37,7 @@ public class AltosParse { 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); } -- cgit v1.2.3 From 3dc67c1401976d6e9e2e942d5a4707a4810a0404 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:43:00 -0700 Subject: 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 --- ao-tools/altosui/AltosGreatCircle.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java index 878da03e..07c02c16 100644 --- a/ao-tools/altosui/AltosGreatCircle.java +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -17,6 +17,8 @@ package altosui; +import altosui.AltosGPS; + import java.lang.Math; public class AltosGreatCircle { @@ -28,8 +30,8 @@ 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; @@ -63,4 +65,13 @@ public class AltosGreatCircle { 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; + } } -- cgit v1.2.3 From 651f6102ac79459fc8d5679d852c963dcb5bb3fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:44:25 -0700 Subject: 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 --- ao-tools/altosui/AltosCSV.java | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index f12c0348..db50e7a2 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -44,6 +44,7 @@ public class AltosCSV { * flight number * callsign * time (seconds since boost) + * rssi * * Flight status * state @@ -74,6 +75,8 @@ public class AltosCSV { * hour (0-23) * minute (0-59) * second (0-59) + * from_pad_dist (m) + * from_pad_dir (deg true) * * GPS Sat data * hdop @@ -81,13 +84,14 @@ public class AltosCSV { */ 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,%8.2f", + out.printf("%s,%d,%d,%s,%8.2f,%4d", record.version, record.serial, record.flight, record.callsign, - (double) (record.tick - boost_tick) / 100.0); + (double) record.time, + record.rssi); } void write_flight_header() { @@ -117,7 +121,7 @@ public class AltosCSV { } void write_gps_header() { - out.printf("connected locked nsat latitude longitude altitude year month day hour minute second"); + out.printf("connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_dir"); } void write_gps(AltosRecord record) { @@ -125,7 +129,11 @@ public class AltosCSV { if (gps == null) gps = new AltosGPS(); - out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d", + 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,%4.0f", gps.connected?1:0, gps.locked?1:0, gps.nsat, @@ -137,7 +145,9 @@ public class AltosCSV { gps.day, gps.hour, gps.minute, - gps.second); + gps.second, + from_pad.distance, + from_pad.bearing); } void write_header() { @@ -205,7 +215,9 @@ public class AltosCSV { write(record); } } catch (IOException ie) { + System.out.printf("IOException\n"); } catch (ParseException pe) { + System.out.printf("ParseException %s\n", pe.getMessage()); } } @@ -214,4 +226,8 @@ public class AltosCSV { out = new PrintStream(name); pad_records = new LinkedList(); } + + public AltosCSV(String in_string) throws FileNotFoundException { + this(new File(in_string)); + } } -- cgit v1.2.3 From e383595cd281687de903fb6176564bbef270cb83 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:47:38 -0700 Subject: 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 --- ao-tools/altosui/AltosEepromReader.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index deab2167..3f2d4c62 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -133,8 +133,6 @@ public class AltosEepromReader extends AltosReader { 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; @@ -156,7 +154,6 @@ public class AltosEepromReader extends AltosReader { 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: @@ -298,10 +295,10 @@ public class AltosEepromReader extends AltosReader { break; tick = record.tick; if (!saw_boost && record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_boost) + record.a >= Altos.ao_flight_boost) { saw_boost = true; - boost_tick = state.tick; + boost_tick = tick; } records.add(record); } -- cgit v1.2.3 From 0942912163255523d923140c01afbdb5da1c19b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:49:37 -0700 Subject: 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 --- ao-tools/altosui/AltosGPS.java | 61 ++++++++++++++++++++++-------------- ao-tools/altosui/AltosTelemetry.java | 34 ++++++++++++++------ 2 files changed, 63 insertions(+), 32 deletions(-) diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index b3ee67e8..acb6fb2c 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -52,14 +52,16 @@ public class AltosGPS { 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); @@ -73,7 +75,7 @@ public class AltosGPS { 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"); @@ -92,32 +94,44 @@ public class AltosGPS { 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) { @@ -172,6 +186,7 @@ public class AltosGPS { 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 */ diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index af29b8c0..bc62690b 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -57,8 +57,12 @@ public class AltosTelemetry extends AltosRecord { String[] words = line.split("\\s+"); int i = 0; - AltosParse.word (words[i++], "VERSION"); - version = AltosParse.parse_int(words[i++]); + 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++]; @@ -66,12 +70,19 @@ public class AltosTelemetry extends AltosRecord { 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++]); @@ -113,12 +124,17 @@ public class AltosTelemetry extends AltosRecord { 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); } } -- cgit v1.2.3 From a16db143fc7ca72dc91e7989420049192114642d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:50:51 -0700 Subject: 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 --- ao-tools/altosui/AltosSerial.java | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 3684f253..5b47960f 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -45,6 +45,8 @@ public class AltosSerial implements Runnable { LinkedBlockingQueue reply_queue; Thread input_thread; String line; + byte[] line_bytes; + int line_count; public void run () { int c; @@ -60,7 +62,14 @@ public class AltosSerial implements Runnable { continue; synchronized(this) { if (c == '\n') { - if (line != "") { + 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")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); @@ -70,10 +79,19 @@ public class AltosSerial implements Runnable { // System.out.printf("GOT: %s\n", line); reply_queue.put(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++; } } } @@ -139,7 +157,7 @@ public class AltosSerial implements Runnable { } public void print(String data) { -// System.out.printf("\"%s\" ", data); +//h System.out.printf("\"%s\" ", data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } -- cgit v1.2.3 From 49364608b59de7421ab00d87d2685bc3b5f58411 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:53:06 -0700 Subject: 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 --- ao-tools/altosui/AltosTelemetryReader.java | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index f1f6788c..a3402f9c 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -47,20 +47,25 @@ public class AltosTelemetryReader extends AltosReader { 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 (IOException io) { - } catch (ParseException pe) { + System.out.printf("io exception\n"); } record_iterator = records.iterator(); try { -- cgit v1.2.3 From 7e0506dc2014b7178f52b950e8c1cb820b35f9c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:54:53 -0700 Subject: altosui: Remove debug printf from AltosState.java Signed-off-by: Keith Packard --- ao-tools/altosui/AltosState.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index deeb4c77..c13dfe68 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -124,11 +124,6 @@ public class AltosState { } 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) { npad++; if (npad > 1) { -- cgit v1.2.3 From 68967157cee620ebedcc8c2ffd6fc7656532087b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:55:44 -0700 Subject: altosui: command line args are converted to csv format Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 63 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 63cb486c..4f3b5dde 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -719,8 +719,67 @@ public class AltosUI extends JFrame { 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 -- cgit v1.2.3 From 2923cf5057f9cef110dd547d8677ea5b60e00796 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 27 Aug 2010 00:10:29 -0700 Subject: 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 --- src/ao.h | 16 ++++----- src/ao_adc.c | 2 +- src/ao_cmd.c | 3 +- src/ao_dma.c | 2 +- src/ao_radio.c | 2 +- src/ao_serial.c | 4 +-- src/ao_timer.c | 2 +- src/ao_usb.c | 2 +- src/cc1111.h | 108 ++++++++++++++++++++++++++++---------------------------- 9 files changed, 70 insertions(+), 71 deletions(-) diff --git a/src/ao.h b/src/ao.h index 8db22799..cd4e4814 100644 --- a/src/ao.h +++ b/src/ao.h @@ -79,7 +79,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) _naked; +ao_yield(void) __naked; /* Add a task to the run queue */ void @@ -139,7 +139,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) interrupt 9; +ao_timer_isr(void) __interrupt 9; /* Initialize the timer */ void @@ -198,7 +198,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) interrupt 1; +ao_adc_isr(void) __interrupt 1; /* Initialize the A/D converter */ void @@ -325,7 +325,7 @@ ao_usb_flush(void); /* USB interrupt handler */ void -ao_usb_isr(void) interrupt 6; +ao_usb_isr(void) __interrupt 6; /* Enable the USB controller */ void @@ -425,7 +425,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) interrupt 8; +ao_dma_isr(void) __interrupt 8; /* * ao_mutex.c @@ -722,10 +722,10 @@ ao_dbg_init(void); #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; @@ -861,7 +861,7 @@ extern __xdata uint8_t ao_radio_done; 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); diff --git a/src/ao_adc.c b/src/ao_adc.c index 50f96848..49d2519e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_get(__xdata struct ao_adc *packet) } void -ao_adc_isr(void) interrupt 1 +ao_adc_isr(void) __interrupt 1 { uint8_t sequence; uint8_t __xdata *a; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 4a68fba4..a54a2316 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -263,13 +263,12 @@ ao_cmd_register(__code struct ao_cmds *cmds) } 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 (;;) { diff --git a/src/ao_dma.c b/src/ao_dma.c index 110138b5..946666ab 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -112,7 +112,7 @@ ao_dma_abort(uint8_t id) } void -ao_dma_isr(void) interrupt 8 +ao_dma_isr(void) __interrupt 8 { uint8_t id, mask; diff --git a/src/ao_radio.c b/src/ao_radio.c index 0849349e..f4a9d3b2 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -275,7 +275,7 @@ __xdata uint8_t ao_radio_done; __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) { diff --git a/src/ao_serial.c b/src/ao_serial.c index 3f103766..a48734c2 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -21,7 +21,7 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; 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); @@ -42,7 +42,7 @@ ao_serial_tx1_start(void) } void -ao_serial_tx1_isr(void) interrupt 14 +ao_serial_tx1_isr(void) __interrupt 14 { UTX1IF = 0; ao_serial_tx1_started = 0; diff --git a/src/ao_timer.c b/src/ao_timer.c index d1731475..c977fbc8 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -41,7 +41,7 @@ volatile __data uint8_t ao_adc_interval = 1; 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 diff --git a/src/ao_usb.c b/src/ao_usb.c index f6e0fcf9..b55130f2 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -43,7 +43,7 @@ ao_usb_set_interrupts(void) * 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; diff --git a/src/cc1111.h b/src/cc1111.h index e8302df2..20ed052a 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,16 +40,16 @@ #include #include -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) @@ -60,7 +60,7 @@ sbit at 0xAF EA; /* Enable All */ #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 */ @@ -70,7 +70,7 @@ sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #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 */ @@ -82,7 +82,7 @@ sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */ #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) @@ -126,20 +126,20 @@ sfr at 0xC6 CLKCON; /* Clock Control */ #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) @@ -150,10 +150,10 @@ sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleare /* * 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) @@ -161,7 +161,7 @@ sbit at 0x99 ENCIF_1; /* AES interrupt 1. */ /* * 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) @@ -169,15 +169,15 @@ sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */ /* * 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 */ @@ -190,15 +190,15 @@ sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */ /* * 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) */ @@ -225,8 +225,8 @@ sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ * 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) @@ -286,13 +286,13 @@ sfr at 0xA9 IP0; /* Interrupt Priority 0 */ */ /* 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) @@ -312,10 +312,10 @@ sfr at 0xEB T4CTL; /* 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) @@ -328,16 +328,16 @@ sfr at 0xEE T4CCTL1; #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) -- cgit v1.2.3 From 9ea94411c9730f7a271366d309ab4827beeeb839 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 11:17:54 -0600 Subject: add a dummy install target --- ao-tools/libaltos/Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index a251e54e..9933dc80 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,5 +1,8 @@ OS:=$(shell uname) +# dummy install target for now so I can work on the rest of the packaging +install: + @echo warning - make install doing nothing in libaltos! # # Linux # -- cgit v1.2.3 From a21b6bb60ac1c07ebd161534a4ea63bfde50dcdf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 11:26:29 -0600 Subject: lose the prebuild hook for now while I'm fumbling --- debian/gbp.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/debian/gbp.conf b/debian/gbp.conf index 9561fdfe..9c366c76 100644 --- a/debian/gbp.conf +++ b/debian/gbp.conf @@ -4,7 +4,8 @@ # the default build command: #builder = debuild -i\.git/ -I.git # the default clean command: -cleaner = debian/rules prebuild && debuild clean +#cleaner = debian/rules prebuild && debuild clean +cleaner = debuild clean # the default branch for upstream sources: upstream-branch = upstream # the default branch for the debian patch: -- cgit v1.2.3 From 72c33a72ee105ec692dad62d6d9c1ad40b89bfe8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 11:45:19 -0600 Subject: add install target for libaltos --- ao-tools/libaltos/Makefile | 6 +++--- debian/dirs | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 9933dc80..cd96fd5f 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -1,8 +1,5 @@ OS:=$(shell uname) -# dummy install target for now so I can work on the rest of the packaging -install: - @echo warning - make install doing nothing in libaltos! # # Linux # @@ -17,6 +14,9 @@ OS_LDFLAGS= LIBNAME=libaltos.so EXEEXT= +install: $(LIBNAME) + /usr/bin/install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) + endif # diff --git a/debian/dirs b/debian/dirs index db75fea7..6bf06c6e 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,5 +1,6 @@ etc/apt/sources.list.d usr/bin +usr/lib/altos usr/share/altos usr/share/applications usr/share/gdm/themes/altusmetrum -- cgit v1.2.3 From 72a18502e40f55cbba6418dc94315517881cd411 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 11:51:24 -0600 Subject: add an install target for altosui --- ao-tools/altosui/Makefile | 7 ++++++- debian/dirs | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index d3ecb889..258a334f 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -96,8 +96,13 @@ endif ifeq ($(OS),Linux) altosui: echo "#!/bin/sh" > $@ - echo "exec java -Djava.library.path=../libaltos -jar altosui.jar" >> $@ + echo "exec java -Djava.library.path=/usr/lib/altos/libaltos -jar altosui.jar" >> $@ chmod +x ./altosui + +install: altosui.jar altosui + /usr/bin/install -c altosui.jar $(DESTDIR)/usr/share/java/altosui.jar + /usr/bin/install -c altosui $(DESTDIR)/usr/bin/altosui + endif clean: diff --git a/debian/dirs b/debian/dirs index 6bf06c6e..7b4dffb8 100644 --- a/debian/dirs +++ b/debian/dirs @@ -4,5 +4,6 @@ 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 -- cgit v1.2.3 From 63bd34cd1b5a411489e8c3ab377f0fe0eec11f67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 27 Aug 2010 10:58:55 -0700 Subject: altosui: add elevation and range information Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSV.java | 12 ++-- ao-tools/altosui/AltosEepromReader.java | 99 ++++++++++++++++++++++++++++++++- ao-tools/altosui/AltosEepromRecord.java | 9 ++- ao-tools/altosui/AltosState.java | 13 ++++- ao-tools/altosui/AltosUI.java | 22 ++++++-- 5 files changed, 142 insertions(+), 13 deletions(-) diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index db50e7a2..4ce8e30e 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -76,7 +76,9 @@ public class AltosCSV { * minute (0-59) * second (0-59) * from_pad_dist (m) - * from_pad_dir (deg true) + * from_pad_azimuth (deg true) + * from_pad_range (m) + * from_pad_elevation (deg from horizon) * * GPS Sat data * hdop @@ -121,7 +123,7 @@ public class AltosCSV { } void write_gps_header() { - out.printf("connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_dir"); + 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) { @@ -133,7 +135,7 @@ public class AltosCSV { 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,%4.0f", + 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, @@ -147,7 +149,9 @@ public class AltosCSV { gps.minute, gps.second, from_pad.distance, - from_pad.bearing); + state.range, + from_pad.bearing, + state.elevation); } void write_header() { diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 3f2d4c62..0705d44e 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -42,7 +42,7 @@ import altosui.AltosEepromMonitor; */ class AltosOrderedRecord extends AltosEepromRecord implements Comparable { - int index; + public int index; public AltosOrderedRecord(String line, int in_index, int prev_tick) throws ParseException { @@ -56,6 +56,11 @@ class AltosOrderedRecord extends AltosEepromRecord implements Comparable> Altos.AO_GPS_NUM_SAT_SHIFT; + System.out.printf("GPS %2d:%02d:%02d%s%s%s %d\n", + state.gps.hour, state.gps.minute, state.gps.second, + state.gps.connected ? " connected" : "", + state.gps.locked ? " locked" : "", + state.gps.date_valid ? " date_valid" : "", + state.gps.nsat); break; case Altos.AO_LOG_GPS_LAT: int lat32 = record.a | (record.b << 16); @@ -267,6 +282,38 @@ public class AltosEepromReader extends AltosReader { } } + /* + * 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); + + System.out.printf("Synthesizing time good %2d:%02d:%02d bad %2d:%02d:%02d\n", + hour, minute, second, + new_hour, new_minute, new_second); + + 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 @@ -282,9 +329,13 @@ public class AltosEepromReader extends AltosReader { seen = 0; records = new TreeSet(); + AltosOrderedRecord last_gps_time = null; + int index = 0; int tick = 0; + boolean missing_time = false; + try { for (;;) { String line = AltosRecord.gets(input); @@ -300,6 +351,52 @@ public class AltosEepromReader extends AltosReader { saw_boost = true; boost_tick = tick; } + + /* 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) { + System.out.printf("Going back to clean up broken GPS time records\n"); + Iterator iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedRecord old = iterator.next(); + if (old.cmd == Altos.AO_LOG_GPS_TIME) { + System.out.printf("Old time record %d, %d\n", old.a, old.b); + } + 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 { + System.out.printf("early GPS missing time\n"); + missing_time = true; + } + records.add(add_gps_time); + record.index = index++; + } + } records.add(record); } } catch (IOException io) { diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java index 86ac1fd2..4d0817ab 100644 --- a/ao-tools/altosui/AltosEepromRecord.java +++ b/ao-tools/altosui/AltosEepromRecord.java @@ -44,7 +44,7 @@ public class AltosEepromRecord { public int tick; public int a; public int b; - String data; + public String data; public boolean tick_valid; public AltosEepromRecord (String line) throws ParseException { @@ -107,4 +107,11 @@ public class AltosEepromRecord { } } + 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; + } } diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index c13dfe68..3ef00f35 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -64,6 +64,8 @@ public class AltosState { boolean gps_ready; AltosGreatCircle from_pad; + double elevation; /* from pad */ + double range; /* total distance */ double gps_height; @@ -124,7 +126,7 @@ public class AltosState { } if (state == Altos.ao_flight_pad) { - 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 */ @@ -161,11 +163,18 @@ public class AltosState { 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; } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 4f3b5dde..5b48e26f 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -264,7 +264,7 @@ public class AltosUI extends JFrame { private AltosState state; int reported_landing; - public void report(boolean last) { + public synchronized void report(boolean last) { if (state == null) return; @@ -278,7 +278,16 @@ public class AltosUI extends JFrame { } /* 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; @@ -288,7 +297,7 @@ public class AltosUI extends JFrame { * 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)) @@ -298,7 +307,7 @@ public class AltosUI extends JFrame { 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; @@ -311,7 +320,7 @@ public class AltosUI extends JFrame { state = null; try { for (;;) { - Thread.sleep(10000); + Thread.sleep(20000); report(false); } } catch (InterruptedException ie) { @@ -319,7 +328,10 @@ public class AltosUI extends JFrame { } public void notice(AltosState new_state) { + AltosState old_state = state; state = new_state; + if (old_state != null && old_state.state != state.state) + report(false); } } -- cgit v1.2.3 From c280071b7db4e9a7af31dc5740eb8d27f137950e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:04:13 -0600 Subject: fix up the wrapper's path to the jar file --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 258a334f..73bc230d 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -96,7 +96,7 @@ endif ifeq ($(OS),Linux) altosui: echo "#!/bin/sh" > $@ - echo "exec java -Djava.library.path=/usr/lib/altos/libaltos -jar altosui.jar" >> $@ + echo "exec java -Djava.library.path=/usr/lib/altos/libaltos -jar /usr/share/java/altosui.jar" >> $@ chmod +x ./altosui install: altosui.jar altosui -- cgit v1.2.3 From 138009e9fad01f79df4c3820fbc206f78688bdce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:06:01 -0600 Subject: update Debian standards version --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index cc8fda94..f2bd1914 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard 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 -- cgit v1.2.3 From 5cc933039e4763b8675611c63b6147b42878a2bb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:16:19 -0600 Subject: fix permissions on installed jar file, switch from ao-view to altosui in the desktop file --- ao-tools/altosui/Makefile | 4 ++-- ao-tools/altosui/altosui.1 | 44 ++++++++++++++++++++++++++++++++++++++++++++ debian/altos.desktop | 4 ++-- 3 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 ao-tools/altosui/altosui.1 diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 73bc230d..101954db 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -100,8 +100,8 @@ altosui: chmod +x ./altosui install: altosui.jar altosui - /usr/bin/install -c altosui.jar $(DESTDIR)/usr/share/java/altosui.jar - /usr/bin/install -c altosui $(DESTDIR)/usr/bin/altosui + /usr/bin/install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar + /usr/bin/install altosui $(DESTDIR)/usr/bin/altosui endif diff --git a/ao-tools/altosui/altosui.1 b/ao-tools/altosui/altosui.1 new file mode 100644 index 00000000..c3130fce --- /dev/null +++ b/ao-tools/altosui/altosui.1 @@ -0,0 +1,44 @@ +.\" +.\" Copyright © 2010 Bdale Garbee +.\" +.\" 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 diff --git a/debian/altos.desktop b/debian/altos.desktop index 4281ad3a..4345cf09 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -1,10 +1,10 @@ [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; -- cgit v1.2.3 From a8dbe082960dc9bdd44c6e4b1198423c4e566029 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:18:28 -0600 Subject: install altosui man page --- ao-tools/altosui/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 101954db..df960130 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -101,6 +101,7 @@ altosui: install: altosui.jar altosui /usr/bin/install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar + /usr/bin/install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/altosui.1 /usr/bin/install altosui $(DESTDIR)/usr/bin/altosui endif -- cgit v1.2.3 From de2e71c4923a0282df74dbe37d087c34b4ddd279 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:25:20 -0600 Subject: fix man page delivery path --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index df960130..22752d5d 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -101,7 +101,7 @@ altosui: install: altosui.jar altosui /usr/bin/install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar - /usr/bin/install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/altosui.1 + /usr/bin/install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1 /usr/bin/install altosui $(DESTDIR)/usr/bin/altosui endif -- cgit v1.2.3 From ae5eff7bc0b63047737223423009707bedcb00f5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:37:36 -0600 Subject: Revert "lose the prebuild hook for now while I'm fumbling" This reverts commit a21b6bb60ac1c07ebd161534a4ea63bfde50dcdf. --- debian/gbp.conf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/debian/gbp.conf b/debian/gbp.conf index 9c366c76..9561fdfe 100644 --- a/debian/gbp.conf +++ b/debian/gbp.conf @@ -4,8 +4,7 @@ # the default build command: #builder = debuild -i\.git/ -I.git # the default clean command: -#cleaner = debian/rules prebuild && debuild clean -cleaner = debuild clean +cleaner = debian/rules prebuild && debuild clean # the default branch for upstream sources: upstream-branch = upstream # the default branch for the debian patch: -- cgit v1.2.3 From 99c1d9b4ef10ec4ebbee058ce0bb38c954a0a3a6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 12:41:26 -0600 Subject: update changelogs for Debian build --- ChangeLog | 648 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 86 ++++++++ 2 files changed, 734 insertions(+) diff --git a/ChangeLog b/ChangeLog index 33986884..c9463ff7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,526 @@ +commit cf65c6b8056c4af7c26b52ec6f9fbd3400cef638 +Merge: 5f2f6a8 ae5eff7 +Author: Bdale Garbee +Date: Fri Aug 27 12:38:25 2010 -0600 + + Merge branch 'bdale' + + Conflicts: + debian/control + +commit ae5eff7bc0b63047737223423009707bedcb00f5 +Author: Bdale Garbee +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 +Date: Fri Aug 27 12:25:20 2010 -0600 + + fix man page delivery path + +commit a8dbe082960dc9bdd44c6e4b1198423c4e566029 +Author: Bdale Garbee +Date: Fri Aug 27 12:18:28 2010 -0600 + + install altosui man page + +commit 5cc933039e4763b8675611c63b6147b42878a2bb +Author: Bdale Garbee +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 +Date: Fri Aug 27 12:06:01 2010 -0600 + + update Debian standards version + +commit c280071b7db4e9a7af31dc5740eb8d27f137950e +Author: Bdale Garbee +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 +Date: Fri Aug 27 11:00:31 2010 -0700 + + Merge remote branch 'origin/master' into new-packet-format + +commit 63bd34cd1b5a411489e8c3ab377f0fe0eec11f67 +Author: Keith Packard +Date: Fri Aug 27 10:58:55 2010 -0700 + + altosui: add elevation and range information + + Signed-off-by: Keith Packard + +commit 72a18502e40f55cbba6418dc94315517881cd411 +Author: Bdale Garbee +Date: Fri Aug 27 11:51:24 2010 -0600 + + add an install target for altosui + +commit 72c33a72ee105ec692dad62d6d9c1ad40b89bfe8 +Author: Bdale Garbee +Date: Fri Aug 27 11:45:19 2010 -0600 + + add install target for libaltos + +commit a21b6bb60ac1c07ebd161534a4ea63bfde50dcdf +Author: Bdale Garbee +Date: Fri Aug 27 11:26:29 2010 -0600 + + lose the prebuild hook for now while I'm fumbling + +commit 9ea94411c9730f7a271366d309ab4827beeeb839 +Author: Bdale Garbee +Date: Fri Aug 27 11:17:54 2010 -0600 + + add a dummy install target + +commit c443f43f8dee6e0fcbcecf9d09e948fd928b7af4 +Merge: 2950431 2923cf5 +Author: Bdale Garbee +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 +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 + +commit 68967157cee620ebedcc8c2ffd6fc7656532087b +Author: Keith Packard +Date: Thu Aug 26 23:55:44 2010 -0700 + + altosui: command line args are converted to csv format + + Signed-off-by: Keith Packard + +commit 7e0506dc2014b7178f52b950e8c1cb820b35f9c6 +Author: Keith Packard +Date: Thu Aug 26 23:54:53 2010 -0700 + + altosui: Remove debug printf from AltosState.java + + Signed-off-by: Keith Packard + +commit 49364608b59de7421ab00d87d2685bc3b5f58411 +Author: Keith Packard +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 + +commit a16db143fc7ca72dc91e7989420049192114642d +Author: Keith Packard +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 + +commit 0942912163255523d923140c01afbdb5da1c19b5 +Author: Keith Packard +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 + +commit e383595cd281687de903fb6176564bbef270cb83 +Author: Keith Packard +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 + +commit 651f6102ac79459fc8d5679d852c963dcb5bb3fc +Author: Keith Packard +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 + +commit 3dc67c1401976d6e9e2e942d5a4707a4810a0404 +Author: Keith Packard +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 + +commit f0fd423d0bf83bc5c3f9d39e9c09397fbe8caed2 +Author: Keith Packard +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 + +commit 68b2b66d7574dfd0bd5e3571b8ffad32ca5d2b73 +Author: Keith Packard +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 + +commit aa6c27df5db6bdae59d00affccb891854a6caa18 +Author: Keith Packard +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 + +commit 34055129b4008f6a9833887b12dee39ffa408002 +Author: Keith Packard +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 + +commit 99400fdc0f19ef538fc362dde5c3ab5b7cdac409 +Author: Keith Packard +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 + +commit ba086cc77273efe5397f60dcaccd1e3771441481 +Author: Keith Packard +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 + +commit 220f3afdaa432c65f8ad45be7cdbe5c8a3616db3 +Author: Keith Packard +Date: Tue Aug 24 04:01:47 2010 -0700 + + altosui: always display romconfig ui while flashing + +commit f62b2aa08ebfd912b3c732397d43ff9f6162ec88 +Author: Keith Packard +Date: Tue Aug 24 04:01:14 2010 -0700 + + altosui: fetch existing romconfig for flashing + +commit d93787284c8e514a929edb9f944c98ae0206a33f +Author: Keith Packard +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 + +commit 7d44cbd621d2b113ac2b802ef17e3d8a660ce7f2 +Author: Keith Packard +Date: Tue Aug 24 03:58:00 2010 -0700 + + altosui: disable radio monitoring while using serial line for debugging + +commit 7bd220dfd9b3fb0e42eb90c3b37eb7b4169eb21b +Author: Keith Packard +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 + +commit 634a550149e7c344a22a637ba484f115592b1018 +Author: Keith Packard +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 + +commit a55b132668a819cc26478a609cb79bd9190deb9d +Author: Keith Packard +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 + +commit 295043112ccde35092945c286596f9045ee6fa05 +Merge: 2007288 ef8376c +Author: Bdale Garbee +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 +Date: Mon Aug 23 22:08:30 2010 -0700 + + altosui: make default Manifest look for built-in freetts + +commit 56b906f535ac2f86bcab71addbbcd376d74f6a73 +Author: Keith Packard +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 + +commit 4c0c099716197ef7539be0cf55bbb164f6804958 +Author: Keith Packard +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 + +commit bd2b44ddd61fadd8bf8ee6bf783ce019b1be7cc0 +Author: Keith Packard +Date: Mon Aug 23 22:01:38 2010 -0700 + + altosui: Remove debug printf from AltosRomconfig + +commit c3f57ffdb6c74de90d982eacd604e658ce9b00a5 +Author: Keith Packard +Date: Mon Aug 23 22:01:11 2010 -0700 + + altosui: flush serial output before waiting for reply + +commit 8857ac5e43eac6db8d5594b8864df497a712242b +Author: Keith Packard +Date: Mon Aug 23 22:00:16 2010 -0700 + + altosui: remove debug printf from AltosHexfile + +commit b1758be01397fd49c441f40852f3558fe9343a2d +Author: Keith Packard +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 + +commit f9e80f39bc39e5882bfe75f959b6501cb3277cd2 +Author: Keith Packard +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 +Date: Mon Aug 23 21:54:47 2010 -0700 + + altosui: pad TM config dialog values to avoid clipping descenders + +commit b8519b8669ff54741dd738ac343fbd2424451247 +Author: Keith Packard +Date: Mon Aug 23 21:53:37 2010 -0700 + + ao-dumplog: Fix --remote and --channel options to actually work + +commit ebeb13688a9a5442c838641ede6ba0dc92c9a1a4 +Author: Keith Packard +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 + +commit 7f8d7978606abe544b1b9b6065c5480ed813b8ec +Author: Keith Packard +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 + +commit 2007288da8a83e3aa925e11cc196f1c65aab2e5c +Author: Bdale Garbee +Date: Thu Aug 5 15:00:15 2010 -0400 + + working on java packaging details + +commit 44b26dd550eef789e70082ccaa46d7d430c67bce +Author: Bdale Garbee +Date: Thu Aug 5 15:15:04 2010 -0400 + + add freetts as a build dep + +commit 0e17853c08f77debef3e8cf82e9cdb6a5079fc9b +Author: Keith Packard +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 + +commit 953bc3438b10b21f3d65d292356c4ab2de23cddd +Author: Keith Packard +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 + +commit e1463d8e265dfd42c824d90088cd2a51b4cf8131 +Author: Keith Packard +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 + +commit 09252ec22d58e946494e4ca2cf367bf3bbe1cc50 +Author: Keith Packard +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 + +commit 22800dc094797e1e0ad99124198809d0360f7556 +Author: Keith Packard +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 + +commit d14c96663a1027164fa30ed89b53f5a9d3fdb82b +Author: Keith Packard +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 + +commit 9d1b27fa147fc8b765d5be165ebef7ee0f85bd37 +Author: Bdale Garbee +Date: Wed Aug 11 22:11:50 2010 -0400 + + update changelogs for Debian build + commit b6da90b4627dde1fe88240c38c51559d8f781dd0 Author: Bdale Garbee Date: Wed Aug 11 17:15:39 2010 -0400 @@ -16,6 +539,55 @@ Date: Wed Aug 11 08:36:59 2010 -0400 update changelogs for Debian build +commit 294d9c7db21eaf1e71504dbcca5040371abcce55 +Author: Keith Packard +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 + +commit f317f1324b69b4241f4bb192e164b33d712d5a43 +Author: Keith Packard +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 + +commit 4738cb2fc639adb1d9237e6c903479f0690dd81a +Author: Keith Packard +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 + +commit b7699a5907e64bc7547fcc27e73f4a35bbaabfff +Author: Keith Packard +Date: Fri Aug 6 13:09:21 2010 -0400 + + altosui: Add comments to Eeprom reader + +commit 0e917f3ff822616adb147517ac961422e5fedbfd +Author: Keith Packard +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 + commit a0a9b445a4d379730b67720f8d7b682d5206a582 Author: Bdale Garbee Date: Thu Aug 5 15:16:48 2010 -0400 @@ -52,12 +624,88 @@ Date: Thu Aug 5 15:00:15 2010 -0400 working on java packaging details +commit d8bf05f7ad55964c9bce0551e58f4ef6c9f721ad +Author: Keith Packard +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 + +commit 85a670b5a904d6750d0f179ae307baeb8fc7cbd2 +Author: Keith Packard +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 + commit 02f17f2cd26189e2676a9dc0d86bd959ed0bc3f4 Author: Bdale Garbee Date: Thu Aug 5 00:54:05 2010 -0400 move to science menu +commit 9e8f7f75442303f9bfa99a0435984f5d36863ae6 +Author: Keith Packard +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 + +commit 9c9b35254c693b3ade42b24d1e29eaf31e6ba2aa +Author: Keith Packard +Date: Sat Jul 31 10:24:56 2010 -0700 + + altosui: Clear displayed data rows as needed. + + Signed-off-by: Keith Packard + +commit 88e0137a60d7a13ddb7781befa76650e13ad44ae +Author: Keith Packard +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 + +commit 1c3b2fe357d6acf28f48aeddd91693f10381be51 +Author: Keith Packard +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 + +commit e286eb61ad2a90746c1c31f95d26d5edb48738d3 +Author: Keith Packard +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 + commit e3a9e3815db3f290e28b40ae02aa654f515cfc37 Author: Bdale Garbee Date: Sat Jul 31 10:55:27 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 6a47c8a7..c2699c88 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,89 @@ +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 Fri, 27 Aug 2010 12:40:04 -0600 + altos (0.6+303+gb6da90b) unstable; urgency=low * add freetts as a build dep -- cgit v1.2.3 From 0bd4cc03b3bf23aa32b5ce1921078021d1d8a9c6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 13:12:46 -0600 Subject: fix path to installed shared library --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 22752d5d..770abcf3 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -96,7 +96,7 @@ endif ifeq ($(OS),Linux) altosui: echo "#!/bin/sh" > $@ - echo "exec java -Djava.library.path=/usr/lib/altos/libaltos -jar /usr/share/java/altosui.jar" >> $@ + echo "exec java -Djava.library.path=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@ chmod +x ./altosui install: altosui.jar altosui -- cgit v1.2.3 From 42055af5c6f17d14a2f1c6a2b5e1ce6d3b45a615 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 13:13:19 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index c9463ff7..84f2e113 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 0bd4cc03b3bf23aa32b5ce1921078021d1d8a9c6 +Author: Bdale Garbee +Date: Fri Aug 27 13:12:46 2010 -0600 + + fix path to installed shared library + +commit 99c1d9b4ef10ec4ebbee058ce0bb38c954a0a3a6 +Author: Bdale Garbee +Date: Fri Aug 27 12:41:26 2010 -0600 + + update changelogs for Debian build + commit cf65c6b8056c4af7c26b52ec6f9fbd3400cef638 Merge: 5f2f6a8 ae5eff7 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index c2699c88..4b45bb7b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.6+375+g0bd4cc0) unstable; urgency=low + + * fix path to installed shared library + + -- Bdale Garbee Fri, 27 Aug 2010 13:13:14 -0600 + altos (0.6+373+gcf65c6b) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 4c5c7c7f198775c398c1ad2edafb3488384cc297 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 22:13:38 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 84f2e113..cf57e427 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 42055af5c6f17d14a2f1c6a2b5e1ce6d3b45a615 +Author: Bdale Garbee +Date: Fri Aug 27 13:13:19 2010 -0600 + + update changelogs for Debian build + commit 0bd4cc03b3bf23aa32b5ce1921078021d1d8a9c6 Author: Bdale Garbee Date: Fri Aug 27 13:12:46 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 4b45bb7b..7ee6add0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.7+18+g42055af) unstable; urgency=low + + * rebuilding to pick up tag 0.7 + + -- Bdale Garbee Fri, 27 Aug 2010 22:12:48 -0600 + altos (0.6+375+g0bd4cc0) unstable; urgency=low * fix path to installed shared library -- cgit v1.2.3 From 1cda15fdef2d9d3e54354bd5c43a0bcc7e3240cb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 22:24:51 -0600 Subject: fix up for an 0.7 release --- debian/changelog | 6 ------ 1 file changed, 6 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7ee6add0..4b45bb7b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,3 @@ -altos (0.7+18+g42055af) unstable; urgency=low - - * rebuilding to pick up tag 0.7 - - -- Bdale Garbee Fri, 27 Aug 2010 22:12:48 -0600 - altos (0.6+375+g0bd4cc0) unstable; urgency=low * fix path to installed shared library -- cgit v1.2.3 From 236685807b63860ad033aa0254ce8f6d8d36d4ef Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 27 Aug 2010 22:26:09 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/ChangeLog b/ChangeLog index cf57e427..dd78087c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 1cda15fdef2d9d3e54354bd5c43a0bcc7e3240cb +Author: Bdale Garbee +Date: Fri Aug 27 22:24:51 2010 -0600 + + fix up for an 0.7 release + +commit 4c5c7c7f198775c398c1ad2edafb3488384cc297 +Author: Bdale Garbee +Date: Fri Aug 27 22:13:38 2010 -0600 + + update changelogs for Debian build + commit 42055af5c6f17d14a2f1c6a2b5e1ce6d3b45a615 Author: Bdale Garbee Date: Fri Aug 27 13:13:19 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 4b45bb7b..022a05be 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.7) unstable; urgency=low + + * update changelogs for Debian build + * fix up for an 0.7 release + + -- Bdale Garbee Fri, 27 Aug 2010 22:25:38 -0600 + altos (0.6+375+g0bd4cc0) unstable; urgency=low * fix path to installed shared library -- cgit v1.2.3 From edcfb1bdf64772d3b83405ccf99385b8fea5d8e4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 17:33:59 -0700 Subject: libaltos: AltusMetrum devices use more than one USB ID. List all usb devices, picking those with AltusMetrum IDs. Signed-off-by: Keith Packard --- ao-tools/libaltos/libaltos.c | 45 +++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index ffdb2366..93c483d1 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -391,24 +391,40 @@ get_string(io_object_t object, CFStringRef entry, char *result, int result_len) 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; } @@ -423,8 +439,15 @@ altos_list_next(struct altos_list *list, struct altos_device *device) 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; -- cgit v1.2.3 From ae02b1590439d5c8dfb472cf1f83a14fdcfbaf11 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 21:36:47 -0700 Subject: 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 --- ao-tools/altosui/AltosConfig.java | 6 +-- ao-tools/altosui/AltosDebug.java | 8 ++-- ao-tools/altosui/AltosEepromDownload.java | 5 ++- ao-tools/altosui/AltosSerial.java | 62 ++++++++++++++++++++----------- 4 files changed, 50 insertions(+), 31 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index ac73e7c5..3d970748 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -122,17 +122,17 @@ public class AltosConfig implements Runnable, ActionListener { 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(); } } diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index ca2e5a90..3f469d48 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -62,8 +62,8 @@ public class AltosDebug extends AltosSerial { void ensure_debug_mode() { if (!debug_mode) { - printf("m 0\nD\n"); - flush_reply(); + printf("D\n"); + flush_input(); debug_mode = true; } } @@ -103,7 +103,7 @@ public class AltosDebug extends AltosSerial { throws IOException, InterruptedException { byte[] data = new byte[length]; - flush_reply(); + flush_input(); ensure_debug_mode(); printf("I %x %x\n", length, address); int i = 0; @@ -155,7 +155,7 @@ public class AltosDebug extends AltosSerial { public byte[] read_bytes(int length) throws IOException, InterruptedException { - flush_reply(); + flush_input(); ensure_debug_mode(); printf("G %x\n", length); int i = 0; diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 02a71118..5e43345b 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -223,10 +223,10 @@ public class AltosEepromDownload implements Runnable { 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); @@ -247,6 +247,7 @@ public class AltosEepromDownload implements Runnable { if (remote) serial_line.printf("~"); monitor.done(); + serial_line.flush_output(); serial_line.close(); } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 5b47960f..99ba3324 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -47,6 +47,7 @@ public class AltosSerial implements Runnable { String line; byte[] line_bytes; int line_count; + boolean monitor_mode; public void run () { int c; @@ -99,35 +100,39 @@ public class AltosSerial implements Runnable { } } - public void flush_reply() { + public void flush_output() { libaltos.altos_flush(altos); + } + + public void flush_input() { + flush_output(); try { - Thread.sleep(100); + Thread.sleep(200); } catch (InterruptedException ie) { } - reply_queue.clear(); + synchronized(this) { + if (!"VERSION".startsWith(line) && + !line.startsWith("VERSION")) + line = ""; + reply_queue.clear(); + } } public String get_reply() throws InterruptedException { - libaltos.altos_flush(altos); + flush_output(); String line = reply_queue.take(); return line; } public void add_monitor(LinkedBlockingQueue q) { + set_monitor(true); monitors.add(q); } public void remove_monitor(LinkedBlockingQueue 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() { @@ -135,8 +140,9 @@ public class AltosSerial implements Runnable { } public void close() { - if (altos != null) + if (altos != null) { libaltos.altos_close(altos); + } if (input_thread != null) { try { input_thread.interrupt(); @@ -157,7 +163,7 @@ public class AltosSerial implements Runnable { } public void print(String data) { -//h System.out.printf("\"%s\" ", data); +// System.out.printf("\"%s\" ", data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } @@ -173,17 +179,28 @@ public class AltosSerial implements Runnable { 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"); + set_monitor(monitor_mode); + flush_input(); } 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); + } + } + + void set_monitor(boolean monitor) { + monitor_mode = monitor; + if (altos != null) { + if (monitor) + printf("m 1\n"); + else + printf("m 0\n"); + } } public void set_callsign(String callsign) { @@ -195,6 +212,7 @@ public class AltosSerial implements Runnable { altos = null; input_thread = null; line = ""; + monitor_mode = false; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); } -- cgit v1.2.3 From e60c59123232915e808cee23ef89eb1a38ced34b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 21:40:21 -0700 Subject: 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 --- ao-tools/altosui/AltosEepromDownload.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 5e43345b..6dbbd3eb 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -142,6 +142,7 @@ public class AltosEepromDownload implements Runnable { 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]); -- cgit v1.2.3 From b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 21:41:40 -0700 Subject: 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 --- ao-tools/libaltos/libaltos.c | 134 +++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 48 deletions(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 93c483d1..65cd6c1a 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -21,6 +21,8 @@ #include #include +#define USE_POLL + PUBLIC int altos_init(void) { @@ -33,6 +35,9 @@ altos_fini(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) @@ -471,20 +476,21 @@ altos_list_finish(struct altos_list *list) #include #include #include -#include #define USB_BUF_SIZE 64 struct altos_file { int fd; +#ifdef USE_POLL int pipe[2]; +#else + int out_fd; +#endif unsigned char out_data[USB_BUF_SIZE]; int out_used; unsigned char in_data[USB_BUF_SIZE]; int in_used; int in_read; - pthread_mutex_t putc_mutex; - pthread_mutex_t getc_mutex; }; struct altos_file * @@ -497,32 +503,54 @@ altos_open(struct altos_device *device) if (!file) return NULL; - pipe(file->pipe); + printf("open %s\n", device->path); file->fd = open(device->path, O_RDWR | O_NOCTTY); + printf("opened %d\n", file->fd); if (file->fd < 0) { perror(device->path); 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; } - pthread_mutex_init(&file->putc_mutex,NULL); - pthread_mutex_init(&file->getc_mutex,NULL); + printf("running %d\n", file->fd); return file; } @@ -532,7 +560,13 @@ altos_close(struct altos_file *file) if (file->fd != -1) { int fd = file->fd; file->fd = -1; +#ifdef USE_POLL write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + printf("close %d\n", fd); close(fd); } } @@ -544,16 +578,20 @@ altos_free(struct altos_file *file) free(file); } -static int -_altos_flush(struct altos_file *file) +int +altos_flush(struct altos_file *file) { while (file->out_used) { int ret; if (file->fd < 0) return -EBADF; - fflush(stdout); + printf("write %d\n", file->out_used); +#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) { @@ -562,6 +600,7 @@ _altos_flush(struct altos_file *file) file->out_used -= ret; } } + return 0; } int @@ -569,79 +608,81 @@ altos_putchar(struct altos_file *file, char c) { int ret; - pthread_mutex_lock(&file->putc_mutex); if (file->out_used == USB_BUF_SIZE) { - ret = _altos_flush(file); + ret = altos_flush(file); if (ret) { - pthread_mutex_unlock(&file->putc_mutex); return ret; } } file->out_data[file->out_used++] = c; ret = 0; if (file->out_used == USB_BUF_SIZE) - ret = _altos_flush(file); - pthread_mutex_unlock(&file->putc_mutex); + ret = altos_flush(file); return 0; } -int -altos_flush(struct altos_file *file) -{ - int ret; - pthread_mutex_lock(&file->putc_mutex); - ret = _altos_flush(file); - pthread_mutex_unlock(&file->putc_mutex); - return ret; -} - - +#ifdef USE_POLL #include +#endif int -altos_getchar(struct altos_file *file, int timeout) +altos_fill(struct altos_file *file, int timeout) { int ret; +#ifdef USE_POLL struct pollfd fd[2]; +#endif if (timeout == 0) timeout = -1; - pthread_mutex_lock(&file->getc_mutex); - fd[0].fd = file->fd; - fd[0].events = POLLIN; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; while (file->in_read == file->in_used) { - if (file->fd < 0) { - pthread_mutex_unlock(&file->getc_mutex); + if (file->fd < 0) return LIBALTOS_ERROR; - } - altos_flush(file); - +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; ret = poll(fd, 2, timeout); if (ret < 0) { perror("altos_getchar"); - pthread_mutex_unlock(&file->getc_mutex); return LIBALTOS_ERROR; } - if (ret == 0) { - pthread_mutex_unlock(&file->getc_mutex); + if (ret == 0) return LIBALTOS_TIMEOUT; - } - if (fd[0].revents & POLLIN) { + if (fd[0].revents & POLLIN) +#endif + { ret = read(file->fd, file->in_data, USB_BUF_SIZE); + if (ret) + printf("read %d\n", ret); if (ret < 0) { perror("altos_getchar"); - pthread_mutex_unlock(&file->getc_mutex); return LIBALTOS_ERROR; } file->in_read = 0; file->in_used = ret; +#ifndef USE_POLL + if (ret == 0 && timeout > 0) + return LIBALTOS_TIMEOUT; +#endif } } - ret = file->in_data[file->in_read++]; - pthread_mutex_unlock(&file->getc_mutex); - return ret; + return 0; +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; } #endif /* POSIX_TTY */ @@ -919,9 +960,6 @@ altos_getchar(struct altos_file *file, int timeout) { 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); -- cgit v1.2.3 From 6527357d1f0e94faf9e7dacac10a39875131be7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 21:43:46 -0700 Subject: libaltos: Missing OS_LDFLAGS on cjnitest build --- ao-tools/libaltos/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index cd96fd5f..f336f22f 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -96,8 +96,8 @@ SRCS = libaltos.c $(SWIG_WRAP) OBJS = $(SRCS:%.c=%.o) LIBS = $(DARWIN_LIBS) -$(CJNITEST): cjnitest.o $(OBJS) - cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBS) +$(CJNITEST): cjnitest.o $(LIBNAME) + cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBNAME) $(LIBS) $(OS_LDFLAGS) $(LIBNAME): $(OBJS) gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) -- cgit v1.2.3 From 1acd3c7ec167b1b18e4ea493e5978c938a91cc89 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 21:45:19 -0700 Subject: libaltos: cjnitest needs altos_flush now --- ao-tools/libaltos/cjnitest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c index 93d1f376..c6d6e069 100644 --- a/ao-tools/libaltos/cjnitest.c +++ b/ao-tools/libaltos/cjnitest.c @@ -30,6 +30,7 @@ main () continue; } altos_puts(file,"v\nc s\n"); + altos_flush(file); while ((c = altos_getchar(file, 100)) >= 0) { putchar (c); } -- cgit v1.2.3 From c4a8569f61eddf690d00337543462235ecbfbe54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 22:41:18 -0700 Subject: 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 --- src/ao_packet_master.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 72bb908a..5e13a91a 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -121,6 +121,10 @@ ao_packet_forward(void) __reentrant 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) { -- cgit v1.2.3 From 43619c13f749b79c096d1e8fdab3d5cfb5fd85f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 22:42:23 -0700 Subject: 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 --- src/ao_packet_master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5e13a91a..50f5aeff 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -126,8 +126,8 @@ ao_packet_forward(void) __reentrant 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_radio_abort(); ao_wake_task(&ao_packet_echo_task); ao_wake_task(&ao_packet_task); ao_yield(); -- cgit v1.2.3 From 63c832394a829f41b8f77d075786530536360349 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 23:22:27 -0700 Subject: 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 --- src/ao_packet_master.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 50f5aeff..641b49f4 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -29,6 +29,8 @@ ao_packet_getchar(void) __critical ao_wake_task(&ao_packet_task); ao_usb_flush(); ao_sleep(&ao_stdin_ready); + if (!ao_packet_enable) + break; } return c; } @@ -127,10 +129,9 @@ ao_packet_forward(void) __reentrant ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_abort(); - 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)); } } -- cgit v1.2.3 From dd5374b8e660012ae4f8b058454fd101e0749ca7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 02:00:30 -0700 Subject: libaltos: Fix windows build. Need stdlib.h to get calloc/free defined, remove debug printfs, fix serial timeouts. Signed-off-by: Keith Packard --- ao-tools/libaltos/libaltos.c | 108 ++++++++++++++++++++----------------------- ao-tools/libaltos/libaltos.h | 2 + 2 files changed, 51 insertions(+), 59 deletions(-) diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 65cd6c1a..1d3b26dd 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -15,7 +15,6 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#define BUILD_DLL #include "libaltos.h" #include #include @@ -503,9 +502,7 @@ altos_open(struct altos_device *device) if (!file) return NULL; - printf("open %s\n", device->path); file->fd = open(device->path, O_RDWR | O_NOCTTY); - printf("opened %d\n", file->fd); if (file->fd < 0) { perror(device->path); free(file); @@ -550,7 +547,6 @@ altos_open(struct altos_device *device) free(file); return NULL; } - printf("running %d\n", file->fd); return file; } @@ -566,7 +562,6 @@ altos_close(struct altos_file *file) close(file->out_fd); file->out_fd = -1; #endif - printf("close %d\n", fd); close(fd); } } @@ -586,7 +581,6 @@ altos_flush(struct altos_file *file) if (file->fd < 0) return -EBADF; - printf("write %d\n", file->out_used); #ifdef USE_POLL ret = write (file->fd, file->out_data, file->out_used); #else @@ -654,8 +648,6 @@ altos_fill(struct altos_file *file, int timeout) #endif { ret = read(file->fd, file->in_data, USB_BUF_SIZE); - if (ret) - printf("read %d\n", ret); if (ret < 0) { perror("altos_getchar"); return LIBALTOS_ERROR; @@ -689,6 +681,7 @@ altos_getchar(struct altos_file *file, int timeout) #ifdef WINDOWS +#include #include #include @@ -708,7 +701,6 @@ struct altos_file { int in_read; }; - PUBLIC struct altos_list * altos_list_start(void) { @@ -733,15 +725,15 @@ altos_list_next(struct altos_list *list, struct altos_device *device) 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, @@ -775,8 +767,6 @@ altos_list_next(struct altos_list *list, struct altos_device *device) 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; } @@ -791,33 +781,26 @@ altos_list_next(struct altos_list *list, struct altos_device *device) 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(); @@ -844,31 +827,32 @@ altos_fill(struct altos_file *file, int timeout) return LIBALTOS_SUCCESS; file->in_read = file->in_used = 0; - if (timeout) { - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; + if (timeout) timeouts.ReadTotalTimeoutConstant = timeout; - } else { - timeouts.ReadIntervalTimeout = 0; - timeouts.ReadTotalTimeoutMultiplier = 0; - timeouts.ReadTotalTimeoutConstant = 0; - } + else + timeouts.ReadTotalTimeoutConstant = 1000; + + timeouts.ReadIntervalTimeout = MAXDWORD; + timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutConstant = 0; - if (!SetCommTimeouts(file->handle, &timeouts)) { + if (!SetCommTimeouts(file->handle, &timeouts)) printf("SetCommTimeouts failed %d\n", GetLastError()); - } - if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) { - result = GetLastError(); - printf ("read failed %d\n", result); - return LIBALTOS_ERROR; - got = 0; + for (;;) { + if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) { + result = GetLastError(); + return LIBALTOS_ERROR; + got = 0; + } + file->in_read = 0; + file->in_used = got; + if (got) + return LIBALTOS_SUCCESS; + if (timeout) + return LIBALTOS_TIMEOUT; } - if (got) - return LIBALTOS_SUCCESS; - return LIBALTOS_TIMEOUT; } PUBLIC int @@ -882,7 +866,6 @@ altos_flush(struct altos_file *file) while (used) { if (!WriteFile(file->handle, data, used, &put, NULL)) { result = GetLastError(); - printf ("write failed %d\n", result); return LIBALTOS_ERROR; } data += put; @@ -895,8 +878,9 @@ altos_flush(struct altos_file *file) 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}; if (!file) return NULL; @@ -910,14 +894,20 @@ altos_open(struct altos_device *device) free(file); return NULL; } - - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; - timeouts.ReadTotalTimeoutConstant = 100; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 10000; - if (!SetCommTimeouts(file->handle, &timeouts)) { - printf("SetCommTimeouts failed %d\n", GetLastError()); + 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; diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h index fe2c483c..6e94899e 100644 --- a/ao-tools/libaltos/libaltos.h +++ b/ao-tools/libaltos/libaltos.h @@ -18,6 +18,8 @@ #ifndef _LIBALTOS_H_ #define _LIBALTOS_H_ +#include + #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) # ifndef BUILD_STATIC # ifdef BUILD_DLL -- cgit v1.2.3 From df34bbe7d1c43b12ab6d610fe810b6e1683e4c21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 02:49:49 -0700 Subject: 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 --- ao-tools/libaltos/Makefile | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index f336f22f..201cf8e2 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -7,16 +7,14 @@ ifeq ($(OS),Linux) JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include -OS_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) +OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) + +OS_APP_CFLAGS=$(OS_LIB_CFLAGS) OS_LDFLAGS= LIBNAME=libaltos.so EXEEXT= - -install: $(LIBNAME) - /usr/bin/install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) - endif # @@ -24,12 +22,13 @@ endif # ifeq ($(OS),Darwin) -OS_CFLAGS=\ +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 @@ -46,7 +45,8 @@ ifneq (,$(findstring MINGW,$(OS))) CC=gcc -OS_CFLAGS = -DWINDOWS -mconsole +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 @@ -87,7 +87,7 @@ all: $(LIBNAME) $(CJNITEST) $(CLASSFILES) .java.class: javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java -CFLAGS=$(OS_CFLAGS) -O0 -g -I. +CFLAGS=$(OS_LIB_CFLAGS) -O -I. LDFLAGS=$(OS_LDFLAGS) @@ -96,11 +96,11 @@ SRCS = libaltos.c $(SWIG_WRAP) OBJS = $(SRCS:%.c=%.o) LIBS = $(DARWIN_LIBS) -$(CJNITEST): cjnitest.o $(LIBNAME) - cc -o $@ $(CFLAGS) cjnitest.o $(OBJS) $(LIBNAME) $(LIBS) $(OS_LDFLAGS) +$(CJNITEST): cjnitest.c $(LIBNAME) + $(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS) $(LIBNAME): $(OBJS) - gcc -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) + $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS) clean: rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o @@ -114,3 +114,11 @@ $(JNI_FILE): libaltos.i0 $(HEADERS) cp swig_bindings/java/*.java libaltosJNI $(SWIG_WRAP): $(JNI_FILE) + +ifeq ($(OS),Linux) +install: $(LIBNAME) + /usr/bin/install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) + +endif + +.NOTPARALLEL: -- cgit v1.2.3 From 5d48c494325524bbeed10e0dc7300ed44e7e208e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 02:53:26 -0700 Subject: 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 --- telemetrum.inf | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/telemetrum.inf b/telemetrum.inf index 8a12b857..0a81084b 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -12,23 +12,38 @@ DriverVer = 08/05/2010,3.1.0.41 %Mfg% = Models, NTx86, NTamd64, NTia64 [Models.NTx86] -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B +%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C +%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D [Models.NTamd64] %TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B +%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C +%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D [Models.NTia64] %TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B +%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C +%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D [DestinationDirs] DefaultDestDir=12 [ControlFlags] ExcludeFromSelect=USB\VID_FFFE&PID_000A +ExcludeFromSelect=USB\VID_FFFE&PID_000B +ExcludeFromSelect=USB\VID_FFFE&PID_000C +ExcludeFromSelect=USB\VID_FFFE&PID_000D [Strings] Mfg = "altusmetrum.org" -TeleMetrum = "TeleMetrum/TeleDongle" +AltusMetrum = "Unknown AltusMetrum Device" +TeleMetrum = "TeleMetrum" +TeleDongle = "TeleDongle" +TeleTerra = "TeleTerra" ;---------------------------------------------------------------------------- -- cgit v1.2.3 From 0300fe581c949232bc52b05fe9c1f6032cad6b60 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 02:56:25 -0700 Subject: libaltos: Add pre-built Mac OS X libaltos.dylib This allows the mac bits to be built on Linux. Signed-off-by: Keith Packard --- ao-tools/libaltos/libaltos.dylib | Bin 0 -> 54176 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 ao-tools/libaltos/libaltos.dylib diff --git a/ao-tools/libaltos/libaltos.dylib b/ao-tools/libaltos/libaltos.dylib new file mode 100755 index 00000000..89aa12e7 Binary files /dev/null and b/ao-tools/libaltos/libaltos.dylib differ -- cgit v1.2.3 From 20a472cfe3369200150ea4ff067ceb28968dbcac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 02:58:23 -0700 Subject: libaltos: Add pre-built Windows .dll This lets us create the windows distribution on Linux. Signed-off-by: Keith Packard --- ao-tools/libaltos/altos.dll | Bin 0 -> 30550 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100755 ao-tools/libaltos/altos.dll diff --git a/ao-tools/libaltos/altos.dll b/ao-tools/libaltos/altos.dll new file mode 100755 index 00000000..f40181e8 Binary files /dev/null and b/ao-tools/libaltos/altos.dll differ -- cgit v1.2.3 From c7ba92317ac55272acbde12416448ebd17b983a6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 04:52:00 -0700 Subject: 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 --- src/ao_usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ao_usb.c b/src/ao_usb.c index b55130f2..b4e3f1fe 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -383,8 +383,11 @@ ao_usb_pollchar(void) __critical 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]; -- cgit v1.2.3 From 35d9a8214252dbe79aeb69ae47d2e5c58a654702 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 05:27:45 -0700 Subject: libaltos: Use overlapped I/O on windows Otherwise, reads block writes and vice-versa. Crazy stuff. Signed-off-by: Keith Packard --- ao-tools/libaltos/altos.dll | Bin 30550 -> 31765 bytes ao-tools/libaltos/libaltos.c | 127 ++++++++++++++++++++++++++++++------------- 2 files changed, 90 insertions(+), 37 deletions(-) diff --git a/ao-tools/libaltos/altos.dll b/ao-tools/libaltos/altos.dll index f40181e8..28e9b4ad 100755 Binary files a/ao-tools/libaltos/altos.dll and b/ao-tools/libaltos/altos.dll differ diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 1d3b26dd..059d2ae9 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -492,7 +492,7 @@ struct altos_file { 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); @@ -550,7 +550,7 @@ altos_open(struct altos_device *device) return file; } -void +PUBLIC void altos_close(struct altos_file *file) { if (file->fd != -1) { @@ -566,14 +566,14 @@ altos_close(struct altos_file *file) } } -void +PUBLIC void altos_free(struct altos_file *file) { altos_close(file); free(file); } -int +PUBLIC int altos_flush(struct altos_file *file) { while (file->out_used) { @@ -597,7 +597,7 @@ altos_flush(struct altos_file *file) return 0; } -int +PUBLIC int altos_putchar(struct altos_file *file, char c) { int ret; @@ -619,7 +619,7 @@ altos_putchar(struct altos_file *file, char c) #include #endif -int +static int altos_fill(struct altos_file *file, int timeout) { int ret; @@ -663,7 +663,7 @@ altos_fill(struct altos_file *file, int timeout) return 0; } -int +PUBLIC int altos_getchar(struct altos_file *file, int timeout) { int ret; @@ -699,6 +699,9 @@ struct altos_file { 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 * @@ -817,42 +820,72 @@ altos_list_finish(struct altos_list *list) } 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.ReadTotalTimeoutConstant = timeout; - else - timeouts.ReadTotalTimeoutConstant = 1000; + 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 { + file->pend_read = FALSE; + file->in_read = 0; + file->in_used = got; + } + return LIBALTOS_SUCCESS; +} - timeouts.ReadIntervalTimeout = MAXDWORD; - timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; - timeouts.WriteTotalTimeoutMultiplier = 0; - timeouts.WriteTotalTimeoutConstant = 0; +static int +altos_wait_read(struct altos_file *file, int timeout) +{ + DWORD ret; + DWORD got; - if (!SetCommTimeouts(file->handle, &timeouts)) - printf("SetCommTimeouts failed %d\n", GetLastError()); + if (!file->pend_read) + return LIBALTOS_SUCCESS; - for (;;) { - if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, NULL)) { - result = GetLastError(); + 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; - got = 0; - } + file->pend_read = FALSE; file->in_read = 0; file->in_used = got; - if (got) - return LIBALTOS_SUCCESS; - if (timeout) - return LIBALTOS_TIMEOUT; + break; + case WAIT_TIMEOUT: + return LIBALTOS_TIMEOUT; + break; + default: + return LIBALTOS_ERROR; } + return LIBALTOS_SUCCESS; +} + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; + + if (file->in_read < file->in_used) + return LIBALTOS_SUCCESS; + + file->in_read = file->in_used = 0; + + ret = altos_queue_read(file); + if (ret) + return ret; + ret = altos_wait_read(file, timeout); + if (ret) + return ret; + + return LIBALTOS_SUCCESS; } PUBLIC int @@ -861,12 +894,21 @@ altos_flush(struct altos_file *file) 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(); - 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; @@ -881,6 +923,7 @@ altos_open(struct altos_device *device) struct altos_file *file = calloc (1, sizeof (struct altos_file)); char full_name[64]; DCB dcbSerialParams = {0}; + COMMTIMEOUTS timeouts; if (!file) return NULL; @@ -889,11 +932,21 @@ altos_open(struct altos_device *device) 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 = 1 << 30; /* almost forever */ + timeouts.WriteTotalTimeoutMultiplier = 0; + timeouts.WriteTotalTimeoutConstant = 0; + SetCommTimeouts(file->handle, &timeouts); + dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(file->handle, &dcbSerialParams)) { CloseHandle(file->handle); -- cgit v1.2.3 From 38ac388baf8125c0644b868a7aaf8eba1bdf990d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 05:28:37 -0700 Subject: altosui: Build linux, mac and windows archives on Linux This adds 'fat' archives for each target OS. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile | 123 +++++++++++++++++++++++++++++++++------------- 1 file changed, 88 insertions(+), 35 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 770abcf3..6514c608 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -39,40 +39,57 @@ CLASSFILES=\ AltosRomconfigUI.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 +# 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) -ifeq ($(OS),Linux) -ALTOSUI_APP=altosui -endif +LINUX_APP=altosui + +DARWIN_ZIP=Altos-Mac.zip + +WINDOWS_ZIP=Altos-Windows.zip -ifeq ($(OS),Darwin) -ALTOSUI_APP=AltosUI.app/Contents/Resources/Java/altosui.jar -endif +LINUX_TGZ=Altos-Linux.tgz -all: altosui.jar $(ALTOSUI_APP) +all: $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) $(CLASSFILES): .java.class: javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui.jar: classes/altosui classes/libaltosJNI $(FREETTSJAR) $(CLASSFILES) Manifest.txt +altosui.jar: classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt cd ./classes && jar cfm ../$@ altosui/Manifest.txt 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 @@ -81,32 +98,68 @@ 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=/usr/lib/altos -jar /usr/share/java/altosui.jar" >> $@ chmod +x ./altosui -install: altosui.jar 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) fat/classes/Manifest.txt + mkdir -p fat/classes + test -L fat/classes/altosui || ln -sf ../.. fat/classes/altosui + test -L fat/classes/libaltosJNI || ln -sf ../../../libaltos/libaltosJNI fat/classes/libaltosJNI + cd ./fat/classes && jar cfm ../../$@ Manifest.txt 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 /usr/bin/install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar /usr/bin/install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1 /usr/bin/install altosui $(DESTDIR)/usr/bin/altosui - -endif clean: rm -f *.class altosui.jar rm -f AltosUI.app/Contents/Resources/Java/* rm -rf classes + rm -rf windows linux + +FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) + +LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui +$(LINUX_TGZ): $(LINUX_FILES) + rm $@ + 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 $@ + 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 -j -r ../$@ AltosUI.app AltOS + +WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf + +$(WINDOWS_ZIP): $(WINDOWS_FILES) + rm $@ + mkdir -p windows/AltOS + rm -f windows/AltOS/* + cp $(WINDOWS_FILES) windows/AltOS + cd windows && zip -j -r ../$@ AltOS -- cgit v1.2.3 From a94900b8862b99b4e317ea0ee3edd2a560f270c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 05:48:23 -0700 Subject: altosui: build debian-style altosui too This adds the dependencies to make sure altosui and altosui.jar get built. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 6514c608..dcaf3ab0 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -76,7 +76,7 @@ WINDOWS_ZIP=Altos-Windows.zip LINUX_TGZ=Altos-Linux.tgz -all: $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) +all: altosui altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) $(CLASSFILES): @@ -88,7 +88,7 @@ altosui.jar: classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt Manifest.txt: Makefile $(CLASSFILES) echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTSLIB)/freetts.jar' >> $@ + echo "Class-Path: $(FREETTSLIB)/freetts.jar" >> $@ classes/altosui: mkdir -p classes -- cgit v1.2.3 From a9a8d23c877e6f6c76857b7c85e3d43b4da1db27 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 05:49:11 -0700 Subject: 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 --- ao-tools/altosui/AltosDevice.java | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 3daf0742..e62a0a7a 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -32,6 +32,7 @@ public class AltosDevice extends altos_device { 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; @@ -58,33 +59,23 @@ public class AltosDevice extends altos_device { 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; } -- cgit v1.2.3 From cbc72399a0f4d7429df0189bcdae683dd491cb9e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 17:56:56 -0600 Subject: continue even if rm's don't have anything to do --- ao-tools/altosui/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index dcaf3ab0..d3b6970f 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -136,7 +136,7 @@ FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui $(LINUX_TGZ): $(LINUX_FILES) - rm $@ + rm -f $@ mkdir -p linux/AltOS rm -f linux/AltOS/* cp $(LINUX_FILES) linux/AltOS @@ -147,7 +147,7 @@ DARWIN_EXTRA=$(HEXFILES) DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA) $(DARWIN_ZIP): $(DARWIN_FILES) - rm $@ + rm -f $@ cp -a AltosUI.app darwin/ mkdir -p darwin/AltosUI.app/Contents/Resources/Java cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java @@ -158,7 +158,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES) WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ZIP): $(WINDOWS_FILES) - rm $@ + rm -f $@ mkdir -p windows/AltOS rm -f windows/AltOS/* cp $(WINDOWS_FILES) windows/AltOS -- cgit v1.2.3 From 81318e5b7179b0311ab099043ecb04a25d763750 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 18:15:40 -0600 Subject: make invocation of 'install' pathless to work on more Unix variants --- ao-tools/altosui/Makefile | 6 +++--- ao-tools/libaltos/Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index d3b6970f..ce627ec0 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -122,9 +122,9 @@ fat/classes/Manifest.txt: $(CLASSFILES) Makefile echo "Class-Path: freetts.jar" >> $@ install: altosui.jar altosui - /usr/bin/install -m 0644 altosui.jar $(DESTDIR)/usr/share/java/altosui.jar - /usr/bin/install -m 0644 altosui.1 $(DESTDIR)/usr/share/man/man1/altosui.1 - /usr/bin/install altosui $(DESTDIR)/usr/bin/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 diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 201cf8e2..77ffa1b4 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -117,7 +117,7 @@ $(SWIG_WRAP): $(JNI_FILE) ifeq ($(OS),Linux) install: $(LIBNAME) - /usr/bin/install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) + install -c $(LIBNAME) $(DESTDIR)/usr/lib/altos/$(LIBNAME) endif -- cgit v1.2.3 From 4790f78aead8a816e5b247c022b2998ce3a94053 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 18:48:50 -0600 Subject: 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 --- .gitattributes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..f929a866 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +ao-tools/libaltos/altos.dll export-ignore +ao-tools/libaltos/libaltos.dylib export-ignore -- cgit v1.2.3 From 25764fcd1b65c3a5a817afdb5901ac30e8a5f0c0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 19:08:29 -0600 Subject: update changelogs for Debian build --- ChangeLog | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 100 +++++++++++++++++++++++ 2 files changed, 336 insertions(+) diff --git a/ChangeLog b/ChangeLog index dd78087c..d1c75a33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,239 @@ +commit 4790f78aead8a816e5b247c022b2998ce3a94053 +Author: Bdale Garbee +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 +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 +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 +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 + +commit a94900b8862b99b4e317ea0ee3edd2a560f270c7 +Author: Keith Packard +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 + +commit 38ac388baf8125c0644b868a7aaf8eba1bdf990d +Author: Keith Packard +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 + +commit 35d9a8214252dbe79aeb69ae47d2e5c58a654702 +Author: Keith Packard +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 + +commit c7ba92317ac55272acbde12416448ebd17b983a6 +Author: Keith Packard +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 + +commit 20a472cfe3369200150ea4ff067ceb28968dbcac +Author: Keith Packard +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 + +commit 0300fe581c949232bc52b05fe9c1f6032cad6b60 +Author: Keith Packard +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 + +commit 5d48c494325524bbeed10e0dc7300ed44e7e208e +Author: Keith Packard +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 + +commit df34bbe7d1c43b12ab6d610fe810b6e1683e4c21 +Author: Keith Packard +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 + +commit dd5374b8e660012ae4f8b058454fd101e0749ca7 +Author: Keith Packard +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 + +commit 63c832394a829f41b8f77d075786530536360349 +Author: Keith Packard +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 + +commit 43619c13f749b79c096d1e8fdab3d5cfb5fd85f1 +Author: Keith Packard +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 + +commit c4a8569f61eddf690d00337543462235ecbfbe54 +Author: Keith Packard +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 + +commit 1acd3c7ec167b1b18e4ea493e5978c938a91cc89 +Author: Keith Packard +Date: Sun Aug 29 21:45:19 2010 -0700 + + libaltos: cjnitest needs altos_flush now + +commit 6527357d1f0e94faf9e7dacac10a39875131be7c +Author: Keith Packard +Date: Sun Aug 29 21:43:46 2010 -0700 + + libaltos: Missing OS_LDFLAGS on cjnitest build + +commit b7fa1ea3338f63b8edcf8aacccb5e519ca0b213f +Author: Keith Packard +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 + +commit e60c59123232915e808cee23ef89eb1a38ced34b +Author: Keith Packard +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 + +commit ae02b1590439d5c8dfb472cf1f83a14fdcfbaf11 +Author: Keith Packard +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 + +commit edcfb1bdf64772d3b83405ccf99385b8fea5d8e4 +Author: Keith Packard +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 + +commit 236685807b63860ad033aa0254ce8f6d8d36d4ef +Author: Bdale Garbee +Date: Fri Aug 27 22:26:09 2010 -0600 + + update changelogs for Debian build + commit 1cda15fdef2d9d3e54354bd5c43a0bcc7e3240cb Author: Bdale Garbee Date: Fri Aug 27 22:24:51 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 022a05be..0d3a49ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,103 @@ +altos (0.7+22+g4790f78) 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 Mon, 30 Aug 2010 19:07:13 -0600 + +altos (0.7+18+g42055af) unstable; urgency=low + + [ 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 Mon, 30 Aug 2010 19:05:34 -0600 + +altos (0.7+22+g4790f78) unstable; urgency=low + + [ 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 Mon, 30 Aug 2010 19:03:37 -0600 + altos (0.7) unstable; urgency=low * update changelogs for Debian build -- cgit v1.2.3 From 507e429db6638f82c32449e9c5ca06b46da30134 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 19:09:00 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 66 +------------------------------------------------------- 2 files changed, 7 insertions(+), 65 deletions(-) diff --git a/ChangeLog b/ChangeLog index d1c75a33..06a33ec5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 25764fcd1b65c3a5a817afdb5901ac30e8a5f0c0 +Author: Bdale Garbee +Date: Mon Aug 30 19:08:29 2010 -0600 + + update changelogs for Debian build + commit 4790f78aead8a816e5b247c022b2998ce3a94053 Author: Bdale Garbee Date: Mon Aug 30 18:48:50 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 0d3a49ac..1cb6c377 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7+22+g4790f78) unstable; urgency=low +altos (0.7+23+g25764fc) unstable; urgency=low [ Bdale Garbee ] * fix up for an 0.7 release @@ -34,70 +34,6 @@ altos (0.7+22+g4790f78) unstable; urgency=low -- Bdale Garbee Mon, 30 Aug 2010 19:07:13 -0600 -altos (0.7+18+g42055af) unstable; urgency=low - - [ 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 Mon, 30 Aug 2010 19:05:34 -0600 - -altos (0.7+22+g4790f78) unstable; urgency=low - - [ 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 Mon, 30 Aug 2010 19:03:37 -0600 - altos (0.7) unstable; urgency=low * update changelogs for Debian build -- cgit v1.2.3 From 2a004d17a13b4ff52d892bfdecff8ad3d0823f7c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 19:37:17 -0600 Subject: don't build all the "fat" jar deliverables by default --- ao-tools/altosui/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index ce627ec0..5a8d7454 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -76,7 +76,8 @@ WINDOWS_ZIP=Altos-Windows.zip LINUX_TGZ=Altos-Linux.tgz -all: altosui altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) +all: altosui.jar $(LINUX_APP) +fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) $(CLASSFILES): -- cgit v1.2.3 From c35632efb1919764e4b8581ed6fcf2bedd4bd517 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 19:37:50 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 06a33ec5..0adbc7be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 2a004d17a13b4ff52d892bfdecff8ad3d0823f7c +Author: Bdale Garbee +Date: Mon Aug 30 19:37:17 2010 -0600 + + don't build all the "fat" jar deliverables by default + +commit 507e429db6638f82c32449e9c5ca06b46da30134 +Author: Bdale Garbee +Date: Mon Aug 30 19:09:00 2010 -0600 + + update changelogs for Debian build + commit 25764fcd1b65c3a5a817afdb5901ac30e8a5f0c0 Author: Bdale Garbee Date: Mon Aug 30 19:08:29 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 1cb6c377..8e51b816 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.7+25+g2a004d1) unstable; urgency=low + + * don't build all the "fat" jar deliverables by default + + -- Bdale Garbee Mon, 30 Aug 2010 19:37:40 -0600 + altos (0.7+23+g25764fc) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From c1c7d731e3774883fa0bb5538be225a59334d124 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 30 Aug 2010 19:52:51 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0adbc7be..5b01d0e0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit c35632efb1919764e4b8581ed6fcf2bedd4bd517 +Author: Bdale Garbee +Date: Mon Aug 30 19:37:50 2010 -0600 + + update changelogs for Debian build + commit 2a004d17a13b4ff52d892bfdecff8ad3d0823f7c Author: Bdale Garbee Date: Mon Aug 30 19:37:17 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 8e51b816..e4c8e6ff 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7+25+g2a004d1) unstable; urgency=low +altos (0.7+26+gc35632e) unstable; urgency=low * don't build all the "fat" jar deliverables by default -- cgit v1.2.3 From d006c5e1255433181aca4c8e6a277b2d1bc0841b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 31 Aug 2010 00:19:37 -0400 Subject: add runtime dependencies for altos binary package --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index f2bd1914..690eb78f 100644 --- a/debian/control +++ b/debian/control @@ -9,7 +9,7 @@ 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 -- cgit v1.2.3 From bd2b9d958c2b7f846031b076ed51c4fbaaf2d68f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 31 Aug 2010 00:20:06 -0400 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5b01d0e0..4d5c6d2e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit d006c5e1255433181aca4c8e6a277b2d1bc0841b +Author: Bdale Garbee +Date: Tue Aug 31 00:19:37 2010 -0400 + + add runtime dependencies for altos binary package + +commit c1c7d731e3774883fa0bb5538be225a59334d124 +Author: Bdale Garbee +Date: Mon Aug 30 19:52:51 2010 -0600 + + update changelogs for Debian build + commit c35632efb1919764e4b8581ed6fcf2bedd4bd517 Author: Bdale Garbee Date: Mon Aug 30 19:37:50 2010 -0600 diff --git a/debian/changelog b/debian/changelog index e4c8e6ff..971cda79 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.7+28+gd006c5e) unstable; urgency=low + + * add runtime dependencies for altos binary package + + -- Bdale Garbee 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 -- cgit v1.2.3 From 775acb89660cdee2f3c54c38297baefe39f2414c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 22:24:09 -0700 Subject: altosui: missed AltosReader.class in the Makefile This caused clean builds to fail to make this file Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 5a8d7454..bf92b5d6 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -26,6 +26,7 @@ CLASSFILES=\ AltosLogfileChooser.class \ AltosParse.class \ AltosPreferences.class \ + AltosReader.class \ AltosRecord.class \ AltosSerialMonitor.class \ AltosSerial.class \ -- cgit v1.2.3 From 1177e0a684328422be5adc68093d0091a218a824 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 19:53:24 -0700 Subject: 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 --- src/ao.h | 4 +++- src/ao_gps_skytraq.c | 13 +++++++++---- src/ao_gps_test.c | 4 +++- src/ao_gps_test_skytraq.c | 4 +++- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/ao.h b/src/ao.h index cd4e4814..5b174947 100644 --- a/src/ao.h +++ b/src/ao.h @@ -781,9 +781,11 @@ struct ao_gps_sat_data { 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; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index c822f7fa..2d3d464c 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -333,14 +333,19 @@ ao_gps(void) __reentrant 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 ^ '*'; diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index cdcc6f4c..edb51304 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -62,9 +62,11 @@ struct ao_gps_sat_data { 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 diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 7fa10eaa..4010e09c 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -63,9 +63,11 @@ struct ao_gps_sat_data { 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 -- cgit v1.2.3 From a470315e5d822a69ef5304512cf73c604c88e481 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 20:14:51 -0700 Subject: 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 --- ao-tools/altosui/Manifest.txt | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 ao-tools/altosui/Manifest.txt diff --git a/ao-tools/altosui/Manifest.txt b/ao-tools/altosui/Manifest.txt deleted file mode 100644 index 504d0de3..00000000 --- a/ao-tools/altosui/Manifest.txt +++ /dev/null @@ -1,2 +0,0 @@ -Main-Class: altosui.AltosUI -Class-Path: /usr/share/java/freetts.jar -- cgit v1.2.3 From d079bfe86ed40ff450ece445cf5f5e3970e44cec Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:44:30 -0400 Subject: update changelogs for Debian build --- ChangeLog | 43 +++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 9 +++++++++ 2 files changed, 52 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4d5c6d2e..a93b89a2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,46 @@ +commit a470315e5d822a69ef5304512cf73c604c88e481 +Author: Keith Packard +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 + +commit 1177e0a684328422be5adc68093d0091a218a824 +Author: Keith Packard +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 + +commit 775acb89660cdee2f3c54c38297baefe39f2414c +Author: Keith Packard +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 + +commit bd2b9d958c2b7f846031b076ed51c4fbaaf2d68f +Author: Bdale Garbee +Date: Tue Aug 31 00:20:06 2010 -0400 + + update changelogs for Debian build + commit d006c5e1255433181aca4c8e6a277b2d1bc0841b Author: Bdale Garbee Date: Tue Aug 31 00:19:37 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 971cda79..33932660 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +altos (0.7+32+ga470315) unstable; urgency=low + + [ 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 Thu, 02 Sep 2010 00:44:15 -0400 + altos (0.7+28+gd006c5e) unstable; urgency=low * add runtime dependencies for altos binary package -- cgit v1.2.3 From 6f24d2a476759104a10b26b54faff2b18b0e208b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:46:21 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a93b89a2..eeeb1442 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit d079bfe86ed40ff450ece445cf5f5e3970e44cec +Author: Bdale Garbee +Date: Thu Sep 2 00:44:30 2010 -0400 + + update changelogs for Debian build + commit a470315e5d822a69ef5304512cf73c604c88e481 Author: Keith Packard Date: Wed Sep 1 20:14:51 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 33932660..7db7e3fc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7+32+ga470315) unstable; urgency=low +altos (0.7+33+gd079bfe) unstable; urgency=low [ Keith Packard ] * altosui: missed AltosReader.class in the Makefile -- cgit v1.2.3 From 83552dfa0d38db9cdf3efc89e64e6c7896467856 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:47:54 -0400 Subject: add distclean targets to libaltos and altosui to all Debian package to build --- ao-tools/altosui/Makefile | 2 ++ ao-tools/libaltos/Makefile | 2 ++ 2 files changed, 4 insertions(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index bf92b5d6..92922de3 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -134,6 +134,8 @@ clean: rm -rf classes rm -rf windows linux +distclean: clean + FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile index 77ffa1b4..cb767c85 100644 --- a/ao-tools/libaltos/Makefile +++ b/ao-tools/libaltos/Makefile @@ -106,6 +106,8 @@ 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 -- cgit v1.2.3 From 14fa24ed93b3b1cec08a170004c6fb7f4d74f7e5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:48:31 -0400 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 +++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index eeeb1442..e92a09a8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 83552dfa0d38db9cdf3efc89e64e6c7896467856 +Author: Bdale Garbee +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 +Date: Thu Sep 2 00:46:21 2010 -0400 + + update changelogs for Debian build + commit d079bfe86ed40ff450ece445cf5f5e3970e44cec Author: Bdale Garbee Date: Thu Sep 2 00:44:30 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 7db7e3fc..25f8a34f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,8 @@ -altos (0.7+33+gd079bfe) unstable; urgency=low +altos (0.7+35+g83552df) unstable; urgency=low + + [ Bdale Garbee ] + * add distclean targets to libaltos and altosui to all Debian package + to build [ Keith Packard ] * altosui: missed AltosReader.class in the Makefile -- cgit v1.2.3 From d5a6ad87c7a9ac03b2e694bed0a54b6cc4322a6f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:50:16 -0400 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e92a09a8..d5361083 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 14fa24ed93b3b1cec08a170004c6fb7f4d74f7e5 +Author: Bdale Garbee +Date: Thu Sep 2 00:48:31 2010 -0400 + + update changelogs for Debian build + commit 83552dfa0d38db9cdf3efc89e64e6c7896467856 Author: Bdale Garbee Date: Thu Sep 2 00:47:54 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 25f8a34f..331b8847 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7+35+g83552df) unstable; urgency=low +altos (0.7+36+g14fa24e) unstable; urgency=low [ Bdale Garbee ] * add distclean targets to libaltos and altosui to all Debian package -- cgit v1.2.3 From 3aafd70257b70b7c11ba9c55749157979bc61ea2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:52:04 -0400 Subject: more makefile distclean target work --- ao-tools/altosui/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 92922de3..85271039 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -135,6 +135,7 @@ clean: rm -rf windows linux distclean: clean + rm -f $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) -- cgit v1.2.3 From 59ff9180f11063c257746b895a167179b3a4ff7c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:53:16 -0400 Subject: and a few more distclean fixes --- ao-tools/altosui/Makefile | 1 + doc/Makefile | 2 ++ 2 files changed, 3 insertions(+) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 85271039..abf5704f 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -136,6 +136,7 @@ clean: distclean: clean rm -f $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) + rm -rf darwin fat FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) diff --git a/doc/Makefile b/doc/Makefile index f8048dce..e840ec41 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -26,6 +26,8 @@ telemetrum-doc.pdf: telemetrum-doc.fo clean: rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo +distclean: clean + indent: telemetrum-doc.xsl xmlindent -i 2 < telemetrum-doc.xsl > telemetrum-doc.new -- cgit v1.2.3 From 59a40f6d5a2159b9009a3fa0737bb679efd5b32c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:55:01 -0400 Subject: another distclean fix --- doc/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/Makefile b/doc/Makefile index e840ec41..238cefb0 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -26,7 +26,8 @@ telemetrum-doc.pdf: telemetrum-doc.fo clean: rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo -distclean: clean +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 -- cgit v1.2.3 From cf30343aadd5039627a85319872685f743e64b16 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 2 Sep 2010 00:55:41 -0400 Subject: update changelogs for Debian build --- ChangeLog | 24 ++++++++++++++++++++++++ debian/changelog | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index d5361083..99716478 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +commit 59a40f6d5a2159b9009a3fa0737bb679efd5b32c +Author: Bdale Garbee +Date: Thu Sep 2 00:55:01 2010 -0400 + + another distclean fix + +commit 59ff9180f11063c257746b895a167179b3a4ff7c +Author: Bdale Garbee +Date: Thu Sep 2 00:53:16 2010 -0400 + + and a few more distclean fixes + +commit 3aafd70257b70b7c11ba9c55749157979bc61ea2 +Author: Bdale Garbee +Date: Thu Sep 2 00:52:04 2010 -0400 + + more makefile distclean target work + +commit d5a6ad87c7a9ac03b2e694bed0a54b6cc4322a6f +Author: Bdale Garbee +Date: Thu Sep 2 00:50:16 2010 -0400 + + update changelogs for Debian build + commit 14fa24ed93b3b1cec08a170004c6fb7f4d74f7e5 Author: Bdale Garbee Date: Thu Sep 2 00:48:31 2010 -0400 diff --git a/debian/changelog b/debian/changelog index 331b8847..b5153149 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,8 @@ -altos (0.7+36+g14fa24e) unstable; urgency=low +altos (0.7+40+g59a40f6) unstable; urgency=low [ Bdale Garbee ] * add distclean targets to libaltos and altosui to all Debian package - to build + to build, and clean up other distclean content as needed [ Keith Packard ] * altosui: missed AltosReader.class in the Makefile -- cgit v1.2.3 From 2f07ad14a16dbf1b75c71784ceae303825c90ade Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 22:43:22 -0700 Subject: 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 --- ao-tools/altosui/AltosFlash.java | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index b7018555..a3e431cd 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -202,9 +202,13 @@ public class AltosFlash { debug.debug_instr(set_clkcon_fast); byte status; - do { + for (int times = 0; times < 20; times++) { + Thread.sleep(1); status = debug.debug_instr(get_sleep); - } while ((status & SLEEP_XOSC_STB) == 0); + if ((status & SLEEP_XOSC_STB) != 0) + return; + } + throw new IOException("Failed to initialize target clock"); } void action(String s, int percent) { @@ -221,6 +225,22 @@ public class AltosFlash { 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"); @@ -264,16 +284,7 @@ public class AltosFlash { this_time); debug.write_memory(flash_prog, flash_page); - debug.set_pc(flash_prog); - int pc = debug.get_pc(); - debug.resume(); - Thread.sleep(100); - for (int times = 0; times < 10; times++) { - byte status = debug.read_status(); - if ((status & AltosDebug.STATUS_CPU_HALTED) != 0) - break; - Thread.sleep(100); - } + run(flash_prog); byte[] check = debug.read_memory(flash_addr, this_time); for (int i = 0; i < this_time; i++) -- cgit v1.2.3 From 9a690c9795e8257d2a3225f905117681668a472f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 22:46:04 -0700 Subject: 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 --- ao-tools/altosui/AltosFlashUI.java | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 73a97a6b..18795695 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -75,17 +75,17 @@ public class AltosFlashUI AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); romconfig_ui.set(flash.romconfig()); - romconfig_ui.showDialog(); - - AltosRomconfig romconfig = romconfig_ui.romconfig(); - if (romconfig == null || !romconfig.valid()) - return; - flash.set_romconfig(romconfig); - serial_value.setText(String.format("%d", - flash.romconfig().serial_number)); - file_value.setText(file.toString()); - setVisible(true); - flash.flash(); + 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", @@ -97,6 +97,8 @@ public class AltosFlashUI file.toString(), JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { + } finally { + abort(); } dispose(); } -- cgit v1.2.3 From 5ee6cd41ed189c3166f76558ecada80917f40652 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 22:47:15 -0700 Subject: 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 --- ao-tools/altosui/AltosRomconfigUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index bc511865..10b3af80 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -162,7 +162,7 @@ public class AltosRomconfigUI } } - public AltosRomconfig romconfig() { + AltosRomconfig romconfig() { try { return new AltosRomconfig(serial(), radio_calibration()); } catch (NumberFormatException ne) { -- cgit v1.2.3 From 8d8980f56a4f2c7d6f2ce667130706e0f04f8ded Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 22:56:12 -0700 Subject: altosui: Remove some debug printfs from AltosRomconfig class Signed-off-by: Keith Packard --- ao-tools/altosui/AltosRomconfig.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 8c9cb27a..22d2dbd3 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -57,7 +57,6 @@ public class AltosRomconfig { static void put_usb_serial(int value, byte[] bytes, int start) { int offset = start + 0xa; int string_num = 0; - System.out.printf("Put usb serial %d\n", value); while (offset < bytes.length && bytes[offset] != 0) { if (bytes[offset + 1] == AO_USB_DESC_STRING) { @@ -67,13 +66,10 @@ public class AltosRomconfig { } offset += ((int) bytes[offset]) & 0xff; } - System.out.printf("offset %d content %d\n", - offset, bytes[offset]); if (offset >= bytes.length || bytes[offset] == 0) return; int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; String fmt = String.format("%%0%dd", len); - System.out.printf("existing serial length %d format %s\n", len, fmt); String s = String.format(fmt, value); if (s.length() != len) { @@ -90,14 +86,12 @@ public class AltosRomconfig { public AltosRomconfig(byte[] bytes, int offset) { version = get_int(bytes, offset + 0, 2); check = get_int(bytes, offset + 2, 2); - System.out.printf("version %d check %d\n", version, check); 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); - System.out.printf("serial %d cal %d\n", serial_number, radio_calibration); valid = true; break; } -- cgit v1.2.3 From cff0d1ef6b338b3d5ad9450d4d5f95df934cb5e4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 22:56:34 -0700 Subject: altosui: Post error dialog on invalid ROM config values. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosRomconfigUI.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 10b3af80..2134975d 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -134,8 +134,17 @@ public class AltosRomconfigUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("ok")) + 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); } -- cgit v1.2.3 From 3b3aa448f3a0f44137f7530b04b58967ba5f22f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Sep 2010 21:11:29 -0700 Subject: 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 --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index abf5704f..0f5d05c8 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -159,7 +159,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES) cp $(DARWIN_RESOURCES) darwin/AltosUI.app/Contents/Resources/Java mkdir -p darwin/AltOS cp $(DARWIN_EXTRA) darwin/AltOS - cd darwin && zip -j -r ../$@ AltosUI.app AltOS + cd darwin && zip -r ../$@ AltosUI.app AltOS WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf -- cgit v1.2.3 From e5ef42c2b22c6639d90631dbbb588f9fd2494385 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 01:12:24 -0700 Subject: 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 --- ao-tools/altosui/AltosCRCException.java | 26 ++++++++++++++++++++++++++ ao-tools/altosui/AltosLog.java | 1 + ao-tools/altosui/AltosSerial.java | 2 +- ao-tools/altosui/AltosTelemetry.java | 9 ++++++++- ao-tools/altosui/AltosTelemetryReader.java | 2 ++ ao-tools/altosui/AltosUI.java | 26 +++++++++++++++++--------- ao-tools/altosui/Makefile | 1 + 7 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 ao-tools/altosui/AltosCRCException.java diff --git a/ao-tools/altosui/AltosCRCException.java b/ao-tools/altosui/AltosCRCException.java new file mode 100644 index 00000000..4a529bcf --- /dev/null +++ b/ao-tools/altosui/AltosCRCException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + } +} diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index ec868b9c..2c241771 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -74,6 +74,7 @@ class AltosLog implements Runnable { open(telem); } } catch (ParseException pe) { + } catch (AltosCRCException ce) { } if (log_file != null) { log_file.write(line); diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 99ba3324..c3daf3b9 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -71,7 +71,7 @@ public class AltosSerial implements Runnable { for (int i = 0; i < line_count; i++) line = line + line_bytes[i]; } - if (line.startsWith("VERSION")) { + if (line.startsWith("VERSION") || line.startsWith("CRC")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); q.put(line); diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index bc62690b..be22dac6 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -23,6 +23,7 @@ import java.util.HashMap; import altosui.AltosConvert; import altosui.AltosRecord; import altosui.AltosGPS; +import altosui.AltosCRCException; /* * Telemetry data contents @@ -53,10 +54,16 @@ import altosui.AltosGPS; */ 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; + 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 { diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index a3402f9c..fdedbde2 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -62,6 +62,8 @@ public class AltosTelemetryReader extends AltosReader { 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) { diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 5b48e26f..e3f61303 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -168,21 +168,17 @@ public class AltosUI extends JFrame { flightInfoModel[i].finish(); } - public void show(AltosState state) { + public void show(AltosState state, int crc_errors) { 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); @@ -197,6 +193,11 @@ public class AltosUI extends JFrame { 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) @@ -362,7 +363,11 @@ public class AltosUI extends JFrame { String name; - AltosRecord read() throws InterruptedException, ParseException { return null; } + int crc_errors; + + void init() { } + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException { return null; } void close() { } @@ -387,11 +392,14 @@ public class AltosUI extends JFrame { old_state = state; state = new AltosState(record, state); update(state); - show(state); + show(state, crc_errors); tell(state, old_state); idle_thread.notice(state); } 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) { @@ -411,7 +419,7 @@ public class AltosUI extends JFrame { AltosSerial serial; LinkedBlockingQueue telem; - AltosRecord read() throws InterruptedException, ParseException { + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException { return new AltosTelemetry(telem.take()); } diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 0f5d05c8..8509391e 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -7,6 +7,7 @@ CLASSFILES=\ AltosConfig.class \ AltosConfigUI.class \ AltosConvert.class \ + AltosCRCException.class \ AltosCSV.class \ AltosCSVUI.class \ AltosDebug.class \ -- cgit v1.2.3 From ba65e4aeb952a1cf49a77f1e24e235508fcea71f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 01:21:57 -0700 Subject: 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 --- ao-tools/altosui/AltosSerial.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index c3daf3b9..c4a7ad76 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -186,10 +186,14 @@ public class AltosSerial implements Runnable { public void set_channel(int channel) { if (altos != null) { + if (monitor_mode) { + printf("m 0\n"); + flush_input(); + } + printf("c r %d\n", channel); if (monitor_mode) - printf("m 0\nc r %d\nm 1\n", channel); - else - printf("c r %d\n", channel); + printf("m 1\n"); + flush_input(); } } @@ -198,8 +202,10 @@ public class AltosSerial implements Runnable { if (altos != null) { if (monitor) printf("m 1\n"); - else + else { printf("m 0\n"); + flush_input(); + } } } -- cgit v1.2.3 From 71191ecef3ba0e00d0f8a7cd1a24982bfa44ec72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 01:30:33 -0700 Subject: 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 --- ao-tools/altosui/AltosUI.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index e3f61303..e63a004c 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -441,6 +441,7 @@ public class AltosUI extends JFrame { if (device != null) { try { + stop_display(); serial_line.open(device); DeviceThread thread = new DeviceThread(serial_line); serial_line.set_channel(AltosPreferences.channel()); @@ -536,8 +537,12 @@ public class AltosUI extends JFrame { 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; } -- cgit v1.2.3 From d4f64e95e31e2335470efc15df2ab357b7d197f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 11:48:55 -0700 Subject: Revert "altosui: Deal with altos bug setting radio channel while monitoring" This reverts commit ba65e4aeb952a1cf49a77f1e24e235508fcea71f. Testing the old code --- ao-tools/altosui/AltosSerial.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index c4a7ad76..c3daf3b9 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -186,14 +186,10 @@ public class AltosSerial implements Runnable { public void set_channel(int channel) { if (altos != null) { - if (monitor_mode) { - printf("m 0\n"); - flush_input(); - } - printf("c r %d\n", channel); if (monitor_mode) - printf("m 1\n"); - flush_input(); + printf("m 0\nc r %d\nm 1\n", channel); + else + printf("c r %d\n", channel); } } @@ -202,10 +198,8 @@ public class AltosSerial implements Runnable { if (altos != null) { if (monitor) printf("m 1\n"); - else { + else printf("m 0\n"); - flush_input(); - } } } -- cgit v1.2.3 From 16d8d6a8853d09f683b13f9cda3c3174a0aab130 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 12:31:05 -0700 Subject: 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 --- ao-tools/altosui/AltosSerial.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index c3daf3b9..bc35d6b8 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -101,7 +101,8 @@ public class AltosSerial implements Runnable { } public void flush_output() { - libaltos.altos_flush(altos); + if (altos != null) + libaltos.altos_flush(altos); } public void flush_input() { @@ -180,8 +181,8 @@ public class AltosSerial implements Runnable { input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); + flush_output(); set_monitor(monitor_mode); - flush_input(); } public void set_channel(int channel) { @@ -190,6 +191,7 @@ public class AltosSerial implements Runnable { printf("m 0\nc r %d\nm 1\n", channel); else printf("c r %d\n", channel); + flush_output(); } } @@ -200,12 +202,15 @@ public class AltosSerial implements Runnable { 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() { -- cgit v1.2.3 From 59798c6fd11502a9c8b66090c23ba50eb250692e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 3 Sep 2010 12:43:45 -0700 Subject: 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 --- ao-tools/altosui/AltosLine.java | 30 ++++++++++++++++++++++++++++++ ao-tools/altosui/AltosLog.java | 15 +++++++++------ ao-tools/altosui/AltosSerial.java | 34 ++++++++++++++++++++++------------ ao-tools/altosui/AltosUI.java | 27 +++++++++++++++++++-------- ao-tools/altosui/Makefile | 1 + ao-tools/libaltos/libaltos.c | 15 ++++++++++++++- 6 files changed, 95 insertions(+), 27 deletions(-) create mode 100644 ao-tools/altosui/AltosLine.java diff --git a/ao-tools/altosui/AltosLine.java b/ao-tools/altosui/AltosLine.java new file mode 100644 index 00000000..86e9d4c6 --- /dev/null +++ b/ao-tools/altosui/AltosLine.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index 2c241771..f876beba 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -24,6 +24,7 @@ import java.text.ParseException; 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 @@ -31,7 +32,7 @@ import altosui.AltosFile; */ class AltosLog implements Runnable { - LinkedBlockingQueue input_queue; + LinkedBlockingQueue input_queue; LinkedBlockingQueue pending_queue; int serial; int flight; @@ -64,9 +65,11 @@ class AltosLog implements Runnable { 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; @@ -77,11 +80,11 @@ class AltosLog implements Runnable { } 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) { @@ -94,7 +97,7 @@ class AltosLog implements Runnable { public AltosLog (AltosSerial s) { pending_queue = new LinkedBlockingQueue (); - input_queue = new LinkedBlockingQueue (); + input_queue = new LinkedBlockingQueue (); s.add_monitor(input_queue); serial = -1; flight = -1; diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index bc35d6b8..a1fc4371 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -27,10 +27,12 @@ import java.util.concurrent.LinkedBlockingQueue; 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 @@ -41,8 +43,8 @@ import libaltosJNI.SWIGTYPE_p_altos_list; public class AltosSerial implements Runnable { SWIGTYPE_p_altos_file altos; - LinkedList> monitors; - LinkedBlockingQueue reply_queue; + LinkedList> monitors; + LinkedBlockingQueue reply_queue; Thread input_thread; String line; byte[] line_bytes; @@ -57,7 +59,15 @@ public class AltosSerial implements Runnable { 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 q = monitors.get(e); + q.put(new AltosLine()); + } + reply_queue.put (new AltosLine()); + break; + } + if (c == libaltosConstants.LIBALTOS_TIMEOUT) continue; if (c == '\r') continue; @@ -73,12 +83,12 @@ public class AltosSerial implements Runnable { } if (line.startsWith("VERSION") || line.startsWith("CRC")) { for (int e = 0; e < monitors.size(); e++) { - LinkedBlockingQueue q = monitors.get(e); - q.put(line); + LinkedBlockingQueue q = monitors.get(e); + q.put(new AltosLine (line)); } } else { // System.out.printf("GOT: %s\n", line); - reply_queue.put(line); + reply_queue.put(new AltosLine (line)); } line_count = 0; line = ""; @@ -121,16 +131,16 @@ public class AltosSerial implements Runnable { public String get_reply() throws InterruptedException { flush_output(); - String line = reply_queue.take(); - return line; + AltosLine line = reply_queue.take(); + return line.line; } - public void add_monitor(LinkedBlockingQueue q) { + public void add_monitor(LinkedBlockingQueue q) { set_monitor(true); monitors.add(q); } - public void remove_monitor(LinkedBlockingQueue q) { + public void remove_monitor(LinkedBlockingQueue q) { monitors.remove(q); if (monitors.isEmpty()) set_monitor(false); @@ -218,7 +228,7 @@ public class AltosSerial implements Runnable { input_thread = null; line = ""; monitor_mode = false; - monitors = new LinkedList> (); - reply_queue = new LinkedBlockingQueue (); + monitors = new LinkedList> (); + reply_queue = new LinkedBlockingQueue (); } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index e63a004c..7e3fb7f9 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -44,6 +44,7 @@ import altosui.AltosChannelMenu; import altosui.AltosFlashUI; import altosui.AltosLogfileChooser; import altosui.AltosCSVUI; +import altosui.AltosLine; import libaltosJNI.*; @@ -169,6 +170,8 @@ public class AltosUI extends JFrame { } public void show(AltosState state, int crc_errors) { + if (state == null) + return; flightStatusModel.set(state); info_reset(); @@ -367,7 +370,7 @@ public class AltosUI extends JFrame { void init() { } - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException { return null; } + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } void close() { } @@ -403,6 +406,11 @@ public class AltosUI extends JFrame { } } } catch (InterruptedException ee) { + } catch (IOException ie) { + JOptionPane.showMessageDialog(AltosUI.this, + String.format("Error reading from \"%s\"", name), + "Telemetry Read Error", + JOptionPane.ERROR_MESSAGE); } finally { close(); idle_thread.interrupt(); @@ -417,10 +425,13 @@ public class AltosUI extends JFrame { class DeviceThread extends DisplayThread { AltosSerial serial; - LinkedBlockingQueue telem; + LinkedBlockingQueue telem; - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException { - 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() { @@ -428,11 +439,11 @@ public class AltosUI extends JFrame { serial.remove_monitor(telem); } - public DeviceThread(AltosSerial s) { + public DeviceThread(AltosSerial s, String in_name) { serial = s; - telem = new LinkedBlockingQueue(); + telem = new LinkedBlockingQueue(); serial.add_monitor(telem); - name = "telemetry"; + name = in_name; } } @@ -443,7 +454,7 @@ public class AltosUI extends JFrame { 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); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 8509391e..cc9a440d 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -23,6 +23,7 @@ CLASSFILES=\ AltosGPS.class \ AltosGreatCircle.class \ AltosHexfile.class \ + AltosLine.class \ AltosLog.class \ AltosLogfileChooser.class \ AltosParse.class \ diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c index 059d2ae9..465f0ac8 100644 --- a/ao-tools/libaltos/libaltos.c +++ b/ao-tools/libaltos/libaltos.c @@ -576,6 +576,11 @@ altos_free(struct altos_file *file) PUBLIC int altos_flush(struct altos_file *file) { + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } while (file->out_used) { int ret; @@ -634,7 +639,7 @@ altos_fill(struct altos_file *file, int timeout) return LIBALTOS_ERROR; #ifdef USE_POLL fd[0].fd = file->fd; - fd[0].events = POLLIN; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; fd[1].fd = file->pipe[0]; fd[1].events = POLLIN; ret = poll(fd, 2, timeout); @@ -644,6 +649,9 @@ altos_fill(struct altos_file *file, int timeout) } if (ret == 0) return LIBALTOS_TIMEOUT; + + if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL)) + return LIBALTOS_ERROR; if (fd[0].revents & POLLIN) #endif { @@ -660,6 +668,11 @@ altos_fill(struct altos_file *file, int timeout) #endif } } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } return 0; } -- cgit v1.2.3 From bf22923cd8b4f6f954718358b411b5b10d8e7b4d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 4 Sep 2010 00:46:29 -0400 Subject: update changelogs for Debian build --- ChangeLog | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 19 ++++++++ 2 files changed, 161 insertions(+) diff --git a/ChangeLog b/ChangeLog index 99716478..70911434 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,145 @@ +commit 59798c6fd11502a9c8b66090c23ba50eb250692e +Author: Keith Packard +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 + +commit 16d8d6a8853d09f683b13f9cda3c3174a0aab130 +Author: Keith Packard +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 + +commit d4f64e95e31e2335470efc15df2ab357b7d197f3 +Author: Keith Packard +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 +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 + +commit ba65e4aeb952a1cf49a77f1e24e235508fcea71f +Author: Keith Packard +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 + +commit e5ef42c2b22c6639d90631dbbb588f9fd2494385 +Author: Keith Packard +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 + +commit 3b3aa448f3a0f44137f7530b04b58967ba5f22f5 +Author: Keith Packard +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 + +commit cff0d1ef6b338b3d5ad9450d4d5f95df934cb5e4 +Author: Keith Packard +Date: Wed Sep 1 22:56:34 2010 -0700 + + altosui: Post error dialog on invalid ROM config values. + + Signed-off-by: Keith Packard + +commit 8d8980f56a4f2c7d6f2ce667130706e0f04f8ded +Author: Keith Packard +Date: Wed Sep 1 22:56:12 2010 -0700 + + altosui: Remove some debug printfs from AltosRomconfig class + + Signed-off-by: Keith Packard + +commit 5ee6cd41ed189c3166f76558ecada80917f40652 +Author: Keith Packard +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 + +commit 9a690c9795e8257d2a3225f905117681668a472f +Author: Keith Packard +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 + +commit 2f07ad14a16dbf1b75c71784ceae303825c90ade +Author: Keith Packard +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 + +commit cf30343aadd5039627a85319872685f743e64b16 +Author: Bdale Garbee +Date: Thu Sep 2 00:55:41 2010 -0400 + + update changelogs for Debian build + commit 59a40f6d5a2159b9009a3fa0737bb679efd5b32c Author: Bdale Garbee Date: Thu Sep 2 00:55:01 2010 -0400 diff --git a/debian/changelog b/debian/changelog index b5153149..2005b64f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +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 Sat, 04 Sep 2010 00:46:12 -0400 + altos (0.7+40+g59a40f6) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From ecb4a09535b6a8da0765010489a96e605dbdeb46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 00:13:11 -0700 Subject: altosui: Add windows installer build using 'nsis' nsis happens to be packaged in debian, and it appears to build usable installers, which is all very cool. Signed-off-by: Keith Packard --- .../Instdrv/NSIS/Contrib/InstDrv/Example.nsi | 84 +++ .../Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe | Bin 0 -> 51831 bytes .../altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c | 704 +++++++++++++++++++++ .../Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp | 110 ++++ .../Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw | 29 + .../Instdrv/NSIS/Contrib/InstDrv/Readme.txt | 141 +++++ .../Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf | 137 ++++ .../Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys | Bin 0 -> 30464 bytes ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll | Bin 0 -> 6656 bytes ao-tools/altosui/Makefile | 10 +- ao-tools/altosui/altos-windows.nsi | 102 +++ 11 files changed, 1312 insertions(+), 5 deletions(-) create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf create mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys create mode 100644 ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll create mode 100644 ao-tools/altosui/altos-windows.nsi diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi new file mode 100644 index 00000000..3ed821eb --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi @@ -0,0 +1,84 @@ +# +# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de) +# + +Name "InstDrv.dll test" + +OutFile "InstDrv-Test.exe" + +ShowInstDetails show + +ComponentText "InstDrv Plugin Usage Example" + +Page components +Page instfiles + +Section "Install a Driver" InstDriver + InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" + Pop $0 + DetailPrint "InitDriverSetup: $0" + + InstDrv::DeleteOemInfFiles /NOUNLOAD + Pop $0 + DetailPrint "DeleteOemInfFiles: $0" + StrCmp $0 "00000000" PrintInfNames ContInst1 + + PrintInfNames: + Pop $0 + DetailPrint "Deleted $0" + Pop $0 + DetailPrint "Deleted $0" + + ContInst1: + InstDrv::CreateDevice /NOUNLOAD + Pop $0 + DetailPrint "CreateDevice: $0" + + SetOutPath $TEMP + File "ircomm2k.inf" + File "ircomm2k.sys" + + InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf" + Pop $0 + DetailPrint "InstallDriver: $0" + StrCmp $0 "00000000" PrintReboot ContInst2 + + PrintReboot: + Pop $0 + DetailPrint "Reboot: $0" + + ContInst2: + InstDrv::CountDevices + Pop $0 + DetailPrint "CountDevices: $0" +SectionEnd + +Section "Uninstall the driver again" UninstDriver + InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" + Pop $0 + DetailPrint "InitDriverSetup: $0" + + InstDrv::DeleteOemInfFiles /NOUNLOAD + Pop $0 + DetailPrint "DeleteOemInfFiles: $0" + StrCmp $0 "00000000" PrintInfNames ContUninst1 + + PrintInfNames: + Pop $0 + DetailPrint "Deleted $0" + Pop $0 + DetailPrint "Deleted $0" + + ContUninst1: + InstDrv::RemoveAllDevices + Pop $0 + DetailPrint "RemoveAllDevices: $0" + StrCmp $0 "00000000" PrintReboot ContUninst2 + + PrintReboot: + Pop $0 + DetailPrint "Reboot: $0" + + ContUninst2: + Delete "$SYSDIR\system32\ircomm2k.sys" +SectionEnd \ No newline at end of file diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe new file mode 100644 index 00000000..615bae15 Binary files /dev/null and b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe differ diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c new file mode 100644 index 00000000..efe866e9 --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c @@ -0,0 +1,704 @@ +/* + +InstDrv.dll - Installs or Removes Device Drivers + +Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not required. +2. Altered versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. + +*/ + + +#include +#include +#include +#include "../exdll/exdll.h" + + +char paramBuf[1024]; +GUID devClass; +char hwIdBuf[1024]; +int initialized = 0; + + + +void* memset(void* dst, int val, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = val; + + return NULL; +} + + + +void* memcpy(void* dst, const void* src, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = *((char *)src)++; + + return NULL; +} + + + +int HexCharToInt(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + else if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + else + return -1; +} + + + +BOOLEAN HexStringToUInt(char* str, int width, void* valBuf) +{ + int i, val; + + + for (i = width - 4; i >= 0; i -= 4) + { + val = HexCharToInt(*str++); + if (val < 0) + return FALSE; + *(unsigned int *)valBuf += val << i; + } + + return TRUE; +} + + + +BOOLEAN StringToGUID(char* guidStr, GUID* pGuid) +{ + int i; + + + memset(pGuid, 0, sizeof(GUID)); + + if (*guidStr++ != '{') + return FALSE; + + if (!HexStringToUInt(guidStr, 32, &pGuid->Data1)) + return FALSE; + guidStr += 8; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data2)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data3)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + for (i = 0; i < 2; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '-') + return FALSE; + + for (i = 2; i < 8; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '}') + return FALSE; + + return TRUE; +} + + + +DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex) +{ + DWORD buffersize = 0; + LPTSTR buffer = NULL; + DWORD dataType; + DWORD result; + + + while (1) + { + if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData)) + { + result = GetLastError(); + break; + } + + GetDeviceRegistryProperty: + if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID, + &dataType, (PBYTE)buffer, buffersize, + &buffersize)) + { + result = GetLastError(); + + if (result == ERROR_INSUFFICIENT_BUFFER) + { + if (buffer != NULL) + LocalFree(buffer); + + buffer = (LPTSTR)LocalAlloc(LPTR, buffersize); + + if (buffer == NULL) + break; + + goto GetDeviceRegistryProperty; + } + else if (result == ERROR_INVALID_DATA) + continue; // ignore invalid entries + else + break; // break on other errors + } + + if (lstrcmpi(buffer, hwIdBuf) == 0) + { + result = 0; + break; + } + } + + if (buffer != NULL) + LocalFree(buffer); + + return result; +} + + + +DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId, + HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData, + DWORD *pIndex, DWORD flags) +{ + DWORD result; + + + *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags); + if (*pDevInfoSet == INVALID_HANDLE_VALUE) + return GetLastError(); + + pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + *pIndex = 0; + + result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex); + + if (result != 0) + SetupDiDestroyDeviceInfoList(*pDevInfoSet); + + return result; +} + + + +/* + * InstDrv::InitDriverSetup devClass drvHWID + * + * devClass - GUID of the driver's device setup class + * drvHWID - Hardware ID of the supported device + * + * Return: + * result - error message, empty on success + */ +void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + EXDLL_INIT(); + + /* convert class GUID */ + popstring(paramBuf); + + if (!StringToGUID(paramBuf, &devClass)) + { + popstring(paramBuf); + pushstring("Invalid GUID!"); + return; + } + + /* get hardware ID */ + memset(hwIdBuf, 0, sizeof(hwIdBuf)); + popstring(hwIdBuf); + + initialized = 1; + pushstring(""); +} + + + +/* + * InstDrv::CountDevices + * + * Return: + * result - Number of installed devices the driver supports + */ +void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + int count = 0; + char countBuf[16]; + DWORD index; + DWORD result; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData, + &index, DIGCF_PRESENT); + if (result != 0) + { + pushstring("0"); + return; + } + + do + { + count++; + } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0); + + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(countBuf, "%d", count); + pushstring(countBuf); +} + + + +/* + * InstDrv::CreateDevice + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + DWORD result = 0; + char resultBuf[16]; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent); + if (devInfoSet == INVALID_HANDLE_VALUE) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + return; + } + + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL, + hwndParent, DICD_GENERATE_ID, &devInfoData)) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, + hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData)) + result = GetLastError(); + + InstallCleanup: + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::InstallDriver infPath + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + char resultBuf[16]; + BOOL reboot; + + + EXDLL_INIT(); + popstring(paramBuf); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf, + INSTALLFLAG_FORCE, &reboot)) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + } + else + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } +} + + + +/* + * InstDrv::DeleteOemInfFiles + * + * Return: + * result - Windows error code + * oeminf - Path of the deleted devices setup file (oemXX.inf) + * oempnf - Path of the deleted devices setup file (oemXX.pnf) + */ +void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + SP_DRVINFO_DATA drvInfoData; + SP_DRVINFO_DETAIL_DATA drvInfoDetail; + DWORD index; + DWORD result; + char resultBuf[16]; + + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER)) + { + result = GetLastError(); + goto Cleanup2; + } + + drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); + drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + + if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData)) + { + result = GetLastError(); + goto Cleanup3; + } + + if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData, + &drvInfoDetail, sizeof(drvInfoDetail), NULL)) + { + result = GetLastError(); + + if (result != ERROR_INSUFFICIENT_BUFFER) + goto Cleanup3; + + result = 0; + } + + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + else + { + index = lstrlen(drvInfoDetail.InfFileName); + if (index > 3) + { + lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf"); + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + } + } + + Cleanup3: + SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER); + + Cleanup2: + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::RemoveAllDevices + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + DWORD index; + DWORD result; + char resultBuf[16]; + BOOL reboot = FALSE; + SP_DEVINSTALL_PARAMS instParams; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + do + { + if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData)) + { + result = GetLastError(); + break; + } + + instParams.cbSize = sizeof(instParams); + if (!reboot && + SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) && + ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0)) + { + reboot = TRUE; + } + + result = FindNextDevice(devInfo, &devInfoData, &index); + } while (result == 0); + + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + if ((result == 0) || (result == ERROR_NO_MORE_ITEMS)) + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } + else + { + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); + } +} + + + +/* + * InstDrv::StartSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_START_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + if ((svcStatus.dwCurrentState == SERVICE_STOPPED) && + (svcStatus.dwWin32ExitCode != 0)) + result = svcStatus.dwWin32ExitCode; + else + result = ERROR_SERVICE_REQUEST_TIMEOUT; + } + } + + if (svcStatus.dwCurrentState == SERVICE_RUNNING) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::StopSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + result = ERROR_SERVICE_REQUEST_TIMEOUT; + break; + } + } + + if (svcStatus.dwCurrentState == SERVICE_STOPPED) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + return TRUE; +} diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp new file mode 100644 index 00000000..874e66c7 --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp @@ -0,0 +1,110 @@ +# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=InstDrv - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "InstDrv.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "InstDrv - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "InstDrv - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "InstDrv - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c +# 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 +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "InstDrv - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 +# SUBTRACT LINK32 /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "InstDrv - Win32 Release" +# Name "InstDrv - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\InstDrv.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw new file mode 100644 index 00000000..b3d02f0e --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt new file mode 100644 index 00000000..e5877aa6 --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt @@ -0,0 +1,141 @@ +InstDrv.dll version 0.2 - Installs or Removes Device Drivers +------------------------------------------------------------ + + +The plugin helps you to create NSIS scripts for installing device drivers or +removing them again. It can count installed device instances, create new ones +or delete all supported device. InstDrv works on Windows 2000 or later. + + + +InstDrv::InitDriverSetup devClass drvHWID +Return: result + +To start processing a driver, first call this function. devClass is the GUID +of the device class the driver supports, drvHWID is the device hardware ID. If +you don't know what these terms mean, you may want to take a look at the +Windows DDK. This function returns an empty string on success, otherwise an +error message. + +InitDriverSetup has to be called every time after the plugin dll has been +(re-)loaded, or if you want to switch to a different driver. + + + +InstDrv::CountDevices +Return: number + +This call returns the number of installed and supported devices of the driver. + + + +InstDrv::CreateDevice +Return: result + +To create a new deviced node which the driver has to support, use this +function. You may even call it multiple times for more than one instance. The +return value is the Windows error code (in hex). Use CreateDevice before +installing or updating the driver itself. + + + +InstDrv::InstallDriver infPath +Return: result + reboot + +InstallDriver installs or updates a device driver as specified in the .inf +setup script. It returns a Windows error code (in hex) and, on success, a flag +signalling if a system reboot is required. + + + +InstDrv::DeleteOemInfFiles +Return: result + oeminf + oempnf + +DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the +oemXX.inf and oemXX.pnf files associated with the drivers. It returns a +Windows error code (in hex) and, on success, the names of the deleted files. +This functions requires that at least one device instance is still present. +So, call it before you remove the devices itself. You should also call it +before updating a driver. This avoids that the inf directory gets slowly +messed up with useless old setup scripts (which does NOT really accelerate +Windows). The error code which comes up when no device is installed is +"00000103". + + + +InstDrv::RemoveAllDevices +Return: result + reboot + +This functions deletes all devices instances the driver supported. It returns +a Windows error code (in hex) and, on success, a flag signalling if the system +needs to be rebooted. You additionally have to remove the driver binaries from +the system paths. + + + +InstDrv::StartSystemService serviceName +Return: result + +Call this function to start the provided system service. The function blocks +until the service is started or the system reported a timeout. The return value +is the Windows error code (in hex). + + + +InstDrv::StopSystemService serviceName +Return: result + +This function tries to stop the provided system service. It blocks until the +service has been shut down or the system reported a timeout. The return value +is the Windows error code (in hex). + + + +Example.nsi + +The example script installs or removes the virtual COM port driver of IrCOMM2k +(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script +are only included for demonstration purposes, they do not work without the +rest of IrCOMM2k (but they also do not cause any harm). + + + +Building the Source Code + +To build the plugin from the source code, some include files and libraries +which come with the Windows DDK are required. + + + +History + + 0.2 - fixed bug when calling InitDriverSetup the second time + - added StartSystemService and StopSystemService + + 0.1 - first release + + + +License + +Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not required. +2. Altered versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf new file mode 100644 index 00000000..ccda1d87 --- /dev/null +++ b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf @@ -0,0 +1,137 @@ +; IrCOMM2k.inf +; +; Installation file for the Virtual Infrared-COM-Port +; +; (c) Copyright 2001, 2002 Jan Kiszka +; + +[Version] +Signature="$Windows NT$" +Provider=%JK% +Class=Ports +ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318} +;DriverVer=03/26/2002,1.2.1.0 + +[DestinationDirs] +IrCOMM2k.Copy2Drivers = 12 +IrCOMM2k.Copy2Winnt = 10 +IrCOMM2k.Copy2System32 = 11 +IrCOMM2k.Copy2Help = 18 + + +; +; Driver information +; + +[Manufacturer] +%JK% = JK.Mfg + +[JK.Mfg] +%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k + + +; +; General installation section +; + +[IrCOMM2k_inst] +CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt +;AddReg = IrCOMM2k_inst_AddReg + + +; +; File sections +; + +[IrCOMM2k.Copy2Drivers] +ircomm2k.sys,,,2 + +;[IrCOMM2k.Copy2System32] +;ircomm2k.exe,,,2 +;ircomm2k.dll,,,2 + +;[IrCOMM2k.Copy2Help] +;ircomm2k.hlp,,,2 + +;[IrCOMM2k.Copy2Winnt] +;IrCOMM2k-Setup.exe,Setup.exe,,2 + + +; +; Service Installation +; + +[IrCOMM2k_inst.Services] +AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst +;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst + +[IrCOMM2k_DriverService_Inst] +DisplayName = %IrCOMM2k.DrvName% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 0 ; SERVICE_ERROR_IGNORE +ServiceBinary = %12%\ircomm2k.sys + +;[IrCOMM2k_Service_Inst] +;DisplayName = %IrCOMM2k.SvcName% +;Description = %IrCOMM2k.SvcDesc% +;ServiceType = 0x00000120 ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS +;StartType = 2 ; SERVICE_AUTO_START +;ErrorControl = 0 ; SERVICE_ERROR_IGNORE +;ServiceBinary = %11%\ircomm2k.exe +;Dependencies = IrCOMM2k +;AddReg = IrCOMM2kSvcAddReg + + +[IrCOMM2k_inst.nt.HW] +AddReg=IrCOMM2kHwAddReg + +[IrCOMM2kHwAddReg] +HKR,,PortSubClass,REG_BINARY,0x00000001 +;HKR,,TimeoutScaling,REG_DWORD,0x00000001 +;HKR,,StatusLines,REG_DWORD,0x00000000 + +;[IrCOMM2k_inst_AddReg] +;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider" +;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe" +;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 " +;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1" +;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de" +;HKLM,%UNINSTALL_KEY%,Publisher,,%JK% +;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe" + +;[IrCOMM2kSvcAddReg] +;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000 + + +[IrCOMM2k_DriverEventLog_Inst] +AddReg = IrCOMM2k_DriverEventLog_AddReg + +[IrCOMM2k_DriverEventLog_AddReg] +HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys" +HKR,,TypesSupported,REG_DWORD,7 + + +[Strings] + +; +; Non-Localizable Strings +; + +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 +SERVICEROOT = "System\CurrentControlSet\Services" +UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k" + +; +; Localizable Strings +; + +JK = "Jan Kiszka" +JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss" +IrCOMM2k.DrvName = "Virtueller Infrarot-Kommunikationsanschluss" +;IrCOMM2k.SvcName = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm" +;IrCOMM2k.SvcDesc = "Bildet über Infarot einen Kommunikationsanschluß nach." diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys new file mode 100644 index 00000000..7882583b Binary files /dev/null and b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys differ diff --git a/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll b/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll new file mode 100644 index 00000000..482e955e Binary files /dev/null and b/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll differ diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index cc9a440d..58acb26e 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -75,12 +75,12 @@ LINUX_APP=altosui DARWIN_ZIP=Altos-Mac.zip -WINDOWS_ZIP=Altos-Windows.zip +WINDOWS_EXE=Altos-Windows.exe LINUX_TGZ=Altos-Linux.tgz all: altosui.jar $(LINUX_APP) -fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) +fat: altosui.jar $(LINUX_APP) $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ) $(CLASSFILES): @@ -137,7 +137,7 @@ clean: rm -rf windows linux distclean: clean - rm -f $(DARWIN_ZIP) $(WINDOWS_ZIP) $(LINUX_TGZ) + rm -f $(DARWIN_ZIP) $(WINDOWS_EXE) $(LINUX_TGZ) rm -rf darwin fat FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) @@ -165,9 +165,9 @@ $(DARWIN_ZIP): $(DARWIN_FILES) WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf -$(WINDOWS_ZIP): $(WINDOWS_FILES) +$(WINDOWS_EXE): $(WINDOWS_FILES) altos-install.nsi rm -f $@ mkdir -p windows/AltOS rm -f windows/AltOS/* cp $(WINDOWS_FILES) windows/AltOS - cd windows && zip -j -r ../$@ AltOS + makensis altos-windows.nsi diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi new file mode 100644 index 00000000..abb0823b --- /dev/null +++ b/ao-tools/altosui/altos-windows.nsi @@ -0,0 +1,102 @@ +!addplugindir Instdrv/NSIS/Plugins + +Name "Altus Metrum Installer" + +OutFile "Altos-Windows.exe" + +; 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 "windows/AltOS/*.jar" + File "windows/AltOS/*.dll" + + CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui.jar" +SectionEnd + +Section "AltosUI Desktop Shortcut" + CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui.jar" +SectionEnd + +Section "TeleMetrum and TeleDongle Firmware" + + SetOutPath $INSTDIR + + File "windows/AltOS/telemetrum-v1.0.ihx" + File "windows/AltOS/teledongle-v0.2.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 -- cgit v1.2.3 From c0988ddbf104ea729090c2e7e2a28cc6dc9e90f6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 00:14:15 -0700 Subject: altosui: ignore built files --- ao-tools/altosui/.gitignore | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ao-tools/altosui/.gitignore b/ao-tools/altosui/.gitignore index 59913193..63672058 100644 --- a/ao-tools/altosui/.gitignore +++ b/ao-tools/altosui/.gitignore @@ -1,2 +1,14 @@ +windows/ +linux/ +darwin/ +fat/ +Manifest.txt +libaltosJNI +classes +altosui +Altos-Linux.tgz +Altos-Mac.zip +Altos-Windows.exe +*.jar *.class altosui -- cgit v1.2.3 From f550677df016070430ed38bfa2b2be33f1b8c40a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 00:16:41 -0700 Subject: altosui: oops. renamed the nsis file to altos-windows.nsi And forgot to change the dependency in the Makefile Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 58acb26e..92f0e690 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -165,7 +165,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES) WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf -$(WINDOWS_EXE): $(WINDOWS_FILES) altos-install.nsi +$(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi rm -f $@ mkdir -p windows/AltOS rm -f windows/AltOS/* -- cgit v1.2.3 From e9ea28504c646fc25791aab09b9e5faf73e0ac0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 01:08:34 -0700 Subject: icon: add some icons for application programs altus-metrum.ico: Windows ICO file altus-metrum-16x16.jpg: 16x16 jpg image for java Signed-off-by: Keith Packard --- icon/altus-metrum-16x16.jpg | Bin 0 -> 1100 bytes icon/altus-metrum.ico | Bin 0 -> 15086 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 icon/altus-metrum-16x16.jpg create mode 100644 icon/altus-metrum.ico diff --git a/icon/altus-metrum-16x16.jpg b/icon/altus-metrum-16x16.jpg new file mode 100644 index 00000000..8d8bbc6a Binary files /dev/null and b/icon/altus-metrum-16x16.jpg differ diff --git a/icon/altus-metrum.ico b/icon/altus-metrum.ico new file mode 100644 index 00000000..e32b4f1e Binary files /dev/null and b/icon/altus-metrum.ico differ -- cgit v1.2.3 From e844e8a0695e27af6f8e3e37a5e3bcc865b862e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 01:13:42 -0700 Subject: altosui: Add icons to application and Windows menus. Use the altus-metrum icon for an application icon and a windows start menu/desktop icon. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 4 ++++ ao-tools/altosui/Makefile | 19 ++++++++++++++----- ao-tools/altosui/altos-windows.nsi | 6 ++++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 7e3fb7f9..eb376be4 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -75,6 +75,10 @@ public class AltosUI extends JFrame { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; + java.net.URL imgURL = AltosUI.class.getResource("/images/altus-metrum-16x16.jpg"); + if (imgURL != null) + setIconImage(new ImageIcon(imgURL).getImage()); + AltosPreferences.init(this); vbox = Box.createVerticalBox(); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile index 92f0e690..90621f36 100644 --- a/ao-tools/altosui/Makefile +++ b/ao-tools/altosui/Makefile @@ -42,6 +42,9 @@ CLASSFILES=\ 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 @@ -87,8 +90,8 @@ $(CLASSFILES): .java.class: javac -encoding UTF8 -classpath "$(CLASSPATH)" $(JAVAFLAGS) $*.java -altosui.jar: classes/altosui classes/libaltosJNI $(CLASSFILES) Manifest.txt - cd ./classes && jar cfm ../$@ altosui/Manifest.txt altosui/*.class libaltosJNI/*.class +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' > $@ @@ -102,6 +105,10 @@ 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" >> $@ @@ -114,11 +121,13 @@ fat/altosui: echo 'exec java -Djava.library.path="$$DIR" -jar "$$DIR"/altosui.jar' >> $@ chmod +x $@ -fat/altosui.jar: $(CLASSFILES) fat/classes/Manifest.txt +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 altosui/*.class libaltosJNI/*.class + cd ./fat/classes && jar cfm ../../$@ Manifest.txt images/* altosui/*.class libaltosJNI/*.class fat/classes/Manifest.txt: $(CLASSFILES) Makefile mkdir -p fat/classes @@ -163,7 +172,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES) cp $(DARWIN_EXTRA) darwin/AltOS cd darwin && zip -r ../$@ AltosUI.app AltOS -WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf +WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ICON) $(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi rm -f $@ diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index abb0823b..5ac708f9 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -50,11 +50,13 @@ Section "AltosUI Application" File "windows/AltOS/*.jar" File "windows/AltOS/*.dll" - CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui.jar" + File "windows/AltOS/*.ico" + + CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd Section "AltosUI Desktop Shortcut" - CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui.jar" + CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd Section "TeleMetrum and TeleDongle Firmware" -- cgit v1.2.3 From 887b11f6b9c81b9f15348d54017e700ca7dc5e55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:27:17 -0700 Subject: Use autotools for altosui and libaltos This switches from hand-written Makefiles to automake with libtool for these parts of the system. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 2 +- ao-tools/altosui/Makefile | 182 ---------------------------------- ao-tools/altosui/Makefile-standalone | 182 ++++++++++++++++++++++++++++++++++ ao-tools/altosui/Makefile.am | 165 ++++++++++++++++++++++++++++++ ao-tools/altosui/altos-windows.nsi | 20 ++-- ao-tools/altosui/altosui-fat | 4 + ao-tools/libaltos/.gitignore | 12 +++ ao-tools/libaltos/Makefile | 126 ----------------------- ao-tools/libaltos/Makefile-standalone | 126 +++++++++++++++++++++++ ao-tools/libaltos/Makefile.am | 27 +++++ configure.ac | 39 +++++++- 11 files changed, 566 insertions(+), 319 deletions(-) delete mode 100644 ao-tools/altosui/Makefile create mode 100644 ao-tools/altosui/Makefile-standalone create mode 100644 ao-tools/altosui/Makefile.am create mode 100755 ao-tools/altosui/altosui-fat create mode 100644 ao-tools/libaltos/.gitignore delete mode 100644 ao-tools/libaltos/Makefile create mode 100644 ao-tools/libaltos/Makefile-standalone create mode 100644 ao-tools/libaltos/Makefile.am diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index eb376be4..37625e8e 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -75,7 +75,7 @@ public class AltosUI extends JFrame { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; - java.net.URL imgURL = AltosUI.class.getResource("/images/altus-metrum-16x16.jpg"); + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); if (imgURL != null) setIconImage(new ImageIcon(imgURL).getImage()); diff --git a/ao-tools/altosui/Makefile b/ao-tools/altosui/Makefile deleted file mode 100644 index 90621f36..00000000 --- a/ao-tools/altosui/Makefile +++ /dev/null @@ -1,182 +0,0 @@ -.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 diff --git a/ao-tools/altosui/Makefile-standalone b/ao-tools/altosui/Makefile-standalone new file mode 100644 index 00000000..90621f36 --- /dev/null +++ b/ao-tools/altosui/Makefile-standalone @@ -0,0 +1,182 @@ +.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 diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am new file mode 100644 index 00000000..20c8b26d --- /dev/null +++ b/ao-tools/altosui/Makefile.am @@ -0,0 +1,165 @@ +JAVAROOT=classes + +CLASSPATH_ENV=CLASSPATH="classes/altosui/*:../libaltos/libaltosJNI/*:$(FREETTS)/*:/usr/share/java/*" + +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.ihx +FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0.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 + +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) + +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): Makefile + -rm -f "$@" + $(LN_S) "$(FREETTS)"/"$@" . + +$(LINUX_DIST): $(LINUX_FILES) + -rm -f $@ + -rm -rf linux + mkdir -p linux/AltOS + cp -a $(LINUX_FILES) linux/AltOS + 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 -a $(MACOSX_FILES) macosx/AltosUI.app/Contents/Resources/Java + cp -a $(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 $@" altos-windows.nsi \ No newline at end of file diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index 5ac708f9..6f38ac0e 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -2,8 +2,6 @@ Name "Altus Metrum Installer" -OutFile "Altos-Windows.exe" - ; Default install directory InstallDir "$PROGRAMFILES\AltusMetrum" @@ -47,10 +45,18 @@ SectionEnd Section "AltosUI Application" SetOutPath $INSTDIR - File "windows/AltOS/*.jar" - File "windows/AltOS/*.dll" + File "altosui.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 "windows/AltOS/*.ico" + File "../../icon/*.ico" CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd @@ -63,8 +69,8 @@ Section "TeleMetrum and TeleDongle Firmware" SetOutPath $INSTDIR - File "windows/AltOS/telemetrum-v1.0.ihx" - File "windows/AltOS/teledongle-v0.2.ihx" + File "../../src/telemetrum-v1.0/telemetrum-v1.0.ihx" + File "../../src/teledongle-v0.2/teledongle-v0.2.ihx" SectionEnd diff --git a/ao-tools/altosui/altosui-fat b/ao-tools/altosui/altosui-fat new file mode 100755 index 00000000..a95b78b8 --- /dev/null +++ b/ao-tools/altosui/altosui-fat @@ -0,0 +1,4 @@ +#!/bin/sh +me=`which "$0"` +dir=`dirname "$me"` +exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui.jar diff --git a/ao-tools/libaltos/.gitignore b/ao-tools/libaltos/.gitignore new file mode 100644 index 00000000..c490e6f8 --- /dev/null +++ b/ao-tools/libaltos/.gitignore @@ -0,0 +1,12 @@ +*.so +*.lo +*.la +*.java +*.class +.libs/ +classlibaltos.stamp +libaltos_wrap.c +libaltosJNI +cjnitest +libaltos.swig +swig_bindings/ diff --git a/ao-tools/libaltos/Makefile b/ao-tools/libaltos/Makefile deleted file mode 100644 index cb767c85..00000000 --- a/ao-tools/libaltos/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -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: diff --git a/ao-tools/libaltos/Makefile-standalone b/ao-tools/libaltos/Makefile-standalone new file mode 100644 index 00000000..4e438050 --- /dev/null +++ b/ao-tools/libaltos/Makefile-standalone @@ -0,0 +1,126 @@ +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: diff --git a/ao-tools/libaltos/Makefile.am b/ao-tools/libaltos/Makefile.am new file mode 100644 index 00000000..2f1d6fca --- /dev/null +++ b/ao-tools/libaltos/Makefile.am @@ -0,0 +1,27 @@ +JAVAC=javac +AM_CFLAGS="-I$(JVM_INCLUDE)" + +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 diff --git a/configure.ac b/configure.ac index fafc6b34..19ae0ac8 100644 --- a/configure.ac +++ b/configure.ac @@ -17,19 +17,50 @@ dnl 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 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" @@ -92,5 +123,7 @@ ao-tools/ao-list/Makefile 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 ]) -- cgit v1.2.3 From bc183400ab93d5902c52851319999cc77f27bc81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:35:17 -0700 Subject: altos: add some SDCDB config files --- src/telemetrum-v0.1-sky/.sdcdbrc | 1 + src/telemetrum-v1.0/.sdcdbrc | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/telemetrum-v0.1-sky/.sdcdbrc create mode 100644 src/telemetrum-v1.0/.sdcdbrc diff --git a/src/telemetrum-v0.1-sky/.sdcdbrc b/src/telemetrum-v0.1-sky/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v0.1-sky/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.0/.sdcdbrc b/src/telemetrum-v1.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. -- cgit v1.2.3 From 2808bba3efa1cff133cc060dabff06fab8b75388 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:58:52 -0700 Subject: Ignore libtool files. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 16ff1f7b..13c9b43d 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,9 @@ .deps TAGS aclocal.m4 +libtool +ltmain.sh +src/Version src/ao_flight_test src/ao_gps_test src/ao_gps_test_skytraq -- cgit v1.2.3 From aed59e1c057c13e28fd368dc2592aa4628211097 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:59:11 -0700 Subject: Add version numbers to released files. Set version to 0.7.1 Instead of using git revision counts for version numbers, use explicit versions numbers configured in the configure.ac file. Expose published files with version numbers. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 8 ++++---- ao-tools/altosui/altos-windows.nsi | 4 ++-- configure.ac | 2 +- src/Makefile | 2 ++ src/Makefile.proto | 6 ++---- src/Version.in | 1 + src/teledongle-v0.1/.gitignore | 2 +- src/teledongle-v0.1/Makefile.defs | 2 +- src/teledongle-v0.2/.gitignore | 2 +- src/teledongle-v0.2/Makefile.defs | 2 +- src/telemetrum-v0.1-sirf/.gitignore | 2 +- src/telemetrum-v0.1-sirf/Makefile.defs | 2 +- src/telemetrum-v0.1-sky/.gitignore | 2 +- src/telemetrum-v0.1-sky/Makefile.defs | 2 +- src/telemetrum-v1.0/.gitignore | 2 +- src/telemetrum-v1.0/Makefile.defs | 2 +- src/tidongle/.gitignore | 2 +- src/tidongle/Makefile.defs | 2 +- 18 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 src/Version.in diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 20c8b26d..ed7e2f76 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -66,8 +66,8 @@ 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.ihx -FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0.ihx +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 @@ -77,7 +77,7 @@ WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(FREETTS_CLASS) -LINUX_FILES=$(FAT_FILES) libaltos.so +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) MACOSX_FILES=$(FAT_FILES) libaltos.dylib MACOSX_EXTRA=$(FIRMWARE) @@ -162,4 +162,4 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) $(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi -rm -f $@ - makensis -Oaltos-windows.log "-XOutFile $@" altos-windows.nsi \ No newline at end of file + makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi \ No newline at end of file diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index 6f38ac0e..c8539a5c 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -69,8 +69,8 @@ Section "TeleMetrum and TeleDongle Firmware" SetOutPath $INSTDIR - File "../../src/telemetrum-v1.0/telemetrum-v1.0.ihx" - File "../../src/teledongle-v0.2/teledongle-v0.2.ihx" + File "../../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" + File "../../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" SectionEnd diff --git a/configure.ac b/configure.ac index 19ae0ac8..d376af3f 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,6 @@ fi AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S -AC_PROG_RANLIB AC_PROG_LIBTOOL PKG_PROG_PKG_CONFIG @@ -126,4 +125,5 @@ ao-tools/ao-view/Makefile ao-tools/libaltos/Makefile ao-tools/altosui/Makefile ao-utils/Makefile +src/Version ]) diff --git a/src/Makefile b/src/Makefile index 24f562e1..95d24425 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,8 @@ # 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 diff --git a/src/Makefile.proto b/src/Makefile.proto index 59a3b8a6..b23eb257 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -10,7 +10,7 @@ vpath ao-make-product.5c .. CC=sdcc ifndef VERSION -VERSION=$(shell git describe) +include ../Version endif CFLAGS=--model-small --debug --opt-code-speed @@ -214,11 +214,9 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ -ao_product.h: ao-make-product.5c always +ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -always: - ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< diff --git a/src/Version.in b/src/Version.in new file mode 100644 index 00000000..aff9490b --- /dev/null +++ b/src/Version.in @@ -0,0 +1 @@ +VERSION=@VERSION@ diff --git a/src/teledongle-v0.1/.gitignore b/src/teledongle-v0.1/.gitignore index 96c802bd..9826814b 100644 --- a/src/teledongle-v0.1/.gitignore +++ b/src/teledongle-v0.1/.gitignore @@ -1,2 +1,2 @@ -teledongle-v0.1 +teledongle-v0.1* ao_product.h diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index be7741d8..ceb80b7a 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -1,4 +1,4 @@ -PROG = teledongle-v0.1.ihx +PROG = teledongle-v0.1-$(VERSION).ihx SRC = \ $(TD_SRC) \ diff --git a/src/teledongle-v0.2/.gitignore b/src/teledongle-v0.2/.gitignore index af79a766..f6ea8c6c 100644 --- a/src/teledongle-v0.2/.gitignore +++ b/src/teledongle-v0.2/.gitignore @@ -1,2 +1,2 @@ -teledongle-v0.2 +teledongle-v0.2* ao_product.h diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index cbec7805..ea9713b6 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -1,4 +1,4 @@ -PROG = teledongle-v0.2.ihx +PROG = teledongle-v0.2-$(VERSION).ihx SRC = \ $(TD_SRC) \ diff --git a/src/telemetrum-v0.1-sirf/.gitignore b/src/telemetrum-v0.1-sirf/.gitignore index 6d584f36..7698f5aa 100644 --- a/src/telemetrum-v0.1-sirf/.gitignore +++ b/src/telemetrum-v0.1-sirf/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sirf +telemetrum-v0.1-sirf* ao_product.h diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 2ce6e6ed..a7310fbc 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v0.1-sirf.ihx +PROG = telemetrum-v0.1-sirf-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/telemetrum-v0.1-sky/.gitignore b/src/telemetrum-v0.1-sky/.gitignore index 5a9fafb5..d25d7ad9 100644 --- a/src/telemetrum-v0.1-sky/.gitignore +++ b/src/telemetrum-v0.1-sky/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sky +telemetrum-v0.1-sky* ao_product.h diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index 098ac547..000287ba 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v0.1-sky.ihx +PROG = telemetrum-v0.1-sky-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/telemetrum-v1.0/.gitignore b/src/telemetrum-v1.0/.gitignore index 76228093..c2212151 100644 --- a/src/telemetrum-v1.0/.gitignore +++ b/src/telemetrum-v1.0/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.2 +telemetrum-* ao_product.h diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index 624ce6e8..010578df 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v1.0.ihx +PROG = telemetrum-v1.0-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/tidongle/.gitignore b/src/tidongle/.gitignore index 3323f640..3888a0f9 100644 --- a/src/tidongle/.gitignore +++ b/src/tidongle/.gitignore @@ -1,2 +1,2 @@ -tidongle +tidongle* ao_product.h diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index fdd51732..0e13cb20 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -1,4 +1,4 @@ -PROG = tidongle.ihx +PROG = tidongle-$(VERSION).ihx SRC = \ $(TI_SRC) -- cgit v1.2.3 From 148b927c3b8bc7b7b5c5356392032faf2b1203d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 18:04:04 -0700 Subject: Add top-level 'fat' target to aid building distribution files Signed-off-by: Keith Packard --- Makefile.am | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile.am b/Makefile.am index 39e7c244..66d7cb55 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,3 +11,6 @@ ChangeLog: (touch ChangeLog; echo 'git directory not found: installing possibly empty changelog.' >&2) dist-hook: ChangeLog + +fat: + cd ao-tools/altosui && $(MAKE) fat -- cgit v1.2.3 From 044fd27449c70474f51b99dec25fd23d3c03a559 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 18:20:45 -0700 Subject: altosui: Fix windows installer to ship correct files Was shipping altosui.jar instead of altosui-fat.jar Signed-off-by: Keith Packard --- ao-tools/altosui/.gitignore | 15 ++++++++++----- ao-tools/altosui/Makefile.am | 7 ++++--- ao-tools/altosui/altos-windows.nsi | 6 +++--- ao-tools/libaltos/Makefile.am | 1 + 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/ao-tools/altosui/.gitignore b/ao-tools/altosui/.gitignore index 63672058..89be1d53 100644 --- a/ao-tools/altosui/.gitignore +++ b/ao-tools/altosui/.gitignore @@ -1,14 +1,19 @@ windows/ linux/ -darwin/ +macosx/ fat/ Manifest.txt +Manifest-fat.txt libaltosJNI classes altosui -Altos-Linux.tgz -Altos-Mac.zip -Altos-Windows.exe +altosui-test +classaltosui.stamp +Altos-Linux-*.tar.bz2 +Altos-Mac-*.zip +Altos-Windows-*.exe +*.dll +*.dylib +*.so *.jar *.class -altosui diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index ed7e2f76..13bceae2 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -1,4 +1,5 @@ JAVAROOT=classes +AM_JAVACFLAGS=-encoding UTF-8 CLASSPATH_ENV=CLASSPATH="classes/altosui/*:../libaltos/libaltosJNI/*:$(FREETTS)/*:/usr/share/java/*" @@ -77,14 +78,14 @@ WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(FREETTS_CLASS) -LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) 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) +all-local: classes/altosui $(JAR) $(FATJAR) altosui altosui-test clean-local: -rm -rf classes/altosui $(JAR) $(FATJAR) \ @@ -139,7 +140,7 @@ $(LIBALTOS): -rm -f "$@" $(LN_S) ../libaltos/"$@" . -$(FREETTS_CLASS): Makefile +$(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index c8539a5c..6ebec214 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -45,7 +45,7 @@ SectionEnd Section "AltosUI Application" SetOutPath $INSTDIR - File "altosui.jar" + File "altosui-fat.jar" File "cmudict04.jar" File "cmulex.jar" File "cmu_time_awb.jar" @@ -58,11 +58,11 @@ Section "AltosUI Application" File "../../icon/*.ico" - CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui.jar" "" "$INSTDIR\altus-metrum.ico" + CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd Section "AltosUI Desktop Shortcut" - CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui.jar" "" "$INSTDIR\altus-metrum.ico" + CreateShortCut "$DESKTOP\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd Section "TeleMetrum and TeleDongle Firmware" diff --git a/ao-tools/libaltos/Makefile.am b/ao-tools/libaltos/Makefile.am index 2f1d6fca..4d29d80e 100644 --- a/ao-tools/libaltos/Makefile.am +++ b/ao-tools/libaltos/Makefile.am @@ -1,5 +1,6 @@ JAVAC=javac AM_CFLAGS="-I$(JVM_INCLUDE)" +AM_JAVACFLAGS=-encoding UTF-8 lib_LTLIBRARIES=libaltos.la -- cgit v1.2.3 From 828e9e4c68e3ac90b6ba2e9fd5f131a9975f7e4a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 18:39:58 -0700 Subject: altosui: Fix up Mac OSX .zip file Must contain 'altosui.jar' instead of altosui-fat.jar. Also, was using 'cp -a' instead of 'cp -p' which made files represented by symlinks not end up in the archive. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 13bceae2..65a3cf9a 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -157,8 +157,9 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) mkdir macosx cp -a AltosUI.app macosx/ mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java - cp -a $(MACOSX_FILES) macosx/AltosUI.app/Contents/Resources/Java - cp -a $(MACOSX_EXTRA) macosx/AltOS + 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 -- cgit v1.2.3 From c3a17c71a45207dd715d537704f161de9219f0d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 18:49:22 -0700 Subject: altosui: Fix linux fat distribution Again, use 'cp -p' instead of 'cp -a' to get files into the archive instead of links. Also, make the shell script 'altosui' instead of 'altosui-fat'. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 9 ++++++--- ao-tools/altosui/altosui-fat | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 65a3cf9a..bc8dbc0d 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -78,7 +78,8 @@ WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(FREETTS_CLASS) -LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) altosui-fat +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) +LINUX_EXTRA=altosui-fat MACOSX_FILES=$(FAT_FILES) libaltos.dylib MACOSX_EXTRA=$(FIRMWARE) @@ -144,11 +145,13 @@ $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . -$(LINUX_DIST): $(LINUX_FILES) +$(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA) -rm -f $@ -rm -rf linux mkdir -p linux/AltOS - cp -a $(LINUX_FILES) 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) diff --git a/ao-tools/altosui/altosui-fat b/ao-tools/altosui/altosui-fat index a95b78b8..9e5a8f15 100755 --- a/ao-tools/altosui/altosui-fat +++ b/ao-tools/altosui/altosui-fat @@ -1,4 +1,4 @@ #!/bin/sh me=`which "$0"` dir=`dirname "$me"` -exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui.jar +exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar -- cgit v1.2.3 From eb0e7a59f0806734a4c959a3ce7c57f71cbe3986 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 00:57:38 -0700 Subject: altosui: Return AO_LOG_INVALID instead of exception for eeprom files When an eeprom file contains an invalid line, just return AO_LOG_INVALID instead of throwing an exception. This allows us to replay and parse files with extraneous serial communication. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromRecord.java | 99 ++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java index 4d0817ab..95cbe015 100644 --- a/ao-tools/altosui/AltosEepromRecord.java +++ b/ao-tools/altosui/AltosEepromRecord.java @@ -47,7 +47,7 @@ public class AltosEepromRecord { public String data; public boolean tick_valid; - public AltosEepromRecord (String line) throws ParseException { + public AltosEepromRecord (String line) { tick_valid = false; tick = 0; a = 0; @@ -55,52 +55,61 @@ public class AltosEepromRecord { 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; } -- cgit v1.2.3 From b2aa689bf3d61e4a3ebe7c828162d1be20aad0f6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 00:59:54 -0700 Subject: altosui: Remove debugging printf from AltosEepromReader These were in place while validing the GPS data reconstruction code that handles eeprom files missing the first GPS date line due to the record overwriting bug in old firmware versions. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 0705d44e..e2a780ac 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -177,12 +177,6 @@ public class AltosEepromReader extends AltosReader { state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT; - System.out.printf("GPS %2d:%02d:%02d%s%s%s %d\n", - state.gps.hour, state.gps.minute, state.gps.second, - state.gps.connected ? " connected" : "", - state.gps.locked ? " locked" : "", - state.gps.date_valid ? " date_valid" : "", - state.gps.nsat); break; case Altos.AO_LOG_GPS_LAT: int lat32 = record.a | (record.b << 16); @@ -306,10 +300,6 @@ public class AltosEepromReader extends AltosReader { int new_hours = (new_minutes / 60); int new_hour = (new_hours % 24); - System.out.printf("Synthesizing time good %2d:%02d:%02d bad %2d:%02d:%02d\n", - hour, minute, second, - new_hour, new_minute, new_second); - bad.a = new_hour + (new_minute << 8); bad.b = new_second + (flags << 8); } @@ -365,13 +355,9 @@ public class AltosEepromReader extends AltosReader { if (record.cmd == Altos.AO_LOG_GPS_TIME) { last_gps_time = record; if (missing_time) { - System.out.printf("Going back to clean up broken GPS time records\n"); Iterator iterator = records.iterator(); while (iterator.hasNext()) { AltosOrderedRecord old = iterator.next(); - if (old.cmd == Altos.AO_LOG_GPS_TIME) { - System.out.printf("Old time record %d, %d\n", old.a, old.b); - } if (old.cmd == Altos.AO_LOG_GPS_TIME && old.a == -1 && old.b == -1) { @@ -389,10 +375,9 @@ public class AltosEepromReader extends AltosReader { -1, -1, index-1); if (last_gps_time != null) update_time(last_gps_time, add_gps_time); - else { - System.out.printf("early GPS missing time\n"); + else missing_time = true; - } + records.add(add_gps_time); record.index = index++; } -- cgit v1.2.3 From 2d58f319a7c1a6a8ccc6a539722009996ba886ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:01:10 -0700 Subject: altosui: Eeprom files contain only one date; save it. While reading eeprom files, the GPS record is reconstructed each time the system sees the first GPS log item (the time field), but as the date isn't repeated, we need to copy it from the old GPS data record. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index e2a780ac..ac54ff44 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -116,7 +116,7 @@ public class AltosEepromReader extends AltosReader { if (last_reported) return null; last_reported = true; - return state; + return new AltosRecord(state); } record = record_iterator.next(); @@ -167,7 +167,15 @@ public class AltosEepromReader extends AltosReader { 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); @@ -197,7 +205,7 @@ public class AltosEepromReader extends AltosReader { } 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; @@ -334,6 +342,8 @@ public class AltosEepromReader extends AltosReader { 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) -- cgit v1.2.3 From 3d99584fcfe43b22e8581874e0ac77ce3d635d48 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:03:18 -0700 Subject: altosui: Add elevation and range data to main display Reported by voice, it's useful to see these on the display as well. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 37625e8e..6a1814ff 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -231,11 +231,19 @@ public class AltosUI extends JFrame { 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'); -- cgit v1.2.3 From 6205547ec7191aab0259a8449520e966a96129e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:08:50 -0700 Subject: altosui: When replay thread is interrupted, don't make final report Normally, the replay process makes one final report after the file has been parsed. However, if the reading process is interrupted to display something else, this report is just annoying, so don't make it. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 6a1814ff..49153766 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -384,11 +384,12 @@ public class AltosUI extends JFrame { AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } - void close() { } + 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; @@ -418,14 +419,18 @@ public class AltosUI extends JFrame { } } } 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) {} } } @@ -446,7 +451,7 @@ public class AltosUI extends JFrame { return new AltosTelemetry(l.line); } - void close() { + void close(boolean interrupted) { serial.close(); serial.remove_monitor(telem); } @@ -530,8 +535,9 @@ public class AltosUI extends JFrame { return null; } - public void close () { - report(); + public void close (boolean interrupted) { + if (!interrupted) + report(); } public ReplayThread(AltosReader in_reader, String in_name) { -- cgit v1.2.3 From 410ba89eef9c9817eef81b702966cb88820ff7c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:13:01 -0700 Subject: altosui: Start idle thread after the rocket leaves the pad This makes the first altitude report time consistently 10 seconds after launch, instead of some random time depending on when the rocket launched relative to the time the device connection was made. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 49153766..fbce5e14 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -277,6 +277,7 @@ public class AltosUI extends JFrame { class IdleThread extends Thread { + boolean started; private AltosState state; int reported_landing; @@ -346,6 +347,10 @@ public class AltosUI extends JFrame { public void notice(AltosState new_state) { AltosState old_state = state; state = new_state; + if (!started && state.state > Altos.ao_flight_pad) { + started = true; + start(); + } if (old_state != null && old_state.state != state.state) report(false); } @@ -398,7 +403,6 @@ public class AltosUI extends JFrame { info_reset(); info_finish(); - idle_thread.start(); try { for (;;) { try { -- cgit v1.2.3 From 4dec5c36702d76dc95beada7c1d3222a638a2cbb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:19:11 -0700 Subject: altosui: Add AltosVoice.drain() to wait for queued speech to finish drain() blocks until all pending phrases have been processed, allowing the UI code to avoid pending data that will end up stale by the time it is emitted. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosVoice.java | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java index ebe9d5a8..ac13ee14 100644 --- a/ao-tools/altosui/AltosVoice.java +++ b/ao-tools/altosui/AltosVoice.java @@ -27,6 +27,7 @@ public class AltosVoice implements Runnable { Voice voice; LinkedBlockingQueue phrases; Thread thread; + boolean busy; final static String voice_name = "kevin16"; @@ -35,15 +36,30 @@ public class AltosVoice implements Runnable { 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) { } } @@ -58,6 +74,7 @@ public class AltosVoice implements Runnable { } public AltosVoice () { + busy = false; voice_manager = VoiceManager.getInstance(); voice = voice_manager.getVoice(voice_name); if (voice != null) { -- cgit v1.2.3 From 9941b05a1d03dafd6cd899b5fe999ed769efb1d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:21:14 -0700 Subject: altosui: Prevent voice altitude data from queueing up When flight status changes rapidly, the queue of voice data can get quite long. This change does two things -- first, it remembers when the altitude reporting happens due to flight events and delays the periodic reporting until a suitable time after that, second it ensures that the voice data has all been delivered before generating a new altitude report. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 58 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index fbce5e14..3aaeb888 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -280,6 +280,8 @@ public class AltosUI extends JFrame { boolean started; private AltosState state; int reported_landing; + int report_interval; + long report_time; public synchronized void report(boolean last) { if (state == null) @@ -331,51 +333,88 @@ public class AltosUI extends JFrame { } } + 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(20000); + 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 (old_state != null && old_state.state != state.state) - report(false); + + 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 { @@ -398,6 +437,7 @@ public class AltosUI extends JFrame { String line; AltosState state = null; AltosState old_state = null; + boolean told; idle_thread = new IdleThread(); @@ -413,8 +453,8 @@ public class AltosUI extends JFrame { state = new AltosState(record, state); update(state); show(state, crc_errors); - tell(state, old_state); - idle_thread.notice(state); + 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) { -- cgit v1.2.3 From 38e1d87c8d449866faac026577fefa9a118428cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:23:53 -0700 Subject: altosui: Use local .class files in the classpath This ensures that compiling only a few changed files will locate the old .class files instead of using a stale .jar file. --- ao-tools/altosui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index bc8dbc0d..98482823 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -1,7 +1,7 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -CLASSPATH_ENV=CLASSPATH="classes/altosui/*:../libaltos/libaltosJNI/*:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" altosui_JAVA = \ AltosChannelMenu.java \ -- cgit v1.2.3 From 6c653a4cba5fef8d49261cf1c024f3e86e9058c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:52:36 -0700 Subject: altosui: Record flight number when scanning file, not when running The very first record in the eeprom is the flight number, but it is time-stamped with the 'boost' time, and so it gets sorted until much later, delaying the return of data until the rocket enters boost mode. This drops all of the nice pad GPS and state date on the floor. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index ac54ff44..86bbaee0 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -130,9 +130,7 @@ public class AltosEepromReader extends AltosReader { 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; @@ -351,6 +349,11 @@ public class AltosEepromReader extends AltosReader { saw_boost = true; boost_tick = tick; } + if (record.cmd == Altos.AO_LOG_FLIGHT) { + state.ground_accel = record.a; + state.flight = record.b; + seen |= seen_flight; + } /* Two firmware bugs caused the loss of some GPS data. * The flight date would never be recorded, and often -- cgit v1.2.3 From b61fec225ada6a9e252e4c7920101ee18c77cbdc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 01:55:56 -0700 Subject: altosui: eeprom files place 'boost' time in the flight number record. Instead of looking for the first state change record, use the Flight record to get the boost tick. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 86bbaee0..cb82f9a9 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -101,8 +101,6 @@ public class AltosEepromReader extends AltosReader { int gps_tick; - boolean saw_boost; - int boost_tick; boolean saw_gps_date; @@ -343,15 +341,10 @@ public class AltosEepromReader extends AltosReader { 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 = tick; - } if (record.cmd == Altos.AO_LOG_FLIGHT) { state.ground_accel = record.a; state.flight = record.b; + boost_tick = tick; seen |= seen_flight; } -- cgit v1.2.3 From 3d49d5f69b41c27003dbc5ccf1899014bd13bd99 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Sep 2010 02:05:06 -0700 Subject: altosui: ensure that 'altosui' script is installed. Pass arguments along. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 6 ++++-- ao-tools/altosui/altosui-fat | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 98482823..dd4b31e6 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -3,6 +3,8 @@ AM_JAVACFLAGS=-encoding UTF-8 CLASSPATH_ENV=CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" +bin_SCRIPTS=altosui + altosui_JAVA = \ AltosChannelMenu.java \ AltosConfig.java \ @@ -129,12 +131,12 @@ Manifest-fat.txt: altosui: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="$(libdir)" -jar "$(altosuidir)/altosui.jar"' >> $@ + 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' >> $@ + echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos" -jar altosui.jar "$$*"' >> $@ chmod +x $@ $(LIBALTOS): diff --git a/ao-tools/altosui/altosui-fat b/ao-tools/altosui/altosui-fat index 9e5a8f15..95b1c051 100755 --- a/ao-tools/altosui/altosui-fat +++ b/ao-tools/altosui/altosui-fat @@ -1,4 +1,4 @@ #!/bin/sh me=`which "$0"` dir=`dirname "$me"` -exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar +exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar "$@" -- cgit v1.2.3 From 3e5824b9a71971ce99bfe38a1e860b421e265f02 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 15:43:47 -0600 Subject: update changelogs for Debian build --- ChangeLog | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 33 +++++++ 2 files changed, 303 insertions(+) diff --git a/ChangeLog b/ChangeLog index 70911434..de8a8fb0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,273 @@ +commit 3d49d5f69b41c27003dbc5ccf1899014bd13bd99 +Author: Keith Packard +Date: Sun Sep 5 02:05:06 2010 -0700 + + altosui: ensure that 'altosui' script is installed. Pass arguments along. + + Signed-off-by: Keith Packard + +commit b61fec225ada6a9e252e4c7920101ee18c77cbdc +Author: Keith Packard +Date: Sun Sep 5 01:55:56 2010 -0700 + + altosui: eeprom files place 'boost' time in the flight number record. + + Instead of looking for the first state change record, use the Flight + record to get the boost tick. + + Signed-off-by: Keith Packard + +commit 6c653a4cba5fef8d49261cf1c024f3e86e9058c6 +Author: Keith Packard +Date: Sun Sep 5 01:52:36 2010 -0700 + + altosui: Record flight number when scanning file, not when running + + The very first record in the eeprom is the flight number, but it is + time-stamped with the 'boost' time, and so it gets sorted until much + later, delaying the return of data until the rocket enters boost + mode. This drops all of the nice pad GPS and state date on the floor. + + Signed-off-by: Keith Packard + +commit 38e1d87c8d449866faac026577fefa9a118428cb +Author: Keith Packard +Date: Sun Sep 5 01:23:53 2010 -0700 + + altosui: Use local .class files in the classpath + + This ensures that compiling only a few changed files will + locate the old .class files instead of using a stale .jar file. + +commit 9941b05a1d03dafd6cd899b5fe999ed769efb1d6 +Author: Keith Packard +Date: Sun Sep 5 01:21:14 2010 -0700 + + altosui: Prevent voice altitude data from queueing up + + When flight status changes rapidly, the queue of voice data can get + quite long. This change does two things -- first, it remembers when + the altitude reporting happens due to flight events and delays the + periodic reporting until a suitable time after that, second it ensures + that the voice data has all been delivered before generating a new + altitude report. + + Signed-off-by: Keith Packard + +commit 4dec5c36702d76dc95beada7c1d3222a638a2cbb +Author: Keith Packard +Date: Sun Sep 5 01:19:11 2010 -0700 + + altosui: Add AltosVoice.drain() to wait for queued speech to finish + + drain() blocks until all pending phrases have been processed, allowing + the UI code to avoid pending data that will end up stale by the time + it is emitted. + + Signed-off-by: Keith Packard + +commit 410ba89eef9c9817eef81b702966cb88820ff7c4 +Author: Keith Packard +Date: Sun Sep 5 01:13:01 2010 -0700 + + altosui: Start idle thread after the rocket leaves the pad + + This makes the first altitude report time consistently 10 seconds + after launch, instead of some random time depending on when the rocket + launched relative to the time the device connection was made. + + Signed-off-by: Keith Packard + +commit 6205547ec7191aab0259a8449520e966a96129e6 +Author: Keith Packard +Date: Sun Sep 5 01:08:50 2010 -0700 + + altosui: When replay thread is interrupted, don't make final report + + Normally, the replay process makes one final report after the file has + been parsed. However, if the reading process is interrupted to display + something else, this report is just annoying, so don't make it. + + Signed-off-by: Keith Packard + +commit 3d99584fcfe43b22e8581874e0ac77ce3d635d48 +Author: Keith Packard +Date: Sun Sep 5 01:03:18 2010 -0700 + + altosui: Add elevation and range data to main display + + Reported by voice, it's useful to see these on the display as well. + + Signed-off-by: Keith Packard + +commit 2d58f319a7c1a6a8ccc6a539722009996ba886ab +Author: Keith Packard +Date: Sun Sep 5 01:01:10 2010 -0700 + + altosui: Eeprom files contain only one date; save it. + + While reading eeprom files, the GPS record is reconstructed each time + the system sees the first GPS log item (the time field), but as the + date isn't repeated, we need to copy it from the old GPS data record. + + Signed-off-by: Keith Packard + +commit b2aa689bf3d61e4a3ebe7c828162d1be20aad0f6 +Author: Keith Packard +Date: Sun Sep 5 00:59:54 2010 -0700 + + altosui: Remove debugging printf from AltosEepromReader + + These were in place while validing the GPS data reconstruction code + that handles eeprom files missing the first GPS date line due to the + record overwriting bug in old firmware versions. + + Signed-off-by: Keith Packard + +commit eb0e7a59f0806734a4c959a3ce7c57f71cbe3986 +Author: Keith Packard +Date: Sun Sep 5 00:57:38 2010 -0700 + + altosui: Return AO_LOG_INVALID instead of exception for eeprom files + + When an eeprom file contains an invalid line, just return + AO_LOG_INVALID instead of throwing an exception. This allows us to + replay and parse files with extraneous serial communication. + + Signed-off-by: Keith Packard + +commit c3a17c71a45207dd715d537704f161de9219f0d7 +Author: Keith Packard +Date: Sat Sep 4 18:49:22 2010 -0700 + + altosui: Fix linux fat distribution + + Again, use 'cp -p' instead of 'cp -a' to get files into the archive + instead of links. Also, make the shell script 'altosui' instead of + 'altosui-fat'. + + Signed-off-by: Keith Packard + +commit 828e9e4c68e3ac90b6ba2e9fd5f131a9975f7e4a +Author: Keith Packard +Date: Sat Sep 4 18:39:58 2010 -0700 + + altosui: Fix up Mac OSX .zip file + + Must contain 'altosui.jar' instead of altosui-fat.jar. + Also, was using 'cp -a' instead of 'cp -p' which made files + represented by symlinks not end up in the archive. + + Signed-off-by: Keith Packard + +commit 044fd27449c70474f51b99dec25fd23d3c03a559 +Author: Keith Packard +Date: Sat Sep 4 18:20:45 2010 -0700 + + altosui: Fix windows installer to ship correct files + + Was shipping altosui.jar instead of altosui-fat.jar + + Signed-off-by: Keith Packard + +commit 148b927c3b8bc7b7b5c5356392032faf2b1203d3 +Author: Keith Packard +Date: Sat Sep 4 18:04:04 2010 -0700 + + Add top-level 'fat' target to aid building distribution files + + Signed-off-by: Keith Packard + +commit aed59e1c057c13e28fd368dc2592aa4628211097 +Author: Keith Packard +Date: Sat Sep 4 17:59:11 2010 -0700 + + Add version numbers to released files. Set version to 0.7.1 + + Instead of using git revision counts for version numbers, use explicit + versions numbers configured in the configure.ac file. Expose published + files with version numbers. + + Signed-off-by: Keith Packard + +commit 2808bba3efa1cff133cc060dabff06fab8b75388 +Author: Keith Packard +Date: Sat Sep 4 17:58:52 2010 -0700 + + Ignore libtool files. + +commit bc183400ab93d5902c52851319999cc77f27bc81 +Author: Keith Packard +Date: Sat Sep 4 17:35:17 2010 -0700 + + altos: add some SDCDB config files + +commit 887b11f6b9c81b9f15348d54017e700ca7dc5e55 +Author: Keith Packard +Date: Sat Sep 4 17:27:17 2010 -0700 + + Use autotools for altosui and libaltos + + This switches from hand-written Makefiles to automake with libtool + for these parts of the system. + + Signed-off-by: Keith Packard + +commit e844e8a0695e27af6f8e3e37a5e3bcc865b862e3 +Author: Keith Packard +Date: Sat Sep 4 01:13:42 2010 -0700 + + altosui: Add icons to application and Windows menus. + + Use the altus-metrum icon for an application icon and a windows start + menu/desktop icon. + + Signed-off-by: Keith Packard + +commit e9ea28504c646fc25791aab09b9e5faf73e0ac0c +Author: Keith Packard +Date: Sat Sep 4 01:08:34 2010 -0700 + + icon: add some icons for application programs + + altus-metrum.ico: Windows ICO file + altus-metrum-16x16.jpg: 16x16 jpg image for java + + Signed-off-by: Keith Packard + +commit f550677df016070430ed38bfa2b2be33f1b8c40a +Author: Keith Packard +Date: Sat Sep 4 00:16:41 2010 -0700 + + altosui: oops. renamed the nsis file to altos-windows.nsi + + And forgot to change the dependency in the Makefile + + Signed-off-by: Keith Packard + +commit c0988ddbf104ea729090c2e7e2a28cc6dc9e90f6 +Author: Keith Packard +Date: Sat Sep 4 00:14:15 2010 -0700 + + altosui: ignore built files + +commit ecb4a09535b6a8da0765010489a96e605dbdeb46 +Author: Keith Packard +Date: Sat Sep 4 00:13:11 2010 -0700 + + altosui: Add windows installer build using 'nsis' + + nsis happens to be packaged in debian, and it appears to build usable + installers, which is all very cool. + + Signed-off-by: Keith Packard + +commit bf22923cd8b4f6f954718358b411b5b10d8e7b4d +Author: Bdale Garbee +Date: Sat Sep 4 00:46:29 2010 -0400 + + update changelogs for Debian build + commit 59798c6fd11502a9c8b66090c23ba50eb250692e Author: Keith Packard Date: Fri Sep 3 12:43:45 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 2005b64f..f46dfe82 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,36 @@ +altos (0.7+79+g3d49d5f) unstable; urgency=low + + [ Keith Packard ] + * altosui: Add windows installer build using 'nsis' + * altosui: ignore built files + * altosui: oops. renamed the nsis file to altos-windows.nsi + * icon: add some icons for application programs + * altosui: Add icons to application and Windows menus. + * Use autotools for altosui and libaltos + * altos: add some SDCDB config files + * Ignore libtool files. + * Add version numbers to released files. Set version to 0.7.1 + * Add top-level 'fat' target to aid building distribution files + * altosui: Fix windows installer to ship correct files + * altosui: Fix up Mac OSX .zip file + * altosui: Fix linux fat distribution + * altosui: Return AO_LOG_INVALID instead of exception for eeprom files + * altosui: Remove debugging printf from AltosEepromReader + * altosui: Eeprom files contain only one date; save it. + * altosui: Add elevation and range data to main display + * altosui: When replay thread is interrupted, don't make final report + * altosui: Start idle thread after the rocket leaves the pad + * altosui: Add AltosVoice.drain() to wait for queued speech to finish + * altosui: Prevent voice altitude data from queueing up + * altosui: Use local .class files in the classpath + * altosui: Record flight number when scanning file, not when running + * altosui: eeprom files place 'boost' time in the flight number + record. + * altosui: ensure that 'altosui' script is installed. Pass arguments + along. + + -- Bdale Garbee Thu, 09 Sep 2010 15:43:28 -0600 + altos (0.7+53+g59798c6) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 012e7176954a6b74b3b667317be0f6dc41d7ab70 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 15:51:02 -0600 Subject: add libtool to build deps --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 690eb78f..712e00d3 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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 +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, libtool Standards-Version: 3.9.1 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 15da683c2f747baef49c8b8d321a86faede0de30 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 15:51:50 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index de8a8fb0..e87431ba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 012e7176954a6b74b3b667317be0f6dc41d7ab70 +Author: Bdale Garbee +Date: Thu Sep 9 15:51:02 2010 -0600 + + add libtool to build deps + +commit 3e5824b9a71971ce99bfe38a1e860b421e265f02 +Author: Bdale Garbee +Date: Thu Sep 9 15:43:47 2010 -0600 + + update changelogs for Debian build + commit 3d49d5f69b41c27003dbc5ccf1899014bd13bd99 Author: Keith Packard Date: Sun Sep 5 02:05:06 2010 -0700 diff --git a/debian/changelog b/debian/changelog index f46dfe82..572af3e6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,7 @@ -altos (0.7+79+g3d49d5f) unstable; urgency=low +altos (0.7+81+g012e717) unstable; urgency=low + + [ Bdale Garbee ] + * add libtool to build deps [ Keith Packard ] * altosui: Add windows installer build using 'nsis' -- cgit v1.2.3 From 16980b848651a6b20a0b458446f0a19fb517539d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 15:10:25 -0700 Subject: altosui: Add explicit requirement to create classes directory The implicit ordering doesn't appear reliable. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index dd4b31e6..4bb67c97 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -91,8 +91,8 @@ 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) \ + -rm -rf classes $(JAR) $(FATJAR) \ + $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test macosx linux @@ -109,6 +109,11 @@ install-altosuiJAVA: altosui.jar classes/altosui: mkdir -p classes/altosui +classaltosui.stamp: classes + +classes: + mkdir -p classes + $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) jar cfm $@ Manifest.txt \ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ -- cgit v1.2.3 From b456bd9d7bcd9d968e43c38eeb6fa6ad8c58f895 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 15:11:41 -0700 Subject: altosui: fix telemetrum.inf FFFE:000A product names on AMD64 and ia64 This appears to matter to Vista. Dunno why. Signed-off-by: Keith Packard --- ao-tools/altosui/altos-windows.nsi | 3 +++ telemetrum.inf | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index 6ebec214..37777fd6 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -40,6 +40,9 @@ Section "Install Driver" InstDriver SetOutPath $TEMP File "../../telemetrum.inf" InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf" + + SetOutPath $INSTDIR + File "../../telemetrum.inf" SectionEnd Section "AltosUI Application" diff --git a/telemetrum.inf b/telemetrum.inf index 0a81084b..0d1a5534 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -6,7 +6,7 @@ Signature = "$Windows NT$" Class = Modem ClassGUID ={4D36E96D-E325-11CE-BFC1-08002BE10318} Provider = %Mfg% -DriverVer = 08/05/2010,3.1.0.41 +DriverVer = 08/05/2010,7.1.0.0 [Manufacturer] %Mfg% = Models, NTx86, NTamd64, NTia64 @@ -18,13 +18,13 @@ DriverVer = 08/05/2010,3.1.0.41 %TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D [Models.NTamd64] -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A %TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B %TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C %TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D [Models.NTia64] -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A %TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B %TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C %TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D @@ -40,7 +40,7 @@ ExcludeFromSelect=USB\VID_FFFE&PID_000D [Strings] Mfg = "altusmetrum.org" -AltusMetrum = "Unknown AltusMetrum Device" +AltusMetrum = "AltusMetrum" TeleMetrum = "TeleMetrum" TeleDongle = "TeleDongle" TeleTerra = "TeleTerra" -- cgit v1.2.3 From 737a64c57a8f979f51c3fa6b3f214520c736cf8a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 15:22:14 -0700 Subject: altosui: hack to make JAVAROOT directory get created before javac runs This ensures that the JAVAROOT directory gets created by adding it to the variable used to set the CLASSPATH environment value. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 4bb67c97..f224dace 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -1,7 +1,7 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -CLASSPATH_ENV=CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -109,11 +109,6 @@ install-altosuiJAVA: altosui.jar classes/altosui: mkdir -p classes/altosui -classaltosui.stamp: classes - -classes: - mkdir -p classes - $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) jar cfm $@ Manifest.txt \ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ -- cgit v1.2.3 From 6c0ae7e966a81ece35bccbe89d626a58afe899a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 15:25:18 -0700 Subject: altosui: remove FATJAR from all-local to avoid building fat .jar file the fat .jar file is used in non-native builds to run from a directory containing all of the freetts jar files along with the altosui jar file. We don't want this on a real install where freetts is installed separately. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index f224dace..760e662d 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -88,7 +88,7 @@ MACOSX_EXTRA=$(FIRMWARE) WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) -all-local: classes/altosui $(JAR) $(FATJAR) altosui altosui-test +all-local: classes/altosui $(JAR) altosui altosui-test clean-local: -rm -rf classes $(JAR) $(FATJAR) \ -- cgit v1.2.3 From c286ada6457579d64e9d8ca44b927258b4a561da Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 16:27:40 -0600 Subject: update changelogs for Debian build --- ChangeLog | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 11 ++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e87431ba..39903ed2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,52 @@ +commit 6c0ae7e966a81ece35bccbe89d626a58afe899a2 +Author: Keith Packard +Date: Thu Sep 9 15:25:18 2010 -0700 + + altosui: remove FATJAR from all-local to avoid building fat .jar file + + the fat .jar file is used in non-native builds to run from a directory + containing all of the freetts jar files along with the altosui jar + file. We don't want this on a real install where freetts is installed separately. + + Signed-off-by: Keith Packard + +commit 737a64c57a8f979f51c3fa6b3f214520c736cf8a +Author: Keith Packard +Date: Thu Sep 9 15:22:14 2010 -0700 + + altosui: hack to make JAVAROOT directory get created before javac runs + + This ensures that the JAVAROOT directory gets created by adding it to + the variable used to set the CLASSPATH environment value. + + Signed-off-by: Keith Packard + +commit b456bd9d7bcd9d968e43c38eeb6fa6ad8c58f895 +Author: Keith Packard +Date: Thu Sep 9 15:11:41 2010 -0700 + + altosui: fix telemetrum.inf FFFE:000A product names on AMD64 and ia64 + + This appears to matter to Vista. Dunno why. + + Signed-off-by: Keith Packard + +commit 16980b848651a6b20a0b458446f0a19fb517539d +Author: Keith Packard +Date: Thu Sep 9 15:10:25 2010 -0700 + + altosui: Add explicit requirement to create classes directory + + The implicit ordering doesn't appear reliable. + + Signed-off-by: Keith Packard + +commit 15da683c2f747baef49c8b8d321a86faede0de30 +Author: Bdale Garbee +Date: Thu Sep 9 15:51:50 2010 -0600 + + update changelogs for Debian build + commit 012e7176954a6b74b3b667317be0f6dc41d7ab70 Author: Bdale Garbee Date: Thu Sep 9 15:51:02 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 572af3e6..d46b0346 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,13 @@ -altos (0.7+81+g012e717) unstable; urgency=low +altos (0.7+86+g6c0ae7e) unstable; urgency=low + + [ Keith Packard ] + * altosui: Add explicit requirement to create classes directory + * altosui: fix telemetrum.inf FFFE:000A product names on AMD64 and + ia64 + * altosui: hack to make JAVAROOT directory get created before javac + runs + * altosui: remove FATJAR from all-local to avoid building fat .jar + file [ Bdale Garbee ] * add libtool to build deps -- cgit v1.2.3 From 35d70c92307dd478bc619b2f6c5a88e155cdad28 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 17:27:07 -0600 Subject: handle versioning of ihx files (poorly) by just wildcarding the file name, which assumes there's only one matching .. probably ok on Debian? --- ao-bringup/turnon_teledongle | 2 +- ao-bringup/turnon_telemetrum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index 7dbb82b5..216afa2a 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2.ihx $SERIAL +$AOLOAD --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 4086a1a8..440eda1b 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/telemetrum-v1.0.ihx $SERIAL +$AOLOAD --cal $CAL_VALUE /usr/share/altos/telemetrum-v1.0*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 1e4c18777d982061f5e507a4d4f4f1cd4d685268 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 17:49:37 -0700 Subject: altosui: Need to have JVM include path substituted into libaltos Makefile The libaltos Makefile needs to find the relevant jni.h file, which is found in the JVM_INCLUDE path, all nicely located by the configure.ac script. Signed-off-by: Keith Packard --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index d376af3f..61c03b18 100644 --- a/configure.ac +++ b/configure.ac @@ -56,6 +56,8 @@ if test "x$JVM_INCLUDE" = "xauto"; then AC_MSG_RESULT([$JVM_INCLUDE]) fi +AC_SUBST(JVM_INCLUDE) + AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S -- cgit v1.2.3 From 4224a7526e51eb8fbf1f0a31bae7ee68c6385095 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 17:52:46 -0700 Subject: altosui: Store libaltos.so in $(libdir)/altos It's not a public library, so hide it away in a subdirectory. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 6 ++++-- ao-tools/libaltos/Makefile.am | 21 +++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 760e662d..804e0c74 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -1,6 +1,8 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 +altoslibdir=$(libdir)/altos + CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -131,12 +133,12 @@ Manifest-fat.txt: altosui: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="$(libdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ + echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ chmod +x $@ altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos" -jar altosui.jar "$$*"' >> $@ + echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ $(LIBALTOS): diff --git a/ao-tools/libaltos/Makefile.am b/ao-tools/libaltos/Makefile.am index 4d29d80e..388d2104 100644 --- a/ao-tools/libaltos/Makefile.am +++ b/ao-tools/libaltos/Makefile.am @@ -1,11 +1,22 @@ JAVAC=javac -AM_CFLAGS="-I$(JVM_INCLUDE)" +AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) AM_JAVACFLAGS=-encoding UTF-8 -lib_LTLIBRARIES=libaltos.la +altoslibdir=$(libdir)/altos + +altoslib_LTLIBRARIES=libaltos.la + +libaltos_la_LDFLAGS = -version-info 1:0:1 libaltos_la_SOURCES=\ - libaltos.c + libaltos.c \ + libaltos_wrap.c + +noinst_PROGRAMS=cjnitest + +cjnitest_LDADD=libaltos.la + +LIBS= HFILES=libaltos.h @@ -18,6 +29,8 @@ $(SWIG_FILE): libaltos.i0 $(HFILES) all-local: classlibaltos.stamp +libaltos_wrap.c: classlibaltos.stamp + classlibaltos.stamp: $(SWIG_FILE) swig -java -package libaltosJNI $(SWIG_FILE) mkdir -p libaltosJNI @@ -25,4 +38,4 @@ classlibaltos.stamp: $(SWIG_FILE) touch classlibaltos.stamp clean-local: - -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) \ No newline at end of file + -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c -- cgit v1.2.3 From 8ee3464d8064ebe1694c7b20177878c0d9961451 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 17:54:41 -0700 Subject: altosui: Display error dialog when AltOS JNI library can't be loaded Having an error dialog appear at application startup seems better than simply failing to present the device dialog later on. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDevice.java | 77 ++++++++++++++++++++++++++------- ao-tools/altosui/AltosDeviceDialog.java | 13 ++++-- ao-tools/altosui/AltosUI.java | 14 ++++++ 3 files changed, 85 insertions(+), 19 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index e62a0a7a..9ae522c2 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -22,20 +22,67 @@ import libaltosJNI.*; public class AltosDevice extends altos_device { - static boolean initialized = false; - static { - try { - System.loadLibrary("altos"); - libaltos.altos_init(); + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + loaded_library = false; + } initialized = true; - } catch (UnsatisfiedLinkError e) { - System.err.println("Native library failed to load.\n" + e); } + return loaded_library; + } + + static int usb_product_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return 0x000a; + } + + static int usb_product_altusmetrum_min() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; + return 0x000a; + } + + static int usb_product_altusmetrum_max() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; + return 0x000d; + } + + static int usb_product_telemetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEMETRUM; + return 0x000b; + } + + static int usb_product_teledongle() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return 0x000c; + } + + static int usb_product_teleterra() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return 0x000d; } - 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 final static int AltusMetrum = usb_product_altusmetrum(); + public final static int TeleMetrum = usb_product_telemetrum(); + public final static int TeleDongle = usb_product_teledongle(); + public final static int TeleTerra = usb_product_teleterra(); + public final static int AltusMetrumMin = usb_product_altusmetrum_min(); + public final static int AltusMetrumMax = usb_product_altusmetrum_max(); + + public final static int Any = 0x10000; public final static int BaseStation = 0x10000 + 1; @@ -48,11 +95,11 @@ public class AltosDevice extends altos_device { } public boolean isAltusMetrum() { - if (getVendor() != libaltosConstants.USB_VENDOR_ALTUSMETRUM) + if (getVendor() != AltusMetrum) return false; - if (getProduct() < libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN) + if (getProduct() < AltusMetrumMin) return false; - if (getProduct() > libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX) + if (getProduct() > AltusMetrumMax) return false; return true; } @@ -80,7 +127,7 @@ public class AltosDevice extends altos_device { } static AltosDevice[] list(int product) { - if (!initialized) + if (!load_library()) return null; SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index 3df4c6eb..ec78e288 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -49,10 +49,15 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { dialog.setVisible(true); return value; } else { - JOptionPane.showMessageDialog(frame, - "No AltOS devices available", - "No AltOS devices", - JOptionPane.ERROR_MESSAGE); + /* check for missing altos JNI library, which + * will put up its own error dialog + */ + if (AltosUI.load_library(frame)) { + JOptionPane.showMessageDialog(frame, + "No AltOS devices available", + "No AltOS devices", + JOptionPane.ERROR_MESSAGE); + } return null; } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 3aaeb888..ca587b25 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -70,8 +70,22 @@ public class AltosUI extends JFrame { public AltosVoice voice = new AltosVoice(); + public static boolean load_library(Frame frame) { + if (!AltosDevice.load_library()) { + JOptionPane.showMessageDialog(frame, + String.format("No AltOS library in \"%s\"", + System.getProperty("java.library.path","")), + "Cannot load device access library", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + public AltosUI() { + load_library(null); + String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; -- cgit v1.2.3 From 5c4e437975054d33604402591e1ea2f314932593 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 20:06:09 -0600 Subject: update changelogs for Debian build --- ChangeLog | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 14 ++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/ChangeLog b/ChangeLog index 39903ed2..a6db0da8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,55 @@ +commit 0ea75761416bff299233991e961ba25b6c7dcf89 +Merge: 35d70c9 8ee3464 +Author: Bdale Garbee +Date: Thu Sep 9 20:05:27 2010 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 8ee3464d8064ebe1694c7b20177878c0d9961451 +Author: Keith Packard +Date: Thu Sep 9 17:54:41 2010 -0700 + + altosui: Display error dialog when AltOS JNI library can't be loaded + + Having an error dialog appear at application startup seems better than + simply failing to present the device dialog later on. + + Signed-off-by: Keith Packard + +commit 4224a7526e51eb8fbf1f0a31bae7ee68c6385095 +Author: Keith Packard +Date: Thu Sep 9 17:52:46 2010 -0700 + + altosui: Store libaltos.so in $(libdir)/altos + + It's not a public library, so hide it away in a subdirectory. + + Signed-off-by: Keith Packard + +commit 1e4c18777d982061f5e507a4d4f4f1cd4d685268 +Author: Keith Packard +Date: Thu Sep 9 17:49:37 2010 -0700 + + altosui: Need to have JVM include path substituted into libaltos Makefile + + The libaltos Makefile needs to find the relevant jni.h file, which is + found in the JVM_INCLUDE path, all nicely located by the configure.ac script. + + Signed-off-by: Keith Packard + +commit 35d70c92307dd478bc619b2f6c5a88e155cdad28 +Author: Bdale Garbee +Date: Thu Sep 9 17:27:07 2010 -0600 + + handle versioning of ihx files (poorly) by just wildcarding the file name, + which assumes there's only one matching .. probably ok on Debian? + +commit c286ada6457579d64e9d8ca44b927258b4a561da +Author: Bdale Garbee +Date: Thu Sep 9 16:27:40 2010 -0600 + + update changelogs for Debian build + commit 6c0ae7e966a81ece35bccbe89d626a58afe899a2 Author: Keith Packard Date: Thu Sep 9 15:25:18 2010 -0700 diff --git a/debian/changelog b/debian/changelog index d46b0346..5f5204ec 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +altos (0.7+92+g0ea7576) unstable; urgency=low + + [ Bdale Garbee ] + * handle versioning of ihx files (poorly) by just wildcarding the file + name + + [ Keith Packard ] + * altosui: Need to have JVM include path substituted into libaltos + Makefile + * altosui: Store libaltos.so in $(libdir)/altos + * altosui: Display error dialog when AltOS JNI library can't be loaded + + -- Bdale Garbee Thu, 09 Sep 2010 20:05:44 -0600 + altos (0.7+86+g6c0ae7e) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 1ac3d7e3ba52d1b0dc834eaa5d7886c730eaf307 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 20:34:22 -0600 Subject: initial cut at an altosui man page --- ao-tools/altosui/Makefile.am | 4 +++- ao-tools/altosui/altosui.1 | 16 +++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 804e0c74..3e0d7c9b 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -1,6 +1,8 @@ JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 +man_MANS=altosui.1 + altoslibdir=$(libdir)/altos CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" @@ -171,4 +173,4 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) $(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 + makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi diff --git a/ao-tools/altosui/altosui.1 b/ao-tools/altosui/altosui.1 index c3130fce..57fa4489 100644 --- a/ao-tools/altosui/altosui.1 +++ b/ao-tools/altosui/altosui.1 @@ -16,7 +16,7 @@ .\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. .\" .\" -.TH AO-VIEW 1 "altosui" "" +.TH ALTOSUI 1 "altosui" "" .SH NAME altosui \- Rocket flight monitor .SH SYNOPSIS @@ -24,21 +24,23 @@ altosui \- Rocket flight monitor .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. +It provides a menu-oriented +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. +When connected to a TeleMetrum device, altosui can be used to configure the +TeleMetrum, and to downloads the eeprom data and store it in a file. +.P +A number of other menu options exist, including the ability to export flight +data in different formats. .SH FILES All data log files are recorded into a user-specified directory -(default ~/AltOS). Files are named using the current date, the serial +(default ~/TeleMetrum). 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 -- cgit v1.2.3 From 632d276118ab04de67561104be650f8fb69a0450 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 20:34:43 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index a6db0da8..bda61ce0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 1ac3d7e3ba52d1b0dc834eaa5d7886c730eaf307 +Author: Bdale Garbee +Date: Thu Sep 9 20:34:22 2010 -0600 + + initial cut at an altosui man page + +commit 5c4e437975054d33604402591e1ea2f314932593 +Author: Bdale Garbee +Date: Thu Sep 9 20:06:09 2010 -0600 + + update changelogs for Debian build + commit 0ea75761416bff299233991e961ba25b6c7dcf89 Merge: 35d70c9 8ee3464 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 5f5204ec..2549c1c9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.7+94+g1ac3d7e) unstable; urgency=low + + * initial cut at an altosui man page + + -- Bdale Garbee Thu, 09 Sep 2010 20:34:38 -0600 + altos (0.7+92+g0ea7576) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 48f57997452e17564e28fe3e37403f6f63d32dea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 20:24:42 -0700 Subject: altosui: conflating USB product and vendor IDs is a bad idea We've now got a USB vendor ID called 'altusmetrum' for generic altusmetrum devices (old USB ID 0x000A) while the general vendor name for all devices is 'altusmetrum' as well. This patch splits vendors and products into separate name spaces, products are prefixed with product_ and vendor with (oddly) vendor_. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 4 +-- ao-tools/altosui/AltosDevice.java | 52 ++++++++++++++++++++----------- ao-tools/altosui/AltosEepromDownload.java | 4 +-- ao-tools/altosui/AltosFlashUI.java | 2 +- ao-tools/altosui/AltosUI.java | 3 +- 5 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 3d970748..7b6cd78c 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -238,12 +238,12 @@ public class AltosConfig implements Runnable, ActionListener { version = new string_ref("unknown"); product = new string_ref("unknown"); - device = AltosDeviceDialog.show(owner, AltosDevice.Any); + device = AltosDeviceDialog.show(owner, AltosDevice.product_any); serial_line = new AltosSerial(); if (device != null) { try { serial_line.open(device); - if (!device.matchProduct(AltosDevice.TeleMetrum)) + if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; config_thread = new Thread(this); config_thread.start(); diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index 9ae522c2..d671031d 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -39,6 +39,12 @@ public class AltosDevice extends altos_device { return loaded_library; } + static int usb_vendor_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_VENDOR_ALTUSMETRUM; + return 0x000a; + } + static int usb_product_altusmetrum() { if (load_library()) return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; @@ -65,26 +71,27 @@ public class AltosDevice extends altos_device { static int usb_product_teledongle() { if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return libaltosConstants.USB_PRODUCT_TELEDONGLE; return 0x000c; } static int usb_product_teleterra() { if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return libaltosConstants.USB_PRODUCT_TELETERRA; return 0x000d; } - public final static int AltusMetrum = usb_product_altusmetrum(); - public final static int TeleMetrum = usb_product_telemetrum(); - public final static int TeleDongle = usb_product_teledongle(); - public final static int TeleTerra = usb_product_teleterra(); - public final static int AltusMetrumMin = usb_product_altusmetrum_min(); - public final static int AltusMetrumMax = usb_product_altusmetrum_max(); + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); + public final static int product_altusmetrum = usb_product_altusmetrum(); + public final static int product_telemetrum = usb_product_telemetrum(); + public final static int product_teledongle = usb_product_teledongle(); + public final static int product_teleterra = usb_product_teleterra(); + public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); + public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - public final static int Any = 0x10000; - public final static int BaseStation = 0x10000 + 1; + public final static int product_any = 0x10000; + public final static int product_basestation = 0x10000 + 1; public String toString() { String name = getName(); @@ -95,29 +102,34 @@ public class AltosDevice extends altos_device { } public boolean isAltusMetrum() { - if (getVendor() != AltusMetrum) + if (getVendor() != vendor_altusmetrum) return false; - if (getProduct() < AltusMetrumMin) + if (getProduct() < product_altusmetrum_min) return false; - if (getProduct() > AltusMetrumMax) + if (getProduct() > product_altusmetrum_max) return false; return true; } public boolean matchProduct(int want_product) { + System.out.printf("vendor %x product %x want %x\n", + getVendor(), getProduct(), want_product); + System.out.printf("vendor_altusmetrum: %d\n", vendor_altusmetrum); + System.out.printf("telemetrum: %d\n", product_telemetrum); + if (!isAltusMetrum()) return false; - if (want_product == Any) + if (want_product == product_any) return true; - if (want_product == BaseStation) - return matchProduct(TeleDongle) || matchProduct(TeleTerra); + if (want_product == product_basestation) + return matchProduct(product_teledongle) || matchProduct(product_teleterra); int have_product = getProduct(); - if (have_product == AltusMetrum) /* old devices match any request */ + if (have_product == product_altusmetrum) /* old devices match any request */ return true; if (want_product == have_product) @@ -127,19 +139,23 @@ public class AltosDevice extends altos_device { } static AltosDevice[] list(int product) { - if (!load_library()) + if (!load_library()) { + System.out.printf("no library\n"); return null; + } SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); ArrayList device_list = new ArrayList(); if (list != null) { + System.out.printf("got device list\n"); SWIGTYPE_p_altos_file file; for (;;) { AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; + System.out.printf("got device\n"); if (device.matchProduct(product)) device_list.add(device); } diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 6dbbd3eb..a7f64904 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -254,7 +254,7 @@ public class AltosEepromDownload implements Runnable { public AltosEepromDownload(JFrame given_frame) { frame = given_frame; - device = AltosDeviceDialog.show(frame, AltosDevice.Any); + device = AltosDeviceDialog.show(frame, AltosDevice.product_any); serial_line = new AltosSerial(); remote = false; @@ -262,7 +262,7 @@ public class AltosEepromDownload implements Runnable { if (device != null) { try { serial_line.open(device); - if (!device.matchProduct(AltosDevice.TeleMetrum)) + if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; eeprom_thread = new Thread(this); eeprom_thread.start(); diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 18795695..5ed417da 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -187,7 +187,7 @@ public class AltosFlashUI build_dialog(); - debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.Any); + debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any); if (debug_dongle == null) return; diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index ca587b25..edee146d 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -523,7 +523,8 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - AltosDevice device = AltosDeviceDialog.show(AltosUI.this, AltosDevice.BaseStation); + AltosDevice device = AltosDeviceDialog.show(AltosUI.this, + AltosDevice.product_basestation); if (device != null) { try { -- cgit v1.2.3 From fcaa480b1dfeb2fd4044f9c4e1b6d50c46fc9984 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 21:29:20 -0600 Subject: update changelogs for Debian build --- ChangeLog | 21 +++++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 28 insertions(+) diff --git a/ChangeLog b/ChangeLog index bda61ce0..8c6759ee 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +commit 48f57997452e17564e28fe3e37403f6f63d32dea +Author: Keith Packard +Date: Thu Sep 9 20:24:42 2010 -0700 + + altosui: conflating USB product and vendor IDs is a bad idea + + We've now got a USB vendor ID called 'altusmetrum' for generic + altusmetrum devices (old USB ID 0x000A) while the general vendor name + for all devices is 'altusmetrum' as well. + + This patch splits vendors and products into separate name spaces, + products are prefixed with product_ and vendor with (oddly) vendor_. + + Signed-off-by: Keith Packard + +commit 632d276118ab04de67561104be650f8fb69a0450 +Author: Bdale Garbee +Date: Thu Sep 9 20:34:43 2010 -0600 + + update changelogs for Debian build + commit 1ac3d7e3ba52d1b0dc834eaa5d7886c730eaf307 Author: Bdale Garbee Date: Thu Sep 9 20:34:22 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 2549c1c9..39708acf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.7+96+g48f5799) unstable; urgency=low + + [ Keith Packard ] + * altosui: conflating USB product and vendor IDs is a bad idea + + -- Bdale Garbee Thu, 09 Sep 2010 21:29:13 -0600 + altos (0.7+94+g1ac3d7e) unstable; urgency=low * initial cut at an altosui man page -- cgit v1.2.3 From 031fd9a954f2e3447d0150eb4ecc81af7b620dca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 20:36:12 -0700 Subject: Add firmware and libaltos to 'fat' target at top-level This ensures that all of the necessary bits are available to construct the distribution images. Signed-off-by: Keith Packard --- Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile.am b/Makefile.am index 66d7cb55..264e577a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -13,4 +13,6 @@ ChangeLog: dist-hook: ChangeLog fat: + cd src && $(MAKE) all + cd ao-tools/libaltos && $(MAKE) all cd ao-tools/altosui && $(MAKE) fat -- cgit v1.2.3 From 72a5c1258db92d0ddd660bfa875e8e55cab47af7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 20:39:41 -0700 Subject: altosui: Remove some debug printfs. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDevice.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index d671031d..f646305b 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -113,11 +113,6 @@ public class AltosDevice extends altos_device { public boolean matchProduct(int want_product) { - System.out.printf("vendor %x product %x want %x\n", - getVendor(), getProduct(), want_product); - System.out.printf("vendor_altusmetrum: %d\n", vendor_altusmetrum); - System.out.printf("telemetrum: %d\n", product_telemetrum); - if (!isAltusMetrum()) return false; @@ -139,23 +134,19 @@ public class AltosDevice extends altos_device { } static AltosDevice[] list(int product) { - if (!load_library()) { - System.out.printf("no library\n"); + if (!load_library()) return null; - } SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); ArrayList device_list = new ArrayList(); if (list != null) { - System.out.printf("got device list\n"); SWIGTYPE_p_altos_file file; for (;;) { AltosDevice device = new AltosDevice(); if (libaltos.altos_list_next(list, device) == 0) break; - System.out.printf("got device\n"); if (device.matchProduct(product)) device_list.add(device); } -- cgit v1.2.3 From dd2b77b2a516a055f29191dcdfeb727e637aae86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 20:59:29 -0700 Subject: altosui: libaltos.so is built with libtool -- it's in ../libaltos/.libs It used to be in ../libaltos Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 3e0d7c9b..56e6d7ae 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -143,7 +143,15 @@ altosui-test: Makefile echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ -$(LIBALTOS): +libaltos.so: + -rm -f "$@" + $(LN_S) ../libaltos/.libs/"$@" . + +libaltos.dylib: + -rm -f "$@" + $(LN_S) ../libaltos/"$@" . + +altos.dll: -rm -f "$@" $(LN_S) ../libaltos/"$@" . -- cgit v1.2.3 From 2d5e48c5dc0e822fdf430f43804c1e5e79fdbf84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 21:28:10 -0700 Subject: Add --with-fat-dir configure option to publish finished stand-alone bits --with-fat-dir specifies a directory to copy the finished linux/macosx/windows stand-alone ("fat") packages to. A sub-directory will be created under the specified directory based on the product version number and the files copied there. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 24 ++++++++++++++++++++++++ configure.ac | 8 ++++++++ 2 files changed, 32 insertions(+) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 56e6d7ae..fa391889 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -102,6 +102,30 @@ clean-local: fat: $(FATJAR) $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) +if FATINSTALL + +FATTARGET=$(FATDIR)/$(VERSION) + +LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST) +MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST) +WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST) + +fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET) + +$(LINUX_DIST_TARGET): $(LINUX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(MACOSX_DIST_TARGET): $(MACOSX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +endif + altosuidir=$(datadir)/java install-altosuiJAVA: altosui.jar diff --git a/configure.ac b/configure.ac index 61c03b18..4bf8f7fe 100644 --- a/configure.ac +++ b/configure.ac @@ -58,6 +58,14 @@ fi AC_SUBST(JVM_INCLUDE) +AC_ARG_WITH(fat-dir, AS_HELP_STRING([--with-fat-dir=PATH], + [Set the directory to install the 'fat' distribution files to (defaults to not installing)]), + [FATDIR=$withval], [FATDIR=none]) + +AM_CONDITIONAL(FATINSTALL, [test "x$FATDIR" != "xnone"]) + +AC_SUBST(FATDIR) + AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S -- cgit v1.2.3 From 96ca7051f60ea299e3e05bafbe5717fc83c3afd2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 22:50:03 -0600 Subject: update changelogs for Debian build --- ChangeLog | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 12 ++++++++++++ 2 files changed, 60 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8c6759ee..8e1be97c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +commit 2d5e48c5dc0e822fdf430f43804c1e5e79fdbf84 +Author: Keith Packard +Date: Thu Sep 9 21:28:10 2010 -0700 + + Add --with-fat-dir configure option to publish finished stand-alone bits + + --with-fat-dir specifies a directory to copy the finished + linux/macosx/windows stand-alone ("fat") packages to. A sub-directory + will be created under the specified directory based on the product + version number and the files copied there. + + Signed-off-by: Keith Packard + +commit dd2b77b2a516a055f29191dcdfeb727e637aae86 +Author: Keith Packard +Date: Thu Sep 9 20:59:29 2010 -0700 + + altosui: libaltos.so is built with libtool -- it's in ../libaltos/.libs + + It used to be in ../libaltos + + Signed-off-by: Keith Packard + +commit 72a5c1258db92d0ddd660bfa875e8e55cab47af7 +Author: Keith Packard +Date: Thu Sep 9 20:39:41 2010 -0700 + + altosui: Remove some debug printfs. + + Signed-off-by: Keith Packard + +commit 031fd9a954f2e3447d0150eb4ecc81af7b620dca +Author: Keith Packard +Date: Thu Sep 9 20:36:12 2010 -0700 + + Add firmware and libaltos to 'fat' target at top-level + + This ensures that all of the necessary bits are available to construct + the distribution images. + + Signed-off-by: Keith Packard + +commit fcaa480b1dfeb2fd4044f9c4e1b6d50c46fc9984 +Author: Bdale Garbee +Date: Thu Sep 9 21:29:20 2010 -0600 + + update changelogs for Debian build + commit 48f57997452e17564e28fe3e37403f6f63d32dea Author: Keith Packard Date: Thu Sep 9 20:24:42 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 39708acf..c808c50d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +altos (0.7.1) unstable; urgency=low + + [ Keith Packard ] + * Add firmware and libaltos to 'fat' target at top-level + * altosui: Remove some debug printfs. + * altosui: libaltos.so is built with libtool -- it's in + ../libaltos/.libs + * Add --with-fat-dir configure option to publish finished stand-alone + bits + + -- Bdale Garbee Thu, 09 Sep 2010 22:49:54 -0600 + altos (0.7+96+g48f5799) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From af200f5b84555de0556b52146379f3934774a3f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 22:30:48 -0700 Subject: altosui: Fix telemetry file reader to handle tick count wrapping The telemetry reader was ignoring tick count wrapping, so you'd see time go backwards in jumps. Not useful. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosTelemetryReader.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index fdedbde2..ae9682ab 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -41,6 +41,7 @@ public class AltosTelemetryReader extends AltosReader { public AltosTelemetryReader (FileInputStream input) { boolean saw_boost = false; + int current_tick = 0; records = new LinkedList (); @@ -51,9 +52,20 @@ public class AltosTelemetryReader extends AltosReader { break; } try { + System.out.printf("%s\n", line); AltosTelemetry record = new AltosTelemetry(line); if (record == null) break; + if (records.isEmpty()) { + current_tick = record.tick; + } else { + int tick = record.tick | (current_tick & ~ 0xffff); + if (tick < current_tick - 0x1000) + tick += 0x10000; + current_tick = tick; + record.tick = current_tick; + } + System.out.printf("\tRSSI %d tick %d\n", record.rssi, record.tick); if (!saw_boost && record.state >= Altos.ao_flight_boost) { saw_boost = true; -- cgit v1.2.3 From 71c85613a28c24c3aad7b4aa3299d8677ef1268e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 23:51:23 -0600 Subject: rewind packaging changelog --- debian/changelog | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/debian/changelog b/debian/changelog index c808c50d..39708acf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,15 +1,3 @@ -altos (0.7.1) unstable; urgency=low - - [ Keith Packard ] - * Add firmware and libaltos to 'fat' target at top-level - * altosui: Remove some debug printfs. - * altosui: libaltos.so is built with libtool -- it's in - ../libaltos/.libs - * Add --with-fat-dir configure option to publish finished stand-alone - bits - - -- Bdale Garbee Thu, 09 Sep 2010 22:49:54 -0600 - altos (0.7+96+g48f5799) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 78ce3120e5a53858ca0d43c734aa5d28b4948ce3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 23:52:20 -0600 Subject: update changelogs for Debian build --- ChangeLog | 23 +++++++++++++++++++++++ debian/changelog | 13 +++++++++++++ 2 files changed, 36 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8e1be97c..8b4f8892 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +commit 71c85613a28c24c3aad7b4aa3299d8677ef1268e +Author: Bdale Garbee +Date: Thu Sep 9 23:51:23 2010 -0600 + + rewind packaging changelog + +commit af200f5b84555de0556b52146379f3934774a3f3 +Author: Keith Packard +Date: Thu Sep 9 22:30:48 2010 -0700 + + altosui: Fix telemetry file reader to handle tick count wrapping + + The telemetry reader was ignoring tick count wrapping, so you'd see + time go backwards in jumps. Not useful. + + Signed-off-by: Keith Packard + +commit 96ca7051f60ea299e3e05bafbe5717fc83c3afd2 +Author: Bdale Garbee +Date: Thu Sep 9 22:50:03 2010 -0600 + + update changelogs for Debian build + commit 2d5e48c5dc0e822fdf430f43804c1e5e79fdbf84 Author: Keith Packard Date: Thu Sep 9 21:28:10 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 39708acf..db929e64 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,16 @@ +altos (0.7.1) unstable; urgency=low + + [ Keith Packard ] + * Add firmware and libaltos to 'fat' target at top-level + * altosui: Remove some debug printfs. + * altosui: libaltos.so is built with libtool -- it's in + ../libaltos/.libs + * Add --with-fat-dir configure option to publish finished stand-alone + bits + * altosui: Fix telemetry file reader to handle tick count wrapping + + -- Bdale Garbee Thu, 09 Sep 2010 23:51:53 -0600 + altos (0.7+96+g48f5799) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From a80bfae15f1499c49f7ef47978bf0337d8120892 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 9 Sep 2010 23:57:34 -0600 Subject: rewind packaging changelog, again --- debian/changelog | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/debian/changelog b/debian/changelog index db929e64..39708acf 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,16 +1,3 @@ -altos (0.7.1) unstable; urgency=low - - [ Keith Packard ] - * Add firmware and libaltos to 'fat' target at top-level - * altosui: Remove some debug printfs. - * altosui: libaltos.so is built with libtool -- it's in - ../libaltos/.libs - * Add --with-fat-dir configure option to publish finished stand-alone - bits - * altosui: Fix telemetry file reader to handle tick count wrapping - - -- Bdale Garbee Thu, 09 Sep 2010 23:51:53 -0600 - altos (0.7+96+g48f5799) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 8b0b584cd0ca7542e65aac0c7897ad7ab4115122 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 22:55:47 -0700 Subject: altosui: Remove debug printfs from AltosTelemetryReader Signed-off-by: Keith Packard --- ao-tools/altosui/AltosTelemetryReader.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index ae9682ab..3564a0a5 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -52,7 +52,6 @@ public class AltosTelemetryReader extends AltosReader { break; } try { - System.out.printf("%s\n", line); AltosTelemetry record = new AltosTelemetry(line); if (record == null) break; @@ -65,7 +64,6 @@ public class AltosTelemetryReader extends AltosReader { current_tick = tick; record.tick = current_tick; } - System.out.printf("\tRSSI %d tick %d\n", record.rssi, record.tick); if (!saw_boost && record.state >= Altos.ao_flight_boost) { saw_boost = true; -- cgit v1.2.3 From 67b6952f7126704478ede5575e5e938d18fcc329 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 23:04:14 -0700 Subject: altosui: Fill in time value of last Eeprom record read from file The last record is handled separately, and was missing the code to compute the time. Sigh. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index cb82f9a9..f1d6a6a7 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -114,7 +114,9 @@ public class AltosEepromReader extends AltosReader { if (last_reported) return null; last_reported = true; - return new AltosRecord(state); + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - boost_tick) / 100.0; + return r; } record = record_iterator.next(); -- cgit v1.2.3 From 9d0e89e8ad8926dc8371fa809835a580ae49711d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 9 Sep 2010 23:04:59 -0700 Subject: altosui: Stop parsing eeprom file after hitting 'landed' state Sometimes there are additional records found in the eeprom file; the reader is mostly worried about not losing anything, so it reads as much as it can. However, the last record written for any flight is the 'landed' record, so we can stop looking at the file after hitting that. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index f1d6a6a7..4cc8536a 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -391,6 +391,11 @@ public class AltosEepromReader extends AltosReader { } } records.add(record); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == Altos.AO_LOG_STATE && + record.a == Altos.ao_flight_landed) + break; } } catch (IOException io) { } catch (ParseException pe) { -- cgit v1.2.3 From 10310672a83a66dc630718b151d653fc066f8e59 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 10 Sep 2010 00:09:25 -0600 Subject: update changelogs for Debian build --- ChangeLog | 44 ++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 16 ++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/ChangeLog b/ChangeLog index 8b4f8892..d6cb54e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,47 @@ +commit 9d0e89e8ad8926dc8371fa809835a580ae49711d +Author: Keith Packard +Date: Thu Sep 9 23:04:59 2010 -0700 + + altosui: Stop parsing eeprom file after hitting 'landed' state + + Sometimes there are additional records found in the eeprom file; the + reader is mostly worried about not losing anything, so it reads as + much as it can. However, the last record written for any flight is the + 'landed' record, so we can stop looking at the file after hitting that. + + Signed-off-by: Keith Packard + +commit 67b6952f7126704478ede5575e5e938d18fcc329 +Author: Keith Packard +Date: Thu Sep 9 23:04:14 2010 -0700 + + altosui: Fill in time value of last Eeprom record read from file + + The last record is handled separately, and was missing the code to + compute the time. Sigh. + + Signed-off-by: Keith Packard + +commit 8b0b584cd0ca7542e65aac0c7897ad7ab4115122 +Author: Keith Packard +Date: Thu Sep 9 22:55:47 2010 -0700 + + altosui: Remove debug printfs from AltosTelemetryReader + + Signed-off-by: Keith Packard + +commit a80bfae15f1499c49f7ef47978bf0337d8120892 +Author: Bdale Garbee +Date: Thu Sep 9 23:57:34 2010 -0600 + + rewind packaging changelog, again + +commit 78ce3120e5a53858ca0d43c734aa5d28b4948ce3 +Author: Bdale Garbee +Date: Thu Sep 9 23:52:20 2010 -0600 + + update changelogs for Debian build + commit 71c85613a28c24c3aad7b4aa3299d8677ef1268e Author: Bdale Garbee Date: Thu Sep 9 23:51:23 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 39708acf..98068ad7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,19 @@ +altos (0.7.1) unstable; urgency=low + + [ Keith Packard ] + * Add firmware and libaltos to 'fat' target at top-level + * altosui: Remove some debug printfs. + * altosui: libaltos.so is built with libtool -- it's in + ../libaltos/.libs + * Add --with-fat-dir configure option to publish finished stand-alone + bits + * altosui: Fix telemetry file reader to handle tick count wrapping + * altosui: Remove debug printfs from AltosTelemetryReader + * altosui: Fill in time value of last Eeprom record read from file + * altosui: Stop parsing eeprom file after hitting 'landed' state + + -- Bdale Garbee Fri, 10 Sep 2010 00:09:02 -0600 + altos (0.7+96+g48f5799) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 7e053ae1f2d09347123ac9fa79e46645378b4c70 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 10 Sep 2010 10:42:35 -0600 Subject: make the column headers comma separated, too, so they align with the data --- ao-tools/altosui/AltosCSV.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 4ce8e30e..07fa371f 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -86,7 +86,7 @@ public class AltosCSV { */ void write_general_header() { - out.printf("version serial flight call time rssi"); + out.printf("version,serial,flight,call,time,rssi"); } void write_general(AltosRecord record) { @@ -97,7 +97,7 @@ public class AltosCSV { } void write_flight_header() { - out.printf("state state_name"); + out.printf("state,state_name"); } void write_flight(AltosRecord record) { @@ -105,7 +105,7 @@ public class AltosCSV { } void write_basic_header() { - out.printf("acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage"); + out.printf("acceleration,pressure,altitude,height,accel_speed,baro_speed,temperature,battery_voltage,drogue_voltage,main_voltage"); } void write_basic(AltosRecord record) { @@ -123,7 +123,7 @@ public class AltosCSV { } 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"); + 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) { @@ -155,10 +155,10 @@ public class AltosCSV { } 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("#"); write_general_header(); + out.printf(","); write_flight_header(); + out.printf(","); write_basic_header(); + out.printf(","); write_gps_header(); out.printf ("\n"); } -- cgit v1.2.3 From 7f2204e0832b14b1edca4266a2cbc272141ecc2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 10 Sep 2010 20:55:05 -0700 Subject: altosui: set default .csv file name in file save dialog This uses setSelectedFile to specify which output filename to make the default in the save dialog. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSVUI.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java index 2d812361..643d4112 100644 --- a/ao-tools/altosui/AltosCSVUI.java +++ b/ao-tools/altosui/AltosCSVUI.java @@ -56,6 +56,7 @@ public class AltosCSVUI path = path.substring(0,dot); path = path.concat(".csv"); csv_chooser = new JFileChooser(path); + csv_chooser.setSelectedFile(new File(path)); int ret = csv_chooser.showSaveDialog(frame); if (ret == JFileChooser.APPROVE_OPTION) { try { -- cgit v1.2.3 From b9623f8ef26491e9fa14e2478295fe6f5cbbd87f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 10 Sep 2010 21:07:14 -0700 Subject: altosui: Remember directory containing firmware files Instead of forcing the user to navigate to the firmware directory each time, this remembers the previous directory and starts there. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlashUI.java | 7 +++++++ ao-tools/altosui/AltosPreferences.java | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 5ed417da..86f57a5f 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -194,6 +194,10 @@ public class AltosFlashUI JFileChooser hexfile_chooser = new JFileChooser(); + File firmwaredir = AltosPreferences.firmwaredir(); + if (firmwaredir != null) + hexfile_chooser.setCurrentDirectory(firmwaredir); + hexfile_chooser.setDialogTitle("Select Flash Image"); hexfile_chooser.setFileFilter(new FileNameExtensionFilter("Flash Image", "ihx")); int returnVal = hexfile_chooser.showOpenDialog(frame); @@ -203,6 +207,9 @@ public class AltosFlashUI file = hexfile_chooser.getSelectedFile(); + if (file != null) + AltosPreferences.set_firmwaredir(file.getParentFile()); + thread = new Thread(this); thread.start(); } diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java index 690f8f1e..52627563 100644 --- a/ao-tools/altosui/AltosPreferences.java +++ b/ao-tools/altosui/AltosPreferences.java @@ -40,6 +40,9 @@ class AltosPreferences { /* callsign preference name */ final static String callsignPreference = "CALLSIGN"; + /* firmware directory preference name */ + final static String firmwaredirPreference = "FIRMWARE"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -55,8 +58,12 @@ class AltosPreferences { /* Voice preference */ static boolean voice; + /* Callsign preference */ static String callsign; + /* Firmware directory */ + static File firmwaredir; + public static void init(Component ui) { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -78,6 +85,12 @@ class AltosPreferences { voice = preferences.getBoolean(voicePreference, true); callsign = preferences.get(callsignPreference,"N0CALL"); + + String firmwaredir_string = preferences.get(firmwaredirPreference, null); + if (firmwaredir_string != null) + firmwaredir = new File(firmwaredir_string); + else + firmwaredir = null; } static void flush_preferences() { @@ -173,4 +186,16 @@ class AltosPreferences { public static String callsign() { return callsign; } + + public static void set_firmwaredir(File new_firmwaredir) { + firmwaredir = new_firmwaredir; + synchronized (preferences) { + preferences.put(firmwaredirPreference, firmwaredir.getPath()); + flush_preferences(); + } + } + + public static File firmwaredir() { + return firmwaredir; + } } -- cgit v1.2.3 From 61590b8729831cb138b2ba6b88802c208d114753 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 15 Sep 2010 06:51:05 +1000 Subject: Add graphing. --- ao-tools/altosui/AltosCsvReader.java | 113 +++++++++++ ao-tools/altosui/AltosDataPoint.java | 29 +++ ao-tools/altosui/AltosGraph.java | 27 +++ ao-tools/altosui/AltosGraphDataChooser.java | 77 +++++++ ao-tools/altosui/AltosGraphTime.java | 222 ++++++++++++++++++++ ao-tools/altosui/AltosGraphUI.java | 301 ++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 17 +- 7 files changed, 785 insertions(+), 1 deletion(-) create mode 100644 ao-tools/altosui/AltosCsvReader.java create mode 100644 ao-tools/altosui/AltosDataPoint.java create mode 100644 ao-tools/altosui/AltosGraph.java create mode 100644 ao-tools/altosui/AltosGraphDataChooser.java create mode 100644 ao-tools/altosui/AltosGraphTime.java create mode 100644 ao-tools/altosui/AltosGraphUI.java diff --git a/ao-tools/altosui/AltosCsvReader.java b/ao-tools/altosui/AltosCsvReader.java new file mode 100644 index 00000000..600788f4 --- /dev/null +++ b/ao-tools/altosui/AltosCsvReader.java @@ -0,0 +1,113 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.lang.UnsupportedOperationException; +import java.util.HashMap; +import java.util.NoSuchElementException; +import java.util.Iterator; +import java.io.*; +import com.csvreader.CsvReader; + +import altosui.AltosDataPoint; + +class AltosCsvReader implements Iterable +{ + public CsvReader csv; + public AltosDataPoint next = null; + + static protected String [] headers = "version serial flight call time rssi state state_name acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_range pad_az pad_el".split(" "); + + AltosCsvReader(Reader stream) { + csv = new CsvReader(stream); + csv.setComment('#'); + csv.setUseComments(true); + csv.setHeaders(headers); + } + AltosCsvReader(String filename) throws FileNotFoundException { + csv = new CsvReader(filename); + csv.setComment('#'); + csv.setUseComments(true); + csv.setHeaders(headers); + } + + public Iterator iterator() { + return new Iterator() { + public void remove() { + throw new UnsupportedOperationException(); + } + public boolean hasNext() { + if (next == null) { + try { + if (csv.readRecord()) { + next = new CsvRow(); + } else { + close(); + return false; + } + } catch (IOException e) { + close(); + return false; + } + } + return true; + } + public AltosDataPoint next() { + if (!hasNext()) + throw new NoSuchElementException(); + AltosDataPoint res = next; + next = null; + return res; + } + }; + } + + public void close() { + csv.close(); + } + + private class CsvRow extends HashMap + implements AltosDataPoint + { + CsvRow() throws IOException { + for (int i = 0; i < headers.length; i++) { + this.put(headers[i], csv.get(headers[i]).trim()); + } + } + + private int intField(String name) { + return Integer.parseInt(get(name).trim()); + } + private double doubleField(String name) { + return Double.valueOf(get(name)).doubleValue(); + } + private String stringField(String name) { + return get(name); + } + + public int version() { return intField("version"); } + public int serial() { return intField("serial"); } + public int flight() { return intField("flight"); } + public String callsign() { return stringField("call"); } + public double time() { return doubleField("time"); } + public double rssi() { return doubleField("rssi"); } + + public int state() { return intField("state"); } + public String state_name() { return stringField("state_name"); } + + public double acceleration() { return doubleField("acceleration"); } + public double pressure() { return doubleField("pressure"); } + public double altitude() { return doubleField("altitude"); } + public double height() { return doubleField("height"); } + public double accel_speed() { return doubleField("accel_speed"); } + public double baro_speed() { return doubleField("baro_speed"); } + public double temperature() { return doubleField("temperature"); } + public double battery_voltage() { + return doubleField("battery_voltage"); + } + public double drogue_voltage() { return doubleField("drogue_voltage"); } + public double main_voltage() { return doubleField("main_voltage"); } + } +} diff --git a/ao-tools/altosui/AltosDataPoint.java b/ao-tools/altosui/AltosDataPoint.java new file mode 100644 index 00000000..66313e03 --- /dev/null +++ b/ao-tools/altosui/AltosDataPoint.java @@ -0,0 +1,29 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +interface AltosDataPoint { + int version(); + int serial(); + int flight(); + String callsign(); + double time(); + double rssi(); + + int state(); + String state_name(); + + double acceleration(); + double pressure(); + double altitude(); + double height(); + double accel_speed(); + double baro_speed(); + double temperature(); + double battery_voltage(); + double drogue_voltage(); + double main_voltage(); +} + diff --git a/ao-tools/altosui/AltosGraph.java b/ao-tools/altosui/AltosGraph.java new file mode 100644 index 00000000..fa3b87c1 --- /dev/null +++ b/ao-tools/altosui/AltosGraph.java @@ -0,0 +1,27 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.*; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.ChartUtilities; + +import altosui.AltosDataPoint; + +abstract class AltosGraph { + public String filename; + public abstract void addData(AltosDataPoint d); + public abstract JFreeChart createChart(); + public void toPNG() throws java.io.IOException { toPNG(300, 500); } + public void toPNG(int width, int height) + throws java.io.IOException + { + File pngout = new File(filename); + JFreeChart chart = createChart(); + ChartUtilities.saveChartAsPNG(pngout, chart, width, height); + System.out.println("Created " + filename); + } +} diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java new file mode 100644 index 00000000..1bf28454 --- /dev/null +++ b/ao-tools/altosui/AltosGraphDataChooser.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosCsvReader; +import altosui.AltosEepromReader; +import altosui.AltosTelemetryReader; + +public class AltosGraphDataChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public Iterable runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + return new AltosCsvReader(new FileReader(file)); + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + filename, + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public AltosGraphDataChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "csv")); + setCurrentDirectory(AltosPreferences.logdir()); + } +} diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java new file mode 100644 index 00000000..c0f99c59 --- /dev/null +++ b/ao-tools/altosui/AltosGraphTime.java @@ -0,0 +1,222 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.HashMap; + +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.AxisLocation; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.labels.StandardXYToolTipGenerator; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.renderer.xy.StandardXYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRenderer; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.TextAnchor; + +import altosui.AltosDataPoint; +import altosui.AltosGraph; + +class AltosGraphTime extends AltosGraph { + static interface Element { + void attachGraph(AltosGraphTime g); + void gotTimeData(double time, AltosDataPoint d); + void addToPlot(AltosGraphTime g, XYPlot plot); + } + + static class TimeAxis implements Element { + private int axis; + private Color color; + private String label; + private AxisLocation locn; + private double min_y = Double.NaN; + + public TimeAxis(int axis, String label, Color color, AxisLocation locn) + { + this.axis = axis; + this.color = color; + this.label = label; + this.locn = locn; + } + + public void setLowerBound(double min_y) { + this.min_y = min_y; + } + + public void attachGraph(AltosGraphTime g) { return; } + public void gotTimeData(double time, AltosDataPoint d) { return; } + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + NumberAxis numAxis = new NumberAxis(label); + if (!Double.isNaN(min_y)) + numAxis.setLowerBound(min_y); + plot.setRangeAxis(axis, numAxis); + plot.setRangeAxisLocation(axis, locn); + numAxis.setLabelPaint(color); + numAxis.setTickLabelPaint(color); + numAxis.setAutoRangeIncludesZero(false); + } + } + + abstract static class TimeSeries implements Element { + protected XYSeries series; + private String axisName; + private Color color; + + public TimeSeries(String axisName, String label, Color color) { + this.series = new XYSeries(label); + this.axisName = axisName; + this.color = color; + } + + public void attachGraph(AltosGraphTime g) { + g.setAxis(this, axisName, color); + } + abstract public void gotTimeData(double time, AltosDataPoint d); + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + XYSeriesCollection dataset = new XYSeriesCollection(); + dataset.addSeries(this.series); + + XYItemRenderer renderer = new StandardXYItemRenderer(); + renderer.setSeriesPaint(0, color); + + int dataNum = g.getDataNum(this); + int axisNum = g.getAxisNum(this); + + plot.setDataset(dataNum, dataset); + plot.mapDatasetToRangeAxis(dataNum, axisNum); + plot.setRenderer(dataNum, renderer); + } + } + + static class StateMarker implements Element { + private double val = Double.NaN; + private String name; + private int state; + + StateMarker(int state, String name) { + this.state = state; + this.name = name; + } + + public void attachGraph(AltosGraphTime g) { return; } + public void gotTimeData(double time, AltosDataPoint d) { + if (Double.isNaN(val) || time < val) { + if (d.state() == state) { + val = time; + } + } + } + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + if (Double.isNaN(val)) + return; + + ValueMarker m = new ValueMarker(val); + m.setLabel(name); + m.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + plot.addDomainMarker(m); + } + } + + private String title; + private ArrayList elements; + private HashMap axes; + private HashMap datasets; + private ArrayList datasetAxis; + + public AltosGraphTime(String title) { + this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png"; + this.title = title; + this.elements = new ArrayList(); + this.axes = new HashMap(); + this.datasets = new HashMap(); + this.datasetAxis = new ArrayList(); + } + + public AltosGraphTime addElement(Element e) { + e.attachGraph(this); + elements.add(e); + return this; + } + + public void setAxis(Element ds, String axisName, Color color) { + Integer axisNum = axes.get(axisName); + int dsNum = datasetAxis.size(); + if (axisNum == null) { + axisNum = newAxis(axisName, color); + } + datasets.put(ds, dsNum); + datasetAxis.add(axisNum); + } + + public int getAxisNum(Element ds) { + return datasetAxis.get( datasets.get(ds) ).intValue(); + } + public int getDataNum(Element ds) { + return datasets.get(ds).intValue(); + } + + private Integer newAxis(String name, Color color) { + int cnt = axes.size(); + AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT; + if (cnt > 0) { + locn = AxisLocation.TOP_OR_RIGHT; + } + Integer res = new Integer(cnt); + axes.put(name, res); + this.addElement(new TimeAxis(cnt, name, color, locn)); + return res; + } + + public void addData(AltosDataPoint d) { + double time = d.time(); + for (Element e : elements) { + e.gotTimeData(time, d); + } + } + + public JFreeChart createChart() { + NumberAxis xAxis = new NumberAxis("Time (s)"); + xAxis.setAutoRangeIncludesZero(false); + XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); + XYPlot plot = new XYPlot(); + plot.setDomainAxis(xAxis); + plot.setRenderer(renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + + renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); + JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, + plot, true); + ChartUtilities.applyCurrentTheme(chart); + + plot.setDomainPannable(true); + plot.setRangePannable(true); + + for (Element e : elements) { + e.addToPlot(this, plot); + } + + return chart; + } + + public void toPNG() throws java.io.IOException { + if (axes.size() > 1) { + toPNG(800, 500); + } else { + toPNG(300, 500); + } + } +} diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java new file mode 100644 index 00000000..73f95023 --- /dev/null +++ b/ao-tools/altosui/AltosGraphUI.java @@ -0,0 +1,301 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.*; +import java.util.ArrayList; + +import javax.swing.JFrame; +import java.awt.Color; + +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.AxisLocation; +import org.jfree.ui.ApplicationFrame; +import org.jfree.ui.RefineryUtilities; + +import altosui.AltosCsvReader; +import altosui.AltosDataPoint; +import altosui.AltosGraphTime; + +public class AltosGraphUI extends JFrame +{ + static final private Color red = new Color(194,31,31); + static final private Color green = new Color(31,194,31); + static final private Color blue = new Color(31,31,194); + static final private Color black = new Color(31,31,31); + + static private class OverallGraphs { + AltosGraphTime.Element height = + new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.height()); + } + }; + + AltosGraphTime.Element speed = + new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { + public void gotTimeData(double time, AltosDataPoint d) { + if (d.state() < 4) { + series.add(time, d.accel_speed()); + } else { + series.add(time, d.baro_speed()); + } + } + }; + + AltosGraphTime.Element acceleration = + new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)", + "Axial Acceleration", blue) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.acceleration()); + } + }; + + AltosGraphTime.Element temperature = + new AltosGraphTime.TimeSeries("Temperature (\u00B0C)", + "Board temperature", red) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.temperature()); + } + }; + + AltosGraphTime.Element drogue_voltage = + new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.drogue_voltage()); + } + }; + + AltosGraphTime.Element main_voltage = + new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.main_voltage()); + } + }; + + AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(2, "Pad"); + AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(3, "Boost"); + AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(4, "Fast"); + AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(5, "Coast"); + AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(6, "Drogue"); + AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(7, "Main"); + AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(8, "Landed"); + + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Overall " + suffix)) + .addElement(e_boost) + .addElement(e_drogue) + .addElement(e_main) + .addElement(e_landed); + } + + public ArrayList graphs() { + ArrayList graphs = new ArrayList(); + + graphs.add( myAltosGraphTime("Summary") + .addElement(height) + .addElement(speed) + .addElement(acceleration) ); + + graphs.add( myAltosGraphTime("Altitude") + .addElement(height) ); + + graphs.add( myAltosGraphTime("Speed") + .addElement(speed) ); + + graphs.add( myAltosGraphTime("Acceleration") + .addElement(acceleration) ); + + graphs.add( myAltosGraphTime("Temperature") + .addElement(temperature) ); + + graphs.add( myAltosGraphTime("Continuity") + .addElement(drogue_voltage) + .addElement(main_voltage) ); + + return graphs; + } + } + + static private class AscentGraphs extends OverallGraphs { + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Ascent " + suffix) { + public void addData(AltosDataPoint d) { + int state = d.state(); + if (3 <= state && state <= 5) { + super.addData(d); + } + } + }).addElement(e_boost) + .addElement(e_fast) + .addElement(e_coast); + } + } + + static private class DescentGraphs extends OverallGraphs { + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Descent " + suffix) { + public void addData(AltosDataPoint d) { + int state = d.state(); + if (6 <= state && state <= 7) { + super.addData(d); + } + } + }).addElement(e_drogue) + .addElement(e_main); + // ((XYGraph)graph[8]).ymin = new Double(-50); + } + } + + public AltosGraphUI(JFrame frame) + { + super("Altos Graph"); + + AltosGraphDataChooser chooser; + chooser = new AltosGraphDataChooser(frame); + Iterable reader = chooser.runDialog(); + if (reader == null) + return; + + init(reader, 0); + } + + public AltosGraphUI(Iterable data, int which) + { + super("Altos Graph"); + init(data, which); + } + + private void init(Iterable data, int which) { + AltosGraph graph = createGraph(data, which); + + JFreeChart chart = graph.createChart(); + ChartPanel chartPanel = new ChartPanel(chart); + chartPanel.setMouseWheelEnabled(true); + chartPanel.setPreferredSize(new java.awt.Dimension(800, 500)); + setContentPane(chartPanel); + + pack(); + + RefineryUtilities.centerFrameOnScreen(this); + + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setVisible(true); + } + + private static AltosGraph createGraph(Iterable data, + int which) + { + return createGraphsWhich(data, which).get(0); + } + + private static ArrayList createGraphs( + Iterable data) + { + return createGraphsWhich(data, -1); + } + + private static ArrayList createGraphsWhich( + Iterable data, int which) + { + ArrayList graph = new ArrayList(); + graph.addAll((new OverallGraphs()).graphs()); + graph.addAll((new AscentGraphs()).graphs()); + graph.addAll((new DescentGraphs()).graphs()); + + if (which > 0) { + if (which >= graph.size()) { + which = 0; + } + AltosGraph g = graph.get(which); + graph = new ArrayList(); + graph.add(g); + } + + for (AltosDataPoint dp : data) { + for (AltosGraph g : graph) { + g.addData(dp); + } + } + + return graph; + } + + public static void main(String[] args) + throws java.io.FileNotFoundException, java.io.IOException + { + if (args.length < 1 || 2 < args.length) + { + System.out.println("Please specify telemetry csv"); + return; + } + + AltosCsvReader csv = new AltosCsvReader(args[0]); + if (args.length == 1) { + for (AltosGraph g : createGraphs(csv)) { + g.toPNG(); + } + } else { + int which = Integer.parseInt(args[1].trim()); + AltosGraphUI demo = new AltosGraphUI(csv, which); + } + } +} + +/* gnuplot bits... + * +300x400 + +-------------------------------------------------------- +TOO HARD! :) + +"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)" + 5:($7 < 6 ? $24-$11 : 1/0) +"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)" + 5:($7 < 6 ? 1/0 : $24-$11) + +set output "overall-gps-accuracy.png" +set ylabel "distance above sea level (m)" +plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \ + "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1 + +set term png tiny size 700,700 enhanced +set xlabel "m" +set ylabel "m" +set polar +set grid polar +set rrange[*:*] +set angles degrees + +set output "overall-gps-path.png" +#:30 with yerrorlines +plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \ + "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \ + "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \ + "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \ + "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ + "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ + "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" + +set output "ascent-gps-path.png" +plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \ + "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \ + "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \ + "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast" + +set output "descent-gps-path.png" +plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ + "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ + "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" + + */ + + diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index edee146d..ad02f2ef 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -667,6 +667,13 @@ public class AltosUI extends JFrame { new AltosCSVUI(AltosUI.this); } + /* Load a flight log CSV file and display a pretty graph. + */ + + private void GraphData() { + new AltosGraphUI(AltosUI.this); + } + /* Create the AltosUI menus */ private void createMenu() { @@ -713,6 +720,14 @@ public class AltosUI extends JFrame { }); menu.add(item); + item = new JMenuItem("Graph Data",KeyEvent.VK_F); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + GraphData(); + } + }); + menu.add(item); + item = new JMenuItem("Quit",KeyEvent.VK_Q); item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK)); @@ -895,4 +910,4 @@ public class AltosUI extends JFrame { altosui.setVisible(true); } } -} \ No newline at end of file +} -- cgit v1.2.3 From af404b428bd742039afc25ff3850f76bc92c7c29 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 15 Sep 2010 07:24:04 +1000 Subject: Add JFreeChart to Makefile.am --- ao-tools/altosui/Makefile.am | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index fa391889..0a91f939 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -5,7 +5,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(JFREECHART)/*:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -48,8 +48,19 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryReader.java \ AltosUI.java \ + AltosCsvReader.java \ + AltosDataPoint.java \ + AltosGraph.java \ + AltosGraphTime.java \ + AltosGraphUI.java \ + AltosGraphDataChooser.java \ AltosVoice.java +JFREECHART_CLASS= \ + jfreechart.jar \ + jcommon.jar \ + csv.jar + FREETTS_CLASS= \ cmudict04.jar \ cmulex.jar \ @@ -82,7 +93,7 @@ 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) +FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) LINUX_EXTRA=altosui-fat @@ -97,7 +108,7 @@ all-local: classes/altosui $(JAR) altosui altosui-test clean-local: -rm -rf classes $(JAR) $(FATJAR) \ $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ - $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ + $(JFREECHART_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test macosx linux fat: $(FATJAR) $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) @@ -143,7 +154,7 @@ $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) -C classes altosui \ -C ../libaltos libaltosJNI -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JAVA_ICON) +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(LIBALTOS) $(JAVA_ICON) jar cfm $@ Manifest-fat.txt \ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ -C classes altosui \ @@ -151,11 +162,11 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(LIBALTOS) $(JA Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar" >> $@ + echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JFREECHAR)/jcommon.jar $(JFREECHART)/csv.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: freetts.jar" >> $@ + echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar csv.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@ -- cgit v1.2.3 From 7a4d7110debb88f4e906fee7c46f2badd561809d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 Sep 2010 02:50:43 -0700 Subject: altosui: Use recorded ground acceleration when reading eeprom files The flight software records 1000 accelerometer samples and records that in the flight log. Use that value instead of using the very few samples recorded in the eeprom before boost is detected. This generates far more accurate accerometer data in the .csv files. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromReader.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java index 4cc8536a..03e73812 100644 --- a/ao-tools/altosui/AltosEepromReader.java +++ b/ao-tools/altosui/AltosEepromReader.java @@ -95,7 +95,6 @@ public class AltosEepromReader extends AltosReader { boolean last_reported; double ground_pres; - double ground_accel; int n_pad_samples; @@ -140,9 +139,6 @@ public class AltosEepromReader extends AltosReader { ground_pres += state.pres; state.ground_pres = (int) (ground_pres / n_pad_samples); state.flight_pres = state.ground_pres; - ground_accel += state.accel; - state.ground_accel = (int) (ground_accel / n_pad_samples); - state.flight_accel = state.ground_accel; } else { state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; @@ -345,6 +341,7 @@ public class AltosEepromReader extends AltosReader { tick = record.tick; if (record.cmd == Altos.AO_LOG_FLIGHT) { state.ground_accel = record.a; + state.flight_accel = record.a; state.flight = record.b; boost_tick = tick; seen |= seen_flight; -- cgit v1.2.3 From 1260589976c1a95848b298497fd251c4ee7d3f93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 Sep 2010 02:52:29 -0700 Subject: altosui: Write raw sensor data to .csv files For data export, provide the raw sensor samples instead of the filtered values. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSV.java | 6 +++--- ao-tools/altosui/AltosRecord.java | 22 +++++++++++++++++----- ao-tools/altosui/AltosState.java | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 07fa371f..f7b3c03c 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -111,9 +111,9 @@ public class AltosCSV { 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.raw_pressure(), + record.raw_altitude(), + record.raw_height(), record.accel_speed(), state.baro_speed, record.temperature(), diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java index b670ee37..18c6079d 100644 --- a/ao-tools/altosui/AltosRecord.java +++ b/ao-tools/altosui/AltosRecord.java @@ -73,7 +73,11 @@ public class AltosRecord { return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; } - public double pressure() { + public double raw_pressure() { + return barometer_to_pressure(pres); + } + + public double filtered_pressure() { return barometer_to_pressure(flight_pres); } @@ -81,16 +85,24 @@ public class AltosRecord { return barometer_to_pressure(ground_pres); } - public double altitude() { - return AltosConvert.pressure_to_altitude(pressure()); + public double filtered_altitude() { + return AltosConvert.pressure_to_altitude(filtered_pressure()); + } + + public double raw_altitude() { + return AltosConvert.pressure_to_altitude(raw_pressure()); } public double ground_altitude() { return AltosConvert.pressure_to_altitude(ground_pressure()); } - public double height() { - return altitude() - ground_altitude(); + public double filtered_height() { + return filtered_altitude() - ground_altitude(); + } + + public double raw_height() { + return raw_altitude() - ground_altitude(); } public double battery_voltage() { diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 3ef00f35..90e73f5e 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -80,7 +80,7 @@ public class AltosState { data = cur; ground_altitude = data.ground_altitude(); - height = data.altitude() - ground_altitude; + height = data.filtered_altitude() - ground_altitude; report_time = System.currentTimeMillis(); -- cgit v1.2.3 From fd010661ced6075f82a961625826665a3d8d1efe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 14:00:04 -0700 Subject: altosui: Factor some UI elements into separate classes Clean up AltosUI by moving the two main tables to separate class files. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosInfoTable.java | 221 +++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosStatusTable.java | 73 +++++++++++ ao-tools/altosui/AltosUI.java | 192 +++------------------------- ao-tools/altosui/Makefile-standalone | 2 + ao-tools/altosui/Makefile.am | 7 +- 5 files changed, 315 insertions(+), 180 deletions(-) create mode 100644 ao-tools/altosui/AltosInfoTable.java create mode 100644 ao-tools/altosui/AltosStatusTable.java diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java new file mode 100644 index 00000000..9964ab10 --- /dev/null +++ b/ao-tools/altosui/AltosInfoTable.java @@ -0,0 +1,221 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosFlightInfoTableModel; +import altosui.AltosState; + +public class AltosInfoTable { + private Box box; + private JTable table[]; + private AltosFlightInfoTableModel model[]; + private Box ibox[]; + + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + + static final int info_columns = 3; + static final int info_rows = 17; + + public AltosInfoTable() { + box = Box.createHorizontalBox(); + model = new AltosFlightInfoTableModel[info_columns]; + table = new JTable[info_columns]; + ibox = new Box[info_columns]; + for (int i = 0; i < info_columns; i++) { + model[i] = new AltosFlightInfoTableModel(); + table[i] = new JTable(model[i]); + ibox[i] = box.createVerticalBox(); + + table[i].setFont(infoValueFont); + table[i].setRowHeight(rowHeight()); + table[i].setShowGrid(true); + ibox[i].add(table[i].getTableHeader()); + ibox[i].add(table[i]); + box.add(ibox[i]); + } + } + + public int rowHeight() { + FontMetrics infoValueMetrics = table[0].getFontMetrics(infoValueFont); + return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 20 / 10; + } + + public int columnWidth() { + FontMetrics infoValueMetrics = table[0].getFontMetrics(infoValueFont); + return infoValueMetrics.charWidth('0') * 20 * 2; + } + + public int height() { + return rowHeight() * info_rows; + } + + public int width() { + return columnWidth() * info_columns; + } + + public Box box() { + return box; + } + + void info_reset() { + for (int i = 0; i < info_columns; i++) + model[i].resetRow(); + } + + void info_add_row(int col, String name, String value) { + model[col].addRow(name, value); + } + + void info_add_row(int col, String name, String format, Object... parameters) { + model[col].addRow(name, String.format(format, parameters)); + } + + void info_add_deg(int col, String name, double v, int pos, int neg) { + int c = pos; + if (v < 0) { + c = neg; + v = -v; + } + double deg = Math.floor(v); + double min = (v - deg) * 60; + + model[col].addRow(name, String.format("%3.0f°%08.5f'", deg, min)); + } + + void info_finish() { + for (int i = 0; i < info_columns; i++) + model[i].finish(); + } + + public void clear() { + info_reset(); + info_finish(); + } + + public void show(AltosState state, int crc_errors) { + if (state == null) + return; + info_reset(); + 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); + info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); + info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); + info_add_row(0, "Temperature", "%9.2f °C", state.temperature); + info_add_row(0, "Battery", "%9.2f V", state.battery); + info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); + info_add_row(0, "Main", "%9.2f V", state.main_sense); + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); + 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) + info_add_row(1, "GPS", " unlocked"); + else + info_add_row(1, "GPS", " missing"); + info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + info_add_row(1, "GPS altitude", "%6d", state.gps.alt); + info_add_row(1, "GPS height", "%6.0f", state.gps_height); + + /* The SkyTraq GPS doesn't report these values */ + if (false) { + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%8.1f m/s", + state.gps.climb_rate); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", + state.gps.h_error, state.gps.v_error); + } + info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); + + if (state.npad > 0) { + if (state.from_pad != null) { + 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'); + info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); + } + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.year, + state.gps.month, + state.gps.day); + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.hour, + state.gps.minute, + state.gps.second); + int nsat_vis = 0; + int c; + + if (state.gps.cc_gps_sat == null) + info_add_row(2, "Satellites Visible", "%4d", 0); + else { + info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); + for (c = 0; c < state.gps.cc_gps_sat.length; c++) { + info_add_row(2, "Satellite id,C/N0", + "%4d, %4d", + state.gps.cc_gps_sat[c].svid, + state.gps.cc_gps_sat[c].c_n0); + } + } + } + info_finish(); + } +} diff --git a/ao-tools/altosui/AltosStatusTable.java b/ao-tools/altosui/AltosStatusTable.java new file mode 100644 index 00000000..3965a57d --- /dev/null +++ b/ao-tools/altosui/AltosStatusTable.java @@ -0,0 +1,73 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosFlightStatusTableModel; +import altosui.AltosFlightInfoTableModel; + +public class AltosStatusTable extends JTable { + private AltosFlightStatusTableModel flightStatusModel; + + JFrame frame; + + private Font statusFont = new Font("SansSerif", Font.BOLD, 24); + + public AltosStatusTable(JFrame in_frame) { + super((TableModel) new AltosFlightStatusTableModel()); + flightStatusModel = (AltosFlightStatusTableModel) getModel(); + frame = in_frame; + + setFont(statusFont); + + TableColumnModel tcm = getColumnModel(); + + for (int i = 0; i < flightStatusModel.getColumnCount(); i++) { + DefaultTableCellRenderer r = new DefaultTableCellRenderer(); + r.setFont(statusFont); + r.setHorizontalAlignment(SwingConstants.CENTER); + tcm.getColumn(i).setCellRenderer(r); + } + + setRowHeight(rowHeight()); + setShowGrid(false); + } + + public int rowHeight() { + FontMetrics statusMetrics = getFontMetrics(statusFont); + return (statusMetrics.getHeight() + statusMetrics.getLeading()) * 15 / 10; + } + + public int height() { + return rowHeight * 4; + } + + public void set(AltosState state) { + flightStatusModel.set(state); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index edee146d..456031ec 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -38,31 +38,25 @@ import altosui.AltosDeviceDialog; import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; -import altosui.AltosFlightStatusTableModel; import altosui.AltosFlightInfoTableModel; import altosui.AltosChannelMenu; import altosui.AltosFlashUI; import altosui.AltosLogfileChooser; import altosui.AltosCSVUI; import altosui.AltosLine; +import altosui.AltosStatusTable; +import altosui.AltosInfoTable; import libaltosJNI.*; public class AltosUI extends JFrame { private int channel = -1; - private AltosFlightStatusTableModel flightStatusModel; - private JTable flightStatus; - - static final int info_columns = 3; - - private AltosFlightInfoTableModel[] flightInfoModel; - private JTable[] flightInfo; + private AltosStatusTable flightStatus; + private AltosInfoTable flightInfo; private AltosSerial serial_line; private AltosLog altos_log; - private Box[] ibox; private Box vbox; - private Box hbox; private Font statusFont = new Font("SansSerif", Font.BOLD, 24); private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); @@ -98,44 +92,12 @@ public class AltosUI extends JFrame { vbox = Box.createVerticalBox(); this.add(vbox); - flightStatusModel = new AltosFlightStatusTableModel(); - flightStatus = new JTable(flightStatusModel); - flightStatus.setFont(statusFont); - TableColumnModel tcm = flightStatus.getColumnModel(); - for (int i = 0; i < flightStatusModel.getColumnCount(); i++) { - DefaultTableCellRenderer r = new DefaultTableCellRenderer(); - r.setFont(statusFont); - r.setHorizontalAlignment(SwingConstants.CENTER); - tcm.getColumn(i).setCellRenderer(r); - } - - FontMetrics statusMetrics = flightStatus.getFontMetrics(statusFont); - int statusHeight = (statusMetrics.getHeight() + statusMetrics.getLeading()) * 15 / 10; - flightStatus.setRowHeight(statusHeight); - flightStatus.setShowGrid(false); + flightStatus = new AltosStatusTable(this); vbox.add(flightStatus); - hbox = Box.createHorizontalBox(); - vbox.add(hbox); - - flightInfo = new JTable[3]; - flightInfoModel = new AltosFlightInfoTableModel[3]; - ibox = new Box[3]; - FontMetrics infoValueMetrics = flightStatus.getFontMetrics(infoValueFont); - int infoHeight = (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 20 / 10; - - for (int i = 0; i < info_columns; i++) { - ibox[i] = Box.createVerticalBox(); - flightInfoModel[i] = new AltosFlightInfoTableModel(); - flightInfo[i] = new JTable(flightInfoModel[i]); - flightInfo[i].setFont(infoValueFont); - flightInfo[i].setRowHeight(infoHeight); - flightInfo[i].setShowGrid(true); - ibox[i].add(flightInfo[i].getTableHeader()); - ibox[i].add(flightInfo[i]); - hbox.add(ibox[i]); - } + flightInfo = new AltosInfoTable(); + vbox.add(flightInfo.box()); setTitle("AltOS"); @@ -144,8 +106,8 @@ public class AltosUI extends JFrame { serial_line = new AltosSerial(); altos_log = new AltosLog(serial_line); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - this.setSize(new Dimension (infoValueMetrics.charWidth('0') * 6 * 20, - statusHeight * 4 + infoHeight * 17)); + this.setSize(new Dimension (flightInfo.width(), + flightStatus.height() + flightInfo.height())); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -157,136 +119,11 @@ public class AltosUI extends JFrame { voice.speak("Rocket flight monitor ready."); } - public void info_reset() { - for (int i = 0; i < info_columns; i++) - flightInfoModel[i].resetRow(); - } - - public void info_add_row(int col, String name, String value) { - flightInfoModel[col].addRow(name, value); - } - - public void info_add_row(int col, String name, String format, Object... parameters) { - flightInfoModel[col].addRow(name, String.format(format, parameters)); - } - - public void info_add_deg(int col, String name, double v, int pos, int neg) { - int c = pos; - if (v < 0) { - c = neg; - v = -v; - } - double deg = Math.floor(v); - double min = (v - deg) * 60; - - flightInfoModel[col].addRow(name, String.format("%3.0f°%08.5f'", deg, min)); - } - - public void info_finish() { - for (int i = 0; i < info_columns; i++) - flightInfoModel[i].finish(); - } - - public void show(AltosState state, int crc_errors) { - if (state == null) - return; - flightStatusModel.set(state); - - info_reset(); - 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); - info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); - info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); - info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); - info_add_row(0, "Temperature", "%9.2f °C", state.temperature); - info_add_row(0, "Battery", "%9.2f V", state.battery); - info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); - info_add_row(0, "Main", "%9.2f V", state.main_sense); - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); - 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) - info_add_row(1, "GPS", " unlocked"); - else - info_add_row(1, "GPS", " missing"); - info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); - info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); - info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - info_add_row(1, "GPS altitude", "%6d", state.gps.alt); - info_add_row(1, "GPS height", "%6.0f", state.gps_height); - - /* The SkyTraq GPS doesn't report these values */ - if (false) { - info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", - state.gps.ground_speed, - state.gps.course); - info_add_row(1, "GPS climb rate", "%8.1f m/s", - state.gps.climb_rate); - info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", - state.gps.h_error, state.gps.v_error); - } - info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); - - if (state.npad > 0) { - if (state.from_pad != null) { - 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'); - info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); - } - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.year, - state.gps.month, - state.gps.day); - info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.hour, - state.gps.minute, - state.gps.second); - int nsat_vis = 0; - int c; - - if (state.gps.cc_gps_sat == null) - info_add_row(2, "Satellites Visible", "%4d", 0); - else { - info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); - for (c = 0; c < state.gps.cc_gps_sat.length; c++) { - info_add_row(2, "Satellite id,C/N0", - "%4d, %4d", - state.gps.cc_gps_sat[c].svid, - state.gps.cc_gps_sat[c].c_n0); - } - } + void show(AltosState state, int crc_errors) { + if (state != null) { + flightStatus.set(state); + flightInfo.show(state, crc_errors); } - info_finish(); } class IdleThread extends Thread { @@ -455,8 +292,7 @@ public class AltosUI extends JFrame { idle_thread = new IdleThread(); - info_reset(); - info_finish(); + flightInfo.clear(); try { for (;;) { try { diff --git a/ao-tools/altosui/Makefile-standalone b/ao-tools/altosui/Makefile-standalone index 90621f36..a95a5aa8 100644 --- a/ao-tools/altosui/Makefile-standalone +++ b/ao-tools/altosui/Makefile-standalone @@ -24,6 +24,7 @@ CLASSFILES=\ AltosGreatCircle.class \ AltosHexfile.class \ AltosLine.class \ + AltosInfoTable.class \ AltosLog.class \ AltosLogfileChooser.class \ AltosParse.class \ @@ -33,6 +34,7 @@ CLASSFILES=\ AltosSerialMonitor.class \ AltosSerial.class \ AltosState.class \ + AltosStatusTable.class \ AltosTelemetry.class \ AltosTelemetryReader.class \ AltosUI.class \ diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index fa391889..56ac0520 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -33,6 +33,7 @@ altosui_JAVA = \ AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ + AltosInfoTable.java \ AltosLine.java \ AltosLogfileChooser.java \ AltosLog.java \ @@ -45,6 +46,7 @@ altosui_JAVA = \ AltosSerial.java \ AltosSerialMonitor.java \ AltosState.java \ + AltosStatusTable.java \ AltosTelemetry.java \ AltosTelemetryReader.java \ AltosUI.java \ @@ -100,8 +102,6 @@ clean-local: $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test macosx linux -fat: $(FATJAR) $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) - if FATINSTALL FATTARGET=$(FATDIR)/$(VERSION) @@ -124,8 +124,11 @@ $(WINDOWS_DIST_TARGET): $(WINDOWS_DIST) mkdir -p $(FATTARGET) cp -p $< $@ +else +fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) endif + altosuidir=$(datadir)/java install-altosuiJAVA: altosui.jar -- cgit v1.2.3 From 34ca8c00f4be72c314baff4c96f1e2f010948454 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 20 Sep 2010 06:30:49 -0700 Subject: altosui: remove unused ReplayThread wrapper classes These aren't used now that the replay opener dialog knows how to build a reader from a filename. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 456031ec..1adeeccf 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -445,19 +445,6 @@ public class AltosUI extends JFrame { } } - class ReplayTelemetryThread extends ReplayThread { - ReplayTelemetryThread(FileInputStream in, String in_name) { - super(new AltosTelemetryReader(in), in_name); - } - - } - - class ReplayEepromThread extends ReplayThread { - ReplayEepromThread(FileInputStream in, String in_name) { - super(new AltosEepromReader(in), in_name); - } - } - Thread display_thread; private void stop_display() { -- cgit v1.2.3 From e66919aa46193bd8c7a1e86fb32a3367dae121f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 23 Sep 2010 16:52:51 -0700 Subject: altosui: Require 4 sats for 'good' GPS data Wait for 10 consecutive GPS reports with at least 4 sats before reporting "GPS ready" state. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosState.java | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 90e73f5e..1048bb51 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -60,6 +60,7 @@ public class AltosState { static final int MIN_PAD_SAMPLES = 10; int npad; + int ngps; int gps_waiting; boolean gps_ready; @@ -97,6 +98,7 @@ public class AltosState { /* Preserve any existing gps data */ npad = prev_state.npad; + ngps = prev_state.ngps; gps = prev_state.gps; pad_lat = prev_state.pad_lat; pad_lon = prev_state.pad_lon; @@ -120,15 +122,23 @@ public class AltosState { baro_speed = prev_state.baro_speed; } else { npad = 0; + ngps = 0; gps = null; baro_speed = 0; time_change = 0; } if (state == Altos.ao_flight_pad) { - if (data.gps != null && data.gps.locked) { + + /* Track consecutive 'good' gps reports, waiting for 10 of them */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) npad++; - if (npad > 1) { + else + npad = 0; + + /* Average GPS data while on the pad */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { + if (ngps > 1) { /* filter pad position */ pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; @@ -138,8 +148,7 @@ public class AltosState { pad_lon = data.gps.lon; pad_alt = data.gps.alt; } - } else { - npad = 0; + ngps++; } } @@ -163,13 +172,13 @@ public class AltosState { if (data.gps != null) { if (gps == null || !gps.locked || data.gps.locked) gps = data.gps; - if (npad > 0 && gps.locked) { + if (ngps > 0 && gps.locked) { from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); } } elevation = 0; range = -1; - if (npad > 0) { + if (ngps > 0) { gps_height = gps.alt - pad_alt; if (from_pad != null) { elevation = Math.atan2(height, from_pad.distance) * 180 / Math.PI; -- cgit v1.2.3 From c89a34d1eb25155405b0036baeadc7bbfeade1c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Sep 2010 17:11:48 -0700 Subject: altosui: Create iterables for log file scanning. Split out display threads Convert from log file reading paradigm to using iterators which is more idiomatic for java. Split more code out of AltosUI.java, including the display update threads for telemetry monitoring and logfile replay.x Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSV.java | 20 +- ao-tools/altosui/AltosCSVUI.java | 15 +- ao-tools/altosui/AltosDisplayThread.java | 255 ++++++++++++++++ ao-tools/altosui/AltosEepromIterable.java | 419 +++++++++++++++++++++++++++ ao-tools/altosui/AltosEepromReader.java | 406 -------------------------- ao-tools/altosui/AltosLogfileChooser.java | 11 +- ao-tools/altosui/AltosRecord.java | 2 +- ao-tools/altosui/AltosRecordIterable.java | 42 +++ ao-tools/altosui/AltosReplayThread.java | 83 ++++++ ao-tools/altosui/AltosTelemetryIterable.java | 83 ++++++ ao-tools/altosui/AltosTelemetryReader.java | 88 ------ ao-tools/altosui/AltosUI.java | 282 ++---------------- ao-tools/altosui/Makefile.am | 7 +- 13 files changed, 920 insertions(+), 793 deletions(-) create mode 100644 ao-tools/altosui/AltosDisplayThread.java create mode 100644 ao-tools/altosui/AltosEepromIterable.java delete mode 100644 ao-tools/altosui/AltosEepromReader.java create mode 100644 ao-tools/altosui/AltosRecordIterable.java create mode 100644 ao-tools/altosui/AltosReplayThread.java create mode 100644 ao-tools/altosui/AltosTelemetryIterable.java delete mode 100644 ao-tools/altosui/AltosTelemetryReader.java diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index f7b3c03c..7f14adad 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -207,22 +207,10 @@ public class AltosCSV { 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 void write(AltosRecordIterable iterable) { + iterable.write_comments(out()); + for (AltosRecord r : iterable) + write(r); } public AltosCSV(File in_name) throws FileNotFoundException { diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java index 643d4112..4eb72de8 100644 --- a/ao-tools/altosui/AltosCSVUI.java +++ b/ao-tools/altosui/AltosCSVUI.java @@ -35,17 +35,17 @@ public class AltosCSVUI extends JDialog implements Runnable, ActionListener { - JFrame frame; - Thread thread; - AltosReader reader; - AltosCSV writer; + JFrame frame; + Thread thread; + AltosRecordIterable iterable; + AltosCSV writer; public void run() { AltosLogfileChooser chooser; chooser = new AltosLogfileChooser(frame); - reader = chooser.runDialog(); - if (reader == null) + iterable = chooser.runDialog(); + if (iterable == null) return; JFileChooser csv_chooser; @@ -67,8 +67,7 @@ public class AltosCSVUI "Cannot open file", JOptionPane.ERROR_MESSAGE); } - writer.write(reader); - reader.close(); + writer.write(iterable); writer.close(); } } diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java new file mode 100644 index 00000000..9cc3d5ce --- /dev/null +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -0,0 +1,255 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosDisplayThread extends Thread { + + Frame parent; + IdleThread idle_thread; + AltosVoice voice; + String name; + int crc_errors; + AltosStatusTable flightStatus; + AltosInfoTable flightInfo; + + class IdleThread extends Thread { + + boolean started; + private AltosState state; + int reported_landing; + int report_interval; + long report_time; + + public synchronized void report(boolean last) { + if (state == null) + return; + + /* reset the landing count once we hear about a new flight */ + if (state.state < Altos.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) { + return; + } + + /* If the rocket isn't on the pad, then report height */ + 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; + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (state.state >= Altos.ao_flight_drogue && + (last || + System.currentTimeMillis() - state.report_time >= 15000 || + state.state == Altos.ao_flight_landed)) + { + if (Math.abs(state.baro_speed) < 20 && state.height < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.from_pad != null) + 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 (;;) { + 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 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(); + } + } + + void init() { } + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + + void close(boolean interrupted) { } + + void update(AltosState state) throws InterruptedException { } + + 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) { + voice.speak("GPS ready"); + ret = true; + } + else if (old_state != null) { + voice.speak("GPS lost"); + ret = true; + } + } + old_state = state; + return ret; + } + + void show(AltosState state, int crc_errors) { + if (state != null) { + flightStatus.set(state); + flightInfo.show(state, crc_errors); + } + } + + public void run() { + boolean interrupted = false; + String line; + AltosState state = null; + AltosState old_state = null; + boolean told; + + idle_thread = new IdleThread(); + + flightInfo.clear(); + try { + for (;;) { + try { + AltosRecord record = read(); + if (record == null) + break; + old_state = state; + state = new AltosState(record, state); + update(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(parent, + String.format("Error reading from \"%s\"", name), + "Telemetry Read Error", + JOptionPane.ERROR_MESSAGE); + } finally { + close(interrupted); + idle_thread.interrupt(); + try { + idle_thread.join(); + } catch (InterruptedException ie) {} + } + } + + public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info) { + parent = in_parent; + voice = in_voice; + flightStatus = in_status; + flightInfo = in_info; + } + + public void report() { + if (idle_thread != null) + idle_thread.report(true); + } + +} diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java new file mode 100644 index 00000000..d4ac3f3e --- /dev/null +++ b/ao-tools/altosui/AltosEepromIterable.java @@ -0,0 +1,419 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosRecord; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosEepromMonitor; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedRecord extends AltosEepromRecord implements Comparable { + + public int index; + + public AltosOrderedRecord(String line, int in_index, int prev_tick) + throws ParseException { + super(line); + int new_tick = tick | (prev_tick & ~0xffff); + if (new_tick < prev_tick) { + if (prev_tick - new_tick > 0x8000) + new_tick += 0x10000; + } + tick = new_tick; + 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) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; + + AltosEepromRecord flight_record; + AltosEepromRecord gps_date_record; + + TreeSet records; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case Altos.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.a; + state.flight_accel = record.a; + state.flight = record.b; + eeprom.boost_tick = record.tick; + break; + case Altos.AO_LOG_SENSOR: + state.accel = record.a; + state.pres = record.b; + if (state.state < Altos.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + state.flight_vel += (state.accel_plus_g - state.accel); + } + eeprom.seen |= seen_sensor; + break; + case Altos.AO_LOG_TEMP_VOLT: + state.temp = record.a; + state.batt = record.b; + eeprom.seen |= seen_temp_volt; + break; + case Altos.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + break; + case Altos.AO_LOG_STATE: + state.state = record.a; + break; + case Altos.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; + state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; + state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> + Altos.AO_GPS_NUM_SAT_SHIFT; + break; + case Altos.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case Altos.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case Altos.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case Altos.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case Altos.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case Altos.AO_LOG_CONFIG_VERSION: + break; + case Altos.AO_LOG_MAIN_DEPLOY: + break; + case Altos.AO_LOG_APOGEE_DELAY: + break; + case Altos.AO_LOG_RADIO_CHANNEL: + break; + case Altos.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case Altos.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case Altos.AO_LOG_RADIO_CAL: + break; + case Altos.AO_LOG_MANUFACTURER: + 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; + } + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = Altos.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedRecord record = iterator.next(); + switch (record.cmd) { + case Altos.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case Altos.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case Altos.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case Altos.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case Altos.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case Altos.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case Altos.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case Altos.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case Altos.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case Altos.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case Altos.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + } + } + } + + /* + * 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedRecord last_gps_time = null; + + int index = 0; + int prev_tick = 0; + + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick); + if (record == null) + break; + if (record.cmd == Altos.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd == Altos.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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) { + gps_date_record = record; + continue; + } + + /* 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 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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == Altos.AO_LOG_STATE && + record.a == Altos.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/ao-tools/altosui/AltosEepromReader.java b/ao-tools/altosui/AltosEepromReader.java deleted file mode 100644 index 03e73812..00000000 --- a/ao-tools/altosui/AltosEepromReader.java +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.AltosRecord; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - -/* - * AltosRecords with an index field so they can be sorted by tick while preserving - * the original ordering for elements with matching ticks - */ -class AltosOrderedRecord extends AltosEepromRecord implements Comparable { - - public int index; - - public AltosOrderedRecord(String line, int in_index, int prev_tick) - throws ParseException { - super(line); - int new_tick = tick | (prev_tick & ~0xffff); - if (new_tick < prev_tick) { - if (prev_tick - new_tick > 0x8000) - new_tick += 0x10000; - } - tick = new_tick; - 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) - return tick_diff; - return index - o.index; - } -} - -public class AltosEepromReader extends AltosReader { - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - - static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; - - AltosRecord state; - AltosOrderedRecord record; - - TreeSet records; - - Iterator record_iterator; - - int seen; - - int index; - - boolean last_reported; - - double ground_pres; - - int n_pad_samples; - - int gps_tick; - - int boost_tick; - - boolean saw_gps_date; - - boolean missing_gps_time; - - public AltosRecord read() throws IOException, ParseException { - for (;;) { - if (record == null) { - if (!record_iterator.hasNext()) { - if (last_reported) - return null; - last_reported = true; - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - boost_tick) / 100.0; - return r; - } - record = record_iterator.next(); - - if ((seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - boost_tick) / 100.0; - return r; - } - } - - state.tick = record.tick; - switch (record.cmd) { - case Altos.AO_LOG_FLIGHT: - /* recorded when first read from the file */ - break; - case Altos.AO_LOG_SENSOR: - state.accel = record.a; - state.pres = record.b; - if (state.state < Altos.ao_flight_boost) { - n_pad_samples++; - ground_pres += state.pres; - state.ground_pres = (int) (ground_pres / n_pad_samples); - state.flight_pres = state.ground_pres; - } else { - state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - state.flight_vel += (state.accel_plus_g - state.accel); - } - seen |= seen_sensor; - break; - case Altos.AO_LOG_TEMP_VOLT: - state.temp = record.a; - state.batt = record.b; - seen |= seen_temp_volt; - break; - case Altos.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - seen |= seen_deploy; - break; - case Altos.AO_LOG_STATE: - 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); - int flags = (record.b >> 8); - state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; - state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; - state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; - state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> - Altos.AO_GPS_NUM_SAT_SHIFT; - break; - case Altos.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case Altos.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case Altos.AO_LOG_GPS_ALT: - state.gps.alt = record.a; - break; - case Altos.AO_LOG_GPS_SAT: - if (state.tick == gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); - } - break; - case Altos.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - - case Altos.AO_LOG_CONFIG_VERSION: - break; - case Altos.AO_LOG_MAIN_DEPLOY: - break; - case Altos.AO_LOG_APOGEE_DELAY: - break; - case Altos.AO_LOG_RADIO_CHANNEL: - break; - case Altos.AO_LOG_CALLSIGN: - state.callsign = record.data; - break; - case Altos.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; - break; - case Altos.AO_LOG_RADIO_CAL: - break; - case Altos.AO_LOG_MANUFACTURER: - 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; - } - record = null; - } - } - - public void write_comments(PrintStream out) { - Iterator iterator = records.iterator(); - out.printf("# Comments\n"); - while (iterator.hasNext()) { - AltosOrderedRecord record = iterator.next(); - switch (record.cmd) { - case Altos.AO_LOG_CONFIG_VERSION: - out.printf("# Config version: %s\n", record.data); - break; - case Altos.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); - break; - case Altos.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); - break; - case Altos.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); - break; - case Altos.AO_LOG_CALLSIGN: - out.printf("# Callsign: %s\n", record.data); - break; - case Altos.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); - break; - case Altos.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); - break; - case Altos.AO_LOG_MANUFACTURER: - out.printf ("# Manufacturer: %s\n", record.data); - break; - case Altos.AO_LOG_PRODUCT: - out.printf ("# Product: %s\n", record.data); - break; - case Altos.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); - break; - case Altos.AO_LOG_SOFTWARE_VERSION: - out.printf ("# Software version: %s\n", record.data); - break; - } - } - } - - /* - * 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 - * are sometimes out of order with GPS data getting timestamps - * matching the first packet out of the GPS unit but not - * written until the final GPS packet has been received. - */ - public AltosEepromReader (FileInputStream input) { - state = new AltosRecord(); - state.state = Altos.ao_flight_pad; - state.accel_plus_g = 15758; - state.accel_minus_g = 16294; - seen = 0; - records = new TreeSet(); - - AltosOrderedRecord last_gps_time = null; - - int index = 0; - int tick = 0; - - boolean missing_time = false; - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) - break; - AltosOrderedRecord record = new AltosOrderedRecord(line, index++, tick); - if (record == null) - break; - if (record.cmd == Altos.AO_LOG_INVALID) - continue; - tick = record.tick; - if (record.cmd == Altos.AO_LOG_FLIGHT) { - state.ground_accel = record.a; - state.flight_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 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); - - /* Bail after reading the 'landed' record; we're all done */ - if (record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_landed) - break; - } - } catch (IOException io) { - } catch (ParseException pe) { - } - record_iterator = records.iterator(); - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java index 36b51de6..8b9d77d6 100644 --- a/ao-tools/altosui/AltosLogfileChooser.java +++ b/ao-tools/altosui/AltosLogfileChooser.java @@ -27,11 +27,6 @@ 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; @@ -45,7 +40,7 @@ public class AltosLogfileChooser extends JFileChooser { return file; } - public AltosReader runDialog() { + public AltosRecordIterable runDialog() { int ret; ret = showOpenDialog(frame); @@ -59,9 +54,9 @@ public class AltosLogfileChooser extends JFileChooser { in = new FileInputStream(file); if (filename.endsWith("eeprom")) - return new AltosEepromReader(in); + return new AltosEepromIterable(in); else - return new AltosTelemetryReader(in); + return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(frame, filename, diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java index 18c6079d..00484767 100644 --- a/ao-tools/altosui/AltosRecord.java +++ b/ao-tools/altosui/AltosRecord.java @@ -142,7 +142,7 @@ public class AltosRecord { return counts_per_g / 9.80665; } public double acceleration() { - return (accel_plus_g - accel) / accel_counts_per_mss(); + return (ground_accel - accel) / accel_counts_per_mss(); } public double accel_speed() { diff --git a/ao-tools/altosui/AltosRecordIterable.java b/ao-tools/altosui/AltosRecordIterable.java new file mode 100644 index 00000000..147ecc14 --- /dev/null +++ b/ao-tools/altosui/AltosRecordIterable.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.AltosRecord; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosEepromMonitor; + +public abstract class AltosRecordIterable implements Iterable { + public abstract Iterator iterator(); + public void write_comments(PrintStream out) { } +} diff --git a/ao-tools/altosui/AltosReplayThread.java b/ao-tools/altosui/AltosReplayThread.java new file mode 100644 index 00000000..b418160a --- /dev/null +++ b/ao-tools/altosui/AltosReplayThread.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Altos; +import altosui.AltosSerial; +import altosui.AltosSerialMonitor; +import altosui.AltosRecord; +import altosui.AltosTelemetry; +import altosui.AltosState; +import altosui.AltosDeviceDialog; +import altosui.AltosPreferences; +import altosui.AltosLog; +import altosui.AltosVoice; +import altosui.AltosFlightInfoTableModel; +import altosui.AltosChannelMenu; +import altosui.AltosFlashUI; +import altosui.AltosLogfileChooser; +import altosui.AltosCSVUI; +import altosui.AltosLine; +import altosui.AltosStatusTable; +import altosui.AltosInfoTable; +import altosui.AltosDisplayThread; + +/* + * Open an existing telemetry file and replay it in realtime + */ + +public class AltosReplayThread extends AltosDisplayThread { + Iterator iterator; + String name; + + public AltosRecord read() { + if (iterator.hasNext()) + return iterator.next(); + return null; + } + + public void close (boolean interrupted) { + if (!interrupted) + report(); + } + + void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > Altos.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + } + + public AltosReplayThread(Frame parent, Iterator in_iterator, + String in_name, AltosVoice voice, + AltosStatusTable status, AltosInfoTable info) { + super(parent, voice, status, info); + iterator = in_iterator; + name = in_name; + } +} diff --git a/ao-tools/altosui/AltosTelemetryIterable.java b/ao-tools/altosui/AltosTelemetryIterable.java new file mode 100644 index 00000000..0a125c98 --- /dev/null +++ b/ao-tools/altosui/AltosTelemetryIterable.java @@ -0,0 +1,83 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import altosui.AltosTelemetry; + +public class AltosTelemetryIterable extends AltosRecordIterable { + LinkedList records; + + public Iterator iterator () { + return records.iterator(); + } + + public AltosTelemetryIterable (FileInputStream input) { + boolean saw_boost = false; + int current_tick = 0; + int boost_tick = 0; + + records = new LinkedList (); + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) { + break; + } + try { + AltosTelemetry record = new AltosTelemetry(line); + if (record == null) + break; + if (records.isEmpty()) { + current_tick = record.tick; + } else { + int tick = record.tick | (current_tick & ~ 0xffff); + if (tick < current_tick - 0x1000) + tick += 0x10000; + current_tick = tick; + record.tick = current_tick; + } + 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) { + System.out.printf("io exception\n"); + } + + /* adjust all tick counts to be relative to boost time */ + for (AltosRecord r : this) + r.time = (r.tick - boost_tick) / 100.0; + + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java deleted file mode 100644 index 3564a0a5..00000000 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; -import altosui.AltosTelemetry; - -public class AltosTelemetryReader extends AltosReader { - LinkedList records; - - Iterator record_iterator; - - int boost_tick; - - public AltosRecord read() throws IOException, ParseException { - AltosRecord r; - if (!record_iterator.hasNext()) - return null; - - r = record_iterator.next(); - r.time = (r.tick - boost_tick) / 100.0; - return r; - } - - public AltosTelemetryReader (FileInputStream input) { - boolean saw_boost = false; - int current_tick = 0; - - records = new LinkedList (); - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) { - break; - } - try { - AltosTelemetry record = new AltosTelemetry(line); - if (record == null) - break; - if (records.isEmpty()) { - current_tick = record.tick; - } else { - int tick = record.tick | (current_tick & ~ 0xffff); - if (tick < current_tick - 0x1000) - tick += 0x10000; - current_tick = tick; - record.tick = current_tick; - } - 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) { - System.out.printf("io exception\n"); - } - record_iterator = records.iterator(); - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 1adeeccf..29eda2ec 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -46,6 +46,7 @@ import altosui.AltosCSVUI; import altosui.AltosLine; import altosui.AltosStatusTable; import altosui.AltosInfoTable; +import altosui.AltosDisplayThread; import libaltosJNI.*; @@ -119,222 +120,7 @@ public class AltosUI extends JFrame { voice.speak("Rocket flight monitor ready."); } - void show(AltosState state, int crc_errors) { - if (state != null) { - flightStatus.set(state); - flightInfo.show(state, crc_errors); - } - } - - class IdleThread extends Thread { - - boolean started; - private AltosState state; - int reported_landing; - int report_interval; - long report_time; - - public synchronized void report(boolean last) { - if (state == null) - return; - - /* reset the landing count once we hear about a new flight */ - if (state.state < Altos.ao_flight_drogue) - reported_landing = 0; - - /* Shut up once the rocket is on the ground */ - if (reported_landing > 2) { - return; - } - - /* If the rocket isn't on the pad, then report height */ - 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; - } - - /* If the rocket is coming down, check to see if it has landed; - * either we've got a landed report or we haven't heard from it in - * a long time - */ - if (state.state >= Altos.ao_flight_drogue && - (last || - System.currentTimeMillis() - state.report_time >= 15000 || - state.state == Altos.ao_flight_landed)) - { - if (Math.abs(state.baro_speed) < 20 && state.height < 100) - voice.speak("rocket landed safely"); - else - voice.speak("rocket may have crashed"); - if (state.from_pad != null) - 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 (;;) { - 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 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 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) { - voice.speak("GPS ready"); - ret = true; - } - else if (old_state != null) { - voice.speak("GPS lost"); - ret = true; - } - } - old_state = state; - return ret; - } - - class DisplayThread extends Thread { - IdleThread idle_thread; - - String name; - - int crc_errors; - - void init() { } - - 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(); - - flightInfo.clear(); - try { - for (;;) { - try { - AltosRecord record = read(); - if (record == null) - break; - old_state = state; - state = new AltosState(record, state); - update(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(interrupted); - idle_thread.interrupt(); - try { - idle_thread.join(); - } catch (InterruptedException ie) {} - } - } - - public void report() { - if (idle_thread != null) - idle_thread.report(true); - } - } - - class DeviceThread extends DisplayThread { + class DeviceThread extends AltosDisplayThread { AltosSerial serial; LinkedBlockingQueue telem; @@ -350,7 +136,8 @@ public class AltosUI extends JFrame { serial.remove_monitor(telem); } - public DeviceThread(AltosSerial s, String in_name) { + public DeviceThread(AltosSerial s, String in_name, AltosVoice voice, AltosStatusTable status, AltosInfoTable info) { + super(AltosUI.this, voice, status, info); serial = s; telem = new LinkedBlockingQueue(); serial.add_monitor(telem); @@ -366,7 +153,7 @@ public class AltosUI extends JFrame { try { stop_display(); serial_line.open(device); - DeviceThread thread = new DeviceThread(serial_line, device.getPath()); + DeviceThread thread = new DeviceThread(serial_line, device.getPath(), voice, flightStatus, flightInfo); serial_line.set_channel(AltosPreferences.channel()); serial_line.set_callsign(AltosPreferences.callsign()); run_display(thread); @@ -409,41 +196,6 @@ public class AltosUI extends JFrame { new AltosFlashUI(AltosUI.this); } - /* - * Open an existing telemetry file and replay it in realtime - */ - - class ReplayThread extends DisplayThread { - AltosReader reader; - String name; - - public AltosRecord read() { - try { - return reader.read(); - } catch (IOException ie) { - JOptionPane.showMessageDialog(AltosUI.this, - name, - "error reading", - JOptionPane.ERROR_MESSAGE); - } catch (ParseException pe) { - } - return null; - } - - public void close (boolean interrupted) { - if (!interrupted) - report(); - } - - public ReplayThread(AltosReader in_reader, String in_name) { - reader = in_reader; - } - void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > Altos.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - } - } Thread display_thread; @@ -469,10 +221,13 @@ public class AltosUI extends JFrame { private void Replay() { AltosLogfileChooser chooser = new AltosLogfileChooser( AltosUI.this); - AltosReader reader = chooser.runDialog(); - if (reader != null) - run_display(new ReplayThread(reader, - chooser.filename())); + AltosRecordIterable iterable = chooser.runDialog(); + if (iterable != null) + run_display(new AltosReplayThread(this, iterable.iterator(), + chooser.filename(), + voice, + flightStatus, + flightInfo)); } /* Connect to TeleMetrum, either directly or through @@ -663,16 +418,16 @@ public class AltosUI extends JFrame { return input.concat(extension); } - static AltosReader open_logfile(String filename) { + static AltosRecordIterable open_logfile(String filename) { File file = new File (filename); try { FileInputStream in; in = new FileInputStream(file); if (filename.endsWith("eeprom")) - return new AltosEepromReader(in); + return new AltosEepromIterable(in); else - return new AltosTelemetryReader(in); + return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { System.out.printf("Cannot open '%s'\n", filename); return null; @@ -696,14 +451,13 @@ public class AltosUI extends JFrame { return; } System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); - AltosReader reader = open_logfile(input); - if (reader == null) + AltosRecordIterable iterable = open_logfile(input); + if (iterable == null) return; AltosCSV writer = open_csv(output); if (writer == null) return; - writer.write(reader); - reader.close(); + writer.write(iterable); writer.close(); } diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 56ac0520..7070af22 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -20,9 +20,10 @@ altosui_JAVA = \ AltosDebug.java \ AltosDeviceDialog.java \ AltosDevice.java \ + AltosDisplayThread.java \ AltosEepromDownload.java \ AltosEepromMonitor.java \ - AltosEepromReader.java \ + AltosEepromIterable.java \ AltosEepromRecord.java \ AltosFile.java \ AltosFlash.java \ @@ -41,6 +42,8 @@ altosui_JAVA = \ AltosPreferences.java \ AltosReader.java \ AltosRecord.java \ + AltosRecordIterable.java \ + AltosReplayThread.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ AltosSerial.java \ @@ -48,7 +51,7 @@ altosui_JAVA = \ AltosState.java \ AltosStatusTable.java \ AltosTelemetry.java \ - AltosTelemetryReader.java \ + AltosTelemetryIterable.java \ AltosUI.java \ AltosVoice.java -- cgit v1.2.3 From fe7eba2e4af36cf29d8dc2378ac6985be04f68c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Sep 2010 18:51:05 -0700 Subject: altosui: .CSV output: add link quality, gps hdop and sat C/N0 numbers This makes the CSV files contain all of the available information. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSV.java | 46 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 7f14adad..c01d55a8 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -45,6 +45,7 @@ public class AltosCSV { * callsign * time (seconds since boost) * rssi + * link quality * * Flight status * state @@ -79,21 +80,22 @@ public class AltosCSV { * from_pad_azimuth (deg true) * from_pad_range (m) * from_pad_elevation (deg from horizon) + * hdop * * GPS Sat data - * hdop * C/N0 data for all 32 valid SDIDs */ void write_general_header() { - out.printf("version,serial,flight,call,time,rssi"); + out.printf("version,serial,flight,call,time,rssi,lqi"); } void write_general(AltosRecord record) { - out.printf("%s,%d,%d,%s,%8.2f,%4d", + out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d", record.version, record.serial, record.flight, record.callsign, (double) record.time, - record.rssi); + record.rssi, + record.status & 0x7f); } void write_flight_header() { @@ -123,7 +125,7 @@ public class AltosCSV { } 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"); + out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,hdop"); } void write_gps(AltosRecord record) { @@ -135,7 +137,7 @@ public class AltosCSV { 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", + out.printf("%2d,%2d,%3d,%12.7f,%12.7f,%6d,%5d,%3d,%3d,%3d,%3d,%3d,%9.0f,%9.0f,%4.0f,%4.0f,%6.1f", gps.connected?1:0, gps.locked?1:0, gps.nsat, @@ -151,7 +153,33 @@ public class AltosCSV { from_pad.distance, state.range, from_pad.bearing, - state.elevation); + state.elevation, + gps.hdop); + } + + void write_gps_sat_header() { + for(int i = 1; i <= 32; i++) { + out.printf("sat%02d", i); + if (i != 32) + out.printf(","); + } + } + + void write_gps_sat(AltosRecord record) { + AltosGPS gps = record.gps; + for(int i = 1; i <= 32; i++) { + int c_n0 = 0; + if (gps != null && gps.cc_gps_sat != null) { + for(int j = 0; j < gps.cc_gps_sat.length; j++) + if (gps.cc_gps_sat[j].svid == i) { + c_n0 = gps.cc_gps_sat[j].c_n0; + break; + } + } + out.printf ("%3d", c_n0); + if (i != 32) + out.printf(","); + } } void write_header() { @@ -159,6 +187,7 @@ public class AltosCSV { out.printf(","); write_flight_header(); out.printf(","); write_basic_header(); out.printf(","); write_gps_header(); + out.printf(","); write_gps_sat_header(); out.printf ("\n"); } @@ -167,7 +196,8 @@ public class AltosCSV { write_general(record); out.printf(","); write_flight(record); out.printf(","); write_basic(record); out.printf(","); - write_gps(record); + write_gps(record); out.printf(","); + write_gps_sat(record); out.printf ("\n"); } -- cgit v1.2.3 From 803203197e51e71e9c77b3610047fd5bf9a56c56 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Sep 2010 18:52:30 -0700 Subject: altosui: Deal with eeprom dates going backwards across wrap eeprom timestamps can go backwards as the GPS time stamps are recorded when the first GPS character is received, but not placed into the eeprom log until the last GPS packet is complete. If this happens at the same time the tick count is wrapping, then the tick count will wrap backwards across the 0 boundary causing time to jump forwards. Fix this by letting time go backwards across the tick boundary, which requires that we know when the first 'real' tick is read from the eeprom file. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromIterable.java | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java index d4ac3f3e..2f1e7e90 100644 --- a/ao-tools/altosui/AltosEepromIterable.java +++ b/ao-tools/altosui/AltosEepromIterable.java @@ -44,15 +44,19 @@ class AltosOrderedRecord extends AltosEepromRecord implements Comparable 0x8000) - new_tick += 0x10000; + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } } - tick = new_tick; index = in_index; } @@ -340,7 +344,7 @@ public class AltosEepromIterable extends AltosRecordIterable { int index = 0; int prev_tick = 0; - + boolean prev_tick_valid = false; boolean missing_time = false; try { @@ -348,12 +352,14 @@ public class AltosEepromIterable extends AltosRecordIterable { String line = AltosRecord.gets(input); if (line == null) break; - AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick); + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); if (record == null) break; if (record.cmd == Altos.AO_LOG_INVALID) continue; prev_tick = record.tick; + if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; if (record.cmd == Altos.AO_LOG_FLIGHT) { flight_record = record; continue; -- cgit v1.2.3 From ce7f59fbfb5a94a67a4ceced3cc371b4c6b6e5d1 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Tue, 28 Sep 2010 14:45:01 +1000 Subject: Hax0r graphing to support telem/eeprom files --- ao-tools/altosui/AltosCSV.java | 1 - ao-tools/altosui/AltosDataPointReader.java | 77 +++++++++++++++++++++++++++++ ao-tools/altosui/AltosGraphDataChooser.java | 20 ++++++-- ao-tools/altosui/Makefile.am | 5 +- 4 files changed, 95 insertions(+), 8 deletions(-) create mode 100644 ao-tools/altosui/AltosDataPointReader.java diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index c01d55a8..3a9e48f8 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -23,7 +23,6 @@ import java.text.*; import java.util.*; import altosui.AltosRecord; -import altosui.AltosReader; public class AltosCSV { File name; diff --git a/ao-tools/altosui/AltosDataPointReader.java b/ao-tools/altosui/AltosDataPointReader.java new file mode 100644 index 00000000..4d7831e4 --- /dev/null +++ b/ao-tools/altosui/AltosDataPointReader.java @@ -0,0 +1,77 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.IOException; +import java.text.ParseException; +import java.lang.UnsupportedOperationException; +import java.util.NoSuchElementException; +import java.util.Iterator; + +import altosui.AltosDataPoint; +import altosui.AltosRecordIterable; +import altosui.AltosRecord; +import altosui.AltosState; + +class AltosDataPointReader implements Iterable { + Iterator iter; + AltosState state; + AltosRecord record; + + public AltosDataPointReader(Iterable reader) { + this.iter = reader.iterator(); + this.state = null; + } + + private void read_next_record() + throws NoSuchElementException + { + record = iter.next(); + state = new AltosState(record, state); + } + + private AltosDataPoint current_dp() { + assert this.record != null; + + return new AltosDataPoint() { + public int version() { return record.version; } + public int serial() { return record.serial; } + public int flight() { return record.flight; } + public String callsign() { return record.callsign; } + public double time() { return record.time; } + public double rssi() { return record.rssi; } + + public int state() { return record.state; } + public String state_name() { return record.state(); } + + public double acceleration() { return record.acceleration(); } + public double pressure() { return record.raw_pressure(); } + public double altitude() { return record.raw_altitude(); } + public double height() { return record.raw_height(); } + public double accel_speed() { return record.accel_speed(); } + public double baro_speed() { return state.baro_speed; } + public double temperature() { return record.temperature(); } + public double battery_voltage() { return record.battery_voltage(); } + public double drogue_voltage() { return record.drogue_voltage(); } + public double main_voltage() { return record.main_voltage(); } + }; + } + + public Iterator iterator() { + return new Iterator() { + public void remove() { + throw new UnsupportedOperationException(); + } + public boolean hasNext() { + return iter.hasNext(); + } + public AltosDataPoint next() { + read_next_record(); + return current_dp(); + } + }; + } +} + diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java index 1bf28454..667d99f7 100644 --- a/ao-tools/altosui/AltosGraphDataChooser.java +++ b/ao-tools/altosui/AltosGraphDataChooser.java @@ -28,10 +28,10 @@ import java.text.*; import java.util.prefs.*; import altosui.AltosPreferences; -import altosui.AltosReader; import altosui.AltosCsvReader; -import altosui.AltosEepromReader; -import altosui.AltosTelemetryReader; +import altosui.AltosDataPointReader; +import altosui.AltosEepromIterable; +import altosui.AltosTelemetryIterable; public class AltosGraphDataChooser extends JFileChooser { JFrame frame; @@ -56,7 +56,17 @@ public class AltosGraphDataChooser extends JFileChooser { return null; filename = file.getName(); try { - return new AltosCsvReader(new FileReader(file)); + if (filename.endsWith("eeprom")) { + FileInputStream in = new FileInputStream(file); + return new AltosDataPointReader(new AltosEepromIterable(in)); + } else if (filename.endsWith("telem")) { + FileInputStream in = new FileInputStream(file); + return new AltosDataPointReader(new AltosTelemetryIterable(in)); + } else if (filename.endsWith("csv")) { + return new AltosCsvReader(new FileReader(file)); + } else { + throw new FileNotFoundException(); + } } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(frame, filename, @@ -71,7 +81,7 @@ public class AltosGraphDataChooser extends JFileChooser { frame = in_frame; setDialogTitle("Select Flight Record File"); setFileFilter(new FileNameExtensionFilter("Flight data file", - "csv")); + "csv", "telem", "eeprom")); setCurrentDirectory(AltosPreferences.logdir()); } } diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index ab8ca7d4..7510c88a 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -5,7 +5,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(JFREECHART)/*:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -53,6 +53,7 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ + AltosDataPointReader.java \ AltosCsvReader.java \ AltosDataPoint.java \ AltosGraph.java \ @@ -168,7 +169,7 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLA Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JFREECHAR)/jcommon.jar $(JFREECHART)/csv.jar" >> $@ + echo "Class-Path: $(FREETTS)/freetts.jar $(FREETTS)/jfreechart.jar $(FREETTS)/jcommon.jar $(FREETTS)/csv.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ -- cgit v1.2.3 From 28da3406426437604125d332e4cda90d459df487 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Sep 2010 22:26:56 -0700 Subject: altosui: use Altos constants in graphing code The Altos class nicely defines constants for all of the flight states. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosGraphUI.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java index 73f95023..d945c333 100644 --- a/ao-tools/altosui/AltosGraphUI.java +++ b/ao-tools/altosui/AltosGraphUI.java @@ -39,7 +39,7 @@ public class AltosGraphUI extends JFrame AltosGraphTime.Element speed = new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { public void gotTimeData(double time, AltosDataPoint d) { - if (d.state() < 4) { + if (d.state() < Altos.ao_flight_drogue) { series.add(time, d.accel_speed()); } else { series.add(time, d.baro_speed()); @@ -81,13 +81,13 @@ public class AltosGraphUI extends JFrame } }; - AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(2, "Pad"); - AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(3, "Boost"); - AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(4, "Fast"); - AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(5, "Coast"); - AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(6, "Drogue"); - AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(7, "Main"); - AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(8, "Landed"); + AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad"); + AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost"); + AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast"); + AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast"); + AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue"); + AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main"); + AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed"); protected AltosGraphTime myAltosGraphTime(String suffix) { return (new AltosGraphTime("Overall " + suffix)) @@ -130,7 +130,7 @@ public class AltosGraphUI extends JFrame return (new AltosGraphTime("Ascent " + suffix) { public void addData(AltosDataPoint d) { int state = d.state(); - if (3 <= state && state <= 5) { + if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) { super.addData(d); } } @@ -145,7 +145,7 @@ public class AltosGraphUI extends JFrame return (new AltosGraphTime("Descent " + suffix) { public void addData(AltosDataPoint d) { int state = d.state(); - if (6 <= state && state <= 7) { + if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) { super.addData(d); } } -- cgit v1.2.3 From 82744c3497d37650b88dee80be7956c4bd1cffb2 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Tue, 28 Sep 2010 15:27:07 +1000 Subject: Add callsign/serial/flight to graph title --- ao-tools/altosui/AltosGraphTime.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java index c0f99c59..ab01b888 100644 --- a/ao-tools/altosui/AltosGraphTime.java +++ b/ao-tools/altosui/AltosGraphTime.java @@ -131,6 +131,10 @@ class AltosGraphTime extends AltosGraph { } } + private String callsign = null; + private Integer serial = null; + private Integer flight = null; + private String title; private ArrayList elements; private HashMap axes; @@ -186,6 +190,9 @@ class AltosGraphTime extends AltosGraph { for (Element e : elements) { e.gotTimeData(time, d); } + if (callsign == null) callsign = d.callsign(); + if (serial == null) serial = new Integer(d.serial()); + if (flight == null) flight = new Integer(d.flight()); } public JFreeChart createChart() { @@ -197,6 +204,13 @@ class AltosGraphTime extends AltosGraph { plot.setRenderer(renderer); plot.setOrientation(PlotOrientation.VERTICAL); + if (serial != null && flight != null) { + title = serial + "/" + flight + ": " + title; + } + if (callsign != null) { + title = callsign + " - " + title; + } + renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, plot, true); -- cgit v1.2.3 From f0d1468ceae065f0cdae6f6ae3323dec5636f073 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Sep 2010 17:56:49 -0700 Subject: altosui: Add KML file export. Command line has switches now, --kml and --csv Export save dialog has combo box to select kml or csv result. Signed-off-by: Keith Packard --- ao-tools/altosui/Altos.java | 7 ++ ao-tools/altosui/AltosCSV.java | 10 +-- ao-tools/altosui/AltosCSVUI.java | 45 +++++++--- ao-tools/altosui/AltosKML.java | 169 ++++++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 73 +++++++++++----- ao-tools/altosui/AltosWriter.java | 32 ++++++++ ao-tools/altosui/Makefile.am | 25 ++++-- 7 files changed, 313 insertions(+), 48 deletions(-) create mode 100644 ao-tools/altosui/AltosKML.java create mode 100644 ao-tools/altosui/AltosWriter.java diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 07bd01ae..997550e0 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -200,4 +200,11 @@ public class Altos { } return v * sign; } + + static String replace_extension(String input, String extension) { + int dot = input.lastIndexOf("."); + if (dot > 0) + input = input.substring(0,dot); + return input.concat(extension); + } } diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java index 3a9e48f8..df98b2b4 100644 --- a/ao-tools/altosui/AltosCSV.java +++ b/ao-tools/altosui/AltosCSV.java @@ -22,9 +22,7 @@ import java.io.*; import java.text.*; import java.util.*; -import altosui.AltosRecord; - -public class AltosCSV { +public class AltosCSV implements AltosWriter { File name; PrintStream out; boolean header_written; @@ -33,9 +31,9 @@ public class AltosCSV { LinkedList pad_records; AltosState state; - static final int ALTOS_CSV_VERSION = 1; + static final int ALTOS_CSV_VERSION = 2; - /* Version 1 format: + /* Version 2 format: * * General info * version number @@ -91,7 +89,7 @@ public class AltosCSV { void write_general(AltosRecord record) { out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d", - record.version, record.serial, record.flight, record.callsign, + ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign, (double) record.time, record.rssi, record.status & 0x7f); diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java index 4eb72de8..eb620ba8 100644 --- a/ao-tools/altosui/AltosCSVUI.java +++ b/ao-tools/altosui/AltosCSVUI.java @@ -38,7 +38,25 @@ public class AltosCSVUI JFrame frame; Thread thread; AltosRecordIterable iterable; - AltosCSV writer; + AltosWriter writer; + JFileChooser csv_chooser; + JComboBox combo_box; + + static String[] combo_box_items = { "CSV", "KML" }; + + void set_default_file() { + File current = csv_chooser.getSelectedFile(); + String current_name = current.getName(); + String new_name = null; + String selected = (String) combo_box.getSelectedItem(); + + if (selected.equals("CSV")) + new_name = Altos.replace_extension(current_name, ".csv"); + else if (selected.equals("KML")) + new_name = Altos.replace_extension(current_name, ".kml"); + if (new_name != null) + csv_chooser.setSelectedFile(new File(new_name)); + } public void run() { AltosLogfileChooser chooser; @@ -47,20 +65,22 @@ public class AltosCSVUI iterable = chooser.runDialog(); if (iterable == 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); - csv_chooser.setSelectedFile(new File(path)); + csv_chooser = new JFileChooser(chooser.file()); + combo_box = new JComboBox(combo_box_items); + combo_box.addActionListener(this); + csv_chooser.setAccessory(combo_box); + csv_chooser.setSelectedFile(chooser.file()); + set_default_file(); int ret = csv_chooser.showSaveDialog(frame); if (ret == JFileChooser.APPROVE_OPTION) { + File file = csv_chooser.getSelectedFile(); + String type = (String) combo_box.getSelectedItem(); try { - writer = new AltosCSV(csv_chooser.getSelectedFile()); + if (type.equals("CSV")) + writer = new AltosCSV(file); + else + writer = new AltosKML(file); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, file.getName(), @@ -73,6 +93,9 @@ public class AltosCSVUI } public void actionPerformed(ActionEvent e) { + System.out.printf("command %s param %s\n", e.getActionCommand(), e.paramString()); + if (e.getActionCommand().equals("comboBoxChanged")) + set_default_file(); } public AltosCSVUI(JFrame in_frame) { diff --git a/ao-tools/altosui/AltosKML.java b/ao-tools/altosui/AltosKML.java new file mode 100644 index 00000000..d586033f --- /dev/null +++ b/ao-tools/altosui/AltosKML.java @@ -0,0 +1,169 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.*; + +public class AltosKML implements AltosWriter { + + File name; + PrintStream out; + int state = -1; + AltosRecord prev = null; + + static final String[] kml_state_colors = { + "FF000000", + "FF000000", + "FF000000", + "FF0000FF", + "FF4080FF", + "FF00FFFF", + "FFFF0000", + "FF00FF00", + "FF000000", + "FFFFFFFF" + }; + + static final String kml_header_start = + "\n" + + "\n" + + "\n" + + " AO Flight#%d S/N: %03d\n" + + " \n"; + static final String kml_header_end = + " \n" + + " 0\n"; + + static final String kml_style_start = + " \n"; + + static final String kml_placemark_start = + " \n" + + " %s\n" + + " #ao-flightstate-%s\n" + + " \n" + + " 1\n" + + " absolute\n" + + " \n"; + + static final String kml_coord_fmt = + " %12.7f, %12.7f, %12.7f \n"; + + static final String kml_placemark_end = + " \n" + + " \n" + + " \n"; + + static final String kml_footer = + "\n" + + "\n"; + + void start (AltosRecord record) { + out.printf(kml_header_start, record.flight, record.serial); + out.printf("Date: %04d-%02d-%02d\n", + record.gps.year, record.gps.month, record.gps.day); + out.printf("Time: %2d:%02d:%02d\n", + record.gps.hour, record.gps.minute, record.gps.second); + out.printf("%s", kml_header_end); + } + + boolean started = false; + + void state_start(AltosRecord record) { + String state_name = Altos.state_name(record.state); + out.printf(kml_style_start, state_name, kml_state_colors[record.state]); + out.printf("\tState: %s\n", state_name); + out.printf("%s", kml_style_end); + out.printf(kml_placemark_start, state_name, state_name); + } + + void state_end(AltosRecord record) { + out.printf("%s", kml_placemark_end); + } + + void coord(AltosRecord record) { + AltosGPS gps = record.gps; + out.printf(kml_coord_fmt, + gps.lon, gps.lat, + record.filtered_altitude(), (double) gps.alt, + record.time, gps.nsat); + } + + void end() { + out.printf("%s", kml_footer); + } + + public void close() { + if (prev != null) { + state_end(prev); + end(); + prev = null; + } + } + + public void write(AltosRecord record) { + AltosGPS gps = record.gps; + + if (gps == null) + return; + if (!started) { + start(record); + started = true; + } + if (prev != null && + prev.gps.second == record.gps.second && + prev.gps.minute == record.gps.minute && + prev.gps.hour == record.gps.hour) + return; + if (record.state != state) { + state = record.state; + if (prev != null) { + coord(record); + state_end(prev); + } + state_start(record); + } + coord(record); + prev = record; + } + + public void write(AltosRecordIterable iterable) { + for (AltosRecord record : iterable) + write(record); + } + + public AltosKML(File in_name) throws FileNotFoundException { + name = in_name; + out = new PrintStream(name); + } + + public AltosKML(String in_string) throws FileNotFoundException { + this(new File(in_string)); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index de0673a2..71481519 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -426,13 +426,6 @@ public class AltosUI extends JFrame { } - 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 AltosRecordIterable open_logfile(String filename) { File file = new File (filename); try { @@ -449,7 +442,7 @@ public class AltosUI extends JFrame { } } - static AltosCSV open_csv(String filename) { + static AltosWriter open_csv(String filename) { File file = new File (filename); try { return new AltosCSV(file); @@ -459,29 +452,65 @@ public class AltosUI extends JFrame { } } - 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; + static AltosWriter open_kml(String filename) { + File file = new File (filename); + try { + return new AltosKML(file); + } catch (FileNotFoundException fe) { + System.out.printf("Cannot open '%s'\n", filename); + return null; } - System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + } + + static final int process_csv = 1; + static final int process_kml = 2; + + static void process_file(String input, int process) { AltosRecordIterable iterable = open_logfile(input); if (iterable == null) return; - AltosCSV writer = open_csv(output); - if (writer == null) - return; - writer.write(iterable); - writer.close(); + if (process == 0) + process = process_csv; + if ((process & process_csv) != 0) { + String output = Altos.replace_extension(input,".csv"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_csv(output); + if (writer != null) { + writer.write(iterable); + writer.close(); + } + } + } + if ((process & process_kml) != 0) { + String output = Altos.replace_extension(input,".kml"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_kml(output); + if (writer == null) + return; + writer.write(iterable); + writer.close(); + } + } } public static void main(final String[] args) { - + int process = 0; /* Handle batch-mode */ if (args.length > 0) { - for (int i = 0; i < args.length; i++) - process_file(args[i]); + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--kml")) + process |= process_kml; + else if (args[i].equals("--csv")) + process |= process_csv; + else + process_file(args[i], process); + } } else { AltosUI altosui = new AltosUI(); altosui.setVisible(true); diff --git a/ao-tools/altosui/AltosWriter.java b/ao-tools/altosui/AltosWriter.java new file mode 100644 index 00000000..a172dff0 --- /dev/null +++ b/ao-tools/altosui/AltosWriter.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.*; + +public interface AltosWriter { + + public void write(AltosRecord record); + + public void write(AltosRecordIterable iterable); + + public void close(); +} diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 7510c88a..4e2a5027 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -35,6 +35,7 @@ altosui_JAVA = \ AltosHexfile.java \ Altos.java \ AltosInfoTable.java \ + AltosKML.java \ AltosLine.java \ AltosLogfileChooser.java \ AltosLog.java \ @@ -53,13 +54,14 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ - AltosDataPointReader.java \ - AltosCsvReader.java \ - AltosDataPoint.java \ - AltosGraph.java \ - AltosGraphTime.java \ - AltosGraphUI.java \ - AltosGraphDataChooser.java \ + AltosWriter.java \ + AltosDataPointReader.java \ + AltosCsvReader.java \ + AltosDataPoint.java \ + AltosGraph.java \ + AltosGraphTime.java \ + AltosGraphUI.java \ + AltosGraphDataChooser.java \ AltosVoice.java JFREECHART_CLASS= \ @@ -109,13 +111,13 @@ MACOSX_EXTRA=$(FIRMWARE) WINDOWS_FILES=$(FAT_FILES) altos.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) -all-local: classes/altosui $(JAR) altosui altosui-test +all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb clean-local: -rm -rf classes $(JAR) $(FATJAR) \ $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ $(JFREECHART_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ - altosui altosui-test macosx linux + altosui altosui-test altosui-jdb macosx linux if FATINSTALL @@ -185,6 +187,11 @@ altosui-test: Makefile echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ +altosui-jdb: Makefile + echo "#!/bin/sh" > $@ + echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ + chmod +x $@ + libaltos.so: -rm -f "$@" $(LN_S) ../libaltos/.libs/"$@" . -- cgit v1.2.3 From d8a2f4ceb1c70a6be976a78e2264c961de2f2277 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:18:45 -0600 Subject: add build dep on jfreechart lib --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 712e00d3..9f3fc532 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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, libtool +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, libtool, libjfreechart-java Standards-Version: 3.9.1 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 7475ab5804bf3fb12b1b755e850af90d5a15d3eb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:19:35 -0600 Subject: update changelogs for Debian build --- ChangeLog | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 43 ++++++++++ 2 files changed, 288 insertions(+) diff --git a/ChangeLog b/ChangeLog index d6cb54e2..d6edcc50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,227 @@ +commit d8a2f4ceb1c70a6be976a78e2264c961de2f2277 +Author: Bdale Garbee +Date: Wed Oct 6 16:18:45 2010 -0600 + + add build dep on jfreechart lib + +commit f0d1468ceae065f0cdae6f6ae3323dec5636f073 +Author: Keith Packard +Date: Tue Sep 28 17:56:49 2010 -0700 + + altosui: Add KML file export. + + Command line has switches now, --kml and --csv + Export save dialog has combo box to select kml or csv result. + + Signed-off-by: Keith Packard + +commit 5a119fd92532d53e552efe1f7c61e87181fcace0 +Merge: 28da340 82744c3 +Author: Keith Packard +Date: Mon Sep 27 22:28:07 2010 -0700 + + Merge remote branch 'aj/master' + +commit 82744c3497d37650b88dee80be7956c4bd1cffb2 +Author: Anthony Towns +Date: Tue Sep 28 15:27:07 2010 +1000 + + Add callsign/serial/flight to graph title + +commit 28da3406426437604125d332e4cda90d459df487 +Author: Keith Packard +Date: Mon Sep 27 22:26:56 2010 -0700 + + altosui: use Altos constants in graphing code + + The Altos class nicely defines constants for all of the flight states. + + Signed-off-by: Keith Packard + +commit ce7f59fbfb5a94a67a4ceced3cc371b4c6b6e5d1 +Author: Anthony Towns +Date: Tue Sep 28 14:45:01 2010 +1000 + + Hax0r graphing to support telem/eeprom files + +commit e2b9f47a205348d38756c70e928a2a9183de6884 +Merge: 7ef3ad0 8032031 +Author: Anthony Towns +Date: Tue Sep 28 12:55:47 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + +commit 803203197e51e71e9c77b3610047fd5bf9a56c56 +Author: Keith Packard +Date: Mon Sep 27 18:52:30 2010 -0700 + + altosui: Deal with eeprom dates going backwards across wrap + + eeprom timestamps can go backwards as the GPS time stamps are + recorded when the first GPS character is received, but not placed into + the eeprom log until the last GPS packet is complete. If this happens + at the same time the tick count is wrapping, then the tick count will + wrap backwards across the 0 boundary causing time to jump forwards. + + Fix this by letting time go backwards across the tick boundary, which + requires that we know when the first 'real' tick is read from the + eeprom file. + + Signed-off-by: Keith Packard + +commit fe7eba2e4af36cf29d8dc2378ac6985be04f68c6 +Author: Keith Packard +Date: Mon Sep 27 18:51:05 2010 -0700 + + altosui: .CSV output: add link quality, gps hdop and sat C/N0 numbers + + This makes the CSV files contain all of the available information. + + Signed-off-by: Keith Packard + +commit c89a34d1eb25155405b0036baeadc7bbfeade1c2 +Author: Keith Packard +Date: Mon Sep 27 17:11:48 2010 -0700 + + altosui: Create iterables for log file scanning. Split out display threads + + Convert from log file reading paradigm to using iterators which is + more idiomatic for java. Split more code out of AltosUI.java, + including the display update threads for telemetry monitoring and + logfile replay.x + + Signed-off-by: Keith Packard + +commit 7ef3ad0c9354c0484c25badc69334b59c7f355e2 +Merge: eb74866 e66919a +Author: Anthony Towns +Date: Fri Sep 24 10:28:06 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + +commit e66919aa46193bd8c7a1e86fb32a3367dae121f5 +Author: Keith Packard +Date: Thu Sep 23 16:52:51 2010 -0700 + + altosui: Require 4 sats for 'good' GPS data + + Wait for 10 consecutive GPS reports with at least 4 sats before + reporting "GPS ready" state. + + Signed-off-by: Keith Packard + +commit 34ca8c00f4be72c314baff4c96f1e2f010948454 +Author: Keith Packard +Date: Mon Sep 20 06:30:49 2010 -0700 + + altosui: remove unused ReplayThread wrapper classes + + These aren't used now that the replay opener dialog knows how to build + a reader from a filename. + + Signed-off-by: Keith Packard + +commit fd010661ced6075f82a961625826665a3d8d1efe +Author: Keith Packard +Date: Mon Aug 30 14:00:04 2010 -0700 + + altosui: Factor some UI elements into separate classes + + Clean up AltosUI by moving the two main tables to separate class files. + + Signed-off-by: Keith Packard + +commit eb74866e919e8c661153847871f5a79e66d37296 +Merge: af404b4 1260589 +Author: Anthony Towns +Date: Mon Sep 20 22:05:26 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + +commit 1260589976c1a95848b298497fd251c4ee7d3f93 +Author: Keith Packard +Date: Sun Sep 19 02:52:29 2010 -0700 + + altosui: Write raw sensor data to .csv files + + For data export, provide the raw sensor samples instead of the + filtered values. + + Signed-off-by: Keith Packard + +commit 7a4d7110debb88f4e906fee7c46f2badd561809d +Author: Keith Packard +Date: Sun Sep 19 02:50:43 2010 -0700 + + altosui: Use recorded ground acceleration when reading eeprom files + + The flight software records 1000 accelerometer samples and records + that in the flight log. Use that value instead of using the very few + samples recorded in the eeprom before boost is detected. This + generates far more accurate accerometer data in the .csv files. + + Signed-off-by: Keith Packard + +commit af404b428bd742039afc25ff3850f76bc92c7c29 +Author: Anthony Towns +Date: Wed Sep 15 07:24:04 2010 +1000 + + Add JFreeChart to Makefile.am + +commit 61590b8729831cb138b2ba6b88802c208d114753 +Author: Anthony Towns +Date: Wed Sep 15 06:51:05 2010 +1000 + + Add graphing. + +commit 3d64f5a6511529ca53699190f4d54de1ba62a9bd +Merge: ec6da08 b9623f8 +Author: Anthony Towns +Date: Sat Sep 11 15:15:14 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + +commit b9623f8ef26491e9fa14e2478295fe6f5cbbd87f +Author: Keith Packard +Date: Fri Sep 10 21:07:14 2010 -0700 + + altosui: Remember directory containing firmware files + + Instead of forcing the user to navigate to the firmware directory each + time, this remembers the previous directory and starts there. + + Signed-off-by: Keith Packard + +commit 7f2204e0832b14b1edca4266a2cbc272141ecc2b +Author: Keith Packard +Date: Fri Sep 10 20:55:05 2010 -0700 + + altosui: set default .csv file name in file save dialog + + This uses setSelectedFile to specify which output filename to make the + default in the save dialog. + + Signed-off-by: Keith Packard + +commit 7e053ae1f2d09347123ac9fa79e46645378b4c70 +Author: Bdale Garbee +Date: Fri Sep 10 10:42:35 2010 -0600 + + make the column headers comma separated, too, so they align with the data + +commit ec6da0824474e46de842845d7b53fe1a1dde33ed +Merge: 7c2e411 1031067 +Author: Anthony Towns +Date: Fri Sep 10 16:11:34 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + +commit 10310672a83a66dc630718b151d653fc066f8e59 +Author: Bdale Garbee +Date: Fri Sep 10 00:09:25 2010 -0600 + + update changelogs for Debian build + commit 9d0e89e8ad8926dc8371fa809835a580ae49711d Author: Keith Packard Date: Thu Sep 9 23:04:59 2010 -0700 @@ -48,6 +272,13 @@ Date: Thu Sep 9 23:51:23 2010 -0600 rewind packaging changelog +commit 7c2e4114a3a43f919a7a6c967d3f16e5d630f90f +Merge: ddc83b4 af200f5 +Author: Anthony Towns +Date: Fri Sep 10 15:50:01 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + commit af200f5b84555de0556b52146379f3934774a3f3 Author: Keith Packard Date: Thu Sep 9 22:30:48 2010 -0700 @@ -259,6 +490,13 @@ Date: Thu Sep 9 15:43:47 2010 -0600 update changelogs for Debian build +commit ddc83b4c401be965a9947782becf20cc8c54e6a2 +Merge: afea6c2 3d49d5f +Author: Anthony Towns +Date: Sun Sep 5 20:49:34 2010 +1000 + + Merge branch 'master' of git://git.gag.com/fw/altos + commit 3d49d5f69b41c27003dbc5ccf1899014bd13bd99 Author: Keith Packard Date: Sun Sep 5 02:05:06 2010 -0700 @@ -1377,6 +1615,13 @@ Date: Mon Aug 23 23:15:05 2010 -0700 Signed-off-by: Keith Packard +commit afea6c264c5ebf12f1d629bd4bc724da86d11b7a +Merge: 0e17853 9d1b27f +Author: Anthony Towns +Date: Tue Aug 24 00:02:31 2010 -0600 + + Merge branch 'master' of git://git.gag.com/fw/altos + commit a55b132668a819cc26478a609cb79bd9190deb9d Author: Keith Packard Date: Mon Aug 23 23:01:36 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 98068ad7..87de6dd8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,46 @@ +altos (0.7.1+28+gd8a2f4c) unstable; urgency=low + + [ Bdale Garbee ] + * make the column headers comma separated, too, so they align with the + data + + [ Keith Packard ] + * altosui: set default .csv file name in file save dialog + * altosui: Remember directory containing firmware files + + [ Anthony Towns ] + * Add graphing. + * Add JFreeChart to Makefile.am + + [ Keith Packard ] + * altosui: Use recorded ground acceleration when reading eeprom files + * altosui: Write raw sensor data to .csv files + * altosui: Factor some UI elements into separate classes + * altosui: remove unused ReplayThread wrapper classes + * altosui: Require 4 sats for 'good' GPS data + * altosui: Create iterables for log file scanning. Split out display + threads + * altosui: .CSV output: add link quality, gps hdop and sat C/N0 + numbers + * altosui: Deal with eeprom dates going backwards across wrap + + [ Anthony Towns ] + * Hax0r graphing to support telem/eeprom files + + [ Keith Packard ] + * altosui: use Altos constants in graphing code + + [ Anthony Towns ] + * Add callsign/serial/flight to graph title + + [ Keith Packard ] + * altosui: Add KML file export. + + [ Bdale Garbee ] + * add build dep on jfreechart lib + + -- Bdale Garbee Wed, 06 Oct 2010 16:19:12 -0600 + altos (0.7.1) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 4396aaaf34cda3751dcca0eceb05b4ffeb411cde Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:25:22 -0600 Subject: add build-dep on libcsv-java --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 9f3fc532..f0288077 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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, libtool, libjfreechart-java +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, libtool, libjfreechart-java, libcsv-java Standards-Version: 3.9.1 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 635066cd35fb24cacf8400a477ea4b4e3dd2c39c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:26:19 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index d6edcc50..ebc6d807 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 4396aaaf34cda3751dcca0eceb05b4ffeb411cde +Author: Bdale Garbee +Date: Wed Oct 6 16:25:22 2010 -0600 + + add build-dep on libcsv-java + +commit 7475ab5804bf3fb12b1b755e850af90d5a15d3eb +Author: Bdale Garbee +Date: Wed Oct 6 16:19:35 2010 -0600 + + update changelogs for Debian build + commit d8a2f4ceb1c70a6be976a78e2264c961de2f2277 Author: Bdale Garbee Date: Wed Oct 6 16:18:45 2010 -0600 diff --git a/debian/changelog b/debian/changelog index 87de6dd8..b9788b58 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.7.1+30+g4396aaa) unstable; urgency=low + + * add build-dep on libcsv-java + + -- Bdale Garbee Wed, 06 Oct 2010 16:25:57 -0600 + altos (0.7.1+28+gd8a2f4c) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 8103432bf7adfe6ee5bf3ee42e1672475e6edd5a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:26:33 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index ebc6d807..c6f9ee48 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 635066cd35fb24cacf8400a477ea4b4e3dd2c39c +Author: Bdale Garbee +Date: Wed Oct 6 16:26:19 2010 -0600 + + update changelogs for Debian build + commit 4396aaaf34cda3751dcca0eceb05b4ffeb411cde Author: Bdale Garbee Date: Wed Oct 6 16:25:22 2010 -0600 diff --git a/debian/changelog b/debian/changelog index b9788b58..a7a66a67 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7.1+30+g4396aaa) unstable; urgency=low +altos (0.7.1+31+g635066c) unstable; urgency=low * add build-dep on libcsv-java -- cgit v1.2.3 From 43e23a60780191e3c6f61df44c5dd08cc8604c51 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 16:27:57 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index c6f9ee48..3cbfd130 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 8103432bf7adfe6ee5bf3ee42e1672475e6edd5a +Author: Bdale Garbee +Date: Wed Oct 6 16:26:33 2010 -0600 + + update changelogs for Debian build + commit 635066cd35fb24cacf8400a477ea4b4e3dd2c39c Author: Bdale Garbee Date: Wed Oct 6 16:26:19 2010 -0600 diff --git a/debian/changelog b/debian/changelog index a7a66a67..beeee17e 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.7.1+31+g635066c) unstable; urgency=low +altos (0.7.1+32+g8103432) unstable; urgency=low * add build-dep on libcsv-java -- cgit v1.2.3 From d5caf6f2f4d9257e26aa4305b26c02d1b263fa24 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 17:14:35 -0600 Subject: remove the csv build dep, as that code will be abandoned --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index f0288077..9f3fc532 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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, libtool, libjfreechart-java, libcsv-java +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, libtool, libjfreechart-java Standards-Version: 3.9.1 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From c2c4d515ef9cc2cae8a8f2803e9498bb0794c4ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Oct 2010 16:25:49 -0700 Subject: altosui: Remove ability to graph data in .csv files There's no reason to support these files when the raw .eeprom or .telem files which generate them should be used instead. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCsvReader.java | 113 ---------------------------- ao-tools/altosui/AltosGraphDataChooser.java | 5 +- ao-tools/altosui/AltosGraphUI.java | 21 ------ ao-tools/altosui/AltosUI.java | 4 - ao-tools/altosui/Makefile.am | 1 - 5 files changed, 1 insertion(+), 143 deletions(-) delete mode 100644 ao-tools/altosui/AltosCsvReader.java diff --git a/ao-tools/altosui/AltosCsvReader.java b/ao-tools/altosui/AltosCsvReader.java deleted file mode 100644 index 600788f4..00000000 --- a/ao-tools/altosui/AltosCsvReader.java +++ /dev/null @@ -1,113 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -import java.lang.UnsupportedOperationException; -import java.util.HashMap; -import java.util.NoSuchElementException; -import java.util.Iterator; -import java.io.*; -import com.csvreader.CsvReader; - -import altosui.AltosDataPoint; - -class AltosCsvReader implements Iterable -{ - public CsvReader csv; - public AltosDataPoint next = null; - - static protected String [] headers = "version serial flight call time rssi state state_name acceleration pressure altitude height accel_speed baro_speed temperature battery_voltage drogue_voltage main_voltage connected locked nsat latitude longitude altitude year month day hour minute second pad_dist pad_range pad_az pad_el".split(" "); - - AltosCsvReader(Reader stream) { - csv = new CsvReader(stream); - csv.setComment('#'); - csv.setUseComments(true); - csv.setHeaders(headers); - } - AltosCsvReader(String filename) throws FileNotFoundException { - csv = new CsvReader(filename); - csv.setComment('#'); - csv.setUseComments(true); - csv.setHeaders(headers); - } - - public Iterator iterator() { - return new Iterator() { - public void remove() { - throw new UnsupportedOperationException(); - } - public boolean hasNext() { - if (next == null) { - try { - if (csv.readRecord()) { - next = new CsvRow(); - } else { - close(); - return false; - } - } catch (IOException e) { - close(); - return false; - } - } - return true; - } - public AltosDataPoint next() { - if (!hasNext()) - throw new NoSuchElementException(); - AltosDataPoint res = next; - next = null; - return res; - } - }; - } - - public void close() { - csv.close(); - } - - private class CsvRow extends HashMap - implements AltosDataPoint - { - CsvRow() throws IOException { - for (int i = 0; i < headers.length; i++) { - this.put(headers[i], csv.get(headers[i]).trim()); - } - } - - private int intField(String name) { - return Integer.parseInt(get(name).trim()); - } - private double doubleField(String name) { - return Double.valueOf(get(name)).doubleValue(); - } - private String stringField(String name) { - return get(name); - } - - public int version() { return intField("version"); } - public int serial() { return intField("serial"); } - public int flight() { return intField("flight"); } - public String callsign() { return stringField("call"); } - public double time() { return doubleField("time"); } - public double rssi() { return doubleField("rssi"); } - - public int state() { return intField("state"); } - public String state_name() { return stringField("state_name"); } - - public double acceleration() { return doubleField("acceleration"); } - public double pressure() { return doubleField("pressure"); } - public double altitude() { return doubleField("altitude"); } - public double height() { return doubleField("height"); } - public double accel_speed() { return doubleField("accel_speed"); } - public double baro_speed() { return doubleField("baro_speed"); } - public double temperature() { return doubleField("temperature"); } - public double battery_voltage() { - return doubleField("battery_voltage"); - } - public double drogue_voltage() { return doubleField("drogue_voltage"); } - public double main_voltage() { return doubleField("main_voltage"); } - } -} diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java index 667d99f7..caa14118 100644 --- a/ao-tools/altosui/AltosGraphDataChooser.java +++ b/ao-tools/altosui/AltosGraphDataChooser.java @@ -28,7 +28,6 @@ import java.text.*; import java.util.prefs.*; import altosui.AltosPreferences; -import altosui.AltosCsvReader; import altosui.AltosDataPointReader; import altosui.AltosEepromIterable; import altosui.AltosTelemetryIterable; @@ -62,8 +61,6 @@ public class AltosGraphDataChooser extends JFileChooser { } else if (filename.endsWith("telem")) { FileInputStream in = new FileInputStream(file); return new AltosDataPointReader(new AltosTelemetryIterable(in)); - } else if (filename.endsWith("csv")) { - return new AltosCsvReader(new FileReader(file)); } else { throw new FileNotFoundException(); } @@ -81,7 +78,7 @@ public class AltosGraphDataChooser extends JFileChooser { frame = in_frame; setDialogTitle("Select Flight Record File"); setFileFilter(new FileNameExtensionFilter("Flight data file", - "csv", "telem", "eeprom")); + "telem", "eeprom")); setCurrentDirectory(AltosPreferences.logdir()); } } diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java index d945c333..25643c76 100644 --- a/ao-tools/altosui/AltosGraphUI.java +++ b/ao-tools/altosui/AltosGraphUI.java @@ -17,7 +17,6 @@ import org.jfree.chart.axis.AxisLocation; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RefineryUtilities; -import altosui.AltosCsvReader; import altosui.AltosDataPoint; import altosui.AltosGraphTime; @@ -228,26 +227,6 @@ public class AltosGraphUI extends JFrame return graph; } - - public static void main(String[] args) - throws java.io.FileNotFoundException, java.io.IOException - { - if (args.length < 1 || 2 < args.length) - { - System.out.println("Please specify telemetry csv"); - return; - } - - AltosCsvReader csv = new AltosCsvReader(args[0]); - if (args.length == 1) { - for (AltosGraph g : createGraphs(csv)) { - g.toPNG(); - } - } else { - int which = Integer.parseInt(args[1].trim()); - AltosGraphUI demo = new AltosGraphUI(csv, which); - } - } } /* gnuplot bits... diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 71481519..28ed42fb 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -59,10 +59,6 @@ public class AltosUI extends JFrame { private AltosLog altos_log; private Box vbox; - private Font statusFont = new Font("SansSerif", Font.BOLD, 24); - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); - public AltosVoice voice = new AltosVoice(); public static boolean load_library(Frame frame) { diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 4e2a5027..58c1517f 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -56,7 +56,6 @@ altosui_JAVA = \ AltosUI.java \ AltosWriter.java \ AltosDataPointReader.java \ - AltosCsvReader.java \ AltosDataPoint.java \ AltosGraph.java \ AltosGraphTime.java \ -- cgit v1.2.3 From 811ced628d586134224c1b501b40ce9eb435fc7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Oct 2010 16:42:27 -0700 Subject: altosui: Separate out jfreechart and jcommon directories This allows these packages to be referenced separately Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 32 +++++++++++++++++++++----------- configure.ac | 12 ++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 58c1517f..2f4ed6d8 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -64,9 +64,10 @@ altosui_JAVA = \ AltosVoice.java JFREECHART_CLASS= \ - jfreechart.jar \ - jcommon.jar \ - csv.jar + jfreechart.jar + +JCOMMON_CLASS=\ + jcommon.jar FREETTS_CLASS= \ cmudict04.jar \ @@ -100,7 +101,7 @@ 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) $(JFREECHART_CLASS) +FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) LINUX_EXTRA=altosui-fat @@ -115,7 +116,7 @@ all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb clean-local: -rm -rf classes $(JAR) $(FATJAR) \ $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ - $(JFREECHART_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ + $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test altosui-jdb macosx linux if FATINSTALL @@ -162,7 +163,7 @@ $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) -C classes altosui \ -C ../libaltos libaltosJNI -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(LIBALTOS) $(JAVA_ICON) +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) jar cfm $@ Manifest-fat.txt \ -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ -C classes altosui \ @@ -170,25 +171,25 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLA Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar $(FREETTS)/jfreechart.jar $(FREETTS)/jcommon.jar $(FREETTS)/csv.jar" >> $@ + echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar csv.jar" >> $@ + echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ + echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ chmod +x $@ altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ altosui-jdb: Makefile echo "#!/bin/sh" > $@ - echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/*" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ + echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ chmod +x $@ libaltos.so: @@ -207,6 +208,14 @@ $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . +$(JFREECHART_CLASS): + -rm -f "$@" + $(LN_S) "$(JFREECHART)"/"$@" . + +$(JCOMMON_CLASS): + -rm -f "$@" + $(LN_S) "$(JCOMMON)"/"$@" . + $(LINUX_DIST): $(LINUX_FILES) $(LINUX_EXTRA) -rm -f $@ -rm -rf linux @@ -224,6 +233,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) 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 $(JFREECHART_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java cp -p $(MACOSX_EXTRA) macosx/AltOS cd macosx && zip -r ../$@ AltosUI.app AltOS diff --git a/configure.ac b/configure.ac index 4bf8f7fe..903c5765 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,18 @@ AC_ARG_WITH(freetts, AS_HELP_STRING([--with-freetts=PATH], AC_SUBST(FREETTS) +AC_ARG_WITH(jfreechart, AS_HELP_STRING([--with-jfreechart=PATH], + [Set jfreechart class path (default /usr/share/java)]), + [JFREECHART=$withval], [JFREECHART=/usr/share/java]) + +AC_SUBST(JFREECHART) + +AC_ARG_WITH(jcommon, AS_HELP_STRING([--with-jcommon=PATH], + [Set jcommon class path (default /usr/share/java)]), + [JCOMMON=$withval], [JCOMMON=/usr/share/java]) + +AC_SUBST(JCOMMON) + 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]) -- cgit v1.2.3 From ca931b1c484bd6b64617370e81b16e169fdae1c2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 6 Oct 2010 17:47:44 -0600 Subject: update changelogs for Debian build --- ChangeLog | 33 +++++++++++++++++++++++++++++++++ debian/changelog | 11 +++++++++++ 2 files changed, 44 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3cbfd130..c248fe08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +commit 811ced628d586134224c1b501b40ce9eb435fc7c +Author: Keith Packard +Date: Wed Oct 6 16:42:27 2010 -0700 + + altosui: Separate out jfreechart and jcommon directories + + This allows these packages to be referenced separately + + Signed-off-by: Keith Packard + +commit c2c4d515ef9cc2cae8a8f2803e9498bb0794c4ed +Author: Keith Packard +Date: Wed Oct 6 16:25:49 2010 -0700 + + altosui: Remove ability to graph data in .csv files + + There's no reason to support these files when the raw .eeprom or + .telem files which generate them should be used instead. + + Signed-off-by: Keith Packard + +commit d5caf6f2f4d9257e26aa4305b26c02d1b263fa24 +Author: Bdale Garbee +Date: Wed Oct 6 17:14:35 2010 -0600 + + remove the csv build dep, as that code will be abandoned + +commit 43e23a60780191e3c6f61df44c5dd08cc8604c51 +Author: Bdale Garbee +Date: Wed Oct 6 16:27:57 2010 -0600 + + update changelogs for Debian build + commit 8103432bf7adfe6ee5bf3ee42e1672475e6edd5a Author: Bdale Garbee Date: Wed Oct 6 16:26:33 2010 -0600 diff --git a/debian/changelog b/debian/changelog index beeee17e..604f7dc7 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,14 @@ +altos (0.7.1+36+g811ced6) unstable; urgency=low + + [ Bdale Garbee ] + * remove the csv build dep, as that code will be abandoned + + [ Keith Packard ] + * altosui: Remove ability to graph data in .csv files + * altosui: Separate out jfreechart and jcommon directories + + -- Bdale Garbee Wed, 06 Oct 2010 17:47:32 -0600 + altos (0.7.1+32+g8103432) unstable; urgency=low * add build-dep on libcsv-java -- cgit v1.2.3 From 16916be51d746b1e1057b3219e5bec8f8814259e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 5 Nov 2010 23:44:47 -0700 Subject: altosui: Split out flight monitoring to separate window This creates a per-TD (or replay) window to contain the flight monitoring information, allowing multiple monitors. This also adds per-TD preferences for monitoring channel. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDisplayThread.java | 40 +++---- ao-tools/altosui/AltosFlightReader.java | 38 +++++++ ao-tools/altosui/AltosFlightUI.java | 128 +++++++++++++++++++++ ao-tools/altosui/AltosLog.java | 17 +-- ao-tools/altosui/AltosPreferences.java | 20 ++-- ao-tools/altosui/AltosReplayReader.java | 57 ++++++++++ ao-tools/altosui/AltosReplayThread.java | 83 -------------- ao-tools/altosui/AltosSerial.java | 2 + ao-tools/altosui/AltosStatusTable.java | 5 +- ao-tools/altosui/AltosTelemetryReader.java | 62 +++++++++++ ao-tools/altosui/AltosUI.java | 171 +++++++---------------------- ao-tools/altosui/Makefile.am | 5 +- 12 files changed, 366 insertions(+), 262 deletions(-) create mode 100644 ao-tools/altosui/AltosFlightReader.java create mode 100644 ao-tools/altosui/AltosFlightUI.java create mode 100644 ao-tools/altosui/AltosReplayReader.java delete mode 100644 ao-tools/altosui/AltosReplayThread.java create mode 100644 ao-tools/altosui/AltosTelemetryReader.java diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java index 9cc3d5ce..b15472ed 100644 --- a/ao-tools/altosui/AltosDisplayThread.java +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -30,13 +30,14 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosDisplayThread extends Thread { - Frame parent; - IdleThread idle_thread; - AltosVoice voice; - String name; - int crc_errors; - AltosStatusTable flightStatus; - AltosInfoTable flightInfo; + Frame parent; + IdleThread idle_thread; + AltosVoice voice; + String name; + AltosFlightReader reader; + int crc_errors; + AltosStatusTable flightStatus; + AltosInfoTable flightInfo; class IdleThread extends Thread { @@ -150,14 +151,6 @@ public class AltosDisplayThread extends Thread { } } - void init() { } - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } - - void close(boolean interrupted) { } - - void update(AltosState state) throws InterruptedException { } - boolean tell(AltosState state, AltosState old_state) { boolean ret = false; if (old_state == null || old_state.state != state.state) { @@ -208,12 +201,12 @@ public class AltosDisplayThread extends Thread { try { for (;;) { try { - AltosRecord record = read(); + AltosRecord record = reader.read(); if (record == null) break; old_state = state; state = new AltosState(record, state); - update(state); + reader.update(state); show(state, crc_errors); told = tell(state, old_state); idle_thread.notice(state, told); @@ -232,7 +225,9 @@ public class AltosDisplayThread extends Thread { "Telemetry Read Error", JOptionPane.ERROR_MESSAGE); } finally { - close(interrupted); + if (!interrupted) + idle_thread.report(true); + reader.close(interrupted); idle_thread.interrupt(); try { idle_thread.join(); @@ -240,16 +235,11 @@ public class AltosDisplayThread extends Thread { } } - public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info) { + public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info, AltosFlightReader in_reader) { parent = in_parent; voice = in_voice; flightStatus = in_status; flightInfo = in_info; + reader = in_reader; } - - public void report() { - if (idle_thread != null) - idle_thread.report(true); - } - } diff --git a/ao-tools/altosui/AltosFlightReader.java b/ao-tools/altosui/AltosFlightReader.java new file mode 100644 index 00000000..3d59de9a --- /dev/null +++ b/ao-tools/altosui/AltosFlightReader.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; + +public class AltosFlightReader { + String name; + + int serial; + + void init() { } + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + + void close(boolean interrupted) { } + + void set_channel(int channel) { } + + void update(AltosState state) throws InterruptedException { } +} diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java new file mode 100644 index 00000000..84ba9dca --- /dev/null +++ b/ao-tools/altosui/AltosFlightUI.java @@ -0,0 +1,128 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightUI extends JFrame { + String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + Object[][] statusData = { { "0", "pad", "-50", "0" } }; + + AltosVoice voice; + AltosFlightReader reader; + AltosDisplayThread thread; + + private Box vbox; + private AltosStatusTable flightStatus; + private AltosInfoTable flightInfo; + + public int width() { + return flightInfo.width(); + } + + public int height() { + return flightStatus.height() + flightInfo.height(); + } + + void stop_display() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + } + + void disconnect() { + stop_display(); + } + + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { + voice = in_voice; + reader = in_reader; + + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); + if (imgURL != null) + setIconImage(new ImageIcon(imgURL).getImage()); + + setTitle(String.format("AltOS %s", reader.name)); + + flightStatus = new AltosStatusTable(); + + vbox = new Box (BoxLayout.Y_AXIS); + vbox.add(flightStatus); + + flightInfo = new AltosInfoTable(); + vbox.add(flightInfo.box()); + + this.add(vbox); + + if (serial >= 0) { + JMenuBar menubar = new JMenuBar(); + + // Channel menu + { + JMenu menu = new AltosChannelMenu(AltosPreferences.channel(serial)); + menu.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int channel = Integer.parseInt(e.getActionCommand()); + reader.set_channel(channel); + AltosPreferences.set_channel(serial, channel); + } + }); + menu.setMnemonic(KeyEvent.VK_C); + menubar.add(menu); + } + + this.setJMenuBar(menubar); + } + + this.setSize(new Dimension (width(), height())); + this.validate(); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + disconnect(); + setVisible(false); + dispose(); + } + }); + + this.setVisible(true); + + thread = new AltosDisplayThread(this, voice, flightStatus, flightInfo, reader); + + thread.start(); + } + + public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) { + this(in_voice, in_reader, -1); + } +} diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index f876beba..fed96c28 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -39,9 +39,15 @@ class AltosLog implements Runnable { FileWriter log_file; Thread log_thread; - void close() throws IOException { - if (log_file != null) - log_file.close(); + void close() { + if (log_file != null) { + try { + log_file.close(); + } catch (IOException io) { + } + } + if (log_thread != null) + log_thread.interrupt(); } boolean open (AltosTelemetry telem) throws IOException { @@ -89,10 +95,7 @@ class AltosLog implements Runnable { } catch (InterruptedException ie) { } catch (IOException ie) { } - try { - close(); - } catch (IOException ie) { - } + close(); } public AltosLog (AltosSerial s) { diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java index 52627563..e2a3df3b 100644 --- a/ao-tools/altosui/AltosPreferences.java +++ b/ao-tools/altosui/AltosPreferences.java @@ -32,7 +32,7 @@ class AltosPreferences { final static String logdirPreference = "LOGDIR"; /* channel preference name */ - final static String channelPreference = "CHANNEL"; + final static String channelPreferenceFormat = "CHANNEL-%d"; /* voice preference name */ final static String voicePreference = "VOICE"; @@ -52,8 +52,8 @@ class AltosPreferences { /* Log directory */ static File logdir; - /* Telemetry channel */ - static int channel; + /* Channel (map serial to channel) */ + static Hashtable channels; /* Voice preference */ static boolean voice; @@ -80,7 +80,7 @@ class AltosPreferences { logdir.mkdirs(); } - channel = preferences.getInt(channelPreference, 0); + channels = new Hashtable(); voice = preferences.getBoolean(voicePreference, true); @@ -151,15 +151,19 @@ class AltosPreferences { return logdir; } - public static void set_channel(int new_channel) { - channel = new_channel; + public static void set_channel(int serial, int new_channel) { + channels.put(serial, new_channel); synchronized (preferences) { - preferences.putInt(channelPreference, channel); + preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel); flush_preferences(); } } - public static int channel() { + public static int channel(int serial) { + if (channels.containsKey(serial)) + return channels.get(serial); + int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + channels.put(serial, channel); return channel; } diff --git a/ao-tools/altosui/AltosReplayReader.java b/ao-tools/altosui/AltosReplayReader.java new file mode 100644 index 00000000..4e5e1d93 --- /dev/null +++ b/ao-tools/altosui/AltosReplayReader.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +/* + * Open an existing telemetry file and replay it in realtime + */ + +public class AltosReplayReader extends AltosFlightReader { + Iterator iterator; + + public AltosRecord read() { + if (iterator.hasNext()) + return iterator.next(); + return null; + } + + public void close (boolean interrupted) { + } + + void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > Altos.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + } + + public AltosReplayReader(Iterator in_iterator, String in_name) { + iterator = in_iterator; + name = in_name; + } +} diff --git a/ao-tools/altosui/AltosReplayThread.java b/ao-tools/altosui/AltosReplayThread.java deleted file mode 100644 index b418160a..00000000 --- a/ao-tools/altosui/AltosReplayThread.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.Altos; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosFlightInfoTableModel; -import altosui.AltosChannelMenu; -import altosui.AltosFlashUI; -import altosui.AltosLogfileChooser; -import altosui.AltosCSVUI; -import altosui.AltosLine; -import altosui.AltosStatusTable; -import altosui.AltosInfoTable; -import altosui.AltosDisplayThread; - -/* - * Open an existing telemetry file and replay it in realtime - */ - -public class AltosReplayThread extends AltosDisplayThread { - Iterator iterator; - String name; - - public AltosRecord read() { - if (iterator.hasNext()) - return iterator.next(); - return null; - } - - public void close (boolean interrupted) { - if (!interrupted) - report(); - } - - void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > Altos.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - } - - public AltosReplayThread(Frame parent, Iterator in_iterator, - String in_name, AltosVoice voice, - AltosStatusTable status, AltosInfoTable info) { - super(parent, voice, status, info); - iterator = in_iterator; - name = in_name; - } -} diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index a1fc4371..f65e44d6 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -193,6 +193,8 @@ public class AltosSerial implements Runnable { print("~\nE 0\n"); flush_output(); set_monitor(monitor_mode); + set_channel(AltosPreferences.channel()); + set_callsign(AltosPreferences.callsign()); } public void set_channel(int channel) { diff --git a/ao-tools/altosui/AltosStatusTable.java b/ao-tools/altosui/AltosStatusTable.java index 3965a57d..0d3a5d14 100644 --- a/ao-tools/altosui/AltosStatusTable.java +++ b/ao-tools/altosui/AltosStatusTable.java @@ -34,14 +34,11 @@ import altosui.AltosFlightInfoTableModel; public class AltosStatusTable extends JTable { private AltosFlightStatusTableModel flightStatusModel; - JFrame frame; - private Font statusFont = new Font("SansSerif", Font.BOLD, 24); - public AltosStatusTable(JFrame in_frame) { + public AltosStatusTable() { super((TableModel) new AltosFlightStatusTableModel()); flightStatusModel = (AltosFlightStatusTableModel) getModel(); - frame = in_frame; setFont(statusFont); diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java new file mode 100644 index 00000000..0b5509eb --- /dev/null +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; +import java.util.concurrent.*; + +class AltosTelemetryReader extends AltosFlightReader { + AltosDevice device; + AltosSerial serial; + AltosLog log; + + LinkedBlockingQueue telem; + + 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(boolean interrupted) { + serial.remove_monitor(telem); + log.close(); + serial.close(); + } + + void set_channel(int channel) { + serial.set_channel(channel); + } + + void set_callsign(String callsign) { + serial.set_callsign(callsign); + } + + public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, IOException { + device = in_device; + serial = new AltosSerial(); + log = new AltosLog(serial); + name = device.getPath(); + + telem = new LinkedBlockingQueue(); + serial.add_monitor(telem); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 28ed42fb..e1bbee30 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -39,7 +39,6 @@ import altosui.AltosPreferences; import altosui.AltosLog; import altosui.AltosVoice; import altosui.AltosFlightInfoTableModel; -import altosui.AltosChannelMenu; import altosui.AltosFlashUI; import altosui.AltosLogfileChooser; import altosui.AltosCSVUI; @@ -51,14 +50,6 @@ import altosui.AltosDisplayThread; import libaltosJNI.*; public class AltosUI extends JFrame { - private int channel = -1; - - private AltosStatusTable flightStatus; - private AltosInfoTable flightInfo; - private AltosSerial serial_line; - private AltosLog altos_log; - private Box vbox; - public AltosVoice voice = new AltosVoice(); public static boolean load_library(Frame frame) { @@ -73,38 +64,41 @@ public class AltosUI extends JFrame { return true; } + void telemetry_window(AltosDevice device) { + try { + AltosFlightReader reader = new AltosTelemetryReader(device); + if (reader != null) + new AltosFlightUI(voice, reader, device.getSerial()); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + String.format("Cannot open device \"%s\"", + device.getPath()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + device.getPath(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); + } + } + public AltosUI() { load_library(null); - 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(); - this.add(vbox); - - flightStatus = new AltosStatusTable(this); - - vbox.add(flightStatus); - - flightInfo = new AltosInfoTable(); - vbox.add(flightInfo.box()); - setTitle("AltOS"); createMenu(); - serial_line = new AltosSerial(); - altos_log = new AltosLog(serial_line); int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - this.setSize(new Dimension (flightInfo.width(), - flightStatus.height() + flightInfo.height())); + this.setSize(new Dimension (300, 100)); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @@ -113,63 +107,14 @@ public class AltosUI extends JFrame { System.exit(0); } }); - voice.speak("Rocket flight monitor ready."); - } - - class DeviceThread extends AltosDisplayThread { - AltosSerial serial; - LinkedBlockingQueue telem; - - 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(boolean interrupted) { - serial.close(); - serial.remove_monitor(telem); - } - - public DeviceThread(AltosSerial s, String in_name, AltosVoice voice, AltosStatusTable status, AltosInfoTable info) { - super(AltosUI.this, voice, status, info); - serial = s; - telem = new LinkedBlockingQueue(); - serial.add_monitor(telem); - name = in_name; - } } private void ConnectToDevice() { AltosDevice device = AltosDeviceDialog.show(AltosUI.this, AltosDevice.product_basestation); - if (device != null) { - try { - stop_display(); - serial_line.open(device); - DeviceThread thread = new DeviceThread(serial_line, device.getPath(), voice, flightStatus, flightInfo); - serial_line.set_channel(AltosPreferences.channel()); - serial_line.set_callsign(AltosPreferences.callsign()); - run_display(thread); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - String.format("Cannot open device \"%s\"", - device.getPath()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.getPath(), - "Unkonwn I/O error", - JOptionPane.ERROR_MESSAGE); - } - } - } - - void DisconnectFromDevice () { - stop_display(); + if (device != null) + telemetry_window(device); } void ConfigureCallsign() { @@ -177,11 +122,8 @@ public class AltosUI extends JFrame { result = JOptionPane.showInputDialog(AltosUI.this, "Configure Callsign", AltosPreferences.callsign()); - if (result != null) { + if (result != null) AltosPreferences.set_callsign(result); - if (serial_line != null) - serial_line.set_callsign(result); - } } void ConfigureTeleMetrum() { @@ -192,25 +134,6 @@ public class AltosUI extends JFrame { new AltosFlashUI(AltosUI.this); } - - Thread display_thread; - - private void stop_display() { - if (display_thread != null && display_thread.isAlive()) { - display_thread.interrupt(); - try { - display_thread.join(); - } catch (InterruptedException ie) {} - } - display_thread = null; - } - - private void run_display(Thread thread) { - stop_display(); - display_thread = thread; - display_thread.start(); - } - /* * Replay a flight from telemetry data */ @@ -218,12 +141,11 @@ public class AltosUI extends JFrame { AltosLogfileChooser chooser = new AltosLogfileChooser( AltosUI.this); AltosRecordIterable iterable = chooser.runDialog(); - if (iterable != null) - run_display(new AltosReplayThread(this, iterable.iterator(), - chooser.filename(), - voice, - flightStatus, - flightInfo)); + if (iterable != null) { + AltosFlightReader reader = new AltosReplayReader(iterable.iterator(), + chooser.filename()); + new AltosFlightUI(voice, reader); + } } /* Connect to TeleMetrum, either directly or through @@ -278,7 +200,7 @@ public class AltosUI extends JFrame { }); menu.add(item); - item = new JMenuItem("Flash Image",KeyEvent.VK_F); + item = new JMenuItem("Flash Image",KeyEvent.VK_I); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FlashImage(); @@ -286,7 +208,7 @@ public class AltosUI extends JFrame { }); menu.add(item); - item = new JMenuItem("Export Data",KeyEvent.VK_F); + item = new JMenuItem("Export Data",KeyEvent.VK_E); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ExportData(); @@ -294,7 +216,7 @@ public class AltosUI extends JFrame { }); menu.add(item); - item = new JMenuItem("Graph Data",KeyEvent.VK_F); + item = new JMenuItem("Graph Data",KeyEvent.VK_G); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { GraphData(); @@ -307,6 +229,7 @@ public class AltosUI extends JFrame { ActionEvent.CTRL_MASK)); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + System.out.printf("exiting\n"); System.exit(0); } }); @@ -314,7 +237,7 @@ public class AltosUI extends JFrame { } // Device menu - { + if (false) { menu = new JMenu("Device"); menu.setMnemonic(KeyEvent.VK_D); menubar.add(menu); @@ -327,14 +250,6 @@ public class AltosUI extends JFrame { }); menu.add(item); - item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - DisconnectFromDevice(); - } - }); - menu.add(item); - menu.addSeparator(); item = new JMenuItem("Set Callsign",KeyEvent.VK_S); @@ -403,23 +318,7 @@ public class AltosUI extends JFrame { }); menu.add(item); } - - // Channel menu - { - menu = new AltosChannelMenu(AltosPreferences.channel()); - menu.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int new_channel = Integer.parseInt(e.getActionCommand()); - AltosPreferences.set_channel(new_channel); - serial_line.set_channel(new_channel); - } - }); - menu.setMnemonic(KeyEvent.VK_C); - menubar.add(menu); - } - this.setJMenuBar(menubar); - } static AltosRecordIterable open_logfile(String filename) { @@ -510,6 +409,10 @@ public class AltosUI extends JFrame { } else { AltosUI altosui = new AltosUI(); altosui.setVisible(true); + + AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation); + for (int i = 0; i < devices.length; i++) + altosui.telemetry_window(devices[i]); } } } diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 2f4ed6d8..2322b93f 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -29,7 +29,9 @@ altosui_JAVA = \ AltosFlash.java \ AltosFlashUI.java \ AltosFlightInfoTableModel.java \ + AltosFlightReader.java \ AltosFlightStatusTableModel.java \ + AltosFlightUI.java \ AltosGPS.java \ AltosGreatCircle.java \ AltosHexfile.java \ @@ -44,7 +46,8 @@ altosui_JAVA = \ AltosReader.java \ AltosRecord.java \ AltosRecordIterable.java \ - AltosReplayThread.java \ + AltosTelemetryReader.java \ + AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ AltosSerial.java \ -- cgit v1.2.3 From 6b17d276271faa8a420a1c8f6be17faaa0c7043c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Nov 2010 22:07:04 -0800 Subject: altosui: Create buttons for main actions Signed-off-by: Keith Packard --- ao-tools/altosui/AltosUI.java | 97 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index e1bbee30..ded9e733 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -83,6 +83,27 @@ public class AltosUI extends JFrame { } } + Container pane; + GridBagLayout gridbag; + + JButton addButton(int x, int y, String label) { + GridBagConstraints c; + JButton b; + + c = new GridBagConstraints(); + c.gridx = x; c.gridy = y; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + b = new JButton(label); + + Dimension ps = b.getPreferredSize(); + + gridbag.setConstraints(b, c); + add(b, c); + return b; + } + public AltosUI() { load_library(null); @@ -93,13 +114,67 @@ public class AltosUI extends JFrame { AltosPreferences.init(this); + pane = getContentPane(); + gridbag = new GridBagLayout(); + pane.setLayout(gridbag); + + JButton b; + + b = addButton(0, 0, "Monitor Flight"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConnectToDevice(); + } + }); + b = addButton(1, 0, "Save Flight Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SaveFlightData(); + } + }); + b = addButton(2, 0, "Replay Flight"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Replay(); + } + }); + b = addButton(0, 1, "Graph Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + GraphData(); + } + }); + b = addButton(1, 1, "Export Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ExportData(); + } + }); + b = addButton(2, 1, "Configure TeleMetrum"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConfigureTeleMetrum(); + } + }); + setTitle("AltOS"); createMenu(); - int dpi = Toolkit.getDefaultToolkit().getScreenResolution(); - this.setSize(new Dimension (300, 100)); - this.validate(); + pane.doLayout(); + pane.validate(); + + doLayout(); + validate(); + + setVisible(true); + + Insets i = getInsets(); + Dimension ps = rootPane.getPreferredSize(); + ps.width += i.left + i.right; + ps.height += i.top + i.bottom; + setPreferredSize(ps); + setSize(ps); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override @@ -184,22 +259,6 @@ public class AltosUI extends JFrame { menu.setMnemonic(KeyEvent.VK_F); menubar.add(menu); - item = new JMenuItem("Replay File",KeyEvent.VK_R); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Replay(); - } - }); - menu.add(item); - - item = new JMenuItem("Save Flight Data",KeyEvent.VK_S); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - SaveFlightData(); - } - }); - menu.add(item); - item = new JMenuItem("Flash Image",KeyEvent.VK_I); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { -- cgit v1.2.3 From 94f4a50d6430cc8280cbdaa9f39d3cb858d0e077 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Nov 2010 22:10:46 -0800 Subject: altosui: Fix channel setting at serial open time Was using the previous non-device-specific preferences API. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index f65e44d6..d6848e57 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -193,7 +193,7 @@ public class AltosSerial implements Runnable { print("~\nE 0\n"); flush_output(); set_monitor(monitor_mode); - set_channel(AltosPreferences.channel()); + set_channel(AltosPreferences.channel(device.getSerial())); set_callsign(AltosPreferences.callsign()); } -- cgit v1.2.3 From a0a92c605e238277c9881545a7226e53b5dbc295 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Nov 2010 22:17:26 -0800 Subject: altosui: Fix more calls to AltosPreferences.channel() Oops. Two more. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 2 +- ao-tools/altosui/AltosEepromDownload.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 7b6cd78c..7fecff0e 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -122,7 +122,7 @@ public class AltosConfig implements Runnable, ActionListener { void start_serial() throws InterruptedException { if (remote) { - serial_line.set_channel(AltosPreferences.channel()); + serial_line.set_channel(AltosPreferences.channel(device.getSerial())); serial_line.set_callsign(AltosPreferences.callsign()); serial_line.printf("p\n"); serial_line.flush_input(); diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index a7f64904..8efc94d2 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -224,7 +224,7 @@ public class AltosEepromDownload implements Runnable { public void run () { if (remote) { - serial_line.set_channel(AltosPreferences.channel()); + serial_line.set_channel(AltosPreferences.channel(device.getSerial())); serial_line.set_callsign(AltosPreferences.callsign()); serial_line.printf("p\nE 0\n"); serial_line.flush_input(); -- cgit v1.2.3 From eb77e806ded99532dc7eaa39c1893f075b028af6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Nov 2010 10:21:34 -0800 Subject: altosui: Create abstract interface for flight data display This allows the implementation of the flight data display to occur in the flight UI instead of the display thread. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDisplayThread.java | 16 ++++++---------- ao-tools/altosui/AltosFlightDisplay.java | 24 ++++++++++++++++++++++++ ao-tools/altosui/AltosFlightUI.java | 13 +++++++++++-- ao-tools/altosui/Makefile.am | 1 + 4 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 ao-tools/altosui/AltosFlightDisplay.java diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java index b15472ed..957ac0d6 100644 --- a/ao-tools/altosui/AltosDisplayThread.java +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -36,8 +36,7 @@ public class AltosDisplayThread extends Thread { String name; AltosFlightReader reader; int crc_errors; - AltosStatusTable flightStatus; - AltosInfoTable flightInfo; + AltosFlightDisplay display; class IdleThread extends Thread { @@ -182,10 +181,8 @@ public class AltosDisplayThread extends Thread { } void show(AltosState state, int crc_errors) { - if (state != null) { - flightStatus.set(state); - flightInfo.show(state, crc_errors); - } + if (state != null) + display.show(state, crc_errors); } public void run() { @@ -197,7 +194,7 @@ public class AltosDisplayThread extends Thread { idle_thread = new IdleThread(); - flightInfo.clear(); + display.reset(); try { for (;;) { try { @@ -235,11 +232,10 @@ public class AltosDisplayThread extends Thread { } } - public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info, AltosFlightReader in_reader) { + public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { parent = in_parent; voice = in_voice; - flightStatus = in_status; - flightInfo = in_info; + display = in_display; reader = in_reader; } } diff --git a/ao-tools/altosui/AltosFlightDisplay.java b/ao-tools/altosui/AltosFlightDisplay.java new file mode 100644 index 00000000..d18d1d1f --- /dev/null +++ b/ao-tools/altosui/AltosFlightDisplay.java @@ -0,0 +1,24 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 interface AltosFlightDisplay { + void reset(); + + void show(AltosState state, int crc_errors); +} diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 84ba9dca..11fc2442 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosFlightUI extends JFrame { +public class AltosFlightUI extends JFrame implements AltosFlightDisplay { String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; Object[][] statusData = { { "0", "pad", "-50", "0" } }; @@ -62,6 +62,15 @@ public class AltosFlightUI extends JFrame { stop_display(); } + public void reset() { + flightInfo.clear(); + } + + public void show(AltosState state, int crc_errors) { + flightStatus.set(state); + flightInfo.show(state, crc_errors); + } + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { voice = in_voice; reader = in_reader; @@ -117,7 +126,7 @@ public class AltosFlightUI extends JFrame { this.setVisible(true); - thread = new AltosDisplayThread(this, voice, flightStatus, flightInfo, reader); + thread = new AltosDisplayThread(this, voice, this, reader); thread.start(); } diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 2322b93f..ccb88ed1 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -28,6 +28,7 @@ altosui_JAVA = \ AltosFile.java \ AltosFlash.java \ AltosFlashUI.java \ + AltosFlightDisplay.java \ AltosFlightInfoTableModel.java \ AltosFlightReader.java \ AltosFlightStatusTableModel.java \ -- cgit v1.2.3 From 22d00785188a880700cd372528189a7a15278da9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Nov 2010 14:40:58 -0800 Subject: altosui: Add tab UI with 'pad' mode. This creates a multi-tab interface for flight monitoring and includes a special tab for 'pad' mode. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlightUI.java | 16 ++- ao-tools/altosui/AltosLed.java | 54 ++++++++ ao-tools/altosui/AltosLights.java | 72 +++++++++++ ao-tools/altosui/AltosPad.java | 249 ++++++++++++++++++++++++++++++++++++ ao-tools/altosui/Makefile.am | 24 +++- icon/grayled.png | Bin 0 -> 1528 bytes icon/grayon.png | Bin 0 -> 1873 bytes icon/greenled.png | Bin 0 -> 2281 bytes icon/greenoff.png | Bin 0 -> 1811 bytes icon/redled.png | Bin 0 -> 2103 bytes icon/redoff.png | Bin 0 -> 1694 bytes 11 files changed, 410 insertions(+), 5 deletions(-) create mode 100644 ao-tools/altosui/AltosLed.java create mode 100644 ao-tools/altosui/AltosLights.java create mode 100644 ao-tools/altosui/AltosPad.java create mode 100644 icon/grayled.png create mode 100644 icon/grayon.png create mode 100644 icon/greenled.png create mode 100644 icon/greenoff.png create mode 100644 icon/redled.png create mode 100644 icon/redoff.png diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 11fc2442..a7caf7e9 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -37,6 +37,11 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosDisplayThread thread; private Box vbox; + + JTabbedPane pane; + + AltosPad pad; + private AltosStatusTable flightStatus; private AltosInfoTable flightInfo; @@ -63,10 +68,12 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } public void reset() { + pad.reset(); flightInfo.clear(); } public void show(AltosState state, int crc_errors) { + pad.show(state, crc_errors); flightStatus.set(state); flightInfo.show(state, crc_errors); } @@ -86,8 +93,15 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { vbox = new Box (BoxLayout.Y_AXIS); vbox.add(flightStatus); + pane = new JTabbedPane(); + + pad = new AltosPad(); + pane.add("Launch Pad", pad); + flightInfo = new AltosInfoTable(); - vbox.add(flightInfo.box()); + pane.add("Table", flightInfo.box()); + + vbox.add(pane); this.add(vbox); diff --git a/ao-tools/altosui/AltosLed.java b/ao-tools/altosui/AltosLed.java new file mode 100644 index 00000000..e08e9960 --- /dev/null +++ b/ao-tools/altosui/AltosLed.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLed extends JLabel { + ImageIcon on, off; + + ImageIcon create_icon(String path) { + java.net.URL imgURL = AltosUI.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set(boolean set) { + if (set) + setIcon(on); + else + setIcon(off); + } + + public AltosLed(String on_path, String off_path) { + on = create_icon(on_path); + off = create_icon(off_path); + setIcon(off); + } +} diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java new file mode 100644 index 00000000..2d2a1938 --- /dev/null +++ b/ao-tools/altosui/AltosLights.java @@ -0,0 +1,72 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLights extends JComponent { + + GridBagLayout gridbag; + + AltosLed red, green; + + ImageIcon create_icon(String path, String description) { + java.net.URL imgURL = AltosUI.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL, description); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set (boolean on) { + if (on) { + red.set(false); + green.set(true); + } else { + red.set(true); + green.set(false); + } + } + + public AltosLights() { + GridBagConstraints c; + gridbag = new GridBagLayout(); + setLayout(gridbag); + + c = new GridBagConstraints(); + red = new AltosLed("/redled.png", "/redoff.png"); + c.gridx = 0; c.gridy = 0; + gridbag.setConstraints(red, c); + add(red); + red.set(true); + green = new AltosLed("/greenled.png", "/greenoff.png"); + c.gridx = 1; c.gridy = 0; + gridbag.setConstraints(green, c); + add(green); + green.set(false); + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java new file mode 100644 index 00000000..133dbed3 --- /dev/null +++ b/ao-tools/altosui/AltosPad.java @@ -0,0 +1,249 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosPad extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + Font label_font; + Font value_font; + + public class LaunchStatus { + JLabel label; + JLabel value; + AltosLights lights; + + void show(AltosState state, int crc_errors) {} + void reset() { + value.setText("0"); + lights.set(false); + } + + public LaunchStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.CENTER; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JLabel("4.00"); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.EAST; + layout.setConstraints(value, c); + add(value); + + } + } + + public class LaunchValue { + JLabel label; + JLabel value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText("0"); + } + public LaunchValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JLabel("4.00"); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.EAST; + layout.setConstraints(value, c); + add(value); + } + } + + class Battery extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.battery)); + lights.set(state.battery > 3.7); + } + public Battery (GridBagLayout layout, int y) { + super(layout, y, "Battery Voltage"); + } + } + + Battery battery; + + class Apogee extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + + class GPS extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4d sats", state.gps.nsat)); + lights.set(state.gps_ready); + } + public GPS (GridBagLayout layout, int y) { + super (layout, y, "GPS Status"); + } + } + + GPS gps; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class PadLat extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(pos(state.pad_lat,"N", "S")); + } + public PadLat (GridBagLayout layout, int y) { + super (layout, y, "Pad Latitude"); + } + } + + PadLat pad_lat; + + class PadLon extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(pos(state.pad_lon,"E", "W")); + } + public PadLon (GridBagLayout layout, int y) { + super (layout, y, "Pad Longitude"); + } + } + + PadLon pad_lon; + + class PadAlt extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.0f m", state.pad_alt)); + } + public PadAlt (GridBagLayout layout, int y) { + super (layout, y, "Pad Altitude"); + } + } + + PadAlt pad_alt; + + public void reset() { + battery.reset(); + apogee.reset(); + main.reset(); + gps.reset(); + pad_lat.reset(); + pad_lon.reset(); + pad_alt.reset(); + } + + public void show(AltosState state, int crc_errors) { + battery.show(state, crc_errors); + apogee.show(state, crc_errors); + main.show(state, crc_errors); + gps.show(state, crc_errors); + pad_lat.show(state, crc_errors); + pad_lon.show(state, crc_errors); + pad_alt.show(state, crc_errors); + } + + public AltosPad() { + layout = new GridBagLayout(); + + GridBagConstraints c; + + label_font = new Font("Dialog", Font.PLAIN, 24); + value_font = new Font("Monospaced", Font.PLAIN, 24); + setLayout(layout); + + c = new GridBagConstraints(); + /* Elements in pad display: + * + * Battery voltage + * Igniter continuity + * GPS lock status and location + * Pad altitude + * RSSI + */ + battery = new Battery(layout, 0); + apogee = new Apogee(layout, 1); + main = new Main(layout, 2); + gps = new GPS(layout, 3); + pad_lat = new PadLat(layout, 4); + pad_lon = new PadLon(layout, 5); + pad_alt = new PadAlt(layout, 6); + } +} diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index ccb88ed1..ab9cf201 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -39,9 +39,12 @@ altosui_JAVA = \ Altos.java \ AltosInfoTable.java \ AltosKML.java \ + AltosLed.java \ + AltosLights.java \ AltosLine.java \ AltosLogfileChooser.java \ AltosLog.java \ + AltosPad.java \ AltosParse.java \ AltosPreferences.java \ AltosReader.java \ @@ -92,8 +95,21 @@ 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 +ICONDIR=$(top_srcdir)/icon + +JAVA_ICON=$(ICONDIR)/altus-metrum-16x16.jpg + +ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ + $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ + $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png + +# icon base names for jar +ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \ + -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ + -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ + -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + +WINDOWS_ICON=$(ICONDIR)/altus-metrum.ico # Firmware FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx @@ -163,13 +179,13 @@ classes/altosui: $(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) jar cfm $@ Manifest.txt \ - -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ + $(ICONJAR) \ -C classes altosui \ -C ../libaltos libaltosJNI $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) jar cfm $@ Manifest-fat.txt \ - -C $(top_srcdir)/icon altus-metrum-16x16.jpg \ + $(ICONJAR) \ -C classes altosui \ -C ../libaltos libaltosJNI diff --git a/icon/grayled.png b/icon/grayled.png new file mode 100644 index 00000000..bb6005c6 Binary files /dev/null and b/icon/grayled.png differ diff --git a/icon/grayon.png b/icon/grayon.png new file mode 100644 index 00000000..c99b376e Binary files /dev/null and b/icon/grayon.png differ diff --git a/icon/greenled.png b/icon/greenled.png new file mode 100644 index 00000000..d7663961 Binary files /dev/null and b/icon/greenled.png differ diff --git a/icon/greenoff.png b/icon/greenoff.png new file mode 100644 index 00000000..c3cf8491 Binary files /dev/null and b/icon/greenoff.png differ diff --git a/icon/redled.png b/icon/redled.png new file mode 100644 index 00000000..230afae0 Binary files /dev/null and b/icon/redled.png differ diff --git a/icon/redoff.png b/icon/redoff.png new file mode 100644 index 00000000..a251402f Binary files /dev/null and b/icon/redoff.png differ -- cgit v1.2.3 From b0d31910da592e2f67c47c8fc3e15ce8135d5094 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Nov 2010 23:34:32 -0800 Subject: altosui: Add ascent, descent and landed tabs This completes the set of tabs for in-flight status information. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosAscent.java | 250 +++++++++++++++++++++++++++++++ ao-tools/altosui/AltosDescent.java | 211 ++++++++++++++++++++++++++ ao-tools/altosui/AltosDisplayThread.java | 14 +- ao-tools/altosui/AltosFlightUI.java | 52 +++++++ ao-tools/altosui/AltosLanded.java | 208 +++++++++++++++++++++++++ ao-tools/altosui/AltosLights.java | 1 + ao-tools/altosui/AltosPad.java | 18 +-- ao-tools/altosui/AltosState.java | 1 + ao-tools/altosui/Makefile.am | 3 + 9 files changed, 743 insertions(+), 15 deletions(-) create mode 100644 ao-tools/altosui/AltosAscent.java create mode 100644 ao-tools/altosui/AltosDescent.java create mode 100644 ao-tools/altosui/AltosLanded.java diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java new file mode 100644 index 00000000..40df7af8 --- /dev/null +++ b/ao-tools/altosui/AltosAscent.java @@ -0,0 +1,250 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosAscent extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + Font label_font; + Font value_font; + + public class AscentValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + public AscentValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(20); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.HORIZONTAL; + c.gridwidth = 2; + layout.setConstraints(value, c); + add(value); + } + } + + public class AscentValueHold { + JLabel label; + JTextField value; + JTextField max_value; + double max; + + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + max_value.setText(""); + max = 0; + } + + void show(String format, double v) { + value.setText(String.format(format, v)); + if (v > max) { + max_value.setText(String.format(format, v)); + max = v; + } + } + public AscentValueHold (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(10); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + layout.setConstraints(value, c); + add(value); + + max_value = new JTextField(10); + max_value.setFont(label_font); + max_value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + layout.setConstraints(max_value, c); + add(max_value); + } + } + + + class Height extends AscentValueHold { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.height); + } + public Height (GridBagLayout layout, int y) { + super (layout, y, "Height"); + } + } + + Height height; + + class Speed extends AscentValueHold { + void show (AltosState state, int crc_errors) { + double speed = state.speed; + if (!state.ascent) + speed = state.baro_speed; + show("%6.0f m/s", speed); + } + public Speed (GridBagLayout layout, int y) { + super (layout, y, "Speed"); + } + } + + Speed speed; + + class Accel extends AscentValueHold { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s²", state.acceleration); + } + public Accel (GridBagLayout layout, int y) { + super (layout, y, "Acceleration"); + } + } + + Accel accel; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Lat extends AscentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lat,"N", "S")); + else + value.setText("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends AscentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lon,"E", "W")); + else + value.setText("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + public void reset() { + lat.reset(); + lon.reset(); + height.reset(); + speed.reset(); + accel.reset(); + } + + public void show(AltosState state, int crc_errors) { + lat.show(state, crc_errors); + lon.show(state, crc_errors); + height.show(state, crc_errors); + speed.show(state, crc_errors); + accel.show(state, crc_errors); + } + + public void labels(GridBagLayout layout, int y) { + GridBagConstraints c; + JLabel cur, max; + + cur = new JLabel("Current"); + cur.setFont(label_font); + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + layout.setConstraints(cur, c); + add(cur); + + max = new JLabel("Maximum"); + max.setFont(label_font); + c.gridx = 2; c.gridy = y; + layout.setConstraints(max, c); + add(max); + } + + public AltosAscent() { + layout = new GridBagLayout(); + + label_font = new Font("Dialog", Font.PLAIN, 24); + value_font = new Font("Monospace", Font.PLAIN, 24); + setLayout(layout); + + /* Elements in ascent display: + * + * lat + * lon + * height + */ + labels(layout, 0); + height = new Height(layout, 1); + speed = new Speed(layout, 2); + accel = new Accel(layout, 3); + lat = new Lat(layout, 4); + lon = new Lon(layout, 5); + } +} diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java new file mode 100644 index 00000000..0d3d17f0 --- /dev/null +++ b/ao-tools/altosui/AltosDescent.java @@ -0,0 +1,211 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosDescent extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + Font label_font; + Font value_font; + + public class DescentValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + + void show(String format, double v) { + value.setText(String.format(format, v)); + } + + public DescentValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(20); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.HORIZONTAL; + layout.setConstraints(value, c); + add(value); + } + } + + class Height extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.height); + } + public Height (GridBagLayout layout, int y) { + super (layout, y, "Height"); + } + } + + Height height; + + class Speed extends DescentValue { + void show (AltosState state, int crc_errors) { + double speed = state.speed; + if (!state.ascent) + speed = state.baro_speed; + show("%6.0f m/s", speed); + } + public Speed (GridBagLayout layout, int y) { + super (layout, y, "Speed"); + } + } + + Speed speed; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Lat extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lat,"N", "S")); + else + value.setText("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lon,"E", "W")); + else + value.setText("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + class Bearing extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%3.0f°", state.from_pad.bearing); + else + value.setText("???"); + } + public Bearing (GridBagLayout layout, int y) { + super (layout, y, "Bearing"); + } + } + + Bearing bearing; + + class Elevation extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%3.0f°", state.elevation); + else + value.setText("???"); + } + public Elevation (GridBagLayout layout, int y) { + super (layout, y, "Elevation"); + } + } + + Elevation elevation; + + class Range extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.range); + } + public Range (GridBagLayout layout, int y) { + super (layout, y, "Range"); + } + } + + Range range; + + public void reset() { + lat.reset(); + lon.reset(); + height.reset(); + speed.reset(); + bearing.reset(); + elevation.reset(); + range.reset(); + } + + public void show(AltosState state, int crc_errors) { + height.show(state, crc_errors); + speed.show(state, crc_errors); + bearing.show(state, crc_errors); + elevation.show(state, crc_errors); + range.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } + + public AltosDescent() { + layout = new GridBagLayout(); + + label_font = new Font("Dialog", Font.PLAIN, 24); + value_font = new Font("Monospace", Font.PLAIN, 24); + setLayout(layout); + + /* Elements in descent display */ + speed = new Speed(layout, 0); + height = new Height(layout, 1); + bearing = new Bearing(layout, 2); + elevation = new Elevation(layout, 3); + range = new Range(layout, 4); + lat = new Lat(layout, 5); + lon = new Lon(layout, 6); + } +} diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java index 957ac0d6..b5b2777e 100644 --- a/ao-tools/altosui/AltosDisplayThread.java +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -38,6 +38,11 @@ public class AltosDisplayThread extends Thread { int crc_errors; AltosFlightDisplay display; + synchronized void show(AltosState state, int crc_errors) { + if (state != null) + display.show(state, crc_errors); + } + class IdleThread extends Thread { boolean started; @@ -93,6 +98,10 @@ public class AltosDisplayThread extends Thread { (int) (state.from_pad.bearing + 0.5), (int) (state.from_pad.distance + 0.5)); ++reported_landing; + if (state.state != Altos.ao_flight_landed) { + state.state = Altos.ao_flight_landed; + show(state, 0); + } } } @@ -180,11 +189,6 @@ public class AltosDisplayThread extends Thread { return ret; } - void show(AltosState state, int crc_errors) { - if (state != null) - display.show(state, crc_errors); - } - public void run() { boolean interrupted = false; String line; diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index a7caf7e9..558b0395 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -41,10 +41,30 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { JTabbedPane pane; AltosPad pad; + AltosAscent ascent; + AltosDescent descent; + AltosLanded landed; private AltosStatusTable flightStatus; private AltosInfoTable flightInfo; + static final int tab_pad = 1; + static final int tab_ascent = 2; + static final int tab_descent = 3; + static final int tab_landed = 4; + + int cur_tab = 0; + + int which_tab(AltosState state) { + if (state.state < Altos.ao_flight_boost) + return tab_pad; + if (state.state <= Altos.ao_flight_coast) + return tab_ascent; + if (state.state <= Altos.ao_flight_main) + return tab_descent; + return tab_landed; + } + public int width() { return flightInfo.width(); } @@ -69,11 +89,34 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { public void reset() { pad.reset(); + ascent.reset(); + descent.reset(); + landed.reset(); flightInfo.clear(); } public void show(AltosState state, int crc_errors) { + int tab = which_tab(state); pad.show(state, crc_errors); + ascent.show(state, crc_errors); + descent.show(state, crc_errors); + landed.show(state, crc_errors); + if (tab != cur_tab) { + switch (tab) { + case tab_pad: + pane.setSelectedComponent(pad); + break; + case tab_ascent: + pane.setSelectedComponent(ascent); + break; + case tab_descent: + pane.setSelectedComponent(descent); + break; + case tab_landed: + pane.setSelectedComponent(landed); + } + cur_tab = tab; + } flightStatus.set(state); flightInfo.show(state, crc_errors); } @@ -98,6 +141,15 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pad = new AltosPad(); pane.add("Launch Pad", pad); + ascent = new AltosAscent(); + pane.add("Ascent", ascent); + + descent = new AltosDescent(); + pane.add("Descent", descent); + + landed = new AltosLanded(); + pane.add("Landed", landed); + flightInfo = new AltosInfoTable(); pane.add("Table", flightInfo.box()); diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java new file mode 100644 index 00000000..4b74aaa3 --- /dev/null +++ b/ao-tools/altosui/AltosLanded.java @@ -0,0 +1,208 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLanded extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + Font label_font; + Font value_font; + + public class LandedValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + + void show(String format, double v) { + value.setText(String.format(format, v)); + } + + public LandedValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(20); + value.setFont(label_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.HORIZONTAL; + layout.setConstraints(value, c); + add(value); + } + } + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Lat extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lat,"N", "S")); + else + value.setText("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lon,"E", "W")); + else + value.setText("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + class Bearing extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%3.0f°", state.from_pad.bearing); + else + value.setText("???"); + } + public Bearing (GridBagLayout layout, int y) { + super (layout, y, "Bearing"); + } + } + + Bearing bearing; + + class Distance extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%6.0f m", state.from_pad.distance); + else + value.setText("???"); + } + public Distance (GridBagLayout layout, int y) { + super (layout, y, "Distance"); + } + } + + Distance distance; + + class Height extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.max_height); + } + public Height (GridBagLayout layout, int y) { + super (layout, y, "Maximum Height"); + } + } + + Height height; + + class Speed extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s", state.max_speed); + } + public Speed (GridBagLayout layout, int y) { + super (layout, y, "Maximum Speed"); + } + } + + Speed speed; + + class Accel extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s²", state.max_acceleration); + } + public Accel (GridBagLayout layout, int y) { + super (layout, y, "Maximum Acceleration"); + } + } + + Accel accel; + + public void reset() { + lat.reset(); + lon.reset(); + bearing.reset(); + distance.reset(); + height.reset(); + speed.reset(); + accel.reset(); + } + + public void show(AltosState state, int crc_errors) { + bearing.show(state, crc_errors); + distance.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + height.show(state, crc_errors); + speed.show(state, crc_errors); + accel.show(state, crc_errors); + } + + public AltosLanded() { + layout = new GridBagLayout(); + + label_font = new Font("Dialog", Font.PLAIN, 24); + value_font = new Font("Monospace", Font.PLAIN, 24); + setLayout(layout); + + /* Elements in descent display */ + bearing = new Bearing(layout, 0); + distance = new Distance(layout, 1); + lat = new Lat(layout, 2); + lon = new Lon(layout, 3); + height = new Height(layout, 4); + speed = new Speed(layout, 5); + accel = new Accel(layout, 6); + } +} diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java index 2d2a1938..f1ed47c2 100644 --- a/ao-tools/altosui/AltosLights.java +++ b/ao-tools/altosui/AltosLights.java @@ -60,6 +60,7 @@ public class AltosLights extends JComponent { c = new GridBagConstraints(); red = new AltosLed("/redled.png", "/redoff.png"); c.gridx = 0; c.gridy = 0; + c.insets = new Insets (0, 5, 0, 5); gridbag.setConstraints(red, c); add(red); red.set(true); diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 133dbed3..7b72be20 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -35,12 +35,12 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public class LaunchStatus { JLabel label; - JLabel value; + JTextField value; AltosLights lights; void show(AltosState state, int crc_errors) {} void reset() { - value.setText("0"); + value.setText(""); lights.set(false); } @@ -64,12 +64,11 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JLabel("4.00"); + value = new JTextField(10); value.setFont(label_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.EAST; + c.anchor = GridBagConstraints.WEST; layout.setConstraints(value, c); add(value); @@ -78,11 +77,11 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public class LaunchValue { JLabel label; - JLabel value; + JTextField value; void show(AltosState state, int crc_errors) {} void reset() { - value.setText("0"); + value.setText(""); } public LaunchValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); @@ -93,16 +92,15 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { c.gridx = 1; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.WEST; layout.setConstraints(label, c); add(label); - value = new JLabel("4.00"); + value = new JTextField(20); value.setFont(label_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.EAST; + c.fill = GridBagConstraints.HORIZONTAL; layout.setConstraints(value, c); add(value); } diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 1048bb51..86eb636a 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -35,6 +35,7 @@ public class AltosState { int tick; int state; + boolean landed; boolean ascent; /* going up? */ double ground_altitude; diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index ab9cf201..267bae63 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -10,6 +10,7 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/ bin_SCRIPTS=altosui altosui_JAVA = \ + AltosAscent.java \ AltosChannelMenu.java \ AltosConfig.java \ AltosConfigUI.java \ @@ -18,6 +19,7 @@ altosui_JAVA = \ AltosCSV.java \ AltosCSVUI.java \ AltosDebug.java \ + AltosDescent.java \ AltosDeviceDialog.java \ AltosDevice.java \ AltosDisplayThread.java \ @@ -39,6 +41,7 @@ altosui_JAVA = \ Altos.java \ AltosInfoTable.java \ AltosKML.java \ + AltosLanded.java \ AltosLed.java \ AltosLights.java \ AltosLine.java \ -- cgit v1.2.3 From 5c6a5335a057be0219450b4b9889c647d8d4a012 Mon Sep 17 00:00:00 2001 From: Bob Finch Date: Mon, 1 Nov 2010 14:36:41 -0600 Subject: Updated PKGBUILD-git.altos Signed-off-by: Keith Packard --- contrib/arch-linux/PKGBUILD-git.altos | 84 +++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos index ff2c66ca..0a3ecec5 100644 --- a/contrib/arch-linux/PKGBUILD-git.altos +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -1,6 +1,6 @@ # Original contributor: Bob Finch pkgname=altos-git -pkgver=20100518 +pkgver=20101031 pkgrel=1 pkgdesc="Software solutions for high powered rocketry avionics" arch=('i686' 'x86_64') @@ -8,57 +8,95 @@ url="http://www.altusmetrum.org/AltOS/" license=('GPL') provides=('altos') conflicts=('altos') -depends=('openssl>=1.0.0' 'libusb-beta' 'plplot-svn' 'sdcc' 'nickle'\ - 'flite' 'kernel26>=2.6.33' 'gconf' 'alsa-lib' 'libglade'\ - 'docbook-xsl' 'fop') -makedepends=('git') +depends=('openssl>=1.0.0' 'libusb1' 'plplot-svn' 'nickle' 'flite' 'kernel26>=2.6.33' 'fop'\ + 'gconf' 'alsa-oss' 'swig' 'libglade' 'freetts' 'jdk>=6u21' 'jfreechart' 'jcommon') +makedepends=('git' 'docbook-xsl=1.76.0' 'sdcc=2.9.0-2_patched' 'nsis' 'tar' 'gzip' 'zip') optdepends=('uucp: cu is included & is a bare boned terminal 2 serial program' 'cutemon: gui-based minimal terminal to serial program' 'google-earth: useful for viewing the kml files of the flight path') +options=('docs') _gitroot="git://git.gag.com/fw/altos" _gitname="altos" +_pkgname="altosui" +_libname="libaltos" build() { cd "$srcdir" msg "Connecting to GIT server...." - + if [ -d $_gitname ] ; then cd $_gitname && git pull origin msg "The local files are updated." else git clone $_gitroot fi - + msg "GIT checkout done or server timeout" msg "Starting make..." - + rm -rf "$srcdir/$_gitname-build" git clone "$srcdir/$_gitname" "$srcdir/$_gitname-build" - cd "$srcdir/$_gitname-build" - + # # BUILD HERE # - - ./autogen.sh - ./configure --prefix=/usr + + sh /etc/profile.d/jdk.sh + + cd "$srcdir/$_gitname-build" + ./autogen.sh --prefix=/usr --with-jvm=/opt/java/include/\ + --with-freetts=/usr/share/java/freetts/lib --with-jcommon=/usr/share/java/jcommon/lib\ + --with-jfreechart=/usr/share/java/jfreechart/lib\ + # --with-fat-dir=$srcdir + # Use this ^ for placing all 3 "fat" packages (linux,mac,windows) into a numbered dir. + + cd "$srcdir/$_gitname-build/ao-tools/$_pkgname/" + sed -i 's:\$(datadir)/java:\$(datadir)/java/altos:' Makefile + # This ^ places altosui.jar in an 'altos' subdirectory. + sed -i 's:\${exec_prefix}/bin:\${exec_prefix}/share/java/altos:' Makefile + # This ^ relocates altosui to allow for an aoss wrapper script. + sed -i 's|:/usr/share/java/\*|:/usr/share/java/*:$(JCOMMON)/*:$(JFREECHART)/*|' Makefile + # This ^ fixes compilation to include reference to jcommon.jar . + sed -i 's:cp -p $(JFREECHART_CLASS):cp -p $(JFREECHART_CLASS) $(JCOMMON_CLASS):' Makefile + # This ^ includes jcommon.jar in the macosx fat package. + + cd "$srcdir/$_gitname-build/ao-tools/$_libname/" + sed -i 's:$(JVM_INCLUDE):/opt/java/include\ -I/opt/java/include/linux:' Makefile + # This ^ enables both jni.h and jni_md.h to be found as required. + + cd "$srcdir/$_gitname-build/doc" + sed -i 's:stylesheet/docbook-xsl:xsl-stylesheets-1.76.0:' Makefile + # This ^ fixes archlinux's use of a specfic reference. + + cd "$srcdir/$_gitname-build" make || return 1 + + cd "$srcdir/$_gitname-build/doc" + make all + + cd "$srcdir/$_gitname-build/ao-tools/altosui" + make fat +} + +package() { + cd "$srcdir/$_gitname-build" make DESTDIR="$pkgdir/" install + mkdir -p $startdir/pkg/usr/share/altos + install -m 644 src/telemetrum-v1.0-* $startdir/pkg/usr/share/altos/ + install -m 644 src/teledongle-v0.2-* $startdir/pkg/usr/share/altos/ + mkdir -p $startdir/pkg/usr/share/pixmaps mkdir -p $startdir/pkg/usr/share/applications install -m644 debian/*.xpm $startdir/pkg/usr/share/pixmaps install -m644 debian/*.desktop $startdir/pkg/usr/share/applications + echo "#!/bin/sh" > holding.bin + echo ". aoss /usr/share/java/altos/altosui" >> holding.bin + install -D -m 755 holding.bin $startdir/pkg/usr/bin/$_pkgname - xsltproc -o telemetrum.html /usr/share/xml/docbook/xsl-stylesheets-1.74.0/html/docbook.xsl\ - doc/telemetrum.xsl - xsltproc -o telemetrum.fo /usr/share/xml/docbook/xsl-stylesheets-1.74.0/fo/docbook.xsl\ - doc/telemetrum.xsl - fop -fo telemetrum.fo -pdf telemetrum.pdf - - mkdir -p $startdir/pkg/usr/share/altos/doc - install -m 644 *.html $startdir/pkg/usr/share/altos/doc/ - install -m 644 *.pdf $startdir/pkg/usr/share/altos/doc/ -} + mkdir -p $startdir/pkg/usr/share/doc/altos + install -m 644 doc/*.html $startdir/pkg/usr/share/doc/altos/ + install -m 644 doc/*.pdf $startdir/pkg/usr/share/doc/altos/ +} -- cgit v1.2.3 From 891e629f6ba20654b614f3ca7211a0f1c92670cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Nov 2010 16:28:19 -0800 Subject: altos: Use grey leds when unlit - easier to see --- ao-tools/altosui/AltosLights.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java index f1ed47c2..08e6b4f8 100644 --- a/ao-tools/altosui/AltosLights.java +++ b/ao-tools/altosui/AltosLights.java @@ -58,13 +58,13 @@ public class AltosLights extends JComponent { setLayout(gridbag); c = new GridBagConstraints(); - red = new AltosLed("/redled.png", "/redoff.png"); + red = new AltosLed("/redled.png", "/grayled.png"); c.gridx = 0; c.gridy = 0; c.insets = new Insets (0, 5, 0, 5); gridbag.setConstraints(red, c); add(red); red.set(true); - green = new AltosLed("/greenled.png", "/greenoff.png"); + green = new AltosLed("/greenled.png", "/grayled.png"); c.gridx = 1; c.gridy = 0; gridbag.setConstraints(green, c); add(green); -- cgit v1.2.3 From b16b873723ee3e5097e6725c59ce191119439ad7 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:38:27 +1000 Subject: use value_font for values --- ao-tools/altosui/AltosAscent.java | 14 +++++++------- ao-tools/altosui/AltosDescent.java | 6 +++--- ao-tools/altosui/AltosLanded.java | 6 +++--- ao-tools/altosui/AltosPad.java | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 40df7af8..51fa1a89 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -53,8 +53,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(20); - value.setFont(label_font); + value = new JTextField(30); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -98,16 +98,16 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(10); - value.setFont(label_font); + value = new JTextField(15); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.EAST; layout.setConstraints(value, c); add(value); - max_value = new JTextField(10); - max_value.setFont(label_font); + max_value = new JTextField(15); + max_value.setFont(value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -231,7 +231,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout = new GridBagLayout(); label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospace", Font.PLAIN, 24); + value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); /* Elements in ascent display: diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index 0d3d17f0..0b7c8036 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -58,8 +58,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(20); - value.setFont(label_font); + value = new JTextField(30); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -196,7 +196,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout = new GridBagLayout(); label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospace", Font.PLAIN, 24); + value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); /* Elements in descent display */ diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java index 4b74aaa3..d170ccad 100644 --- a/ao-tools/altosui/AltosLanded.java +++ b/ao-tools/altosui/AltosLanded.java @@ -58,8 +58,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(20); - value.setFont(label_font); + value = new JTextField(30); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -193,7 +193,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { layout = new GridBagLayout(); label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospace", Font.PLAIN, 24); + value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); /* Elements in descent display */ diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 7b72be20..da047072 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -64,8 +64,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(10); - value.setFont(label_font); + value = new JTextField(15); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -95,8 +95,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(20); - value.setFont(label_font); + value = new JTextField(30); + value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; -- cgit v1.2.3 From 1f3e091efdfb2fe6f06a066cac60f5d267b94856 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:40:37 +1000 Subject: add --replay command line argument --- ao-tools/altosui/AltosUI.java | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index ded9e733..2861444d 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -456,7 +456,26 @@ public class AltosUI extends JFrame { public static void main(final String[] args) { int process = 0; /* Handle batch-mode */ - if (args.length > 0) { + if (args.length == 2 && args[0].equals("--replay")) { + String filename = args[1]; + FileInputStream in; + try { + in = new FileInputStream(filename); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", filename); + return; + } + AltosRecordIterable recs; + AltosReplayReader reader; + if (filename.endsWith("eeprom")) { + recs = new AltosEepromIterable(in); + } else { + recs = new AltosTelemetryIterable(in); + } + reader = new AltosReplayReader(recs.iterator(), filename); + new AltosFlightUI(new AltosVoice(), reader); + return; + } else if (args.length > 0) { for (int i = 0; i < args.length; i++) { if (args[i].equals("--kml")) process |= process_kml; -- cgit v1.2.3 From 3ffaa5d1c00b28be20fd4a26deb7bd41d953e92a Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:43:05 +1000 Subject: read preferences for --replay --- ao-tools/altosui/AltosFlightUI.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 558b0395..3581c54c 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -122,6 +122,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { + AltosPreferences.init(this); + voice = in_voice; reader = in_reader; -- cgit v1.2.3 From 8503943e3613f8670b128012b12ff14fb54321d7 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:45:43 +1000 Subject: reduce font size for FlightInfoTable --- ao-tools/altosui/AltosInfoTable.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java index 9964ab10..2f326e07 100644 --- a/ao-tools/altosui/AltosInfoTable.java +++ b/ao-tools/altosui/AltosInfoTable.java @@ -37,8 +37,8 @@ public class AltosInfoTable { private AltosFlightInfoTableModel model[]; private Box ibox[]; - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 12); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 12); static final int info_columns = 3; static final int info_rows = 17; -- cgit v1.2.3 From 317ec72a34906faad88c6924e634617b074e71db Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:52:01 +1000 Subject: use grayled.png for off --- ao-tools/altosui/AltosLights.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java index f1ed47c2..2fa38412 100644 --- a/ao-tools/altosui/AltosLights.java +++ b/ao-tools/altosui/AltosLights.java @@ -58,16 +58,16 @@ public class AltosLights extends JComponent { setLayout(gridbag); c = new GridBagConstraints(); - red = new AltosLed("/redled.png", "/redoff.png"); + red = new AltosLed("/redled.png", "/grayled.png"); c.gridx = 0; c.gridy = 0; c.insets = new Insets (0, 5, 0, 5); gridbag.setConstraints(red, c); add(red); red.set(true); - green = new AltosLed("/greenled.png", "/greenoff.png"); + green = new AltosLed("/greenled.png", "/grayled.png"); c.gridx = 1; c.gridy = 0; gridbag.setConstraints(green, c); add(green); green.set(false); } -} \ No newline at end of file +} -- cgit v1.2.3 From cc0a730de093c49be2a921101d27622b6f592e92 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 15:57:52 +1000 Subject: add compass bearing to voice output --- ao-tools/altosui/AltosDisplayThread.java | 4 +++- ao-tools/altosui/AltosGreatCircle.java | 25 +++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java index b5b2777e..375965b9 100644 --- a/ao-tools/altosui/AltosDisplayThread.java +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -69,8 +69,10 @@ public class AltosDisplayThread extends Thread { state.state < Altos.ao_flight_landed && state.range >= 0) { - voice.speak("Height %d, bearing %d, elevation %d, range %d.\n", + voice.speak("Height %d, bearing %s %d, elevation %d, range %d.\n", (int) (state.height + 0.5), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_VOICE), (int) (state.from_pad.bearing + 0.5), (int) (state.elevation + 0.5), (int) (state.range + 0.5)); diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java index 07c02c16..aa6ae3b9 100644 --- a/ao-tools/altosui/AltosGreatCircle.java +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -30,6 +30,31 @@ public class AltosGreatCircle { static final double rad = Math.PI / 180; static final double earth_radius = 6371.2 * 1000; /* in meters */ + static int BEARING_LONG = 0; + static int BEARING_SHORT = 1; + static int BEARING_VOICE = 2; + String bearing_words(int length) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } + public AltosGreatCircle (double start_lat, double start_lon, double end_lat, double end_lon) { -- cgit v1.2.3 From 75f7698b99a661ed17a91748a99699fa6761772a Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 11 Nov 2010 16:06:32 +1000 Subject: add compass bearing during descent --- ao-tools/altosui/AltosDescent.java | 50 ++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index 0b7c8036..56d3e4fe 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -62,6 +62,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.HORIZONTAL; layout.setConstraints(value, c); @@ -133,15 +134,54 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Lon lon; - class Bearing extends DescentValue { + class Bearing { + JLabel label; + JTextField value; + JTextField value_deg; + void reset () { + value.setText(""); + value_deg.setText(""); + } void show (AltosState state, int crc_errors) { - if (state.from_pad != null) - show("%3.0f°", state.from_pad.bearing); - else + if (state.from_pad != null) { + value.setText(state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG)); + value_deg.setText(String.format("%3.0f°", state.from_pad.bearing)); + } else { value.setText("???"); + value_deg.setText("???"); + } } public Bearing (GridBagLayout layout, int y) { - super (layout, y, "Bearing"); + GridBagConstraints c = new GridBagConstraints(); + + label = new JLabel("Bearing"); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(30); + value.setFont(value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.HORIZONTAL; + layout.setConstraints(value, c); + add(value); + + value_deg = new JTextField(5); + value_deg.setFont(value_font); + value_deg.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.HORIZONTAL; + + layout.setConstraints(value_deg, c); + add(value_deg); } } -- cgit v1.2.3 From 81e7b43ecad666e2e2310c7c94184f888bc86585 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2010 02:07:41 +1000 Subject: add site map tab, at least for QRS launches --- ao-tools/altosui/AltosFlightUI.java | 6 ++ ao-tools/altosui/AltosSiteMap.java | 137 ++++++++++++++++++++++++++++++++++++ ao-tools/altosui/Makefile.am | 1 + 3 files changed, 144 insertions(+) create mode 100644 ao-tools/altosui/AltosSiteMap.java diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 3581c54c..816ffa23 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -44,6 +44,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosAscent ascent; AltosDescent descent; AltosLanded landed; + AltosSiteMap sitemap; private AltosStatusTable flightStatus; private AltosInfoTable flightInfo; @@ -93,6 +94,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { descent.reset(); landed.reset(); flightInfo.clear(); + sitemap.reset(); } public void show(AltosState state, int crc_errors) { @@ -119,6 +121,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } flightStatus.set(state); flightInfo.show(state, crc_errors); + sitemap.show(state, crc_errors); } public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { @@ -155,6 +158,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { flightInfo = new AltosInfoTable(); pane.add("Table", flightInfo.box()); + sitemap = new AltosSiteMap(); + pane.add("Site Map", sitemap); + vbox.add(pane); this.add(vbox); diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java new file mode 100644 index 00000000..22b9aebe --- /dev/null +++ b/ao-tools/altosui/AltosSiteMap.java @@ -0,0 +1,137 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +public class AltosSiteMap extends JComponent implements AltosFlightDisplay { + double lat, lng; + int zoom; + double scale_x, scale_y; + Point2D.Double coord_pt; + Point2D.Double last_pt; + + Graphics2D g2d; + + private void setLocation(double new_lat, double new_lng, int new_zoom) { + lat = new_lat; + lng = new_lng; + zoom = new_zoom; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + coord_pt = pt(lat, lng, new Point2D.Double(0,0)); + coord_pt.x = 320-coord_pt.x; + coord_pt.y = 320-coord_pt.y; + last_pt = null; + } + + private static double limit(double v, double lo, double hi) { + if (v < lo) + return lo; + if (hi < v) + return hi; + return v; + } + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + private Point2D.Double pt(double lat, double lng) { + return pt(lat, lng, coord_pt); + } + + private Point2D.Double pt(double lat, double lng, Point2D.Double centre) { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = centre.x + lng*scale_x; + e = limit(Math.sin(Math.toRadians(lat)),-(1-1.0E-15),1-1.0E-15); + res.y = centre.y + 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + + public void reset() { + // ? + } + + static Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK // landed + }; + + public void show(AltosState state, int crc_errors) { + if (!state.gps_ready) + return; + Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + if (last_pt != null && pt != last_pt) { + if (0 <= state.state && state.state < stateColors.length) { + g2d.setColor(stateColors[state.state]); + } + g2d.draw(new Line2D.Double(last_pt, pt)); + } + last_pt = pt; + repaint(); + } + + public AltosSiteMap() { + GridBagLayout layout = new GridBagLayout(); + setLayout(layout); + + GridBagConstraints c = new GridBagConstraints(); + + setLocation(-27.850, 152.960, 15); + String pngfile = "/home/aj/qrs-S27.850,W152.960-15.png"; + + c.gridx = 0; c.gridy = 0; + c.weightx = 1; c.weighty = 1; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + + try { + BufferedImage myPicture = ImageIO.read(new File(pngfile)); + g2d = myPicture.createGraphics(); + JLabel picLabel = new JLabel(new ImageIcon( myPicture )); + JScrollPane scrollPane = new JScrollPane(picLabel); + layout.setConstraints(scrollPane, c); + add(scrollPane); + } catch (Exception e) { + throw new RuntimeException(e); + }; + } +} + diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 267bae63..fc532863 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -59,6 +59,7 @@ altosui_JAVA = \ AltosRomconfigUI.java \ AltosSerial.java \ AltosSerialMonitor.java \ + AltosSiteMap.java \ AltosState.java \ AltosStatusTable.java \ AltosTelemetry.java \ -- cgit v1.2.3 From 0327c1da01a3f6ede01f05c1d775651a57fd0c68 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2010 02:08:58 +1000 Subject: tabs -> spaces --- ao-tools/altosui/AltosSiteMap.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 22b9aebe..6f33aabd 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -78,9 +78,9 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } - public void reset() { - // ? - } + public void reset() { + // ? + } static Color stateColors[] = { Color.WHITE, // startup @@ -94,7 +94,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { Color.BLACK // landed }; - public void show(AltosState state, int crc_errors) { + public void show(AltosState state, int crc_errors) { if (!state.gps_ready) return; Point2D.Double pt = pt(state.gps.lat, state.gps.lon); @@ -106,7 +106,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } last_pt = pt; repaint(); - } + } public AltosSiteMap() { GridBagLayout layout = new GridBagLayout(); -- cgit v1.2.3 From beb6c881ec006241c7d2820c64e5381131d41180 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2010 03:24:26 +1000 Subject: make infotable scrollable, revert its fontsize to 14 --- ao-tools/altosui/AltosFlightUI.java | 2 +- ao-tools/altosui/AltosInfoTable.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 816ffa23..f56b3d1b 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -156,7 +156,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Landed", landed); flightInfo = new AltosInfoTable(); - pane.add("Table", flightInfo.box()); + pane.add("Table", new JScrollPane(flightInfo.box())); sitemap = new AltosSiteMap(); pane.add("Site Map", sitemap); diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java index 2f326e07..9964ab10 100644 --- a/ao-tools/altosui/AltosInfoTable.java +++ b/ao-tools/altosui/AltosInfoTable.java @@ -37,8 +37,8 @@ public class AltosInfoTable { private AltosFlightInfoTableModel model[]; private Box ibox[]; - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 12); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 12); + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); static final int info_columns = 3; static final int info_rows = 17; -- cgit v1.2.3 From 1bcfa22de7821984149db10cb79913efed36b41e Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2010 23:29:40 +1000 Subject: pull up maps for arbitrary locations --- ao-tools/altosui/AltosSiteMap.java | 54 +++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 6f33aabd..420bfc81 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -40,7 +40,8 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { Graphics2D g2d; - private void setLocation(double new_lat, double new_lng, int new_zoom) { + private void setLocation(double new_lat, double new_lng) { + int new_zoom = 15; lat = new_lat; lng = new_lng; zoom = new_zoom; @@ -50,6 +51,17 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { coord_pt.x = 320-coord_pt.x; coord_pt.y = 320-coord_pt.y; last_pt = null; + + try { + File pngfile = new File(AltosPreferences.logdir(), + FileCoord(lat, lng, zoom)); + System.out.printf("Trying file %s\n", pngfile); + BufferedImage myPicture = ImageIO.read(pngfile); + picLabel.setIcon(new ImageIcon( myPicture )); + g2d = myPicture.createGraphics(); + } catch (Exception e) { + throw new RuntimeException(e); + }; } private static double limit(double v, double lo, double hi) { @@ -60,6 +72,16 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { return v; } + private static String FileCoord(double lat, double lng, int zoom) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return String.format("map-%c%.3f,%c%.3f-%d.png", + chlat, lat, chlng, lng, zoom); + } + + // based on google js // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js // search for fromLatLngToPoint and fromPointToLatLng @@ -95,8 +117,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { }; public void show(AltosState state, int crc_errors) { - if (!state.gps_ready) + if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) return; + double plat = (int)(state.pad_lat*200)/200.0; + double plon = (int)(state.pad_lon*200)/200.0; + + if (last_pt == null) { + setLocation(plat, plon); + } + Point2D.Double pt = pt(state.gps.lat, state.gps.lon); if (last_pt != null && pt != last_pt) { if (0 <= state.state && state.state < stateColors.length) { @@ -107,31 +136,24 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { last_pt = pt; repaint(); } - + + JLabel picLabel = new JLabel(); + public AltosSiteMap() { GridBagLayout layout = new GridBagLayout(); setLayout(layout); GridBagConstraints c = new GridBagConstraints(); - setLocation(-27.850, 152.960, 15); - String pngfile = "/home/aj/qrs-S27.850,W152.960-15.png"; - c.gridx = 0; c.gridy = 0; c.weightx = 1; c.weighty = 1; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; + picLabel = new JLabel(); + JScrollPane scrollPane = new JScrollPane(picLabel); + layout.setConstraints(scrollPane, c); + add(scrollPane); - try { - BufferedImage myPicture = ImageIO.read(new File(pngfile)); - g2d = myPicture.createGraphics(); - JLabel picLabel = new JLabel(new ImageIcon( myPicture )); - JScrollPane scrollPane = new JScrollPane(picLabel); - layout.setConstraints(scrollPane, c); - add(scrollPane); - } catch (Exception e) { - throw new RuntimeException(e); - }; } } -- cgit v1.2.3 From 991541f57f065f429c6ec425efd6ac731280b2c1 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 12 Nov 2010 23:42:42 +1000 Subject: better error behaviour if no map --- ao-tools/altosui/AltosSiteMap.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 420bfc81..1fb70b35 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -40,7 +40,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { Graphics2D g2d; - private void setLocation(double new_lat, double new_lng) { + private boolean setLocation(double new_lat, double new_lng) { int new_zoom = 15; lat = new_lat; lng = new_lng; @@ -60,8 +60,10 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { picLabel.setIcon(new ImageIcon( myPicture )); g2d = myPicture.createGraphics(); } catch (Exception e) { - throw new RuntimeException(e); - }; + // throw new RuntimeException(e); + return false; + } + return true; } private static double limit(double v, double lo, double hi) { @@ -116,14 +118,20 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { Color.BLACK // landed }; + boolean nomaps = false; public void show(AltosState state, int crc_errors) { + if (nomaps) + return; if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) return; double plat = (int)(state.pad_lat*200)/200.0; double plon = (int)(state.pad_lon*200)/200.0; if (last_pt == null) { - setLocation(plat, plon); + if (!setLocation(plat, plon)) { + nomaps = true; + return; + } } Point2D.Double pt = pt(state.gps.lat, state.gps.lon); -- cgit v1.2.3 From 7def9dd0d0a4ce9cf7c65de573100e664f278717 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 12 Nov 2010 10:58:54 -0700 Subject: first cut at instructions on how to re-flash TM and TD devices based on email reply to a user who asked --- doc/telemetrum-doc.xsl | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index b7963aec..ff8cd755 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -761,6 +761,54 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. + + Updating Device Firmware + <para> + The big conceptual thing to realize is that you have to use a + TeleDongle as a programmer to update a TeleMetrum, and vice versa. + Due to limited memory resources in the cc1111, we don't support + programming a unit directly over USB. + </para> + <para> + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. Take the 2 + screws out of the TeleDongle case to get access to the circuit + board. Plug the 8-pin end of the programming cable to the + matching connector on the TeleDongle, and the 4-pin end to the + matching connector on the TeleMetrum. Plug the TeleDongle into + your computer's USB port, power up the TeleMetrum, then run + altosui. Using the File/Flash menu, pick the TeleDongle as the + programming device, and the image you want put on the TeleMetrum, + and it should flash the TeleMetrum with new firmware. + </para> + <para> + Confirm that the TeleMetrum board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. + </para> + <para> + To update the TeleDongle's firmware, you switch things around. Put + the 8-pin end of the programming cable on the TeleMetrum board's + (locking) 8-pin connector, put the 4-pin end on the TeleDongle + board, plug both into USB (the TeleDongle needs power, the + TeleMetrum is now the programmer). Use the altosui interface to + pick the TeleMetrum as the programmer and a suitable image for + the TeleDongle, and it should program ok. You can verify the + TeleDongle programmed correctly by using a terminal program to + talk to it and using the 'v' command, etc. Once you're happy, + put the cover back on the TeleDongle. + </para> + <para> + Be careful removing the programming cable from the locking 8-pin + connector on TeleMetrum. You'll need a fingernail or perhaps a thin + screwdriver or knife blade to gently pry the locking ears out + slightly to extract the connector. We used a locking connector on + TeleMetrum to help ensure that the cabling to companion boards + used in a rocket don't ever come loose accidentally in flight. + </para> + </chapter> <chapter> <title>Using Altus Metrum Products
-- cgit v1.2.3 From f1118717780a81f9257d2eed7828b66538deb8a8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 12 Nov 2010 17:32:21 -0700 Subject: fold in content from Keith's email on the re-flashing subject --- doc/telemetrum-doc.xsl | 1336 ++++++++++++++++++++++++++---------------------- 1 file changed, 726 insertions(+), 610 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index ff8cd755..67831fe2 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -27,6 +27,13 @@ + + 0.3 + 12 November 2010 + + Add instructions for re-flashing devices using AltosUI + + 0.2 18 July 2010 @@ -118,12 +125,12 @@ When you have successfully installed the software suite (either from compiled source code or as the pre-built Debian package) you will have 10 or so executable programs all of which have names beginning - with 'ao-'. + with 'ao-'. ('ao-view' is the lone GUI-based program, the rest are command-line oriented.) You will also have man pages, that give you basic info - on each program. + on each program. You will also get this documentation in two file types in the doc/ -directory, telemetrum-doc.pdf and telemetrum-doc.html. + directory, telemetrum-doc.pdf and telemetrum-doc.html. Finally you will have a couple control files that allow the ao-view GUI-based program to appear in your menu of programs (under the 'Internet' category). @@ -133,7 +140,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. with using USB ports. The first thing you should try after getting both units plugged into to your computer's usb port(s) is to run 'ao-list' from a terminal-window to see what port-device-name each - device has been assigned by the operating system. + device has been assigned by the operating system. You will need this information to access the devices via their respective on-board firmware and data using other command line programs in the AltOS software suite. @@ -158,7 +165,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. Both TeleMetrum and TeleDongle share the concept of a two level command set in their firmware. - The first layer has several single letter commands. Once + The first layer has several single letter commands. Once you are using 'cu' (or 'cutecom') sending (typing) a '?' returns a full list of these commands. The second level are configuration sub-commands accessed @@ -177,7 +184,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. use 'N0CALL' which is cute, but not exactly legal! Spend a few minutes getting comfortable with the units, their firmware, and 'cu' (or possibly 'cutecom'). - For instance, try to send + For instance, try to send (type) a 'c r 2' and verify the channel change by sending a 'c s'. Verify you can connect and disconnect from the units while in your terminal program by sending the escape-disconnect mentioned above. @@ -250,7 +257,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. As for ao-view.... some things are in the menu but don't do anything very useful. The developers have stopped working on ao-view to focus on a new, cross-platform ground station program. So ao-view may or - may not be updated in the future. Mostly you just use + may not be updated in the future. Mostly you just use the Log and Device menus. It has a wonderful display of the incoming flight data and I am sure you will enjoy what it has to say to you once you enable the voice output! @@ -299,659 +306,768 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. Live telemetry is written to file(s) whenever 'ao-view' is connected to the TeleDongle. The file area defaults to ~/altos but is easily changed using the menus in 'ao-view'. The files that - are written end in '.telem'. The after-flight + are written end in '.telem'. The after-flight data-dumped files will end in .eeprom and represent continuous data unlike the rf-linked .telem files that are subject to the turnarounds/data-packaging time slots in the half-duplex rf data path. See the above instructions on what and how to save the eeprom stored data after physically retrieving your TeleMetrum. Make sure to save - the on-board data after each flight, as the current firmware will - over-write any previous flight data during a new flight. + the on-board data after each flight, as the current firmware will + over-write any previous flight data during a new flight. + +
+
+ + Specifications + + + + Recording altimeter for model rocketry. - - - - Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - - - - Handling Precautions + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + + + + Handling Precautions + + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe with a + see-through plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to + "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + + Hardware Overview + + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. + + + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide and so may be the most familiar option. + You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. + + + + Operation +
+ Firmware Modes + + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. + + + At power on, you will hear three beeps + ("S" in Morse code for startup) and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. + - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. + In flight or "pad" mode, TeleMetrum turns on the GPS system, + engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. - The Lithium Polymer rechargeable batteries used with TeleMetrum have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. - The TeleMetrum barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe with a - see-through plastic payload bay. + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! +
+
+ GPS - The TeleMetrum barometric sensor sampling port must be able to - "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! - As with all other rocketry electronics, TeleMetrum must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. - - - Hardware Overview +
+
+ Ground Testing - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! - A typical TeleMetrum installation using the on-board GPS antenna and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. +
+
+ Radio Link - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar option. - You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we had to decide how to manage the + link. - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + + We don't use a 'normal packet radio' mode because they're just too + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had flights to above 21k feet AGL with good reception, and calculations + suggest we should be good to well over 40k feet AGL with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights! + +
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. - - - Operation
- Firmware Modes - - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. - - - At power on, you will hear three beeps - ("S" in Morse code for startup) and then a pause while - TeleMetrum completes initialization and self tests, and decides which - mode to enter next. - - - In flight or "pad" mode, TeleMetrum turns on the GPS system, - engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when TeleMetrum is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! + Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip on + your TeleMetrum board if you want the change to stay in place across reboots.
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. + Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + Please note that the TeleMetrum apogee detection algorithm always + fires a fraction of a second *after* apogee. If you are also flying + an altimeter like the PerfectFlite MAWD, which only supports selecting + 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 + seconds delay and set the TeleMetrum to fire your backup 2 or 3 + seconds later to avoid any chance of both charges firing + simultaneously. We've flown several airframes this way quite happily, + including Keith's successful L3 cert.
- Ground Testing + Main Deployment Altitude - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. + To set the main deployment altitude, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+
+ Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip.
- Radio Link - - The chip our boards are based on incorporates an RF transceiver, but - it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we had to decide how to manage the - link. - - - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which - allows us to use the RF link to configure the rocket, do things like - ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only - transmits and doesn't listen at all. That's because we want to put - ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract - data later... - - - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a - Gaussian filter before they go into the modulator to limit the - transmitted bandwidth. When combined with the hardware forward error - correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had flights to above 21k feet AGL with good reception, and calculations - suggest we should be good to well over 40k feet AGL with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! + Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor.
+
+
+ + Updating Device Firmware + + The big conceptual thing to realize is that you have to use a + TeleDongle as a programmer to update a TeleMetrum, and vice versa. + Due to limited memory resources in the cc1111, we don't support + programming either unit directly over USB. + + + You may wish to begin by ensuring you have current firmware images. + These are distributed as part of the AltOS software bundle that + also includes the AltosUI ground station program. Newer ground + station versions typically work fine with older firmware versions, + so you don't need to update your devices just to try out new + software features. You can always download the most recent + version from http://www.altusmetrum.org/AltOS/. + + + We recommend updating TeleMetrum first, before updating TeleDongle. + +
+ Updating TeleMetrum Firmware + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the + matching connector on the TeleDongle, and the 4-pin end to the + matching connector on the TeleMetrum. + + + Attach a battery to the TeleMetrum board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMetrum, which should have a + name in the form telemetrum-v1.0-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMetrum with new firmware, showing a progress bar. + + + Confirm that the TeleMetrum board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. + + + If something goes wrong, give it another try. + + +
+
+ Updating TeleDongle Firmware + + Updating TeleDongle's firmware is just like updating TeleMetrum + firmware, but you switch which board is the programmer and which + is the programming target. + + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Find the USB cable that you got as part of the starter kit, and + plug the "mini" end in to the mating connector on TeleMetrum. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the (latching) + matching connector on the TeleMetrum, and the 4-pin end to the + matching connector on the TeleDongle. + + + Attach a battery to the TeleMetrum board. + + + Plug both TeleMetrum and TeleDongle into your computer's USB + ports, and power up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleMongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleDongle, which should have a + name in the form teledongle-v0.2-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. The TeleDongle + serial number is on the "bottom" of the circuit board, and can + usually be read through the translucent blue plastic case without + needing to remove the board from the case. + + + Hit the 'OK' button and the software should proceed to flash + the TeleDongle with new firmware, showing a progress bar. + + + Confirm that the TeleDongle board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. Once you're happy, remove the programming cable + and put the cover back on the TeleDongle. + + + If something goes wrong, give it another try. + + + + Be careful removing the programming cable from the locking 8-pin + connector on TeleMetrum. You'll need a fingernail or perhaps a thin + screwdriver or knife blade to gently pry the locking ears out + slightly to extract the connector. We used a locking connector on + TeleMetrum to help ensure that the cabling to companion boards + used in a rocket don't ever come loose accidentally in flight. + +
+
+ + Using Altus Metrum Products +
+ Being Legal + + First off, in the US, you need an [amateur radio license](../Radio) or + other authorization to legally operate the radio transmitters that are part + of our products. +
- Configurable Parameters - - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. - -
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip on - your TeleMetrum board if you want the change to stay in place across reboots. - -
-
- Apogee Delay - - Apogee delay is the number of seconds after TeleMetrum detects flight - apogee that the drogue charge should be fired. In most cases, this - should be left at the default of 0. However, if you are flying - redundant electronics such as for an L3 certification, you may wish - to set one of your altimeters to a positive delay so that both - primary and backup pyrotechnic charges do not fire simultaneously. - - - To set the apogee delay, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - Please note that the TeleMetrum apogee detection algorithm always - fires a fraction of a second *after* apogee. If you are also flying - an altimeter like the PerfectFlite MAWD, which only supports selecting - 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 - seconds delay and set the TeleMetrum to fire your backup 2 or 3 - seconds later to avoid any chance of both charges firing - simultaneously. We've flown several airframes this way quite happily, - including Keith's successful L3 cert. - -
-
- Main Deployment Altitude - - By default, TeleMetrum will fire the main deployment charge at an - elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this - to suit. In particular, if you are flying two altimeters, you may - wish to set the - deployment elevation for the backup altimeter to be something lower - than the primary so that both pyrotechnic charges don't fire - simultaneously. - - - To set the main deployment altitude, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
+ In the Rocket + + In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. +
- Calibration - - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. - -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 Mhz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Accelerometer - - The accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - -
+ On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our [TeleDongle](../TeleDongle) units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + Right now, all of our application software is written for Linux. However, + because we understand that many people run Windows or MacOS, we are working + on a new ground station program written in Java that should work on all + operating systems. + + + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the Yaesu VX-7R at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT. +
- - - Updating Device Firmware - <para> - The big conceptual thing to realize is that you have to use a - TeleDongle as a programmer to update a TeleMetrum, and vice versa. - Due to limited memory resources in the cc1111, we don't support - programming a unit directly over USB. - </para> - <para> - Find the 'programming cable' that you got as part of the starter - kit, that has a red 8-pin MicroMaTch connector on one end and a - red 4-pin MicroMaTch connector on the other end. Take the 2 - screws out of the TeleDongle case to get access to the circuit - board. Plug the 8-pin end of the programming cable to the - matching connector on the TeleDongle, and the 4-pin end to the - matching connector on the TeleMetrum. Plug the TeleDongle into - your computer's USB port, power up the TeleMetrum, then run - altosui. Using the File/Flash menu, pick the TeleDongle as the - programming device, and the image you want put on the TeleMetrum, - and it should flash the TeleMetrum with new firmware. - </para> - <para> - Confirm that the TeleMetrum board seems to have updated ok, which you - can do by plugging in to it over USB and using a terminal program - to connect to the board and issue the 'v' command to check - the version, etc. - </para> - <para> - To update the TeleDongle's firmware, you switch things around. Put - the 8-pin end of the programming cable on the TeleMetrum board's - (locking) 8-pin connector, put the 4-pin end on the TeleDongle - board, plug both into USB (the TeleDongle needs power, the - TeleMetrum is now the programmer). Use the altosui interface to - pick the TeleMetrum as the programmer and a suitable image for - the TeleDongle, and it should program ok. You can verify the - TeleDongle programmed correctly by using a terminal program to - talk to it and using the 'v' command, etc. Once you're happy, - put the cover back on the TeleDongle. - </para> - <para> - Be careful removing the programming cable from the locking 8-pin - connector on TeleMetrum. You'll need a fingernail or perhaps a thin - screwdriver or knife blade to gently pry the locking ears out - slightly to extract the connector. We used a locking connector on - TeleMetrum to help ensure that the cabling to companion boards - used in a rocket don't ever come loose accidentally in flight. - </para> - </chapter> - <chapter> - <title>Using Altus Metrum Products
- Being Legal - - First off, in the US, you need an [amateur radio license](../Radio) or - other authorization to legally operate the radio transmitters that are part - of our products. - -
- In the Rocket - - In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. - - - By default, we ship TeleMetrum with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, - which is opaque to RF signals, you may choose to have an SMA connector - installed so that you can run a coaxial cable to an antenna mounted - elsewhere in the rocket. - -
-
- On the Ground - - To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our [TeleDongle](../TeleDongle) units. The - TeleDongle in turn plugs directly into the USB port on a notebook - computer. Because TeleDongle looks like a simple serial port, your computer - does not require special device drivers... just plug it in. - - - Right now, all of our application software is written for Linux. However, - because we understand that many people run Windows or MacOS, we are working - on a new ground station program written in Java that should work on all - operating systems. - - - After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the - TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo - battery, so you'll want one of those anyway... the same cable used by lots - of digital cameras and other modern electronic stuff will work fine. - - - If your rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket - position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. - - - You may also enjoy having a ham radio "HT" that covers the 70cm band... you - can use that with your antenna to direction-find the rocket on the ground - the same way you can use a Walston or Beeline tracker. This can be handy - if the rocket is hiding in sage brush or a tree, or if the last GPS position - doesn't get you close enough because the rocket dropped into a canyon, or - the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-7R at launches. - - - So, to recap, on the ground the hardware you'll need includes: - - - an antenna and feedline - - - a TeleDongle - - - a notebook computer - - - optionally, a handheld GPS receiver - - - optionally, an HT or receiver covering 435 Mhz - - - - - The best hand-held commercial directional antennas we've found for radio - direction finding rockets are from - - Arrow Antennas. - - The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. - -
-
- Data Analysis - - Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum - board. Once this data is on your computer, our postflight tools make it - easy to quickly get to the numbers everyone wants, like apogee altitude, - max acceleration, and max velocity. You can also generate and view a - standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file - useable with Google Maps and Google Earth for visualizing the flight path - in two or three dimensions! - - - Our ultimate goal is to emit a set of files for each flight that can be - published as a web page per flight, or just viewed on your local disk with - a web browser. - -
-
- Future Plans - - In the future, we intend to offer "companion boards" for the rocket that will - plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. - - - We are also working on the design of a hand-held ground terminal that will - allow monitoring the rocket's status, collecting data during flight, and - logging data after flight without the need for a notebook computer on the - flight line. Particularly since it is so difficult to read most notebook - screens in direct sunlight, we think this will be a great thing to have. - - - Because all of our work is open, both the hardware designs and the software, - if you have some great idea for an addition to the current Altus Metrum family, - feel free to dive in and help! Or let us know what you'd like to see that - we aren't already working on, and maybe we'll get excited about it too... - -
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. +
- - How GPS Works - + Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + - Placeholder. + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too...
-
- - +
+
+ + How GPS Works + + + Placeholder. + +
+
+ + -- cgit v1.2.3 From a6f30fae906bd87dff192c5fd4d10df283f99930 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Nov 2010 17:02:22 -0800 Subject: altosui: Add RF calibration to TeleMetrum config dialog I think that's the last user-settable value. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 6 ++++++ ao-tools/altosui/AltosConfigUI.java | 43 ++++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 7fecff0e..b7474f3b 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -83,6 +83,7 @@ public class AltosConfig implements Runnable, ActionListener { int_ref main_deploy; int_ref apogee_delay; int_ref radio_channel; + int_ref radio_calibration; string_ref version; string_ref product; string_ref callsign; @@ -146,6 +147,7 @@ public class AltosConfig implements Runnable, ActionListener { get_int(line, "Main deploy:", main_deploy); get_int(line, "Apogee delay:", apogee_delay); get_int(line, "Radio channel:", radio_channel); + get_int(line, "Radio cal:", radio_calibration); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -175,6 +177,7 @@ public class AltosConfig implements Runnable, ActionListener { config_ui.set_main_deploy(main_deploy.get()); config_ui.set_apogee_delay(apogee_delay.get()); config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); } catch (InterruptedException ie) { @@ -188,12 +191,14 @@ public class AltosConfig implements Runnable, ActionListener { main_deploy.set(config_ui.main_deploy()); apogee_delay.set(config_ui.apogee_delay()); radio_channel.set(config_ui.radio_channel()); + radio_calibration.set(config_ui.radio_calibration()); callsign.set(config_ui.callsign()); try { start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); serial_line.printf("c r %d\n", radio_channel.get()); + serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.printf("c c %s\n", callsign.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { @@ -234,6 +239,7 @@ public class AltosConfig implements Runnable, ActionListener { main_deploy = new int_ref(250); apogee_delay = new int_ref(0); radio_channel = new int_ref(0); + radio_calibration = new int_ref(1186611); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index 605ccc8b..37128573 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -57,6 +57,7 @@ public class AltosConfigUI JLabel main_deploy_label; JLabel apogee_delay_label; JLabel radio_channel_label; + JLabel radio_calibration_label; JLabel callsign_label; public boolean dirty; @@ -68,6 +69,7 @@ public class AltosConfigUI JComboBox main_deploy_value; JComboBox apogee_delay_value; JComboBox radio_channel_value; + JTextField radio_calibration_value; JTextField callsign_value; JButton save; @@ -256,7 +258,7 @@ public class AltosConfigUI radio_channel_value.addItemListener(this); pane.add(radio_channel_value, c); - /* Callsign */ + /* Radio Calibration */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 6; c.gridwidth = 3; @@ -264,11 +266,34 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = il; c.ipady = 5; + radio_calibration_label = new JLabel("RF Calibration:"); + pane.add(radio_calibration_label, c); + + c = new GridBagConstraints(); + c.gridx = 3; c.gridy = 6; + 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(String.format("%d", 1186611)); + radio_calibration_value.getDocument().addDocumentListener(this); + pane.add(radio_calibration_value, c); + + /* Callsign */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 7; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; callsign_label = new JLabel("Callsign:"); pane.add(callsign_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 6; + c.gridx = 3; c.gridy = 7; c.gridwidth = 3; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -281,7 +306,7 @@ public class AltosConfigUI /* Buttons */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 7; + c.gridx = 0; c.gridy = 8; c.gridwidth = 6; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -292,7 +317,7 @@ public class AltosConfigUI save.setActionCommand("save"); c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 7; + c.gridx = 0; c.gridy = 8; c.gridwidth = 6; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -303,7 +328,7 @@ public class AltosConfigUI reset.setActionCommand("reset"); c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 7; + c.gridx = 0; c.gridy = 8; c.gridwidth = 6; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -415,6 +440,14 @@ public class AltosConfigUI return radio_channel_value.getSelectedIndex(); } + public void set_radio_calibration(int new_radio_calibration) { + radio_calibration_value.setText(String.format("%d", new_radio_calibration)); + } + + public int radio_calibration() { + return Integer.parseInt(radio_calibration_value.getText()); + } + public void set_callsign(String new_callsign) { callsign_value.setText(new_callsign); } -- cgit v1.2.3 From 1e7e02987276847274493312202d22222c953149 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 14 Nov 2010 00:57:45 +1000 Subject: AltosTelemetryReader: actually open serial port --- ao-tools/altosui/AltosTelemetryReader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index 0b5509eb..03e694f8 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -58,5 +58,6 @@ class AltosTelemetryReader extends AltosFlightReader { telem = new LinkedBlockingQueue(); serial.add_monitor(telem); + serial.open(device); } } -- cgit v1.2.3 From e68fe9454352087889c560d95797922493117acb Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 14 Nov 2010 00:59:01 +1000 Subject: AltosSiteMap: add targeting circles around landing site --- ao-tools/altosui/AltosSiteMap.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 1fb70b35..25b77792 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -118,6 +118,7 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { Color.BLACK // landed }; + boolean drawn_landed_circle = false; boolean nomaps = false; public void show(AltosState state, int crc_errors) { if (nomaps) @@ -141,6 +142,15 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { } g2d.draw(new Line2D.Double(last_pt, pt)); } + + if (state.state == 8 && !drawn_landed_circle) { + drawn_landed_circle = true; + g2d.setColor(Color.RED); + g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + last_pt = pt; repaint(); } -- cgit v1.2.3 From 566c6486c8815ae241e0b116a93b1a0ff4783831 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 13 Nov 2010 12:19:12 -0700 Subject: continuing to work on the docs --- doc/telemetrum-doc.xsl | 72 ++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 67831fe2..1bcd8632 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -72,8 +72,8 @@ More products will be added to the Altus Metrum family over time, and - we currently envision that this will be a single, comprehensive manual - for the entire product family. + we currently envision that this will evolve to be be the single, + comprehensive manual for the entire product family. @@ -88,52 +88,39 @@ The first thing to do after you check the inventory of parts in your "starter kit" is to charge the battery by plugging it into the - corresponding socket of the TeleMetrum and then using the USB A to B - cable to plug the Telemetrum into your computer's USB socket. The + corresponding socket of the TeleMetrum and then using the USB A to mini + B cable to plug the Telemetrum into your computer's USB socket. The TeleMetrum circuitry will charge the battery whenever it is plugged - into the usb socket. The TeleMetrum's on-off switch does NOT control - the charging circuitry. When the GPS chip is initially searching for - satellites, the unit will pull more current than it can pull from the - usb port, so the battery must be plugged in order to get a good - satellite lock. Once GPS is locked the current consumption goes back + in, because the TeleMetrum's on-off switch does NOT control the + charging circuitry. When the GPS chip is initially searching for + satellites, TeleMetrum will consume more current than it can pull + from the usb port, so the battery must be attached in order to get + satellite lock. Once GPS is locked, the current consumption goes back down enough to enable charging while running. So it's a good idea to fully charge the battery as your first item of business so there is no issue getting and maintaining satellite lock. The yellow charge indicator led will go out when the - battery is nearly full and the charger goes to trickle charge. + battery is nearly full and the charger goes to trickle charge. It + can take several hours to fully recharge a deeply discharged battery. - The other active device in the starter kit is the half-duplex TeleDongle - rf link. If you plug it in to your computer it should "just work", - showing up as a serial port device. If you are using Linux and are + The other active device in the starter kit is the TeleDongle USB to + RF interface. If you plug it in to your Mac or Linux computer it should + "just work", showing up as a serial port device. Windows systems need + driver information that is part of the AltOS download to know that the + existing USB modem driver will work. If you are using Linux and are having problems, try moving to a fresher kernel (2.6.33 or newer), as - there were some ugly USB serial driver bugs in earlier versions. + the USB serial driver had ugly bugs in some earlier versions. - Next you should obtain and install the AltOS utilities. The first - generation sofware was written for Linux only. New software is coming - soon that will also run on Windows and Mac. For now, we'll concentrate - on Linux. If you are using Debian, an 'altos' package already exists, - see http://altusmetrum.org/AltOS for details on how to install it. - User-contributed directions for building packages on ArchLinux may be - found in the contrib/arch-linux directory as PKGBUILD files. - Between the debian/rules file and the PKGBUILD files in - contrib, you should find enough information to learn how to build the - software for any other version of Linux. - - - When you have successfully installed the software suite (either from - compiled source code or as the pre-built Debian package) you will - have 10 or so executable programs all of which have names beginning - with 'ao-'. - ('ao-view' is the lone GUI-based program, the rest are command-line - oriented.) You will also have man pages, that give you basic info - on each program. - You will also get this documentation in two file types in the doc/ - directory, telemetrum-doc.pdf and telemetrum-doc.html. - Finally you will have a couple control files that allow the ao-view - GUI-based program to appear in your menu of programs (under - the 'Internet' category). + Next you should obtain and install the AltOS utilities. These include + the AltosUI ground station program, current firmware images for + TeleMetrum and TeleDongle, and a number of standalone utilities that + are rarely needed. Pre-built binary packages are available for Debian + Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode + and build instructions for some other Linux variants are also available. + The latest version may always be downloaded from + http://altusmetrum.org/AltOS. Both Telemetrum and TeleDongle can be directly communicated @@ -796,7 +783,6 @@ kit, that has a red 8-pin MicroMaTch connector on one end and a red 4-pin MicroMaTch connector on the other end. - Take the 2 screws out of the TeleDongle case to get access to the circuit board. @@ -805,6 +791,9 @@ Plug the 8-pin end of the programming cable to the matching connector on the TeleDongle, and the 4-pin end to the matching connector on the TeleMetrum. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. Attach a battery to the TeleMetrum board. @@ -871,6 +860,9 @@ Plug the 8-pin end of the programming cable to the (latching) matching connector on the TeleMetrum, and the 4-pin end to the matching connector on the TeleDongle. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. Attach a battery to the TeleMetrum board. @@ -883,7 +875,7 @@ Run AltosUI, and select 'Flash Image' from the File menu. - Pick the TeleMongle device from the list, identifying it as the + Pick the TeleMetrum device from the list, identifying it as the programming device. -- cgit v1.2.3 From 8463ffcaca6bcd31e645aba71c171f548dce96d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Nov 2010 15:19:14 -0800 Subject: altosui: Eliminate unncessary import altosui lines Java appears to automatically import every module from the current package. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSVUI.java | 3 --- ao-tools/altosui/AltosConfig.java | 14 -------------- ao-tools/altosui/AltosConfigUI.java | 13 ------------- ao-tools/altosui/AltosDataPointReader.java | 5 ----- ao-tools/altosui/AltosDebug.java | 2 -- ao-tools/altosui/AltosDeviceDialog.java | 1 - ao-tools/altosui/AltosEepromDownload.java | 12 ------------ ao-tools/altosui/AltosEepromIterable.java | 8 -------- ao-tools/altosui/AltosEepromMonitor.java | 10 ---------- ao-tools/altosui/AltosEepromRecord.java | 11 ----------- ao-tools/altosui/AltosFile.java | 2 -- ao-tools/altosui/AltosFlash.java | 2 -- ao-tools/altosui/AltosFlashUI.java | 3 --- ao-tools/altosui/AltosGPS.java | 2 -- ao-tools/altosui/AltosGraph.java | 2 -- ao-tools/altosui/AltosGraphDataChooser.java | 5 ----- ao-tools/altosui/AltosGraphTime.java | 3 --- ao-tools/altosui/AltosGraphUI.java | 3 --- ao-tools/altosui/AltosGreatCircle.java | 2 -- ao-tools/altosui/AltosInfoTable.java | 3 --- ao-tools/altosui/AltosLog.java | 3 --- ao-tools/altosui/AltosParse.java | 2 -- ao-tools/altosui/AltosReader.java | 2 -- ao-tools/altosui/AltosRecord.java | 2 -- ao-tools/altosui/AltosRecordIterable.java | 8 -------- ao-tools/altosui/AltosRomconfig.java | 1 - ao-tools/altosui/AltosRomconfigUI.java | 2 -- ao-tools/altosui/AltosSerial.java | 9 ++------- ao-tools/altosui/AltosState.java | 3 --- ao-tools/altosui/AltosStatusTable.java | 3 --- ao-tools/altosui/AltosTelemetry.java | 4 ---- ao-tools/altosui/AltosTelemetryIterable.java | 1 - ao-tools/altosui/AltosUI.java | 19 ------------------- 33 files changed, 2 insertions(+), 163 deletions(-) diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java index eb620ba8..16f25338 100644 --- a/ao-tools/altosui/AltosCSVUI.java +++ b/ao-tools/altosui/AltosCSVUI.java @@ -28,9 +28,6 @@ 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 diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index b7474f3b..30f7d541 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -28,20 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.Altos; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosFlightStatusTableModel; -import altosui.AltosFlightInfoTableModel; -import altosui.AltosConfigUI; - import libaltosJNI.*; public class AltosConfig implements Runnable, ActionListener { diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index 37128573..9e3856b0 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -29,19 +29,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.Altos; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosFlightStatusTableModel; -import altosui.AltosFlightInfoTableModel; - import libaltosJNI.*; public class AltosConfigUI diff --git a/ao-tools/altosui/AltosDataPointReader.java b/ao-tools/altosui/AltosDataPointReader.java index 4d7831e4..7704310b 100644 --- a/ao-tools/altosui/AltosDataPointReader.java +++ b/ao-tools/altosui/AltosDataPointReader.java @@ -10,11 +10,6 @@ import java.lang.UnsupportedOperationException; import java.util.NoSuchElementException; import java.util.Iterator; -import altosui.AltosDataPoint; -import altosui.AltosRecordIterable; -import altosui.AltosRecord; -import altosui.AltosState; - class AltosDataPointReader implements Iterable { Iterator iter; AltosState state; diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 3f469d48..9c10129d 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -22,8 +22,6 @@ 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 { diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java index ec78e288..2966ad1e 100644 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ b/ao-tools/altosui/AltosDeviceDialog.java @@ -26,7 +26,6 @@ import libaltosJNI.libaltos; import libaltosJNI.altos_device; import libaltosJNI.SWIGTYPE_p_altos_file; import libaltosJNI.SWIGTYPE_p_altos_list; -import altosui.AltosDevice; public class AltosDeviceDialog extends JDialog implements ActionListener { diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 8efc94d2..bd9e4b48 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -28,18 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.Altos; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - import libaltosJNI.*; public class AltosEepromDownload implements Runnable { diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java index 2f1e7e90..fc683321 100644 --- a/ao-tools/altosui/AltosEepromIterable.java +++ b/ao-tools/altosui/AltosEepromIterable.java @@ -28,14 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosRecord; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - /* * AltosRecords with an index field so they can be sorted by tick while preserving * the original ordering for elements with matching ticks diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java index b88fdd29..7ff00ead 100644 --- a/ao-tools/altosui/AltosEepromMonitor.java +++ b/ao-tools/altosui/AltosEepromMonitor.java @@ -28,16 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; - public class AltosEepromMonitor extends JDialog { Container pane; diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java index 95cbe015..5a673817 100644 --- a/ao-tools/altosui/AltosEepromRecord.java +++ b/ao-tools/altosui/AltosEepromRecord.java @@ -28,17 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - public class AltosEepromRecord { public int cmd; public int tick; diff --git a/ao-tools/altosui/AltosFile.java b/ao-tools/altosui/AltosFile.java index 7f65381f..06360572 100644 --- a/ao-tools/altosui/AltosFile.java +++ b/ao-tools/altosui/AltosFile.java @@ -20,8 +20,6 @@ package altosui; import java.lang.*; import java.io.File; import java.util.*; -import altosui.AltosTelemetry; -import altosui.AltosPreferences; class AltosFile extends File { diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index a3e431cd..25b4a06e 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -28,8 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosHexfile; - public class AltosFlash { File file; FileInputStream input; diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 86f57a5f..70c8c549 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -28,9 +28,6 @@ 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 diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java index acb6fb2c..83821842 100644 --- a/ao-tools/altosui/AltosGPS.java +++ b/ao-tools/altosui/AltosGPS.java @@ -19,8 +19,6 @@ package altosui; import java.lang.*; import java.text.*; -import altosui.AltosParse; - public class AltosGPS { public class AltosGPSSat { diff --git a/ao-tools/altosui/AltosGraph.java b/ao-tools/altosui/AltosGraph.java index fa3b87c1..58c27979 100644 --- a/ao-tools/altosui/AltosGraph.java +++ b/ao-tools/altosui/AltosGraph.java @@ -9,8 +9,6 @@ import java.io.*; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartUtilities; -import altosui.AltosDataPoint; - abstract class AltosGraph { public String filename; public abstract void addData(AltosDataPoint d); diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java index caa14118..d128f4d5 100644 --- a/ao-tools/altosui/AltosGraphDataChooser.java +++ b/ao-tools/altosui/AltosGraphDataChooser.java @@ -27,11 +27,6 @@ import java.util.*; import java.text.*; import java.util.prefs.*; -import altosui.AltosPreferences; -import altosui.AltosDataPointReader; -import altosui.AltosEepromIterable; -import altosui.AltosTelemetryIterable; - public class AltosGraphDataChooser extends JFileChooser { JFrame frame; String filename; diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java index ab01b888..a5451280 100644 --- a/ao-tools/altosui/AltosGraphTime.java +++ b/ao-tools/altosui/AltosGraphTime.java @@ -24,9 +24,6 @@ import org.jfree.data.xy.XYSeriesCollection; import org.jfree.ui.RectangleAnchor; import org.jfree.ui.TextAnchor; -import altosui.AltosDataPoint; -import altosui.AltosGraph; - class AltosGraphTime extends AltosGraph { static interface Element { void attachGraph(AltosGraphTime g); diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java index 25643c76..908aa3b4 100644 --- a/ao-tools/altosui/AltosGraphUI.java +++ b/ao-tools/altosui/AltosGraphUI.java @@ -17,9 +17,6 @@ import org.jfree.chart.axis.AxisLocation; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RefineryUtilities; -import altosui.AltosDataPoint; -import altosui.AltosGraphTime; - public class AltosGraphUI extends JFrame { static final private Color red = new Color(194,31,31); diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java index aa6ae3b9..fb1b6ab3 100644 --- a/ao-tools/altosui/AltosGreatCircle.java +++ b/ao-tools/altosui/AltosGreatCircle.java @@ -17,8 +17,6 @@ package altosui; -import altosui.AltosGPS; - import java.lang.Math; public class AltosGreatCircle { diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java index 2f326e07..28924410 100644 --- a/ao-tools/altosui/AltosInfoTable.java +++ b/ao-tools/altosui/AltosInfoTable.java @@ -28,9 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosFlightInfoTableModel; -import altosui.AltosState; - public class AltosInfoTable { private Box box; private JTable table[]; diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index fed96c28..137147d5 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -22,9 +22,6 @@ import java.lang.*; import java.util.*; import java.text.ParseException; 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 diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java index 4d82de78..fbfcaaee 100644 --- a/ao-tools/altosui/AltosParse.java +++ b/ao-tools/altosui/AltosParse.java @@ -20,8 +20,6 @@ package altosui; import java.text.*; import java.lang.*; -import altosui.Altos; - public class AltosParse { static boolean isdigit(char c) { return '0' <= c && c <= '9'; diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java index 5be8795d..b9280a0c 100644 --- a/ao-tools/altosui/AltosReader.java +++ b/ao-tools/altosui/AltosReader.java @@ -21,8 +21,6 @@ import java.io.*; import java.util.*; import java.text.*; -import altosui.AltosRecord; - public class AltosReader { public AltosRecord read() throws IOException, ParseException { return null; } public void close() { } diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java index 00484767..1160a273 100644 --- a/ao-tools/altosui/AltosRecord.java +++ b/ao-tools/altosui/AltosRecord.java @@ -21,8 +21,6 @@ import java.lang.*; import java.text.*; import java.util.HashMap; import java.io.*; -import altosui.AltosConvert; -import altosui.AltosGPS; public class AltosRecord { int version; diff --git a/ao-tools/altosui/AltosRecordIterable.java b/ao-tools/altosui/AltosRecordIterable.java index 147ecc14..a7df92d1 100644 --- a/ao-tools/altosui/AltosRecordIterable.java +++ b/ao-tools/altosui/AltosRecordIterable.java @@ -28,14 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosRecord; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosEepromMonitor; - public abstract class AltosRecordIterable implements Iterable { public abstract Iterator iterator(); public void write_comments(PrintStream out) { } diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 22d2dbd3..55056b5e 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -17,7 +17,6 @@ package altosui; import java.io.*; -import altosui.AltosHexfile; public class AltosRomconfig { public boolean valid; diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 2134975d..e1dc974e 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -28,8 +28,6 @@ import java.util.*; import java.text.*; import java.util.prefs.*; -import altosui.AltosRomconfig; - public class AltosRomconfigUI extends JDialog implements ActionListener diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index d6848e57..6787e0c8 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -26,13 +26,8 @@ import java.io.*; import java.util.concurrent.LinkedBlockingQueue; 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; + +import libaltosJNI.*; /* * This class reads from the serial port and places each received diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java index 86eb636a..ec499d5a 100644 --- a/ao-tools/altosui/AltosState.java +++ b/ao-tools/altosui/AltosState.java @@ -21,9 +21,6 @@ package altosui; -import altosui.AltosRecord; -import altosui.AltosGPS; - public class AltosState { AltosRecord data; diff --git a/ao-tools/altosui/AltosStatusTable.java b/ao-tools/altosui/AltosStatusTable.java index 0d3a5d14..02c6232f 100644 --- a/ao-tools/altosui/AltosStatusTable.java +++ b/ao-tools/altosui/AltosStatusTable.java @@ -28,9 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.AltosFlightStatusTableModel; -import altosui.AltosFlightInfoTableModel; - public class AltosStatusTable extends JTable { private AltosFlightStatusTableModel flightStatusModel; diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java index be22dac6..bdb6466a 100644 --- a/ao-tools/altosui/AltosTelemetry.java +++ b/ao-tools/altosui/AltosTelemetry.java @@ -20,10 +20,6 @@ package altosui; import java.lang.*; import java.text.*; import java.util.HashMap; -import altosui.AltosConvert; -import altosui.AltosRecord; -import altosui.AltosGPS; -import altosui.AltosCRCException; /* * Telemetry data contents diff --git a/ao-tools/altosui/AltosTelemetryIterable.java b/ao-tools/altosui/AltosTelemetryIterable.java index 0a125c98..a71ab872 100644 --- a/ao-tools/altosui/AltosTelemetryIterable.java +++ b/ao-tools/altosui/AltosTelemetryIterable.java @@ -20,7 +20,6 @@ package altosui; import java.io.*; import java.util.*; import java.text.*; -import altosui.AltosTelemetry; public class AltosTelemetryIterable extends AltosRecordIterable { LinkedList records; diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 2861444d..9ab451de 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -28,25 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -import altosui.Altos; -import altosui.AltosSerial; -import altosui.AltosSerialMonitor; -import altosui.AltosRecord; -import altosui.AltosTelemetry; -import altosui.AltosState; -import altosui.AltosDeviceDialog; -import altosui.AltosPreferences; -import altosui.AltosLog; -import altosui.AltosVoice; -import altosui.AltosFlightInfoTableModel; -import altosui.AltosFlashUI; -import altosui.AltosLogfileChooser; -import altosui.AltosCSVUI; -import altosui.AltosLine; -import altosui.AltosStatusTable; -import altosui.AltosInfoTable; -import altosui.AltosDisplayThread; - import libaltosJNI.*; public class AltosUI extends JFrame { -- cgit v1.2.3 From dcfa56498d1b65a213b8aba9cbd6c4806532383c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Nov 2010 16:07:04 -0800 Subject: altosui: Open serial device at 'new' time. Prohibit duplicate opens. With the per-serial UI, there's never a reason to create a serial device without opening it right away. This eliminates the bug caused by not opening the serial device for telemetry reception. Serial devices can now be opened only once; this eliminates errors when trying to reflash or configure devices while receiving telemetry. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 9 +++++++-- ao-tools/altosui/AltosDebug.java | 11 ++++++++--- ao-tools/altosui/AltosEepromDownload.java | 9 +++++++-- ao-tools/altosui/AltosFlash.java | 13 +++++-------- ao-tools/altosui/AltosFlashUI.java | 11 ++++++++--- ao-tools/altosui/AltosSerial.java | 28 +++++++++++++++++----------- ao-tools/altosui/AltosTelemetryReader.java | 5 +++-- ao-tools/altosui/AltosUI.java | 6 ++++++ ao-tools/altosui/Makefile.am | 1 + 9 files changed, 62 insertions(+), 31 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 30f7d541..09e204a9 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -231,10 +231,9 @@ public class AltosConfig implements Runnable, ActionListener { product = new string_ref("unknown"); device = AltosDeviceDialog.show(owner, AltosDevice.product_any); - serial_line = new AltosSerial(); if (device != null) { try { - serial_line.open(device); + serial_line = new AltosSerial(device); if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; config_thread = new Thread(this); @@ -245,6 +244,12 @@ public class AltosConfig implements Runnable, ActionListener { device.getPath()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.getPath()), + "Device in use", + JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(owner, device.getPath(), diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 9c10129d..9aa35d3f 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -19,9 +19,10 @@ package altosui; import java.lang.*; import java.io.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.LinkedList; -import java.util.Iterator; +import java.util.concurrent.*; +import java.util.*; + +import libaltosJNI.*; public class AltosDebug extends AltosSerial { @@ -259,4 +260,8 @@ public class AltosDebug extends AltosSerial { public void reset() { printf ("R\n"); } + + public AltosDebug (altos_device in_device) throws FileNotFoundException, AltosSerialInUseException { + super(in_device); + } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index bd9e4b48..8996b924 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -244,12 +244,11 @@ public class AltosEepromDownload implements Runnable { frame = given_frame; device = AltosDeviceDialog.show(frame, AltosDevice.product_any); - serial_line = new AltosSerial(); remote = false; if (device != null) { try { - serial_line.open(device); + serial_line = new AltosSerial(device); if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; eeprom_thread = new Thread(this); @@ -260,6 +259,12 @@ public class AltosEepromDownload implements Runnable { device.getPath()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + device.getPath()), + "Device in use", + JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, device.getPath(), diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index 25b4a06e..fa2465d3 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -329,17 +329,14 @@ public class AltosFlash { return rom_config; } - public void open() throws IOException, FileNotFoundException, InterruptedException { + public AltosFlash(File in_file, AltosDevice in_debug_dongle) + throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException { + file = in_file; + debug_dongle = in_debug_dongle; + debug = new AltosDebug(in_debug_dongle); 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 diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index 70c8c549..b09cb594 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -65,10 +65,9 @@ public class AltosFlashUI } public void run() { - flash = new AltosFlash(file, debug_dongle); - flash.addActionListener(this); try { - flash.open(); + flash = new AltosFlash(file, debug_dongle); + flash.addActionListener(this); AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); romconfig_ui.set(flash.romconfig()); @@ -88,6 +87,12 @@ public class AltosFlashUI "Cannot open image", file.toString(), JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + debug_dongle.getPath()), + "Device in use", + JOptionPane.ERROR_MESSAGE); } catch (IOException e) { JOptionPane.showMessageDialog(frame, e.getMessage(), diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 6787e0c8..99a92fdb 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -23,9 +23,8 @@ package altosui; import java.lang.*; import java.io.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.LinkedList; -import java.util.Iterator; +import java.util.concurrent.*; +import java.util.*; import libaltosJNI.*; @@ -37,6 +36,9 @@ import libaltosJNI.*; public class AltosSerial implements Runnable { + static List devices_opened = Collections.synchronizedList(new LinkedList()); + + altos_device device; SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; @@ -141,10 +143,6 @@ public class AltosSerial implements Runnable { set_monitor(false); } - public boolean opened() { - return altos != null; - } - public void close() { if (altos != null) { libaltos.altos_close(altos); @@ -161,6 +159,9 @@ public class AltosSerial implements Runnable { libaltos.altos_free(altos); altos = null; } + synchronized (devices_opened) { + devices_opened.remove(device.getPath()); + } } public void putc(char c) { @@ -178,7 +179,12 @@ public class AltosSerial implements Runnable { print(String.format(format, arguments)); } - public void open(altos_device device) throws FileNotFoundException { + private void open() throws FileNotFoundException, AltosSerialInUseException { + synchronized (devices_opened) { + if (devices_opened.contains(device.getPath())) + throw new AltosSerialInUseException(device); + devices_opened.add(device.getPath()); + } close(); altos = libaltos.altos_open(device); if (altos == null) @@ -220,12 +226,12 @@ public class AltosSerial implements Runnable { } } - public AltosSerial() { - altos = null; - input_thread = null; + public AltosSerial(altos_device in_device) throws FileNotFoundException, AltosSerialInUseException { + device = in_device; line = ""; monitor_mode = false; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); + open(); } } diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index 0b5509eb..ff02c722 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -50,9 +50,10 @@ class AltosTelemetryReader extends AltosFlightReader { serial.set_callsign(callsign); } - public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, IOException { + public AltosTelemetryReader (AltosDevice in_device) + throws FileNotFoundException, AltosSerialInUseException, IOException { device = in_device; - serial = new AltosSerial(); + serial = new AltosSerial(device); log = new AltosLog(serial); name = device.getPath(); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 9ab451de..0d8f0e8d 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -56,6 +56,12 @@ public class AltosUI extends JFrame { device.getPath()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(AltosUI.this, + String.format("Device \"%s\" already in use", + device.getPath()), + "Device in use", + JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, device.getPath(), diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 267bae63..f4c743df 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -58,6 +58,7 @@ altosui_JAVA = \ AltosRomconfig.java \ AltosRomconfigUI.java \ AltosSerial.java \ + AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosState.java \ AltosStatusTable.java \ -- cgit v1.2.3 From 11c95f687b1f68d35fa1a0af2c4e7982b8bb226a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Nov 2010 17:09:51 -0800 Subject: altosui: Replace flight status table with labels, fix resize. There's no reason to use a table for the flight status data, replace that with a selection of widgets instead. Also, set all of the grid bag constraints for the various flight status displays so that resize does something sensible. Adds a scrollbar to the table display so that it can shrink. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosAscent.java | 13 ++- ao-tools/altosui/AltosDescent.java | 78 +++++++++------- ao-tools/altosui/AltosFlightStatus.java | 157 ++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosFlightUI.java | 10 +- ao-tools/altosui/AltosLanded.java | 6 +- ao-tools/altosui/AltosPad.java | 20 ++-- ao-tools/altosui/AltosStatusTable.java | 67 -------------- ao-tools/altosui/Makefile.am | 3 +- 8 files changed, 237 insertions(+), 117 deletions(-) create mode 100644 ao-tools/altosui/AltosFlightStatus.java delete mode 100644 ao-tools/altosui/AltosStatusTable.java diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 51fa1a89..7525b655 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -43,6 +43,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public AscentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; label = new JLabel(text); label.setFont(label_font); @@ -50,6 +51,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { c.gridx = 0; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(label, c); add(label); @@ -58,8 +61,9 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; + c.fill = GridBagConstraints.BOTH; c.gridwidth = 2; + c.weightx = 1; layout.setConstraints(value, c); add(value); } @@ -88,6 +92,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public AscentValueHold (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; label = new JLabel(text); label.setFont(label_font); @@ -95,6 +100,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { c.gridx = 0; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(label, c); add(label); @@ -103,6 +110,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; layout.setConstraints(value, c); add(value); @@ -111,6 +120,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; layout.setConstraints(max_value, c); add(max_value); } diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index 56d3e4fe..b69e36b6 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -48,6 +48,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { public DescentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; label = new JLabel(text); label.setFont(label_font); @@ -55,6 +56,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.gridx = 0; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(label, c); add(label); @@ -64,7 +67,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.gridx = 1; c.gridy = y; c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; layout.setConstraints(value, c); add(value); } @@ -138,50 +142,54 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { JLabel label; JTextField value; JTextField value_deg; - void reset () { + void reset () { value.setText(""); value_deg.setText(""); - } + } void show (AltosState state, int crc_errors) { if (state.from_pad != null) { - value.setText(state.from_pad.bearing_words( - AltosGreatCircle.BEARING_LONG)); + value.setText(state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG)); value_deg.setText(String.format("%3.0f°", state.from_pad.bearing)); } else { value.setText("???"); value_deg.setText("???"); - } + } } public Bearing (GridBagLayout layout, int y) { - GridBagConstraints c = new GridBagConstraints(); - - label = new JLabel("Bearing"); - label.setFont(label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); - c.anchor = GridBagConstraints.WEST; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(30); - value.setFont(value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.HORIZONTAL; - layout.setConstraints(value, c); - add(value); - - value_deg = new JTextField(5); - value_deg.setFont(value_font); - value_deg.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.HORIZONTAL; - - layout.setConstraints(value_deg, c); - add(value_deg); + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel("Bearing"); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + c.weightx = 0; + c.fill = GridBagConstraints.VERTICAL; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(30); + value.setFont(value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.weightx = 1; + c.fill = GridBagConstraints.BOTH; + layout.setConstraints(value, c); + add(value); + + value_deg = new JTextField(5); + value_deg.setFont(value_font); + value_deg.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.weightx = 1; + c.fill = GridBagConstraints.BOTH; + layout.setConstraints(value_deg, c); + add(value_deg); } } diff --git a/ao-tools/altosui/AltosFlightStatus.java b/ao-tools/altosui/AltosFlightStatus.java new file mode 100644 index 00000000..b99a5325 --- /dev/null +++ b/ao-tools/altosui/AltosFlightStatus.java @@ -0,0 +1,157 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + + private Font status_font; + + public class FlightValue { + JLabel label; + JTextField value; + + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + public FlightValue (GridBagLayout layout, int x, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(5, 5, 5, 5); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + + label = new JLabel(text); + label.setFont(status_font); + label.setHorizontalAlignment(SwingConstants.CENTER); + c.gridx = x; c.gridy = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(""); + value.setFont(status_font); + value.setHorizontalAlignment(SwingConstants.CENTER); + c.gridx = x; c.gridy = 1; + layout.setConstraints(value, c); + add(value); + } + } + + class Call extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(state.data.callsign); + } + public Call (GridBagLayout layout, int x) { + super (layout, x, "Callsign"); + } + } + + Call call; + + class Serial extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.serial)); + } + public Serial (GridBagLayout layout, int x) { + super (layout, x, "Serial"); + } + } + + Serial serial; + + class Flight extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.flight)); + } + public Flight (GridBagLayout layout, int x) { + super (layout, x, "Flight"); + } + } + + Flight flight; + + class FlightState extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(state.data.state()); + } + public FlightState (GridBagLayout layout, int x) { + super (layout, x, "State"); + } + } + + FlightState flight_state; + + class RSSI extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.rssi)); + } + public RSSI (GridBagLayout layout, int x) { + super (layout, x, "RSSI (dBm)"); + } + } + + RSSI rssi; + + public void reset () { + call.reset(); + serial.reset(); + flight.reset(); + flight_state.reset(); + rssi.reset(); + } + + public void show (AltosState state, int crc_errors) { + call.show(state, crc_errors); + serial.show(state, crc_errors); + flight.show(state, crc_errors); + flight_state.show(state, crc_errors); + rssi.show(state, crc_errors); + } + + public int height() { + Dimension d = layout.preferredLayoutSize(this); + return d.height; + } + + public AltosFlightStatus() { + layout = new GridBagLayout(); + + status_font = new Font("SansSerif", Font.BOLD, 24); + setLayout(layout); + + call = new Call(layout, 0); + serial = new Serial(layout, 1); + flight = new Flight(layout, 2); + flight_state = new FlightState(layout, 3); + rssi = new RSSI(layout, 4); + } +} diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 3581c54c..ae31048d 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -45,7 +45,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosDescent descent; AltosLanded landed; - private AltosStatusTable flightStatus; + private AltosFlightStatus flightStatus; + private JScrollPane flightInfoPane; private AltosInfoTable flightInfo; static final int tab_pad = 1; @@ -117,7 +118,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } cur_tab = tab; } - flightStatus.set(state); + flightStatus.show(state, crc_errors); flightInfo.show(state, crc_errors); } @@ -133,7 +134,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { setTitle(String.format("AltOS %s", reader.name)); - flightStatus = new AltosStatusTable(); + flightStatus = new AltosFlightStatus(); vbox = new Box (BoxLayout.Y_AXIS); vbox.add(flightStatus); @@ -153,7 +154,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Landed", landed); flightInfo = new AltosInfoTable(); - pane.add("Table", flightInfo.box()); + flightInfoPane = new JScrollPane(flightInfo.box()); + pane.add("Table", flightInfoPane); vbox.add(pane); diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java index d170ccad..465c9dce 100644 --- a/ao-tools/altosui/AltosLanded.java +++ b/ao-tools/altosui/AltosLanded.java @@ -48,6 +48,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { public LandedValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; label = new JLabel(text); label.setFont(label_font); @@ -55,6 +56,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { c.gridx = 0; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; + c.weightx = 0; + c.fill = GridBagConstraints.VERTICAL; layout.setConstraints(label, c); add(label); @@ -63,7 +66,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.fill = GridBagConstraints.BOTH; layout.setConstraints(value, c); add(value); } diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index da047072..650ed012 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -46,11 +46,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public LaunchStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; lights = new AltosLights(); c.gridx = 0; c.gridy = y; c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(lights, c); add(lights); @@ -60,7 +62,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { c.gridx = 1; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(label, c); add(label); @@ -69,6 +72,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; layout.setConstraints(value, c); add(value); @@ -85,13 +90,16 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } public LaunchValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(10, 10, 10, 10); + c.weighty = 1; label = new JLabel(text); label.setFont(label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 1; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; layout.setConstraints(label, c); add(label); @@ -100,7 +108,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.HORIZONTAL; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; layout.setConstraints(value, c); add(value); } @@ -221,13 +230,10 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public AltosPad() { layout = new GridBagLayout(); - GridBagConstraints c; - label_font = new Font("Dialog", Font.PLAIN, 24); value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); - c = new GridBagConstraints(); /* Elements in pad display: * * Battery voltage diff --git a/ao-tools/altosui/AltosStatusTable.java b/ao-tools/altosui/AltosStatusTable.java deleted file mode 100644 index 02c6232f..00000000 --- a/ao-tools/altosui/AltosStatusTable.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosStatusTable extends JTable { - private AltosFlightStatusTableModel flightStatusModel; - - private Font statusFont = new Font("SansSerif", Font.BOLD, 24); - - public AltosStatusTable() { - super((TableModel) new AltosFlightStatusTableModel()); - flightStatusModel = (AltosFlightStatusTableModel) getModel(); - - setFont(statusFont); - - TableColumnModel tcm = getColumnModel(); - - for (int i = 0; i < flightStatusModel.getColumnCount(); i++) { - DefaultTableCellRenderer r = new DefaultTableCellRenderer(); - r.setFont(statusFont); - r.setHorizontalAlignment(SwingConstants.CENTER); - tcm.getColumn(i).setCellRenderer(r); - } - - setRowHeight(rowHeight()); - setShowGrid(false); - } - - public int rowHeight() { - FontMetrics statusMetrics = getFontMetrics(statusFont); - return (statusMetrics.getHeight() + statusMetrics.getLeading()) * 15 / 10; - } - - public int height() { - return rowHeight * 4; - } - - public void set(AltosState state) { - flightStatusModel.set(state); - } -} diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index f4c743df..d11ea3e2 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -33,7 +33,7 @@ altosui_JAVA = \ AltosFlightDisplay.java \ AltosFlightInfoTableModel.java \ AltosFlightReader.java \ - AltosFlightStatusTableModel.java \ + AltosFlightStatus.java \ AltosFlightUI.java \ AltosGPS.java \ AltosGreatCircle.java \ @@ -61,7 +61,6 @@ altosui_JAVA = \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosState.java \ - AltosStatusTable.java \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ -- cgit v1.2.3 From 511903704f7e1b22e88dd3e3cc35fd3c0583820e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Nov 2010 03:26:57 -0800 Subject: altosui: With --replay option, exit when replay window is closed Otherwise, the application hangs around forever. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlightUI.java | 10 ++++++++- ao-tools/altosui/AltosUI.java | 41 +++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index ae31048d..5134a24e 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -56,6 +56,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { int cur_tab = 0; + boolean exit_on_close = false; + int which_tab(AltosState state) { if (state.state < Altos.ao_flight_boost) return tab_pad; @@ -122,8 +124,12 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { flightInfo.show(state, crc_errors); } + public void set_exit_on_close() { + exit_on_close = true; + } + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { - AltosPreferences.init(this); + AltosPreferences.init(this); voice = in_voice; reader = in_reader; @@ -191,6 +197,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { disconnect(); setVisible(false); dispose(); + if (exit_on_close) + System.exit(0); } }); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 0d8f0e8d..a2e416ba 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -443,26 +443,27 @@ public class AltosUI extends JFrame { public static void main(final String[] args) { int process = 0; /* Handle batch-mode */ - if (args.length == 2 && args[0].equals("--replay")) { - String filename = args[1]; - FileInputStream in; - try { - in = new FileInputStream(filename); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); - return; - } - AltosRecordIterable recs; - AltosReplayReader reader; - if (filename.endsWith("eeprom")) { - recs = new AltosEepromIterable(in); - } else { - recs = new AltosTelemetryIterable(in); - } - reader = new AltosReplayReader(recs.iterator(), filename); - new AltosFlightUI(new AltosVoice(), reader); - return; - } else if (args.length > 0) { + if (args.length == 2 && args[0].equals("--replay")) { + String filename = args[1]; + FileInputStream in; + try { + in = new FileInputStream(filename); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", filename); + return; + } + AltosRecordIterable recs; + AltosReplayReader reader; + if (filename.endsWith("eeprom")) { + recs = new AltosEepromIterable(in); + } else { + recs = new AltosTelemetryIterable(in); + } + reader = new AltosReplayReader(recs.iterator(), filename); + AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); + flight_ui.set_exit_on_close(); + return; + } else if (args.length > 0) { for (int i = 0; i < args.length; i++) { if (args[i].equals("--kml")) process |= process_kml; -- cgit v1.2.3 From 524644d8d8ce3f8a5a914ecfc7e2a8d474d89095 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Nov 2010 22:04:44 +0800 Subject: altosui: oops, missed a file in the previous commit AltosSerialInUseException.java just defines a new exception, thanks to java for making this live in a separate file. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerialInUseException.java | 28 +++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 ao-tools/altosui/AltosSerialInUseException.java diff --git a/ao-tools/altosui/AltosSerialInUseException.java b/ao-tools/altosui/AltosSerialInUseException.java new file mode 100644 index 00000000..4b108c7c --- /dev/null +++ b/ao-tools/altosui/AltosSerialInUseException.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 libaltosJNI.*; + +public class AltosSerialInUseException extends Exception { + public altos_device device; + + public AltosSerialInUseException (altos_device in_device) { + device = in_device; + } +} -- cgit v1.2.3 From 257e97137325f5dbbd6aa034f20fd6937b67df90 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Nov 2010 22:38:35 +0800 Subject: altosui: eliminate menu bar, moving elements to buttons. This adds a new 'configure AltosUI' dialog to set the log directory and voice preferences. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfigureUI.java | 120 +++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 158 +++++---------------------------- ao-tools/altosui/Makefile.am | 1 + 3 files changed, 144 insertions(+), 135 deletions(-) create mode 100644 ao-tools/altosui/AltosConfigureUI.java diff --git a/ao-tools/altosui/AltosConfigureUI.java b/ao-tools/altosui/AltosConfigureUI.java new file mode 100644 index 00000000..88c180f1 --- /dev/null +++ b/ao-tools/altosui/AltosConfigureUI.java @@ -0,0 +1,120 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosConfigureUI extends JDialog { + JFrame owner; + AltosVoice voice; + Container pane; + + JRadioButton enable_voice; + JButton test_voice; + JButton close; + + JButton configure_log; + JTextField log_directory; + + public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) { + super(in_owner, "Configure AltosUI", false); + + GridBagConstraints c; + + Insets insets = new Insets(4, 4, 4, 4); + + owner = in_owner; + voice = in_voice; + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.insets = insets; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + + /* Enable Voice */ + c.gridx = 0; + c.gridy = 0; + enable_voice = new JRadioButton("Enable Voice", AltosPreferences.voice()); + enable_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosPreferences.set_voice(enabled); + if (enabled) + voice.speak_always("Enable voice."); + else + voice.speak_always("Disable voice."); + } + }); + pane.add(enable_voice, c); + c.gridx = 1; + c.gridy = 0; + test_voice = new JButton("Test Voice"); + test_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + voice.speak("That's one small step for man; one giant leap for mankind."); + } + }); + pane.add(test_voice, c); + + close = new JButton("Close"); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 2; + pane.add(close, c); + + configure_log = new JButton("Configure Log"); + configure_log.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosPreferences.ConfigureLog(); + log_directory.setText(AltosPreferences.logdir().getPath()); + } + }); + c.gridwidth = 1; + + c.gridx = 0; + c.gridy = 2; + pane.add(configure_log, c); + + log_directory = new JTextField(AltosPreferences.logdir().getPath()); + c.gridx = 1; + c.gridy = 2; + c.fill = GridBagConstraints.BOTH; + pane.add(log_directory, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index a2e416ba..bedf2459 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -144,9 +144,28 @@ public class AltosUI extends JFrame { } }); - setTitle("AltOS"); + b = addButton(0, 2, "Configure AltosUI"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConfigureAltosUI(); + } + }); + + b = addButton(1, 2, "Flash Image"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FlashImage(); + } + }); + + b = addButton(2, 2, "Quit"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); - createMenu(); + setTitle("AltOS"); pane.doLayout(); pane.validate(); @@ -232,139 +251,8 @@ public class AltosUI extends JFrame { new AltosGraphUI(AltosUI.this); } - /* Create the AltosUI menus - */ - private void createMenu() { - JMenuBar menubar = new JMenuBar(); - JMenu menu; - JMenuItem item; - JRadioButtonMenuItem radioitem; - - // File menu - { - menu = new JMenu("File"); - menu.setMnemonic(KeyEvent.VK_F); - menubar.add(menu); - - item = new JMenuItem("Flash Image",KeyEvent.VK_I); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - FlashImage(); - } - }); - menu.add(item); - - item = new JMenuItem("Export Data",KeyEvent.VK_E); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ExportData(); - } - }); - menu.add(item); - - item = new JMenuItem("Graph Data",KeyEvent.VK_G); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - GraphData(); - } - }); - menu.add(item); - - item = new JMenuItem("Quit",KeyEvent.VK_Q); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, - ActionEvent.CTRL_MASK)); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - System.out.printf("exiting\n"); - System.exit(0); - } - }); - menu.add(item); - } - - // Device menu - if (false) { - menu = new JMenu("Device"); - menu.setMnemonic(KeyEvent.VK_D); - menubar.add(menu); - - item = new JMenuItem("Connect to Device",KeyEvent.VK_C); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConnectToDevice(); - } - }); - menu.add(item); - - menu.addSeparator(); - - item = new JMenuItem("Set Callsign",KeyEvent.VK_S); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConfigureCallsign(); - } - }); - - menu.add(item); - - item = new JMenuItem("Configure TeleMetrum device",KeyEvent.VK_T); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConfigureTeleMetrum(); - } - }); - - menu.add(item); - } - // Log menu - { - menu = new JMenu("Log"); - menu.setMnemonic(KeyEvent.VK_L); - menubar.add(menu); - - item = new JMenuItem("New Log",KeyEvent.VK_N); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - } - }); - menu.add(item); - - item = new JMenuItem("Configure Log",KeyEvent.VK_C); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - AltosPreferences.ConfigureLog(); - } - }); - menu.add(item); - } - // Voice menu - { - menu = new JMenu("Voice", true); - menu.setMnemonic(KeyEvent.VK_V); - menubar.add(menu); - - radioitem = new JRadioButtonMenuItem("Enable Voice", AltosPreferences.voice()); - radioitem.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource(); - boolean enabled = item.isSelected(); - AltosPreferences.set_voice(enabled); - if (enabled) - voice.speak_always("Enable voice."); - else - voice.speak_always("Disable voice."); - } - }); - menu.add(radioitem); - item = new JMenuItem("Test Voice",KeyEvent.VK_T); - item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - voice.speak("That's one small step for man; one giant leap for mankind."); - } - }); - menu.add(item); - } - this.setJMenuBar(menubar); + private void ConfigureAltosUI() { + new AltosConfigureUI(AltosUI.this, voice); } static AltosRecordIterable open_logfile(String filename) { diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index d11ea3e2..8d0fe16e 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -14,6 +14,7 @@ altosui_JAVA = \ AltosChannelMenu.java \ AltosConfig.java \ AltosConfigUI.java \ + AltosConfigureUI.java \ AltosConvert.java \ AltosCRCException.java \ AltosCSV.java \ -- cgit v1.2.3 From 39e371561469d8e5059638ffa4e7075f391de268 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 15 Nov 2010 23:14:51 +0800 Subject: altosui: add reboot button to telemetrum configuration UI This lets you reconfigure and reboot telemetrum, including over the radio link. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 20 +++++++-- ao-tools/altosui/AltosConfigUI.java | 90 +++++++++++++++++++++---------------- 2 files changed, 68 insertions(+), 42 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 09e204a9..a0fdb623 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -198,12 +198,26 @@ public class AltosConfig implements Runnable, ActionListener { public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("save")) { + if (cmd.equals("Save")) { save_data(); set_ui(); - } else if (cmd.equals("reset")) { + } else if (cmd.equals("Reset")) { set_ui(); - } else if (cmd.equals("close")) { + } else if (cmd.equals("Reboot")) { + if (serial_line != null) { + try { + start_serial(); + serial_line.printf("r eboot\n"); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + serial_line.close(); + } + } else if (cmd.equals("Close")) { if (serial_line != null) serial_line.close(); } diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index 9e3856b0..e04933eb 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -61,6 +61,7 @@ public class AltosConfigUI JButton save; JButton reset; + JButton reboot; JButton close; ActionListener listener; @@ -92,7 +93,7 @@ public class AltosConfigUI public void windowClosing(WindowEvent e) { ui.actionPerformed(new ActionEvent(e.getSource(), ActionEvent.ACTION_PERFORMED, - "close")); + "Close")); } } @@ -112,7 +113,7 @@ public class AltosConfigUI /* Product */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 0; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -120,8 +121,8 @@ public class AltosConfigUI pane.add(product_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 0; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 0; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -132,7 +133,7 @@ public class AltosConfigUI /* Version */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 1; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -141,8 +142,8 @@ public class AltosConfigUI pane.add(version_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 1; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 1; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -154,7 +155,7 @@ public class AltosConfigUI /* Serial */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 2; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -163,8 +164,8 @@ public class AltosConfigUI pane.add(serial_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 2; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 2; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -176,7 +177,7 @@ public class AltosConfigUI /* Main deploy */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 3; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -185,8 +186,8 @@ public class AltosConfigUI pane.add(main_deploy_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 3; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -200,7 +201,7 @@ public class AltosConfigUI /* Apogee delay */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 4; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -209,8 +210,8 @@ public class AltosConfigUI pane.add(apogee_delay_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 4; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 4; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -224,7 +225,7 @@ public class AltosConfigUI /* Radio channel */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 5; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -233,8 +234,8 @@ public class AltosConfigUI pane.add(radio_channel_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 5; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 5; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -248,7 +249,7 @@ public class AltosConfigUI /* Radio Calibration */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 6; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -257,8 +258,8 @@ public class AltosConfigUI pane.add(radio_calibration_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 6; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 6; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -271,7 +272,7 @@ public class AltosConfigUI /* Callsign */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 7; - c.gridwidth = 3; + c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; @@ -280,8 +281,8 @@ public class AltosConfigUI pane.add(callsign_label, c); c = new GridBagConstraints(); - c.gridx = 3; c.gridy = 7; - c.gridwidth = 3; + c.gridx = 4; c.gridy = 7; + c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; c.anchor = GridBagConstraints.LINE_START; @@ -294,36 +295,47 @@ public class AltosConfigUI /* Buttons */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 8; - c.gridwidth = 6; + c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; c.insets = il; save = new JButton("Save"); pane.add(save, c); save.addActionListener(this); - save.setActionCommand("save"); + save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; - c.gridwidth = 6; + c.gridx = 2; c.gridy = 8; + c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = il; reset = new JButton("Reset"); pane.add(reset, c); reset.addActionListener(this); - reset.setActionCommand("reset"); + reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; - c.gridwidth = 6; + c.gridx = 4; c.gridy = 8; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + reboot = new JButton("Reboot"); + pane.add(reboot, c); + reboot.addActionListener(this); + reboot.setActionCommand("Reboot"); + + c = new GridBagConstraints(); + c.gridx = 6; c.gridy = 8; + c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; c.insets = il; close = new JButton("Close"); pane.add(close, c); close.addActionListener(this); - close.setActionCommand("close"); + close.setActionCommand("Close"); addWindowListener(new ConfigListener(this)); } @@ -336,12 +348,12 @@ public class AltosConfigUI } /* If any values have been changed, confirm before closing */ - public boolean check_dirty() { + public boolean check_dirty(String operation) { if (dirty) { - Object[] options = { "Close anyway", "Keep editing" }; + Object[] options = { String.format("%s anyway", operation), "Keep editing" }; int i; i = JOptionPane.showOptionDialog(this, - "Configuration modified, close anyway?", + String.format("Configuration modified. %s anyway?", operation), "Configuration Modified", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE, @@ -356,11 +368,11 @@ public class AltosConfigUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("close")) - if (!check_dirty()) + if (cmd.equals("Close") || cmd.equals("Reboot")) + if (!check_dirty(cmd)) return; listener.actionPerformed(e); - if (cmd.equals("close")) { + if (cmd.equals("Close") || cmd.equals("Reboot")) { setVisible(false); dispose(); } -- cgit v1.2.3 From d1dbe3b69e6f95ef8ecd4cf959863b922ab47c66 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 15 Nov 2010 11:08:00 -0700 Subject: add a paragraph about forcing TM back to idle mode if an accel cal goes badly --- doc/telemetrum-doc.xsl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 1bcd8632..90e202b4 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -752,6 +752,21 @@ sensor... nothing is permanently "lost" or "damaged" if the calibration is poor. + + In the unlikely event an accel cal that goes badly, it is possible + that TeleMetrum may always come up in 'pad mode' and as such not be + listening to either the USB or radio interfaces. If that happens, + there is a special hook in the firmware to force the board back + in to 'idle mode' so you can re-do the cal. To use this hook, you + just need to ground the SPI clock pin at power-on. This pin is + available as pin 2 on the 8-pin companion connector, and pin 1 is + ground. So either carefully install a fine-gauge wire jumper + between the two pins closest to the index hole end of the 8-pin + connector, or plug in the programming cable to the 8-pin connector + and use a small screwdriver or similar to short the two pins closest + to the index post on the 4-pin end of the programming cable, and + power up the board. It should come up in 'idle mode' (two beeps). + -- cgit v1.2.3 From fcca333cda64be35f0c9fb0109eef1be3709dddd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Nov 2010 21:49:59 +0800 Subject: altosui: Add callsign configuration in AltosUI configuration dialog This callsign is used during packet communication. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfigUI.java | 2 +- ao-tools/altosui/AltosConfigureUI.java | 56 ++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index e04933eb..ca89f58d 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -288,7 +288,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - callsign_value = new JTextField("N0CALL"); + callsign_value = new JTextField(AltosPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); pane.add(callsign_value, c); diff --git a/ao-tools/altosui/AltosConfigureUI.java b/ao-tools/altosui/AltosConfigureUI.java index 88c180f1..64c17eaf 100644 --- a/ao-tools/altosui/AltosConfigureUI.java +++ b/ao-tools/altosui/AltosConfigureUI.java @@ -22,13 +22,17 @@ 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 java.util.concurrent.LinkedBlockingQueue; -public class AltosConfigureUI extends JDialog { +public class AltosConfigureUI + extends JDialog + implements DocumentListener +{ JFrame owner; AltosVoice voice; Container pane; @@ -40,6 +44,22 @@ public class AltosConfigureUI extends JDialog { JButton configure_log; JTextField log_directory; + JLabel callsign_label; + JTextField callsign_value; + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + AltosPreferences.set_callsign(callsign_value.getText()); + } + + public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) { super(in_owner, "Configure AltosUI", false); @@ -83,17 +103,6 @@ public class AltosConfigureUI extends JDialog { }); pane.add(test_voice, c); - close = new JButton("Close"); - close.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 2; - pane.add(close, c); - configure_log = new JButton("Configure Log"); configure_log.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -113,6 +122,29 @@ public class AltosConfigureUI extends JDialog { c.fill = GridBagConstraints.BOTH; pane.add(log_directory, c); + callsign_label = new JLabel("Callsign"); + c.gridx = 0; + c.gridy = 3; + pane.add(callsign_label, c); + + callsign_value = new JTextField(AltosPreferences.callsign()); + callsign_value.getDocument().addDocumentListener(this); + c.gridx = 1; + c.gridy = 3; + pane.add(callsign_value, c); + + close = new JButton("Close"); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + pane.add(close, c); + pack(); setLocationRelativeTo(owner); setVisible(true); -- cgit v1.2.3 From d0eb41619544ead6d9dab3a8d024a12936c9cdd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Nov 2010 22:20:00 +0800 Subject: altosui: Cleanup flight UI layout Use common constants for fonts and insets Shrink fonts so that the window is < 600 pixels tall. Signed-off-by: Keith Packard --- ao-tools/altosui/Altos.java | 6 +++ ao-tools/altosui/AltosAscent.java | 24 +++++------- ao-tools/altosui/AltosDescent.java | 18 ++++----- ao-tools/altosui/AltosFlightInfoTableModel.java | 2 +- ao-tools/altosui/AltosFlightStatus.java | 7 +--- ao-tools/altosui/AltosFlightUI.java | 2 +- ao-tools/altosui/AltosLanded.java | 4 +- ao-tools/altosui/AltosPad.java | 50 +++++++++++++++++-------- 8 files changed, 64 insertions(+), 49 deletions(-) diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 997550e0..197e98db 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -67,6 +67,12 @@ public class Altos { static boolean map_initialized = false; + static final int tab_elt_pad = 5; + + static final Font label_font = new Font("Dialog", Font.PLAIN, 22); + static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); + static final Font status_font = new Font("SansSerif", Font.BOLD, 24); + static void initialize_map() { string_to_state.put("startup", ao_flight_startup); diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 7525b655..8e1b6347 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -30,8 +30,6 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - Font label_font; - Font value_font; public class AscentValue { JLabel label; @@ -46,10 +44,10 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { c.weighty = 1; label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; @@ -57,7 +55,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(30); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -95,10 +93,10 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { c.weighty = 1; label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; @@ -106,7 +104,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(15); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -116,7 +114,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { add(value); max_value = new JTextField(15); - max_value.setFont(value_font); + max_value.setFont(Altos.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -224,15 +222,15 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { JLabel cur, max; cur = new JLabel("Current"); - cur.setFont(label_font); + cur.setFont(Altos.label_font); c = new GridBagConstraints(); c.gridx = 1; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); layout.setConstraints(cur, c); add(cur); max = new JLabel("Maximum"); - max.setFont(label_font); + max.setFont(Altos.label_font); c.gridx = 2; c.gridy = y; layout.setConstraints(max, c); add(max); @@ -241,8 +239,6 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { public AltosAscent() { layout = new GridBagLayout(); - label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); /* Elements in ascent display: diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index b69e36b6..ceb78e57 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -30,8 +30,6 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - Font label_font; - Font value_font; public class DescentValue { JLabel label; @@ -51,10 +49,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.weighty = 1; label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; @@ -62,7 +60,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(30); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.gridwidth = 2; @@ -161,10 +159,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.weighty = 1; label = new JLabel("Bearing"); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.weightx = 0; c.fill = GridBagConstraints.VERTICAL; @@ -172,7 +170,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(30); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -182,7 +180,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { add(value); value_deg = new JTextField(5); - value_deg.setFont(value_font); + value_deg.setFont(Altos.value_font); value_deg.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -243,8 +241,6 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { public AltosDescent() { layout = new GridBagLayout(); - label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospaced", Font.PLAIN, 24); setLayout(layout); /* Elements in descent display */ diff --git a/ao-tools/altosui/AltosFlightInfoTableModel.java b/ao-tools/altosui/AltosFlightInfoTableModel.java index 2a22e3e5..3355ff52 100644 --- a/ao-tools/altosui/AltosFlightInfoTableModel.java +++ b/ao-tools/altosui/AltosFlightInfoTableModel.java @@ -46,7 +46,7 @@ public class AltosFlightInfoTableModel extends AbstractTableModel { public int getColumnCount() { return columnNames.length; } public String getColumnName(int col) { return columnNames[col]; } - public int getRowCount() { return 20; } + public int getRowCount() { return 17; } int current_row = 0; int prev_num_rows = 0; diff --git a/ao-tools/altosui/AltosFlightStatus.java b/ao-tools/altosui/AltosFlightStatus.java index b99a5325..59c9e9db 100644 --- a/ao-tools/altosui/AltosFlightStatus.java +++ b/ao-tools/altosui/AltosFlightStatus.java @@ -31,8 +31,6 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - private Font status_font; - public class FlightValue { JLabel label; JTextField value; @@ -51,14 +49,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay c.weighty = 1; label = new JLabel(text); - label.setFont(status_font); + label.setFont(Altos.status_font); label.setHorizontalAlignment(SwingConstants.CENTER); c.gridx = x; c.gridy = 0; layout.setConstraints(label, c); add(label); value = new JTextField(""); - value.setFont(status_font); + value.setFont(Altos.status_font); value.setHorizontalAlignment(SwingConstants.CENTER); c.gridx = x; c.gridy = 1; layout.setConstraints(value, c); @@ -145,7 +143,6 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay public AltosFlightStatus() { layout = new GridBagLayout(); - status_font = new Font("SansSerif", Font.BOLD, 24); setLayout(layout); call = new Call(layout, 0); diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 5134a24e..78b005c0 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -187,7 +187,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { this.setJMenuBar(menubar); } - this.setSize(new Dimension (width(), height())); + this.setSize(this.getPreferredSize()); this.validate(); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java index 465c9dce..0656ea6c 100644 --- a/ao-tools/altosui/AltosLanded.java +++ b/ao-tools/altosui/AltosLanded.java @@ -196,8 +196,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { public AltosLanded() { layout = new GridBagLayout(); - label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospaced", Font.PLAIN, 24); + label_font = new Font("Dialog", Font.PLAIN, 22); + value_font = new Font("Monospaced", Font.PLAIN, 22); setLayout(layout); /* Elements in descent display */ diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 650ed012..8b258c7d 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -60,7 +60,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { label.setFont(label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 1; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; @@ -90,7 +90,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } public LaunchValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(10, 10, 10, 10); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.weighty = 1; label = new JLabel(text); @@ -151,17 +151,32 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { Main main; - class GPS extends LaunchStatus { + class GPSLocked extends LaunchStatus { void show (AltosState state, int crc_errors) { value.setText(String.format("%4d sats", state.gps.nsat)); + lights.set(state.gps.locked); + } + public GPSLocked (GridBagLayout layout, int y) { + super (layout, y, "GPS Locked"); + } + } + + GPSLocked gps_locked; + + class GPSReady extends LaunchStatus { + void show (AltosState state, int crc_errors) { + if (state.gps_ready) + value.setText("Ready"); + else + value.setText(String.format("Waiting %d", state.gps_waiting)); lights.set(state.gps_ready); } - public GPS (GridBagLayout layout, int y) { - super (layout, y, "GPS Status"); + public GPSReady (GridBagLayout layout, int y) { + super (layout, y, "GPS Ready"); } } - GPS gps; + GPSReady gps_ready; String pos(double p, String pos, String neg) { String h = pos; @@ -211,7 +226,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery.reset(); apogee.reset(); main.reset(); - gps.reset(); + gps_locked.reset(); + gps_ready.reset(); pad_lat.reset(); pad_lon.reset(); pad_alt.reset(); @@ -221,7 +237,8 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery.show(state, crc_errors); apogee.show(state, crc_errors); main.show(state, crc_errors); - gps.show(state, crc_errors); + gps_locked.show(state, crc_errors); + gps_ready.show(state, crc_errors); pad_lat.show(state, crc_errors); pad_lon.show(state, crc_errors); pad_alt.show(state, crc_errors); @@ -230,24 +247,27 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public AltosPad() { layout = new GridBagLayout(); - label_font = new Font("Dialog", Font.PLAIN, 24); - value_font = new Font("Monospaced", Font.PLAIN, 24); + label_font = new Font("Dialog", Font.PLAIN, 22); + value_font = new Font("Monospaced", Font.PLAIN, 22); setLayout(layout); /* Elements in pad display: * * Battery voltage * Igniter continuity - * GPS lock status and location + * GPS lock status + * GPS ready status + * GPS location * Pad altitude * RSSI */ battery = new Battery(layout, 0); apogee = new Apogee(layout, 1); main = new Main(layout, 2); - gps = new GPS(layout, 3); - pad_lat = new PadLat(layout, 4); - pad_lon = new PadLon(layout, 5); - pad_alt = new PadAlt(layout, 6); + gps_locked = new GPSLocked(layout, 3); + gps_ready = new GPSReady(layout, 4); + pad_lat = new PadLat(layout, 5); + pad_lon = new PadLon(layout, 6); + pad_alt = new PadAlt(layout, 7); } } -- cgit v1.2.3 From 1a4b6e96f823035b113f01d1bdfd61afc1f33e25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 16 Nov 2010 22:46:29 +0800 Subject: altosui: Add igniter status to ascent and descent tabs Monitor igniters during all phases of the flight. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosAscent.java | 77 ++++++++++++++++++++++ ao-tools/altosui/AltosDescent.java | 130 +++++++++++++++++++++++++++++-------- ao-tools/altosui/AltosPad.java | 12 ++-- 3 files changed, 183 insertions(+), 36 deletions(-) diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 8e1b6347..38ced95e 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -31,6 +31,53 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; + public class AscentStatus { + JLabel label; + JTextField value; + AltosLights lights; + + void show(AltosState state, int crc_errors) {} + void reset() { + value.setText(""); + lights.set(false); + } + + public AscentStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(15); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + } + } + public class AscentValue { JLabel label; JTextField value; @@ -173,6 +220,30 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { return String.format("%s %4d° %9.6f", h, deg, min); } + class Apogee extends AscentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends AscentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + class Lat extends AscentValue { void show (AltosState state, int crc_errors) { if (state.gps != null) @@ -204,6 +275,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { public void reset() { lat.reset(); lon.reset(); + main.reset(); + apogee.reset(); height.reset(); speed.reset(); accel.reset(); @@ -213,6 +286,8 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lat.show(state, crc_errors); lon.show(state, crc_errors); height.show(state, crc_errors); + main.show(state, crc_errors); + apogee.show(state, crc_errors); speed.show(state, crc_errors); accel.show(state, crc_errors); } @@ -253,5 +328,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { accel = new Accel(layout, 3); lat = new Lat(layout, 4); lon = new Lon(layout, 5); + apogee = new Apogee(layout, 6); + main = new Main(layout, 7); } } diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index ceb78e57..aacd2998 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -31,6 +31,52 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; + public class DescentStatus { + JLabel label; + JTextField value; + AltosLights lights; + + void show(AltosState state, int crc_errors) {} + void reset() { + value.setText(""); + lights.set(false); + } + + public DescentStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(15); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + } + } public class DescentValue { JLabel label; JTextField value; @@ -44,14 +90,14 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setText(String.format(format, v)); } - public DescentValue (GridBagLayout layout, int y, String text) { + public DescentValue (GridBagLayout layout, int x, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; label = new JLabel(text); label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; + c.gridx = x + 0; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -59,11 +105,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(30); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; - c.gridwidth = 2; + c.gridx = x + 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -76,8 +121,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { void show (AltosState state, int crc_errors) { show("%6.0f m", state.height); } - public Height (GridBagLayout layout, int y) { - super (layout, y, "Height"); + public Height (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Height"); } } @@ -90,8 +135,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { speed = state.baro_speed; show("%6.0f m/s", speed); } - public Speed (GridBagLayout layout, int y) { - super (layout, y, "Speed"); + public Speed (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Speed"); } } @@ -115,8 +160,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { else value.setText("???"); } - public Lat (GridBagLayout layout, int y) { - super (layout, y, "Latitude"); + public Lat (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Latitude"); } } @@ -129,13 +174,37 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { else value.setText("???"); } - public Lon (GridBagLayout layout, int y) { - super (layout, y, "Longitude"); + public Lon (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Longitude"); } } Lon lon; + class Apogee extends DescentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends DescentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + class Bearing { JLabel label; JTextField value; @@ -154,14 +223,14 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value_deg.setText("???"); } } - public Bearing (GridBagLayout layout, int y) { + public Bearing (GridBagLayout layout, int x, int y) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; label = new JLabel("Bearing"); label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; + c.gridx = x + 0; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.weightx = 0; @@ -172,9 +241,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value = new JTextField(30); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; + c.gridx = x + 1; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.weightx = 1; + c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; layout.setConstraints(value, c); add(value); @@ -182,7 +252,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value_deg = new JTextField(5); value_deg.setFont(Altos.value_font); value_deg.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; + c.gridx = x + 3; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.weightx = 1; c.fill = GridBagConstraints.BOTH; @@ -200,8 +270,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { else value.setText("???"); } - public Elevation (GridBagLayout layout, int y) { - super (layout, y, "Elevation"); + public Elevation (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Elevation"); } } @@ -211,8 +281,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { void show (AltosState state, int crc_errors) { show("%6.0f m", state.range); } - public Range (GridBagLayout layout, int y) { - super (layout, y, "Range"); + public Range (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Range"); } } @@ -226,6 +296,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { bearing.reset(); elevation.reset(); range.reset(); + main.reset(); + apogee.reset(); } public void show(AltosState state, int crc_errors) { @@ -236,6 +308,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { range.show(state, crc_errors); lat.show(state, crc_errors); lon.show(state, crc_errors); + main.show(state, crc_errors); + apogee.show(state, crc_errors); } public AltosDescent() { @@ -244,12 +318,12 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { setLayout(layout); /* Elements in descent display */ - speed = new Speed(layout, 0); - height = new Height(layout, 1); - bearing = new Bearing(layout, 2); - elevation = new Elevation(layout, 3); - range = new Range(layout, 4); - lat = new Lat(layout, 5); - lon = new Lon(layout, 6); + speed = new Speed(layout, 0, 0); height = new Height(layout, 2, 0); + elevation = new Elevation(layout, 0, 1); range = new Range(layout, 2, 1); + bearing = new Bearing(layout, 0, 2); + lat = new Lat(layout, 0, 3); + lon = new Lon(layout, 0, 4); + apogee = new Apogee(layout, 5); + main = new Main(layout, 6); } } diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 8b258c7d..77289f89 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -30,8 +30,6 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosPad extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - Font label_font; - Font value_font; public class LaunchStatus { JLabel label; @@ -57,7 +55,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { add(lights); label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 1; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); @@ -68,7 +66,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(15); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -94,7 +92,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { c.weighty = 1; label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -104,7 +102,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { add(label); value = new JTextField(30); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; @@ -247,8 +245,6 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public AltosPad() { layout = new GridBagLayout(); - label_font = new Font("Dialog", Font.PLAIN, 22); - value_font = new Font("Monospaced", Font.PLAIN, 22); setLayout(layout); /* Elements in pad display: -- cgit v1.2.3 From 483346a03c94b200692f5e6d59f3feee4dcf2ace Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 19 Nov 2010 12:09:46 +1000 Subject: altosui: tile site maps --- ao-tools/altosui/AltosFlightUI.java | 4 +- ao-tools/altosui/AltosSiteMap.java | 138 +++--------------------- ao-tools/altosui/AltosSiteMapTile.java | 190 +++++++++++++++++++++++++++++++++ ao-tools/altosui/Makefile.am | 1 + 4 files changed, 206 insertions(+), 127 deletions(-) create mode 100644 ao-tools/altosui/AltosSiteMapTile.java diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 1372cc00..658d6f6f 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -48,6 +48,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { private AltosFlightStatus flightStatus; private JScrollPane flightInfoPane; + private JScrollPane sitemapPane; private AltosInfoTable flightInfo; static final int tab_pad = 1; @@ -167,7 +168,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Table", flightInfoPane); sitemap = new AltosSiteMap(); - pane.add("Site Map", sitemap); + sitemapPane = new JScrollPane(sitemap); + pane.add("Site Map", sitemapPane); vbox.add(pane); diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 25b77792..df1cc246 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -32,146 +32,32 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMap extends JComponent implements AltosFlightDisplay { - double lat, lng; - int zoom; - double scale_x, scale_y; - Point2D.Double coord_pt; - Point2D.Double last_pt; - - Graphics2D g2d; - - private boolean setLocation(double new_lat, double new_lng) { - int new_zoom = 15; - lat = new_lat; - lng = new_lng; - zoom = new_zoom; - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - coord_pt = pt(lat, lng, new Point2D.Double(0,0)); - coord_pt.x = 320-coord_pt.x; - coord_pt.y = 320-coord_pt.y; - last_pt = null; - - try { - File pngfile = new File(AltosPreferences.logdir(), - FileCoord(lat, lng, zoom)); - System.out.printf("Trying file %s\n", pngfile); - BufferedImage myPicture = ImageIO.read(pngfile); - picLabel.setIcon(new ImageIcon( myPicture )); - g2d = myPicture.createGraphics(); - } catch (Exception e) { - // throw new RuntimeException(e); - return false; - } - return true; - } - - private static double limit(double v, double lo, double hi) { - if (v < lo) - return lo; - if (hi < v) - return hi; - return v; - } - - private static String FileCoord(double lat, double lng, int zoom) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return String.format("map-%c%.3f,%c%.3f-%d.png", - chlat, lat, chlng, lng, zoom); - } - - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - private Point2D.Double pt(double lat, double lng) { - return pt(lat, lng, coord_pt); - } - - private Point2D.Double pt(double lat, double lng, Point2D.Double centre) { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = centre.x + lng*scale_x; - e = limit(Math.sin(Math.toRadians(lat)),-(1-1.0E-15),1-1.0E-15); - res.y = centre.y + 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - public void reset() { - // ? + // nothing } - - static Color stateColors[] = { - Color.WHITE, // startup - Color.WHITE, // idle - Color.WHITE, // pad - Color.RED, // boost - Color.PINK, // fast - Color.YELLOW, // coast - Color.CYAN, // drogue - Color.BLUE, // main - Color.BLACK // landed - }; - - boolean drawn_landed_circle = false; - boolean nomaps = false; public void show(AltosState state, int crc_errors) { - if (nomaps) - return; - if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) - return; - double plat = (int)(state.pad_lat*200)/200.0; - double plon = (int)(state.pad_lon*200)/200.0; - - if (last_pt == null) { - if (!setLocation(plat, plon)) { - nomaps = true; - return; - } - } - - Point2D.Double pt = pt(state.gps.lat, state.gps.lon); - if (last_pt != null && pt != last_pt) { - if (0 <= state.state && state.state < stateColors.length) { - g2d.setColor(stateColors[state.state]); - } - g2d.draw(new Line2D.Double(last_pt, pt)); - } - - if (state.state == 8 && !drawn_landed_circle) { - drawn_landed_circle = true; - g2d.setColor(Color.RED); - g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + for (int x = 0; x < mapTiles.length; x++) { + mapTiles[x].show(state, crc_errors); } - - last_pt = pt; - repaint(); } - - JLabel picLabel = new JLabel(); + + AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; public AltosSiteMap() { + GridBagLayout layout = new GridBagLayout(); setLayout(layout); GridBagConstraints c = new GridBagConstraints(); - - c.gridx = 0; c.gridy = 0; - c.weightx = 1; c.weighty = 1; c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; - picLabel = new JLabel(); - JScrollPane scrollPane = new JScrollPane(picLabel); - layout.setConstraints(scrollPane, c); - add(scrollPane); + for (int x = 0; x < 9; x++) { + c.gridx = x % 3; c.gridy = x / 3; + mapTiles[x] = new AltosSiteMapTile((x%3)-1, (x/3)-1); + layout.setConstraints(mapTiles[x], c); + add(mapTiles[x]); + } } } diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java new file mode 100644 index 00000000..d84941ae --- /dev/null +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -0,0 +1,190 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +public class AltosSiteMapTile extends JLabel { + double lat, lng; + int zoom; + double scale_x, scale_y; + Point2D.Double coord_pt; + Point2D.Double last_pt; + + Graphics2D g2d; + + int off_x; + int off_y; + + int px_size = 512; + + private boolean setLocation(double new_lat, double new_lng) { + int new_zoom = 16; + lat = new_lat; + lng = new_lng; + zoom = new_zoom; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + coord_pt = pt(lat, lng, new Point2D.Double(0,0)); + coord_pt.x = px_size/2-coord_pt.x - off_x * px_size; + coord_pt.y = px_size/2-coord_pt.y - off_y * px_size; + last_pt = null; + + Point2D.Double map_latlng; + map_latlng = latlng(new Point2D.Double(px_size/2, px_size/2)); + + BufferedImage myPicture; + File pngfile = new File(AltosPreferences.logdir(), + FileCoord(map_latlng, zoom)); + try { + myPicture = ImageIO.read(pngfile); + System.out.printf("# Found file %s\n", pngfile); + } catch (Exception e) { + // throw new RuntimeException(e); + System.out.printf("# Failed to find file %s\n", pngfile); + System.out.printf(" wget -O '%s' 'http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32'\n", pngfile, map_latlng.x, map_latlng.y, zoom, px_size, px_size); + myPicture = new BufferedImage(px_size, px_size, + BufferedImage.TYPE_INT_RGB); + } + setIcon(new ImageIcon( myPicture )); + g2d = myPicture.createGraphics(); + return true; + } + + private static double limit(double v, double lo, double hi) { + if (v < lo) + return lo; + if (hi < v) + return hi; + return v; + } + + private static String FileCoord(Point2D.Double latlng, int zoom) { + double lat, lng; + lat = latlng.x; + lng = latlng.y; + return FileCoord(lat, lng, zoom); + } + private static String FileCoord(double lat, double lng, int zoom) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return String.format("map-%c%.3f,%c%.3f-%d.png", + chlat, lat, chlng, lng, zoom); + } + + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + private Point2D.Double pt(double lat, double lng) { + return pt(lat, lng, coord_pt); + } + + private Point2D.Double pt(double lat, double lng, Point2D.Double centre) { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = centre.x + lng*scale_x; + e = limit(Math.sin(Math.toRadians(lat)),-(1-1.0E-15),1-1.0E-15); + res.y = centre.y + 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + private Point2D.Double latlng(Point2D.Double pt) { + return latlng(pt, coord_pt); + } + private Point2D.Double latlng(Point2D.Double pt, Point2D.Double centre) { + double lat, lng; + double rads; + + lng = (pt.x - centre.x)/scale_x; + rads = 2 * Math.atan(Math.exp((pt.y-centre.y)/-scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new Point2D.Double(lat,lng); + } + + static Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK // landed + }; + + boolean drawn_landed_circle = false; + boolean nomaps = false; + public void show(AltosState state, int crc_errors) { + if (nomaps) + return; + if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) + return; + double plat = (int)(state.pad_lat*200)/200.0; + double plon = (int)(state.pad_lon*200)/200.0; + + if (last_pt == null) { + if (!setLocation(plat, plon)) { + nomaps = true; + return; + } + } + + Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + if (last_pt != null && pt != last_pt) { + if (0 <= state.state && state.state < stateColors.length) { + g2d.setColor(stateColors[state.state]); + } + g2d.draw(new Line2D.Double(last_pt, pt)); + } + + if (state.state == 8 && !drawn_landed_circle) { + drawn_landed_circle = true; + g2d.setColor(Color.RED); + g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + + last_pt = pt; + repaint(); + } + + public AltosSiteMapTile(int x_tile_offset, int y_tile_offset) { + off_x = x_tile_offset; + off_y = y_tile_offset; + } +} + diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 1c24ce13..b6b2e572 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -62,6 +62,7 @@ altosui_JAVA = \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosSiteMap.java \ + AltosSiteMapTile.java \ AltosState.java \ AltosTelemetry.java \ AltosTelemetryIterable.java \ -- cgit v1.2.3 From fda93afcd8aa4133b0e5f008b824d072e338d0ed Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 19 Nov 2010 13:02:05 +1000 Subject: AltosSiteMapTile: autoscale to about 2 nmi per tile --- ao-tools/altosui/AltosSiteMapTile.java | 37 +++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index d84941ae..919de825 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -32,7 +32,6 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMapTile extends JLabel { - double lat, lng; int zoom; double scale_x, scale_y; Point2D.Double coord_pt; @@ -45,16 +44,20 @@ public class AltosSiteMapTile extends JLabel { int px_size = 512; - private boolean setLocation(double new_lat, double new_lng) { - int new_zoom = 16; - lat = new_lat; - lng = new_lng; - zoom = new_zoom; + private boolean setLocation(double lat, double lng) { + Point2D.Double north_1nm; + for (zoom = 3; zoom < 22; zoom++) { + coord_pt = pt(lat, lng, new Point2D.Double(0,0), zoom); + north_1nm = pt(lat+1/60.0, lng, new Point2D.Double(0,0), zoom); + if (coord_pt.y - north_1nm.y > px_size/2) + break; + } + coord_pt.x = px_size/2 - ((long)coord_pt.x/px_size + off_x) * px_size; + coord_pt.y = px_size/2 - ((long)coord_pt.y/px_size + off_y) * px_size; + scale_x = 256/360.0 * Math.pow(2, zoom); scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - coord_pt = pt(lat, lng, new Point2D.Double(0,0)); - coord_pt.x = px_size/2-coord_pt.x - off_x * px_size; - coord_pt.y = px_size/2-coord_pt.y - off_y * px_size; + last_pt = null; Point2D.Double map_latlng; @@ -97,7 +100,7 @@ public class AltosSiteMapTile extends JLabel { char chlng = lng < 0 ? 'E' : 'W'; if (lat < 0) lat = -lat; if (lng < 0) lng = -lng; - return String.format("map-%c%.3f,%c%.3f-%d.png", + return String.format("map-%c%.6f,%c%.6f-%d.png", chlat, lat, chlng, lng, zoom); } @@ -106,10 +109,20 @@ public class AltosSiteMapTile extends JLabel { // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js // search for fromLatLngToPoint and fromPointToLatLng private Point2D.Double pt(double lat, double lng) { - return pt(lat, lng, coord_pt); + return pt(lat, lng, coord_pt, scale_x, scale_y); + } + + private static Point2D.Double pt(double lat, double lng, + Point2D.Double centre, int zoom) + { + double scale_x = 256/360.0 * Math.pow(2, zoom); + double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + return pt(lat, lng, centre, scale_x, scale_y); } - private Point2D.Double pt(double lat, double lng, Point2D.Double centre) { + private static Point2D.Double pt(double lat, double lng, + Point2D.Double centre, double scale_x, double scale_y) + { Point2D.Double res = new Point2D.Double(); double e; -- cgit v1.2.3 From fa45336062523838ba8abb08427cdc4d9c7de7a8 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 19 Nov 2010 13:17:29 +1000 Subject: AltosSiteMapTile: adjust centering calculation --- ao-tools/altosui/AltosSiteMapTile.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index 919de825..6f5ddede 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -52,8 +52,8 @@ public class AltosSiteMapTile extends JLabel { if (coord_pt.y - north_1nm.y > px_size/2) break; } - coord_pt.x = px_size/2 - ((long)coord_pt.x/px_size + off_x) * px_size; - coord_pt.y = px_size/2 - ((long)coord_pt.y/px_size + off_y) * px_size; + coord_pt.x = -px_size * Math.floor(coord_pt.x/px_size + off_x); + coord_pt.y = -px_size * Math.floor(coord_pt.y/px_size + off_y); scale_x = 256/360.0 * Math.pow(2, zoom); scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); -- cgit v1.2.3 From 90b9bc4475011bead7117ed72fa5efa0f77b2813 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 19 Nov 2010 13:30:00 +1000 Subject: AltosSiteMapTile: adjust scale to 1 nmi per tile --- ao-tools/altosui/AltosSiteMapTile.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index 6f5ddede..c14fb93f 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -45,11 +45,13 @@ public class AltosSiteMapTile extends JLabel { int px_size = 512; private boolean setLocation(double lat, double lng) { - Point2D.Double north_1nm; + Point2D.Double north_step; + double step_nm = 0.5; for (zoom = 3; zoom < 22; zoom++) { coord_pt = pt(lat, lng, new Point2D.Double(0,0), zoom); - north_1nm = pt(lat+1/60.0, lng, new Point2D.Double(0,0), zoom); - if (coord_pt.y - north_1nm.y > px_size/2) + north_step = pt(lat+step_nm/60.0, lng, + new Point2D.Double(0,0), zoom); + if (coord_pt.y - north_step.y > px_size/2) break; } coord_pt.x = -px_size * Math.floor(coord_pt.x/px_size + off_x); -- cgit v1.2.3 From 24ffcf86c43290ce0f70fb4ee0984b3debdb8a5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 15:41:30 +0800 Subject: altosui: Add igniter ground testing code Not yet hooked up, but the UI is finished. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosIgnite.java | 155 ++++++++++++++++++++++++++++++ ao-tools/altosui/AltosIgniteUI.java | 183 ++++++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosUI.java | 23 +++-- ao-tools/altosui/Makefile.am | 2 + 4 files changed, 357 insertions(+), 6 deletions(-) create mode 100644 ao-tools/altosui/AltosIgnite.java create mode 100644 ao-tools/altosui/AltosIgniteUI.java diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java new file mode 100644 index 00000000..5c27e8fa --- /dev/null +++ b/ao-tools/altosui/AltosIgnite.java @@ -0,0 +1,155 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +public class AltosIgnite { + AltosDevice device; + AltosSerial serial; + boolean remote; + final static int None = 0; + final static int Apogee = 1; + final static int Main = 2; + + final static int Unknown = 0; + final static int Ready = 1; + final static int Active = 2; + final static int Open = 3; + + private void start_serial() throws InterruptedException { + if (remote) { + serial.set_channel(AltosPreferences.channel(device.getSerial())); + serial.set_callsign(AltosPreferences.callsign()); + serial.printf("~\np\n"); + serial.flush_input(); + } + } + + private void stop_serial() throws InterruptedException { + if (serial == null) + return; + if (remote) { + serial.printf("~"); + serial.flush_output(); + } + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + private int status(String status_name) { + if (status_name.equals("unknown")) + return Unknown; + if (status_name.equals("ready")) + return Ready; + if (status_name.equals("active")) + return Active; + if (status_name.equals("open")) + return Open; + return Unknown; + } + + public int status(int igniter) { + int status = Unknown; + if (serial == null) + return status; + string_ref status_name = new string_ref(); + try { + start_serial(); + serial.printf("t\n"); + for (;;) { + String line = serial.get_reply(); + if (get_string(line, "Igniter: drogue Status: ", status_name)) + if (igniter == Apogee) + status = status(status_name.get()); + if (get_string(line, "Igniter: main Status: ", status_name)) { + if (igniter == Main) + status = status(status_name.get()); + break; + } + } + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + return status; + } + + public void fire(int igniter) { + if (serial == null) + return; + try { + start_serial(); + switch (igniter) { + case Main: + serial.printf("i DoIt main\n"); + break; + case Apogee: + serial.printf("i DoIt drogue\n"); + break; + } + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + + device = in_device; + serial = null; +// serial = new AltosSerial(device); + remote = false; + +// if (!device.matchProduct(AltosDevice.product_telemetrum)) +// remote = true; + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java new file mode 100644 index 00000000..62da413c --- /dev/null +++ b/ao-tools/altosui/AltosIgniteUI.java @@ -0,0 +1,183 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +public class AltosIgniteUI + extends JDialog + implements ActionListener +{ + JFrame owner; + JLabel label; + JRadioButton apogee; + JRadioButton main; + JToggleButton arm; + JButton fire; + javax.swing.Timer timer; + + final static int timeout = 1 * 1000; + + int time_remaining; + + void set_arm_text() { + if (arm.isSelected()) + arm.setText(String.format("%d", time_remaining)); + else + arm.setText("Arm"); + } + + void start_timer() { + time_remaining = 10; + set_arm_text(); + timer.restart(); + } + + void stop_timer() { + time_remaining = 0; + arm.setSelected(false); + arm.setEnabled(false); + fire.setEnabled(false); + timer.stop(); + set_arm_text(); + } + + void cancel () { + apogee.setSelected(false); + main.setSelected(false); + fire.setEnabled(false); + stop_timer(); + } + + void tick_timer() { + --time_remaining; + if (time_remaining <= 0) + cancel(); + else + set_arm_text(); + } + + void fire() { + if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) { + int igniter = AltosIgnite.None; + if (apogee.isSelected() && !main.isSelected()) + igniter = AltosIgnite.Apogee; + else if (main.isSelected() && !apogee.isSelected()) + igniter = AltosIgnite.Main; + System.out.printf ("fire %d\n", igniter); + cancel(); + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd.equals("apogee") || cmd.equals("main")) { + stop_timer(); + arm.setEnabled(true); + } + + if (cmd.equals("apogee") && apogee.isSelected()) + main.setSelected(false); + if (cmd.equals("main") && main.isSelected()) + apogee.setSelected(false); + + if (cmd.equals("arm")) { + if (arm.isSelected()) { + fire.setEnabled(true); + start_timer(); + } else + cancel(); + } + if (cmd.equals("fire")) + fire(); + if (cmd.equals("tick")) + tick_timer(); + } + + public AltosIgniteUI(JFrame in_owner) { + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + timer = new javax.swing.Timer(timeout, this); + timer.setActionCommand("tick"); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + label = new JLabel ("Fire Igniter"); + pane.add(label, c); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + apogee = new JRadioButton ("Apogee"); + pane.add(apogee, c); + apogee.addActionListener(this); + apogee.setActionCommand("apogee"); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + main = new JRadioButton ("Main"); + pane.add(main, c); + main.addActionListener(this); + main.setActionCommand("main"); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + arm = new JToggleButton ("Arm"); + pane.add(arm, c); + arm.addActionListener(this); + arm.setActionCommand("arm"); + arm.setEnabled(false); + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + fire = new JButton ("Fire"); + fire.setEnabled(false); + pane.add(fire, c); + fire.addActionListener(this); + fire.setActionCommand("fire"); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} \ No newline at end of file diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index bedf2459..5e9566f0 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -125,40 +125,47 @@ public class AltosUI extends JFrame { Replay(); } }); - b = addButton(0, 1, "Graph Data"); + b = addButton(3, 0, "Graph Data"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { GraphData(); } }); - b = addButton(1, 1, "Export Data"); + b = addButton(4, 0, "Export Data"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ExportData(); } }); - b = addButton(2, 1, "Configure TeleMetrum"); + b = addButton(0, 1, "Configure TeleMetrum"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureTeleMetrum(); } }); - b = addButton(0, 2, "Configure AltosUI"); + b = addButton(1, 1, "Configure AltosUI"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureAltosUI(); } }); - b = addButton(1, 2, "Flash Image"); + b = addButton(2, 1, "Flash Image"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FlashImage(); } }); - b = addButton(2, 2, "Quit"); + b = addButton(3, 1, "Fire Igniter"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FireIgniter(); + } + }); + + b = addButton(4, 1, "Quit"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); @@ -215,6 +222,10 @@ public class AltosUI extends JFrame { new AltosFlashUI(AltosUI.this); } + void FireIgniter() { + new AltosIgniteUI(AltosUI.this); + } + /* * Replay a flight from telemetry data */ diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 8d0fe16e..25977b12 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -40,6 +40,8 @@ altosui_JAVA = \ AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ + AltosIgnite.java \ + AltosIgniteUI.java \ AltosInfoTable.java \ AltosKML.java \ AltosLanded.java \ -- cgit v1.2.3 From 8f72f08839346fb225238420324f0edcd070e531 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 17:14:17 +0800 Subject: altosui: Unify datafile selection to AltosDataChooser Instead of having several separate intefaces, use a single dialog for selecting data files for graph/export/replay. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosCSVUI.java | 73 +++++++++++++------------- ao-tools/altosui/AltosDataChooser.java | 79 +++++++++++++++++++++++++++++ ao-tools/altosui/AltosGraphDataChooser.java | 79 ----------------------------- ao-tools/altosui/AltosGraphUI.java | 17 +++---- ao-tools/altosui/AltosLogfileChooser.java | 78 ---------------------------- ao-tools/altosui/AltosUI.java | 17 +++++-- ao-tools/altosui/Makefile.am | 3 +- 7 files changed, 140 insertions(+), 206 deletions(-) create mode 100644 ao-tools/altosui/AltosDataChooser.java delete mode 100644 ao-tools/altosui/AltosGraphDataChooser.java delete mode 100644 ao-tools/altosui/AltosLogfileChooser.java diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java index 16f25338..e1b6002d 100644 --- a/ao-tools/altosui/AltosCSVUI.java +++ b/ao-tools/altosui/AltosCSVUI.java @@ -30,16 +30,15 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosCSVUI extends JDialog - implements Runnable, ActionListener + implements ActionListener { - JFrame frame; - Thread thread; - AltosRecordIterable iterable; - AltosWriter writer; JFileChooser csv_chooser; + JPanel accessory; JComboBox combo_box; + AltosRecordIterable iterable; + AltosWriter writer; - static String[] combo_box_items = { "CSV", "KML" }; + static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; void set_default_file() { File current = csv_chooser.getSelectedFile(); @@ -47,57 +46,63 @@ public class AltosCSVUI String new_name = null; String selected = (String) combo_box.getSelectedItem(); - if (selected.equals("CSV")) + if (selected.contains("CSV")) new_name = Altos.replace_extension(current_name, ".csv"); - else if (selected.equals("KML")) + else if (selected.contains("KML")) new_name = Altos.replace_extension(current_name, ".kml"); if (new_name != null) csv_chooser.setSelectedFile(new File(new_name)); } - public void run() { - AltosLogfileChooser chooser; + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("comboBoxChanged")) + set_default_file(); + } + + public AltosCSVUI(JFrame frame, AltosRecordIterable in_iterable, File source_file) { + iterable = in_iterable; + csv_chooser = new JFileChooser(source_file); + + accessory = new JPanel(); + accessory.setLayout(new GridBagLayout()); - chooser = new AltosLogfileChooser(frame); - iterable = chooser.runDialog(); - if (iterable == null) - return; + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.weightx = 1; + c.weighty = 0; + c.insets = new Insets (4, 4, 4, 4); + + JLabel accessory_label = new JLabel("Export File Type"); + c.gridx = 0; + c.gridy = 0; + accessory.add(accessory_label, c); - csv_chooser = new JFileChooser(chooser.file()); combo_box = new JComboBox(combo_box_items); combo_box.addActionListener(this); - csv_chooser.setAccessory(combo_box); - csv_chooser.setSelectedFile(chooser.file()); + c.gridx = 0; + c.gridy = 1; + accessory.add(combo_box, c); + + csv_chooser.setAccessory(accessory); + csv_chooser.setSelectedFile(source_file); set_default_file(); int ret = csv_chooser.showSaveDialog(frame); if (ret == JFileChooser.APPROVE_OPTION) { - File file = csv_chooser.getSelectedFile(); - String type = (String) combo_box.getSelectedItem(); + File file = csv_chooser.getSelectedFile(); + String type = (String) combo_box.getSelectedItem(); try { - if (type.equals("CSV")) + if (type.contains("CSV")) writer = new AltosCSV(file); else writer = new AltosKML(file); + writer.write(iterable); + writer.close(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, file.getName(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } - writer.write(iterable); - writer.close(); } } - - public void actionPerformed(ActionEvent e) { - System.out.printf("command %s param %s\n", e.getActionCommand(), e.paramString()); - if (e.getActionCommand().equals("comboBoxChanged")) - set_default_file(); - } - - public AltosCSVUI(JFrame in_frame) { - frame = in_frame; - thread = new Thread(this); - thread.start(); - } } diff --git a/ao-tools/altosui/AltosDataChooser.java b/ao-tools/altosui/AltosDataChooser.java new file mode 100644 index 00000000..15de05c2 --- /dev/null +++ b/ao-tools/altosui/AltosDataChooser.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +public class AltosDataChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public AltosRecordIterable runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + if (filename.endsWith("eeprom")) { + FileInputStream in = new FileInputStream(file); + return new AltosEepromIterable(in); + } else if (filename.endsWith("telem")) { + FileInputStream in = new FileInputStream(file); + return new AltosTelemetryIterable(in); + } else { + throw new FileNotFoundException(); + } + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + filename, + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public AltosDataChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "telem", "eeprom")); + setCurrentDirectory(AltosPreferences.logdir()); + } +} diff --git a/ao-tools/altosui/AltosGraphDataChooser.java b/ao-tools/altosui/AltosGraphDataChooser.java deleted file mode 100644 index d128f4d5..00000000 --- a/ao-tools/altosui/AltosGraphDataChooser.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -public class AltosGraphDataChooser extends JFileChooser { - JFrame frame; - String filename; - File file; - - public String filename() { - return filename; - } - - public File file() { - return file; - } - - public Iterable runDialog() { - int ret; - - ret = showOpenDialog(frame); - if (ret == APPROVE_OPTION) { - file = getSelectedFile(); - if (file == null) - return null; - filename = file.getName(); - try { - if (filename.endsWith("eeprom")) { - FileInputStream in = new FileInputStream(file); - return new AltosDataPointReader(new AltosEepromIterable(in)); - } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - return new AltosDataPointReader(new AltosTelemetryIterable(in)); - } else { - throw new FileNotFoundException(); - } - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - filename, - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } - return null; - } - - public AltosGraphDataChooser(JFrame in_frame) { - frame = in_frame; - setDialogTitle("Select Flight Record File"); - setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom")); - setCurrentDirectory(AltosPreferences.logdir()); - } -} diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java index 908aa3b4..cd158651 100644 --- a/ao-tools/altosui/AltosGraphUI.java +++ b/ao-tools/altosui/AltosGraphUI.java @@ -151,18 +151,15 @@ public class AltosGraphUI extends JFrame } } - public AltosGraphUI(JFrame frame) - { - super("Altos Graph"); + public AltosGraphUI(AltosRecordIterable records) { + super("Altos Graph"); - AltosGraphDataChooser chooser; - chooser = new AltosGraphDataChooser(frame); - Iterable reader = chooser.runDialog(); - if (reader == null) - return; + Iterable reader = new AltosDataPointReader (records); + if (reader == null) + return; - init(reader, 0); - } + init(reader, 0); + } public AltosGraphUI(Iterable data, int which) { diff --git a/ao-tools/altosui/AltosLogfileChooser.java b/ao-tools/altosui/AltosLogfileChooser.java deleted file mode 100644 index 8b9d77d6..00000000 --- a/ao-tools/altosui/AltosLogfileChooser.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -public class AltosLogfileChooser extends JFileChooser { - JFrame frame; - String filename; - File file; - - public String filename() { - return filename; - } - - public File file() { - return file; - } - - public AltosRecordIterable 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 AltosEepromIterable(in); - else - return new AltosTelemetryIterable(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 diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 5e9566f0..c82c8e8a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -230,8 +230,9 @@ public class AltosUI extends JFrame { * Replay a flight from telemetry data */ private void Replay() { - AltosLogfileChooser chooser = new AltosLogfileChooser( + AltosDataChooser chooser = new AltosDataChooser( AltosUI.this); + AltosRecordIterable iterable = chooser.runDialog(); if (iterable != null) { AltosFlightReader reader = new AltosReplayReader(iterable.iterator(), @@ -252,14 +253,24 @@ public class AltosUI extends JFrame { */ private void ExportData() { - new AltosCSVUI(AltosUI.this); + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosRecordIterable record_reader = chooser.runDialog(); + if (record_reader == null) + return; + new AltosCSVUI(AltosUI.this, record_reader, chooser.file()); } /* Load a flight log CSV file and display a pretty graph. */ private void GraphData() { - new AltosGraphUI(AltosUI.this); + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosRecordIterable record_reader = chooser.runDialog(); + if (record_reader == null) + return; + new AltosGraphUI(record_reader); } private void ConfigureAltosUI() { diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 25977b12..a603ca8a 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -48,7 +48,6 @@ altosui_JAVA = \ AltosLed.java \ AltosLights.java \ AltosLine.java \ - AltosLogfileChooser.java \ AltosLog.java \ AltosPad.java \ AltosParse.java \ @@ -73,7 +72,7 @@ altosui_JAVA = \ AltosGraph.java \ AltosGraphTime.java \ AltosGraphUI.java \ - AltosGraphDataChooser.java \ + AltosDataChooser.java \ AltosVoice.java JFREECHART_CLASS= \ -- cgit v1.2.3 From 0e7a10f71803d60f8b34c5a91efd220449442769 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 17:16:03 +0800 Subject: altosui: Clean up global AltosUI configuration settings dialog This dialog had a mish-mash of styles and was confusing. Now it's got a label for each line, and suitable setters for each element Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfigureUI.java | 71 +++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/ao-tools/altosui/AltosConfigureUI.java b/ao-tools/altosui/AltosConfigureUI.java index 64c17eaf..153c59fd 100644 --- a/ao-tools/altosui/AltosConfigureUI.java +++ b/ao-tools/altosui/AltosConfigureUI.java @@ -75,12 +75,25 @@ public class AltosConfigureUI c = new GridBagConstraints(); c.insets = insets; c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; + c.anchor = GridBagConstraints.WEST; - /* Enable Voice */ + /* Nice label at the top */ c.gridx = 0; c.gridy = 0; - enable_voice = new JRadioButton("Enable Voice", AltosPreferences.voice()); + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + pane.add(new JLabel ("Configure AltOS UI"), c); + + /* Voice settings */ + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Voice"), c); + + enable_voice = new JRadioButton("Enable", AltosPreferences.voice()); enable_voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); @@ -92,9 +105,20 @@ public class AltosConfigureUI voice.speak_always("Disable voice."); } }); - pane.add(enable_voice, c); c.gridx = 1; - c.gridy = 0; + c.gridy = 1; + c.gridwidth = 1; + c.weightx = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(enable_voice, c); + + c.gridx = 2; + c.gridy = 1; + c.gridwidth = 1; + c.weightx = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.EAST; test_voice = new JButton("Test Voice"); test_voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -103,36 +127,46 @@ public class AltosConfigureUI }); pane.add(test_voice, c); - configure_log = new JButton("Configure Log"); + /* Log directory settings */ + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Log Directory"), c); + + configure_log = new JButton(AltosPreferences.logdir().getPath()); configure_log.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AltosPreferences.ConfigureLog(); - log_directory.setText(AltosPreferences.logdir().getPath()); + configure_log.setText(AltosPreferences.logdir().getPath()); } }); - c.gridwidth = 1; - - c.gridx = 0; - c.gridy = 2; - pane.add(configure_log, c); - - log_directory = new JTextField(AltosPreferences.logdir().getPath()); c.gridx = 1; c.gridy = 2; + c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; - pane.add(log_directory, c); + c.anchor = GridBagConstraints.WEST; + pane.add(configure_log, c); - callsign_label = new JLabel("Callsign"); + /* Callsign setting */ c.gridx = 0; c.gridy = 3; - pane.add(callsign_label, c); + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Callsign"), c); callsign_value = new JTextField(AltosPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); c.gridx = 1; c.gridy = 3; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; pane.add(callsign_value, c); + /* And a close button at the bottom */ close = new JButton("Close"); close.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -141,8 +175,9 @@ public class AltosConfigureUI }); c.gridx = 0; c.gridy = 4; - c.gridwidth = 2; + c.gridwidth = 3; c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; pane.add(close, c); pack(); -- cgit v1.2.3 From f0542085de2139ef562af068ec05fa73f47c73b1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 20:26:49 +0800 Subject: doc: Add preliminary altosui documentation Also, update the Makefile to allow for further documents to be added without a lot of custom rules. Signed-off-by: Keith Packard --- doc/Makefile | 37 ++-- doc/altosui-doc.xsl | 561 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 581 insertions(+), 17 deletions(-) create mode 100644 doc/altosui-doc.xsl diff --git a/doc/Makefile b/doc/Makefile index 238cefb0..57300c10 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,32 +2,35 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -all: telemetrum-doc.html telemetrum-doc.pdf +HTML=telemetrum-doc.html altosui-doc.html +PDF=telemetrum-doc.pdf altosui-doc.pdf +DOC=$(HTML) $(PDF) +HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl +FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl +PDFSTYLE= -publish: all - cp telemetrum-doc.html \ - telemetrum-doc.pdf /home/bdale/web/altusmetrum/TeleMetrum/doc/ - (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/TeleMetrum/doc/* ; git push) +.SUFFIXES: .xsl .html .fo .pdf + +.xsl.html: + xsltproc -o $@ $(HTMLSTYLE) $*.xsl +.xsl.fo: + xsltproc -o $@ $(FOSTYLE) $*.xsl -telemetrum-doc.html: telemetrum-doc.xsl - xsltproc -o telemetrum-doc.html \ - /usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl \ - telemetrum-doc.xsl +.fo.pdf: + fop -fo $*.fo -pdf $@ -telemetrum-doc.fo: telemetrum-doc.xsl - xsltproc -o telemetrum-doc.fo \ - /usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl \ - telemetrum-doc.xsl +all: $(HTML) $(PDF) -telemetrum-doc.pdf: telemetrum-doc.fo - fop -fo telemetrum-doc.fo -pdf telemetrum-doc.pdf +publish: $(DOC) + cp $(DOC)telemetrum-doc.html home/bdale/web/altusmetrum/TeleMetrum/doc/ + (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/TeleMetrum/doc/* ; git push) clean: - rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo + rm -f *.html *.pdf *.fo distclean: - rm -f telemetrum-doc.html telemetrum-doc.pdf telemetrum-doc.fo + rm -f *.html *.pdf *.fo indent: telemetrum-doc.xsl xmlindent -i 2 < telemetrum-doc.xsl > telemetrum-doc.new diff --git a/doc/altosui-doc.xsl b/doc/altosui-doc.xsl new file mode 100644 index 00000000..5f330739 --- /dev/null +++ b/doc/altosui-doc.xsl @@ -0,0 +1,561 @@ + + + + AltosUI + Altos Metrum Graphical User Interface Manual + + + Bdale + Garbee + + + Keith + Packard + + + 2010 + Bdale Garbee and Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.1 + 19 November 2010 + Initial content + + + + + Introduction + + The AltosUI program provides a graphical user interface for + interacting with the Altus Metrum product family, including + TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, + configure TeleMetrum and TeleDongle devices and many other + tasks. The primary interface window provides a selection of + buttons, one for each major activity in the system. This manual + is split into chapters, each of which documents one of the tasks + provided from the top-level toolbar. + + + + Packet Command Mode + Controlling TeleMetrum Over The Radio Link + + One of the unique features of the Altos Metrum environment is + the ability to create a two way command link between TeleDongle + and TeleMetrum using the digital radio transceivers built into + each device. This allows you to interact with TeleMetrum from + afar, as if it were directly connected to the computer. + + + Any operation which can be performed with TeleMetrum + can either be done with TeleMetrum directly connected to + the computer via the USB cable, or through the packet + link. Simply select the appropriate TeleDongle device when + the list of devices is presented and AltosUI will use packet + command mode. + + + + + Save Flight Data—Recover flight data from the rocket without + opening it up. + + + + + Configure TeleMetrum—Reset apogee delays or main deploy + heights to respond to changing launch conditions. You can + also 'reboot' the TeleMetrum device. Use this to remotely + enable the flight computer by turning TeleMetrum on while + horizontal, then once the airframe is oriented for launch, + you can reboot TeleMetrum and have it restart in pad mode + without having to climb the scary ladder. + + + + + Fire Igniters—Test your deployment charges without snaking + wires out through holes in the airframe. Simply assembly the + rocket as if for flight with the apogee and main charges + loaded, then remotely command TeleMetrum to fire the + igniters. + + + + + Packet command mode uses the same RF channels as telemetry + mode. Configure the desired TeleDongle channel using the + flight monitor window channel selector and then close that + window before performing the desired operation. + + + TeleMetrum only enables packet command mode in 'idle' mode, so + make sure you have TeleMetrum lying horizontally when you turn + it on. Otherwise, TeleMetrum will start in 'pad' mode ready for + flight and will not be listening for command packets from TeleDongle. + + + When packet command mode is enabled, you can monitor the link + by watching the lights on the TeleDongle and TeleMetrum + devices. The red LED will flash each time TeleDongle or + TeleMetrum transmit a packet while the green LED will light up + on TeleDongle while it is waiting to receive a packet from + TeleMetrum. + + + + Monitor Flight + Receive, Record and Display Telemetry Data + + Selecting this item brings up a dialog box listing all of the + connected TeleDongle devices. When you choose one of these, + AltosUI will create a window to display telemetry data as + received by the selected TeleDongle device. + + + All telemetry data received are automatically recorded in + suitable log files. The name of the files includes the current + date and rocket serial and flight numbers. + + + The radio channel being monitored by the TeleDongle device is + displayed at the top of the window. You can configure the + channel by clicking on the channel box and selecting the desired + channel. AltosUI remembers the last channel selected for each + TeleDongle and selects that automatically the next time you use + that device. + + + Below the TeleDongle channel selector, the window contains a few + significant pieces of information about the TeleMetrum providing + the telemetry data stream: + + + + The TeleMetrum callsign + + + The TeleMetrum serial number + + + The flight number. Each TeleMetrum remembers how many + times it has flown. + + + + The rocket flight state. Each flight passes through several + states including Pad, Boost, Fast, Coast, Drogue, Main and + Landed. + + + + + The Received Signal Strength Indicator value. This lets + you know how strong a signal TeleDongle is receiving. The + radio inside TeleDongle operates down to about -99dBm; + weaker signals may not be receiveable. The packet link uses + error correction and detection techniques which prevent + incorrect data from being reported. + + + + + Finally, the largest portion of the window contains a set of + tabs, each of which contain some information about the rocket. + They're arranged in 'flight order' so that as the flight + progresses, the selected tab automatically switches to display + data relevant to the current state of the flight. You can select + other tabs at any time. The final 'table' tab contains all of + the telemetry data in one place. + +
+ Launch Pad + + The 'Launch Pad' tab shows information used to decide when the + rocket is ready for flight. The first elements include red/green + indicators, if any of these is red, you'll want to evaluate + whether the rocket is ready to launch: + + + + Battery Voltage. This indicates whether the LiPo battery + powering the TeleMetrum has sufficient charge to last for + the duration of the flight. A value of more than + 3.7V is required for a 'GO' status. + + + + + Apogee Igniter Voltage. This indicates whether the apogee + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + Main Igniter Voltage. This indicates whether the main + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + GPS Locked. This indicates whether the GPS receiver is + currently able to compute position information. GPS requires + at least 4 satellites to compute an accurate position. + + + + + GPS Ready. This indicates whether GPS has reported at least + 10 consecutive positions without losing lock. This ensures + that the GPS receiver has reliable reception from the + satellites. + + + + + The LaunchPad tab also shows the computed launch pad position + and altitude, averaging many reported positions to improve the + accuracy of the fix. + + +
+
+ Ascent + + This tab is shown during Boost, Fast and Coast + phases. The information displayed here helps monitor the + rocket as it heads towards apogee. + + + The height, speed and acceleration are shown along with the + maxium values for each of them. This allows you to quickly + answer the most commonly asked questions you'll hear during + flight. + + + The current latitude and longitude reported by the GPS are + also shown. Note that under high acceleration, these values + may not get updated as the GPS receiver loses position + fix. Once the rocket starts coasting, the receiver should + start reporting position again. + + + Finally, the current igniter voltages are reported as in the + Launch Pad tab. This can help diagnose deployment failures + caused by wiring which comes loose under high acceleration. + +
+
+ Descent + + Once the rocket has reached apogee and (we hope) activated the + apogee charge, attention switches to tracking the rocket on + the way back to the ground, and for dual-deploy flights, + waiting for the main charge to fire. + + + To monitor whether the apogee charge operated correctly, the + current descent rate is reported along with the current + height. Good descent rates generally range from 15-30m/s. + + + To help locate the rocket in the sky, use the elevation and + bearing information to figure out where to look. Elevation is + in degrees above the horizon. Bearing is reported in degrees + relative to true north. Range can help figure out how big the + rocket will appear. Note that all of these values are relative + to the pad location. If the elevation is near 90°, the rocket + is over the pad, not over you. + + + Finally, the igniter voltages are reported in this tab as + well, both to monitor the main charge as well as to see what + the status of the apogee charge is. + +
+
+ Landed + + Once the rocket is on the ground, attention switches to + recovery. While the radio signal is generally lost once the + rocket is on the ground, the last reported GPS position is + generally within a short distance of the actual landing location. + + + The last reported GPS position is reported both by + latitude and longitude as well as a bearing and distance from + the launch pad. The distance should give you a good idea of + whether you'll want to walk or hitch a ride. Take the reported + latitude and longitude and enter them into your handheld GPS + unit and have that compute a track to the landing location. + + + Finally, the maximum height, speed and acceleration reported + during the flight are displayed for your admiring observers. + +
+
+ + Save Flight Data + + TeleMetrum records flight data to its internal flash memory. + This data is recorded at a much higher rate than the telemetry + system can handle, and is not subject to radio drop-outs. As + such, it provides a more complete and precise record of the + flight. The 'Save Flight Data' button allows you to read the + flash memory and write it to disk. + + + Clicking on the 'Save Flight Data' button brings up a list of + connected TeleMetrum and TeleDongle devices. If you select a + TeleMetrum device, the flight data will be downloaded from that + device directly. If you select a TeleDongle device, flight data + will be downloaded from a TeleMetrum device connected via the + packet command link to the specified TeleDongle. See the chapter + on Packet Command Mode for more information about this. + + + The filename for the data is computed automatically from the recorded + flight date, TeleMetrum serial number and flight number + information. + + + + Replay Flight + + Select this button and you are prompted to select a flight + record file, either a .telem file recording telemetry data or a + .eeprom file containing flight data saved from the TeleMetrum + flash memory. + + + Once a flight record is selected, the flight monitor interface + is displayed and the flight is re-enacted in real time. Check + the Monitor Flight chapter above to learn how this window operates. + + + + Graph Data + + This section should be written by AJ. + + + + Export Data + + This tool takes the raw data files and makes them available for + external analysis. When you select this button, you are prompted to select a flight + data file (either .eeprom or .telem will do, remember that + .eeprom files contain higher resolution and more continuous + data). Next, a second dialog appears which is used to select + where to write the resulting file. It has a selector to choose + between CSV and KML file formats. + +
+ Comma Separated Value Format + + This is a text file containing the data in a form suitable for + import into a spreadsheet or other external data analysis + tool. The first few lines of the file contain the version and + configuration information from the TeleMetrum device, then + there is a single header line which labels all of the + fields. All of these lines start with a '#' character which + most tools can be configured to skip over. + + + The remaining lines of the file contain the data, with each + field separated by a comma and at least one space. All of + the sensor values are converted to standard units, with the + barometric data reported in both pressure, altitude and + height above pad units. + +
+
+ Keyhole Markup Language (for Google Earth) + + This is the format used by + Googleearth to provide an overlay within that + application. With this, you can use Googleearth to see the + whole flight path in 3D. + +
+
+ + Configure TeleMetrum + + Select this button and then select either a TeleMetrum or + TeleDongle Device from the list provided. Selecting a TeleDongle + device will use Packet Comamnd Mode to configure remote + TeleMetrum device. Learn how to use this in the Packet Command + Mode chapter. + + + The first few lines of the dialog provide information about the + connected TeleMetrum device, including the product name, + software version and hardware serial number. Below that are the + individual configuration entries. + + + At the bottom of the dialog, there are four buttons: + + + + + Save. This writes any changes to the TeleMetrum + configuration parameter block in flash memory. If you don't + press this button, any changes you make will be lost. + + + + + Reset. This resets the dialog to the most recently saved values, + erasing any changes you have made. + + + + + Reboot. This reboots the TeleMetrum device. Use this to + switch from idle to pad mode by rebooting once the rocket is + oriented for flight. + + + + + Close. This closes the dialog. Any unsaved changes will be + lost. + + + + + The rest of the dialog contains the parameters to be configured. + +
+ Main Deploy Altitude + + This sets the altitude (above the recorded pad altitude) at + which the 'main' igniter will fire. The drop-down menu shows + some common values, but you can edit the text directly and + choose whatever you like. If the apogee charge fires below + this altitude, then the main charge will fire two seconds + after the apogee charge fires. + +
+
+ Apogee Delay + + When flying redundant electronics, it's often important to + ensure that multiple apogee charges don't fire at precisely + the same time as that can overpressurize the apogee deployment + bay and cause a structural failure of the airframe. The Apogee + Delay parameter tells the flight computer to fire the apogee + charge a certain number of seconds after apogee has been + detected. + +
+
+ Radio Channel + + This configures which of the 10 radio channels to use for both + telemetry and packet command mode. Note that if you set this + value via packet command mode, you will have to reconfigure + the TeleDongle channel before you will be able to use packet + command mode again. + +
+
+ Radio Calibration + + The radios in every Altus Metrum device are calibrated at the + factory to ensure that they transmit and receive on the + specified frequency for each channel. You can adjust that + calibration by changing this value. To change the TeleDongle's + calibration, you must reprogram the unit completely. + +
+
+ Callsign + + This sets the callsign included in each telemetry packet. Set this + as needed to conform to your local radio regulations. + +
+
+ + Configure AltosUI + + This button presents a dialog so that you can configure the AltosUI global settings. + +
+ Voice Settings + + AltosUI provides voice annoucements during flight so that you + can keep your eyes on the sky and still get information about + the current flight status. However, sometimes you don't want + to hear them. + + + + Enable—turns all voice announcements on and off + + + + Test Voice—Plays a short message allowing you to verify + that the audio systme is working and the volume settings + are reasonable + + + +
+
+ Log Directory + + AltosUI logs all telemetry data and saves all TeleMetrum flash + data to this directory. This directory is also used as the + staring point when selecting data files for display or export. + + + Click on the directory name to bring up a directory choosing + dialog, select a new directory and click 'Select Directory' to + change where AltosUI reads and writes data files. + +
+
+ Callsign + + This value is used in command packet mode and is transmitted + in each packet sent from TeleDongle and received from + TeleMetrum. It is not used in telemetry mode as that transmits + packets only from TeleMetrum to TeleDongle. Configure this + with the AltosUI operators callsign as needed to comply with + your local radio regulations. + +
+
+ + Flash Image + + + + + Fire Igniter + + + +
\ No newline at end of file -- cgit v1.2.3 From b4bdda65488e8ef27d2889cb6cc8eda3c5d50e0a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 20:29:14 +0800 Subject: doc: git ignore generated doc files Signed-off-by: Keith Packard --- doc/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 doc/.gitignore diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000..54ca39bc --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,3 @@ +*.html +*.pdf +*.fo -- cgit v1.2.3 From 68078eab3c07d8dc83302747cf6f3dcb1797c6ce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 20:44:29 +0800 Subject: doc: Document the 'Flash Image' operation. Signed-off-by: Keith Packard --- doc/altosui-doc.xsl | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/doc/altosui-doc.xsl b/doc/altosui-doc.xsl index 5f330739..4a1f43b5 100644 --- a/doc/altosui-doc.xsl +++ b/doc/altosui-doc.xsl @@ -1,6 +1,7 @@ + AltosUI Altos Metrum Graphical User Interface Manual @@ -551,6 +552,40 @@ Flash Image + This reprograms any Altus Metrum device by using a TeleMetrum or + TeleDongle as a programming dongle. Please read the directions + for connecting the programming cable in the main TeleMetrum + manual before reading these instructions. + + + Once you have the programmer and target devices connected, + push the 'Flash Image' button. That will present a dialog box + listing all of the connected devices. Carefully select the + programmer device, not the device to be programmed. + + + Next, select the image to flash to the device. These are named + with the product name and firmware version. The file selector + will start in the directory containing the firmware included + with the AltosUI package. Navigate to the directory containing + the desired firmware if it isn't there. + + + Next, a small dialog containing the device serial number and + RF calibration values should appear. If these values are + incorrect (possibly due to a corrupted image in the device), + enter the correct values here. + + + Finally, a dialog containing a progress bar will follow the + programming process. + + + When programming is complete, the target device will + reboot. Note that if the target device is connected via USB, you + will have to unplug it and then plug it back in for the USB + connection to reset so that you can communicate with the device + again. -- cgit v1.2.3 From 9ffc2eb53a47e435f39b02896b0e43ae5f47f450 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 18:25:48 -0800 Subject: altosui: Use timeouts to recover from broken packet links. This puts timeouts every place the system reads from the packet link and aborts the in-progress operation if it takes more than a second to get a response. Also mixed in here are persistent igniter status displays for the ejection testing UI. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 95 +++++++++-------- ao-tools/altosui/AltosEepromDownload.java | 26 +++-- ao-tools/altosui/AltosFlashUI.java | 2 +- ao-tools/altosui/AltosIgnite.java | 58 ++++++----- ao-tools/altosui/AltosIgniteUI.java | 162 ++++++++++++++++++++++++++--- ao-tools/altosui/AltosSerial.java | 11 +- ao-tools/altosui/AltosTelemetryReader.java | 2 +- ao-tools/altosui/AltosUI.java | 6 +- 8 files changed, 268 insertions(+), 94 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index a0fdb623..19503dcb 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; import libaltosJNI.*; @@ -123,12 +123,14 @@ public class AltosConfig implements Runnable, ActionListener { } } - void get_data() throws InterruptedException { + void get_data() throws InterruptedException, TimeoutException { try { start_serial(); serial_line.printf("c s\nv\n"); for (;;) { - String line = serial_line.get_reply(); + String line = serial_line.get_reply(1000); + if (line == null) + throw new TimeoutException(); get_int(line, "serial-number", serial); get_int(line, "Main deploy:", main_deploy); get_int(line, "Apogee delay:", apogee_delay); @@ -147,27 +149,34 @@ public class AltosConfig implements Runnable, ActionListener { } } - void init_ui () { + void init_ui () throws InterruptedException, TimeoutException { config_ui = new AltosConfigUI(owner); config_ui.addActionListener(this); set_ui(); } - void set_ui() { - try { - if (serial_line != null) - get_data(); - config_ui.set_serial(serial.get()); - config_ui.set_product(product.get()); - config_ui.set_version(version.get()); - config_ui.set_main_deploy(main_deploy.get()); - config_ui.set_apogee_delay(apogee_delay.get()); - config_ui.set_radio_channel(radio_channel.get()); - config_ui.set_radio_calibration(radio_calibration.get()); - config_ui.set_callsign(callsign.get()); - config_ui.set_clean(); - } catch (InterruptedException ie) { - } + void abort() { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + serial_line.close(); + serial_line = null; + } + + void set_ui() throws InterruptedException, TimeoutException { + if (serial_line != null) + get_data(); + config_ui.set_serial(serial.get()); + config_ui.set_product(product.get()); + config_ui.set_version(version.get()); + config_ui.set_main_deploy(main_deploy.get()); + config_ui.set_apogee_delay(apogee_delay.get()); + config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_callsign(callsign.get()); + config_ui.set_clean(); } void run_dialog() { @@ -198,28 +207,28 @@ public class AltosConfig implements Runnable, ActionListener { public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("Save")) { - save_data(); - set_ui(); - } else if (cmd.equals("Reset")) { - set_ui(); - } else if (cmd.equals("Reboot")) { - if (serial_line != null) { - try { + try { + if (cmd.equals("Save")) { + save_data(); + set_ui(); + } else if (cmd.equals("Reset")) { + set_ui(); + } else if (cmd.equals("Reboot")) { + if (serial_line != null) { start_serial(); serial_line.printf("r eboot\n"); - } catch (InterruptedException ie) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { - } + serial_line.flush_output(); + stop_serial(); + serial_line.close(); } - serial_line.close(); + } else if (cmd.equals("Close")) { + if (serial_line != null) + serial_line.close(); } - } else if (cmd.equals("Close")) { - if (serial_line != null) - serial_line.close(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); } } @@ -227,8 +236,10 @@ public class AltosConfig implements Runnable, ActionListener { try { init_ui(); config_ui.make_visible(); -// } catch (InterruptedException ie) { - } finally { + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); } } @@ -255,18 +266,18 @@ public class AltosConfig implements Runnable, ActionListener { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, String.format("Cannot open device \"%s\"", - device.getPath()), + device.toString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(owner, String.format("Device \"%s\" already in use", - device.getPath()), + device.toString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(owner, - device.getPath(), + device.toString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 8996b924..912ff476 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; import libaltosJNI.*; @@ -78,7 +78,7 @@ public class AltosEepromDownload implements Runnable { Thread eeprom_thread; AltosEepromMonitor monitor; - void CaptureLog() throws IOException, InterruptedException { + void CaptureLog() throws IOException, InterruptedException, TimeoutException { int serial = 0; int block, state_block = 0; int addr; @@ -97,8 +97,10 @@ public class AltosEepromDownload implements Runnable { /* Pull the serial number out of the version information */ for (;;) { - String line = serial_line.get_reply(); + String line = serial_line.get_reply(1000); + if (line == null) + throw new TimeoutException(); if (line.startsWith("serial-number")) { try { serial = Integer.parseInt(line.substring(13).trim()); @@ -125,7 +127,9 @@ public class AltosEepromDownload implements Runnable { any_valid = false; monitor.set_value(state_names[state], state, block - state_block); for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(); + String line = serial_line.get_reply(1000); + if (line == null) + throw new TimeoutException(); int[] values = ParseHex(line); if (values == null) { @@ -228,10 +232,16 @@ public class AltosEepromDownload implements Runnable { CaptureLog(); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, - device.getPath(), + device.toString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(frame, + String.format("Connection to \"%s\" failed", + device.toString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); } if (remote) serial_line.printf("~"); @@ -256,18 +266,18 @@ public class AltosEepromDownload implements Runnable { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, String.format("Cannot open device \"%s\"", - device.getPath()), + device.toString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", - device.getPath()), + device.toString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, - device.getPath(), + device.toString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index b09cb594..d3b72c67 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -90,7 +90,7 @@ public class AltosFlashUI } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", - debug_dongle.getPath()), + debug_dongle.toString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException e) { diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java index 5c27e8fa..8e92ec1b 100644 --- a/ao-tools/altosui/AltosIgnite.java +++ b/ao-tools/altosui/AltosIgnite.java @@ -18,6 +18,7 @@ package altosui; import java.io.*; +import java.util.concurrent.*; public class AltosIgnite { AltosDevice device; @@ -91,35 +92,40 @@ public class AltosIgnite { return Unknown; } - public int status(int igniter) { + public int status(int igniter) throws InterruptedException, TimeoutException { int status = Unknown; if (serial == null) return status; string_ref status_name = new string_ref(); - try { - start_serial(); - serial.printf("t\n"); - for (;;) { - String line = serial.get_reply(); - if (get_string(line, "Igniter: drogue Status: ", status_name)) - if (igniter == Apogee) - status = status(status_name.get()); - if (get_string(line, "Igniter: main Status: ", status_name)) { - if (igniter == Main) - status = status(status_name.get()); - break; - } - } - } catch (InterruptedException ie) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { + start_serial(); + serial.printf("t\n"); + for (;;) { + String line = serial.get_reply(1000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Igniter: drogue Status: ", status_name)) + if (igniter == Apogee) + status = status(status_name.get()); + if (get_string(line, "Igniter: main Status: ", status_name)) { + if (igniter == Main) + status = status(status_name.get()); + break; } } + stop_serial(); return status; } + public String status_string(int status) { + switch (status) { + case Unknown: return "Unknown"; + case Ready: return "Ready"; + case Active: return "Active"; + case Open: return "Open"; + default: return "Unknown"; + } + } + public void fire(int igniter) { if (serial == null) return; @@ -142,14 +148,18 @@ public class AltosIgnite { } } + public void close() { + serial.close(); + serial = null; + } + public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; - serial = null; -// serial = new AltosSerial(device); + serial = new AltosSerial(device); remote = false; -// if (!device.matchProduct(AltosDevice.product_telemetrum)) -// remote = true; + if (!device.matchProduct(AltosDevice.product_telemetrum)) + remote = true; } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java index 62da413c..caecc3ef 100644 --- a/ao-tools/altosui/AltosIgniteUI.java +++ b/ao-tools/altosui/AltosIgniteUI.java @@ -27,22 +27,31 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; +import java.util.concurrent.*; public class AltosIgniteUI extends JDialog implements ActionListener { + AltosDevice device; + AltosIgnite ignite; JFrame owner; JLabel label; JRadioButton apogee; + JLabel apogee_status_label; JRadioButton main; + JLabel main_status_label; JToggleButton arm; JButton fire; javax.swing.Timer timer; + int apogee_status; + int main_status; + final static int timeout = 1 * 1000; int time_remaining; + boolean timer_running; void set_arm_text() { if (arm.isSelected()) @@ -54,7 +63,7 @@ public class AltosIgniteUI void start_timer() { time_remaining = 10; set_arm_text(); - timer.restart(); + timer_running = true; } void stop_timer() { @@ -62,7 +71,7 @@ public class AltosIgniteUI arm.setSelected(false); arm.setEnabled(false); fire.setEnabled(false); - timer.stop(); + timer_running = false; set_arm_text(); } @@ -73,12 +82,47 @@ public class AltosIgniteUI stop_timer(); } + void get_ignite_status() throws InterruptedException, TimeoutException { + apogee_status = ignite.status(AltosIgnite.Apogee); + main_status = ignite.status(AltosIgnite.Main); + } + + void set_ignite_status() throws InterruptedException, TimeoutException { + get_ignite_status(); + apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status))); + main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status))); + } + + void close() { + timer.stop(); + setVisible(false); + ignite.close(); + } + + void abort() { + close(); + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + void tick_timer() { - --time_remaining; - if (time_remaining <= 0) - cancel(); - else - set_arm_text(); + if (timer_running) { + --time_remaining; + if (time_remaining <= 0) + cancel(); + else + set_arm_text(); + } + try { + set_ignite_status(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } } void fire() { @@ -88,7 +132,7 @@ public class AltosIgniteUI igniter = AltosIgnite.Apogee; else if (main.isSelected() && !apogee.isSelected()) igniter = AltosIgnite.Main; - System.out.printf ("fire %d\n", igniter); + ignite.fire(igniter); cancel(); } } @@ -97,13 +141,18 @@ public class AltosIgniteUI String cmd = e.getActionCommand(); if (cmd.equals("apogee") || cmd.equals("main")) { stop_timer(); - arm.setEnabled(true); } - if (cmd.equals("apogee") && apogee.isSelected()) + if (cmd.equals("apogee") && apogee.isSelected()) { main.setSelected(false); - if (cmd.equals("main") && main.isSelected()) + if (apogee_status == AltosIgnite.Ready) + arm.setEnabled(true); + } + if (cmd.equals("main") && main.isSelected()) { apogee.setSelected(false); + if (main_status == AltosIgnite.Ready) + arm.setEnabled(true); + } if (cmd.equals("arm")) { if (arm.isSelected()) { @@ -116,15 +165,71 @@ public class AltosIgniteUI fire(); if (cmd.equals("tick")) tick_timer(); + if (cmd.equals("close")) { + close(); + } + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosIgniteUI ui; + + public ConfigListener(AltosIgniteUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + if (device != null) { + try { + ignite = new AltosIgnite(device); + return true; + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + return false; } public AltosIgniteUI(JFrame in_owner) { + + owner = in_owner; + apogee_status = AltosIgnite.Unknown; + main_status = AltosIgnite.Unknown; + + if (!open()) + return; + Container pane = getContentPane(); GridBagConstraints c = new GridBagConstraints(); Insets i = new Insets(4,4,4,4); timer = new javax.swing.Timer(timeout, this); timer.setActionCommand("tick"); + timer_running = false; + timer.restart(); owner = in_owner; @@ -139,12 +244,14 @@ public class AltosIgniteUI c.gridx = 0; c.gridy = 0; c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; label = new JLabel ("Fire Igniter"); pane.add(label, c); c.gridx = 0; c.gridy = 1; c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; apogee = new JRadioButton ("Apogee"); pane.add(apogee, c); apogee.addActionListener(this); @@ -153,14 +260,40 @@ public class AltosIgniteUI c.gridx = 1; c.gridy = 1; c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + apogee_status_label = new JLabel(); + pane.add(apogee_status_label, c); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; main = new JRadioButton ("Main"); pane.add(main, c); main.addActionListener(this); main.setActionCommand("main"); - c.gridx = 0; + c.gridx = 1; c.gridy = 2; c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + main_status_label = new JLabel(); + pane.add(main_status_label, c); + + try { + set_ignite_status(); + } catch (InterruptedException ie) { + abort(); + return; + } catch (TimeoutException te) { + abort(); + return; + } + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; arm = new JToggleButton ("Arm"); pane.add(arm, c); arm.addActionListener(this); @@ -168,8 +301,9 @@ public class AltosIgniteUI arm.setEnabled(false); c.gridx = 1; - c.gridy = 2; + c.gridy = 3; c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; fire = new JButton ("Fire"); fire.setEnabled(false); pane.add(fire, c); @@ -179,5 +313,7 @@ public class AltosIgniteUI pack(); setLocationRelativeTo(owner); setVisible(true); + + addWindowListener(new ConfigListener(this)); } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 99a92fdb..0d32a5ae 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -132,6 +132,14 @@ public class AltosSerial implements Runnable { return line.line; } + public String get_reply(int timeout) throws InterruptedException { + flush_output(); + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line == null) + return null; + return line.line; + } + public void add_monitor(LinkedBlockingQueue q) { set_monitor(true); monitors.add(q); @@ -185,10 +193,9 @@ public class AltosSerial implements Runnable { throw new AltosSerialInUseException(device); devices_opened.add(device.getPath()); } - close(); altos = libaltos.altos_open(device); if (altos == null) - throw new FileNotFoundException(device.getPath()); + throw new FileNotFoundException(device.toString()); input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index ff02c722..379e0e67 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -55,7 +55,7 @@ class AltosTelemetryReader extends AltosFlightReader { device = in_device; serial = new AltosSerial(device); log = new AltosLog(serial); - name = device.getPath(); + name = device.toString(); telem = new LinkedBlockingQueue(); serial.add_monitor(telem); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index c82c8e8a..b573ef7f 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -53,18 +53,18 @@ public class AltosUI extends JFrame { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, String.format("Cannot open device \"%s\"", - device.getPath()), + device.toString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(AltosUI.this, String.format("Device \"%s\" already in use", - device.getPath()), + device.toString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.getPath(), + device.toString(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); } -- cgit v1.2.3 From fa07afc73bc5eccff8464a2def05ad600da33c97 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 19 Nov 2010 23:33:42 -0700 Subject: update turnon scripts to use stashed copies of stable release firmware --- ao-bringup/turnon_teledongle | 2 +- ao-bringup/turnon_telemetrum | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index 216afa2a..5145e9b0 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL +$AOLOAD --cal $CAL_VALUE /usr/share/altos/stable/teledongle-v0.2*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 440eda1b..405247fa 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/telemetrum-v1.0*.ihx $SERIAL +$AOLOAD --cal $CAL_VALUE /usr/share/altos/stable/telemetrum-v1.0*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 594e80572821f1848db062d0cff18ca8bf0d90ce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 22:44:48 -0800 Subject: altosui: switch channel selector to combo box. Shorten displayed device names A combo box displays the current value, which is quite nice to have. Add a 'toShortString' for AltosDevice so that the window frames and error messages don't have extra spaces generated by the altos_device toString method. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosChannelMenu.java | 24 +++++------- ao-tools/altosui/AltosConfig.java | 8 ++-- ao-tools/altosui/AltosDebug.java | 2 +- ao-tools/altosui/AltosDevice.java | 9 +++++ ao-tools/altosui/AltosEepromDownload.java | 10 ++--- ao-tools/altosui/AltosFlashUI.java | 2 +- ao-tools/altosui/AltosFlightUI.java | 62 ++++++++++++++++-------------- ao-tools/altosui/AltosIgniteUI.java | 8 ++-- ao-tools/altosui/AltosSerial.java | 6 +-- ao-tools/altosui/AltosTelemetryReader.java | 2 +- ao-tools/altosui/AltosUI.java | 6 +-- 11 files changed, 74 insertions(+), 65 deletions(-) diff --git a/ao-tools/altosui/AltosChannelMenu.java b/ao-tools/altosui/AltosChannelMenu.java index 504c13c6..8069c853 100644 --- a/ao-tools/altosui/AltosChannelMenu.java +++ b/ao-tools/altosui/AltosChannelMenu.java @@ -28,8 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosChannelMenu extends JMenu implements ActionListener { - ButtonGroup group; +public class AltosChannelMenu extends JComboBox implements ActionListener { int channel; LinkedList listeners; @@ -38,33 +37,28 @@ public class AltosChannelMenu extends JMenu implements ActionListener { } public void actionPerformed(ActionEvent e) { - channel = Integer.parseInt(e.getActionCommand()); + channel = getSelectedIndex(); + + ActionEvent newe = new ActionEvent(this, channel, e.getActionCommand()); ListIterator i = listeners.listIterator(); - ActionEvent newe = new ActionEvent(this, channel, e.getActionCommand()); while (i.hasNext()) { ActionListener listener = i.next(); listener.actionPerformed(newe); } + setMaximumSize(getPreferredSize()); } public AltosChannelMenu(int current_channel) { - super("Channel", true); - group = new ButtonGroup(); channel = current_channel; listeners = new LinkedList(); - for (int c = 0; c <= 9; c++) { - JRadioButtonMenuItem radioitem = new JRadioButtonMenuItem(String.format("Channel %1d (%7.3fMHz)", c, - 434.550 + c * 0.1), - c == channel); - radioitem.setActionCommand(String.format("%d", c)); - radioitem.addActionListener(this); - add(radioitem); - group.add(radioitem); - } + for (int c = 0; c <= 9; c++) + addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1)); + setSelectedIndex(channel); + setMaximumRowCount(10); } } diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 19503dcb..6bda20d8 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -158,7 +158,7 @@ public class AltosConfig implements Runnable, ActionListener { void abort() { JOptionPane.showMessageDialog(owner, String.format("Connection to \"%s\" failed", - device.toString()), + device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); serial_line.close(); @@ -266,18 +266,18 @@ public class AltosConfig implements Runnable, ActionListener { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, String.format("Cannot open device \"%s\"", - device.toString()), + device.toShortString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(owner, String.format("Device \"%s\" already in use", - device.toString()), + device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(owner, - device.toString(), + device.toShortString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java index 9aa35d3f..8d435b66 100644 --- a/ao-tools/altosui/AltosDebug.java +++ b/ao-tools/altosui/AltosDebug.java @@ -261,7 +261,7 @@ public class AltosDebug extends AltosSerial { printf ("R\n"); } - public AltosDebug (altos_device in_device) throws FileNotFoundException, AltosSerialInUseException { + public AltosDebug (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { super(in_device); } } \ No newline at end of file diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java index f646305b..f0fda57b 100644 --- a/ao-tools/altosui/AltosDevice.java +++ b/ao-tools/altosui/AltosDevice.java @@ -101,6 +101,15 @@ public class AltosDevice extends altos_device { getName(), getSerial(), getPath()); } + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + name, getSerial(), getPath()); + + } + public boolean isAltusMetrum() { if (getVendor() != vendor_altusmetrum) return false; diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index 912ff476..fb5dcfc0 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -232,14 +232,14 @@ public class AltosEepromDownload implements Runnable { CaptureLog(); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, - device.toString(), + device.toShortString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { } catch (TimeoutException te) { JOptionPane.showMessageDialog(frame, String.format("Connection to \"%s\" failed", - device.toString()), + device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); } @@ -266,18 +266,18 @@ public class AltosEepromDownload implements Runnable { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, String.format("Cannot open device \"%s\"", - device.toString()), + device.toShortString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", - device.toString()), + device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(frame, - device.toString(), + device.toShortString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java index d3b72c67..f63097ac 100644 --- a/ao-tools/altosui/AltosFlashUI.java +++ b/ao-tools/altosui/AltosFlashUI.java @@ -90,7 +90,7 @@ public class AltosFlashUI } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", - debug_dongle.toString()), + debug_dongle.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException e) { diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 78b005c0..56ab7ebc 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -36,8 +36,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosFlightReader reader; AltosDisplayThread thread; - private Box vbox; - JTabbedPane pane; AltosPad pad; @@ -128,22 +126,47 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { exit_on_close = true; } + Container bag; + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { AltosPreferences.init(this); voice = in_voice; reader = in_reader; + bag = getContentPane(); + bag.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); if (imgURL != null) setIconImage(new ImageIcon(imgURL).getImage()); setTitle(String.format("AltOS %s", reader.name)); - flightStatus = new AltosFlightStatus(); + if (serial >= 0) { + // Channel menu + JComboBox channels = new AltosChannelMenu(AltosPreferences.channel(serial)); + channels.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int channel = Integer.parseInt(e.getActionCommand()); + reader.set_channel(channel); + AltosPreferences.set_channel(serial, channel); + } + }); + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.WEST; + bag.add (channels, c); + } - vbox = new Box (BoxLayout.Y_AXIS); - vbox.add(flightStatus); + flightStatus = new AltosFlightStatus(); + c.gridx = 0; + c.gridy = 1; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + bag.add(flightStatus, c); pane = new JTabbedPane(); @@ -163,29 +186,12 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { flightInfoPane = new JScrollPane(flightInfo.box()); pane.add("Table", flightInfoPane); - vbox.add(pane); - - this.add(vbox); - - if (serial >= 0) { - JMenuBar menubar = new JMenuBar(); - - // Channel menu - { - JMenu menu = new AltosChannelMenu(AltosPreferences.channel(serial)); - menu.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int channel = Integer.parseInt(e.getActionCommand()); - reader.set_channel(channel); - AltosPreferences.set_channel(serial, channel); - } - }); - menu.setMnemonic(KeyEvent.VK_C); - menubar.add(menu); - } - - this.setJMenuBar(menubar); - } + c.gridx = 0; + c.gridy = 2; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + bag.add(pane, c); this.setSize(this.getPreferredSize()); this.validate(); diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java index caecc3ef..0207e39f 100644 --- a/ao-tools/altosui/AltosIgniteUI.java +++ b/ao-tools/altosui/AltosIgniteUI.java @@ -103,7 +103,7 @@ public class AltosIgniteUI close(); JOptionPane.showMessageDialog(owner, String.format("Connection to \"%s\" failed", - device.toString()), + device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); } @@ -194,18 +194,18 @@ public class AltosIgniteUI } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, String.format("Cannot open device \"%s\"", - device.toString()), + device.toShortString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(owner, String.format("Device \"%s\" already in use", - device.toString()), + device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(owner, - device.toString(), + device.toShortString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); } diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 0d32a5ae..ab74486b 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -38,7 +38,7 @@ public class AltosSerial implements Runnable { static List devices_opened = Collections.synchronizedList(new LinkedList()); - altos_device device; + AltosDevice device; SWIGTYPE_p_altos_file altos; LinkedList> monitors; LinkedBlockingQueue reply_queue; @@ -195,7 +195,7 @@ public class AltosSerial implements Runnable { } altos = libaltos.altos_open(device); if (altos == null) - throw new FileNotFoundException(device.toString()); + throw new FileNotFoundException(device.toShortString()); input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); @@ -233,7 +233,7 @@ public class AltosSerial implements Runnable { } } - public AltosSerial(altos_device in_device) throws FileNotFoundException, AltosSerialInUseException { + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; line = ""; monitor_mode = false; diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index 379e0e67..de5f50e9 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -55,7 +55,7 @@ class AltosTelemetryReader extends AltosFlightReader { device = in_device; serial = new AltosSerial(device); log = new AltosLog(serial); - name = device.toString(); + name = device.toShortString(); telem = new LinkedBlockingQueue(); serial.add_monitor(telem); diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index b573ef7f..6bfde014 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -53,18 +53,18 @@ public class AltosUI extends JFrame { } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, String.format("Cannot open device \"%s\"", - device.toString()), + device.toShortString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { JOptionPane.showMessageDialog(AltosUI.this, String.format("Device \"%s\" already in use", - device.toString()), + device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); } catch (IOException ee) { JOptionPane.showMessageDialog(AltosUI.this, - device.toString(), + device.toShortString(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); } -- cgit v1.2.3 From 8c8dc3794c7b5fa5a5b43b1c461d6c8bb3ab425d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 23:09:15 -0800 Subject: altosui: When switching log files, don't terminate log thread The log thread automatically switches output files when the incoming telemetry changes. Don't use 'close' for that as 'close' terminates the log thread as well as closing the file. Create a new 'close_log_file' function which just closes the file. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosLog.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index 137147d5..11319768 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -36,15 +36,23 @@ class AltosLog implements Runnable { FileWriter log_file; Thread log_thread; - void close() { + private void close_log_file() { if (log_file != null) { try { log_file.close(); } catch (IOException io) { } + log_file = null; } - if (log_thread != null) + } + + void close() { + close_log_file(); + if (log_thread != null) { + log_thread.interrupt(); + log_thread = null; log_thread.interrupt(); + } } boolean open (AltosTelemetry telem) throws IOException { @@ -74,7 +82,7 @@ class AltosLog implements Runnable { try { AltosTelemetry telem = new AltosTelemetry(line.line); if (telem.serial != serial || telem.flight != flight || log_file == null) { - close(); + close_log_file(); serial = telem.serial; flight = telem.flight; open(telem); -- cgit v1.2.3 From 7920ed5c34b088f45ce4213b061ddd1ffe22cee8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 19 Nov 2010 23:18:51 -0800 Subject: altosui: calling thread.interrupt with null thread doesn't work well This was a left-over from debugging the previous patch. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosLog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java index 11319768..dd147d21 100644 --- a/ao-tools/altosui/AltosLog.java +++ b/ao-tools/altosui/AltosLog.java @@ -51,7 +51,6 @@ class AltosLog implements Runnable { if (log_thread != null) { log_thread.interrupt(); log_thread = null; - log_thread.interrupt(); } } -- cgit v1.2.3 From 71c41eadd12c3ece5fffce7669e4991778046d4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 00:09:03 -0800 Subject: altosui: Initialize display thread state in constructor instead of run Some state will get set before run is called, initializing it there can be too late. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosDisplayThread.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java index 375965b9..3e719130 100644 --- a/ao-tools/altosui/AltosDisplayThread.java +++ b/ao-tools/altosui/AltosDisplayThread.java @@ -116,10 +116,6 @@ public class AltosDisplayThread extends Thread { } public void run () { - - reported_landing = 0; - state = null; - report_interval = 10000; try { for (;;) { set_report_time(); @@ -159,6 +155,12 @@ public class AltosDisplayThread extends Thread { } else if (spoken) set_report_time(); } + + public IdleThread() { + state = null; + reported_landing = 0; + report_interval = 10000; + } } boolean tell(AltosState state, AltosState old_state) { -- cgit v1.2.3 From 9a99cabc1c34c657fc95246192ba6d330f5f22d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 00:13:58 -0800 Subject: altosui: Fix channel changing in flight UI to actually work Replacing the menu with a combo box required reworking the way events are delivered from that widget back to the channel changing function. Just delete the old magic and use the JComboBox action listener directly. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosChannelMenu.java | 20 -------------------- ao-tools/altosui/AltosFlightUI.java | 5 +++-- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/ao-tools/altosui/AltosChannelMenu.java b/ao-tools/altosui/AltosChannelMenu.java index 8069c853..abbb86f4 100644 --- a/ao-tools/altosui/AltosChannelMenu.java +++ b/ao-tools/altosui/AltosChannelMenu.java @@ -30,31 +30,11 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosChannelMenu extends JComboBox implements ActionListener { int channel; - LinkedList listeners; - - public void addActionListener(ActionListener l) { - listeners.add(l); - } - - public void actionPerformed(ActionEvent e) { - channel = getSelectedIndex(); - - ActionEvent newe = new ActionEvent(this, channel, e.getActionCommand()); - - ListIterator i = listeners.listIterator(); - - while (i.hasNext()) { - ActionListener listener = i.next(); - listener.actionPerformed(newe); - } - setMaximumSize(getPreferredSize()); - } public AltosChannelMenu(int current_channel) { channel = current_channel; - listeners = new LinkedList(); for (int c = 0; c <= 9; c++) addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1)); setSelectedIndex(channel); diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 56ab7ebc..ac88aa15 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -127,6 +127,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } Container bag; + JComboBox channels; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { AltosPreferences.init(this); @@ -147,10 +148,10 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { if (serial >= 0) { // Channel menu - JComboBox channels = new AltosChannelMenu(AltosPreferences.channel(serial)); + channels = new AltosChannelMenu(AltosPreferences.channel(serial)); channels.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - int channel = Integer.parseInt(e.getActionCommand()); + int channel = channels.getSelectedIndex(); reader.set_channel(channel); AltosPreferences.set_channel(serial, channel); } -- cgit v1.2.3 From 58f8d069ce9488e2987b8e92caa69fe68cda7569 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 20 Nov 2010 21:06:37 +1000 Subject: AltosSiteMap: add autoscroll and grabndrag scroll --- ao-tools/altosui/AltosFlightUI.java | 4 +--- ao-tools/altosui/AltosSiteMap.java | 38 +++++++++++++++++++++++++++++++--- ao-tools/altosui/AltosSiteMapTile.java | 32 +++++++++++++++++++++------- 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 6db6c67b..c85fc977 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -46,7 +46,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { private AltosFlightStatus flightStatus; private JScrollPane flightInfoPane; - private JScrollPane sitemapPane; private AltosInfoTable flightInfo; static final int tab_pad = 1; @@ -192,8 +191,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Table", flightInfoPane); sitemap = new AltosSiteMap(); - sitemapPane = new JScrollPane(sitemap); - pane.add("Site Map", sitemapPane); + pane.add("Site Map", sitemap); c.gridx = 0; c.gridy = 2; diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index df1cc246..1db83959 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -21,6 +21,7 @@ import java.awt.*; import java.awt.image.*; import java.awt.event.*; import javax.swing.*; +import javax.swing.event.MouseInputAdapter; import javax.imageio.ImageIO; import javax.swing.table.*; import java.io.*; @@ -31,7 +32,7 @@ import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; -public class AltosSiteMap extends JComponent implements AltosFlightDisplay { +public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { public void reset() { // nothing } @@ -43,10 +44,40 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; + class GrabNDrag extends MouseInputAdapter { + private JComponent scroll; + private Point startPt = new Point(); + + public GrabNDrag(JComponent parent) { + scroll = parent; + } + + public void mousePressed(MouseEvent e) { + startPt.setLocation(e.getPoint()); + } + public void mouseDragged(MouseEvent e) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; + + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } + } + public AltosSiteMap() { + JComponent comp = new JComponent() { + GrabNDrag scroller = new GrabNDrag(this); + { + addMouseMotionListener(scroller); + addMouseListener(scroller); + setAutoscrolls(true); + } + }; GridBagLayout layout = new GridBagLayout(); - setLayout(layout); + comp.setLayout(layout); GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.CENTER; @@ -56,8 +87,9 @@ public class AltosSiteMap extends JComponent implements AltosFlightDisplay { c.gridx = x % 3; c.gridy = x / 3; mapTiles[x] = new AltosSiteMapTile((x%3)-1, (x/3)-1); layout.setConstraints(mapTiles[x], c); - add(mapTiles[x]); + comp.add(mapTiles[x]); } + setViewportView(comp); } } diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index c14fb93f..df57aa7d 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -65,21 +65,19 @@ public class AltosSiteMapTile extends JLabel { Point2D.Double map_latlng; map_latlng = latlng(new Point2D.Double(px_size/2, px_size/2)); - BufferedImage myPicture; File pngfile = new File(AltosPreferences.logdir(), FileCoord(map_latlng, zoom)); try { + BufferedImage myPicture; myPicture = ImageIO.read(pngfile); + setIcon(new ImageIcon( myPicture )); System.out.printf("# Found file %s\n", pngfile); + g2d = myPicture.createGraphics(); } catch (Exception e) { // throw new RuntimeException(e); System.out.printf("# Failed to find file %s\n", pngfile); System.out.printf(" wget -O '%s' 'http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32'\n", pngfile, map_latlng.x, map_latlng.y, zoom, px_size, px_size); - myPicture = new BufferedImage(px_size, px_size, - BufferedImage.TYPE_INT_RGB); } - setIcon(new ImageIcon( myPicture )); - g2d = myPicture.createGraphics(); return true; } @@ -167,8 +165,8 @@ public class AltosSiteMapTile extends JLabel { return; if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) return; - double plat = (int)(state.pad_lat*200)/200.0; - double plon = (int)(state.pad_lon*200)/200.0; + double plat = state.pad_lat; + double plon = state.pad_lon; if (last_pt == null) { if (!setLocation(plat, plon)) { @@ -185,6 +183,19 @@ public class AltosSiteMapTile extends JLabel { g2d.draw(new Line2D.Double(last_pt, pt)); } + if (0 <= pt.x && pt.x < px_size) { + if (0 <= pt.y && pt.y < px_size) { + int dx = 500, dy = 250; + if (last_pt != null && state.state > 2) { + dx = Math.min(200, 20 + (int) Math.abs(last_pt.x - pt.x)); + dy = Math.min(100, 10 + (int) Math.abs(last_pt.y - pt.y)); + } + Rectangle r = new Rectangle((int)pt.x-dx, (int)pt.y-dy, + dx*2, dy*2); + scrollRectToVisible(r); + } + } + if (state.state == 8 && !drawn_landed_circle) { drawn_landed_circle = true; g2d.setColor(Color.RED); @@ -198,6 +209,13 @@ public class AltosSiteMapTile extends JLabel { } public AltosSiteMapTile(int x_tile_offset, int y_tile_offset) { + BufferedImage myPicture = new BufferedImage(px_size, px_size, + BufferedImage.TYPE_INT_RGB); + setIcon(new ImageIcon( myPicture )); + g2d = myPicture.createGraphics(); + g2d.setColor(Color.GRAY); + g2d.fillRect(0, 0, px_size, px_size); + off_x = x_tile_offset; off_y = y_tile_offset; } -- cgit v1.2.3 From 20f714bbe3137de8fb7491b39985021fd1774930 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 20 Nov 2010 22:49:51 +1000 Subject: AltosSiteMapTile: seperate map and drawing layers --- ao-tools/altosui/AltosSiteMapTile.java | 94 ++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index df57aa7d..ca68412a 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -31,18 +31,33 @@ import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; -public class AltosSiteMapTile extends JLabel { +public class AltosSiteMapTile extends JLayeredPane { int zoom; double scale_x, scale_y; Point2D.Double coord_pt; Point2D.Double last_pt; + JLabel mapLabel; + JLabel draw; Graphics2D g2d; int off_x; int off_y; - int px_size = 512; + static final int px_size = 512; + + private void loadMap() { + Point2D.Double map_latlng = latlng(px_size/2, px_size/2); + File pngfile = new File(AltosPreferences.logdir(), + FileCoord(map_latlng, zoom)); + try { + mapLabel.setIcon(new ImageIcon(ImageIO.read(pngfile))); + } catch (Exception e) { + // throw new RuntimeException(e); + System.out.printf("# Failed to find file %s\n", pngfile); + System.out.printf(" wget -O '%s' 'http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32'\n", pngfile, map_latlng.x, map_latlng.y, zoom, px_size, px_size); + } + } private boolean setLocation(double lat, double lng) { Point2D.Double north_step; @@ -62,22 +77,6 @@ public class AltosSiteMapTile extends JLabel { last_pt = null; - Point2D.Double map_latlng; - map_latlng = latlng(new Point2D.Double(px_size/2, px_size/2)); - - File pngfile = new File(AltosPreferences.logdir(), - FileCoord(map_latlng, zoom)); - try { - BufferedImage myPicture; - myPicture = ImageIO.read(pngfile); - setIcon(new ImageIcon( myPicture )); - System.out.printf("# Found file %s\n", pngfile); - g2d = myPicture.createGraphics(); - } catch (Exception e) { - // throw new RuntimeException(e); - System.out.printf("# Failed to find file %s\n", pngfile); - System.out.printf(" wget -O '%s' 'http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32'\n", pngfile, map_latlng.x, map_latlng.y, zoom, px_size, px_size); - } return true; } @@ -132,6 +131,9 @@ public class AltosSiteMapTile extends JLabel { return res; } + private Point2D.Double latlng(double x, double y) { + return latlng(new Point2D.Double(x,y), coord_pt); + } private Point2D.Double latlng(Point2D.Double pt) { return latlng(pt, coord_pt); } @@ -159,24 +161,22 @@ public class AltosSiteMapTile extends JLabel { }; boolean drawn_landed_circle = false; - boolean nomaps = false; public void show(AltosState state, int crc_errors) { - if (nomaps) - return; - if (!state.gps_ready && state.pad_lat == 0 && state.pad_lon == 0) - return; - double plat = state.pad_lat; - double plon = state.pad_lon; + if (!state.gps_ready) { + if (state.pad_lat == 0 && state.pad_lon == 0) + return; + if (state.ngps < 3) + return; + } if (last_pt == null) { - if (!setLocation(plat, plon)) { - nomaps = true; - return; - } + setLocation(state.pad_lat, state.pad_lon); + loadMap(); + last_pt = pt; } Point2D.Double pt = pt(state.gps.lat, state.gps.lon); - if (last_pt != null && pt != last_pt) { + if (pt != last_pt) { if (0 <= state.state && state.state < stateColors.length) { g2d.setColor(stateColors[state.state]); } @@ -186,7 +186,7 @@ public class AltosSiteMapTile extends JLabel { if (0 <= pt.x && pt.x < px_size) { if (0 <= pt.y && pt.y < px_size) { int dx = 500, dy = 250; - if (last_pt != null && state.state > 2) { + if (state.state > 2) { dx = Math.min(200, 20 + (int) Math.abs(last_pt.x - pt.x)); dy = Math.min(100, 10 + (int) Math.abs(last_pt.y - pt.y)); } @@ -207,14 +207,32 @@ public class AltosSiteMapTile extends JLabel { last_pt = pt; repaint(); } - + + public static Graphics2D fillLabel(JLabel l, Color c) { + BufferedImage img = new BufferedImage(px_size, px_size, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g = img.createGraphics(); + g.setColor(c); + g.fillRect(0, 0, px_size, px_size); + l.setIcon(new ImageIcon(img)); + return g; + } + public AltosSiteMapTile(int x_tile_offset, int y_tile_offset) { - BufferedImage myPicture = new BufferedImage(px_size, px_size, - BufferedImage.TYPE_INT_RGB); - setIcon(new ImageIcon( myPicture )); - g2d = myPicture.createGraphics(); - g2d.setColor(Color.GRAY); - g2d.fillRect(0, 0, px_size, px_size); + setPreferredSize(new Dimension(px_size, px_size)); + + mapLabel = new JLabel(); + fillLabel(mapLabel, Color.GRAY); + mapLabel.setOpaque(true); + mapLabel.setBounds(0, 0, px_size, px_size); + add(mapLabel, new Integer(0)); + + draw = new JLabel(); + g2d = fillLabel(draw, new Color(127, 127, 127, 0)); + draw.setBounds(0, 0, px_size, px_size); + draw.setOpaque(false); + + add(draw, new Integer(1)); off_x = x_tile_offset; off_y = y_tile_offset; -- cgit v1.2.3 From 25ffe1cc7823895886b4777f310b4bda1c80133b Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 00:07:16 +1000 Subject: AltosSiteMap: automatic fetching of map data --- ao-tools/altosui/AltosSiteMapLabel.java | 142 ++++++++++++++++++++++++++++++++ ao-tools/altosui/AltosSiteMapTile.java | 32 +------ ao-tools/altosui/Makefile.am | 1 + 3 files changed, 147 insertions(+), 28 deletions(-) create mode 100644 ao-tools/altosui/AltosSiteMapLabel.java diff --git a/ao-tools/altosui/AltosSiteMapLabel.java b/ao-tools/altosui/AltosSiteMapLabel.java new file mode 100644 index 00000000..1a371c5b --- /dev/null +++ b/ao-tools/altosui/AltosSiteMapLabel.java @@ -0,0 +1,142 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.net.URL; +import java.net.URLConnection; + +public class AltosSiteMapLabel extends JLabel { + public static boolean fetchMap(File file, String url) { + URL u; + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return false; + } + + byte[] data; + try { + URLConnection uc = u.openConnection(); + int contentLength = uc.getContentLength(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) { + return false; + } + } catch (IOException e) { + return false; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + if (file.exists()) { + file.delete(); + } + return false; + } + return true; + } + + public void fetchAndLoadMap(final File pngfile, final String url) { + System.out.printf("# Trying to fetch %s...\n", pngfile); + + Thread thread = new Thread() { + public void run() { + try { + if (fetchMap(pngfile, url)) { + setIcon(new ImageIcon(ImageIO.read(pngfile))); + } + } catch (Exception e) { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, url); + } + } + }; + thread.start(); + } + + public void fetchMap(double lat, double lng, int zoom, int px_size) { + File pngfile = MapFile(lat, lng, zoom); + String url = MapURL(lat, lng, zoom, px_size); + + if (!pngfile.exists()) { + fetchMap(pngfile, url); + } + } + + public void loadMap(double lat, double lng, int zoom, int px_size) { + File pngfile = MapFile(lat, lng, zoom); + String url = MapURL(lat, lng, zoom, px_size); + + if (!pngfile.exists()) { + fetchAndLoadMap(pngfile, url); + return; + } + + try { + setIcon(new ImageIcon(ImageIO.read(pngfile))); + return; + } catch (IOException e) { + System.out.printf("# IO error trying to load %s\n", pngfile); + return; + } + } + + private static File MapFile(double lat, double lng, int zoom) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return new File(AltosPreferences.logdir(), + String.format("map-%c%.6f,%c%.6f-%d.png", + chlat, lat, chlng, lng, zoom)); + } + + private static String MapURL(double lat, double lng, + int zoom, int px_size) + { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + } +} + diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index ca68412a..56bc98af 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -37,7 +37,7 @@ public class AltosSiteMapTile extends JLayeredPane { Point2D.Double coord_pt; Point2D.Double last_pt; - JLabel mapLabel; + AltosSiteMapLabel mapLabel; JLabel draw; Graphics2D g2d; @@ -48,15 +48,7 @@ public class AltosSiteMapTile extends JLayeredPane { private void loadMap() { Point2D.Double map_latlng = latlng(px_size/2, px_size/2); - File pngfile = new File(AltosPreferences.logdir(), - FileCoord(map_latlng, zoom)); - try { - mapLabel.setIcon(new ImageIcon(ImageIO.read(pngfile))); - } catch (Exception e) { - // throw new RuntimeException(e); - System.out.printf("# Failed to find file %s\n", pngfile); - System.out.printf(" wget -O '%s' 'http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32'\n", pngfile, map_latlng.x, map_latlng.y, zoom, px_size, px_size); - } + mapLabel.loadMap(map_latlng.x, map_latlng.y, zoom, px_size); } private boolean setLocation(double lat, double lng) { @@ -88,22 +80,6 @@ public class AltosSiteMapTile extends JLayeredPane { return v; } - private static String FileCoord(Point2D.Double latlng, int zoom) { - double lat, lng; - lat = latlng.x; - lng = latlng.y; - return FileCoord(lat, lng, zoom); - } - private static String FileCoord(double lat, double lng, int zoom) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom); - } - - // based on google js // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js // search for fromLatLngToPoint and fromPointToLatLng @@ -172,7 +148,7 @@ public class AltosSiteMapTile extends JLayeredPane { if (last_pt == null) { setLocation(state.pad_lat, state.pad_lon); loadMap(); - last_pt = pt; + last_pt = pt(state.pad_lat, state.pad_lon); } Point2D.Double pt = pt(state.gps.lat, state.gps.lon); @@ -221,7 +197,7 @@ public class AltosSiteMapTile extends JLayeredPane { public AltosSiteMapTile(int x_tile_offset, int y_tile_offset) { setPreferredSize(new Dimension(px_size, px_size)); - mapLabel = new JLabel(); + mapLabel = new AltosSiteMapLabel(); fillLabel(mapLabel, Color.GRAY); mapLabel.setOpaque(true); mapLabel.setBounds(0, 0, px_size, px_size); diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 41afdf27..334608f6 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -63,6 +63,7 @@ altosui_JAVA = \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosSiteMap.java \ + AltosSiteMapLabel.java \ AltosSiteMapTile.java \ AltosState.java \ AltosTelemetry.java \ -- cgit v1.2.3 From 51e403145d28ac913e36d205077a613845596be2 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 00:17:51 +1000 Subject: AltosSiteMapTile: draw boost circle as well as landed --- ao-tools/altosui/AltosSiteMapTile.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index 56bc98af..6035a794 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -137,6 +137,7 @@ public class AltosSiteMapTile extends JLayeredPane { }; boolean drawn_landed_circle = false; + boolean drawn_boost_circle = false; public void show(AltosState state, int crc_errors) { if (!state.gps_ready) { if (state.pad_lat == 0 && state.pad_lon == 0) @@ -172,9 +173,16 @@ public class AltosSiteMapTile extends JLayeredPane { } } + if (state.state == 3 && !drawn_boost_circle) { + drawn_boost_circle = true; + g2d.setColor(Color.RED); + g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); + g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); + g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); + } if (state.state == 8 && !drawn_landed_circle) { drawn_landed_circle = true; - g2d.setColor(Color.RED); + g2d.setColor(Color.BLACK); g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); -- cgit v1.2.3 From 89f44c5587ea4f927d5e398b6af919df0d6561c3 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 01:27:01 +1000 Subject: AltosAscent/Descent: tidy up layout --- ao-tools/altosui/AltosAscent.java | 15 +-- ao-tools/altosui/AltosDescent.java | 195 ++++++++++++++++++------------------- 2 files changed, 101 insertions(+), 109 deletions(-) diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 38ced95e..9bba6633 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -69,6 +69,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -93,7 +94,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { label = new JLabel(text); label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; + c.gridx = 1; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -104,7 +105,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value = new JTextField(30); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; + c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.gridwidth = 2; @@ -142,7 +143,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { label = new JLabel(text); label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; + c.gridx = 1; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -153,7 +154,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value = new JTextField(15); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; + c.gridx = 2; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -163,7 +164,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { max_value = new JTextField(15); max_value.setFont(Altos.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; + c.gridx = 3; c.gridy = y; c.anchor = GridBagConstraints.EAST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -299,14 +300,14 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { cur = new JLabel("Current"); cur.setFont(Altos.label_font); c = new GridBagConstraints(); - c.gridx = 1; c.gridy = y; + c.gridx = 2; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); layout.setConstraints(cur, c); add(cur); max = new JLabel("Maximum"); max.setFont(Altos.label_font); - c.gridx = 2; c.gridy = y; + c.gridx = 3; c.gridy = y; layout.setConstraints(max, c); add(max); } diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index aacd2998..379946e1 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -31,12 +31,12 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; - public class DescentStatus { + public abstract class DescentStatus { JLabel label; JTextField value; AltosLights lights; - void show(AltosState state, int crc_errors) {} + abstract void show(AltosState state, int crc_errors); void reset() { value.setText(""); lights.set(false); @@ -69,6 +69,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -77,15 +78,17 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } } - public class DescentValue { + + public abstract class DescentValue { JLabel label; JTextField value; - void show(AltosState state, int crc_errors) {} void reset() { value.setText(""); } + abstract void show(AltosState state, int crc_errors); + void show(String format, double v) { value.setText(String.format(format, v)); } @@ -97,7 +100,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { label = new JLabel(text); label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = x + 0; c.gridy = y; + c.gridx = x + 1; c.gridy = y; c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; @@ -108,7 +111,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 1; c.gridy = y; + c.gridx = x + 2; c.gridy = y; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -117,12 +121,70 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } } - class Height extends DescentValue { + public abstract class DescentDualValue { + JLabel label; + JTextField value1; + JTextField value2; + + void reset() { + value1.setText(""); + value2.setText(""); + } + + abstract void show(AltosState state, int crc_errors); + void show(String v1, String v2) { + value1.setText(v1); + value2.setText(v2); + } + void show(String f1, double v1, String f2, double v2) { + value1.setText(String.format(f1, v1)); + value2.setText(String.format(f2, v2)); + } + + public DescentDualValue (GridBagLayout layout, int x, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = x + 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value1 = new JTextField(17); + value1.setFont(Altos.value_font); + value1.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value1, c); + add(value1); + + value2 = new JTextField(17); + value2.setFont(Altos.value_font); + value2.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 3; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value2, c); + add(value2); + } + } + + class Height extends DescentDualValue { void show (AltosState state, int crc_errors) { - show("%6.0f m", state.height); + show("%6.0f m", state.height, + "%3.0f°", state.elevation); } public Height (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Height"); + super (layout, x, y, "Height/Elevation"); } } @@ -153,33 +215,20 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { return String.format("%s %4d° %9.6f", h, deg, min); } - class Lat extends DescentValue { + class LatLon extends DescentDualValue { void show (AltosState state, int crc_errors) { if (state.gps != null) - value.setText(pos(state.gps.lat,"N", "S")); + show(pos(state.gps.lat,"N", "S"), + pos(state.gps.lon,"W", "E")); else - value.setText("???"); + show("???", "???"); } - public Lat (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Latitude"); + public LatLon (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Lat/Long"); } } - Lat lat; - - class Lon extends DescentValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - value.setText(pos(state.gps.lon,"E", "W")); - else - value.setText("???"); - } - public Lon (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Longitude"); - } - } - - Lon lon; + LatLon latlon; class Apogee extends DescentStatus { void show (AltosState state, int crc_errors) { @@ -205,78 +254,23 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Main main; - class Bearing { - JLabel label; - JTextField value; - JTextField value_deg; - void reset () { - value.setText(""); - value_deg.setText(""); - } + class Bearing extends DescentDualValue { void show (AltosState state, int crc_errors) { if (state.from_pad != null) { - value.setText(state.from_pad.bearing_words( - AltosGreatCircle.BEARING_LONG)); - value_deg.setText(String.format("%3.0f°", state.from_pad.bearing)); + show( state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG), + String.format("%3.0f°", state.from_pad.bearing)); } else { - value.setText("???"); - value_deg.setText("???"); + show("???", "???"); } } public Bearing (GridBagLayout layout, int x, int y) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel("Bearing"); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = x + 0; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.weightx = 0; - c.fill = GridBagConstraints.VERTICAL; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(30); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 1; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.weightx = 1; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - layout.setConstraints(value, c); - add(value); - - value_deg = new JTextField(5); - value_deg.setFont(Altos.value_font); - value_deg.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 3; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.weightx = 1; - c.fill = GridBagConstraints.BOTH; - layout.setConstraints(value_deg, c); - add(value_deg); - } + super (layout, x, y, "Bearing"); + } } Bearing bearing; - class Elevation extends DescentValue { - void show (AltosState state, int crc_errors) { - if (state.from_pad != null) - show("%3.0f°", state.elevation); - else - value.setText("???"); - } - public Elevation (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Elevation"); - } - } - - Elevation elevation; - class Range extends DescentValue { void show (AltosState state, int crc_errors) { show("%6.0f m", state.range); @@ -289,12 +283,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Range range; public void reset() { - lat.reset(); - lon.reset(); + latlon.reset(); height.reset(); speed.reset(); bearing.reset(); - elevation.reset(); range.reset(); main.reset(); apogee.reset(); @@ -304,10 +296,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { height.show(state, crc_errors); speed.show(state, crc_errors); bearing.show(state, crc_errors); - elevation.show(state, crc_errors); range.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + latlon.show(state, crc_errors); main.show(state, crc_errors); apogee.show(state, crc_errors); } @@ -318,11 +308,12 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { setLayout(layout); /* Elements in descent display */ - speed = new Speed(layout, 0, 0); height = new Height(layout, 2, 0); - elevation = new Elevation(layout, 0, 1); range = new Range(layout, 2, 1); - bearing = new Bearing(layout, 0, 2); - lat = new Lat(layout, 0, 3); - lon = new Lon(layout, 0, 4); + speed = new Speed(layout, 0, 0); + height = new Height(layout, 0, 1); + range = new Range(layout, 0, 2); + bearing = new Bearing(layout, 0, 3); + latlon = new LatLon(layout, 0, 4); + apogee = new Apogee(layout, 5); main = new Main(layout, 6); } -- cgit v1.2.3 From 6f8bc2ad20b715343e0510563ab0f14787ef3e07 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 01:34:52 +1000 Subject: AltosDescent: switch elev from height to range --- ao-tools/altosui/AltosDescent.java | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index 379946e1..930b8968 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -178,13 +178,12 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } } - class Height extends DescentDualValue { + class Height extends DescentValue { void show (AltosState state, int crc_errors) { - show("%6.0f m", state.height, - "%3.0f°", state.elevation); + show("%6.0f m", state.height); } public Height (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Height/Elevation"); + super (layout, x, y, "Height"); } } @@ -224,7 +223,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { show("???", "???"); } public LatLon (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Lat/Long"); + super (layout, x, y, "Latitude, Longitude"); } } @@ -257,9 +256,9 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Bearing extends DescentDualValue { void show (AltosState state, int crc_errors) { if (state.from_pad != null) { - show( state.from_pad.bearing_words( - AltosGreatCircle.BEARING_LONG), - String.format("%3.0f°", state.from_pad.bearing)); + show( String.format("%3.0f°", state.from_pad.bearing), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG)); } else { show("???", "???"); } @@ -271,12 +270,13 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Bearing bearing; - class Range extends DescentValue { + class Range extends DescentDualValue { void show (AltosState state, int crc_errors) { - show("%6.0f m", state.range); + show("%6.0f m", state.range, + "%3.0f°", state.elevation); } public Range (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Range"); + super (layout, x, y, "Range, Elevation"); } } -- cgit v1.2.3 From b47517d4c2e49f6f7b9954d2c85f96397fe1103e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 14:06:37 -0800 Subject: altosui: re-indent --- ao-tools/altosui/AltosAscent.java | 2 +- ao-tools/altosui/AltosDescent.java | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 9bba6633..b1b812a1 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -69,7 +69,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; - c.gridwidth = 2; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index 930b8968..d6de8b98 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -69,7 +69,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; - c.gridwidth = 2; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -112,7 +112,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; - c.gridwidth = 2; + c.gridwidth = 2; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -133,9 +133,9 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { abstract void show(AltosState state, int crc_errors); void show(String v1, String v2) { - value1.setText(v1); - value2.setText(v2); - } + value1.setText(v1); + value2.setText(v2); + } void show(String f1, double v1, String f2, double v2) { value1.setText(String.format(f1, v1)); value2.setText(String.format(f2, v2)); @@ -217,8 +217,8 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class LatLon extends DescentDualValue { void show (AltosState state, int crc_errors) { if (state.gps != null) - show(pos(state.gps.lat,"N", "S"), - pos(state.gps.lon,"W", "E")); + show(pos(state.gps.lat,"N", "S"), + pos(state.gps.lon,"W", "E")); else show("???", "???"); } @@ -256,16 +256,16 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Bearing extends DescentDualValue { void show (AltosState state, int crc_errors) { if (state.from_pad != null) { - show( String.format("%3.0f°", state.from_pad.bearing), - state.from_pad.bearing_words( - AltosGreatCircle.BEARING_LONG)); + show( String.format("%3.0f°", state.from_pad.bearing), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG)); } else { show("???", "???"); } } public Bearing (GridBagLayout layout, int x, int y) { super (layout, x, y, "Bearing"); - } + } } Bearing bearing; @@ -273,7 +273,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Range extends DescentDualValue { void show (AltosState state, int crc_errors) { show("%6.0f m", state.range, - "%3.0f°", state.elevation); + "%3.0f°", state.elevation); } public Range (GridBagLayout layout, int x, int y) { super (layout, x, y, "Range, Elevation"); @@ -308,11 +308,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { setLayout(layout); /* Elements in descent display */ - speed = new Speed(layout, 0, 0); - height = new Height(layout, 0, 1); - range = new Range(layout, 0, 2); - bearing = new Bearing(layout, 0, 3); - latlon = new LatLon(layout, 0, 4); + speed = new Speed(layout, 0, 0); + height = new Height(layout, 0, 1); + range = new Range(layout, 0, 2); + bearing = new Bearing(layout, 0, 3); + latlon = new LatLon(layout, 0, 4); apogee = new Apogee(layout, 5); main = new Main(layout, 6); -- cgit v1.2.3 From 72f5e05f9f0055f2cef8b840812f090556c94338 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 08:18:39 +1000 Subject: AltosSiteMap: major refactoring --- ao-tools/altosui/AltosSiteMap.java | 214 ++++++++++++++++++++++++++++---- ao-tools/altosui/AltosSiteMapCache.java | 103 +++++++++++++++ ao-tools/altosui/AltosSiteMapLabel.java | 142 --------------------- ao-tools/altosui/AltosSiteMapTile.java | 117 ++--------------- ao-tools/altosui/AltosUI.java | 6 +- ao-tools/altosui/Makefile.am | 3 +- 6 files changed, 316 insertions(+), 269 deletions(-) create mode 100644 ao-tools/altosui/AltosSiteMapCache.java delete mode 100644 ao-tools/altosui/AltosSiteMapLabel.java diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 1db83959..a8b66dac 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -33,36 +33,206 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { + // max vertical step in a tile in naut. miles + static final double tile_size_nmi = 1.0; + + static final int px_size = 512; + + private static Point2D.Double translatePoint(Point2D.Double p, + Point2D.Double d) + { + return new Point2D.Double(p.x + d.x, p.y + d.y); + } + + static class LatLng { + public double lat, lng; + public LatLng(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + private static Point2D.Double pt(LatLng latlng, int zoom) { + double scale_x = 256/360.0 * Math.pow(2, zoom); + double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + return pt(latlng, scale_x, scale_y); + } + + private static Point2D.Double pt(LatLng latlng, + double scale_x, double scale_y) + { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = latlng.lng * scale_x; + + e = Math.sin(Math.toRadians(latlng.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + static private LatLng latlng(Point2D.Double pt, + double scale_x, double scale_y) + { + double lat, lng; + double rads; + + lng = pt.x/scale_x; + rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new LatLng(lat,lng); + } + + int zoom; + double scale_x, scale_y; + + private Point2D.Double pt(double lat, double lng) { + return pt(new LatLng(lat, lng), scale_x, scale_y); + } + + private LatLng latlng(double x, double y) { + return latlng(new Point2D.Double(x,y), scale_x, scale_y); + } + private LatLng latlng(Point2D.Double pt) { + return latlng(pt, scale_x, scale_y); + } + + AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; + Point2D.Double [] tileOffset = new Point2D.Double[9]; + + private Point2D.Double getBaseLocation(double lat, double lng) { + Point2D.Double locn, north_step; + + zoom = 2; + // stupid loop structure to please Java's control flow analysis + do { + zoom++; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + locn = pt(lat, lng); + north_step = pt(lat+tile_size_nmi/60.0, lng); + if (locn.y - north_step.y > px_size) + break; + } while (zoom < 22); + locn.x = -px_size * Math.floor(locn.x/px_size); + locn.y = -px_size * Math.floor(locn.y/px_size); + return locn; + } + public void reset() { // nothing } - public void show(AltosState state, int crc_errors) { - for (int x = 0; x < mapTiles.length; x++) { - mapTiles[x].show(state, crc_errors); + + private void bgLoadMap(final int i, + final File pngfile, final String pngurl) + { + Thread thread = new Thread() { + public void run() { + ImageIcon res; + res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); + if (res != null) { + mapTiles[i].loadMap(res); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } + }; + thread.start(); + } + + public static void prefetchMaps(double lat, double lng, int w, int h) { + AltosPreferences.init(null); + + AltosSiteMap asm = new AltosSiteMap(true); + Point2D.Double c = asm.getBaseLocation(lat, lng); + Point2D.Double p = new Point2D.Double(); + Point2D.Double p2; + int dx = -w/2, dy = -h/2; + for (int y = dy; y < h+dy; y++) { + for (int x = dx; x < w+dx; x++) { + LatLng map_latlng = asm.latlng( + -c.x + x*px_size + px_size/2, + -c.y + y*px_size + px_size/2); + File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); + if (pngfile.exists()) { + System.out.printf("Already have %s\n", pngfile); + } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { + System.out.printf("Fetched map %s\n", pngfile); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } } } - - AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; - class GrabNDrag extends MouseInputAdapter { - private JComponent scroll; - private Point startPt = new Point(); + private void initMaps(double lat, double lng) { + Point2D.Double c = getBaseLocation(lat, lng); + Point2D.Double p = new Point2D.Double(); + + for (int i = 0; i < 9; i++) { + int x = i%3 - 1, y = i/3 - 1; - public GrabNDrag(JComponent parent) { - scroll = parent; + tileOffset[i] = new Point2D.Double( + c.x - x*px_size, p.y = c.y - y*px_size); + LatLng map_latlng = latlng( + -tileOffset[i].x+px_size/2, + -tileOffset[i].y+px_size/2); + + File pngfile = MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng); + bgLoadMap(i, pngfile, pngurl); + } + } + + private File MapFile(double lat, double lng) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return new File(AltosPreferences.logdir(), + String.format("map-%c%.6f,%c%.6f-%d.png", + chlat, lat, chlng, lng, zoom)); + } + + private String MapURL(double lat, double lng) { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + } + + boolean initialised = false; + public void show(AltosState state, int crc_errors) { + // if insufficient gps data, nothing to update + if (!state.gps_ready) { + if (state.pad_lat == 0 && state.pad_lon == 0) + return; + if (state.ngps < 3) + return; + } + + if (!initialised) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; } - public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); + Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + for (int x = 0; x < mapTiles.length; x++) { + mapTiles[x].show(state, crc_errors, + translatePoint(pt, tileOffset[x])); } - public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; - - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); + } + + private AltosSiteMap(boolean knowWhatYouAreDoing) { + if (!knowWhatYouAreDoing) { + throw new RuntimeException("Arggh."); } } @@ -83,9 +253,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; + // put some space between the map tiles, debugging only + // c.insets = new Insets(5, 5, 5, 5); for (int x = 0; x < 9; x++) { c.gridx = x % 3; c.gridy = x / 3; - mapTiles[x] = new AltosSiteMapTile((x%3)-1, (x/3)-1); + mapTiles[x] = new AltosSiteMapTile(px_size); layout.setConstraints(mapTiles[x], c); comp.add(mapTiles[x]); } diff --git a/ao-tools/altosui/AltosSiteMapCache.java b/ao-tools/altosui/AltosSiteMapCache.java new file mode 100644 index 00000000..dbdcbf65 --- /dev/null +++ b/ao-tools/altosui/AltosSiteMapCache.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.net.URL; +import java.net.URLConnection; + +public class AltosSiteMapCache extends JLabel { + public static boolean fetchMap(File file, String url) { + URL u; + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return false; + } + + byte[] data; + try { + URLConnection uc = u.openConnection(); + int contentLength = uc.getContentLength(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) { + return false; + } + } catch (IOException e) { + return false; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + if (file.exists()) { + file.delete(); + } + return false; + } + return true; + } + + public static ImageIcon fetchAndLoadMap(File pngfile, String url) { + if (!pngfile.exists()) { + if (!fetchMap(pngfile, url)) { + return null; + } + } + return loadMap(pngfile, url); + } + + public static ImageIcon loadMap(File pngfile, String url) { + if (!pngfile.exists()) { + return null; + } + + try { + return new ImageIcon(ImageIO.read(pngfile)); + } catch (IOException e) { + System.out.printf("# IO error trying to load %s\n", pngfile); + return null; + } + } +} + diff --git a/ao-tools/altosui/AltosSiteMapLabel.java b/ao-tools/altosui/AltosSiteMapLabel.java deleted file mode 100644 index 1a371c5b..00000000 --- a/ao-tools/altosui/AltosSiteMapLabel.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.imageio.ImageIO; -import javax.swing.table.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.net.URL; -import java.net.URLConnection; - -public class AltosSiteMapLabel extends JLabel { - public static boolean fetchMap(File file, String url) { - URL u; - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return false; - } - - byte[] data; - try { - URLConnection uc = u.openConnection(); - int contentLength = uc.getContentLength(); - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); - - if (offset != contentLength) { - return false; - } - } catch (IOException e) { - return false; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return false; - } catch (IOException e) { - if (file.exists()) { - file.delete(); - } - return false; - } - return true; - } - - public void fetchAndLoadMap(final File pngfile, final String url) { - System.out.printf("# Trying to fetch %s...\n", pngfile); - - Thread thread = new Thread() { - public void run() { - try { - if (fetchMap(pngfile, url)) { - setIcon(new ImageIcon(ImageIO.read(pngfile))); - } - } catch (Exception e) { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, url); - } - } - }; - thread.start(); - } - - public void fetchMap(double lat, double lng, int zoom, int px_size) { - File pngfile = MapFile(lat, lng, zoom); - String url = MapURL(lat, lng, zoom, px_size); - - if (!pngfile.exists()) { - fetchMap(pngfile, url); - } - } - - public void loadMap(double lat, double lng, int zoom, int px_size) { - File pngfile = MapFile(lat, lng, zoom); - String url = MapURL(lat, lng, zoom, px_size); - - if (!pngfile.exists()) { - fetchAndLoadMap(pngfile, url); - return; - } - - try { - setIcon(new ImageIcon(ImageIO.read(pngfile))); - return; - } catch (IOException e) { - System.out.printf("# IO error trying to load %s\n", pngfile); - return; - } - } - - private static File MapFile(double lat, double lng, int zoom) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return new File(AltosPreferences.logdir(), - String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom)); - } - - private static String MapURL(double lat, double lng, - int zoom, int px_size) - { - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); - } -} - diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index 6035a794..de28fc8b 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -32,96 +32,15 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMapTile extends JLayeredPane { - int zoom; - double scale_x, scale_y; Point2D.Double coord_pt; Point2D.Double last_pt; - AltosSiteMapLabel mapLabel; + JLabel mapLabel; JLabel draw; Graphics2D g2d; - int off_x; - int off_y; - - static final int px_size = 512; - - private void loadMap() { - Point2D.Double map_latlng = latlng(px_size/2, px_size/2); - mapLabel.loadMap(map_latlng.x, map_latlng.y, zoom, px_size); - } - - private boolean setLocation(double lat, double lng) { - Point2D.Double north_step; - double step_nm = 0.5; - for (zoom = 3; zoom < 22; zoom++) { - coord_pt = pt(lat, lng, new Point2D.Double(0,0), zoom); - north_step = pt(lat+step_nm/60.0, lng, - new Point2D.Double(0,0), zoom); - if (coord_pt.y - north_step.y > px_size/2) - break; - } - coord_pt.x = -px_size * Math.floor(coord_pt.x/px_size + off_x); - coord_pt.y = -px_size * Math.floor(coord_pt.y/px_size + off_y); - - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - - last_pt = null; - - return true; - } - - private static double limit(double v, double lo, double hi) { - if (v < lo) - return lo; - if (hi < v) - return hi; - return v; - } - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - private Point2D.Double pt(double lat, double lng) { - return pt(lat, lng, coord_pt, scale_x, scale_y); - } - - private static Point2D.Double pt(double lat, double lng, - Point2D.Double centre, int zoom) - { - double scale_x = 256/360.0 * Math.pow(2, zoom); - double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - return pt(lat, lng, centre, scale_x, scale_y); - } - - private static Point2D.Double pt(double lat, double lng, - Point2D.Double centre, double scale_x, double scale_y) - { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = centre.x + lng*scale_x; - e = limit(Math.sin(Math.toRadians(lat)),-(1-1.0E-15),1-1.0E-15); - res.y = centre.y + 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - private Point2D.Double latlng(double x, double y) { - return latlng(new Point2D.Double(x,y), coord_pt); - } - private Point2D.Double latlng(Point2D.Double pt) { - return latlng(pt, coord_pt); - } - private Point2D.Double latlng(Point2D.Double pt, Point2D.Double centre) { - double lat, lng; - double rads; - - lng = (pt.x - centre.x)/scale_x; - rads = 2 * Math.atan(Math.exp((pt.y-centre.y)/-scale_y)); - lat = Math.toDegrees(rads - Math.PI/2); - - return new Point2D.Double(lat,lng); + public void loadMap(ImageIcon icn) { + mapLabel.setIcon(icn); } static Color stateColors[] = { @@ -138,21 +57,13 @@ public class AltosSiteMapTile extends JLayeredPane { boolean drawn_landed_circle = false; boolean drawn_boost_circle = false; - public void show(AltosState state, int crc_errors) { - if (!state.gps_ready) { - if (state.pad_lat == 0 && state.pad_lon == 0) - return; - if (state.ngps < 3) - return; - } - + public void show(AltosState state, int crc_errors, Point2D.Double pt) { if (last_pt == null) { - setLocation(state.pad_lat, state.pad_lon); - loadMap(); - last_pt = pt(state.pad_lat, state.pad_lon); + // setLocation(state.pad_lat, state.pad_lon); + // loadMap(); + last_pt = pt; } - Point2D.Double pt = pt(state.gps.lat, state.gps.lon); if (pt != last_pt) { if (0 <= state.state && state.state < stateColors.length) { g2d.setColor(stateColors[state.state]); @@ -160,6 +71,7 @@ public class AltosSiteMapTile extends JLayeredPane { g2d.draw(new Line2D.Double(last_pt, pt)); } + int px_size = getWidth(); if (0 <= pt.x && pt.x < px_size) { if (0 <= pt.y && pt.y < px_size) { int dx = 500, dy = 250; @@ -192,7 +104,7 @@ public class AltosSiteMapTile extends JLayeredPane { repaint(); } - public static Graphics2D fillLabel(JLabel l, Color c) { + public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { BufferedImage img = new BufferedImage(px_size, px_size, BufferedImage.TYPE_INT_ARGB); Graphics2D g = img.createGraphics(); @@ -202,24 +114,21 @@ public class AltosSiteMapTile extends JLayeredPane { return g; } - public AltosSiteMapTile(int x_tile_offset, int y_tile_offset) { + public AltosSiteMapTile(int px_size) { setPreferredSize(new Dimension(px_size, px_size)); - mapLabel = new AltosSiteMapLabel(); - fillLabel(mapLabel, Color.GRAY); + mapLabel = new JLabel(); + fillLabel(mapLabel, Color.GRAY, px_size); mapLabel.setOpaque(true); mapLabel.setBounds(0, 0, px_size, px_size); add(mapLabel, new Integer(0)); draw = new JLabel(); - g2d = fillLabel(draw, new Color(127, 127, 127, 0)); + g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); draw.setBounds(0, 0, px_size, px_size); draw.setOpaque(false); add(draw, new Integer(1)); - - off_x = x_tile_offset; - off_y = y_tile_offset; } } diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 6bfde014..93a5e0d8 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -353,7 +353,11 @@ public class AltosUI extends JFrame { public static void main(final String[] args) { int process = 0; /* Handle batch-mode */ - if (args.length == 2 && args[0].equals("--replay")) { + if (args.length == 3 && args[0].equals("--fetchmaps")) { + double lat = Double.parseDouble(args[1]); + double lon = Double.parseDouble(args[2]); + AltosSiteMap.prefetchMaps(lat, lon, 5, 5); + } else if (args.length == 2 && args[0].equals("--replay")) { String filename = args[1]; FileInputStream in; try { diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 334608f6..93a43b12 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -10,6 +10,7 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/ bin_SCRIPTS=altosui altosui_JAVA = \ + GrabNDrag.java \ AltosAscent.java \ AltosChannelMenu.java \ AltosConfig.java \ @@ -63,7 +64,7 @@ altosui_JAVA = \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosSiteMap.java \ - AltosSiteMapLabel.java \ + AltosSiteMapCache.java \ AltosSiteMapTile.java \ AltosState.java \ AltosTelemetry.java \ -- cgit v1.2.3 From 66ebd954d9c9a44a8db0ee713c682e39306fabd8 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 08:28:24 +1000 Subject: Add GrabNDrag.java --- ao-tools/altosui/GrabNDrag.java | 51 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 ao-tools/altosui/GrabNDrag.java diff --git a/ao-tools/altosui/GrabNDrag.java b/ao-tools/altosui/GrabNDrag.java new file mode 100644 index 00000000..b44f3fe2 --- /dev/null +++ b/ao-tools/altosui/GrabNDrag.java @@ -0,0 +1,51 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; + +class GrabNDrag extends MouseInputAdapter { + private JComponent scroll; + private Point startPt = new Point(); + + public GrabNDrag(JComponent parent) { + scroll = parent; + } + + public void mousePressed(MouseEvent e) { + startPt.setLocation(e.getPoint()); + } + public void mouseDragged(MouseEvent e) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; + + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } +} -- cgit v1.2.3 From 37f0201d724693528f37ac7d275f68f90cf94da0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 14:31:23 -0800 Subject: altosui: change descent tab formatting to four columns This places labels to the left of each field. For igniter voltages, it uses three columns for the labels. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosAscent.java | 8 ++-- ao-tools/altosui/AltosDescent.java | 93 ++++++++++++++++++++++++++------------ ao-tools/altosui/AltosLanded.java | 2 +- ao-tools/altosui/AltosPad.java | 4 +- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index b1b812a1..2ceaa183 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -65,7 +65,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(15); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -102,7 +102,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(30); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -151,7 +151,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(15); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -161,7 +161,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(value, c); add(value); - max_value = new JTextField(15); + max_value = new JTextField(17); max_value.setFont(Altos.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 3; c.gridy = y; diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index d6de8b98..abe64fdc 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -61,15 +61,16 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; + c.gridwidth = 3; c.weightx = 0; layout.setConstraints(label, c); add(label); - value = new JTextField(15); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.gridwidth = 2; + c.gridx = 4; c.gridy = y; + c.gridwidth = 1; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; @@ -93,6 +94,10 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setText(String.format(format, v)); } + void show(String v) { + value.setText(v); + } + public DescentValue (GridBagLayout layout, int x, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -105,19 +110,17 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.VERTICAL; c.weightx = 0; - layout.setConstraints(label, c); - add(label); + add(label, c); value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; - c.gridwidth = 2; + c.gridwidth = 1; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; - layout.setConstraints(value, c); - add(value); + add(value, c); } } @@ -169,10 +172,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2 = new JTextField(17); value2.setFont(Altos.value_font); value2.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 3; c.gridy = y; + c.gridx = x + 4; c.gridy = y; c.anchor = GridBagConstraints.WEST; c.fill = GridBagConstraints.BOTH; c.weightx = 1; + c.gridwidth = 1; layout.setConstraints(value2, c); add(value2); } @@ -211,23 +215,36 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } int deg = (int) Math.floor(p); double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %4d° %9.6f", h, deg, min); + return String.format("%s %d° %9.6f", h, deg, min); } - class LatLon extends DescentDualValue { + class Lat extends DescentValue { void show (AltosState state, int crc_errors) { if (state.gps != null) - show(pos(state.gps.lat,"N", "S"), - pos(state.gps.lon,"W", "E")); + show(pos(state.gps.lat,"N", "S")); else - show("???", "???"); + show("???"); } - public LatLon (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Latitude, Longitude"); + public Lat (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Latitude"); } } - LatLon latlon; + Lat lat; + + class Lon extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + show(pos(state.gps.lon,"W", "E")); + else + show("???"); + } + public Lon (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Longitude"); + } + } + + Lon lon; class Apogee extends DescentStatus { void show (AltosState state, int crc_errors) { @@ -270,24 +287,36 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { Bearing bearing; - class Range extends DescentDualValue { + class Range extends DescentValue { void show (AltosState state, int crc_errors) { - show("%6.0f m", state.range, - "%3.0f°", state.elevation); + show("%6.0f m", state.range); } public Range (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Range, Elevation"); + super (layout, x, y, "Range"); } } Range range; + class Elevation extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%3.0f°", state.elevation); + } + public Elevation (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Elevation"); + } + } + + Elevation elevation; + public void reset() { - latlon.reset(); + lat.reset(); + lon.reset(); height.reset(); speed.reset(); bearing.reset(); range.reset(); + elevation.reset(); main.reset(); apogee.reset(); } @@ -297,7 +326,9 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { speed.show(state, crc_errors); bearing.show(state, crc_errors); range.show(state, crc_errors); - latlon.show(state, crc_errors); + elevation.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); main.show(state, crc_errors); apogee.show(state, crc_errors); } @@ -309,12 +340,14 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { /* Elements in descent display */ speed = new Speed(layout, 0, 0); - height = new Height(layout, 0, 1); - range = new Range(layout, 0, 2); - bearing = new Bearing(layout, 0, 3); - latlon = new LatLon(layout, 0, 4); - - apogee = new Apogee(layout, 5); - main = new Main(layout, 6); + height = new Height(layout, 2, 0); + elevation = new Elevation(layout, 0, 1); + range = new Range(layout, 2, 1); + bearing = new Bearing(layout, 0, 2); + lat = new Lat(layout, 0, 3); + lon = new Lon(layout, 2, 3); + + apogee = new Apogee(layout, 4); + main = new Main(layout, 5); } } diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java index 0656ea6c..059dbb6d 100644 --- a/ao-tools/altosui/AltosLanded.java +++ b/ao-tools/altosui/AltosLanded.java @@ -61,7 +61,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(30); + value = new JTextField(17); value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 77289f89..480e4d79 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -65,7 +65,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(15); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -101,7 +101,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(30); + value = new JTextField(17); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; -- cgit v1.2.3 From 82636305021c41d676f5f0f11378724fe0de0079 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 08:44:13 +1000 Subject: AltosSiteMap: be more polite about preferred size --- ao-tools/altosui/AltosSiteMap.java | 1 + 1 file changed, 1 insertion(+) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index a8b66dac..a241cbd0 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -262,6 +262,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { comp.add(mapTiles[x]); } setViewportView(comp); + setPreferredSize(new Dimension(500,200)); } } -- cgit v1.2.3 From 1e712647dd6df1e77650db705f3ac32a3c8f6907 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 08:58:44 +1000 Subject: altosui: reindent --- ao-tools/altosui/AltosSiteMap.java | 463 ++++++++++++++++---------------- ao-tools/altosui/AltosSiteMapCache.java | 126 ++++----- ao-tools/altosui/AltosSiteMapTile.java | 196 +++++++------- 3 files changed, 393 insertions(+), 392 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index a241cbd0..5f5e30f0 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -33,236 +33,237 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { - // max vertical step in a tile in naut. miles - static final double tile_size_nmi = 1.0; - - static final int px_size = 512; - - private static Point2D.Double translatePoint(Point2D.Double p, - Point2D.Double d) - { - return new Point2D.Double(p.x + d.x, p.y + d.y); - } - - static class LatLng { - public double lat, lng; - public LatLng(double lat, double lng) { - this.lat = lat; - this.lng = lng; - } - } - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - private static Point2D.Double pt(LatLng latlng, int zoom) { - double scale_x = 256/360.0 * Math.pow(2, zoom); - double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - return pt(latlng, scale_x, scale_y); - } - - private static Point2D.Double pt(LatLng latlng, - double scale_x, double scale_y) - { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = latlng.lng * scale_x; - - e = Math.sin(Math.toRadians(latlng.lat)); - e = Math.max(e,-(1-1.0E-15)); - e = Math.min(e, 1-1.0E-15 ); - - res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - static private LatLng latlng(Point2D.Double pt, - double scale_x, double scale_y) - { - double lat, lng; - double rads; - - lng = pt.x/scale_x; - rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); - lat = Math.toDegrees(rads - Math.PI/2); - - return new LatLng(lat,lng); - } - - int zoom; - double scale_x, scale_y; - - private Point2D.Double pt(double lat, double lng) { - return pt(new LatLng(lat, lng), scale_x, scale_y); - } - - private LatLng latlng(double x, double y) { - return latlng(new Point2D.Double(x,y), scale_x, scale_y); - } - private LatLng latlng(Point2D.Double pt) { - return latlng(pt, scale_x, scale_y); - } - - AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; - Point2D.Double [] tileOffset = new Point2D.Double[9]; - - private Point2D.Double getBaseLocation(double lat, double lng) { - Point2D.Double locn, north_step; - - zoom = 2; - // stupid loop structure to please Java's control flow analysis - do { - zoom++; - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - locn = pt(lat, lng); - north_step = pt(lat+tile_size_nmi/60.0, lng); - if (locn.y - north_step.y > px_size) - break; - } while (zoom < 22); - locn.x = -px_size * Math.floor(locn.x/px_size); - locn.y = -px_size * Math.floor(locn.y/px_size); - return locn; - } - - public void reset() { - // nothing - } - - private void bgLoadMap(final int i, - final File pngfile, final String pngurl) - { - Thread thread = new Thread() { - public void run() { - ImageIcon res; - res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); - if (res != null) { - mapTiles[i].loadMap(res); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); - } - } - }; - thread.start(); - } - - public static void prefetchMaps(double lat, double lng, int w, int h) { - AltosPreferences.init(null); - - AltosSiteMap asm = new AltosSiteMap(true); - Point2D.Double c = asm.getBaseLocation(lat, lng); - Point2D.Double p = new Point2D.Double(); - Point2D.Double p2; - int dx = -w/2, dy = -h/2; - for (int y = dy; y < h+dy; y++) { - for (int x = dx; x < w+dx; x++) { - LatLng map_latlng = asm.latlng( - -c.x + x*px_size + px_size/2, - -c.y + y*px_size + px_size/2); - File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); - if (pngfile.exists()) { - System.out.printf("Already have %s\n", pngfile); - } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { - System.out.printf("Fetched map %s\n", pngfile); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); - } - } - } - } - - private void initMaps(double lat, double lng) { - Point2D.Double c = getBaseLocation(lat, lng); - Point2D.Double p = new Point2D.Double(); - - for (int i = 0; i < 9; i++) { - int x = i%3 - 1, y = i/3 - 1; - - tileOffset[i] = new Point2D.Double( - c.x - x*px_size, p.y = c.y - y*px_size); - LatLng map_latlng = latlng( - -tileOffset[i].x+px_size/2, - -tileOffset[i].y+px_size/2); - - File pngfile = MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng); - bgLoadMap(i, pngfile, pngurl); - } - } - - private File MapFile(double lat, double lng) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return new File(AltosPreferences.logdir(), - String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom)); - } - - private String MapURL(double lat, double lng) { - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); - } - - boolean initialised = false; - public void show(AltosState state, int crc_errors) { - // if insufficient gps data, nothing to update - if (!state.gps_ready) { - if (state.pad_lat == 0 && state.pad_lon == 0) - return; - if (state.ngps < 3) - return; - } - - if (!initialised) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; - } - - Point2D.Double pt = pt(state.gps.lat, state.gps.lon); - for (int x = 0; x < mapTiles.length; x++) { - mapTiles[x].show(state, crc_errors, - translatePoint(pt, tileOffset[x])); - } - } - - private AltosSiteMap(boolean knowWhatYouAreDoing) { - if (!knowWhatYouAreDoing) { - throw new RuntimeException("Arggh."); - } - } - - public AltosSiteMap() { - JComponent comp = new JComponent() { - GrabNDrag scroller = new GrabNDrag(this); - { - addMouseMotionListener(scroller); - addMouseListener(scroller); - setAutoscrolls(true); - } - }; - - GridBagLayout layout = new GridBagLayout(); - comp.setLayout(layout); - - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - - // put some space between the map tiles, debugging only - // c.insets = new Insets(5, 5, 5, 5); - for (int x = 0; x < 9; x++) { - c.gridx = x % 3; c.gridy = x / 3; - mapTiles[x] = new AltosSiteMapTile(px_size); - layout.setConstraints(mapTiles[x], c); - comp.add(mapTiles[x]); - } - setViewportView(comp); - setPreferredSize(new Dimension(500,200)); - } + // max vertical step in a tile in naut. miles + static final double tile_size_nmi = 1.0; + + static final int px_size = 512; + + private static Point2D.Double translatePoint(Point2D.Double p, + Point2D.Double d) + { + return new Point2D.Double(p.x + d.x, p.y + d.y); + } + + static class LatLng { + public double lat, lng; + public LatLng(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + private static Point2D.Double pt(LatLng latlng, int zoom) { + double scale_x = 256/360.0 * Math.pow(2, zoom); + double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + return pt(latlng, scale_x, scale_y); + } + + private static Point2D.Double pt(LatLng latlng, + double scale_x, double scale_y) + { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = latlng.lng * scale_x; + + e = Math.sin(Math.toRadians(latlng.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + static private LatLng latlng(Point2D.Double pt, + double scale_x, double scale_y) + { + double lat, lng; + double rads; + + lng = pt.x/scale_x; + rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new LatLng(lat,lng); + } + + int zoom; + double scale_x, scale_y; + + private Point2D.Double pt(double lat, double lng) { + return pt(new LatLng(lat, lng), scale_x, scale_y); + } + + private LatLng latlng(double x, double y) { + return latlng(new Point2D.Double(x,y), scale_x, scale_y); + } + private LatLng latlng(Point2D.Double pt) { + return latlng(pt, scale_x, scale_y); + } + + AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; + Point2D.Double [] tileOffset = new Point2D.Double[9]; + + private Point2D.Double getBaseLocation(double lat, double lng) { + Point2D.Double locn, north_step; + + zoom = 2; + // stupid loop structure to please Java's control flow analysis + do { + zoom++; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + locn = pt(lat, lng); + north_step = pt(lat+tile_size_nmi/60.0, lng); + if (locn.y - north_step.y > px_size) + break; + } while (zoom < 22); + locn.x = -px_size * Math.floor(locn.x/px_size); + locn.y = -px_size * Math.floor(locn.y/px_size); + return locn; + } + + public void reset() { + // nothing + } + + private void bgLoadMap(final int i, + final File pngfile, final String pngurl) + { + Thread thread = new Thread() { + public void run() { + ImageIcon res; + res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); + if (res != null) { + mapTiles[i].loadMap(res); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } + }; + thread.start(); + } + + public static void prefetchMaps(double lat, double lng, int w, int h) { + AltosPreferences.init(null); + + AltosSiteMap asm = new AltosSiteMap(true); + Point2D.Double c = asm.getBaseLocation(lat, lng); + Point2D.Double p = new Point2D.Double(); + Point2D.Double p2; + int dx = -w/2, dy = -h/2; + for (int y = dy; y < h+dy; y++) { + for (int x = dx; x < w+dx; x++) { + LatLng map_latlng = asm.latlng( + -c.x + x*px_size + px_size/2, + -c.y + y*px_size + px_size/2); + File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); + if (pngfile.exists()) { + System.out.printf("Already have %s\n", pngfile); + } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { + System.out.printf("Fetched map %s\n", pngfile); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } + } + } + + private void initMaps(double lat, double lng) { + Point2D.Double c = getBaseLocation(lat, lng); + Point2D.Double p = new Point2D.Double(); + + for (int i = 0; i < 9; i++) { + int x = i%3 - 1, y = i/3 - 1; + + tileOffset[i] = new Point2D.Double( + c.x - x*px_size, p.y = c.y - y*px_size); + LatLng map_latlng = latlng( + -tileOffset[i].x+px_size/2, + -tileOffset[i].y+px_size/2); + + File pngfile = MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng); + bgLoadMap(i, pngfile, pngurl); + } + } + + private File MapFile(double lat, double lng) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return new File(AltosPreferences.logdir(), + String.format("map-%c%.6f,%c%.6f-%d.png", + chlat, lat, chlng, lng, zoom)); + } + + private String MapURL(double lat, double lng) { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + } + + boolean initialised = false; + public void show(AltosState state, int crc_errors) { + // if insufficient gps data, nothing to update + if (!state.gps_ready) { + if (state.pad_lat == 0 && state.pad_lon == 0) + return; + if (state.ngps < 3) + return; + } + + if (!initialised) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; + } + + Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + for (int x = 0; x < mapTiles.length; x++) { + mapTiles[x].show(state, crc_errors, + translatePoint(pt, tileOffset[x])); + } + } + + private AltosSiteMap(boolean knowWhatYouAreDoing) { + if (!knowWhatYouAreDoing) { + throw new RuntimeException("Arggh."); + } + } + + public AltosSiteMap() { + JComponent comp = new JComponent() { + GrabNDrag scroller = new GrabNDrag(this); + { + addMouseMotionListener(scroller); + addMouseListener(scroller); + setAutoscrolls(true); + } + }; + + GridBagLayout layout = new GridBagLayout(); + comp.setLayout(layout); + + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + + // put some space between the map tiles, debugging only + // c.insets = new Insets(5, 5, 5, 5); + for (int x = 0; x < 9; x++) { + c.gridx = x % 3; + c.gridy = x / 3; + mapTiles[x] = new AltosSiteMapTile(px_size); + layout.setConstraints(mapTiles[x], c); + comp.add(mapTiles[x]); + } + setViewportView(comp); + setPreferredSize(new Dimension(500,200)); + } } diff --git a/ao-tools/altosui/AltosSiteMapCache.java b/ao-tools/altosui/AltosSiteMapCache.java index dbdcbf65..e9dbf8e6 100644 --- a/ao-tools/altosui/AltosSiteMapCache.java +++ b/ao-tools/altosui/AltosSiteMapCache.java @@ -31,73 +31,73 @@ import java.net.URL; import java.net.URLConnection; public class AltosSiteMapCache extends JLabel { - public static boolean fetchMap(File file, String url) { - URL u; - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return false; - } + public static boolean fetchMap(File file, String url) { + URL u; + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return false; + } - byte[] data; - try { - URLConnection uc = u.openConnection(); - int contentLength = uc.getContentLength(); - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); + byte[] data; + try { + URLConnection uc = u.openConnection(); + int contentLength = uc.getContentLength(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); - if (offset != contentLength) { - return false; - } - } catch (IOException e) { - return false; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return false; - } catch (IOException e) { - if (file.exists()) { - file.delete(); - } - return false; - } - return true; - } + if (offset != contentLength) { + return false; + } + } catch (IOException e) { + return false; + } - public static ImageIcon fetchAndLoadMap(File pngfile, String url) { - if (!pngfile.exists()) { - if (!fetchMap(pngfile, url)) { - return null; - } - } - return loadMap(pngfile, url); - } + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + if (file.exists()) { + file.delete(); + } + return false; + } + return true; + } - public static ImageIcon loadMap(File pngfile, String url) { - if (!pngfile.exists()) { - return null; - } + public static ImageIcon fetchAndLoadMap(File pngfile, String url) { + if (!pngfile.exists()) { + if (!fetchMap(pngfile, url)) { + return null; + } + } + return loadMap(pngfile, url); + } - try { - return new ImageIcon(ImageIO.read(pngfile)); - } catch (IOException e) { - System.out.printf("# IO error trying to load %s\n", pngfile); - return null; - } - } + public static ImageIcon loadMap(File pngfile, String url) { + if (!pngfile.exists()) { + return null; + } + + try { + return new ImageIcon(ImageIO.read(pngfile)); + } catch (IOException e) { + System.out.printf("# IO error trying to load %s\n", pngfile); + return null; + } + } } diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index de28fc8b..8aee86c1 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -32,103 +32,103 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMapTile extends JLayeredPane { - Point2D.Double coord_pt; - Point2D.Double last_pt; - - JLabel mapLabel; - JLabel draw; - Graphics2D g2d; - - public void loadMap(ImageIcon icn) { - mapLabel.setIcon(icn); - } - - static Color stateColors[] = { - Color.WHITE, // startup - Color.WHITE, // idle - Color.WHITE, // pad - Color.RED, // boost - Color.PINK, // fast - Color.YELLOW, // coast - Color.CYAN, // drogue - Color.BLUE, // main - Color.BLACK // landed - }; - - boolean drawn_landed_circle = false; - boolean drawn_boost_circle = false; - public void show(AltosState state, int crc_errors, Point2D.Double pt) { - if (last_pt == null) { - // setLocation(state.pad_lat, state.pad_lon); - // loadMap(); - last_pt = pt; - } - - if (pt != last_pt) { - if (0 <= state.state && state.state < stateColors.length) { - g2d.setColor(stateColors[state.state]); - } - g2d.draw(new Line2D.Double(last_pt, pt)); - } - - int px_size = getWidth(); - if (0 <= pt.x && pt.x < px_size) { - if (0 <= pt.y && pt.y < px_size) { - int dx = 500, dy = 250; - if (state.state > 2) { - dx = Math.min(200, 20 + (int) Math.abs(last_pt.x - pt.x)); - dy = Math.min(100, 10 + (int) Math.abs(last_pt.y - pt.y)); - } - Rectangle r = new Rectangle((int)pt.x-dx, (int)pt.y-dy, - dx*2, dy*2); - scrollRectToVisible(r); - } - } - - if (state.state == 3 && !drawn_boost_circle) { - drawn_boost_circle = true; - g2d.setColor(Color.RED); - g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); - g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); - g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); - } - if (state.state == 8 && !drawn_landed_circle) { - drawn_landed_circle = true; - g2d.setColor(Color.BLACK); - g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); - } - - last_pt = pt; - repaint(); - } - - public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { - BufferedImage img = new BufferedImage(px_size, px_size, - BufferedImage.TYPE_INT_ARGB); - Graphics2D g = img.createGraphics(); - g.setColor(c); - g.fillRect(0, 0, px_size, px_size); - l.setIcon(new ImageIcon(img)); - return g; - } - - public AltosSiteMapTile(int px_size) { - setPreferredSize(new Dimension(px_size, px_size)); - - mapLabel = new JLabel(); - fillLabel(mapLabel, Color.GRAY, px_size); - mapLabel.setOpaque(true); - mapLabel.setBounds(0, 0, px_size, px_size); - add(mapLabel, new Integer(0)); - - draw = new JLabel(); - g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); - draw.setBounds(0, 0, px_size, px_size); - draw.setOpaque(false); - - add(draw, new Integer(1)); - } + Point2D.Double coord_pt; + Point2D.Double last_pt; + + JLabel mapLabel; + JLabel draw; + Graphics2D g2d; + + public void loadMap(ImageIcon icn) { + mapLabel.setIcon(icn); + } + + static Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK // landed + }; + + boolean drawn_landed_circle = false; + boolean drawn_boost_circle = false; + public void show(AltosState state, int crc_errors, Point2D.Double pt) { + if (last_pt == null) { + // setLocation(state.pad_lat, state.pad_lon); + // loadMap(); + last_pt = pt; + } + + if (pt != last_pt) { + if (0 <= state.state && state.state < stateColors.length) { + g2d.setColor(stateColors[state.state]); + } + g2d.draw(new Line2D.Double(last_pt, pt)); + } + + int px_size = getWidth(); + if (0 <= pt.x && pt.x < px_size) { + if (0 <= pt.y && pt.y < px_size) { + int dx = 500, dy = 250; + if (state.state > 2) { + dx = Math.min(200, 20 + (int) Math.abs(last_pt.x - pt.x)); + dy = Math.min(100, 10 + (int) Math.abs(last_pt.y - pt.y)); + } + Rectangle r = new Rectangle((int)pt.x-dx, (int)pt.y-dy, + dx*2, dy*2); + scrollRectToVisible(r); + } + } + + if (state.state == 3 && !drawn_boost_circle) { + drawn_boost_circle = true; + g2d.setColor(Color.RED); + g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); + g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); + g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); + } + if (state.state == 8 && !drawn_landed_circle) { + drawn_landed_circle = true; + g2d.setColor(Color.BLACK); + g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + + last_pt = pt; + repaint(); + } + + public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { + BufferedImage img = new BufferedImage(px_size, px_size, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g = img.createGraphics(); + g.setColor(c); + g.fillRect(0, 0, px_size, px_size); + l.setIcon(new ImageIcon(img)); + return g; + } + + public AltosSiteMapTile(int px_size) { + setPreferredSize(new Dimension(px_size, px_size)); + + mapLabel = new JLabel(); + fillLabel(mapLabel, Color.GRAY, px_size); + mapLabel.setOpaque(true); + mapLabel.setBounds(0, 0, px_size, px_size); + add(mapLabel, new Integer(0)); + + draw = new JLabel(); + g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); + draw.setBounds(0, 0, px_size, px_size); + draw.setOpaque(false); + + add(draw, new Integer(1)); + } } -- cgit v1.2.3 From ece2c86e2641b2cd613791293526c492b1606aa1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 16:19:42 -0800 Subject: altosui: Rewrite info table to mix with scroll pane well. Fix startup size Using a single table for the info table means that the scroll pane automatically picks up the table headers and shows them above the scrollable view. This patch also fixes the application size at startup so that no scrollbar is required in the info table, and the window is < 800x600. Signed-off-by: Keith Packard --- ao-tools/altosui/Altos.java | 2 + ao-tools/altosui/AltosAscent.java | 8 +-- ao-tools/altosui/AltosDescent.java | 8 +-- ao-tools/altosui/AltosFlightInfoTableModel.java | 77 +++++++++++++------------ ao-tools/altosui/AltosFlightUI.java | 24 +++----- ao-tools/altosui/AltosInfoTable.java | 70 +++++++--------------- ao-tools/altosui/AltosLanded.java | 2 +- ao-tools/altosui/AltosPad.java | 4 +- 8 files changed, 83 insertions(+), 112 deletions(-) diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java index 197e98db..8ee94e04 100644 --- a/ao-tools/altosui/Altos.java +++ b/ao-tools/altosui/Altos.java @@ -73,6 +73,8 @@ public class Altos { static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); static final Font status_font = new Font("SansSerif", Font.BOLD, 24); + static final int text_width = 16; + static void initialize_map() { string_to_state.put("startup", ao_flight_startup); diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java index 2ceaa183..64bdcf30 100644 --- a/ao-tools/altosui/AltosAscent.java +++ b/ao-tools/altosui/AltosAscent.java @@ -65,7 +65,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -102,7 +102,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -151,7 +151,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -161,7 +161,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { layout.setConstraints(value, c); add(value); - max_value = new JTextField(17); + max_value = new JTextField(Altos.text_width); max_value.setFont(Altos.value_font); max_value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 3; c.gridy = y; diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java index abe64fdc..16ccd458 100644 --- a/ao-tools/altosui/AltosDescent.java +++ b/ao-tools/altosui/AltosDescent.java @@ -66,7 +66,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 4; c.gridy = y; @@ -112,7 +112,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { c.weightx = 0; add(label, c); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; @@ -159,7 +159,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value1 = new JTextField(17); + value1 = new JTextField(Altos.text_width); value1.setFont(Altos.value_font); value1.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 2; c.gridy = y; @@ -169,7 +169,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { layout.setConstraints(value1, c); add(value1); - value2 = new JTextField(17); + value2 = new JTextField(Altos.text_width); value2.setFont(Altos.value_font); value2.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = x + 4; c.gridy = y; diff --git a/ao-tools/altosui/AltosFlightInfoTableModel.java b/ao-tools/altosui/AltosFlightInfoTableModel.java index 3355ff52..e23eff68 100644 --- a/ao-tools/altosui/AltosFlightInfoTableModel.java +++ b/ao-tools/altosui/AltosFlightInfoTableModel.java @@ -29,53 +29,56 @@ import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; public class AltosFlightInfoTableModel extends AbstractTableModel { - private String[] columnNames = {"Field", "Value"}; + final static private String[] columnNames = {"Field", "Value"}; - class InfoLine { - String name; - String value; + int rows; + int cols; + private String[][] data; - public InfoLine(String n, String v) { - name = n; - value = v; - } - } - - private ArrayList rows = new ArrayList(); - - public int getColumnCount() { return columnNames.length; } - public String getColumnName(int col) { return columnNames[col]; } - - public int getRowCount() { return 17; } - - int current_row = 0; - int prev_num_rows = 0; + public int getColumnCount() { return cols; } + public int getRowCount() { return rows; } + public String getColumnName(int col) { return columnNames[col & 1]; } public Object getValueAt(int row, int col) { - if (row >= rows.size()) + if (row >= rows || col >= cols) return ""; - if (col == 0) - return rows.get(row).name; - else - return rows.get(row).value; + return data[row][col]; } - public void resetRow() { - current_row = 0; + int[] current_row; + + public void reset() { + for (int i = 0; i < cols / 2; i++) + current_row[i] = 0; } - public void addRow(String name, String value) { - if (current_row >= rows.size()) - rows.add(current_row, new InfoLine(name, value)); - else - rows.set(current_row, new InfoLine(name, value)); - current_row++; + + public void clear() { + reset(); + for (int c = 0; c < cols; c++) + for (int r = 0; r < rows; r++) + data[r][c] = ""; + fireTableDataChanged(); + } + + public void addRow(int col, String name, String value) { + if (current_row[col] < rows) { + data[current_row[col]][col * 2] = name; + data[current_row[col]][col * 2 + 1] = value; + } + current_row[col]++; } + public void finish() { - if (current_row > prev_num_rows) - fireTableRowsInserted(prev_num_rows, current_row - 1); - while (rows.size() > current_row) - rows.remove(rows.size() - 1); - prev_num_rows = current_row; + for (int c = 0; c < cols / 2; c++) + while (current_row[c] < rows) + addRow(c, "", ""); fireTableDataChanged(); } + + public AltosFlightInfoTableModel (int in_rows, int in_cols) { + rows = in_rows; + cols = in_cols * 2; + data = new String[rows][cols]; + current_row = new int[in_cols]; + } } diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index ac88aa15..d5bcdb10 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -44,7 +44,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosLanded landed; private AltosFlightStatus flightStatus; - private JScrollPane flightInfoPane; private AltosInfoTable flightInfo; static final int tab_pad = 1; @@ -66,14 +65,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { return tab_landed; } - public int width() { - return flightInfo.width(); - } - - public int height() { - return flightStatus.height() + flightInfo.height(); - } - void stop_display() { if (thread != null && thread.isAlive()) { thread.interrupt(); @@ -146,6 +137,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { setTitle(String.format("AltOS %s", reader.name)); + /* Stick channel selector at top of table for telemetry monitoring */ if (serial >= 0) { // Channel menu channels = new AltosChannelMenu(AltosPreferences.channel(serial)); @@ -162,6 +154,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { bag.add (channels, c); } + /* Flight status is always visible */ flightStatus = new AltosFlightStatus(); c.gridx = 0; c.gridy = 1; @@ -169,6 +162,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { c.weightx = 1; bag.add(flightStatus, c); + /* The rest of the window uses a tabbed pane to + * show one of the alternate data views + */ pane = new JTabbedPane(); pad = new AltosPad(); @@ -184,9 +180,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Landed", landed); flightInfo = new AltosInfoTable(); - flightInfoPane = new JScrollPane(flightInfo.box()); - pane.add("Table", flightInfoPane); + pane.add("Table", new JScrollPane(flightInfo)); + /* Make the tabbed pane use the rest of the window space */ c.gridx = 0; c.gridy = 2; c.fill = GridBagConstraints.BOTH; @@ -194,9 +190,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { c.weighty = 1; bag.add(pane, c); - this.setSize(this.getPreferredSize()); - this.validate(); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { @Override @@ -209,7 +202,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } }); - this.setVisible(true); + pack(); + setVisible(true); thread = new AltosDisplayThread(this, voice, this, reader); diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java index 28924410..c571d5c9 100644 --- a/ao-tools/altosui/AltosInfoTable.java +++ b/ao-tools/altosui/AltosInfoTable.java @@ -28,11 +28,8 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosInfoTable { - private Box box; - private JTable table[]; - private AltosFlightInfoTableModel model[]; - private Box ibox[]; +public class AltosInfoTable extends JTable { + private AltosFlightInfoTableModel model; private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 12); private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 12); @@ -40,58 +37,35 @@ public class AltosInfoTable { static final int info_columns = 3; static final int info_rows = 17; - public AltosInfoTable() { - box = Box.createHorizontalBox(); - model = new AltosFlightInfoTableModel[info_columns]; - table = new JTable[info_columns]; - ibox = new Box[info_columns]; - for (int i = 0; i < info_columns; i++) { - model[i] = new AltosFlightInfoTableModel(); - table[i] = new JTable(model[i]); - ibox[i] = box.createVerticalBox(); - - table[i].setFont(infoValueFont); - table[i].setRowHeight(rowHeight()); - table[i].setShowGrid(true); - ibox[i].add(table[i].getTableHeader()); - ibox[i].add(table[i]); - box.add(ibox[i]); - } - } - - public int rowHeight() { - FontMetrics infoValueMetrics = table[0].getFontMetrics(infoValueFont); - return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 20 / 10; - } - - public int columnWidth() { - FontMetrics infoValueMetrics = table[0].getFontMetrics(infoValueFont); - return infoValueMetrics.charWidth('0') * 20 * 2; + int desired_row_height() { + FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); + return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; } - public int height() { - return rowHeight() * info_rows; - } - - public int width() { - return columnWidth() * info_columns; + public AltosInfoTable() { + super(new AltosFlightInfoTableModel(info_rows, info_columns)); + model = (AltosFlightInfoTableModel) getModel(); + setFont(infoValueFont); + setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); + setShowGrid(true); + setRowHeight(desired_row_height()); + doLayout(); } - public Box box() { - return box; + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); } void info_reset() { - for (int i = 0; i < info_columns; i++) - model[i].resetRow(); + model.reset(); } void info_add_row(int col, String name, String value) { - model[col].addRow(name, value); + model.addRow(col, name, value); } void info_add_row(int col, String name, String format, Object... parameters) { - model[col].addRow(name, String.format(format, parameters)); + info_add_row (col, name, String.format(format, parameters)); } void info_add_deg(int col, String name, double v, int pos, int neg) { @@ -103,17 +77,15 @@ public class AltosInfoTable { double deg = Math.floor(v); double min = (v - deg) * 60; - model[col].addRow(name, String.format("%3.0f°%08.5f'", deg, min)); + info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min)); } void info_finish() { - for (int i = 0; i < info_columns; i++) - model[i].finish(); + model.finish(); } public void clear() { - info_reset(); - info_finish(); + model.clear(); } public void show(AltosState state, int crc_errors) { diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java index 059dbb6d..d34efe6d 100644 --- a/ao-tools/altosui/AltosLanded.java +++ b/ao-tools/altosui/AltosLanded.java @@ -61,7 +61,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java index 480e4d79..66954347 100644 --- a/ao-tools/altosui/AltosPad.java +++ b/ao-tools/altosui/AltosPad.java @@ -65,7 +65,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; @@ -101,7 +101,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { layout.setConstraints(label, c); add(label); - value = new JTextField(17); + value = new JTextField(Altos.text_width); value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 2; c.gridy = y; -- cgit v1.2.3 From e5b1adae9b23b98a6321986f5cd67c9d3166b87f Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 10:34:39 +1000 Subject: AltosSiteMap: better gps check, lower zoom --- ao-tools/altosui/AltosSiteMap.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 5f5e30f0..72a65b15 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -34,7 +34,7 @@ import java.awt.geom.Line2D; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // max vertical step in a tile in naut. miles - static final double tile_size_nmi = 1.0; + static final double tile_size_nmi = 2.0; static final int px_size = 512; @@ -211,10 +211,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { boolean initialised = false; public void show(AltosState state, int crc_errors) { // if insufficient gps data, nothing to update - if (!state.gps_ready) { + if (!state.gps.locked) { if (state.pad_lat == 0 && state.pad_lon == 0) return; - if (state.ngps < 3) + if (state.gps.nsat < 4) return; } -- cgit v1.2.3 From 440a0f3f5130eb0c8e614691892be8c94e7fd3c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 16:55:12 -0800 Subject: altosui: Set site map flight path lines to 6 pixels anti-aliased. Much more visible over the map. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSiteMapTile.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index 9d6f855d..fd4cf0bb 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -125,6 +125,9 @@ public class AltosSiteMapTile extends JLayeredPane { draw = new JLabel(); g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); draw.setBounds(0, 0, px_size, px_size); draw.setOpaque(false); -- cgit v1.2.3 From 878913551a1e4e3c8f2b39fa4aeb234880735a1c Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 10:55:22 +1000 Subject: AltosSiteMap: explain tile size better --- ao-tools/altosui/AltosSiteMap.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 72a65b15..e222e2c8 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -33,8 +33,10 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { - // max vertical step in a tile in naut. miles - static final double tile_size_nmi = 2.0; + // preferred vertical step in a tile in naut. miles + // will actually choose a step size between x and 2x, where this + // is 1.5x + static final double tile_size_nmi = 1.5; static final int px_size = 512; @@ -117,7 +119,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { scale_x = 256/360.0 * Math.pow(2, zoom); scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); locn = pt(lat, lng); - north_step = pt(lat+tile_size_nmi/60.0, lng); + north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); if (locn.y - north_step.y > px_size) break; } while (zoom < 22); -- cgit v1.2.3 From c3994dd82d489289ebc99ff9c5fa88f560c023ac Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 13:07:11 +1000 Subject: AltosSiteMap: extend map if rocket goes far away --- ao-tools/altosui/AltosSiteMap.java | 130 +++++++++++++++++++++++---------- ao-tools/altosui/AltosSiteMapTile.java | 22 ++---- 2 files changed, 98 insertions(+), 54 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 2c542061..25450e7e 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -36,7 +36,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // preferred vertical step in a tile in naut. miles // will actually choose a step size between x and 2x, where this // is 1.5x - static final double tile_size_nmi = 1.5; + static final double tile_size_nmi = 0.75; static final int px_size = 512; @@ -106,8 +106,23 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { return latlng(pt, scale_x, scale_y); } - AltosSiteMapTile [] mapTiles = new AltosSiteMapTile[9]; - Point2D.Double [] tileOffset = new Point2D.Double[9]; + Vector mapTiles = new Vector(); + Point2D.Double centre; + + private Point tileOffset(AltosSiteMapTile tile) { + GridBagConstraints c = layout.getConstraints(tile); + return new Point(c.gridx - 100, c.gridy - 100); + } + private Point2D.Double tileCoordOffset(AltosSiteMapTile tile) { + Point p = tileOffset(tile); + return new Point2D.Double(centre.x - p.x*px_size, + centre.y - p.y * px_size); + } + + private Point tileOffset(Point2D.Double p) { + return new Point((int)Math.floor((centre.x+p.x)/px_size), + (int)Math.floor((centre.y+p.y)/px_size)); + } private Point2D.Double getBaseLocation(double lat, double lng) { Point2D.Double locn, north_step; @@ -132,15 +147,16 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // nothing } - private void bgLoadMap(final int i, + private void bgLoadMap(final AltosSiteMapTile tile, final File pngfile, final String pngurl) { + //System.out.printf("Loading/fetching map %s\n", pngfile); Thread thread = new Thread() { public void run() { ImageIcon res; res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); if (res != null) { - mapTiles[i].loadMap(res); + tile.loadMap(res); } else { System.out.printf("# Failed to fetch file %s\n", pngfile); System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); @@ -154,15 +170,16 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { AltosPreferences.init(null); AltosSiteMap asm = new AltosSiteMap(true); - Point2D.Double c = asm.getBaseLocation(lat, lng); + asm.centre = asm.getBaseLocation(lat, lng); + Point2D.Double p = new Point2D.Double(); Point2D.Double p2; int dx = -w/2, dy = -h/2; for (int y = dy; y < h+dy; y++) { for (int x = dx; x < w+dx; x++) { LatLng map_latlng = asm.latlng( - -c.x + x*px_size + px_size/2, - -c.y + y*px_size + px_size/2); + -asm.centre.x + x*px_size + px_size/2, + -asm.centre.y + y*px_size + px_size/2); File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); if (pngfile.exists()) { @@ -177,22 +194,21 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } - private void initMaps(double lat, double lng) { - Point2D.Double c = getBaseLocation(lat, lng); - Point2D.Double p = new Point2D.Double(); + private void initMap(AltosSiteMapTile tile) { + Point2D.Double offset = tileCoordOffset(tile); - for (int i = 0; i < 9; i++) { - int x = i%3 - 1, y = i/3 - 1; + LatLng map_latlng = latlng(px_size/2-offset.x, px_size/2-offset.y); - tileOffset[i] = new Point2D.Double( - c.x - x*px_size, p.y = c.y - y*px_size); - LatLng map_latlng = latlng( - -tileOffset[i].x+px_size/2, - -tileOffset[i].y+px_size/2); + File pngfile = MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng); + bgLoadMap(tile, pngfile, pngurl); + } + + private void initMaps(double lat, double lng) { + centre = getBaseLocation(lat, lng); - File pngfile = MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng); - bgLoadMap(i, pngfile, pngurl); + for (AltosSiteMapTile tile : mapTiles) { + initMap(tile); } } @@ -211,6 +227,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } boolean initialised = false; + Point2D.Double last_pt = null; + int last_state = -1; public void show(AltosState state, int crc_errors) { // if insufficient gps data, nothing to update if (state.gps == null) @@ -228,10 +246,51 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } Point2D.Double pt = pt(state.gps.lat, state.gps.lon); - for (int x = 0; x < mapTiles.length; x++) { - mapTiles[x].show(state, crc_errors, - translatePoint(pt, tileOffset[x])); + if (last_pt == pt && last_state == state.state) + return; + + if (last_pt == null) { + last_pt = pt; + } + boolean in_any = false; + for (AltosSiteMapTile tile : mapTiles) { + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(tile)); + lref = translatePoint(last_pt, tileCoordOffset(tile)); + tile.show(state, crc_errors, lref, ref); + if (0 <= ref.x && ref.x < px_size) + if (0 <= ref.y && ref.y < px_size) + in_any = true; } + if (!in_any) { + AltosSiteMapTile tile = addTileAt(tileOffset(pt)); + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(tile)); + lref = translatePoint(last_pt, tileCoordOffset(tile)); + initMap(tile); + setViewportView(comp); + tile.show(state, crc_errors, lref, ref); + } + last_pt = pt; + last_state = state.state; + } + + private AltosSiteMapTile addTileAt(Point offset) { + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + + // put some space between the map tiles, debugging only + // c.insets = new Insets(5, 5, 5, 5); + // + AltosSiteMapTile t = new AltosSiteMapTile(px_size); + mapTiles.add(t); + c.gridx = offset.x + 100; + c.gridy = offset.y + 100; + layout.setConstraints(t, c); + comp.add(t); + + return t; } private AltosSiteMap(boolean knowWhatYouAreDoing) { @@ -240,8 +299,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } + JComponent comp; + private GridBagLayout layout; + public AltosSiteMap() { - JComponent comp = new JComponent() { + comp = new JComponent() { GrabNDrag scroller = new GrabNDrag(this); { addMouseMotionListener(scroller); @@ -250,21 +312,13 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } }; - GridBagLayout layout = new GridBagLayout(); + layout = new GridBagLayout(); comp.setLayout(layout); - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - - // put some space between the map tiles, debugging only - // c.insets = new Insets(5, 5, 5, 5); - for (int x = 0; x < 9; x++) { - c.gridx = x % 3; - c.gridy = x / 3; - mapTiles[x] = new AltosSiteMapTile(px_size); - layout.setConstraints(mapTiles[x], c); - comp.add(mapTiles[x]); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + addTileAt(new Point(x, y)); + } } setViewportView(comp); setPreferredSize(new Dimension(500,200)); diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index fd4cf0bb..ea8c8bd9 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -32,9 +32,6 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; public class AltosSiteMapTile extends JLayeredPane { - Point2D.Double coord_pt; - Point2D.Double last_pt; - JLabel mapLabel; JLabel draw; Graphics2D g2d; @@ -57,19 +54,13 @@ public class AltosSiteMapTile extends JLayeredPane { boolean drawn_landed_circle = false; boolean drawn_boost_circle = false; - public void show(AltosState state, int crc_errors, Point2D.Double pt) { - if (last_pt == null) { - // setLocation(state.pad_lat, state.pad_lon); - // loadMap(); - last_pt = pt; - } - - if (pt != last_pt) { - if (0 <= state.state && state.state < stateColors.length) { - g2d.setColor(stateColors[state.state]); - } - g2d.draw(new Line2D.Double(last_pt, pt)); + public void show(AltosState state, int crc_errors, + Point2D.Double last_pt, Point2D.Double pt) + { + if (0 <= state.state && state.state < stateColors.length) { + g2d.setColor(stateColors[state.state]); } + g2d.draw(new Line2D.Double(last_pt, pt)); int px_size = getWidth(); if (0 <= pt.x && pt.x < px_size) { @@ -100,7 +91,6 @@ public class AltosSiteMapTile extends JLayeredPane { g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); } - last_pt = pt; repaint(); } -- cgit v1.2.3 From c040bcd06679484175542208fb564d0271a7fc1b Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 13:19:36 +1000 Subject: AltosSiteMap: try to get new tile construction right --- ao-tools/altosui/AltosSiteMap.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 25450e7e..dd99ad48 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -264,12 +264,14 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } if (!in_any) { AltosSiteMapTile tile = addTileAt(tileOffset(pt)); + setViewportView(comp); + Point2D.Double ref, lref; ref = translatePoint(pt, tileCoordOffset(tile)); lref = translatePoint(last_pt, tileCoordOffset(tile)); - initMap(tile); - setViewportView(comp); tile.show(state, crc_errors, lref, ref); + + initMap(tile); } last_pt = pt; last_state = state.state; -- cgit v1.2.3 From 71e487344395a8efc9cd279aad92f601ff4c6d3d Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 14:05:00 +1000 Subject: AltosSiteMap: thread safe tile addition --- ao-tools/altosui/AltosSiteMap.java | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index dd99ad48..df5207bf 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -229,7 +229,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { boolean initialised = false; Point2D.Double last_pt = null; int last_state = -1; - public void show(AltosState state, int crc_errors) { + public void show(final AltosState state, final int crc_errors) { // if insufficient gps data, nothing to update if (state.gps == null) return; @@ -245,7 +245,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { initialised = true; } - Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + final Point2D.Double pt = pt(state.gps.lat, state.gps.lon); if (last_pt == pt && last_state == state.state) return; @@ -263,15 +263,23 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { in_any = true; } if (!in_any) { - AltosSiteMapTile tile = addTileAt(tileOffset(pt)); - setViewportView(comp); - - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(tile)); - lref = translatePoint(last_pt, tileCoordOffset(tile)); - tile.show(state, crc_errors, lref, ref); - - initMap(tile); + try { + SwingUtilities.invokeAndWait( new Runnable() { + public void run() { + AltosSiteMapTile tile = addTileAt(tileOffset(pt)); + setViewportView(comp); + + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(tile)); + lref = translatePoint(last_pt, tileCoordOffset(tile)); + tile.show(state, crc_errors, lref, ref); + + initMap(tile); + } + } ); + } catch (Exception e) { + // pray + } } last_pt = pt; last_state = state.state; -- cgit v1.2.3 From 84e570d8a8a52e0d358582135ec1b3a12be94c26 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 14:45:10 +1000 Subject: AltosSiteMap: refactor tile collection --- ao-tools/altosui/AltosSiteMap.java | 75 ++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 40 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index df5207bf..5e34dd49 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -106,15 +106,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { return latlng(pt, scale_x, scale_y); } - Vector mapTiles = new Vector(); + HashMap mapTiles = new HashMap(); Point2D.Double centre; - private Point tileOffset(AltosSiteMapTile tile) { - GridBagConstraints c = layout.getConstraints(tile); - return new Point(c.gridx - 100, c.gridy - 100); - } - private Point2D.Double tileCoordOffset(AltosSiteMapTile tile) { - Point p = tileOffset(tile); + private Point2D.Double tileCoordOffset(Point p) { return new Point2D.Double(centre.x - p.x*px_size, centre.y - p.y * px_size); } @@ -194,10 +189,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } - private void initMap(AltosSiteMapTile tile) { - Point2D.Double offset = tileCoordOffset(tile); + private void initMap(AltosSiteMapTile tile, Point offset) { + Point2D.Double coord = tileCoordOffset(offset); - LatLng map_latlng = latlng(px_size/2-offset.x, px_size/2-offset.y); + LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); File pngfile = MapFile(map_latlng.lat, map_latlng.lng); String pngurl = MapURL(map_latlng.lat, map_latlng.lng); @@ -207,8 +202,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { private void initMaps(double lat, double lng) { centre = getBaseLocation(lat, lng); - for (AltosSiteMapTile tile : mapTiles) { - initMap(tile); + for (Point k : mapTiles.keySet()) { + initMap(mapTiles.get(k), k); } } @@ -253,39 +248,40 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { last_pt = pt; } boolean in_any = false; - for (AltosSiteMapTile tile : mapTiles) { + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(tile)); - lref = translatePoint(last_pt, tileCoordOffset(tile)); + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); tile.show(state, crc_errors, lref, ref); if (0 <= ref.x && ref.x < px_size) if (0 <= ref.y && ref.y < px_size) in_any = true; } if (!in_any) { - try { - SwingUtilities.invokeAndWait( new Runnable() { - public void run() { - AltosSiteMapTile tile = addTileAt(tileOffset(pt)); - setViewportView(comp); - - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(tile)); - lref = translatePoint(last_pt, tileCoordOffset(tile)); - tile.show(state, crc_errors, lref, ref); - - initMap(tile); - } - } ); - } catch (Exception e) { - // pray - } + final AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + final Point offset = tileOffset(pt); + mapTiles.put(offset, tile); + + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); + tile.show(state, crc_errors, lref, ref); + + initMap(tile, offset); + + SwingUtilities.invokeLater( new Runnable() { + public void run() { + addTileAt(tile, offset); + setViewportView(comp); + } + } ); } last_pt = pt; last_state = state.state; } - private AltosSiteMapTile addTileAt(Point offset) { + private void addTileAt(AltosSiteMapTile tile, Point offset) { GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; @@ -293,14 +289,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // put some space between the map tiles, debugging only // c.insets = new Insets(5, 5, 5, 5); // - AltosSiteMapTile t = new AltosSiteMapTile(px_size); - mapTiles.add(t); c.gridx = offset.x + 100; c.gridy = offset.y + 100; - layout.setConstraints(t, c); - comp.add(t); - - return t; + layout.setConstraints(tile, c); + comp.add(tile); } private AltosSiteMap(boolean knowWhatYouAreDoing) { @@ -327,7 +319,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { - addTileAt(new Point(x, y)); + AltosSiteMapTile t = new AltosSiteMapTile(px_size); + Point offset = new Point(x, y); + mapTiles.put(offset, t); + addTileAt(t, offset); } } setViewportView(comp); -- cgit v1.2.3 From a08b2a6363c194195db92029743f6612676373ce Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 15:03:21 +1000 Subject: AltosSiteMap: never accept 0,0 as lat/long --- ao-tools/altosui/AltosSiteMap.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 5e34dd49..0375128e 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -228,9 +228,9 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // if insufficient gps data, nothing to update if (state.gps == null) return; + if (state.pad_lat == 0 && state.pad_lon == 0) + return; if (!state.gps.locked) { - if (state.pad_lat == 0 && state.pad_lon == 0) - return; if (state.gps.nsat < 4) return; } -- cgit v1.2.3 From 0393830f85da5efc96bbdf0d9769b66019c34b33 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 15:13:35 +1000 Subject: AltosSiteMap: limit nr of tiles to 200x200 --- ao-tools/altosui/AltosSiteMap.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 0375128e..b2d79043 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -40,6 +40,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { static final int px_size = 512; + static final int MAX_TILE_DELTA = 100; + private static Point2D.Double translatePoint(Point2D.Double p, Point2D.Double d) { @@ -282,15 +284,22 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } private void addTileAt(AltosSiteMapTile tile, Point offset) { + if (Math.abs(offset.x) >= MAX_TILE_DELTA || + Math.abs(offset.y) >= MAX_TILE_DELTA) + { + System.out.printf("Rocket too far away from pad (tile %d,%d)\n", + offset.x, offset.y); + return; + } + GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; - // put some space between the map tiles, debugging only // c.insets = new Insets(5, 5, 5, 5); - // - c.gridx = offset.x + 100; - c.gridy = offset.y + 100; + + c.gridx = offset.x + MAX_TILE_DELTA; + c.gridy = offset.y + MAX_TILE_DELTA; layout.setConstraints(tile, c); comp.add(tile); } -- cgit v1.2.3 From e7954c820763f80e993f9f822e837725cf36af84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Nov 2010 22:03:26 -0800 Subject: altosui: When fixing eeprom gps time information, make GPS data valid Eeprom files may be missing the GPS time (due to a firmware bug). Working around this involves finding the next valid GPS time and using that to create a fake GPS time entry. However, that next GPS time may not be locked or may have few sats as it is from the boost stage of the flight. Fix this by simply forcing the fake time packet to have 4 sats and be locked. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosEepromIterable.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java index fc683321..f8e6d7e5 100644 --- a/ao-tools/altosui/AltosEepromIterable.java +++ b/ao-tools/altosui/AltosEepromIterable.java @@ -309,6 +309,12 @@ public class AltosEepromIterable extends AltosRecordIterable { int flags = (good.b >> 8); int seconds = hour * 3600 + minute * 60 + second; + /* Make sure this looks like a good GPS value */ + if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); + flags |= Altos.AO_GPS_RUNNING; + flags |= Altos.AO_GPS_VALID; + int new_seconds = seconds + diff; if (new_seconds < 0) new_seconds += 24 * 3600; -- cgit v1.2.3 From 4a9ded5b39ed08e13abc2cddba8b712f62b983f2 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 21 Nov 2010 17:39:50 +1000 Subject: AltosSiteMap: ensure buffer around active tile --- ao-tools/altosui/AltosSiteMap.java | 53 ++++++++++++++++++++++++++-------- ao-tools/altosui/AltosSiteMapTile.java | 17 +++++++---- 2 files changed, 53 insertions(+), 17 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index b2d79043..802eb68c 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -260,29 +260,57 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { if (0 <= ref.y && ref.y < px_size) in_any = true; } - if (!in_any) { - final AltosSiteMapTile tile = new AltosSiteMapTile(px_size); - final Point offset = tileOffset(pt); - mapTiles.put(offset, tile); + Point offset = tileOffset(pt); + if (!in_any) { Point2D.Double ref, lref; ref = translatePoint(pt, tileCoordOffset(offset)); lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(state, crc_errors, lref, ref); + AltosSiteMapTile tile = createTile(offset); + tile.show(state, crc_errors, lref, ref); initMap(tile, offset); + finishTileLater(tile, offset); + } - SwingUtilities.invokeLater( new Runnable() { - public void run() { - addTileAt(tile, offset); - setViewportView(comp); - } - } ); + if (offset != tileOffset(last_pt)) { + ensureTilesAround(offset); } + last_pt = pt; last_state = state.state; } + private AltosSiteMapTile createTile(final Point offset) { + final AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + mapTiles.put(offset, tile); + return tile; + } + private void finishTileLater(final AltosSiteMapTile tile, + final Point offset) + { + SwingUtilities.invokeLater( new Runnable() { + public void run() { + addTileAt(tile, offset); + tile.setScrollable(); + } + } ); + } + + private void ensureTilesAround(Point base_offset) { + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + Point offset = new Point(base_offset.x + x, base_offset.y + y); + if (mapTiles.containsKey(offset)) + continue; + AltosSiteMapTile tile = createTile(offset); + initMap(tile, offset); + finishTileLater(tile, offset); + } + } + } + + private void addTileAt(AltosSiteMapTile tile, Point offset) { if (Math.abs(offset.x) >= MAX_TILE_DELTA || Math.abs(offset.y) >= MAX_TILE_DELTA) @@ -328,10 +356,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { - AltosSiteMapTile t = new AltosSiteMapTile(px_size); Point offset = new Point(x, y); + AltosSiteMapTile t = new AltosSiteMapTile(px_size); mapTiles.put(offset, t); addTileAt(t, offset); + t.setScrollable(); } } setViewportView(comp); diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index ea8c8bd9..e0942986 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -52,10 +52,17 @@ public class AltosSiteMapTile extends JLayeredPane { Color.BLACK // landed }; - boolean drawn_landed_circle = false; - boolean drawn_boost_circle = false; - public void show(AltosState state, int crc_errors, - Point2D.Double last_pt, Point2D.Double pt) + private boolean drawn_landed_circle = false; + private boolean drawn_boost_circle = false; + private boolean scrollable = false; + public synchronized void setScrollable() { + scrollable = true; + } + public synchronized boolean isScrollable() { + return scrollable; + } + public synchronized void show(AltosState state, int crc_errors, + Point2D.Double last_pt, Point2D.Double pt) { if (0 <= state.state && state.state < stateColors.length) { g2d.setColor(stateColors[state.state]); @@ -63,7 +70,7 @@ public class AltosSiteMapTile extends JLayeredPane { g2d.draw(new Line2D.Double(last_pt, pt)); int px_size = getWidth(); - if (0 <= pt.x && pt.x < px_size) { + if (isScrollable() && 0 <= pt.x && pt.x < px_size) { if (0 <= pt.y && pt.y < px_size) { int dx = 500, dy = 250; if (state.state > 2) { -- cgit v1.2.3 From b85df38b5611e45cb9296df07b720badf74ac26e Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Mon, 22 Nov 2010 05:22:17 +1000 Subject: altosui: improve sitemap scrolling behaviour --- ao-tools/altosui/AltosSiteMap.java | 53 +++++++++++++++++++++++----------- ao-tools/altosui/AltosSiteMapTile.java | 21 -------------- ao-tools/altosui/GrabNDrag.java | 35 ++++++++++++---------- 3 files changed, 55 insertions(+), 54 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 802eb68c..2477e4f8 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -273,6 +273,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { finishTileLater(tile, offset); } + scrollRocketToVisible(pt); + if (offset != tileOffset(last_pt)) { ensureTilesAround(offset); } @@ -281,8 +283,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { last_state = state.state; } - private AltosSiteMapTile createTile(final Point offset) { - final AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + private AltosSiteMapTile createTile(Point offset) { + AltosSiteMapTile tile = new AltosSiteMapTile(px_size); mapTiles.put(offset, tile); return tile; } @@ -292,7 +294,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { SwingUtilities.invokeLater( new Runnable() { public void run() { addTileAt(tile, offset); - tile.setScrollable(); } } ); } @@ -310,6 +311,18 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } + private Point topleft = new Point(0,0); + private void scrollRocketToVisible(Point2D.Double pt) { + Rectangle r = comp.getVisibleRect(); + Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); + int dx = (int)copt.x - r.width/2 - r.x; + int dy = (int)copt.y - r.height/2 - r.y; + if (Math.abs(dx) > r.width/3 || Math.abs(dy) > r.height/3) { + r.x += dx; + r.y += dy; + comp.scrollRectToVisible(r); + } + } private void addTileAt(AltosSiteMapTile tile, Point offset) { if (Math.abs(offset.x) >= MAX_TILE_DELTA || @@ -320,6 +333,18 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { return; } + boolean review = false; + Rectangle r = comp.getVisibleRect(); + if (offset.x < topleft.x) { + r.x += (topleft.x - offset.x) * px_size; + topleft.x = offset.x; + review = true; + } + if (offset.y < topleft.y) { + r.y += (topleft.y - offset.y) * px_size; + topleft.y = offset.y; + review = true; + } GridBagConstraints c = new GridBagConstraints(); c.anchor = GridBagConstraints.CENTER; c.fill = GridBagConstraints.BOTH; @@ -329,7 +354,11 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { c.gridx = offset.x + MAX_TILE_DELTA; c.gridy = offset.y + MAX_TILE_DELTA; layout.setConstraints(tile, c); + comp.add(tile); + if (review) { + comp.scrollRectToVisible(r); + } } private AltosSiteMap(boolean knowWhatYouAreDoing) { @@ -338,29 +367,19 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } - JComponent comp; - private GridBagLayout layout; + JComponent comp = new JComponent() { }; + private GridBagLayout layout = new GridBagLayout(); public AltosSiteMap() { - comp = new JComponent() { - GrabNDrag scroller = new GrabNDrag(this); - { - addMouseMotionListener(scroller); - addMouseListener(scroller); - setAutoscrolls(true); - } - }; + GrabNDrag scroller = new GrabNDrag(comp); - layout = new GridBagLayout(); comp.setLayout(layout); for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { Point offset = new Point(x, y); - AltosSiteMapTile t = new AltosSiteMapTile(px_size); - mapTiles.put(offset, t); + AltosSiteMapTile t = createTile(offset); addTileAt(t, offset); - t.setScrollable(); } } setViewportView(comp); diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java index e0942986..8301f42b 100644 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ b/ao-tools/altosui/AltosSiteMapTile.java @@ -54,13 +54,6 @@ public class AltosSiteMapTile extends JLayeredPane { private boolean drawn_landed_circle = false; private boolean drawn_boost_circle = false; - private boolean scrollable = false; - public synchronized void setScrollable() { - scrollable = true; - } - public synchronized boolean isScrollable() { - return scrollable; - } public synchronized void show(AltosState state, int crc_errors, Point2D.Double last_pt, Point2D.Double pt) { @@ -69,20 +62,6 @@ public class AltosSiteMapTile extends JLayeredPane { } g2d.draw(new Line2D.Double(last_pt, pt)); - int px_size = getWidth(); - if (isScrollable() && 0 <= pt.x && pt.x < px_size) { - if (0 <= pt.y && pt.y < px_size) { - int dx = 500, dy = 250; - if (state.state > 2) { - dx = Math.min(200, 20 + (int) Math.abs(last_pt.x - pt.x)); - dy = Math.min(100, 10 + (int) Math.abs(last_pt.y - pt.y)); - } - Rectangle r = new Rectangle((int)pt.x-dx, (int)pt.y-dy, - dx*2, dy*2); - scrollRectToVisible(r); - } - } - if (state.state == 3 && !drawn_boost_circle) { drawn_boost_circle = true; g2d.setColor(Color.RED); diff --git a/ao-tools/altosui/GrabNDrag.java b/ao-tools/altosui/GrabNDrag.java index b44f3fe2..e6b87b58 100644 --- a/ao-tools/altosui/GrabNDrag.java +++ b/ao-tools/altosui/GrabNDrag.java @@ -29,23 +29,26 @@ import java.util.*; import java.text.*; class GrabNDrag extends MouseInputAdapter { - private JComponent scroll; - private Point startPt = new Point(); + private JComponent scroll; + private Point startPt = new Point(); - public GrabNDrag(JComponent parent) { - scroll = parent; - } + public GrabNDrag(JComponent scroll) { + this.scroll = scroll; + scroll.addMouseMotionListener(this); + scroll.addMouseListener(this); + scroll.setAutoscrolls(true); + } - public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); - } - public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; + public void mousePressed(MouseEvent e) { + startPt.setLocation(e.getPoint()); + } + public void mouseDragged(MouseEvent e) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); - } + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } } -- cgit v1.2.3 From 902735ffbfdd97672d52b09f17cdcd619193fd05 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Mon, 22 Nov 2010 05:29:26 +1000 Subject: altosui: keep sitemap more centred on rocket --- ao-tools/altosui/AltosSiteMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 2477e4f8..80970605 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -317,7 +317,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); int dx = (int)copt.x - r.width/2 - r.x; int dy = (int)copt.y - r.height/2 - r.y; - if (Math.abs(dx) > r.width/3 || Math.abs(dy) > r.height/3) { + if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { r.x += dx; r.y += dy; comp.scrollRectToVisible(r); -- cgit v1.2.3 From 377ee7e90ecd028f984cd1abce96b2efc3b5b977 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Nov 2010 14:03:17 -0800 Subject: altos: Add on/off modes to 'C' command This lets the user turn the radio on/off and then invoke other commands. Signed-off-by: Keith Packard --- src/ao_radio.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index f4a9d3b2..3fb4afd7 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -448,19 +448,32 @@ ao_radio_rdf_abort(void) void ao_radio_test(void) { - ao_set_monitor(0); - ao_packet_slave_stop(); - ao_radio_get(); - printf ("Hit a character to stop..."); flush(); - RFST = RFST_STX; - getchar(); - ao_radio_idle(); - ao_radio_put(); - putchar('\n'); + uint8_t mode = 2; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if (mode & 2) { + ao_set_monitor(0); + ao_packet_slave_stop(); + ao_radio_get(); + RFST = RFST_STX; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if (mode & 1) { + ao_radio_idle(); + ao_radio_put(); + } } __code struct ao_cmds ao_radio_cmds[] = { - { 'C', ao_radio_test, "C Radio carrier test" }, + { 'C', ao_radio_test, "C <1 start, 0 stop, none both> Radio carrier test" }, { 0, ao_radio_test, NULL }, }; -- cgit v1.2.3 From a79606a6507fc01a74910f7959e84c4e9a730714 Mon Sep 17 00:00:00 2001 From: Bob Finch Date: Mon, 22 Nov 2010 12:24:42 -0700 Subject: Added PKGBUILDs for deps into contribs --- contrib/arch-linux/PKGBUILD-git.freetts | 38 +++++ contrib/arch-linux/PKGBUILD-git.jcommon | 28 ++++ contrib/arch-linux/PKGBUILD-git.jfreechart | 27 ++++ contrib/arch-linux/PKGBUILD-git.nsis.patched | 34 ++++ contrib/arch-linux/PKGBUILD-git.sdcc_patched | 34 ++++ contrib/arch-linux/new.patch | 35 ++++ contrib/arch-linux/nsis-2.43-64bit-fixes.patch | 211 +++++++++++++++++++++++++ 7 files changed, 407 insertions(+) create mode 100644 contrib/arch-linux/PKGBUILD-git.freetts create mode 100644 contrib/arch-linux/PKGBUILD-git.jcommon create mode 100644 contrib/arch-linux/PKGBUILD-git.jfreechart create mode 100644 contrib/arch-linux/PKGBUILD-git.nsis.patched create mode 100644 contrib/arch-linux/PKGBUILD-git.sdcc_patched create mode 100644 contrib/arch-linux/new.patch create mode 100644 contrib/arch-linux/nsis-2.43-64bit-fixes.patch diff --git a/contrib/arch-linux/PKGBUILD-git.freetts b/contrib/arch-linux/PKGBUILD-git.freetts new file mode 100644 index 00000000..b16a994d --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.freetts @@ -0,0 +1,38 @@ +# Original contributor: Bob Finch + +pkgname=freetts +_pkgname=FreeTTS +pkgver=1.2.2 +_pkgver=1.2 +pkgrel=1 +pkgdesc="Sun's rewrite of flite for java" +arch=('any') +license=('custom') +depends=('java-environment') +makedepends=('junit' 'apache-ant') +#source=(http://downloads.sourceforge.net/project/\ +#$pkgname/$_pkgname/$_pkgname%20$pkgver/$pkgname-$pkgver-src.zip) +source=(http://downloads.sourceforge.net/project/\ +$pkgname/$_pkgname/$_pkgname%20$pkgver/$pkgname-$pkgver-bin.zip) +url="http://freetts.sourceforge.net/" +#md5sums=('692b5ece251fed88539736e55af5f391') +md5sums=('cd751e5fd5c7ed29cf6879fc5200605d') + +build() { +# [ -z "${JAVA_HOME}" ] && . /etc/profile.d/jdk.sh +# [ -z "${ANT_HOME}" ] && . /etc/profile.d/apache-ant.sh + +# cd ${startdir}/src/$pkgname-$pkgver/lib + cd ${startdir}/src/$pkgname-$_pkgver/lib + rm README.txt jsapi.sh jsapi.exe + +# cd ${startdir}/src/$pkgname-$pkgver +# ln -s . src +# /usr/share/java/apache-ant/bin/ant + + cd $srcdir/$pkgname-$_pkgver + install -d $pkgdir/usr/share/java/$pkgname/lib + install -m644 lib/* $pkgdir/usr/share/java/$pkgname/lib/ + +# cp -a bld $pkgdir/usr/share/java/$pkgname/ +} diff --git a/contrib/arch-linux/PKGBUILD-git.jcommon b/contrib/arch-linux/PKGBUILD-git.jcommon new file mode 100644 index 00000000..8c435436 --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.jcommon @@ -0,0 +1,28 @@ +# Original contributor: Bob Finch + +pkgname=jcommon +_pkgname=JCommon +_project=jfreechart +pkgver=1.0.16 +pkgrel=1 +pkgdesc="Base routines for JFreeChart" +arch=('any') +license=('lgpl') +depends=('java-environment') +makedepends=('apache-ant' 'zip' 'gzip' 'tar') +source=(http://downloads.sourceforge.net/project/\ +$_project/3.%20$_pkgname/$pkgver/$pkgname-$pkgver.tar.gz) +url="http://www.jfree.org/jcommon/" +md5sums=('5fb774c225cdc7d15a99c9702031ae05') + +build() { + [ -z "${JAVA_HOME}" ] && . /etc/profile.d/jdk.sh + [ -z "${ANT_HOME}" ] && . /etc/profile.d/apache-ant.sh + + cd ${startdir}/src/$pkgname-$pkgver/ant + /usr/share/java/apache-ant/bin/ant + + cd ${startdir}/src/$pkgname-$pkgver + install -d $pkgdir/usr/share/java/$pkgname/lib + install -m644 $pkgname-$pkgver.jar $pkgdir/usr/share/java/$pkgname/lib/$pkgname.jar +} diff --git a/contrib/arch-linux/PKGBUILD-git.jfreechart b/contrib/arch-linux/PKGBUILD-git.jfreechart new file mode 100644 index 00000000..f7427983 --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.jfreechart @@ -0,0 +1,27 @@ +# Original contributor: Bob Finch + +pkgname=jfreechart +_pkgname=JFreeChart +pkgver=1.0.13 +pkgrel=1 +pkgdesc="Charting program for Java" +arch=('any') +license=('lgpl') +depends=('java-environment' 'jcommon') +makedepends=('apache-ant' 'zip' 'gzip' 'tar') +source=(http://downloads.sourceforge.net/project/\ +$pkgname/1.%20$_pkgname/$pkgver/$pkgname-$pkgver.tar.gz) +url="http://www.jfree.org/jfreechart/" +md5sums=('c90e2f8f612b9aaf3f24a4afce219076') + +build() { + [ -z "${JAVA_HOME}" ] && . /etc/profile.d/jdk.sh + [ -z "${ANT_HOME}" ] && . /etc/profile.d/apache-ant.sh + + cd ${startdir}/src/$pkgname-$pkgver/ant + /usr/share/java/apache-ant/bin/ant + + cd ${startdir}/src/$pkgname-$pkgver + install -d $pkgdir/usr/share/java/$pkgname/lib + install -m644 lib/$pkgname-$pkgver.jar $pkgdir/usr/share/java/$pkgname/lib/$pkgname.jar +} diff --git a/contrib/arch-linux/PKGBUILD-git.nsis.patched b/contrib/arch-linux/PKGBUILD-git.nsis.patched new file mode 100644 index 00000000..fe751cb9 --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.nsis.patched @@ -0,0 +1,34 @@ +# Contributor: Andre Klitzing +# Contributor: mosra +pkgname=nsis +pkgver=2.46 +pkgrel=3 +pkgdesc='A professional open source system to create Windows installers' +arch=('i686' 'x86_64') +url='http://nsis.sourceforge.net' +license='http://nsis.sourceforge.net/License' +depends=('mingw32-runtime') +makedepends=('scons' 'mingw32-gcc' 'mingw32-binutils' 'mingw32-w32api') +source=(http://downloads.sourceforge.net/project/nsis/NSIS%202/$pkgver/$pkgname-$pkgver-src.tar.bz2 + nsis-2.43-64bit-fixes.patch) +md5sums=('61c2e81739436b06d7cf7bcce1d533ac' + '9eead3b78da54e3afda8f6a5b663aea9') + +build() { + cd "$srcdir/$pkgname-$pkgver-src" + + # Patch taken from + # http://cvs.fedoraproject.org/viewvc/rpms/mingw32-nsis/F-11/nsis-2.43-64bit-fixes.patch + patch -p1 -i "$srcdir/nsis-2.43-64bit-fixes.patch" || return 1 + + # Patch version from DD-MM-YYY.cvs to 2.46 (makes CPack working again) + sed -i "s/'Version of NSIS', cvs_version)/'Version of NSIS', '${pkgver}')/" \ + "${srcdir}/${pkgname}-${pkgver}-src/SConstruct" + + scons PREFIX_DEST="$pkgdir/" PREFIX=/usr/i486-mingw32 SKIPUTILS='NSIS Menu' install || return 1 + + # Add a symlink to 'makensis' for lazy people ;-) + mkdir "$pkgdir/usr/bin/" + cd "$pkgdir/usr/bin/" + ln -s ../i486-mingw32/bin/makensis +} diff --git a/contrib/arch-linux/PKGBUILD-git.sdcc_patched b/contrib/arch-linux/PKGBUILD-git.sdcc_patched new file mode 100644 index 00000000..1a78c292 --- /dev/null +++ b/contrib/arch-linux/PKGBUILD-git.sdcc_patched @@ -0,0 +1,34 @@ +# $Id: PKGBUILD 23526 2010-08-12 12:59:41Z spupykin $ +# Maintainer: Sergej Pupykin +# Maintainer: Jose Negron +# Patched w/ keith packard's patch for altos - RJF 26-aug-10 + +pkgname=sdcc +pkgver=2.9.0 +pkgrel=2_patched +pkgdesc="Retargettable ANSI C compiler (Intel 8051, Maxim 80DS390, Zilog Z80 and the Motorola 68HC08)" +arch=('i686' 'x86_64') +license=('GPL') +depends=('bash' 'gcc-libs') +makedepends=('gputils' 'flex' 'bison' 'patch') +provides=('sdcc') +conflicts=('sdcc') +url="http://sdcc.sourceforge.net/" +options=(!strip) +#Patch file was taken from https://bugzilla.redhat.com/show_bug.cgi?id=488217 +source=(http://downloads.sourceforge.net/sourceforge/sdcc/$pkgname-src-$pkgver.tar.bz2 + http://aur.archlinux.org/packages/$pkgname/$pkgname/$pkgname-$pkgver.patch + new.patch) +md5sums=('a6151ed328fd3bc48305ffbc628dc122' + '35313a8edca4f2c8a03ad57036da4e62' + '65612bb094e719713bc477efd6000672') + +build() { + cd $srcdir/$pkgname + patch -p1 -i ../$pkgname-$pkgver.patch + patch -p0 -i ../new.patch + ./configure --prefix=$pkgdir/usr + make + make install + strip $pkgdir/usr/bin/* || true +} diff --git a/contrib/arch-linux/new.patch b/contrib/arch-linux/new.patch new file mode 100644 index 00000000..74e1df06 --- /dev/null +++ b/contrib/arch-linux/new.patch @@ -0,0 +1,35 @@ +--- src/SDCCast.c ++++ src/SDCCast.c +@@ -863,6 +863,8 @@ processParms (ast *func, + + ftype = (*actParm)->ftype; + ++ resultType = RESULT_TYPE_NONE; ++ + /* If it's a char, upcast to int. */ + if (IS_INTEGRAL (ftype) + && (getSize (ftype) < (unsigned) INTSIZE)) +@@ -874,12 +876,14 @@ processParms (ast *func, + { + newType = newAst_LINK (copyLinkChain(ftype)); + DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; ++ resultType = RESULT_TYPE_GPTR; + } + + if (IS_AGGREGATE (ftype)) + { + newType = newAst_LINK (copyLinkChain (ftype)); + DCL_TYPE (newType->opval.lnk) = port->unqualified_pointer; ++ resultType = RESULT_TYPE_GPTR; + } + + if (newType) +@@ -890,7 +894,7 @@ processParms (ast *func, + (*actParm)->filename = (*actParm)->right->filename; + (*actParm)->lineno = (*actParm)->right->lineno; + +- decorateType (*actParm, RESULT_TYPE_NONE); ++ decorateType (*actParm, resultType); + } + return 0; + } /* vararg */ diff --git a/contrib/arch-linux/nsis-2.43-64bit-fixes.patch b/contrib/arch-linux/nsis-2.43-64bit-fixes.patch new file mode 100644 index 00000000..342396d7 --- /dev/null +++ b/contrib/arch-linux/nsis-2.43-64bit-fixes.patch @@ -0,0 +1,211 @@ +diff -ur nsis-2.43-src/SCons/Config/gnu nsis-2.43-src-64bit-fixes/SCons/Config/gnu +--- nsis-2.43-src/SCons/Config/gnu 2009-02-05 01:52:28.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/SCons/Config/gnu 2009-02-25 07:59:44.000000000 +0100 +@@ -95,8 +95,6 @@ + makensis_env.Append(CXXFLAGS = ['-Wall']) # all warnings + + conf = FlagsConfigure(makensis_env) +-conf.CheckCompileFlag('-m32') # +-conf.CheckLinkFlag('-m32') # + conf.CheckLinkFlag('$MAP_FLAG') # generate map file + if not defenv['DEBUG'] and defenv['STRIP'] and defenv['STRIP_CP']: + TestStrip(conf) # strip +@@ -149,8 +147,6 @@ + ### cross-platform util environment adjustments + + conf = FlagsConfigure(cp_util_env) +-conf.CheckCompileFlag('-m32') +-conf.CheckLinkFlag('-m32') + if not defenv['DEBUG'] and defenv['STRIP'] and defenv['STRIP_CP']: + TestStrip(conf) # strip + conf.Finish() +@@ -160,8 +156,6 @@ + test_env = defenv.Clone() + test_env.Append(CPPPATH = ['#$BUILD_CONFIG']) + conf = FlagsConfigure(test_env) +-conf.CheckCompileFlag('-m32') +-conf.CheckLinkFlag('-m32') + conf.Finish() + + ### weird GCC requirements +diff -ur nsis-2.43-src/Source/DialogTemplate.cpp nsis-2.43-src-64bit-fixes/Source/DialogTemplate.cpp +--- nsis-2.43-src/Source/DialogTemplate.cpp 2007-11-30 10:54:13.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/DialogTemplate.cpp 2009-02-25 07:59:44.000000000 +0100 +@@ -74,7 +74,7 @@ + if (IS_INTRESOURCE(x)) { \ + *(WORD*)seeker = 0xFFFF; \ + seeker += sizeof(WORD); \ +- *(WORD*)seeker = ConvertEndianness(WORD(DWORD(x))); \ ++ *(WORD*)seeker = ConvertEndianness(WORD(long(x))); \ + seeker += sizeof(WORD); \ + } \ + else { \ +@@ -622,7 +622,7 @@ + } + } + +- assert((DWORD) seeker - (DWORD) pbDlg == dwSize); ++ assert((long) seeker - (long) pbDlg == dwSize); + + // DONE! + return pbDlg; +diff -ur nsis-2.43-src/Source/mmap.cpp nsis-2.43-src-64bit-fixes/Source/mmap.cpp +--- nsis-2.43-src/Source/mmap.cpp 2009-02-01 15:44:30.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/mmap.cpp 2009-02-25 07:59:44.000000000 +0100 +@@ -322,7 +322,7 @@ + if (!pView) + return; + +- unsigned int alignment = ((unsigned int)pView) % m_iAllocationGranularity; ++ unsigned int alignment = ((unsigned long)pView) % m_iAllocationGranularity; + pView = (char *)pView - alignment; + size += alignment; + #ifdef _WIN32 +diff -ur nsis-2.43-src/Source/Platform.h nsis-2.43-src-64bit-fixes/Source/Platform.h +--- nsis-2.43-src/Source/Platform.h 2009-02-01 15:44:30.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/Platform.h 2009-02-25 07:59:44.000000000 +0100 +@@ -166,7 +166,7 @@ + # define MAKEINTRESOURCE MAKEINTRESOURCEA + # endif + # ifndef IMAGE_FIRST_SECTION +-# define IMAGE_FIRST_SECTION(h) ( PIMAGE_SECTION_HEADER( (DWORD) h + \ ++# define IMAGE_FIRST_SECTION(h) ( PIMAGE_SECTION_HEADER( (long) h + \ + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + \ + FIX_ENDIAN_INT16(PIMAGE_NT_HEADERS(h)->FileHeader.SizeOfOptionalHeader) ) ) + # endif +@@ -198,7 +198,7 @@ + #endif + + #ifndef ULONG_PTR +-# define ULONG_PTR DWORD ++# define ULONG_PTR ULONG + #endif + + #ifndef IDC_HAND +@@ -703,7 +703,7 @@ + WORD e_oemid; + WORD e_oeminfo; + WORD e_res2[10]; +- LONG e_lfanew; ++ DWORD e_lfanew; + } IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER; + # pragma pack() + # pragma pack(4) +diff -ur nsis-2.43-src/Source/Plugins.cpp nsis-2.43-src-64bit-fixes/Source/Plugins.cpp +--- nsis-2.43-src/Source/Plugins.cpp 2009-02-01 15:44:30.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/Plugins.cpp 2009-02-25 07:59:44.000000000 +0100 +@@ -136,7 +136,7 @@ + DWORD prd = FIX_ENDIAN_INT32(sections[i].PointerToRawData); + PIMAGE_EXPORT_DIRECTORY exports = PIMAGE_EXPORT_DIRECTORY(&dlldata[0] + prd + ExportDirVA - va); + DWORD na = FIX_ENDIAN_INT32(exports->AddressOfNames); +- unsigned long *names = (unsigned long*)((unsigned long) exports + (char *) na - ExportDirVA); ++ unsigned int *names = (unsigned int*)((unsigned long) exports + (char *) na - ExportDirVA); + for (unsigned long j = 0; j < FIX_ENDIAN_INT32(exports->NumberOfNames); j++) + { + const string name = string((char*)exports + FIX_ENDIAN_INT32(names[j]) - ExportDirVA); +diff -ur nsis-2.43-src/Source/ResourceEditor.cpp nsis-2.43-src-64bit-fixes/Source/ResourceEditor.cpp +--- nsis-2.43-src/Source/ResourceEditor.cpp 2009-02-05 01:50:12.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/ResourceEditor.cpp 2009-02-25 07:59:44.000000000 +0100 +@@ -684,7 +684,7 @@ + rdDir.NumberOfIdEntries = ConvertEndianness(rdDir.NumberOfIdEntries); + + CopyMemory(seeker, &rdDir, sizeof(IMAGE_RESOURCE_DIRECTORY)); +- crd->m_dwWrittenAt = DWORD(seeker); ++ crd->m_dwWrittenAt = long(seeker); + seeker += sizeof(IMAGE_RESOURCE_DIRECTORY); + + for (int i = 0; i < crd->CountEntries(); i++) { +@@ -705,7 +705,7 @@ + rDirE.UName.NameString.NameIsString = (crd->GetEntry(i)->HasName()) ? 1 : 0; + + CopyMemory(seeker, &rDirE, sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY)); +- crd->GetEntry(i)->m_dwWrittenAt = DWORD(seeker); ++ crd->GetEntry(i)->m_dwWrittenAt = long(seeker); + seeker += sizeof(MY_IMAGE_RESOURCE_DIRECTORY_ENTRY); + } + qDirs.pop(); +@@ -721,7 +721,7 @@ + rDataE.Size = ConvertEndianness(cRDataE->GetSize()); + + CopyMemory(seeker, &rDataE, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); +- cRDataE->m_dwWrittenAt = DWORD(seeker); ++ cRDataE->m_dwWrittenAt = long(seeker); + seeker += sizeof(IMAGE_RESOURCE_DATA_ENTRY); + + qDataEntries.pop(); +@@ -733,7 +733,7 @@ + while (!qStrings.empty()) { + CResourceDirectoryEntry* cRDirE = qStrings.front(); + +- PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->UName.NameString.NameOffset = ConvertEndianness(DWORD(seeker) - DWORD(pbRsrcSec)); ++ PMY_IMAGE_RESOURCE_DIRECTORY_ENTRY(cRDirE->m_dwWrittenAt)->UName.NameString.NameOffset = ConvertEndianness(long(seeker) - long(pbRsrcSec)); + + WCHAR* szName = cRDirE->GetName(); + WORD iLen = winchar_strlen(szName) + 1; +@@ -764,7 +764,7 @@ + /* + * Set all of the directory entries offsets. + */ +- SetOffsets(m_cResDir, DWORD(pbRsrcSec)); ++ SetOffsets(m_cResDir, long(pbRsrcSec)); + } + + // Sets the offsets in directory entries +@@ -887,7 +887,7 @@ + // Returns -1 if can not be found + int CResourceDirectory::Find(WCHAR* szName) { + if (IS_INTRESOURCE(szName)) +- return Find((WORD) (DWORD) szName); ++ return Find((WORD) (long) szName); + else + if (szName[0] == '#') + return Find(WORD(winchar_stoi(szName + 1))); +@@ -965,7 +965,7 @@ + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; +- m_wId = (WORD) (DWORD) szName; ++ m_wId = (WORD) (long) szName; + } + else { + m_bHasName = true; +@@ -979,7 +979,7 @@ + if (IS_INTRESOURCE(szName)) { + m_bHasName = false; + m_szName = 0; +- m_wId = (WORD) (DWORD) szName; ++ m_wId = (WORD) (long) szName; + } + else { + m_bHasName = true; +diff -ur nsis-2.43-src/Source/util.cpp nsis-2.43-src-64bit-fixes/Source/util.cpp +--- nsis-2.43-src/Source/util.cpp 2009-02-01 15:44:30.000000000 +0100 ++++ nsis-2.43-src-64bit-fixes/Source/util.cpp 2009-02-25 07:59:44.000000000 +0100 +@@ -77,9 +77,9 @@ + } + + if (width != 0) { +- LONG biWidth; ++ DWORD biWidth; + fseek(f, 18, SEEK_SET); // Seek to the width member of the header +- fread(&biWidth, sizeof(LONG), 1, f); ++ fread(&biWidth, sizeof(DWORD), 1, f); + FIX_ENDIAN_INT32_INPLACE(biWidth); + if (width != biWidth) { + fclose(f); +@@ -88,12 +88,12 @@ + } + + if (height != 0) { +- LONG biHeight; ++ DWORD biHeight; + fseek(f, 22, SEEK_SET); // Seek to the height member of the header +- fread(&biHeight, sizeof(LONG), 1, f); ++ fread(&biHeight, sizeof(DWORD), 1, f); + FIX_ENDIAN_INT32_INPLACE(biHeight); + // Bitmap height can be negative too... +- if (height != abs(biHeight)) { ++ if (height != abs((long int)biHeight)) { + fclose(f); + return -3; + } -- cgit v1.2.3 From 68323cbb222f1f33198a42abaa0550af22f75a93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Nov 2010 15:53:27 -0800 Subject: altosui: Close serial port when debug link fails If the debug connection isn't working, close down the serial port when reporting the failure. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosFlash.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java index fa2465d3..3af25c23 100644 --- a/ao-tools/altosui/AltosFlash.java +++ b/ao-tools/altosui/AltosFlash.java @@ -336,7 +336,9 @@ public class AltosFlash { debug = new AltosDebug(in_debug_dongle); input = new FileInputStream(file); image = new AltosHexfile(input); - if (!debug.check_connection()) + if (!debug.check_connection()) { + debug.close(); throw new IOException("Debug port not connected"); + } } } \ No newline at end of file -- cgit v1.2.3 From b27327a05d249eaf969b67d2a8d12fc6a93841f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Nov 2010 15:56:04 -0800 Subject: altos: assume igniter worked. Many igniters don't go open when fired, so there's no way to know if they worked. Assume they did as a failed igniter is unlikely to do anything when fired again anyways. Signed-off-by: Keith Packard --- src/ao_ignite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 4093b6a7..58d340d9 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -113,9 +113,7 @@ ao_igniter(void) ao_igniter_fire(igniter); ao_delay(AO_IGNITER_CHARGE_TIME); - status = ao_igniter_status(igniter); - if (status == ao_igniter_open) - ao_ignition[igniter].fired = 1; + ao_ignition[igniter].fired = 1; } } } -- cgit v1.2.3 From 5523e7d55ecc8d310e495fa4f5115f7483c42d65 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 22 Nov 2010 21:07:10 -0700 Subject: add a rudimentary --help for command line use --- ao-tools/altosui/AltosUI.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java index 93a5e0d8..94c4dd2a 100644 --- a/ao-tools/altosui/AltosUI.java +++ b/ao-tools/altosui/AltosUI.java @@ -353,7 +353,14 @@ public class AltosUI extends JFrame { public static void main(final String[] args) { int process = 0; /* Handle batch-mode */ - if (args.length == 3 && args[0].equals("--fetchmaps")) { + if (args.length == 1 && args[0].equals("--help")) { + System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); + System.out.printf(" Options:\n"); + System.out.printf(" --fetchmaps \tpre-fetch maps for site map view\n"); + System.out.printf(" --replay \t\trelive the glory of past flights \n"); + System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n"); + System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n"); + } else if (args.length == 3 && args[0].equals("--fetchmaps")) { double lat = Double.parseDouble(args[1]); double lon = Double.parseDouble(args[2]); AltosSiteMap.prefetchMaps(lat, lon, 5, 5); -- cgit v1.2.3 From 737f2fdd012202f453120ece117ae5e859b32082 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Nov 2010 22:26:19 -0800 Subject: doc: Add internal documentation for AltOS Signed-off-by: Keith Packard --- doc/Makefile | 4 +- doc/altos.xsl | 1441 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1443 insertions(+), 2 deletions(-) create mode 100644 doc/altos.xsl diff --git a/doc/Makefile b/doc/Makefile index 57300c10..52934290 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,8 +2,8 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -HTML=telemetrum-doc.html altosui-doc.html -PDF=telemetrum-doc.pdf altosui-doc.pdf +HTML=telemetrum-doc.html altosui-doc.html altos.html +PDF=telemetrum-doc.pdf altosui-doc.pdf altos.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl diff --git a/doc/altos.xsl b/doc/altos.xsl new file mode 100644 index 00000000..9a88a5b5 --- /dev/null +++ b/doc/altos.xsl @@ -0,0 +1,1441 @@ + + + + + AltOS + Altos Metrum Operating System + + + Keith + Packard + + + 2010 + Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.1 + 22 November 2010 + Initial content + + + + + Overview + + AltOS is a operating system built for the 8051-compatible + processor found in the TI cc1111 microcontroller. It's designed + to be small and easy to program with. The main features are: + + + Multi-tasking. While the 8051 doesn't provide separate + address spaces, it's often easier to write code that operates + in separate threads instead of tying everything into one giant + event loop. + + + + Non-preemptive. This increases latency for thread + switching but reduces the number of places where context + switching can occur. It also simplifies the operating system + design somewhat. Nothing in the target system (rocket flight + control) has tight timing requirements, and so this seems like + a reasonable compromise. + + + + Sleep/wakeup scheduling. Taken directly from ancient + Unix designs, these two provide the fundemental scheduling + primitive within AltOS. + + + + Mutexes. As a locking primitive, mutexes are easier to + use than semaphores, at least in my experience. + + + + Timers. Tasks can set an alarm which will abort any + pending sleep, allowing operations to time-out instead of + blocking forever. + + + + + + The device drivers and other subsystems in AltOS are + conventionally enabled by invoking their _init() function from + the 'main' function before that calls + ao_start_scheduler(). These functions initialize the pin + assignments, add various commands to the command processor and + may add tasks to the scheduler to handle the device. A typical + main program, thus, looks like: + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_slave_init(); + ao_packet_master_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} + + As you can see, a long sequence of subsystems are initialized + and then the scheduler is started. + + + + Programming the 8051 with SDCC + + The 8051 is a primitive 8-bit processor, designed in the mists + of time in as few transistors as possible. The architecture is + highly irregular and includes several separate memory + spaces. Furthermore, accessing stack variables is slow, and the + stack itself is of limited size. While SDCC papers over the + instruction set, it is not completely able to hide the memory + architecture from the application designer. + +
+ 8051 memory spaces + + The __data/__xdata/__code memory spaces below were completely + separate in the original 8051 design. In the cc1111, this + isn't true—they all live in a single unified 64kB address + space, and so it's possible to convert any address into a + unique 16-bit address. SDCC doesn't know this, and so a + 'global' address to SDCC consumes 3 bytes of memory, 1 byte as + a tag indicating the memory space and 2 bytes of offset within + that space. AltOS avoids these 3-byte addresses as much as + possible; using them involves a function call per byte + access. The result is that nearly every variable declaration + is decorated with a memory space identifier which clutters the + code but makes the resulting code far smaller and more + efficient. + + + SDCC 8051 memory spaces + + __data + + + The 8051 can directly address these 128 bytes of + memory. This makes them precious so they should be + reserved for frequently addressed values. Oh, just to + confuse things further, the 8 general registers in the + CPU are actually stored in this memory space. There are + magic instructions to 'bank switch' among 4 banks of + these registers located at 0x00 - 0x1F. AltOS uses only + the first bank at 0x00 - 0x07, leaving the other 24 + bytes available for other data. + + + + + __idata + + + There are an additional 128 bytes of internal memory + that share the same address space as __data but which + cannot be directly addressed. The stack normally + occupies this space and so AltOS doesn't place any + static storage here. + + + + + __xdata + + + This is additional general memory accessed through a + single 16-bit address register. The CC1111F32 has 32kB + of memory available here. Most program data should live + in this memory space. + + + + + __pdata + + + This is an alias for the first 256 bytes of __xdata + memory, but uses a shorter addressing mode with + single global 8-bit value for the high 8 bits of the + address and any of several 8-bit registers for the low 8 + bits. AltOS uses a few bits of this memory, it should + probably use more. + + + + + __code + + + All executable code must live in this address space, but + you can stick read-only data here too. It is addressed + using the 16-bit address register and special 'code' + access opcodes. Anything read-only should live in this space. + + + + + __bit + + + The 8051 has 128 bits of bit-addressible memory that + lives in the __data segment from 0x20 through + 0x2f. Special instructions access these bits + in a single atomic operation. This isn't so much a + separate address space as a special addressing mode for + a few bytes in the __data segment. + + + + + __sfr, __sfr16, __sfr32, __sbit + + + Access to physical registers in the device use this mode + which declares the variable name, it's type and the + address it lives at. No memory is allocated for these + variables. + + + + +
+
+ Function calls on the 8051 + + Because stack addressing is expensive, and stack space + limited, the default function call declaration in SDCC + allocates all parameters and local variables in static global + memory. Just like fortran. This makes these functions + non-reentrant, and also consume space for parameters and + locals even when they are not running. The benefit is smaller + code and faster execution. + +
+ __reentrant functions + + All functions which are re-entrant, either due to recursion + or due to a potential context switch while executing, should + be marked as __reentrant so that their parameters and local + variables get allocated on the stack. This ensures that + these values are not overwritten by another invocation of + the function. + + + Functions which use significant amounts of space for + arguments and/or local variables and which are not often + invoked can also be marked as __reentrant. The resulting + code will be larger, but the savings in memory are + frequently worthwhile. + +
+
+ Non __reentrant functions + + All parameters and locals in non-reentrant functions can + have data space decoration so that they are allocated in + __xdata, __pdata or __data space as desired. This can avoid + consuming __data space for infrequently used variables in + frequently used functions. + + + All library functions called by SDCC, including functions + for multiplying and dividing large data types, are + non-reentrant. Because of this, interrupt handlers must not + invoke any library functions, including the multiply and + divide code. + +
+
+ __interrupt functions + + Interrupt functions are declared with with an __interrupt + decoration that includes the interrupt number. SDCC saves + and restores all of the registers in these functions and + uses the 'reti' instruction at the end so that they operate + as stand-alone interrupt handlers. Interrupt functions may + call the ao_wakeup function to wake AltOS tasks. + +
+
+ __critical functions and statements + + SDCC has built-in support for suspending interrupts during + critical code. Functions marked as __critical will have + interrupts suspended for the whole period of + execution. Individual statements may also be marked as + __critical which blocks interrupts during the execution of + that statement. Keeping critical sections as short as + possible is key to ensuring that interrupts are handled as + quickly as possible. + +
+
+
+ + Task functions + + This chapter documents how to create, destroy and schedule AltOS tasks. + + + AltOS Task Functions + + ao_add_task + + +void +ao_add_task(__xdata struct ao_task * task, + void (*start)(void), + __code char *name); + + + This initializes the statically allocated task structure, + assigns a name to it (not used for anything but the task + display), and the start address. It does not switch to the + new task. 'start' must not ever return; there is no place + to return to. + + + + + ao_exit + + +void +ao_exit(void) + + + This terminates the current task. + + + + + ao_sleep + + +void +ao_sleep(__xdata void *wchan) + + + This suspends the current task until 'wchan' is signaled + by ao_wakeup, or until the timeout, set by ao_alarm, + fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise + it returns 1. This is the only way to switch to another task. + + + + + ao_wakeup + + +void +ao_wakeup(__xdata void *wchan) + + + Wake all tasks blocked on 'wchan'. This makes them + available to be run again, but does not actually switch + to another task. + + + + + ao_alarm + + +void +ao_alarm(uint16_t delay) + + + Schedules an alarm to fire in at least 'delay' ticks. If + the task is asleep when the alarm fires, it will wakeup + and ao_sleep will return 1. + + + + + ao_wake_task + + +void +ao_wake_task(__xdata struct ao_task *task) + + + Force a specific task to wake up, independent of which + 'wchan' it is waiting for. + + + + + ao_start_scheduler + + +void +ao_start_scheduler(void) + + + This is called from 'main' when the system is all + initialized and ready to run. It will not return. + + + + + ao_clock_init + + +void +ao_clock_init(void) + + + This turns on the external 48MHz clock then switches the + hardware to using it. This is required by many of the + internal devices like USB. It should be called by the + 'main' function first, before initializing any of the + other devices in the system. + + + + + + + Timer Functions + + AltOS sets up one of the cc1111 timers to run at 100Hz and + exposes this tick as the fundemental unit of time. At each + interrupt, AltOS increments the counter, and schedules any tasks + waiting for that time to pass, then fires off the ADC system to + collect current data readings. Doing this from the ISR ensures + that the ADC values are sampled at a regular rate, independent + of any scheduling jitter. + + + AltOS Timer Functions + + ao_time + + +uint16_t +ao_time(void) + + + Returns the current system tick count. Note that this is + only a 16 bit value, and so it wraps every 655.36 seconds. + + + + + ao_delay + + +void +ao_delay(uint16_t ticks); + + + Suspend the current task for at least 'ticks' clock units. + + + + + ao_timer_set_adc_interval + + +void +ao_timer_set_adc_interval(uint8_t interval); + + + This sets the number of ticks between ADC samples. If set + to 0, no ADC samples are generated. AltOS uses this to + slow down the ADC sampling rate to save power. + + + + + ao_timer_init + + +void +ao_timer_init(void) + + + This turns on the 100Hz tick using the CC1111 timer 1. It + is required for any of the time-based functions to + work. It should be called by 'main' before ao_start_scheduler. + + + + + + + AltOS Mutexes + + AltOS provides mutexes as a basic synchronization primitive. Each + mutexes is simply a byte of memory which holds 0 when the mutex + is free or the task id of the owning task when the mutex is + owned. Mutex calls are checked—attempting to acquire a mutex + already held by the current task or releasing a mutex not held + by the current task will both cause a panic. + + + Mutex Functions + + ao_mutex_get + + +void +ao_mutex_get(__xdata uint8_t *mutex); + + + Acquires the specified mutex, blocking if the mutex is + owned by another task. + + + + + ao_mutex_put + + +void +ao_mutex_put(__xdata uint8_t *mutex); + + + Releases the specified mutex, waking up all tasks waiting + for it. + + + + + + + CC1111 DMA engine + + The CC1111 contains a useful bit of extra hardware in the form + of five programmable DMA engines. They can be configured to copy + data in memory, or between memory and devices (or even between + two devices). AltOS exposes a general interface to this hardware + and uses it to handle radio and SPI data. + + + Code using a DMA engine should allocate one at startup + time. There is no provision to free them, and if you run out, + AltOS will simply panic. + + + During operation, the DMA engine is initialized with the + transfer parameters. Then it is started, at which point it + awaits a suitable event to start copying data. When copying data + from hardware to memory, that trigger event is supplied by the + hardware device. When copying data from memory to hardware, the + transfer is usually initiated by software. + + + AltOS DMA functions + + ao_dma_alloc + + +uint8_t +ao_dma_alloc(__xdata uint8_t *done) + + + Allocates a DMA engine, returning the identifier. Whenever + this DMA engine completes a transfer. 'done' is cleared + when the DMA is started, and then receives the + AO_DMA_DONE bit on a successful transfer or the + AO_DMA_ABORTED bit if ao_dma_abort was called. Note that + it is possible to get both bits if the transfer was + aborted after it had finished. + + + + + ao_dma_set_transfer + + +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) + + + Initializes the specified dma engine to copy data + from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and + cfg1 are values directly out of the CC1111 documentation + and tell the DMA engine what the transfer unit size, + direction and step are. + + + + + ao_dma_start + + +void +ao_dma_start(uint8_t id); + + + Arm the specified DMA engine and await a signal from + either hardware or software to start transferring data. + + + + + ao_dma_trigger + + +void +ao_dma_trigger(uint8_t id) + + + Trigger the specified DMA engine to start copying data. + + + + + ao_dma_abort + + +void +ao_dma_abort(uint8_t id) + + + Terminate any in-progress DMA transation, marking its + 'done' variable with the AO_DMA_ABORTED bit. + + + + + + + SDCC Stdio interface + + AltOS offers a stdio interface over both USB and the RF packet + link. This provides for control of the device localy or + remotely. This is hooked up to the stdio functions in SDCC by + providing the standard putchar/getchar/flush functions. These + automatically multiplex the two available communication + channels; output is always delivered to the channel which + provided the most recent input. + + + SDCC stdio functions + + putchar + + +void +putchar(char c) + + + Delivers a single character to the current console + device. + + + + + getchar + + +char +getchar(void) + + + Reads a single character from any of the available + console devices. The current console device is set to + that which delivered this character. This blocks until + a character is available. + + + + + flush + + +void +flush(void) + + + Flushes the current console device output buffer. Any + pending characters will be delivered to the target device. +xo + + + + ao_add_stdio + + +void +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) + + + This adds another console device to the available + list. + + + 'pollchar' returns either an available character or + AO_READ_AGAIN if none is available. Significantly, it does + not block. The device driver must set 'ao_stdin_ready' to + 1 and call ao_wakeup(&ao_stdin_ready) when it receives + input to tell getchar that more data is available, at + which point 'pollchar' will be called again. + + + 'putchar' queues a character for output, flushing if the output buffer is + full. It may block in this case. + + + 'flush' forces the output buffer to be flushed. It may + block until the buffer is delivered, but it is not + required to do so. + + + + + + + Command line interface + + AltOS includes a simple command line parser which is hooked up + to the stdio interfaces permitting remote control of the device + over USB or the RF link as desired. Each command uses a single + character to invoke it, the remaining characters on the line are + available as parameters to the command. + + + AltOS command line parsing functions + + ao_cmd_register + + +void +ao_cmd_register(__code struct ao_cmds *cmds) + + + This registers a set of commands with the command + parser. There is a fixed limit on the number of command + sets, the system will panic if too many are registered. + Each command is defined by a struct ao_cmds entry: + +struct ao_cmds { + char cmd; + void (*func)(void); + const char *help; +}; + + 'cmd' is the character naming the command. 'func' is the + function to invoke and 'help' is a string displayed by the + '?' command. Syntax errors found while executing 'func' + should be indicated by modifying the global ao_cmd_status + variable with one of the following values: + + + ao_cmd_success + + + The command was parsed successfully. There is no + need to assign this value, it is the default. + + + + + ao_cmd_lex_error + + + A token in the line was invalid, such as a number + containing invalid characters. The low-level + lexing functions already assign this value as needed. + + + + + ao_syntax_error + + + The command line is invalid for some reason other + than invalid tokens. + + + + + + + + + ao_cmd_lex + + +void +ao_cmd_lex(void); + + + This gets the next character out of the command line + buffer and sticks it into ao_cmd_lex_c. At the end of the + line, ao_cmd_lex_c will get a newline ('\n') character. + + + + + ao_cmd_put16 + + +void +ao_cmd_put16(uint16_t v); + + + Writes 'v' as four hexadecimal characters. + + + + + ao_cmd_put8 + + +void +ao_cmd_put8(uint8_t v); + + + Writes 'v' as two hexadecimal characters. + + + + + ao_cmd_white + + +void +ao_cmd_white(void) + + + This skips whitespace by calling ao_cmd_lex while + ao_cmd_lex_c is either a space or tab. It does not skip + any characters if ao_cmd_lex_c already non-white. + + + + + ao_cmd_hex + + +void +ao_cmd_hex(void) + + + This reads a 16-bit hexadecimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_i; + + + + + ao_cmd_decimal + + +void +ao_cmd_decimal(void) + + + This reads a 32-bit decimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_u32 and the low 16 bits are stored + in ao_cmd_lex_i; + + + + + ao_match_word + + +uint8_t +ao_match_word(__code char *word) + + + This checks to make sure that 'word' occurs on the command + line. It does not skip leading white space. If 'word' is + found, then 1 is returned. Otherwise, ao_cmd_status is set to + ao_cmd_syntax_error and 0 is returned. + + + + + ao_cmd_init + + +void +ao_cmd_init(void + + + Initializes the command system, setting up the built-in + commands and adding a task to run the command processing + loop. It should be called by 'main' before ao_start_scheduler. + + + + + + + CC1111 USB target device + + The CC1111 contains a full-speed USB target device. It can be + programmed to offer any kind of USB target, but to simplify + interactions with a variety of operating systems, AltOS provides + only a single target device profile, that of a USB modem which + has native drivers for Linux, Windows and Mac OS X. It would be + easy to change the code to provide an alternate target device if + necessary. + + + To the rest of the system, the USB device looks like a simple + two-way byte stream. It can be hooked into the command line + interface if desired, offering control of the device over the + USB link. Alternatively, the functions can be accessed directly + to provide for USB-specific I/O. + + + AltOS USB functions + + ao_usb_flush + + +void +ao_usb_flush(void); + + + Flushes any pending USB output. This queues an 'IN' packet + to be delivered to the USB host if there is pending data, + or if the last IN packet was full to indicate to the host + that there isn't any more pending data available. + + + + + ao_usb_putchar + + +void +ao_usb_putchar(char c); + + + If there is a pending 'IN' packet awaiting delivery to the + host, this blocks until that has been fetched. Then, this + adds a byte to the pending IN packet for delivery to the + USB host. If the USB packet is full, this queues the 'IN' + packet for delivery. + + + + + ao_usb_pollchar + + +char +ao_usb_pollchar(void); + + + If there are no characters remaining in the last 'OUT' + packet received, this returns AO_READ_AGAIN. Otherwise, it + returns the next character, reporting to the host that it + is ready for more data when the last character is gone. + + + + + ao_usb_getchar + + +char +ao_usb_getchar(void); + + + This uses ao_pollchar to receive the next character, + blocking while ao_pollchar returns AO_READ_AGAIN. + + + + + ao_usb_disable + + +void +ao_usb_disable(void); + + + This turns off the USB controller. It will no longer + respond to host requests, nor return characters. Calling + any of the i/o routines while the USB device is disabled + is undefined, and likely to break things. Disabling the + USB device when not needed saves power. + + + Note that neither TeleDongle nor TeleMetrum are able to + signal to the USB host that they have disconnected, so + after disabling the USB device, it's likely that the cable + will need to be disconnected and reconnected before it + will work again. + + + + + ao_usb_enable + + +void +ao_usb_enable(void); + + + This turns the USB controller on again after it has been + disabled. See the note above about needing to physically + remove and re-insert the cable to get the host to + re-initialize the USB link. + + + + + ao_usb_init + + +void +ao_usb_init(void); + + + This turns the USB controller on, adds a task to handle + the control end point and adds the usb I/O functions to + the stdio system. Call this from main before + ao_start_scheduler. + + + + + + + CC1111 Serial peripheral + + The CC1111 provides two USART peripherals. AltOS uses one for + asynch serial data, generally to communicate with a GPS device, + and the other for a SPI bus. The UART is configured to operate + in 8-bits, no parity, 1 stop bit framing. The default + configuration has clock settings for 4800, 9600 and 57600 baud + operation. Additional speeds can be added by computing + appropriate clock values. + + + To prevent loss of data, AltOS provides receive and transmit + fifos of 32 characters each. + + + AltOS serial functions + + ao_serial_getchar + + +char +ao_serial_getchar(void); + + + Returns the next character from the receive fifo, blocking + until a character is received if the fifo is empty. + + + + + ao_serial_putchar + + +void +ao_serial_putchar(char c); + + + Adds a character to the transmit fifo, blocking if the + fifo is full. Starts transmitting characters. + + + + + ao_serial_drain + + +void +ao_serial_drain(void); + + + Blocks until the transmit fifo is empty. Used internally + when changing serial speeds. + + + + + ao_serial_set_speed + + +void +ao_serial_set_speed(uint8_t speed); + + + Changes the serial baud rate to one of + AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or + AO_SERIAL_SPEED_57600. This first flushes the transmit + fifo using ao_serial_drain. + + + + + ao_serial_init + + +void +ao_serial_init(void) + + + Initializes the serial peripheral. Call this from 'main' + before jumping to ao_start_scheduler. The default speed + setting is AO_SERIAL_SPEED_4800. + + + + + + + CC1111 Radio peripheral + + The CC1111 radio transceiver sends and receives digital packets + with forward error correction and detection. The AltOS driver is + fairly specific to the needs of the TeleMetrum and TeleDongle + devices, using it for other tasks may require customization of + the driver itself. There are three basic modes of operation: + + + + Telemetry mode. In this mode, TeleMetrum transmits telemetry + frames at a fixed rate. The frames are of fixed size. This + is strictly a one-way communication from TeleMetrum to + TeleDongle. + + + + + Packet mode. In this mode, the radio is used to create a + reliable duplex byte stream between TeleDongle and + TeleMetrum. This is an asymmetrical protocol with + TeleMetrum only transmitting in response to a packet sent + from TeleDongle. Thus getting data from TeleMetrum to + TeleDongle requires polling. The polling rate is adaptive, + when no data has been received for a while, the rate slows + down. The packets are checked at both ends and invalid + data are ignored. + + + On the TeleMetrum side, the packet link is hooked into the + stdio mechanism, providing an alternate data path for the + command processor. It is enabled when the unit boots up in + 'idle' mode. + + + On the TeleDongle side, the packet link is enabled with a + command; data from the stdio package is forwarded over the + packet link providing a connection from the USB command + stream to the remote TeleMetrum device. + + + + + Radio Direction Finding mode. In this mode, TeleMetrum + constructs a special packet that sounds like an audio tone + when received by a conventional narrow-band FM + receiver. This is designed to provide a beacon to track + the device when other location mechanisms fail. + + + + + + AltOS radio functions + + ao_radio_set_telemetry + + +void +ao_radio_set_telemetry(void); + + + Configures the radio to send or receive telemetry + packets. This includes packet length, modulation scheme and + other RF parameters. It does not include the base frequency + or channel though. Those are set at the time of transmission + or reception, in case the values are changed by the user. + + + + + ao_radio_set_packet + + +void +ao_radio_set_packet(void); + + + Configures the radio to send or receive packet data. This + includes packet length, modulation scheme and other RF + parameters. It does not include the base frequency or + channel though. Those are set at the time of transmission or + reception, in case the values are changed by the user. + + + + + ao_radio_set_rdf + + +void +ao_radio_set_rdf(void); + + + Configures the radio to send RDF 'packets'. An RDF 'packet' + is a sequence of hex 0x55 bytes sent at a base bit rate of + 2kbps using a 5kHz deviation. All of the error correction + and data whitening logic is turned off so that the resulting + modulation is received as a 1kHz tone by a conventional 70cm + FM audio receiver. + + + + + ao_radio_idle + + +void +ao_radio_idle(void); + + + Sets the radio device to idle mode, waiting until it reaches + that state. This will terminate any in-progress transmit or + receive operation. + + + + + ao_radio_get + + +void +ao_radio_get(void); + + + Acquires the radio mutex and then configures the radio + frequency using the global radio calibration and channel + values. + + + + + ao_radio_put + + +void +ao_radio_put(void); + + + Releases the radio mutex. + + + + + ao_radio_abort + + +void +ao_radio_abort(void); + + + Aborts any transmission or reception process by aborting the + associated DMA object and calling ao_radio_idle to terminate + the radio operation. + + + + + + AltOS radio telemetry functions + + In telemetry mode, you can send or receive a telemetry + packet. The data from receiving a packet also includes the RSSI + and status values supplied by the receiver. These are added + after the telemetry data. + + + ao_radio_send + + +void +ao_radio_send(__xdata struct ao_telemetry *telemetry); + + + This sends the specific telemetry packet, waiting for the + transmission to complete. The radio must have been set to + telemetry mode. This function calls ao_radio_get() before + sending, and ao_radio_put() afterwards, to correctly + serialize access to the radio device. + + + + + ao_radio_recv + + +void +ao_radio_recv(__xdata struct ao_radio_recv *radio); + + + This blocks waiting for a telemetry packet to be received. + The radio must have been set to telemetry mode. This + function calls ao_radio_get() before receiving, and + ao_radio_put() afterwards, to correctly serialize access + to the radio device. This returns non-zero if a packet was + received, or zero if the operation was aborted (from some + other task calling ao_radio_abort()). + + + + + + AltOS radio direction finding function + + In radio direction finding mode, there's just one function to + use + + + ao_radio_rdf + + +void +ao_radio_rdf(int ms); + + + This sends an RDF packet lasting for the specified amount + of time. The maximum length is 1020 ms. + + + + + + Packet mode functions + + Packet mode is asymmetrical and is configured at compile time + for either master or slave mode (but not both). The basic I/O + functions look the same at both ends, but the internals are + different, along with the initialization steps. + + + ao_packet_putchar + + +void +ao_packet_putchar(char c); + + + If the output queue is full, this first blocks waiting for + that data to be delivered. Then, queues a character for + packet transmission. On the master side, this will + transmit a packet if the output buffer is full. On the + slave side, any pending data will be sent the next time + the master polls for data. + + + + + ao_packet_pollchar + + +char +ao_packet_pollchar(void); + + + This returns a pending input character if available, + otherwise returns AO_READ_AGAIN. On the master side, if + this empties the buffer, it triggers a poll for more data. + + + + + ao_packet_slave_start + + +void +ao_packet_slave_start(void); + + + This is available only on the slave side and starts a task + to listen for packet data. + + + + + ao_packet_slave_stop + + +void +ao_packet_slave_stop(void); + + + Disables the packet slave task, stopping the radio receiver. + + + + + ao_packet_slave_init + + +void +ao_packet_slave_init(void); + + + Adds the packet stdio functions to the stdio package so + that when packet slave mode is enabled, characters will + get send and received through the stdio functions. + + + + + ao_packet_master_init + + +void +ao_packet_master_init(void); + + + Adds the 'p' packet forward command to start packet mode. + + + + + +
-- cgit v1.2.3 From c7119c21baa9d4ca681975b8613ade6593f65577 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 24 Nov 2010 02:11:36 +1000 Subject: altosui: don't switch away from user selected tab --- ao-tools/altosui/AltosFlightUI.java | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 732f7395..b0cc521d 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -47,23 +47,17 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; - static final int tab_pad = 1; - static final int tab_ascent = 2; - static final int tab_descent = 3; - static final int tab_landed = 4; - - int cur_tab = 0; - boolean exit_on_close = false; - int which_tab(AltosState state) { + JComponent cur_tab = null; + JComponent which_tab(AltosState state) { if (state.state < Altos.ao_flight_boost) - return tab_pad; + return pad; if (state.state <= Altos.ao_flight_coast) - return tab_ascent; + return ascent; if (state.state <= Altos.ao_flight_main) - return tab_descent; - return tab_landed; + return descent; + return landed; } void stop_display() { @@ -90,24 +84,14 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - int tab = which_tab(state); + JComponent tab = which_tab(state); pad.show(state, crc_errors); ascent.show(state, crc_errors); descent.show(state, crc_errors); landed.show(state, crc_errors); if (tab != cur_tab) { - switch (tab) { - case tab_pad: - pane.setSelectedComponent(pad); - break; - case tab_ascent: - pane.setSelectedComponent(ascent); - break; - case tab_descent: - pane.setSelectedComponent(descent); - break; - case tab_landed: - pane.setSelectedComponent(landed); + if (cur_tab == pane.getSelectedComponent()) { + pane.setSelectedComponent(tab); } cur_tab = tab; } -- cgit v1.2.3 From 84cd5d42d8b5659463544fe2a400758b56478609 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 24 Nov 2010 02:13:32 +1000 Subject: altosui: sitemap uses rocket gps if no pad gps --- ao-tools/altosui/AltosSiteMap.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java index 80970605..d4a4cbf4 100644 --- a/ao-tools/altosui/AltosSiteMap.java +++ b/ao-tools/altosui/AltosSiteMap.java @@ -230,16 +230,19 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // if insufficient gps data, nothing to update if (state.gps == null) return; - if (state.pad_lat == 0 && state.pad_lon == 0) + if (!state.gps.locked && state.gps.nsat < 4) return; - if (!state.gps.locked) { - if (state.gps.nsat < 4) - return; - } if (!initialised) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; + if (state.pad_lat != 0 || state.pad_lon != 0) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; + } else if (state.gps.lat != 0 || state.gps.lon != 0) { + initMaps(state.gps.lat, state.gps.lon); + initialised = true; + } else { + return; + } } final Point2D.Double pt = pt(state.gps.lat, state.gps.lon); -- cgit v1.2.3 From 853b7112e34212040c4cb7289f9cfdb2f3ea9f90 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Nov 2010 18:53:18 -0700 Subject: merge Keith's AltosUI documention into "the big book" --- doc/Makefile | 4 +- doc/altosui-doc.xsl | 596 ------------------ doc/telemetrum-doc.xsl | 1629 ++++++++++++++++++++++++++++++++---------------- 3 files changed, 1099 insertions(+), 1130 deletions(-) delete mode 100644 doc/altosui-doc.xsl diff --git a/doc/Makefile b/doc/Makefile index 52934290..65917ea2 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,8 +2,8 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -HTML=telemetrum-doc.html altosui-doc.html altos.html -PDF=telemetrum-doc.pdf altosui-doc.pdf altos.pdf +HTML=telemetrum-doc.html altos.html +PDF=telemetrum-doc.pdf altos.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl diff --git a/doc/altosui-doc.xsl b/doc/altosui-doc.xsl deleted file mode 100644 index 4a1f43b5..00000000 --- a/doc/altosui-doc.xsl +++ /dev/null @@ -1,596 +0,0 @@ - - - - - AltosUI - Altos Metrum Graphical User Interface Manual - - - Bdale - Garbee - - - Keith - Packard - - - 2010 - Bdale Garbee and Keith Packard - - - - This document is released under the terms of the - - Creative Commons ShareAlike 3.0 - - license. - - - - - 0.1 - 19 November 2010 - Initial content - - - - - Introduction - - The AltosUI program provides a graphical user interface for - interacting with the Altus Metrum product family, including - TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, - configure TeleMetrum and TeleDongle devices and many other - tasks. The primary interface window provides a selection of - buttons, one for each major activity in the system. This manual - is split into chapters, each of which documents one of the tasks - provided from the top-level toolbar. - - - - Packet Command Mode - Controlling TeleMetrum Over The Radio Link - - One of the unique features of the Altos Metrum environment is - the ability to create a two way command link between TeleDongle - and TeleMetrum using the digital radio transceivers built into - each device. This allows you to interact with TeleMetrum from - afar, as if it were directly connected to the computer. - - - Any operation which can be performed with TeleMetrum - can either be done with TeleMetrum directly connected to - the computer via the USB cable, or through the packet - link. Simply select the appropriate TeleDongle device when - the list of devices is presented and AltosUI will use packet - command mode. - - - - - Save Flight Data—Recover flight data from the rocket without - opening it up. - - - - - Configure TeleMetrum—Reset apogee delays or main deploy - heights to respond to changing launch conditions. You can - also 'reboot' the TeleMetrum device. Use this to remotely - enable the flight computer by turning TeleMetrum on while - horizontal, then once the airframe is oriented for launch, - you can reboot TeleMetrum and have it restart in pad mode - without having to climb the scary ladder. - - - - - Fire Igniters—Test your deployment charges without snaking - wires out through holes in the airframe. Simply assembly the - rocket as if for flight with the apogee and main charges - loaded, then remotely command TeleMetrum to fire the - igniters. - - - - - Packet command mode uses the same RF channels as telemetry - mode. Configure the desired TeleDongle channel using the - flight monitor window channel selector and then close that - window before performing the desired operation. - - - TeleMetrum only enables packet command mode in 'idle' mode, so - make sure you have TeleMetrum lying horizontally when you turn - it on. Otherwise, TeleMetrum will start in 'pad' mode ready for - flight and will not be listening for command packets from TeleDongle. - - - When packet command mode is enabled, you can monitor the link - by watching the lights on the TeleDongle and TeleMetrum - devices. The red LED will flash each time TeleDongle or - TeleMetrum transmit a packet while the green LED will light up - on TeleDongle while it is waiting to receive a packet from - TeleMetrum. - - - - Monitor Flight - Receive, Record and Display Telemetry Data - - Selecting this item brings up a dialog box listing all of the - connected TeleDongle devices. When you choose one of these, - AltosUI will create a window to display telemetry data as - received by the selected TeleDongle device. - - - All telemetry data received are automatically recorded in - suitable log files. The name of the files includes the current - date and rocket serial and flight numbers. - - - The radio channel being monitored by the TeleDongle device is - displayed at the top of the window. You can configure the - channel by clicking on the channel box and selecting the desired - channel. AltosUI remembers the last channel selected for each - TeleDongle and selects that automatically the next time you use - that device. - - - Below the TeleDongle channel selector, the window contains a few - significant pieces of information about the TeleMetrum providing - the telemetry data stream: - - - - The TeleMetrum callsign - - - The TeleMetrum serial number - - - The flight number. Each TeleMetrum remembers how many - times it has flown. - - - - The rocket flight state. Each flight passes through several - states including Pad, Boost, Fast, Coast, Drogue, Main and - Landed. - - - - - The Received Signal Strength Indicator value. This lets - you know how strong a signal TeleDongle is receiving. The - radio inside TeleDongle operates down to about -99dBm; - weaker signals may not be receiveable. The packet link uses - error correction and detection techniques which prevent - incorrect data from being reported. - - - - - Finally, the largest portion of the window contains a set of - tabs, each of which contain some information about the rocket. - They're arranged in 'flight order' so that as the flight - progresses, the selected tab automatically switches to display - data relevant to the current state of the flight. You can select - other tabs at any time. The final 'table' tab contains all of - the telemetry data in one place. - -
- Launch Pad - - The 'Launch Pad' tab shows information used to decide when the - rocket is ready for flight. The first elements include red/green - indicators, if any of these is red, you'll want to evaluate - whether the rocket is ready to launch: - - - - Battery Voltage. This indicates whether the LiPo battery - powering the TeleMetrum has sufficient charge to last for - the duration of the flight. A value of more than - 3.7V is required for a 'GO' status. - - - - - Apogee Igniter Voltage. This indicates whether the apogee - igniter has continuity. If the igniter has a low - resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is - required for a 'GO' status. - - - - - Main Igniter Voltage. This indicates whether the main - igniter has continuity. If the igniter has a low - resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is - required for a 'GO' status. - - - - - GPS Locked. This indicates whether the GPS receiver is - currently able to compute position information. GPS requires - at least 4 satellites to compute an accurate position. - - - - - GPS Ready. This indicates whether GPS has reported at least - 10 consecutive positions without losing lock. This ensures - that the GPS receiver has reliable reception from the - satellites. - - - - - The LaunchPad tab also shows the computed launch pad position - and altitude, averaging many reported positions to improve the - accuracy of the fix. - - -
-
- Ascent - - This tab is shown during Boost, Fast and Coast - phases. The information displayed here helps monitor the - rocket as it heads towards apogee. - - - The height, speed and acceleration are shown along with the - maxium values for each of them. This allows you to quickly - answer the most commonly asked questions you'll hear during - flight. - - - The current latitude and longitude reported by the GPS are - also shown. Note that under high acceleration, these values - may not get updated as the GPS receiver loses position - fix. Once the rocket starts coasting, the receiver should - start reporting position again. - - - Finally, the current igniter voltages are reported as in the - Launch Pad tab. This can help diagnose deployment failures - caused by wiring which comes loose under high acceleration. - -
-
- Descent - - Once the rocket has reached apogee and (we hope) activated the - apogee charge, attention switches to tracking the rocket on - the way back to the ground, and for dual-deploy flights, - waiting for the main charge to fire. - - - To monitor whether the apogee charge operated correctly, the - current descent rate is reported along with the current - height. Good descent rates generally range from 15-30m/s. - - - To help locate the rocket in the sky, use the elevation and - bearing information to figure out where to look. Elevation is - in degrees above the horizon. Bearing is reported in degrees - relative to true north. Range can help figure out how big the - rocket will appear. Note that all of these values are relative - to the pad location. If the elevation is near 90°, the rocket - is over the pad, not over you. - - - Finally, the igniter voltages are reported in this tab as - well, both to monitor the main charge as well as to see what - the status of the apogee charge is. - -
-
- Landed - - Once the rocket is on the ground, attention switches to - recovery. While the radio signal is generally lost once the - rocket is on the ground, the last reported GPS position is - generally within a short distance of the actual landing location. - - - The last reported GPS position is reported both by - latitude and longitude as well as a bearing and distance from - the launch pad. The distance should give you a good idea of - whether you'll want to walk or hitch a ride. Take the reported - latitude and longitude and enter them into your handheld GPS - unit and have that compute a track to the landing location. - - - Finally, the maximum height, speed and acceleration reported - during the flight are displayed for your admiring observers. - -
-
- - Save Flight Data - - TeleMetrum records flight data to its internal flash memory. - This data is recorded at a much higher rate than the telemetry - system can handle, and is not subject to radio drop-outs. As - such, it provides a more complete and precise record of the - flight. The 'Save Flight Data' button allows you to read the - flash memory and write it to disk. - - - Clicking on the 'Save Flight Data' button brings up a list of - connected TeleMetrum and TeleDongle devices. If you select a - TeleMetrum device, the flight data will be downloaded from that - device directly. If you select a TeleDongle device, flight data - will be downloaded from a TeleMetrum device connected via the - packet command link to the specified TeleDongle. See the chapter - on Packet Command Mode for more information about this. - - - The filename for the data is computed automatically from the recorded - flight date, TeleMetrum serial number and flight number - information. - - - - Replay Flight - - Select this button and you are prompted to select a flight - record file, either a .telem file recording telemetry data or a - .eeprom file containing flight data saved from the TeleMetrum - flash memory. - - - Once a flight record is selected, the flight monitor interface - is displayed and the flight is re-enacted in real time. Check - the Monitor Flight chapter above to learn how this window operates. - - - - Graph Data - - This section should be written by AJ. - - - - Export Data - - This tool takes the raw data files and makes them available for - external analysis. When you select this button, you are prompted to select a flight - data file (either .eeprom or .telem will do, remember that - .eeprom files contain higher resolution and more continuous - data). Next, a second dialog appears which is used to select - where to write the resulting file. It has a selector to choose - between CSV and KML file formats. - -
- Comma Separated Value Format - - This is a text file containing the data in a form suitable for - import into a spreadsheet or other external data analysis - tool. The first few lines of the file contain the version and - configuration information from the TeleMetrum device, then - there is a single header line which labels all of the - fields. All of these lines start with a '#' character which - most tools can be configured to skip over. - - - The remaining lines of the file contain the data, with each - field separated by a comma and at least one space. All of - the sensor values are converted to standard units, with the - barometric data reported in both pressure, altitude and - height above pad units. - -
-
- Keyhole Markup Language (for Google Earth) - - This is the format used by - Googleearth to provide an overlay within that - application. With this, you can use Googleearth to see the - whole flight path in 3D. - -
-
- - Configure TeleMetrum - - Select this button and then select either a TeleMetrum or - TeleDongle Device from the list provided. Selecting a TeleDongle - device will use Packet Comamnd Mode to configure remote - TeleMetrum device. Learn how to use this in the Packet Command - Mode chapter. - - - The first few lines of the dialog provide information about the - connected TeleMetrum device, including the product name, - software version and hardware serial number. Below that are the - individual configuration entries. - - - At the bottom of the dialog, there are four buttons: - - - - - Save. This writes any changes to the TeleMetrum - configuration parameter block in flash memory. If you don't - press this button, any changes you make will be lost. - - - - - Reset. This resets the dialog to the most recently saved values, - erasing any changes you have made. - - - - - Reboot. This reboots the TeleMetrum device. Use this to - switch from idle to pad mode by rebooting once the rocket is - oriented for flight. - - - - - Close. This closes the dialog. Any unsaved changes will be - lost. - - - - - The rest of the dialog contains the parameters to be configured. - -
- Main Deploy Altitude - - This sets the altitude (above the recorded pad altitude) at - which the 'main' igniter will fire. The drop-down menu shows - some common values, but you can edit the text directly and - choose whatever you like. If the apogee charge fires below - this altitude, then the main charge will fire two seconds - after the apogee charge fires. - -
-
- Apogee Delay - - When flying redundant electronics, it's often important to - ensure that multiple apogee charges don't fire at precisely - the same time as that can overpressurize the apogee deployment - bay and cause a structural failure of the airframe. The Apogee - Delay parameter tells the flight computer to fire the apogee - charge a certain number of seconds after apogee has been - detected. - -
-
- Radio Channel - - This configures which of the 10 radio channels to use for both - telemetry and packet command mode. Note that if you set this - value via packet command mode, you will have to reconfigure - the TeleDongle channel before you will be able to use packet - command mode again. - -
-
- Radio Calibration - - The radios in every Altus Metrum device are calibrated at the - factory to ensure that they transmit and receive on the - specified frequency for each channel. You can adjust that - calibration by changing this value. To change the TeleDongle's - calibration, you must reprogram the unit completely. - -
-
- Callsign - - This sets the callsign included in each telemetry packet. Set this - as needed to conform to your local radio regulations. - -
-
- - Configure AltosUI - - This button presents a dialog so that you can configure the AltosUI global settings. - -
- Voice Settings - - AltosUI provides voice annoucements during flight so that you - can keep your eyes on the sky and still get information about - the current flight status. However, sometimes you don't want - to hear them. - - - - Enable—turns all voice announcements on and off - - - - Test Voice—Plays a short message allowing you to verify - that the audio systme is working and the volume settings - are reasonable - - - -
-
- Log Directory - - AltosUI logs all telemetry data and saves all TeleMetrum flash - data to this directory. This directory is also used as the - staring point when selecting data files for display or export. - - - Click on the directory name to bring up a directory choosing - dialog, select a new directory and click 'Select Directory' to - change where AltosUI reads and writes data files. - -
-
- Callsign - - This value is used in command packet mode and is transmitted - in each packet sent from TeleDongle and received from - TeleMetrum. It is not used in telemetry mode as that transmits - packets only from TeleMetrum to TeleDongle. Configure this - with the AltosUI operators callsign as needed to comply with - your local radio regulations. - -
-
- - Flash Image - - This reprograms any Altus Metrum device by using a TeleMetrum or - TeleDongle as a programming dongle. Please read the directions - for connecting the programming cable in the main TeleMetrum - manual before reading these instructions. - - - Once you have the programmer and target devices connected, - push the 'Flash Image' button. That will present a dialog box - listing all of the connected devices. Carefully select the - programmer device, not the device to be programmed. - - - Next, select the image to flash to the device. These are named - with the product name and firmware version. The file selector - will start in the directory containing the firmware included - with the AltosUI package. Navigate to the directory containing - the desired firmware if it isn't there. - - - Next, a small dialog containing the device serial number and - RF calibration values should appear. If these values are - incorrect (possibly due to a corrupted image in the device), - enter the correct values here. - - - Finally, a dialog containing a progress bar will follow the - programming process. - - - When programming is complete, the target device will - reboot. Note that if the target device is connected via USB, you - will have to unplug it and then plug it back in for the USB - connection to reset so that you can communicate with the device - again. - - - - Fire Igniter - - - -
\ No newline at end of file diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index b7963aec..6be23e7f 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -27,6 +27,11 @@ + + 0.3 + 23 November 2010 + New section on AltosUI mostly by Keith + 0.2 18 July 2010 @@ -118,12 +123,12 @@ When you have successfully installed the software suite (either from compiled source code or as the pre-built Debian package) you will have 10 or so executable programs all of which have names beginning - with 'ao-'. + with 'ao-'. ('ao-view' is the lone GUI-based program, the rest are command-line oriented.) You will also have man pages, that give you basic info - on each program. + on each program. You will also get this documentation in two file types in the doc/ -directory, telemetrum-doc.pdf and telemetrum-doc.html. + directory, telemetrum-doc.pdf and telemetrum-doc.html. Finally you will have a couple control files that allow the ao-view GUI-based program to appear in your menu of programs (under the 'Internet' category). @@ -133,7 +138,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. with using USB ports. The first thing you should try after getting both units plugged into to your computer's usb port(s) is to run 'ao-list' from a terminal-window to see what port-device-name each - device has been assigned by the operating system. + device has been assigned by the operating system. You will need this information to access the devices via their respective on-board firmware and data using other command line programs in the AltOS software suite. @@ -158,7 +163,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. Both TeleMetrum and TeleDongle share the concept of a two level command set in their firmware. - The first layer has several single letter commands. Once + The first layer has several single letter commands. Once you are using 'cu' (or 'cutecom') sending (typing) a '?' returns a full list of these commands. The second level are configuration sub-commands accessed @@ -177,7 +182,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. use 'N0CALL' which is cute, but not exactly legal! Spend a few minutes getting comfortable with the units, their firmware, and 'cu' (or possibly 'cutecom'). - For instance, try to send + For instance, try to send (type) a 'c r 2' and verify the channel change by sending a 'c s'. Verify you can connect and disconnect from the units while in your terminal program by sending the escape-disconnect mentioned above. @@ -250,7 +255,7 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. As for ao-view.... some things are in the menu but don't do anything very useful. The developers have stopped working on ao-view to focus on a new, cross-platform ground station program. So ao-view may or - may not be updated in the future. Mostly you just use + may not be updated in the future. Mostly you just use the Log and Device menus. It has a wonderful display of the incoming flight data and I am sure you will enjoy what it has to say to you once you enable the voice output! @@ -299,611 +304,1171 @@ directory, telemetrum-doc.pdf and telemetrum-doc.html. Live telemetry is written to file(s) whenever 'ao-view' is connected to the TeleDongle. The file area defaults to ~/altos but is easily changed using the menus in 'ao-view'. The files that - are written end in '.telem'. The after-flight + are written end in '.telem'. The after-flight data-dumped files will end in .eeprom and represent continuous data unlike the rf-linked .telem files that are subject to the turnarounds/data-packaging time slots in the half-duplex rf data path. See the above instructions on what and how to save the eeprom stored data after physically retrieving your TeleMetrum. Make sure to save - the on-board data after each flight, as the current firmware will - over-write any previous flight data during a new flight. + the on-board data after each flight, as the current firmware will + over-write any previous flight data during a new flight. + + +
+ + Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + + + + Handling Precautions + + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe with a + see-through plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to + "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + + Hardware Overview + + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. + + + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide and so may be the most familiar option. + You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. + + + + System Operation +
+ Firmware Modes + + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. + + + At power on, you will hear three beeps + ("S" in Morse code for startup) and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. + + + In flight or "pad" mode, TeleMetrum turns on the GPS system, + engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. + + + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. + + + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! + +
+
+ GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! + + + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. + +
+
+ Ground Testing + + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! + + + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. + + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. + +
+
+ Radio Link + + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we had to decide how to manage the + link. + + + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + + We don't use a 'normal packet radio' mode because they're just too + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had flights to above 21k feet AGL with good reception, and calculations + suggest we should be good to well over 40k feet AGL with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights! + +
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. + +
+ Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip on + your TeleMetrum board if you want the change to stay in place across reboots. + +
+
+ Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + Please note that the TeleMetrum apogee detection algorithm always + fires a fraction of a second *after* apogee. If you are also flying + an altimeter like the PerfectFlite MAWD, which only supports selecting + 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 + seconds delay and set the TeleMetrum to fire your backup 2 or 3 + seconds later to avoid any chance of both charges firing + simultaneously. We've flown several airframes this way quite happily, + including Keith's successful L3 cert.
- - - Specifications +
+ Main Deployment Altitude + + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. + + + To set the main deployment altitude, use the [FIXME] command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+
+ Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor. + +
+
+
+ + + AltosUI + + The AltosUI program provides a graphical user interface for + interacting with the Altus Metrum product family, including + TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, + configure TeleMetrum and TeleDongle devices and many other + tasks. The primary interface window provides a selection of + buttons, one for each major activity in the system. This manual + is split into chapters, each of which documents one of the tasks + provided from the top-level toolbar. + +
+ Packet Command Mode + Controlling TeleMetrum Over The Radio Link + + One of the unique features of the Altos Metrum environment is + the ability to create a two way command link between TeleDongle + and TeleMetrum using the digital radio transceivers built into + each device. This allows you to interact with TeleMetrum from + afar, as if it were directly connected to the computer. + + + Any operation which can be performed with TeleMetrum + can either be done with TeleMetrum directly connected to + the computer via the USB cable, or through the packet + link. Simply select the appropriate TeleDongle device when + the list of devices is presented and AltosUI will use packet + command mode. + - Recording altimeter for model rocketry. + Save Flight Data—Recover flight data from the rocket without + opening it up. - Supports dual deployment (can fire 2 ejection charges). + Configure TeleMetrum—Reset apogee delays or main deploy + heights to respond to changing launch conditions. You can + also 'reboot' the TeleMetrum device. Use this to remotely + enable the flight computer by turning TeleMetrum on while + horizontal, then once the airframe is oriented for launch, + you can reboot TeleMetrum and have it restart in pad mode + without having to climb the scary ladder. - 70cm ham-band transceiver for telemetry downlink. + Fire Igniters—Test your deployment charges without snaking + wires out through holes in the airframe. Simply assembly the + rocket as if for flight with the apogee and main charges + loaded, then remotely command TeleMetrum to fire the + igniters. + + + Packet command mode uses the same RF channels as telemetry + mode. Configure the desired TeleDongle channel using the + flight monitor window channel selector and then close that + window before performing the desired operation. + + + TeleMetrum only enables packet command mode in 'idle' mode, so + make sure you have TeleMetrum lying horizontally when you turn + it on. Otherwise, TeleMetrum will start in 'pad' mode ready for + flight and will not be listening for command packets from TeleDongle. + + + When packet command mode is enabled, you can monitor the link + by watching the lights on the TeleDongle and TeleMetrum + devices. The red LED will flash each time TeleDongle or + TeleMetrum transmit a packet while the green LED will light up + on TeleDongle while it is waiting to receive a packet from + TeleMetrum. + +
+
+ Monitor Flight + Receive, Record and Display Telemetry Data + + Selecting this item brings up a dialog box listing all of the + connected TeleDongle devices. When you choose one of these, + AltosUI will create a window to display telemetry data as + received by the selected TeleDongle device. + + + All telemetry data received are automatically recorded in + suitable log files. The name of the files includes the current + date and rocket serial and flight numbers. + + + The radio channel being monitored by the TeleDongle device is + displayed at the top of the window. You can configure the + channel by clicking on the channel box and selecting the desired + channel. AltosUI remembers the last channel selected for each + TeleDongle and selects that automatically the next time you use + that device. + + + Below the TeleDongle channel selector, the window contains a few + significant pieces of information about the TeleMetrum providing + the telemetry data stream: + + - - Barometric pressure sensor good to 45k feet MSL. - + The TeleMetrum callsign - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. + The TeleMetrum serial number + + + The flight number. Each TeleMetrum remembers how many + times it has flown. - On-board, integrated GPS receiver with 5hz update rate capability. + The rocket flight state. Each flight passes through several + states including Pad, Boost, Fast, Coast, Drogue, Main and + Landed. - On-board 1 megabyte non-volatile memory for flight data storage. + The Received Signal Strength Indicator value. This lets + you know how strong a signal TeleDongle is receiving. The + radio inside TeleDongle operates down to about -99dBm; + weaker signals may not be receiveable. The packet link uses + error correction and detection techniques which prevent + incorrect data from being reported. + + + Finally, the largest portion of the window contains a set of + tabs, each of which contain some information about the rocket. + They're arranged in 'flight order' so that as the flight + progresses, the selected tab automatically switches to display + data relevant to the current state of the flight. You can select + other tabs at any time. The final 'table' tab contains all of + the telemetry data in one place. + +
+ Launch Pad + + The 'Launch Pad' tab shows information used to decide when the + rocket is ready for flight. The first elements include red/green + indicators, if any of these is red, you'll want to evaluate + whether the rocket is ready to launch: + + + + Battery Voltage. This indicates whether the LiPo battery + powering the TeleMetrum has sufficient charge to last for + the duration of the flight. A value of more than + 3.7V is required for a 'GO' status. + + + + + Apogee Igniter Voltage. This indicates whether the apogee + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + Main Igniter Voltage. This indicates whether the main + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + GPS Locked. This indicates whether the GPS receiver is + currently able to compute position information. GPS requires + at least 4 satellites to compute an accurate position. + + + + + GPS Ready. This indicates whether GPS has reported at least + 10 consecutive positions without losing lock. This ensures + that the GPS receiver has reliable reception from the + satellites. + + + + + The LaunchPad tab also shows the computed launch pad position + and altitude, averaging many reported positions to improve the + accuracy of the fix. + + +
+
+ Ascent + + This tab is shown during Boost, Fast and Coast + phases. The information displayed here helps monitor the + rocket as it heads towards apogee. + + + The height, speed and acceleration are shown along with the + maxium values for each of them. This allows you to quickly + answer the most commonly asked questions you'll hear during + flight. + + + The current latitude and longitude reported by the GPS are + also shown. Note that under high acceleration, these values + may not get updated as the GPS receiver loses position + fix. Once the rocket starts coasting, the receiver should + start reporting position again. + + + Finally, the current igniter voltages are reported as in the + Launch Pad tab. This can help diagnose deployment failures + caused by wiring which comes loose under high acceleration. + +
+
+ Descent + + Once the rocket has reached apogee and (we hope) activated the + apogee charge, attention switches to tracking the rocket on + the way back to the ground, and for dual-deploy flights, + waiting for the main charge to fire. + + + To monitor whether the apogee charge operated correctly, the + current descent rate is reported along with the current + height. Good descent rates generally range from 15-30m/s. + + + To help locate the rocket in the sky, use the elevation and + bearing information to figure out where to look. Elevation is + in degrees above the horizon. Bearing is reported in degrees + relative to true north. Range can help figure out how big the + rocket will appear. Note that all of these values are relative + to the pad location. If the elevation is near 90°, the rocket + is over the pad, not over you. + + + Finally, the igniter voltages are reported in this tab as + well, both to monitor the main charge as well as to see what + the status of the apogee charge is. + +
+
+ Landed + + Once the rocket is on the ground, attention switches to + recovery. While the radio signal is generally lost once the + rocket is on the ground, the last reported GPS position is + generally within a short distance of the actual landing location. + + + The last reported GPS position is reported both by + latitude and longitude as well as a bearing and distance from + the launch pad. The distance should give you a good idea of + whether you'll want to walk or hitch a ride. Take the reported + latitude and longitude and enter them into your handheld GPS + unit and have that compute a track to the landing location. + + + Finally, the maximum height, speed and acceleration reported + during the flight are displayed for your admiring observers. + +
+
+
+ Save Flight Data + + TeleMetrum records flight data to its internal flash memory. + This data is recorded at a much higher rate than the telemetry + system can handle, and is not subject to radio drop-outs. As + such, it provides a more complete and precise record of the + flight. The 'Save Flight Data' button allows you to read the + flash memory and write it to disk. + + + Clicking on the 'Save Flight Data' button brings up a list of + connected TeleMetrum and TeleDongle devices. If you select a + TeleMetrum device, the flight data will be downloaded from that + device directly. If you select a TeleDongle device, flight data + will be downloaded from a TeleMetrum device connected via the + packet command link to the specified TeleDongle. See the chapter + on Packet Command Mode for more information about this. + + + The filename for the data is computed automatically from the recorded + flight date, TeleMetrum serial number and flight number + information. + +
+
+ Replay Flight + + Select this button and you are prompted to select a flight + record file, either a .telem file recording telemetry data or a + .eeprom file containing flight data saved from the TeleMetrum + flash memory. + + + Once a flight record is selected, the flight monitor interface + is displayed and the flight is re-enacted in real time. Check + the Monitor Flight chapter above to learn how this window operates. + +
+
+ Graph Data + + This section should be written by AJ. + +
+
+ Export Data + + This tool takes the raw data files and makes them available for + external analysis. When you select this button, you are prompted to select a flight + data file (either .eeprom or .telem will do, remember that + .eeprom files contain higher resolution and more continuous + data). Next, a second dialog appears which is used to select + where to write the resulting file. It has a selector to choose + between CSV and KML file formats. + +
+ Comma Separated Value Format + + This is a text file containing the data in a form suitable for + import into a spreadsheet or other external data analysis + tool. The first few lines of the file contain the version and + configuration information from the TeleMetrum device, then + there is a single header line which labels all of the + fields. All of these lines start with a '#' character which + most tools can be configured to skip over. + + + The remaining lines of the file contain the data, with each + field separated by a comma and at least one space. All of + the sensor values are converted to standard units, with the + barometric data reported in both pressure, altitude and + height above pad units. + +
+
+ Keyhole Markup Language (for Google Earth) + + This is the format used by + Googleearth to provide an overlay within that + application. With this, you can use Googleearth to see the + whole flight path in 3D. + +
+
+
+ Configure TeleMetrum + + Select this button and then select either a TeleMetrum or + TeleDongle Device from the list provided. Selecting a TeleDongle + device will use Packet Comamnd Mode to configure remote + TeleMetrum device. Learn how to use this in the Packet Command + Mode chapter. + + + The first few lines of the dialog provide information about the + connected TeleMetrum device, including the product name, + software version and hardware serial number. Below that are the + individual configuration entries. + + + At the bottom of the dialog, there are four buttons: + + - USB interface for battery charging, configuration, and data recovery. + Save. This writes any changes to the TeleMetrum + configuration parameter block in flash memory. If you don't + press this button, any changes you make will be lost. - Fully integrated support for LiPo rechargeable batteries. + Reset. This resets the dialog to the most recently saved values, + erasing any changes you have made. - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. + Reboot. This reboots the TeleMetrum device. Use this to + switch from idle to pad mode by rebooting once the rocket is + oriented for flight. - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + Close. This closes the dialog. Any unsaved changes will be + lost. - - - Handling Precautions - - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. - - - The Lithium Polymer rechargeable batteries used with TeleMetrum have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. - - - The TeleMetrum barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe with a - see-through plastic payload bay. - - - The TeleMetrum barometric sensor sampling port must be able to - "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. - - - As with all other rocketry electronics, TeleMetrum must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. - - - - Hardware Overview - - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. - - - A typical TeleMetrum installation using the on-board GPS antenna and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. - - - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] - - - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar option. - You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. - - - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. - - - - Operation + + The rest of the dialog contains the parameters to be configured. +
- Firmware Modes - - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. - - - At power on, you will hear three beeps - ("S" in Morse code for startup) and then a pause while - TeleMetrum completes initialization and self tests, and decides which - mode to enter next. - - - In flight or "pad" mode, TeleMetrum turns on the GPS system, - engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when TeleMetrum is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! + Main Deploy Altitude + + This sets the altitude (above the recorded pad altitude) at + which the 'main' igniter will fire. The drop-down menu shows + some common values, but you can edit the text directly and + choose whatever you like. If the apogee charge fires below + this altitude, then the main charge will fire two seconds + after the apogee charge fires.
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. + Apogee Delay + + When flying redundant electronics, it's often important to + ensure that multiple apogee charges don't fire at precisely + the same time as that can overpressurize the apogee deployment + bay and cause a structural failure of the airframe. The Apogee + Delay parameter tells the flight computer to fire the apogee + charge a certain number of seconds after apogee has been + detected.
- Ground Testing + Radio Channel - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! + This configures which of the 10 radio channels to use for both + telemetry and packet command mode. Note that if you set this + value via packet command mode, you will have to reconfigure + the TeleDongle channel before you will be able to use packet + command mode again. +
+
+ Radio Calibration - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. + The radios in every Altus Metrum device are calibrated at the + factory to ensure that they transmit and receive on the + specified frequency for each channel. You can adjust that + calibration by changing this value. To change the TeleDongle's + calibration, you must reprogram the unit completely. +
+
+ Callsign - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. + This sets the callsign included in each telemetry packet. Set this + as needed to conform to your local radio regulations.
+
+
+ Configure AltosUI + + This button presents a dialog so that you can configure the AltosUI global settings. +
- Radio Link - - The chip our boards are based on incorporates an RF transceiver, but - it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we had to decide how to manage the - link. - - - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which - allows us to use the RF link to configure the rocket, do things like - ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only - transmits and doesn't listen at all. That's because we want to put - ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract - data later... - - - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a - Gaussian filter before they go into the modulator to limit the - transmitted bandwidth. When combined with the hardware forward error - correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had flights to above 21k feet AGL with good reception, and calculations - suggest we should be good to well over 40k feet AGL with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! + Voice Settings + + AltosUI provides voice annoucements during flight so that you + can keep your eyes on the sky and still get information about + the current flight status. However, sometimes you don't want + to hear them. + + + Enable—turns all voice announcements on and off + + + + Test Voice—Plays a short message allowing you to verify + that the audio systme is working and the volume settings + are reasonable + + +
- Configurable Parameters + Log Directory - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. + AltosUI logs all telemetry data and saves all TeleMetrum flash + data to this directory. This directory is also used as the + staring point when selecting data files for display or export. + + + Click on the directory name to bring up a directory choosing + dialog, select a new directory and click 'Select Directory' to + change where AltosUI reads and writes data files. -
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip on - your TeleMetrum board if you want the change to stay in place across reboots. - -
-
- Apogee Delay - - Apogee delay is the number of seconds after TeleMetrum detects flight - apogee that the drogue charge should be fired. In most cases, this - should be left at the default of 0. However, if you are flying - redundant electronics such as for an L3 certification, you may wish - to set one of your altimeters to a positive delay so that both - primary and backup pyrotechnic charges do not fire simultaneously. - - - To set the apogee delay, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - Please note that the TeleMetrum apogee detection algorithm always - fires a fraction of a second *after* apogee. If you are also flying - an altimeter like the PerfectFlite MAWD, which only supports selecting - 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 - seconds delay and set the TeleMetrum to fire your backup 2 or 3 - seconds later to avoid any chance of both charges firing - simultaneously. We've flown several airframes this way quite happily, - including Keith's successful L3 cert. - -
-
- Main Deployment Altitude - - By default, TeleMetrum will fire the main deployment charge at an - elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this - to suit. In particular, if you are flying two altimeters, you may - wish to set the - deployment elevation for the backup altimeter to be something lower - than the primary so that both pyrotechnic charges don't fire - simultaneously. - - - To set the main deployment altitude, use the [FIXME] command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
- Calibration + Callsign - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. + This value is used in command packet mode and is transmitted + in each packet sent from TeleDongle and received from + TeleMetrum. It is not used in telemetry mode as that transmits + packets only from TeleMetrum to TeleDongle. Configure this + with the AltosUI operators callsign as needed to comply with + your local radio regulations. -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 Mhz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Accelerometer - - The accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - -
- - - Using Altus Metrum Products +
+
+ Flash Image + + This reprograms any Altus Metrum device by using a TeleMetrum or + TeleDongle as a programming dongle. Please read the directions + for connecting the programming cable in the main TeleMetrum + manual before reading these instructions. + + + Once you have the programmer and target devices connected, + push the 'Flash Image' button. That will present a dialog box + listing all of the connected devices. Carefully select the + programmer device, not the device to be programmed. + + + Next, select the image to flash to the device. These are named + with the product name and firmware version. The file selector + will start in the directory containing the firmware included + with the AltosUI package. Navigate to the directory containing + the desired firmware if it isn't there. + + + Next, a small dialog containing the device serial number and + RF calibration values should appear. If these values are + incorrect (possibly due to a corrupted image in the device), + enter the correct values here. + + + Finally, a dialog containing a progress bar will follow the + programming process. + + + When programming is complete, the target device will + reboot. Note that if the target device is connected via USB, you + will have to unplug it and then plug it back in for the USB + connection to reset so that you can communicate with the device + again. + +
+
+ Fire Igniter + + +
+
+ + Using Altus Metrum Products +
+ Being Legal + + First off, in the US, you need an [amateur radio license](../Radio) or + other authorization to legally operate the radio transmitters that are part + of our products. +
- Being Legal + In the Rocket - First off, in the US, you need an [amateur radio license](../Radio) or - other authorization to legally operate the radio transmitters that are part - of our products. + In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. -
- In the Rocket - - In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. - - - By default, we ship TeleMetrum with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, - which is opaque to RF signals, you may choose to have an SMA connector - installed so that you can run a coaxial cable to an antenna mounted - elsewhere in the rocket. - -
-
- On the Ground - - To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our [TeleDongle](../TeleDongle) units. The - TeleDongle in turn plugs directly into the USB port on a notebook - computer. Because TeleDongle looks like a simple serial port, your computer - does not require special device drivers... just plug it in. - - - Right now, all of our application software is written for Linux. However, - because we understand that many people run Windows or MacOS, we are working - on a new ground station program written in Java that should work on all - operating systems. - - - After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the - TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo - battery, so you'll want one of those anyway... the same cable used by lots - of digital cameras and other modern electronic stuff will work fine. - - - If your rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket - position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. - - - You may also enjoy having a ham radio "HT" that covers the 70cm band... you - can use that with your antenna to direction-find the rocket on the ground - the same way you can use a Walston or Beeline tracker. This can be handy - if the rocket is hiding in sage brush or a tree, or if the last GPS position - doesn't get you close enough because the rocket dropped into a canyon, or - the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-7R at launches. - - - So, to recap, on the ground the hardware you'll need includes: - - - an antenna and feedline - - - a TeleDongle - - - a notebook computer - - - optionally, a handheld GPS receiver - - - optionally, an HT or receiver covering 435 Mhz - - - - - The best hand-held commercial directional antennas we've found for radio - direction finding rockets are from - - Arrow Antennas. - - The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. - -
-
- Data Analysis - - Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum - board. Once this data is on your computer, our postflight tools make it - easy to quickly get to the numbers everyone wants, like apogee altitude, - max acceleration, and max velocity. You can also generate and view a - standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file - useable with Google Maps and Google Earth for visualizing the flight path - in two or three dimensions! - - - Our ultimate goal is to emit a set of files for each flight that can be - published as a web page per flight, or just viewed on your local disk with - a web browser. - -
-
- Future Plans - - In the future, we intend to offer "companion boards" for the rocket that will - plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. - - - We are also working on the design of a hand-held ground terminal that will - allow monitoring the rocket's status, collecting data during flight, and - logging data after flight without the need for a notebook computer on the - flight line. Particularly since it is so difficult to read most notebook - screens in direct sunlight, we think this will be a great thing to have. - - - Because all of our work is open, both the hardware designs and the software, - if you have some great idea for an addition to the current Altus Metrum family, - feel free to dive in and help! Or let us know what you'd like to see that - we aren't already working on, and maybe we'll get excited about it too... - -
- - How GPS Works - + On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our [TeleDongle](../TeleDongle) units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + Right now, all of our application software is written for Linux. However, + because we understand that many people run Windows or MacOS, we are working + on a new ground station program written in Java that should work on all + operating systems. + - Placeholder. + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the Yaesu VX-7R at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT.
- - - +
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. + +
+
+ Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + + + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too... + +
+
+
+ + How GPS Works + + + Placeholder. + +
+
+
+ -- cgit v1.2.3 From f1892b137b1de3d6caf0293bd40ed5c3e4948066 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Nov 2010 18:58:11 -0700 Subject: lose the placeholder on how GPS works, as it's going to be a while before I tackle that, if ever. --- doc/telemetrum-doc.xsl | 8 -------- 1 file changed, 8 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 6be23e7f..5c3e4c38 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -1461,14 +1461,6 @@ -
- - How GPS Works - - - Placeholder. - -
-- cgit v1.2.3 From d873dc28f0752aeb58a6263e42bdd5b9095bd392 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 18:56:46 -0800 Subject: altos: remove unused variable from ao_igniter The 'status' variable used to hold a reported status value from the igniter after firing, but we ignore that now. Signed-off-by: Keith Packard --- src/ao_ignite.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 58d340d9..f2b15dd2 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -101,7 +101,6 @@ void ao_igniter(void) { __xdata enum ao_ignter igniter; - __xdata enum ao_igniter_status status; ao_config_get(); for (;;) { -- cgit v1.2.3 From 54468e5dc567aaac5c5c20e921859b7cec28bb88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 18:57:49 -0800 Subject: altos: Don't abort radio transmissions with ao_radio_abort We only want to abort pending radio reception to release the radio for other use, or to change the radio channel. Let radio transmission proceed. This fixes a problem with using packet mode to configure the radio channel; if the packet transmission is aborted, the TM ends up wedged. Signed-off-by: Keith Packard --- src/ao_radio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index 3fb4afd7..b2105ff8 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,8 +432,11 @@ ao_radio_rdf(int ms) void ao_radio_abort(void) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); + /* Only abort if a task is waiting to receive data */ + if (RFST == RFST_SRX) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } } void -- cgit v1.2.3 From 3b9db8c82d26a6a2e43d4ca40742fc1bdc502380 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 19:02:54 -0800 Subject: altos: Make radio test command careful with the radio mutex. Remember whether the radio test mode is on or off and don't try to do either of them twice to prevent the mutex from being acquired or released twice. Signed-off-by: Keith Packard --- src/ao_radio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index b2105ff8..67d5f6ba 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -452,26 +452,29 @@ void ao_radio_test(void) { uint8_t mode = 2; + static __xdata radio_on; ao_cmd_white(); if (ao_cmd_lex_c != '\n') { ao_cmd_decimal(); mode = (uint8_t) ao_cmd_lex_u32; } mode++; - if (mode & 2) { + if ((mode & 2) && !radio_on) { ao_set_monitor(0); ao_packet_slave_stop(); ao_radio_get(); RFST = RFST_STX; + radio_on = 1; } if (mode == 3) { printf ("Hit a character to stop..."); flush(); getchar(); putchar('\n'); } - if (mode & 1) { + if ((mode & 1) && radio_on) { ao_radio_idle(); ao_radio_put(); + radio_on = 0; } } -- cgit v1.2.3 From ed7cf7d262fcf7c0c677c2fb981582b571de9e5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 19:04:55 -0800 Subject: altosui: Make AltosSerial.flush_input keep reading while non-empty Flushing the input buffer can take a while, especially over the packet link. Keep reading while stuff is appearing on the reply queue. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosSerial.java | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index ab74486b..8a6ad05e 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -114,16 +114,20 @@ public class AltosSerial implements Runnable { 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(); - } + boolean got_some; + do { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + got_some = !reply_queue.isEmpty(); + synchronized(this) { + if (!"VERSION".startsWith(line) && + !line.startsWith("VERSION")) + line = ""; + reply_queue.clear(); + } + } while (got_some); } public String get_reply() throws InterruptedException { -- cgit v1.2.3 From 6cd9be22f06f21d12ee2f668989d83d3c61d14c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 19:08:07 -0800 Subject: altosui: New AltosSerial.set_radio function sets channel/call Use this anytime you need to set the device radio channel and call sign, either for telemetry reception or packet mode origination. This uses the saved callsign and per-device radio channel number. Do not use this when opening a telemetrum as there won't be a saved channel number. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 7 +++---- ao-tools/altosui/AltosEepromDownload.java | 7 +++---- ao-tools/altosui/AltosFlightUI.java | 1 - ao-tools/altosui/AltosIgnite.java | 7 +++---- ao-tools/altosui/AltosSerial.java | 9 +++++++-- ao-tools/altosui/AltosTelemetryReader.java | 6 ++---- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 6bda20d8..52dbfd79 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -109,9 +109,8 @@ public class AltosConfig implements Runnable, ActionListener { void start_serial() throws InterruptedException { if (remote) { - serial_line.set_channel(AltosPreferences.channel(device.getSerial())); - serial_line.set_callsign(AltosPreferences.callsign()); - serial_line.printf("p\n"); + serial_line.set_radio(); + serial_line.printf("p\nE 0\n"); serial_line.flush_input(); } } @@ -128,7 +127,7 @@ public class AltosConfig implements Runnable, ActionListener { start_serial(); serial_line.printf("c s\nv\n"); for (;;) { - String line = serial_line.get_reply(1000); + String line = serial_line.get_reply(5000); if (line == null) throw new TimeoutException(); get_int(line, "serial-number", serial); diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java index fb5dcfc0..02fc36f2 100644 --- a/ao-tools/altosui/AltosEepromDownload.java +++ b/ao-tools/altosui/AltosEepromDownload.java @@ -97,7 +97,7 @@ public class AltosEepromDownload implements Runnable { /* Pull the serial number out of the version information */ for (;;) { - String line = serial_line.get_reply(1000); + String line = serial_line.get_reply(5000); if (line == null) throw new TimeoutException(); @@ -127,7 +127,7 @@ public class AltosEepromDownload implements Runnable { any_valid = false; monitor.set_value(state_names[state], state, block - state_block); for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(1000); + String line = serial_line.get_reply(5000); if (line == null) throw new TimeoutException(); int[] values = ParseHex(line); @@ -216,8 +216,7 @@ public class AltosEepromDownload implements Runnable { public void run () { if (remote) { - serial_line.set_channel(AltosPreferences.channel(device.getSerial())); - serial_line.set_callsign(AltosPreferences.callsign()); + serial_line.set_radio(); serial_line.printf("p\nE 0\n"); serial_line.flush_input(); } diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java index 732f7395..24d25bd7 100644 --- a/ao-tools/altosui/AltosFlightUI.java +++ b/ao-tools/altosui/AltosFlightUI.java @@ -148,7 +148,6 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { public void actionPerformed(ActionEvent e) { int channel = channels.getSelectedIndex(); reader.set_channel(channel); - AltosPreferences.set_channel(serial, channel); } }); c.gridx = 0; diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java index 8e92ec1b..75c0a17a 100644 --- a/ao-tools/altosui/AltosIgnite.java +++ b/ao-tools/altosui/AltosIgnite.java @@ -35,9 +35,8 @@ public class AltosIgnite { private void start_serial() throws InterruptedException { if (remote) { - serial.set_channel(AltosPreferences.channel(device.getSerial())); - serial.set_callsign(AltosPreferences.callsign()); - serial.printf("~\np\n"); + serial.set_radio(); + serial.printf("p\nE 0\n"); serial.flush_input(); } } @@ -100,7 +99,7 @@ public class AltosIgnite { start_serial(); serial.printf("t\n"); for (;;) { - String line = serial.get_reply(1000); + String line = serial.get_reply(5000); if (line == null) throw new TimeoutException(); if (get_string(line, "Igniter: drogue Status: ", status_name)) diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java index 8a6ad05e..b19143e5 100644 --- a/ao-tools/altosui/AltosSerial.java +++ b/ao-tools/altosui/AltosSerial.java @@ -198,13 +198,18 @@ public class AltosSerial implements Runnable { devices_opened.add(device.getPath()); } altos = libaltos.altos_open(device); - if (altos == null) + if (altos == null) { + close(); throw new FileNotFoundException(device.toShortString()); + } input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); + set_monitor(false); flush_output(); - set_monitor(monitor_mode); + } + + public void set_radio() { set_channel(AltosPreferences.channel(device.getSerial())); set_callsign(AltosPreferences.callsign()); } diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java index de5f50e9..6c5a9397 100644 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ b/ao-tools/altosui/AltosTelemetryReader.java @@ -44,10 +44,7 @@ class AltosTelemetryReader extends AltosFlightReader { void set_channel(int channel) { serial.set_channel(channel); - } - - void set_callsign(String callsign) { - serial.set_callsign(callsign); + AltosPreferences.set_channel(device.getSerial(), channel); } public AltosTelemetryReader (AltosDevice in_device) @@ -58,6 +55,7 @@ class AltosTelemetryReader extends AltosFlightReader { name = device.toShortString(); telem = new LinkedBlockingQueue(); + serial.set_radio(); serial.add_monitor(telem); } } -- cgit v1.2.3 From f3233985a132e1d660e6df12d0056b6729f16faf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 19:09:31 -0800 Subject: altosui: Disable radio configation over packet link. Attempting to configure the radio over the packet link will only end up confusing the user, so disable it. This also works around a bug in older TM code which would lock up when trying to do this. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 8 +++++--- ao-tools/altosui/AltosConfigUI.java | 6 +++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index 52dbfd79..b1acd410 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -149,7 +149,7 @@ public class AltosConfig implements Runnable, ActionListener { } void init_ui () throws InterruptedException, TimeoutException { - config_ui = new AltosConfigUI(owner); + config_ui = new AltosConfigUI(owner, remote); config_ui.addActionListener(this); set_ui(); } @@ -191,8 +191,10 @@ public class AltosConfig implements Runnable, ActionListener { start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); - serial_line.printf("c r %d\n", radio_channel.get()); - serial_line.printf("c f %d\n", radio_calibration.get()); + if (!remote) { + serial_line.printf("c r %d\n", radio_channel.get()); + serial_line.printf("c f %d\n", radio_calibration.get()); + } serial_line.printf("c c %s\n", callsign.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java index ca89f58d..cfa5d7b9 100644 --- a/ao-tools/altosui/AltosConfigUI.java +++ b/ao-tools/altosui/AltosConfigUI.java @@ -98,7 +98,7 @@ public class AltosConfigUI } /* Build the UI using a grid bag */ - public AltosConfigUI(JFrame in_owner) { + public AltosConfigUI(JFrame in_owner, boolean remote) { super (in_owner, "Configure TeleMetrum", false); owner = in_owner; @@ -244,6 +244,8 @@ public class AltosConfigUI radio_channel_value = new JComboBox(radio_channel_values); radio_channel_value.setEditable(false); radio_channel_value.addItemListener(this); + if (remote) + radio_channel_value.setEnabled(false); pane.add(radio_channel_value, c); /* Radio Calibration */ @@ -267,6 +269,8 @@ public class AltosConfigUI c.ipady = 5; radio_calibration_value = new JTextField(String.format("%d", 1186611)); radio_calibration_value.getDocument().addDocumentListener(this); + if (remote) + radio_calibration_value.setEnabled(false); pane.add(radio_calibration_value, c); /* Callsign */ -- cgit v1.2.3 From 7d90e2f6009e060fb59c519f7e564483a7ca6872 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 20:17:44 -0800 Subject: altosui: Let people fire igniters that don't read as 'ready' This provides for igniter testing with LEDs or other materials that don't look like regular igniters. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosIgniteUI.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java index 0207e39f..d542729c 100644 --- a/ao-tools/altosui/AltosIgniteUI.java +++ b/ao-tools/altosui/AltosIgniteUI.java @@ -145,13 +145,11 @@ public class AltosIgniteUI if (cmd.equals("apogee") && apogee.isSelected()) { main.setSelected(false); - if (apogee_status == AltosIgnite.Ready) - arm.setEnabled(true); + arm.setEnabled(true); } if (cmd.equals("main") && main.isSelected()) { apogee.setSelected(false); - if (main_status == AltosIgnite.Ready) - arm.setEnabled(true); + arm.setEnabled(true); } if (cmd.equals("arm")) { -- cgit v1.2.3 From 7a50837ea0d92db3f469f197ec8210aee22aa143 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 10:55:18 -0800 Subject: altosui: Make sure packet mode is turned off when the connection fails When the packet connection times out, turn packet mode off when closing the serial port. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosConfig.java | 10 +++++++++- ao-tools/altosui/AltosIgnite.java | 9 +++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java index b1acd410..1c42870f 100644 --- a/ao-tools/altosui/AltosConfig.java +++ b/ao-tools/altosui/AltosConfig.java @@ -74,7 +74,7 @@ public class AltosConfig implements Runnable, ActionListener { string_ref product; string_ref callsign; AltosConfigUI config_ui; - + boolean serial_started; boolean get_int(String line, String label, int_ref x) { if (line.startsWith(label)) { @@ -108,6 +108,7 @@ public class AltosConfig implements Runnable, ActionListener { } void start_serial() throws InterruptedException { + serial_started = true; if (remote) { serial_line.set_radio(); serial_line.printf("p\nE 0\n"); @@ -116,6 +117,9 @@ public class AltosConfig implements Runnable, ActionListener { } void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; if (remote) { serial_line.printf("~"); serial_line.flush_output(); @@ -160,6 +164,10 @@ public class AltosConfig implements Runnable, ActionListener { device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); + try { + stop_serial(); + } catch (InterruptedException ie) { + } serial_line.close(); serial_line = null; } diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java index 75c0a17a..3cbd8a75 100644 --- a/ao-tools/altosui/AltosIgnite.java +++ b/ao-tools/altosui/AltosIgnite.java @@ -24,6 +24,7 @@ public class AltosIgnite { AltosDevice device; AltosSerial serial; boolean remote; + boolean serial_started; final static int None = 0; final static int Apogee = 1; final static int Main = 2; @@ -34,6 +35,7 @@ public class AltosIgnite { final static int Open = 3; private void start_serial() throws InterruptedException { + serial_started = true; if (remote) { serial.set_radio(); serial.printf("p\nE 0\n"); @@ -42,6 +44,9 @@ public class AltosIgnite { } private void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; if (serial == null) return; if (remote) { @@ -148,6 +153,10 @@ public class AltosIgnite { } public void close() { + try { + stop_serial(); + } catch (InterruptedException ie) { + } serial.close(); serial = null; } -- cgit v1.2.3 From 357826aa9c7b42c59f5d52b8eb016d73b6da0c7f Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 25 Nov 2010 09:07:34 +1000 Subject: docs: Document altosui "Graph Data" button --- doc/telemetrum-doc.xsl | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 5c3e4c38..8f554d88 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -1087,7 +1087,30 @@
Graph Data - This section should be written by AJ. + Select this button and you are prompted to select a flight + record file, either a .telem file recording telemetry data or a + .eeprom file containing flight data saved from the TeleMetrum + flash memory. + + + Once a flight record is selected, the acceleration (blue), + velocity (green) and altitude (red) of the flight are plotted and + displayed, measured in metric units. + + + The graph can be zoomed into a particular area by clicking and + dragging down and to the right. Once zoomed, the graph can be + reset by clicking and dragging up and to the left. Holding down + control and clicking and dragging allows the graph to be panned. + The right mouse button causes a popup menu to be displayed, giving + you the option save or print the plot. + + + Note that telemetry files will generally produce poor graphs + due to the lower sampling rate and missed telemetry packets, + and will also often have significant amounts of data received + while the rocket was waiting on the pad. Use saved flight data + for graphing where possible.
-- cgit v1.2.3 From 3fbefb3eea981d34a09496cf8abf0119de2e35bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 14:57:57 -0800 Subject: Move altosui to the top level, placing libaltos inside it. Signed-off-by: Keith Packard --- altosui/.gitignore | 19 + .../01altosui-contents.xml | 1 + .../01altosui.xml | 1 + .../AltOS Package Configuration.pmdoc/index.xml | 1 + altosui/Altos.java | 218 +++++ altosui/AltosAscent.java | 335 +++++++ altosui/AltosCRCException.java | 26 + altosui/AltosCSV.java | 252 +++++ altosui/AltosCSVUI.java | 108 ++ altosui/AltosChannelMenu.java | 44 + altosui/AltosConfig.java | 295 ++++++ altosui/AltosConfigUI.java | 466 +++++++++ altosui/AltosConfigureUI.java | 187 ++++ altosui/AltosConvert.java | 192 ++++ altosui/AltosDataChooser.java | 79 ++ altosui/AltosDataPoint.java | 29 + altosui/AltosDataPointReader.java | 72 ++ altosui/AltosDebug.java | 267 +++++ altosui/AltosDescent.java | 353 +++++++ altosui/AltosDevice.java | 170 ++++ altosui/AltosDeviceDialog.java | 164 ++++ altosui/AltosDisplayThread.java | 249 +++++ altosui/AltosEepromDownload.java | 285 ++++++ altosui/AltosEepromIterable.java | 423 ++++++++ altosui/AltosEepromMonitor.java | 176 ++++ altosui/AltosEepromRecord.java | 115 +++ altosui/AltosFile.java | 44 + altosui/AltosFlash.java | 344 +++++++ altosui/AltosFlashUI.java | 218 +++++ altosui/AltosFlightDisplay.java | 24 + altosui/AltosFlightInfoTableModel.java | 84 ++ altosui/AltosFlightReader.java | 38 + altosui/AltosFlightStatus.java | 154 +++ altosui/AltosFlightStatusTableModel.java | 61 ++ altosui/AltosFlightUI.java | 221 +++++ altosui/AltosGPS.java | 215 ++++ altosui/AltosGraph.java | 25 + altosui/AltosGraphTime.java | 233 +++++ altosui/AltosGraphUI.java | 274 ++++++ altosui/AltosGreatCircle.java | 100 ++ altosui/AltosHexfile.java | 252 +++++ altosui/AltosIgnite.java | 173 ++++ altosui/AltosIgniteUI.java | 317 ++++++ altosui/AltosInfoTable.java | 190 ++++ altosui/AltosKML.java | 169 ++++ altosui/AltosLanded.java | 212 ++++ altosui/AltosLed.java | 54 + altosui/AltosLights.java | 73 ++ altosui/AltosLine.java | 30 + altosui/AltosLog.java | 115 +++ altosui/AltosPad.java | 269 +++++ altosui/AltosParse.java | 79 ++ altosui/AltosPreferences.java | 205 ++++ altosui/AltosReader.java | 28 + altosui/AltosRecord.java | 219 +++++ altosui/AltosRecordIterable.java | 34 + altosui/AltosReplayReader.java | 57 ++ altosui/AltosRomconfig.java | 147 +++ altosui/AltosRomconfigUI.java | 186 ++++ altosui/AltosSerial.java | 253 +++++ altosui/AltosSerialInUseException.java | 28 + altosui/AltosSerialMonitor.java | 22 + altosui/AltosSiteMap.java | 388 ++++++++ altosui/AltosSiteMapCache.java | 103 ++ altosui/AltosSiteMapTile.java | 112 +++ altosui/AltosState.java | 197 ++++ altosui/AltosTelemetry.java | 143 +++ altosui/AltosTelemetryIterable.java | 82 ++ altosui/AltosTelemetryReader.java | 61 ++ altosui/AltosUI.app/Contents/Info.plist | 38 + .../AltosUI.app/Contents/MacOS/JavaApplicationStub | Bin 0 -> 61296 bytes altosui/AltosUI.app/Contents/PkgInfo | 1 + .../Contents/Resources/AltosUIIcon.icns | Bin 0 -> 129010 bytes altosui/AltosUI.java | 405 ++++++++ altosui/AltosVoice.java | 95 ++ altosui/AltosWriter.java | 32 + altosui/GrabNDrag.java | 54 + altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi | 84 ++ .../Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe | Bin 0 -> 51831 bytes altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c | 704 ++++++++++++++ altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp | 110 +++ altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw | 29 + altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt | 141 +++ altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf | 137 +++ altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys | Bin 0 -> 30464 bytes altosui/Instdrv/NSIS/Plugins/InstDrv.dll | Bin 0 -> 6656 bytes altosui/Makefile-standalone | 184 ++++ altosui/Makefile.am | 272 ++++++ altosui/altos-windows.nsi | 113 +++ altosui/altosui-fat | 4 + altosui/altosui.1 | 46 + altosui/altusmetrum.jpg | Bin 0 -> 72868 bytes altosui/libaltos/.gitignore | 12 + altosui/libaltos/Makefile-standalone | 126 +++ altosui/libaltos/Makefile.am | 41 + altosui/libaltos/altos.dll | Bin 0 -> 31765 bytes altosui/libaltos/cjnitest.c | 43 + altosui/libaltos/libaltos.c | 1028 ++++++++++++++++++++ altosui/libaltos/libaltos.dylib | Bin 0 -> 54176 bytes altosui/libaltos/libaltos.h | 102 ++ altosui/libaltos/libaltos.i0 | 5 + ao-tools/Makefile.am | 2 +- ao-tools/altosui/.gitignore | 19 - .../01altosui-contents.xml | 1 - .../01altosui.xml | 1 - .../AltOS Package Configuration.pmdoc/index.xml | 1 - ao-tools/altosui/Altos.java | 218 ----- ao-tools/altosui/AltosAscent.java | 335 ------- ao-tools/altosui/AltosCRCException.java | 26 - ao-tools/altosui/AltosCSV.java | 252 ----- ao-tools/altosui/AltosCSVUI.java | 108 -- ao-tools/altosui/AltosChannelMenu.java | 44 - ao-tools/altosui/AltosConfig.java | 295 ------ ao-tools/altosui/AltosConfigUI.java | 466 --------- ao-tools/altosui/AltosConfigureUI.java | 187 ---- ao-tools/altosui/AltosConvert.java | 192 ---- ao-tools/altosui/AltosDataChooser.java | 79 -- ao-tools/altosui/AltosDataPoint.java | 29 - ao-tools/altosui/AltosDataPointReader.java | 72 -- ao-tools/altosui/AltosDebug.java | 267 ----- ao-tools/altosui/AltosDescent.java | 353 ------- ao-tools/altosui/AltosDevice.java | 170 ---- ao-tools/altosui/AltosDeviceDialog.java | 164 ---- ao-tools/altosui/AltosDisplayThread.java | 249 ----- ao-tools/altosui/AltosEepromDownload.java | 285 ------ ao-tools/altosui/AltosEepromIterable.java | 423 -------- ao-tools/altosui/AltosEepromMonitor.java | 176 ---- ao-tools/altosui/AltosEepromRecord.java | 115 --- ao-tools/altosui/AltosFile.java | 44 - ao-tools/altosui/AltosFlash.java | 344 ------- ao-tools/altosui/AltosFlashUI.java | 218 ----- ao-tools/altosui/AltosFlightDisplay.java | 24 - ao-tools/altosui/AltosFlightInfoTableModel.java | 84 -- ao-tools/altosui/AltosFlightReader.java | 38 - ao-tools/altosui/AltosFlightStatus.java | 154 --- ao-tools/altosui/AltosFlightStatusTableModel.java | 61 -- ao-tools/altosui/AltosFlightUI.java | 221 ----- ao-tools/altosui/AltosGPS.java | 215 ---- ao-tools/altosui/AltosGraph.java | 25 - ao-tools/altosui/AltosGraphTime.java | 233 ----- ao-tools/altosui/AltosGraphUI.java | 274 ------ ao-tools/altosui/AltosGreatCircle.java | 100 -- ao-tools/altosui/AltosHexfile.java | 252 ----- ao-tools/altosui/AltosIgnite.java | 173 ---- ao-tools/altosui/AltosIgniteUI.java | 317 ------ ao-tools/altosui/AltosInfoTable.java | 190 ---- ao-tools/altosui/AltosKML.java | 169 ---- ao-tools/altosui/AltosLanded.java | 212 ---- ao-tools/altosui/AltosLed.java | 54 - ao-tools/altosui/AltosLights.java | 73 -- ao-tools/altosui/AltosLine.java | 30 - ao-tools/altosui/AltosLog.java | 115 --- ao-tools/altosui/AltosPad.java | 269 ----- ao-tools/altosui/AltosParse.java | 79 -- ao-tools/altosui/AltosPreferences.java | 205 ---- ao-tools/altosui/AltosReader.java | 28 - ao-tools/altosui/AltosRecord.java | 219 ----- ao-tools/altosui/AltosRecordIterable.java | 34 - ao-tools/altosui/AltosReplayReader.java | 57 -- ao-tools/altosui/AltosRomconfig.java | 147 --- ao-tools/altosui/AltosRomconfigUI.java | 186 ---- ao-tools/altosui/AltosSerial.java | 253 ----- ao-tools/altosui/AltosSerialInUseException.java | 28 - ao-tools/altosui/AltosSerialMonitor.java | 22 - ao-tools/altosui/AltosSiteMap.java | 388 -------- ao-tools/altosui/AltosSiteMapCache.java | 103 -- ao-tools/altosui/AltosSiteMapTile.java | 112 --- ao-tools/altosui/AltosState.java | 197 ---- ao-tools/altosui/AltosTelemetry.java | 143 --- ao-tools/altosui/AltosTelemetryIterable.java | 82 -- ao-tools/altosui/AltosTelemetryReader.java | 61 -- ao-tools/altosui/AltosUI.app/Contents/Info.plist | 38 - .../AltosUI.app/Contents/MacOS/JavaApplicationStub | Bin 61296 -> 0 bytes ao-tools/altosui/AltosUI.app/Contents/PkgInfo | 1 - .../Contents/Resources/AltosUIIcon.icns | Bin 129010 -> 0 bytes ao-tools/altosui/AltosUI.java | 405 -------- ao-tools/altosui/AltosVoice.java | 95 -- ao-tools/altosui/AltosWriter.java | 32 - ao-tools/altosui/GrabNDrag.java | 54 - .../Instdrv/NSIS/Contrib/InstDrv/Example.nsi | 84 -- .../Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe | Bin 51831 -> 0 bytes .../altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c | 704 -------------- .../Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp | 110 --- .../Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw | 29 - .../Instdrv/NSIS/Contrib/InstDrv/Readme.txt | 141 --- .../Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf | 137 --- .../Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys | Bin 30464 -> 0 bytes ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll | Bin 6656 -> 0 bytes ao-tools/altosui/Makefile-standalone | 184 ---- ao-tools/altosui/Makefile.am | 271 ------ ao-tools/altosui/altos-windows.nsi | 113 --- ao-tools/altosui/altosui-fat | 4 - ao-tools/altosui/altosui.1 | 46 - ao-tools/altosui/altusmetrum.jpg | Bin 72868 -> 0 bytes ao-tools/libaltos/.gitignore | 12 - ao-tools/libaltos/Makefile-standalone | 126 --- ao-tools/libaltos/Makefile.am | 41 - ao-tools/libaltos/altos.dll | Bin 31765 -> 0 bytes ao-tools/libaltos/cjnitest.c | 43 - ao-tools/libaltos/libaltos.c | 1028 -------------------- ao-tools/libaltos/libaltos.dylib | Bin 54176 -> 0 bytes ao-tools/libaltos/libaltos.h | 102 -- ao-tools/libaltos/libaltos.i0 | 5 - configure.ac | 4 +- 204 files changed, 14569 insertions(+), 14568 deletions(-) create mode 100644 altosui/.gitignore create mode 100644 altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml create mode 100644 altosui/AltOS Package Configuration.pmdoc/01altosui.xml create mode 100644 altosui/AltOS Package Configuration.pmdoc/index.xml create mode 100644 altosui/Altos.java create mode 100644 altosui/AltosAscent.java create mode 100644 altosui/AltosCRCException.java create mode 100644 altosui/AltosCSV.java create mode 100644 altosui/AltosCSVUI.java create mode 100644 altosui/AltosChannelMenu.java create mode 100644 altosui/AltosConfig.java create mode 100644 altosui/AltosConfigUI.java create mode 100644 altosui/AltosConfigureUI.java create mode 100644 altosui/AltosConvert.java create mode 100644 altosui/AltosDataChooser.java create mode 100644 altosui/AltosDataPoint.java create mode 100644 altosui/AltosDataPointReader.java create mode 100644 altosui/AltosDebug.java create mode 100644 altosui/AltosDescent.java create mode 100644 altosui/AltosDevice.java create mode 100644 altosui/AltosDeviceDialog.java create mode 100644 altosui/AltosDisplayThread.java create mode 100644 altosui/AltosEepromDownload.java create mode 100644 altosui/AltosEepromIterable.java create mode 100644 altosui/AltosEepromMonitor.java create mode 100644 altosui/AltosEepromRecord.java create mode 100644 altosui/AltosFile.java create mode 100644 altosui/AltosFlash.java create mode 100644 altosui/AltosFlashUI.java create mode 100644 altosui/AltosFlightDisplay.java create mode 100644 altosui/AltosFlightInfoTableModel.java create mode 100644 altosui/AltosFlightReader.java create mode 100644 altosui/AltosFlightStatus.java create mode 100644 altosui/AltosFlightStatusTableModel.java create mode 100644 altosui/AltosFlightUI.java create mode 100644 altosui/AltosGPS.java create mode 100644 altosui/AltosGraph.java create mode 100644 altosui/AltosGraphTime.java create mode 100644 altosui/AltosGraphUI.java create mode 100644 altosui/AltosGreatCircle.java create mode 100644 altosui/AltosHexfile.java create mode 100644 altosui/AltosIgnite.java create mode 100644 altosui/AltosIgniteUI.java create mode 100644 altosui/AltosInfoTable.java create mode 100644 altosui/AltosKML.java create mode 100644 altosui/AltosLanded.java create mode 100644 altosui/AltosLed.java create mode 100644 altosui/AltosLights.java create mode 100644 altosui/AltosLine.java create mode 100644 altosui/AltosLog.java create mode 100644 altosui/AltosPad.java create mode 100644 altosui/AltosParse.java create mode 100644 altosui/AltosPreferences.java create mode 100644 altosui/AltosReader.java create mode 100644 altosui/AltosRecord.java create mode 100644 altosui/AltosRecordIterable.java create mode 100644 altosui/AltosReplayReader.java create mode 100644 altosui/AltosRomconfig.java create mode 100644 altosui/AltosRomconfigUI.java create mode 100644 altosui/AltosSerial.java create mode 100644 altosui/AltosSerialInUseException.java create mode 100644 altosui/AltosSerialMonitor.java create mode 100644 altosui/AltosSiteMap.java create mode 100644 altosui/AltosSiteMapCache.java create mode 100644 altosui/AltosSiteMapTile.java create mode 100644 altosui/AltosState.java create mode 100644 altosui/AltosTelemetry.java create mode 100644 altosui/AltosTelemetryIterable.java create mode 100644 altosui/AltosTelemetryReader.java create mode 100644 altosui/AltosUI.app/Contents/Info.plist create mode 100755 altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub create mode 100644 altosui/AltosUI.app/Contents/PkgInfo create mode 100644 altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns create mode 100644 altosui/AltosUI.java create mode 100644 altosui/AltosVoice.java create mode 100644 altosui/AltosWriter.java create mode 100644 altosui/GrabNDrag.java create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf create mode 100644 altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys create mode 100644 altosui/Instdrv/NSIS/Plugins/InstDrv.dll create mode 100644 altosui/Makefile-standalone create mode 100644 altosui/Makefile.am create mode 100644 altosui/altos-windows.nsi create mode 100755 altosui/altosui-fat create mode 100644 altosui/altosui.1 create mode 100644 altosui/altusmetrum.jpg create mode 100644 altosui/libaltos/.gitignore create mode 100644 altosui/libaltos/Makefile-standalone create mode 100644 altosui/libaltos/Makefile.am create mode 100755 altosui/libaltos/altos.dll create mode 100644 altosui/libaltos/cjnitest.c create mode 100644 altosui/libaltos/libaltos.c create mode 100755 altosui/libaltos/libaltos.dylib create mode 100644 altosui/libaltos/libaltos.h create mode 100644 altosui/libaltos/libaltos.i0 delete mode 100644 ao-tools/altosui/.gitignore delete mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml delete mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml delete mode 100644 ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml delete mode 100644 ao-tools/altosui/Altos.java delete mode 100644 ao-tools/altosui/AltosAscent.java delete mode 100644 ao-tools/altosui/AltosCRCException.java delete mode 100644 ao-tools/altosui/AltosCSV.java delete mode 100644 ao-tools/altosui/AltosCSVUI.java delete mode 100644 ao-tools/altosui/AltosChannelMenu.java delete mode 100644 ao-tools/altosui/AltosConfig.java delete mode 100644 ao-tools/altosui/AltosConfigUI.java delete mode 100644 ao-tools/altosui/AltosConfigureUI.java delete mode 100644 ao-tools/altosui/AltosConvert.java delete mode 100644 ao-tools/altosui/AltosDataChooser.java delete mode 100644 ao-tools/altosui/AltosDataPoint.java delete mode 100644 ao-tools/altosui/AltosDataPointReader.java delete mode 100644 ao-tools/altosui/AltosDebug.java delete mode 100644 ao-tools/altosui/AltosDescent.java delete mode 100644 ao-tools/altosui/AltosDevice.java delete mode 100644 ao-tools/altosui/AltosDeviceDialog.java delete mode 100644 ao-tools/altosui/AltosDisplayThread.java delete mode 100644 ao-tools/altosui/AltosEepromDownload.java delete mode 100644 ao-tools/altosui/AltosEepromIterable.java delete mode 100644 ao-tools/altosui/AltosEepromMonitor.java delete mode 100644 ao-tools/altosui/AltosEepromRecord.java delete mode 100644 ao-tools/altosui/AltosFile.java delete mode 100644 ao-tools/altosui/AltosFlash.java delete mode 100644 ao-tools/altosui/AltosFlashUI.java delete mode 100644 ao-tools/altosui/AltosFlightDisplay.java delete mode 100644 ao-tools/altosui/AltosFlightInfoTableModel.java delete mode 100644 ao-tools/altosui/AltosFlightReader.java delete mode 100644 ao-tools/altosui/AltosFlightStatus.java delete mode 100644 ao-tools/altosui/AltosFlightStatusTableModel.java delete mode 100644 ao-tools/altosui/AltosFlightUI.java delete mode 100644 ao-tools/altosui/AltosGPS.java delete mode 100644 ao-tools/altosui/AltosGraph.java delete mode 100644 ao-tools/altosui/AltosGraphTime.java delete mode 100644 ao-tools/altosui/AltosGraphUI.java delete mode 100644 ao-tools/altosui/AltosGreatCircle.java delete mode 100644 ao-tools/altosui/AltosHexfile.java delete mode 100644 ao-tools/altosui/AltosIgnite.java delete mode 100644 ao-tools/altosui/AltosIgniteUI.java delete mode 100644 ao-tools/altosui/AltosInfoTable.java delete mode 100644 ao-tools/altosui/AltosKML.java delete mode 100644 ao-tools/altosui/AltosLanded.java delete mode 100644 ao-tools/altosui/AltosLed.java delete mode 100644 ao-tools/altosui/AltosLights.java delete mode 100644 ao-tools/altosui/AltosLine.java delete mode 100644 ao-tools/altosui/AltosLog.java delete mode 100644 ao-tools/altosui/AltosPad.java delete mode 100644 ao-tools/altosui/AltosParse.java delete mode 100644 ao-tools/altosui/AltosPreferences.java delete mode 100644 ao-tools/altosui/AltosReader.java delete mode 100644 ao-tools/altosui/AltosRecord.java delete mode 100644 ao-tools/altosui/AltosRecordIterable.java delete mode 100644 ao-tools/altosui/AltosReplayReader.java delete mode 100644 ao-tools/altosui/AltosRomconfig.java delete mode 100644 ao-tools/altosui/AltosRomconfigUI.java delete mode 100644 ao-tools/altosui/AltosSerial.java delete mode 100644 ao-tools/altosui/AltosSerialInUseException.java delete mode 100644 ao-tools/altosui/AltosSerialMonitor.java delete mode 100644 ao-tools/altosui/AltosSiteMap.java delete mode 100644 ao-tools/altosui/AltosSiteMapCache.java delete mode 100644 ao-tools/altosui/AltosSiteMapTile.java delete mode 100644 ao-tools/altosui/AltosState.java delete mode 100644 ao-tools/altosui/AltosTelemetry.java delete mode 100644 ao-tools/altosui/AltosTelemetryIterable.java delete mode 100644 ao-tools/altosui/AltosTelemetryReader.java delete mode 100644 ao-tools/altosui/AltosUI.app/Contents/Info.plist delete mode 100755 ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub delete mode 100644 ao-tools/altosui/AltosUI.app/Contents/PkgInfo delete mode 100644 ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns delete mode 100644 ao-tools/altosui/AltosUI.java delete mode 100644 ao-tools/altosui/AltosVoice.java delete mode 100644 ao-tools/altosui/AltosWriter.java delete mode 100644 ao-tools/altosui/GrabNDrag.java delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys delete mode 100644 ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll delete mode 100644 ao-tools/altosui/Makefile-standalone delete mode 100644 ao-tools/altosui/Makefile.am delete mode 100644 ao-tools/altosui/altos-windows.nsi delete mode 100755 ao-tools/altosui/altosui-fat delete mode 100644 ao-tools/altosui/altosui.1 delete mode 100644 ao-tools/altosui/altusmetrum.jpg delete mode 100644 ao-tools/libaltos/.gitignore delete mode 100644 ao-tools/libaltos/Makefile-standalone delete mode 100644 ao-tools/libaltos/Makefile.am delete mode 100755 ao-tools/libaltos/altos.dll delete mode 100644 ao-tools/libaltos/cjnitest.c delete mode 100644 ao-tools/libaltos/libaltos.c delete mode 100755 ao-tools/libaltos/libaltos.dylib delete mode 100644 ao-tools/libaltos/libaltos.h delete mode 100644 ao-tools/libaltos/libaltos.i0 diff --git a/altosui/.gitignore b/altosui/.gitignore new file mode 100644 index 00000000..89be1d53 --- /dev/null +++ b/altosui/.gitignore @@ -0,0 +1,19 @@ +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 diff --git a/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml new file mode 100644 index 00000000..18e00fe4 --- /dev/null +++ b/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/altosui/AltOS Package Configuration.pmdoc/01altosui.xml new file mode 100644 index 00000000..6170931b --- /dev/null +++ b/altosui/AltOS Package Configuration.pmdoc/01altosui.xml @@ -0,0 +1 @@ +org.altusmetrum.altosUi.AltosUI.pkg0.7AltosUI.app/Applications/AltosUI.appinstallTo.pathinstallFrom.isRelativeTypeversionparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/altosui/AltOS Package Configuration.pmdoc/index.xml b/altosui/AltOS Package Configuration.pmdoc/index.xml new file mode 100644 index 00000000..fabe54a6 --- /dev/null +++ b/altosui/AltOS Package Configuration.pmdoc/index.xml @@ -0,0 +1 @@ +AltOS UI/Users/keithp/altos/ao-tools/altosui/AltosUI.pkgorg.altusmetrumInstall AltOS User Interfacealtusmetrum.jpg01altosui.xmlproperties.anywhereDomainproperties.titleproperties.customizeOptiondescriptionproperties.userDomainproperties.systemDomain \ No newline at end of file diff --git a/altosui/Altos.java b/altosui/Altos.java new file mode 100644 index 00000000..8ee94e04 --- /dev/null +++ b/altosui/Altos.java @@ -0,0 +1,218 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import java.text.*; + +public class Altos { + /* EEProm command letters */ + static final int AO_LOG_FLIGHT = 'F'; + static final int AO_LOG_SENSOR = 'A'; + static final int AO_LOG_TEMP_VOLT = 'T'; + static final int AO_LOG_DEPLOY = 'D'; + static final int AO_LOG_STATE = 'S'; + static final int AO_LOG_GPS_TIME = 'G'; + static final int AO_LOG_GPS_LAT = 'N'; + static final int AO_LOG_GPS_LON = 'W'; + static final int AO_LOG_GPS_ALT = 'H'; + static final int AO_LOG_GPS_SAT = 'V'; + static final int AO_LOG_GPS_DATE = 'Y'; + + /* Added for header fields in eeprom files */ + static final int AO_LOG_CONFIG_VERSION = 1000; + static final int AO_LOG_MAIN_DEPLOY = 1001; + static final int AO_LOG_APOGEE_DELAY = 1002; + static final int AO_LOG_RADIO_CHANNEL = 1003; + static final int AO_LOG_CALLSIGN = 1004; + static final int AO_LOG_ACCEL_CAL = 1005; + static final int AO_LOG_RADIO_CAL = 1006; + static final int AO_LOG_MANUFACTURER = 1007; + static final int AO_LOG_PRODUCT = 1008; + static final int AO_LOG_SERIAL_NUMBER = 1009; + static final int AO_LOG_SOFTWARE_VERSION = 1010; + + /* Added to flag invalid records */ + static final int AO_LOG_INVALID = -1; + + /* Flight state numbers and names */ + static final int ao_flight_startup = 0; + static final int ao_flight_idle = 1; + static final int ao_flight_pad = 2; + static final int ao_flight_boost = 3; + static final int ao_flight_fast = 4; + static final int ao_flight_coast = 5; + static final int ao_flight_drogue = 6; + static final int ao_flight_main = 7; + static final int ao_flight_landed = 8; + static final int ao_flight_invalid = 9; + + static HashMap string_to_state = new HashMap(); + + static boolean map_initialized = false; + + static final int tab_elt_pad = 5; + + static final Font label_font = new Font("Dialog", Font.PLAIN, 22); + static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); + static final Font status_font = new Font("SansSerif", Font.BOLD, 24); + + static final int text_width = 16; + + static void initialize_map() + { + string_to_state.put("startup", ao_flight_startup); + string_to_state.put("idle", ao_flight_idle); + string_to_state.put("pad", ao_flight_pad); + string_to_state.put("boost", ao_flight_boost); + string_to_state.put("fast", ao_flight_fast); + string_to_state.put("coast", ao_flight_coast); + string_to_state.put("drogue", ao_flight_drogue); + string_to_state.put("main", ao_flight_main); + string_to_state.put("landed", ao_flight_landed); + string_to_state.put("invalid", ao_flight_invalid); + map_initialized = true; + } + + static String[] state_to_string = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + static public int state(String state) { + if (!map_initialized) + initialize_map(); + if (string_to_state.containsKey(state)) + return string_to_state.get(state); + return ao_flight_invalid; + } + + static public String state_name(int state) { + if (state < 0 || state_to_string.length <= state) + return "invalid"; + return state_to_string[state]; + } + + static final int AO_GPS_VALID = (1 << 4); + static final int AO_GPS_RUNNING = (1 << 5); + 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; + } + + static String replace_extension(String input, String extension) { + int dot = input.lastIndexOf("."); + if (dot > 0) + input = input.substring(0,dot); + return input.concat(extension); + } +} diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java new file mode 100644 index 00000000..64bdcf30 --- /dev/null +++ b/altosui/AltosAscent.java @@ -0,0 +1,335 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosAscent extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + + public class AscentStatus { + JLabel label; + JTextField value; + AltosLights lights; + + void show(AltosState state, int crc_errors) {} + void reset() { + value.setText(""); + lights.set(false); + } + + public AscentStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.gridwidth = 2; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + } + } + + public class AscentValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + public AscentValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.gridwidth = 2; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + public class AscentValueHold { + JLabel label; + JTextField value; + JTextField max_value; + double max; + + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + max_value.setText(""); + max = 0; + } + + void show(String format, double v) { + value.setText(String.format(format, v)); + if (v > max) { + max_value.setText(String.format(format, v)); + max = v; + } + } + public AscentValueHold (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + max_value = new JTextField(Altos.text_width); + max_value.setFont(Altos.value_font); + max_value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 3; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(max_value, c); + add(max_value); + } + } + + + class Height extends AscentValueHold { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.height); + } + public Height (GridBagLayout layout, int y) { + super (layout, y, "Height"); + } + } + + Height height; + + class Speed extends AscentValueHold { + void show (AltosState state, int crc_errors) { + double speed = state.speed; + if (!state.ascent) + speed = state.baro_speed; + show("%6.0f m/s", speed); + } + public Speed (GridBagLayout layout, int y) { + super (layout, y, "Speed"); + } + } + + Speed speed; + + class Accel extends AscentValueHold { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s²", state.acceleration); + } + public Accel (GridBagLayout layout, int y) { + super (layout, y, "Acceleration"); + } + } + + Accel accel; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Apogee extends AscentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends AscentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + + class Lat extends AscentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lat,"N", "S")); + else + value.setText("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends AscentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lon,"E", "W")); + else + value.setText("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + public void reset() { + lat.reset(); + lon.reset(); + main.reset(); + apogee.reset(); + height.reset(); + speed.reset(); + accel.reset(); + } + + public void show(AltosState state, int crc_errors) { + lat.show(state, crc_errors); + lon.show(state, crc_errors); + height.show(state, crc_errors); + main.show(state, crc_errors); + apogee.show(state, crc_errors); + speed.show(state, crc_errors); + accel.show(state, crc_errors); + } + + public void labels(GridBagLayout layout, int y) { + GridBagConstraints c; + JLabel cur, max; + + cur = new JLabel("Current"); + cur.setFont(Altos.label_font); + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + layout.setConstraints(cur, c); + add(cur); + + max = new JLabel("Maximum"); + max.setFont(Altos.label_font); + c.gridx = 3; c.gridy = y; + layout.setConstraints(max, c); + add(max); + } + + public AltosAscent() { + layout = new GridBagLayout(); + + setLayout(layout); + + /* Elements in ascent display: + * + * lat + * lon + * height + */ + labels(layout, 0); + height = new Height(layout, 1); + speed = new Speed(layout, 2); + accel = new Accel(layout, 3); + lat = new Lat(layout, 4); + lon = new Lon(layout, 5); + apogee = new Apogee(layout, 6); + main = new Main(layout, 7); + } +} diff --git a/altosui/AltosCRCException.java b/altosui/AltosCRCException.java new file mode 100644 index 00000000..4a529bcf --- /dev/null +++ b/altosui/AltosCRCException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + } +} diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java new file mode 100644 index 00000000..df98b2b4 --- /dev/null +++ b/altosui/AltosCSV.java @@ -0,0 +1,252 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.*; + +public class AltosCSV implements AltosWriter { + File name; + PrintStream out; + boolean header_written; + boolean seen_boost; + int boost_tick; + LinkedList pad_records; + AltosState state; + + static final int ALTOS_CSV_VERSION = 2; + + /* Version 2 format: + * + * General info + * version number + * serial number + * flight number + * callsign + * time (seconds since boost) + * rssi + * link quality + * + * Flight status + * state + * state name + * + * Basic sensors + * acceleration (m/s²) + * pressure (mBar) + * altitude (m) + * height (m) + * accelerometer speed (m/s) + * barometer speed (m/s) + * temp (°C) + * battery (V) + * drogue (V) + * main (V) + * + * GPS data + * connected (1/0) + * locked (1/0) + * nsat (used for solution) + * latitude (°) + * longitude (°) + * altitude (m) + * year (e.g. 2010) + * month (1-12) + * day (1-31) + * 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) + * hdop + * + * GPS Sat data + * C/N0 data for all 32 valid SDIDs + */ + + void write_general_header() { + out.printf("version,serial,flight,call,time,rssi,lqi"); + } + + void write_general(AltosRecord record) { + out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d", + ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign, + (double) record.time, + record.rssi, + record.status & 0x7f); + } + + void write_flight_header() { + out.printf("state,state_name"); + } + + void write_flight(AltosRecord record) { + 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.raw_pressure(), + record.raw_altitude(), + record.raw_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,hdop"); + } + + 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,%6.1f", + 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, + gps.hdop); + } + + void write_gps_sat_header() { + for(int i = 1; i <= 32; i++) { + out.printf("sat%02d", i); + if (i != 32) + out.printf(","); + } + } + + void write_gps_sat(AltosRecord record) { + AltosGPS gps = record.gps; + for(int i = 1; i <= 32; i++) { + int c_n0 = 0; + if (gps != null && gps.cc_gps_sat != null) { + for(int j = 0; j < gps.cc_gps_sat.length; j++) + if (gps.cc_gps_sat[j].svid == i) { + c_n0 = gps.cc_gps_sat[j].c_n0; + break; + } + } + out.printf ("%3d", c_n0); + if (i != 32) + out.printf(","); + } + } + + 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(","); write_gps_sat_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(","); + write_gps_sat(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; + } + 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(AltosRecordIterable iterable) { + iterable.write_comments(out()); + for (AltosRecord r : iterable) + write(r); + } + + public AltosCSV(File in_name) throws FileNotFoundException { + name = in_name; + out = new PrintStream(name); + pad_records = new LinkedList(); + } + + public AltosCSV(String in_string) throws FileNotFoundException { + this(new File(in_string)); + } +} diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java new file mode 100644 index 00000000..e1b6002d --- /dev/null +++ b/altosui/AltosCSVUI.java @@ -0,0 +1,108 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosCSVUI + extends JDialog + implements ActionListener +{ + JFileChooser csv_chooser; + JPanel accessory; + JComboBox combo_box; + AltosRecordIterable iterable; + AltosWriter writer; + + static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; + + void set_default_file() { + File current = csv_chooser.getSelectedFile(); + String current_name = current.getName(); + String new_name = null; + String selected = (String) combo_box.getSelectedItem(); + + if (selected.contains("CSV")) + new_name = Altos.replace_extension(current_name, ".csv"); + else if (selected.contains("KML")) + new_name = Altos.replace_extension(current_name, ".kml"); + if (new_name != null) + csv_chooser.setSelectedFile(new File(new_name)); + } + + public void actionPerformed(ActionEvent e) { + if (e.getActionCommand().equals("comboBoxChanged")) + set_default_file(); + } + + public AltosCSVUI(JFrame frame, AltosRecordIterable in_iterable, File source_file) { + iterable = in_iterable; + csv_chooser = new JFileChooser(source_file); + + accessory = new JPanel(); + accessory.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.weightx = 1; + c.weighty = 0; + c.insets = new Insets (4, 4, 4, 4); + + JLabel accessory_label = new JLabel("Export File Type"); + c.gridx = 0; + c.gridy = 0; + accessory.add(accessory_label, c); + + combo_box = new JComboBox(combo_box_items); + combo_box.addActionListener(this); + c.gridx = 0; + c.gridy = 1; + accessory.add(combo_box, c); + + csv_chooser.setAccessory(accessory); + csv_chooser.setSelectedFile(source_file); + set_default_file(); + int ret = csv_chooser.showSaveDialog(frame); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = csv_chooser.getSelectedFile(); + String type = (String) combo_box.getSelectedItem(); + try { + if (type.contains("CSV")) + writer = new AltosCSV(file); + else + writer = new AltosKML(file); + writer.write(iterable); + writer.close(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + file.getName(), + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + } +} diff --git a/altosui/AltosChannelMenu.java b/altosui/AltosChannelMenu.java new file mode 100644 index 00000000..abbb86f4 --- /dev/null +++ b/altosui/AltosChannelMenu.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosChannelMenu extends JComboBox implements ActionListener { + int channel; + + public AltosChannelMenu(int current_channel) { + + channel = current_channel; + + for (int c = 0; c <= 9; c++) + addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1)); + setSelectedIndex(channel); + setMaximumRowCount(10); + } + +} diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java new file mode 100644 index 00000000..1c42870f --- /dev/null +++ b/altosui/AltosConfig.java @@ -0,0 +1,295 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosConfig implements Runnable, ActionListener { + + class int_ref { + int value; + + public int get() { + return value; + } + public void set(int i) { + value = i; + } + public int_ref(int i) { + value = i; + } + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref(String i) { + value = i; + } + } + + JFrame owner; + AltosDevice device; + AltosSerial serial_line; + boolean remote; + Thread config_thread; + int_ref serial; + int_ref main_deploy; + int_ref apogee_delay; + int_ref radio_channel; + int_ref radio_calibration; + string_ref version; + string_ref product; + string_ref callsign; + AltosConfigUI config_ui; + boolean serial_started; + + boolean get_int(String line, String label, int_ref x) { + if (line.startsWith(label)) { + try { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) { + int i = Integer.parseInt(tokens[0]); + x.set(i); + return true; + } + } catch (NumberFormatException ne) { + } + } + return false; + } + + boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + void start_serial() throws InterruptedException { + serial_started = true; + if (remote) { + serial_line.set_radio(); + serial_line.printf("p\nE 0\n"); + serial_line.flush_input(); + } + } + + void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + if (remote) { + serial_line.printf("~"); + serial_line.flush_output(); + } + } + + void get_data() throws InterruptedException, TimeoutException { + try { + start_serial(); + serial_line.printf("c s\nv\n"); + for (;;) { + String line = serial_line.get_reply(5000); + if (line == null) + throw new TimeoutException(); + get_int(line, "serial-number", serial); + get_int(line, "Main deploy:", main_deploy); + get_int(line, "Apogee delay:", apogee_delay); + get_int(line, "Radio channel:", radio_channel); + get_int(line, "Radio cal:", radio_calibration); + get_string(line, "Callsign:", callsign); + get_string(line,"software-version", version); + get_string(line,"product", product); + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + } finally { + stop_serial(); + } + } + + void init_ui () throws InterruptedException, TimeoutException { + config_ui = new AltosConfigUI(owner, remote); + config_ui.addActionListener(this); + set_ui(); + } + + void abort() { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial_line.close(); + serial_line = null; + } + + void set_ui() throws InterruptedException, TimeoutException { + if (serial_line != null) + get_data(); + config_ui.set_serial(serial.get()); + config_ui.set_product(product.get()); + config_ui.set_version(version.get()); + config_ui.set_main_deploy(main_deploy.get()); + config_ui.set_apogee_delay(apogee_delay.get()); + config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_callsign(callsign.get()); + config_ui.set_clean(); + } + + void run_dialog() { + } + + void save_data() { + main_deploy.set(config_ui.main_deploy()); + apogee_delay.set(config_ui.apogee_delay()); + radio_channel.set(config_ui.radio_channel()); + radio_calibration.set(config_ui.radio_calibration()); + callsign.set(config_ui.callsign()); + try { + start_serial(); + serial_line.printf("c m %d\n", main_deploy.get()); + serial_line.printf("c d %d\n", apogee_delay.get()); + if (!remote) { + serial_line.printf("c r %d\n", radio_channel.get()); + serial_line.printf("c f %d\n", radio_calibration.get()); + } + serial_line.printf("c c %s\n", callsign.get()); + serial_line.printf("c w\n"); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + try { + if (cmd.equals("Save")) { + save_data(); + set_ui(); + } else if (cmd.equals("Reset")) { + set_ui(); + } else if (cmd.equals("Reboot")) { + if (serial_line != null) { + start_serial(); + serial_line.printf("r eboot\n"); + serial_line.flush_output(); + stop_serial(); + serial_line.close(); + } + } else if (cmd.equals("Close")) { + if (serial_line != null) + serial_line.close(); + } + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } + } + + public void run () { + try { + init_ui(); + config_ui.make_visible(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } + } + + public AltosConfig(JFrame given_owner) { + owner = given_owner; + + serial = new int_ref(0); + main_deploy = new int_ref(250); + apogee_delay = new int_ref(0); + radio_channel = new int_ref(0); + radio_calibration = new int_ref(1186611); + callsign = new string_ref("N0CALL"); + version = new string_ref("unknown"); + product = new string_ref("unknown"); + + device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + if (device != null) { + try { + serial_line = new AltosSerial(device); + if (!device.matchProduct(AltosDevice.product_telemetrum)) + remote = true; + config_thread = new Thread(this); + config_thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + } +} \ No newline at end of file diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java new file mode 100644 index 00000000..cfa5d7b9 --- /dev/null +++ b/altosui/AltosConfigUI.java @@ -0,0 +1,466 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.LinkedBlockingQueue; + +import libaltosJNI.*; + +public class AltosConfigUI + extends JDialog + implements ActionListener, ItemListener, DocumentListener +{ + + Container pane; + Box box; + JLabel product_label; + JLabel version_label; + JLabel serial_label; + JLabel main_deploy_label; + JLabel apogee_delay_label; + JLabel radio_channel_label; + JLabel radio_calibration_label; + JLabel callsign_label; + + public boolean dirty; + + JFrame owner; + JLabel product_value; + JLabel version_value; + JLabel serial_value; + JComboBox main_deploy_value; + JComboBox apogee_delay_value; + JComboBox radio_channel_value; + JTextField radio_calibration_value; + JTextField callsign_value; + + JButton save; + JButton reset; + JButton reboot; + JButton close; + + ActionListener listener; + + static String[] main_deploy_values = { + "100", "150", "200", "250", "300", "350", + "400", "450", "500" + }; + + static String[] apogee_delay_values = { + "0", "1", "2", "3", "4", "5" + }; + + static String[] radio_channel_values = new String[10]; + { + for (int i = 0; i <= 9; i++) + radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)", + i, 434.550 + i * 0.1); + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosConfigUI ui; + + public ConfigListener(AltosConfigUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "Close")); + } + } + + /* Build the UI using a grid bag */ + public AltosConfigUI(JFrame in_owner, boolean remote) { + super (in_owner, "Configure TeleMetrum", false); + + 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()); + + /* Product */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + product_label = new JLabel("Product:"); + pane.add(product_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 0; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + product_value = new JLabel(""); + pane.add(product_value, c); + + /* Version */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 1; + c.gridwidth = 4; + 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 = new GridBagConstraints(); + c.gridx = 4; c.gridy = 1; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + version_value = new JLabel(""); + pane.add(version_value, c); + + /* Serial */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 2; + c.gridwidth = 4; + 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 = new GridBagConstraints(); + c.gridx = 4; c.gridy = 2; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + /* Main deploy */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 3; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + main_deploy_label = new JLabel("Main Deploy Altitude(m):"); + pane.add(main_deploy_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 3; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + main_deploy_value = new JComboBox(main_deploy_values); + main_deploy_value.setEditable(true); + main_deploy_value.addItemListener(this); + pane.add(main_deploy_value, c); + + /* Apogee delay */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 4; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + apogee_delay_label = new JLabel("Apogee Delay(s):"); + pane.add(apogee_delay_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 4; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + apogee_delay_value = new JComboBox(apogee_delay_values); + apogee_delay_value.setEditable(true); + apogee_delay_value.addItemListener(this); + pane.add(apogee_delay_value, c); + + /* Radio channel */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 5; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_channel_label = new JLabel("Radio Channel:"); + pane.add(radio_channel_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 5; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_channel_value = new JComboBox(radio_channel_values); + radio_channel_value.setEditable(false); + radio_channel_value.addItemListener(this); + if (remote) + radio_channel_value.setEnabled(false); + pane.add(radio_channel_value, c); + + /* Radio Calibration */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 6; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_calibration_label = new JLabel("RF Calibration:"); + pane.add(radio_calibration_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 6; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_calibration_value = new JTextField(String.format("%d", 1186611)); + radio_calibration_value.getDocument().addDocumentListener(this); + if (remote) + radio_calibration_value.setEnabled(false); + pane.add(radio_calibration_value, c); + + /* Callsign */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 7; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + callsign_label = new JLabel("Callsign:"); + pane.add(callsign_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 7; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + callsign_value = new JTextField(AltosPreferences.callsign()); + callsign_value.getDocument().addDocumentListener(this); + pane.add(callsign_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 8; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + save = new JButton("Save"); + pane.add(save, c); + save.addActionListener(this); + save.setActionCommand("Save"); + + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = 8; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + reset = new JButton("Reset"); + pane.add(reset, c); + reset.addActionListener(this); + reset.setActionCommand("Reset"); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 8; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + reboot = new JButton("Reboot"); + pane.add(reboot, c); + reboot.addActionListener(this); + reboot.setActionCommand("Reboot"); + + c = new GridBagConstraints(); + c.gridx = 6; c.gridy = 8; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_END; + c.insets = il; + close = new JButton("Close"); + pane.add(close, c); + close.addActionListener(this); + close.setActionCommand("Close"); + + addWindowListener(new ConfigListener(this)); + } + + /* Once the initial values are set, the config code will show the dialog */ + public void make_visible() { + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } + + /* If any values have been changed, confirm before closing */ + public boolean check_dirty(String operation) { + if (dirty) { + Object[] options = { String.format("%s anyway", operation), "Keep editing" }; + int i; + i = JOptionPane.showOptionDialog(this, + String.format("Configuration modified. %s anyway?", operation), + "Configuration Modified", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, options, options[1]); + if (i != 0) + return false; + } + return true; + } + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("Close") || cmd.equals("Reboot")) + if (!check_dirty(cmd)) + return; + listener.actionPerformed(e); + if (cmd.equals("Close") || cmd.equals("Reboot")) { + setVisible(false); + dispose(); + } + dirty = false; + } + + /* ItemListener interface method */ + public void itemStateChanged(ItemEvent e) { + dirty = true; + } + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + dirty = true; + } + + public void insertUpdate(DocumentEvent e) { + dirty = true; + } + + public void removeUpdate(DocumentEvent e) { + dirty = true; + } + + /* Let the config code hook on a listener */ + public void addActionListener(ActionListener l) { + listener = l; + } + + /* set and get all of the dialog values */ + public void set_product(String product) { + product_value.setText(product); + } + + public void set_version(String version) { + version_value.setText(version); + } + + public void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + public void set_main_deploy(int new_main_deploy) { + main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy)); + } + + public int main_deploy() { + return Integer.parseInt(main_deploy_value.getSelectedItem().toString()); + } + + public void set_apogee_delay(int new_apogee_delay) { + apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); + } + + public int apogee_delay() { + return Integer.parseInt(apogee_delay_value.getSelectedItem().toString()); + } + + public void set_radio_channel(int new_radio_channel) { + radio_channel_value.setSelectedIndex(new_radio_channel); + } + + public int radio_channel() { + return radio_channel_value.getSelectedIndex(); + } + + public void set_radio_calibration(int new_radio_calibration) { + radio_calibration_value.setText(String.format("%d", new_radio_calibration)); + } + + public int radio_calibration() { + return Integer.parseInt(radio_calibration_value.getText()); + } + + public void set_callsign(String new_callsign) { + callsign_value.setText(new_callsign); + } + + public String callsign() { + return callsign_value.getText(); + } + + public void set_clean() { + dirty = false; + } + + } \ No newline at end of file diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java new file mode 100644 index 00000000..153c59fd --- /dev/null +++ b/altosui/AltosConfigureUI.java @@ -0,0 +1,187 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.LinkedBlockingQueue; + +public class AltosConfigureUI + extends JDialog + implements DocumentListener +{ + JFrame owner; + AltosVoice voice; + Container pane; + + JRadioButton enable_voice; + JButton test_voice; + JButton close; + + JButton configure_log; + JTextField log_directory; + + JLabel callsign_label; + JTextField callsign_value; + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + AltosPreferences.set_callsign(callsign_value.getText()); + } + + public void insertUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public void removeUpdate(DocumentEvent e) { + changedUpdate(e); + } + + public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) { + super(in_owner, "Configure AltosUI", false); + + GridBagConstraints c; + + Insets insets = new Insets(4, 4, 4, 4); + + owner = in_owner; + voice = in_voice; + pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + c = new GridBagConstraints(); + c.insets = insets; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + + /* Nice label at the top */ + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + pane.add(new JLabel ("Configure AltOS UI"), c); + + /* Voice settings */ + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Voice"), c); + + enable_voice = new JRadioButton("Enable", AltosPreferences.voice()); + enable_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosPreferences.set_voice(enabled); + if (enabled) + voice.speak_always("Enable voice."); + else + voice.speak_always("Disable voice."); + } + }); + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.weightx = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(enable_voice, c); + + c.gridx = 2; + c.gridy = 1; + c.gridwidth = 1; + c.weightx = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.EAST; + test_voice = new JButton("Test Voice"); + test_voice.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + voice.speak("That's one small step for man; one giant leap for mankind."); + } + }); + pane.add(test_voice, c); + + /* Log directory settings */ + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Log Directory"), c); + + configure_log = new JButton(AltosPreferences.logdir().getPath()); + configure_log.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosPreferences.ConfigureLog(); + configure_log.setText(AltosPreferences.logdir().getPath()); + } + }); + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + pane.add(configure_log, c); + + /* Callsign setting */ + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Callsign"), c); + + callsign_value = new JTextField(AltosPreferences.callsign()); + callsign_value.getDocument().addDocumentListener(this); + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + pane.add(callsign_value, c); + + /* And a close button at the bottom */ + close = new JButton("Close"); + close.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + setVisible(false); + } + }); + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + pane.add(close, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java new file mode 100644 index 00000000..8cc1df27 --- /dev/null +++ b/altosui/AltosConvert.java @@ -0,0 +1,192 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Sensor data conversion functions + */ +package altosui; + +public class AltosConvert { + /* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= Math.pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * Math.pow(base, exponent); + } + + return pressure; + } + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ + static double + pressure_to_altitude(double pressure) + { + + double next_base_temperature = LAYER0_BASE_TEMPERATURE; + double next_base_pressure = LAYER0_BASE_PRESSURE; + + double altitude; + double base_pressure; + double base_temperature; + double base; /* base for function to determine base pressure of next layer */ + double exponent; /* exponent for function to determine base pressure + of next layer */ + double coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= Math.pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * Math.log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (Math.pow(base, exponent) - 1); + } + + return altitude; + } + + static double + cc_battery_to_voltage(double battery) + { + return battery / 32767.0 * 5.0; + } + + static double + cc_ignitor_to_voltage(double ignite) + { + return ignite / 32767 * 15.0; + } +} diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java new file mode 100644 index 00000000..15de05c2 --- /dev/null +++ b/altosui/AltosDataChooser.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +public class AltosDataChooser extends JFileChooser { + JFrame frame; + String filename; + File file; + + public String filename() { + return filename; + } + + public File file() { + return file; + } + + public AltosRecordIterable runDialog() { + int ret; + + ret = showOpenDialog(frame); + if (ret == APPROVE_OPTION) { + file = getSelectedFile(); + if (file == null) + return null; + filename = file.getName(); + try { + if (filename.endsWith("eeprom")) { + FileInputStream in = new FileInputStream(file); + return new AltosEepromIterable(in); + } else if (filename.endsWith("telem")) { + FileInputStream in = new FileInputStream(file); + return new AltosTelemetryIterable(in); + } else { + throw new FileNotFoundException(); + } + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(frame, + filename, + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + return null; + } + + public AltosDataChooser(JFrame in_frame) { + frame = in_frame; + setDialogTitle("Select Flight Record File"); + setFileFilter(new FileNameExtensionFilter("Flight data file", + "telem", "eeprom")); + setCurrentDirectory(AltosPreferences.logdir()); + } +} diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java new file mode 100644 index 00000000..66313e03 --- /dev/null +++ b/altosui/AltosDataPoint.java @@ -0,0 +1,29 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +interface AltosDataPoint { + int version(); + int serial(); + int flight(); + String callsign(); + double time(); + double rssi(); + + int state(); + String state_name(); + + double acceleration(); + double pressure(); + double altitude(); + double height(); + double accel_speed(); + double baro_speed(); + double temperature(); + double battery_voltage(); + double drogue_voltage(); + double main_voltage(); +} + diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java new file mode 100644 index 00000000..7704310b --- /dev/null +++ b/altosui/AltosDataPointReader.java @@ -0,0 +1,72 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.IOException; +import java.text.ParseException; +import java.lang.UnsupportedOperationException; +import java.util.NoSuchElementException; +import java.util.Iterator; + +class AltosDataPointReader implements Iterable { + Iterator iter; + AltosState state; + AltosRecord record; + + public AltosDataPointReader(Iterable reader) { + this.iter = reader.iterator(); + this.state = null; + } + + private void read_next_record() + throws NoSuchElementException + { + record = iter.next(); + state = new AltosState(record, state); + } + + private AltosDataPoint current_dp() { + assert this.record != null; + + return new AltosDataPoint() { + public int version() { return record.version; } + public int serial() { return record.serial; } + public int flight() { return record.flight; } + public String callsign() { return record.callsign; } + public double time() { return record.time; } + public double rssi() { return record.rssi; } + + public int state() { return record.state; } + public String state_name() { return record.state(); } + + public double acceleration() { return record.acceleration(); } + public double pressure() { return record.raw_pressure(); } + public double altitude() { return record.raw_altitude(); } + public double height() { return record.raw_height(); } + public double accel_speed() { return record.accel_speed(); } + public double baro_speed() { return state.baro_speed; } + public double temperature() { return record.temperature(); } + public double battery_voltage() { return record.battery_voltage(); } + public double drogue_voltage() { return record.drogue_voltage(); } + public double main_voltage() { return record.main_voltage(); } + }; + } + + public Iterator iterator() { + return new Iterator() { + public void remove() { + throw new UnsupportedOperationException(); + } + public boolean hasNext() { + return iter.hasNext(); + } + public AltosDataPoint next() { + read_next_record(); + return current_dp(); + } + }; + } +} + diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java new file mode 100644 index 00000000..8d435b66 --- /dev/null +++ b/altosui/AltosDebug.java @@ -0,0 +1,267 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; +import java.util.*; + +import libaltosJNI.*; + +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"); + } + + public AltosDebug (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + super(in_device); + } +} \ No newline at end of file diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java new file mode 100644 index 00000000..16ccd458 --- /dev/null +++ b/altosui/AltosDescent.java @@ -0,0 +1,353 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosDescent extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + + public abstract class DescentStatus { + JLabel label; + JTextField value; + AltosLights lights; + + abstract void show(AltosState state, int crc_errors); + void reset() { + value.setText(""); + lights.set(false); + } + + public DescentStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.gridwidth = 3; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 4; c.gridy = y; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + } + } + + public abstract class DescentValue { + JLabel label; + JTextField value; + + void reset() { + value.setText(""); + } + + abstract void show(AltosState state, int crc_errors); + + void show(String format, double v) { + value.setText(String.format(format, v)); + } + + void show(String v) { + value.setText(v); + } + + public DescentValue (GridBagLayout layout, int x, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = x + 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + add(label, c); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 2; c.gridy = y; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + add(value, c); + } + } + + public abstract class DescentDualValue { + JLabel label; + JTextField value1; + JTextField value2; + + void reset() { + value1.setText(""); + value2.setText(""); + } + + abstract void show(AltosState state, int crc_errors); + void show(String v1, String v2) { + value1.setText(v1); + value2.setText(v2); + } + void show(String f1, double v1, String f2, double v2) { + value1.setText(String.format(f1, v1)); + value2.setText(String.format(f2, v2)); + } + + public DescentDualValue (GridBagLayout layout, int x, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = x + 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value1 = new JTextField(Altos.text_width); + value1.setFont(Altos.value_font); + value1.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value1, c); + add(value1); + + value2 = new JTextField(Altos.text_width); + value2.setFont(Altos.value_font); + value2.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = x + 4; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.gridwidth = 1; + layout.setConstraints(value2, c); + add(value2); + } + } + + class Height extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.height); + } + public Height (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Height"); + } + } + + Height height; + + class Speed extends DescentValue { + void show (AltosState state, int crc_errors) { + double speed = state.speed; + if (!state.ascent) + speed = state.baro_speed; + show("%6.0f m/s", speed); + } + public Speed (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Speed"); + } + } + + Speed speed; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %d° %9.6f", h, deg, min); + } + + class Lat extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + show(pos(state.gps.lat,"N", "S")); + else + show("???"); + } + public Lat (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends DescentValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + show(pos(state.gps.lon,"W", "E")); + else + show("???"); + } + public Lon (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Longitude"); + } + } + + Lon lon; + + class Apogee extends DescentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends DescentStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + + class Bearing extends DescentDualValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) { + show( String.format("%3.0f°", state.from_pad.bearing), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_LONG)); + } else { + show("???", "???"); + } + } + public Bearing (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Bearing"); + } + } + + Bearing bearing; + + class Range extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.range); + } + public Range (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Range"); + } + } + + Range range; + + class Elevation extends DescentValue { + void show (AltosState state, int crc_errors) { + show("%3.0f°", state.elevation); + } + public Elevation (GridBagLayout layout, int x, int y) { + super (layout, x, y, "Elevation"); + } + } + + Elevation elevation; + + public void reset() { + lat.reset(); + lon.reset(); + height.reset(); + speed.reset(); + bearing.reset(); + range.reset(); + elevation.reset(); + main.reset(); + apogee.reset(); + } + + public void show(AltosState state, int crc_errors) { + height.show(state, crc_errors); + speed.show(state, crc_errors); + bearing.show(state, crc_errors); + range.show(state, crc_errors); + elevation.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + main.show(state, crc_errors); + apogee.show(state, crc_errors); + } + + public AltosDescent() { + layout = new GridBagLayout(); + + setLayout(layout); + + /* Elements in descent display */ + speed = new Speed(layout, 0, 0); + height = new Height(layout, 2, 0); + elevation = new Elevation(layout, 0, 1); + range = new Range(layout, 2, 1); + bearing = new Bearing(layout, 0, 2); + lat = new Lat(layout, 0, 3); + lon = new Lon(layout, 2, 3); + + apogee = new Apogee(layout, 4); + main = new Main(layout, 5); + } +} diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java new file mode 100644 index 00000000..f0fda57b --- /dev/null +++ b/altosui/AltosDevice.java @@ -0,0 +1,170 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import libaltosJNI.*; + +public class AltosDevice extends altos_device { + + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + loaded_library = false; + } + initialized = true; + } + return loaded_library; + } + + static int usb_vendor_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_VENDOR_ALTUSMETRUM; + return 0x000a; + } + + static int usb_product_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return 0x000a; + } + + static int usb_product_altusmetrum_min() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; + return 0x000a; + } + + static int usb_product_altusmetrum_max() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; + return 0x000d; + } + + static int usb_product_telemetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEMETRUM; + return 0x000b; + } + + static int usb_product_teledongle() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEDONGLE; + return 0x000c; + } + + static int usb_product_teleterra() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELETERRA; + return 0x000d; + } + + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); + public final static int product_altusmetrum = usb_product_altusmetrum(); + public final static int product_telemetrum = usb_product_telemetrum(); + public final static int product_teledongle = usb_product_teledongle(); + public final static int product_teleterra = usb_product_teleterra(); + public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); + public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); + + + public final static int product_any = 0x10000; + public final static int product_basestation = 0x10000 + 1; + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + getName(), getSerial(), getPath()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + name, getSerial(), getPath()); + + } + + public boolean isAltusMetrum() { + if (getVendor() != vendor_altusmetrum) + return false; + if (getProduct() < product_altusmetrum_min) + return false; + if (getProduct() > product_altusmetrum_max) + return false; + return true; + } + + public boolean matchProduct(int want_product) { + + if (!isAltusMetrum()) + return false; + + if (want_product == product_any) + return true; + + if (want_product == product_basestation) + return matchProduct(product_teledongle) || matchProduct(product_teleterra); + + int have_product = getProduct(); + + if (have_product == product_altusmetrum) /* old devices match any request */ + return true; + + if (want_product == have_product) + return true; + + return false; + } + + static AltosDevice[] list(int product) { + if (!load_library()) + return null; + + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + SWIGTYPE_p_altos_file file; + + for (;;) { + AltosDevice device = new AltosDevice(); + if (libaltos.altos_list_next(list, device) == 0) + break; + if (device.matchProduct(product)) + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + AltosDevice[] devices = new AltosDevice[device_list.size()]; + for (int i = 0; i < device_list.size(); i++) + devices[i] = device_list.get(i); + return devices; + } +} \ No newline at end of file diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java new file mode 100644 index 00000000..2966ad1e --- /dev/null +++ b/altosui/AltosDeviceDialog.java @@ -0,0 +1,164 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; + +public class AltosDeviceDialog extends JDialog implements ActionListener { + + private static AltosDeviceDialog dialog; + private static AltosDevice value = null; + private JList list; + + public static AltosDevice show (Component frameComp, int product) { + + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDevice[] devices; + devices = AltosDevice.list(product); + + if (devices != null && devices.length > 0) { + value = null; + dialog = new AltosDeviceDialog(frame, frameComp, + devices, + devices[0]); + + dialog.setVisible(true); + return value; + } else { + /* check for missing altos JNI library, which + * will put up its own error dialog + */ + if (AltosUI.load_library(frame)) { + JOptionPane.showMessageDialog(frame, + "No AltOS devices available", + "No AltOS devices", + JOptionPane.ERROR_MESSAGE); + } + return null; + } + } + + private AltosDeviceDialog (Frame frame, Component location, + AltosDevice[] devices, + AltosDevice initial) { + super(frame, "Device Selection", true); + + value = null; + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(this); + + final JButton selectButton = new JButton("Select"); + selectButton.setActionCommand("select"); + selectButton.addActionListener(this); + getRootPane().setDefaultButton(selectButton); + + list = new JList(devices) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + selectButton.doClick(); //emulate button click + } + } + }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + //Lay out the buttons from left to right. + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancelButton); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(selectButton); + + //Put everything together, using the content pane's BorderLayout. + Container contentPane = getContentPane(); + contentPane.add(listPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + //Initialize values. + list.setSelectedValue(initial, true); + pack(); + setLocationRelativeTo(location); + } + + //Handle clicks on the Set and Cancel buttons. + public void actionPerformed(ActionEvent e) { + if ("select".equals(e.getActionCommand())) + AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue()); + AltosDeviceDialog.dialog.setVisible(false); + } + +} diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java new file mode 100644 index 00000000..3e719130 --- /dev/null +++ b/altosui/AltosDisplayThread.java @@ -0,0 +1,249 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosDisplayThread extends Thread { + + Frame parent; + IdleThread idle_thread; + AltosVoice voice; + String name; + AltosFlightReader reader; + int crc_errors; + AltosFlightDisplay display; + + synchronized void show(AltosState state, int crc_errors) { + if (state != null) + display.show(state, crc_errors); + } + + class IdleThread extends Thread { + + boolean started; + private AltosState state; + int reported_landing; + int report_interval; + long report_time; + + public synchronized void report(boolean last) { + if (state == null) + return; + + /* reset the landing count once we hear about a new flight */ + if (state.state < Altos.ao_flight_drogue) + reported_landing = 0; + + /* Shut up once the rocket is on the ground */ + if (reported_landing > 2) { + return; + } + + /* If the rocket isn't on the pad, then report height */ + if (Altos.ao_flight_drogue <= state.state && + state.state < Altos.ao_flight_landed && + state.range >= 0) + { + voice.speak("Height %d, bearing %s %d, elevation %d, range %d.\n", + (int) (state.height + 0.5), + state.from_pad.bearing_words( + AltosGreatCircle.BEARING_VOICE), + (int) (state.from_pad.bearing + 0.5), + (int) (state.elevation + 0.5), + (int) (state.range + 0.5)); + } else if (state.state > Altos.ao_flight_pad) { + voice.speak("%d meters", (int) (state.height + 0.5)); + } else { + reported_landing = 0; + } + + /* If the rocket is coming down, check to see if it has landed; + * either we've got a landed report or we haven't heard from it in + * a long time + */ + if (state.state >= Altos.ao_flight_drogue && + (last || + System.currentTimeMillis() - state.report_time >= 15000 || + state.state == Altos.ao_flight_landed)) + { + if (Math.abs(state.baro_speed) < 20 && state.height < 100) + voice.speak("rocket landed safely"); + else + voice.speak("rocket may have crashed"); + if (state.from_pad != null) + voice.speak("Bearing %d degrees, range %d meters.", + (int) (state.from_pad.bearing + 0.5), + (int) (state.from_pad.distance + 0.5)); + ++reported_landing; + if (state.state != Altos.ao_flight_landed) { + state.state = Altos.ao_flight_landed; + show(state, 0); + } + } + } + + long now () { + return System.currentTimeMillis(); + } + + void set_report_time() { + report_time = now() + report_interval; + } + + public void run () { + try { + for (;;) { + 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 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(); + } + + public IdleThread() { + state = null; + reported_landing = 0; + report_interval = 10000; + } + } + + 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) { + voice.speak("GPS ready"); + ret = true; + } + else if (old_state != null) { + voice.speak("GPS lost"); + ret = true; + } + } + old_state = state; + return ret; + } + + public void run() { + boolean interrupted = false; + String line; + AltosState state = null; + AltosState old_state = null; + boolean told; + + idle_thread = new IdleThread(); + + display.reset(); + try { + for (;;) { + try { + AltosRecord record = reader.read(); + if (record == null) + break; + old_state = state; + state = new AltosState(record, state); + reader.update(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(parent, + String.format("Error reading from \"%s\"", name), + "Telemetry Read Error", + JOptionPane.ERROR_MESSAGE); + } finally { + if (!interrupted) + idle_thread.report(true); + reader.close(interrupted); + idle_thread.interrupt(); + try { + idle_thread.join(); + } catch (InterruptedException ie) {} + } + } + + public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { + parent = in_parent; + voice = in_voice; + display = in_display; + reader = in_reader; + } +} diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java new file mode 100644 index 00000000..02fc36f2 --- /dev/null +++ b/altosui/AltosEepromDownload.java @@ -0,0 +1,285 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosEepromDownload implements Runnable { + + static final String[] state_names = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + int checksum(int[] line) { + int csum = 0x5a; + for (int i = 1; i < line.length; i++) + csum += line[i]; + return csum & 0xff; + } + + void FlushPending(FileWriter file, LinkedList pending) throws IOException { + while (!pending.isEmpty()) { + file.write(pending.remove()); + } + } + + JFrame frame; + AltosDevice device; + AltosSerial serial_line; + boolean remote; + Thread eeprom_thread; + AltosEepromMonitor monitor; + + void CaptureLog() throws IOException, InterruptedException, TimeoutException { + int serial = 0; + int block, state_block = 0; + int addr; + int flight = 0; + int year = 0, month = 0, day = 0; + int state = 0; + boolean done = false; + boolean want_file = false; + boolean any_valid; + FileWriter eeprom_file = null; + AltosFile eeprom_name; + LinkedList eeprom_pending = new LinkedList(); + + serial_line.printf("\nc s\nv\n"); + + /* Pull the serial number out of the version information */ + + for (;;) { + String line = serial_line.get_reply(5000); + + if (line == null) + throw new TimeoutException(); + if (line.startsWith("serial-number")) { + try { + serial = Integer.parseInt(line.substring(13).trim()); + } catch (NumberFormatException ne) { + serial = 0; + } + } + + eeprom_pending.add(String.format("%s\n", line)); + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + if (serial == 0) + throw new IOException("no serial number found"); + + monitor.set_serial(serial); + /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ + + state = 0; state_block = 0; + for (block = 0; !done && block < 511; block++) { + serial_line.printf("e %x\n", block); + any_valid = false; + monitor.set_value(state_names[state], state, block - state_block); + for (addr = 0; addr < 0x100;) { + String line = serial_line.get_reply(5000); + if (line == null) + throw new TimeoutException(); + int[] values = ParseHex(line); + + 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]); + } else if (checksum(values) != 0) { + System.out.printf("invalid checksum at 0x%x\n", + block * 256 + values[0]); + } else { + any_valid = true; + int cmd = values[1]; + int tick = values[3] + (values[4] << 8); + int a = values[5] + (values[6] << 8); + int b = values[7] + (values[8] << 8); + + if (cmd == Altos.AO_LOG_FLIGHT) { + flight = b; + monitor.set_flight(flight); + } + + /* Monitor state transitions to update display */ + if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { + if (a > Altos.ao_flight_pad) + want_file = true; + if (a > state) + state_block = block; + state = a; + } + + if (cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (a & 0xff); + month = (a >> 8) & 0xff; + day = (b & 0xff); + want_file = true; + } + + if (eeprom_file == null) { + if (serial != 0 && flight != 0 && want_file) { + if (year != 0 && month != 0 && day != 0) + eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); + else + eeprom_name = new AltosFile(serial, flight, "eeprom"); + + monitor.set_file(eeprom_name.getName()); + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + eeprom_pending = null; + } + } + } + + String log_line = String.format("%c %4x %4x %4x\n", + cmd, tick, a, b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + + if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { + done = true; + } + } + addr += 8; + } + if (!any_valid) + done = true; + } + if (eeprom_file == null) { + eeprom_name = new AltosFile(serial,flight,"eeprom"); + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + FlushPending(eeprom_file, eeprom_pending); + } + } + if (eeprom_file != null) { + eeprom_file.flush(); + eeprom_file.close(); + } + } + + public void run () { + if (remote) { + serial_line.set_radio(); + serial_line.printf("p\nE 0\n"); + serial_line.flush_input(); + } + + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + eeprom_thread.interrupt(); + } + }); + try { + CaptureLog(); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(frame, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + if (remote) + serial_line.printf("~"); + monitor.done(); + serial_line.flush_output(); + serial_line.close(); + } + + public AltosEepromDownload(JFrame given_frame) { + frame = given_frame; + device = AltosDeviceDialog.show(frame, AltosDevice.product_any); + + remote = false; + + if (device != null) { + try { + serial_line = new AltosSerial(device); + if (!device.matchProduct(AltosDevice.product_telemetrum)) + remote = true; + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + } +} diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java new file mode 100644 index 00000000..f8e6d7e5 --- /dev/null +++ b/altosui/AltosEepromIterable.java @@ -0,0 +1,423 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedRecord extends AltosEepromRecord implements Comparable { + + public int index; + + public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + 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) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; + + AltosEepromRecord flight_record; + AltosEepromRecord gps_date_record; + + TreeSet records; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case Altos.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.a; + state.flight_accel = record.a; + state.flight = record.b; + eeprom.boost_tick = record.tick; + break; + case Altos.AO_LOG_SENSOR: + state.accel = record.a; + state.pres = record.b; + if (state.state < Altos.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + state.flight_vel += (state.accel_plus_g - state.accel); + } + eeprom.seen |= seen_sensor; + break; + case Altos.AO_LOG_TEMP_VOLT: + state.temp = record.a; + state.batt = record.b; + eeprom.seen |= seen_temp_volt; + break; + case Altos.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + break; + case Altos.AO_LOG_STATE: + state.state = record.a; + break; + case Altos.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; + state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; + state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> + Altos.AO_GPS_NUM_SAT_SHIFT; + break; + case Altos.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case Altos.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case Altos.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case Altos.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case Altos.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case Altos.AO_LOG_CONFIG_VERSION: + break; + case Altos.AO_LOG_MAIN_DEPLOY: + break; + case Altos.AO_LOG_APOGEE_DELAY: + break; + case Altos.AO_LOG_RADIO_CHANNEL: + break; + case Altos.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case Altos.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case Altos.AO_LOG_RADIO_CAL: + break; + case Altos.AO_LOG_MANUFACTURER: + 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; + } + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = Altos.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedRecord record = iterator.next(); + switch (record.cmd) { + case Altos.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case Altos.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case Altos.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case Altos.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case Altos.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case Altos.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case Altos.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case Altos.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case Altos.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case Altos.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case Altos.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + } + } + } + + /* + * 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; + + /* Make sure this looks like a good GPS value */ + if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); + flags |= Altos.AO_GPS_RUNNING; + flags |= Altos.AO_GPS_VALID; + + 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedRecord last_gps_time = null; + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); + if (record == null) + break; + if (record.cmd == Altos.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == Altos.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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) { + gps_date_record = record; + continue; + } + + /* 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 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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == Altos.AO_LOG_STATE && + record.a == Altos.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java new file mode 100644 index 00000000..7ff00ead --- /dev/null +++ b/altosui/AltosEepromMonitor.java @@ -0,0 +1,176 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosEepromMonitor extends JDialog { + + Container pane; + Box box; + JLabel serial_label; + JLabel flight_label; + JLabel file_label; + JLabel serial_value; + JLabel flight_value; + JLabel file_value; + JButton cancel; + JProgressBar pbar; + int min_state, max_state; + + public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { + super (owner, "Download Flight Data", false); + + 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; + flight_label = new JLabel("Flight:"); + pane.add(flight_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; + flight_value = new JLabel(""); + pane.add(flight_value, c); + + c = new GridBagConstraints(); + c.fill = GridBagConstraints.NONE; + c.gridx = 0; c.gridy = 2; + 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 = 2; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + file_value = new JLabel(""); + pane.add(file_value, c); + + min_state = in_min_state; + max_state = in_max_state; + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum((max_state - min_state) * 100); + pbar.setValue(0); + pbar.setString("startup"); + 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 = 3; + 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 = 4; + c.gridwidth = GridBagConstraints.REMAINDER; + Insets ic = new Insets(4,4,4,4); + c.insets = ic; + pane.add(cancel, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } + + public void addActionListener (ActionListener l) { + cancel.addActionListener(l); + } + + public void set_value(String state_name, int in_state, int in_block) { + int block = in_block; + int state = in_state; + + if (block > 100) + block = 100; + if (state < min_state) state = min_state; + if (state >= max_state) state = max_state - 1; + state -= min_state; + + int pos = state * 100 + block; + + pbar.setString(state_name); + pbar.setValue(pos); + } + + public void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + + public void set_flight(int flight) { + flight_value.setText(String.format("%d", flight)); + } + + public void set_file(String file) { + file_value.setText(String.format("%s", file)); + } + + public void done() { + setVisible(false); + dispose(); + } +} diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java new file mode 100644 index 00000000..5a673817 --- /dev/null +++ b/altosui/AltosEepromRecord.java @@ -0,0 +1,115 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosEepromRecord { + public int cmd; + public int tick; + public int a; + public int b; + public String data; + public boolean tick_valid; + + public AltosEepromRecord (String line) { + tick_valid = false; + tick = 0; + a = 0; + b = 0; + data = null; + if (line == null) { + cmd = Altos.AO_LOG_INVALID; + data = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + 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; + } +} diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java new file mode 100644 index 00000000..06360572 --- /dev/null +++ b/altosui/AltosFile.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.File; +import java.util.*; + +class AltosFile extends File { + + public AltosFile(int year, int month, int day, int serial, int flight, String extension) { + super (AltosPreferences.logdir(), + String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + year, month, day, serial, flight, extension)); + } + + public AltosFile(int serial, int flight, String extension) { + this(Calendar.getInstance().get(Calendar.YEAR), + Calendar.getInstance().get(Calendar.MONTH) + 1, + Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + serial, + flight, + extension); + } + + public AltosFile(AltosTelemetry telem) { + this(telem.serial, telem.flight, "telem"); + } +} diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java new file mode 100644 index 00000000..3af25c23 --- /dev/null +++ b/altosui/AltosFlash.java @@ -0,0 +1,344 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +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 AltosFlash(File in_file, AltosDevice in_debug_dongle) + throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException { + file = in_file; + debug_dongle = in_debug_dongle; + debug = new AltosDebug(in_debug_dongle); + input = new FileInputStream(file); + image = new AltosHexfile(input); + if (!debug.check_connection()) { + debug.close(); + throw new IOException("Debug port not connected"); + } + } +} \ No newline at end of file diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java new file mode 100644 index 00000000..f63097ac --- /dev/null +++ b/altosui/AltosFlashUI.java @@ -0,0 +1,218 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +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() { + try { + flash = new AltosFlash(file, debug_dongle); + flash.addActionListener(this); + 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 (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + debug_dongle.toShortString()), + "Device in use", + 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.product_any); + + if (debug_dongle == null) + return; + + JFileChooser hexfile_chooser = new JFileChooser(); + + File firmwaredir = AltosPreferences.firmwaredir(); + if (firmwaredir != null) + hexfile_chooser.setCurrentDirectory(firmwaredir); + + 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(); + + if (file != null) + AltosPreferences.set_firmwaredir(file.getParentFile()); + + thread = new Thread(this); + thread.start(); + } +} \ No newline at end of file diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java new file mode 100644 index 00000000..d18d1d1f --- /dev/null +++ b/altosui/AltosFlightDisplay.java @@ -0,0 +1,24 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 interface AltosFlightDisplay { + void reset(); + + void show(AltosState state, int crc_errors); +} diff --git a/altosui/AltosFlightInfoTableModel.java b/altosui/AltosFlightInfoTableModel.java new file mode 100644 index 00000000..e23eff68 --- /dev/null +++ b/altosui/AltosFlightInfoTableModel.java @@ -0,0 +1,84 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightInfoTableModel extends AbstractTableModel { + final static private String[] columnNames = {"Field", "Value"}; + + int rows; + int cols; + private String[][] data; + + public int getColumnCount() { return cols; } + public int getRowCount() { return rows; } + public String getColumnName(int col) { return columnNames[col & 1]; } + + public Object getValueAt(int row, int col) { + if (row >= rows || col >= cols) + return ""; + return data[row][col]; + } + + int[] current_row; + + public void reset() { + for (int i = 0; i < cols / 2; i++) + current_row[i] = 0; + } + + public void clear() { + reset(); + for (int c = 0; c < cols; c++) + for (int r = 0; r < rows; r++) + data[r][c] = ""; + fireTableDataChanged(); + } + + public void addRow(int col, String name, String value) { + if (current_row[col] < rows) { + data[current_row[col]][col * 2] = name; + data[current_row[col]][col * 2 + 1] = value; + } + current_row[col]++; + } + + public void finish() { + for (int c = 0; c < cols / 2; c++) + while (current_row[c] < rows) + addRow(c, "", ""); + fireTableDataChanged(); + } + + public AltosFlightInfoTableModel (int in_rows, int in_cols) { + rows = in_rows; + cols = in_cols * 2; + data = new String[rows][cols]; + current_row = new int[in_cols]; + } +} diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java new file mode 100644 index 00000000..3d59de9a --- /dev/null +++ b/altosui/AltosFlightReader.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; + +public class AltosFlightReader { + String name; + + int serial; + + void init() { } + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + + void close(boolean interrupted) { } + + void set_channel(int channel) { } + + void update(AltosState state) throws InterruptedException { } +} diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java new file mode 100644 index 00000000..59c9e9db --- /dev/null +++ b/altosui/AltosFlightStatus.java @@ -0,0 +1,154 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + + public class FlightValue { + JLabel label; + JTextField value; + + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + public FlightValue (GridBagLayout layout, int x, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(5, 5, 5, 5); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.status_font); + label.setHorizontalAlignment(SwingConstants.CENTER); + c.gridx = x; c.gridy = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(""); + value.setFont(Altos.status_font); + value.setHorizontalAlignment(SwingConstants.CENTER); + c.gridx = x; c.gridy = 1; + layout.setConstraints(value, c); + add(value); + } + } + + class Call extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(state.data.callsign); + } + public Call (GridBagLayout layout, int x) { + super (layout, x, "Callsign"); + } + } + + Call call; + + class Serial extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.serial)); + } + public Serial (GridBagLayout layout, int x) { + super (layout, x, "Serial"); + } + } + + Serial serial; + + class Flight extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.flight)); + } + public Flight (GridBagLayout layout, int x) { + super (layout, x, "Flight"); + } + } + + Flight flight; + + class FlightState extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(state.data.state()); + } + public FlightState (GridBagLayout layout, int x) { + super (layout, x, "State"); + } + } + + FlightState flight_state; + + class RSSI extends FlightValue { + void show(AltosState state, int crc_errors) { + value.setText(String.format("%d", state.data.rssi)); + } + public RSSI (GridBagLayout layout, int x) { + super (layout, x, "RSSI (dBm)"); + } + } + + RSSI rssi; + + public void reset () { + call.reset(); + serial.reset(); + flight.reset(); + flight_state.reset(); + rssi.reset(); + } + + public void show (AltosState state, int crc_errors) { + call.show(state, crc_errors); + serial.show(state, crc_errors); + flight.show(state, crc_errors); + flight_state.show(state, crc_errors); + rssi.show(state, crc_errors); + } + + public int height() { + Dimension d = layout.preferredLayoutSize(this); + return d.height; + } + + public AltosFlightStatus() { + layout = new GridBagLayout(); + + setLayout(layout); + + call = new Call(layout, 0); + serial = new Serial(layout, 1); + flight = new Flight(layout, 2); + flight_state = new FlightState(layout, 3); + rssi = new RSSI(layout, 4); + } +} diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java new file mode 100644 index 00000000..4c24b6ac --- /dev/null +++ b/altosui/AltosFlightStatusTableModel.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightStatusTableModel extends AbstractTableModel { + private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + private Object[] data = { 0, "idle", 0, 0 }; + + public int getColumnCount() { return columnNames.length; } + public int getRowCount() { return 2; } + public Object getValueAt(int row, int col) { + if (row == 0) + return columnNames[col]; + return data[col]; + } + + public void setValueAt(Object value, int col) { + data[col] = value; + fireTableCellUpdated(1, col); + } + + public void setValueAt(Object value, int row, int col) { + setValueAt(value, col); + } + + public void set(AltosState state) { + setValueAt(String.format("%1.0f", state.height), 0); + setValueAt(state.data.state(), 1); + setValueAt(state.data.rssi, 2); + double speed = state.baro_speed; + if (state.ascent) + speed = state.speed; + setValueAt(String.format("%1.0f", speed), 3); + } +} diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java new file mode 100644 index 00000000..24d25bd7 --- /dev/null +++ b/altosui/AltosFlightUI.java @@ -0,0 +1,221 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosFlightUI extends JFrame implements AltosFlightDisplay { + String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; + Object[][] statusData = { { "0", "pad", "-50", "0" } }; + + AltosVoice voice; + AltosFlightReader reader; + AltosDisplayThread thread; + + JTabbedPane pane; + + AltosPad pad; + AltosAscent ascent; + AltosDescent descent; + AltosLanded landed; + AltosSiteMap sitemap; + + private AltosFlightStatus flightStatus; + private AltosInfoTable flightInfo; + + static final int tab_pad = 1; + static final int tab_ascent = 2; + static final int tab_descent = 3; + static final int tab_landed = 4; + + int cur_tab = 0; + + boolean exit_on_close = false; + + int which_tab(AltosState state) { + if (state.state < Altos.ao_flight_boost) + return tab_pad; + if (state.state <= Altos.ao_flight_coast) + return tab_ascent; + if (state.state <= Altos.ao_flight_main) + return tab_descent; + return tab_landed; + } + + void stop_display() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + } + + void disconnect() { + stop_display(); + } + + public void reset() { + pad.reset(); + ascent.reset(); + descent.reset(); + landed.reset(); + flightInfo.clear(); + sitemap.reset(); + } + + public void show(AltosState state, int crc_errors) { + int tab = which_tab(state); + pad.show(state, crc_errors); + ascent.show(state, crc_errors); + descent.show(state, crc_errors); + landed.show(state, crc_errors); + if (tab != cur_tab) { + switch (tab) { + case tab_pad: + pane.setSelectedComponent(pad); + break; + case tab_ascent: + pane.setSelectedComponent(ascent); + break; + case tab_descent: + pane.setSelectedComponent(descent); + break; + case tab_landed: + pane.setSelectedComponent(landed); + } + cur_tab = tab; + } + flightStatus.show(state, crc_errors); + flightInfo.show(state, crc_errors); + sitemap.show(state, crc_errors); + } + + public void set_exit_on_close() { + exit_on_close = true; + } + + Container bag; + JComboBox channels; + + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { + AltosPreferences.init(this); + + voice = in_voice; + reader = in_reader; + + bag = getContentPane(); + bag.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); + if (imgURL != null) + setIconImage(new ImageIcon(imgURL).getImage()); + + setTitle(String.format("AltOS %s", reader.name)); + + /* Stick channel selector at top of table for telemetry monitoring */ + if (serial >= 0) { + // Channel menu + channels = new AltosChannelMenu(AltosPreferences.channel(serial)); + channels.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int channel = channels.getSelectedIndex(); + reader.set_channel(channel); + } + }); + c.gridx = 0; + c.gridy = 0; + c.anchor = GridBagConstraints.WEST; + bag.add (channels, c); + } + + /* Flight status is always visible */ + flightStatus = new AltosFlightStatus(); + c.gridx = 0; + c.gridy = 1; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + bag.add(flightStatus, c); + + /* The rest of the window uses a tabbed pane to + * show one of the alternate data views + */ + pane = new JTabbedPane(); + + pad = new AltosPad(); + pane.add("Launch Pad", pad); + + ascent = new AltosAscent(); + pane.add("Ascent", ascent); + + descent = new AltosDescent(); + pane.add("Descent", descent); + + landed = new AltosLanded(); + pane.add("Landed", landed); + + flightInfo = new AltosInfoTable(); + pane.add("Table", new JScrollPane(flightInfo)); + + sitemap = new AltosSiteMap(); + pane.add("Site Map", sitemap); + + /* Make the tabbed pane use the rest of the window space */ + c.gridx = 0; + c.gridy = 2; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + bag.add(pane, c); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + disconnect(); + setVisible(false); + dispose(); + if (exit_on_close) + System.exit(0); + } + }); + + pack(); + setVisible(true); + + thread = new AltosDisplayThread(this, voice, this, reader); + + thread.start(); + } + + public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) { + this(in_voice, in_reader, -1); + } +} diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java new file mode 100644 index 00000000..83821842 --- /dev/null +++ b/altosui/AltosGPS.java @@ -0,0 +1,215 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; + +public class AltosGPS { + public class AltosGPSSat { + int svid; + int c_n0; + } + + int nsat; + boolean locked; + boolean connected; + boolean date_valid; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + int year; + int month; + int day; + int hour; + int minute; + int second; + + int gps_extended; /* has extra data */ + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless? */ + int h_error; /* m */ + int v_error; /* m */ + + AltosGPSSat[] cc_gps_sat; /* tracking data */ + + 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 = AltosParse.parse_int(hms[0]); + minute = AltosParse.parse_int(hms[1]); + second = AltosParse.parse_int(hms[2]); + } + + void ClearGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } + + 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"); + + connected = false; + locked = false; + lat = lon = 0; + alt = 0; + ClearGPSTime(); + if ((words[i]).equals("unlocked")) { + connected = true; + i++; + } else if ((words[i]).equals("not-connected")) { + i++; + } else if (words.length >= 40) { + locked = true; + connected = true; + + 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(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++; + } + 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) { + lat = in_lat / 10.0e7; + } + + public void set_longitude(int in_lon) { + lon = in_lon / 10.0e7; + } + + public void set_time(int hour, int minute, int second) { + hour = hour; + minute = minute; + second = second; + } + + public void set_date(int year, int month, int day) { + year = year; + month = month; + day = day; + } + + public void set_flags(int flags) { + flags = flags; + } + + public void set_altitude(int altitude) { + altitude = altitude; + } + + public void add_sat(int svid, int c_n0) { + if (cc_gps_sat == null) { + cc_gps_sat = new AltosGPS.AltosGPSSat[1]; + } else { + AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1]; + for (int i = 0; i < cc_gps_sat.length; i++) + new_gps_sat[i] = cc_gps_sat[i]; + cc_gps_sat = new_gps_sat; + } + AltosGPS.AltosGPSSat sat = new AltosGPS.AltosGPSSat(); + sat.svid = svid; + sat.c_n0 = c_n0; + cc_gps_sat[cc_gps_sat.length - 1] = sat; + } + + public AltosGPS() { + ClearGPSTime(); + cc_gps_sat = null; + } + + public AltosGPS(AltosGPS old) { + 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 */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + gps_extended = old.gps_extended; /* has extra data */ + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } + } + } +} diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java new file mode 100644 index 00000000..58c27979 --- /dev/null +++ b/altosui/AltosGraph.java @@ -0,0 +1,25 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.*; + +import org.jfree.chart.JFreeChart; +import org.jfree.chart.ChartUtilities; + +abstract class AltosGraph { + public String filename; + public abstract void addData(AltosDataPoint d); + public abstract JFreeChart createChart(); + public void toPNG() throws java.io.IOException { toPNG(300, 500); } + public void toPNG(int width, int height) + throws java.io.IOException + { + File pngout = new File(filename); + JFreeChart chart = createChart(); + ChartUtilities.saveChartAsPNG(pngout, chart, width, height); + System.out.println("Created " + filename); + } +} diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java new file mode 100644 index 00000000..a5451280 --- /dev/null +++ b/altosui/AltosGraphTime.java @@ -0,0 +1,233 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.awt.Color; +import java.util.ArrayList; +import java.util.HashMap; + +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.AxisLocation; +import org.jfree.chart.axis.NumberAxis; +import org.jfree.chart.labels.StandardXYToolTipGenerator; +import org.jfree.chart.plot.PlotOrientation; +import org.jfree.chart.plot.XYPlot; +import org.jfree.chart.plot.ValueMarker; +import org.jfree.chart.renderer.xy.StandardXYItemRenderer; +import org.jfree.chart.renderer.xy.XYItemRenderer; +import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; +import org.jfree.data.xy.XYSeries; +import org.jfree.data.xy.XYSeriesCollection; +import org.jfree.ui.RectangleAnchor; +import org.jfree.ui.TextAnchor; + +class AltosGraphTime extends AltosGraph { + static interface Element { + void attachGraph(AltosGraphTime g); + void gotTimeData(double time, AltosDataPoint d); + void addToPlot(AltosGraphTime g, XYPlot plot); + } + + static class TimeAxis implements Element { + private int axis; + private Color color; + private String label; + private AxisLocation locn; + private double min_y = Double.NaN; + + public TimeAxis(int axis, String label, Color color, AxisLocation locn) + { + this.axis = axis; + this.color = color; + this.label = label; + this.locn = locn; + } + + public void setLowerBound(double min_y) { + this.min_y = min_y; + } + + public void attachGraph(AltosGraphTime g) { return; } + public void gotTimeData(double time, AltosDataPoint d) { return; } + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + NumberAxis numAxis = new NumberAxis(label); + if (!Double.isNaN(min_y)) + numAxis.setLowerBound(min_y); + plot.setRangeAxis(axis, numAxis); + plot.setRangeAxisLocation(axis, locn); + numAxis.setLabelPaint(color); + numAxis.setTickLabelPaint(color); + numAxis.setAutoRangeIncludesZero(false); + } + } + + abstract static class TimeSeries implements Element { + protected XYSeries series; + private String axisName; + private Color color; + + public TimeSeries(String axisName, String label, Color color) { + this.series = new XYSeries(label); + this.axisName = axisName; + this.color = color; + } + + public void attachGraph(AltosGraphTime g) { + g.setAxis(this, axisName, color); + } + abstract public void gotTimeData(double time, AltosDataPoint d); + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + XYSeriesCollection dataset = new XYSeriesCollection(); + dataset.addSeries(this.series); + + XYItemRenderer renderer = new StandardXYItemRenderer(); + renderer.setSeriesPaint(0, color); + + int dataNum = g.getDataNum(this); + int axisNum = g.getAxisNum(this); + + plot.setDataset(dataNum, dataset); + plot.mapDatasetToRangeAxis(dataNum, axisNum); + plot.setRenderer(dataNum, renderer); + } + } + + static class StateMarker implements Element { + private double val = Double.NaN; + private String name; + private int state; + + StateMarker(int state, String name) { + this.state = state; + this.name = name; + } + + public void attachGraph(AltosGraphTime g) { return; } + public void gotTimeData(double time, AltosDataPoint d) { + if (Double.isNaN(val) || time < val) { + if (d.state() == state) { + val = time; + } + } + } + + public void addToPlot(AltosGraphTime g, XYPlot plot) { + if (Double.isNaN(val)) + return; + + ValueMarker m = new ValueMarker(val); + m.setLabel(name); + m.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + plot.addDomainMarker(m); + } + } + + private String callsign = null; + private Integer serial = null; + private Integer flight = null; + + private String title; + private ArrayList elements; + private HashMap axes; + private HashMap datasets; + private ArrayList datasetAxis; + + public AltosGraphTime(String title) { + this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png"; + this.title = title; + this.elements = new ArrayList(); + this.axes = new HashMap(); + this.datasets = new HashMap(); + this.datasetAxis = new ArrayList(); + } + + public AltosGraphTime addElement(Element e) { + e.attachGraph(this); + elements.add(e); + return this; + } + + public void setAxis(Element ds, String axisName, Color color) { + Integer axisNum = axes.get(axisName); + int dsNum = datasetAxis.size(); + if (axisNum == null) { + axisNum = newAxis(axisName, color); + } + datasets.put(ds, dsNum); + datasetAxis.add(axisNum); + } + + public int getAxisNum(Element ds) { + return datasetAxis.get( datasets.get(ds) ).intValue(); + } + public int getDataNum(Element ds) { + return datasets.get(ds).intValue(); + } + + private Integer newAxis(String name, Color color) { + int cnt = axes.size(); + AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT; + if (cnt > 0) { + locn = AxisLocation.TOP_OR_RIGHT; + } + Integer res = new Integer(cnt); + axes.put(name, res); + this.addElement(new TimeAxis(cnt, name, color, locn)); + return res; + } + + public void addData(AltosDataPoint d) { + double time = d.time(); + for (Element e : elements) { + e.gotTimeData(time, d); + } + if (callsign == null) callsign = d.callsign(); + if (serial == null) serial = new Integer(d.serial()); + if (flight == null) flight = new Integer(d.flight()); + } + + public JFreeChart createChart() { + NumberAxis xAxis = new NumberAxis("Time (s)"); + xAxis.setAutoRangeIncludesZero(false); + XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); + XYPlot plot = new XYPlot(); + plot.setDomainAxis(xAxis); + plot.setRenderer(renderer); + plot.setOrientation(PlotOrientation.VERTICAL); + + if (serial != null && flight != null) { + title = serial + "/" + flight + ": " + title; + } + if (callsign != null) { + title = callsign + " - " + title; + } + + renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); + JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, + plot, true); + ChartUtilities.applyCurrentTheme(chart); + + plot.setDomainPannable(true); + plot.setRangePannable(true); + + for (Element e : elements) { + e.addToPlot(this, plot); + } + + return chart; + } + + public void toPNG() throws java.io.IOException { + if (axes.size() > 1) { + toPNG(800, 500); + } else { + toPNG(300, 500); + } + } +} diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java new file mode 100644 index 00000000..cd158651 --- /dev/null +++ b/altosui/AltosGraphUI.java @@ -0,0 +1,274 @@ + +// Copyright (c) 2010 Anthony Towns +// GPL v2 or later + +package altosui; + +import java.io.*; +import java.util.ArrayList; + +import javax.swing.JFrame; +import java.awt.Color; + +import org.jfree.chart.ChartPanel; +import org.jfree.chart.ChartUtilities; +import org.jfree.chart.JFreeChart; +import org.jfree.chart.axis.AxisLocation; +import org.jfree.ui.ApplicationFrame; +import org.jfree.ui.RefineryUtilities; + +public class AltosGraphUI extends JFrame +{ + static final private Color red = new Color(194,31,31); + static final private Color green = new Color(31,194,31); + static final private Color blue = new Color(31,31,194); + static final private Color black = new Color(31,31,31); + + static private class OverallGraphs { + AltosGraphTime.Element height = + new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.height()); + } + }; + + AltosGraphTime.Element speed = + new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { + public void gotTimeData(double time, AltosDataPoint d) { + if (d.state() < Altos.ao_flight_drogue) { + series.add(time, d.accel_speed()); + } else { + series.add(time, d.baro_speed()); + } + } + }; + + AltosGraphTime.Element acceleration = + new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)", + "Axial Acceleration", blue) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.acceleration()); + } + }; + + AltosGraphTime.Element temperature = + new AltosGraphTime.TimeSeries("Temperature (\u00B0C)", + "Board temperature", red) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.temperature()); + } + }; + + AltosGraphTime.Element drogue_voltage = + new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.drogue_voltage()); + } + }; + + AltosGraphTime.Element main_voltage = + new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) + { + public void gotTimeData(double time, AltosDataPoint d) { + series.add(time, d.main_voltage()); + } + }; + + AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad"); + AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost"); + AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast"); + AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast"); + AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue"); + AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main"); + AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed"); + + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Overall " + suffix)) + .addElement(e_boost) + .addElement(e_drogue) + .addElement(e_main) + .addElement(e_landed); + } + + public ArrayList graphs() { + ArrayList graphs = new ArrayList(); + + graphs.add( myAltosGraphTime("Summary") + .addElement(height) + .addElement(speed) + .addElement(acceleration) ); + + graphs.add( myAltosGraphTime("Altitude") + .addElement(height) ); + + graphs.add( myAltosGraphTime("Speed") + .addElement(speed) ); + + graphs.add( myAltosGraphTime("Acceleration") + .addElement(acceleration) ); + + graphs.add( myAltosGraphTime("Temperature") + .addElement(temperature) ); + + graphs.add( myAltosGraphTime("Continuity") + .addElement(drogue_voltage) + .addElement(main_voltage) ); + + return graphs; + } + } + + static private class AscentGraphs extends OverallGraphs { + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Ascent " + suffix) { + public void addData(AltosDataPoint d) { + int state = d.state(); + if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) { + super.addData(d); + } + } + }).addElement(e_boost) + .addElement(e_fast) + .addElement(e_coast); + } + } + + static private class DescentGraphs extends OverallGraphs { + protected AltosGraphTime myAltosGraphTime(String suffix) { + return (new AltosGraphTime("Descent " + suffix) { + public void addData(AltosDataPoint d) { + int state = d.state(); + if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) { + super.addData(d); + } + } + }).addElement(e_drogue) + .addElement(e_main); + // ((XYGraph)graph[8]).ymin = new Double(-50); + } + } + + public AltosGraphUI(AltosRecordIterable records) { + super("Altos Graph"); + + Iterable reader = new AltosDataPointReader (records); + if (reader == null) + return; + + init(reader, 0); + } + + public AltosGraphUI(Iterable data, int which) + { + super("Altos Graph"); + init(data, which); + } + + private void init(Iterable data, int which) { + AltosGraph graph = createGraph(data, which); + + JFreeChart chart = graph.createChart(); + ChartPanel chartPanel = new ChartPanel(chart); + chartPanel.setMouseWheelEnabled(true); + chartPanel.setPreferredSize(new java.awt.Dimension(800, 500)); + setContentPane(chartPanel); + + pack(); + + RefineryUtilities.centerFrameOnScreen(this); + + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setVisible(true); + } + + private static AltosGraph createGraph(Iterable data, + int which) + { + return createGraphsWhich(data, which).get(0); + } + + private static ArrayList createGraphs( + Iterable data) + { + return createGraphsWhich(data, -1); + } + + private static ArrayList createGraphsWhich( + Iterable data, int which) + { + ArrayList graph = new ArrayList(); + graph.addAll((new OverallGraphs()).graphs()); + graph.addAll((new AscentGraphs()).graphs()); + graph.addAll((new DescentGraphs()).graphs()); + + if (which > 0) { + if (which >= graph.size()) { + which = 0; + } + AltosGraph g = graph.get(which); + graph = new ArrayList(); + graph.add(g); + } + + for (AltosDataPoint dp : data) { + for (AltosGraph g : graph) { + g.addData(dp); + } + } + + return graph; + } +} + +/* gnuplot bits... + * +300x400 + +-------------------------------------------------------- +TOO HARD! :) + +"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)" + 5:($7 < 6 ? $24-$11 : 1/0) +"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)" + 5:($7 < 6 ? 1/0 : $24-$11) + +set output "overall-gps-accuracy.png" +set ylabel "distance above sea level (m)" +plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \ + "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1 + +set term png tiny size 700,700 enhanced +set xlabel "m" +set ylabel "m" +set polar +set grid polar +set rrange[*:*] +set angles degrees + +set output "overall-gps-path.png" +#:30 with yerrorlines +plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \ + "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \ + "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \ + "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \ + "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ + "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ + "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" + +set output "ascent-gps-path.png" +plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \ + "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \ + "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \ + "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast" + +set output "descent-gps-path.png" +plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ + "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ + "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" + + */ + + diff --git a/altosui/AltosGreatCircle.java b/altosui/AltosGreatCircle.java new file mode 100644 index 00000000..fb1b6ab3 --- /dev/null +++ b/altosui/AltosGreatCircle.java @@ -0,0 +1,100 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.Math; + +public class AltosGreatCircle { + double distance; + double bearing; + + double sqr(double a) { return a * a; } + + static final double rad = Math.PI / 180; + static final double earth_radius = 6371.2 * 1000; /* in meters */ + + static int BEARING_LONG = 0; + static int BEARING_SHORT = 1; + static int BEARING_VOICE = 2; + String bearing_words(int length) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } + + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) + { + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + + sqr(Math.cos(lat1) * Math.sin(lat2) - + Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); + double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); + double d = Math.atan2(vdn,vdd); + double course; + + if (Math.cos(lat1) < 1e-20) { + if (lat1 > 0) + course = Math.PI; + else + course = -Math.PI; + } else { + if (d < 1e-10) + course = 0; + else + course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / + (Math.sin(d)*Math.cos(lat1))); + if (Math.sin(lon2-lon1) > 0) + course = 2 * Math.PI-course; + } + 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; + } +} diff --git a/altosui/AltosHexfile.java b/altosui/AltosHexfile.java new file mode 100644 index 00000000..19e35ae1 --- /dev/null +++ b/altosui/AltosHexfile.java @@ -0,0 +1,252 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 record_list = new LinkedList(); + 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 diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java new file mode 100644 index 00000000..3cbd8a75 --- /dev/null +++ b/altosui/AltosIgnite.java @@ -0,0 +1,173 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.*; + +public class AltosIgnite { + AltosDevice device; + AltosSerial serial; + boolean remote; + boolean serial_started; + final static int None = 0; + final static int Apogee = 1; + final static int Main = 2; + + final static int Unknown = 0; + final static int Ready = 1; + final static int Active = 2; + final static int Open = 3; + + private void start_serial() throws InterruptedException { + serial_started = true; + if (remote) { + serial.set_radio(); + serial.printf("p\nE 0\n"); + serial.flush_input(); + } + } + + private void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + if (serial == null) + return; + if (remote) { + serial.printf("~"); + serial.flush_output(); + } + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + private int status(String status_name) { + if (status_name.equals("unknown")) + return Unknown; + if (status_name.equals("ready")) + return Ready; + if (status_name.equals("active")) + return Active; + if (status_name.equals("open")) + return Open; + return Unknown; + } + + public int status(int igniter) throws InterruptedException, TimeoutException { + int status = Unknown; + if (serial == null) + return status; + string_ref status_name = new string_ref(); + start_serial(); + serial.printf("t\n"); + for (;;) { + String line = serial.get_reply(5000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Igniter: drogue Status: ", status_name)) + if (igniter == Apogee) + status = status(status_name.get()); + if (get_string(line, "Igniter: main Status: ", status_name)) { + if (igniter == Main) + status = status(status_name.get()); + break; + } + } + stop_serial(); + return status; + } + + public String status_string(int status) { + switch (status) { + case Unknown: return "Unknown"; + case Ready: return "Ready"; + case Active: return "Active"; + case Open: return "Open"; + default: return "Unknown"; + } + } + + public void fire(int igniter) { + if (serial == null) + return; + try { + start_serial(); + switch (igniter) { + case Main: + serial.printf("i DoIt main\n"); + break; + case Apogee: + serial.printf("i DoIt drogue\n"); + break; + } + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void close() { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial.close(); + serial = null; + } + + public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + + device = in_device; + serial = new AltosSerial(device); + remote = false; + + if (!device.matchProduct(AltosDevice.product_telemetrum)) + remote = true; + } +} \ No newline at end of file diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java new file mode 100644 index 00000000..d542729c --- /dev/null +++ b/altosui/AltosIgniteUI.java @@ -0,0 +1,317 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.*; + +public class AltosIgniteUI + extends JDialog + implements ActionListener +{ + AltosDevice device; + AltosIgnite ignite; + JFrame owner; + JLabel label; + JRadioButton apogee; + JLabel apogee_status_label; + JRadioButton main; + JLabel main_status_label; + JToggleButton arm; + JButton fire; + javax.swing.Timer timer; + + int apogee_status; + int main_status; + + final static int timeout = 1 * 1000; + + int time_remaining; + boolean timer_running; + + void set_arm_text() { + if (arm.isSelected()) + arm.setText(String.format("%d", time_remaining)); + else + arm.setText("Arm"); + } + + void start_timer() { + time_remaining = 10; + set_arm_text(); + timer_running = true; + } + + void stop_timer() { + time_remaining = 0; + arm.setSelected(false); + arm.setEnabled(false); + fire.setEnabled(false); + timer_running = false; + set_arm_text(); + } + + void cancel () { + apogee.setSelected(false); + main.setSelected(false); + fire.setEnabled(false); + stop_timer(); + } + + void get_ignite_status() throws InterruptedException, TimeoutException { + apogee_status = ignite.status(AltosIgnite.Apogee); + main_status = ignite.status(AltosIgnite.Main); + } + + void set_ignite_status() throws InterruptedException, TimeoutException { + get_ignite_status(); + apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status))); + main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status))); + } + + void close() { + timer.stop(); + setVisible(false); + ignite.close(); + } + + void abort() { + close(); + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + + void tick_timer() { + if (timer_running) { + --time_remaining; + if (time_remaining <= 0) + cancel(); + else + set_arm_text(); + } + try { + set_ignite_status(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } + } + + void fire() { + if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) { + int igniter = AltosIgnite.None; + if (apogee.isSelected() && !main.isSelected()) + igniter = AltosIgnite.Apogee; + else if (main.isSelected() && !apogee.isSelected()) + igniter = AltosIgnite.Main; + ignite.fire(igniter); + cancel(); + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + if (cmd.equals("apogee") || cmd.equals("main")) { + stop_timer(); + } + + if (cmd.equals("apogee") && apogee.isSelected()) { + main.setSelected(false); + arm.setEnabled(true); + } + if (cmd.equals("main") && main.isSelected()) { + apogee.setSelected(false); + arm.setEnabled(true); + } + + if (cmd.equals("arm")) { + if (arm.isSelected()) { + fire.setEnabled(true); + start_timer(); + } else + cancel(); + } + if (cmd.equals("fire")) + fire(); + if (cmd.equals("tick")) + tick_timer(); + if (cmd.equals("close")) { + close(); + } + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosIgniteUI ui; + + public ConfigListener(AltosIgniteUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + if (device != null) { + try { + ignite = new AltosIgnite(device); + return true; + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + return false; + } + + public AltosIgniteUI(JFrame in_owner) { + + owner = in_owner; + apogee_status = AltosIgnite.Unknown; + main_status = AltosIgnite.Unknown; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + timer = new javax.swing.Timer(timeout, this); + timer.setActionCommand("tick"); + timer_running = false; + timer.restart(); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + label = new JLabel ("Fire Igniter"); + pane.add(label, c); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + apogee = new JRadioButton ("Apogee"); + pane.add(apogee, c); + apogee.addActionListener(this); + apogee.setActionCommand("apogee"); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + apogee_status_label = new JLabel(); + pane.add(apogee_status_label, c); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + main = new JRadioButton ("Main"); + pane.add(main, c); + main.addActionListener(this); + main.setActionCommand("main"); + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + main_status_label = new JLabel(); + pane.add(main_status_label, c); + + try { + set_ignite_status(); + } catch (InterruptedException ie) { + abort(); + return; + } catch (TimeoutException te) { + abort(); + return; + } + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + arm = new JToggleButton ("Arm"); + pane.add(arm, c); + arm.addActionListener(this); + arm.setActionCommand("arm"); + arm.setEnabled(false); + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + fire = new JButton ("Fire"); + fire.setEnabled(false); + pane.add(fire, c); + fire.addActionListener(this); + fire.setActionCommand("fire"); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + + addWindowListener(new ConfigListener(this)); + } +} \ No newline at end of file diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java new file mode 100644 index 00000000..723f8301 --- /dev/null +++ b/altosui/AltosInfoTable.java @@ -0,0 +1,190 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosInfoTable extends JTable { + private AltosFlightInfoTableModel model; + + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + + static final int info_columns = 3; + static final int info_rows = 17; + + int desired_row_height() { + FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); + return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; + } + + public AltosInfoTable() { + super(new AltosFlightInfoTableModel(info_rows, info_columns)); + model = (AltosFlightInfoTableModel) getModel(); + setFont(infoValueFont); + setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); + setShowGrid(true); + setRowHeight(desired_row_height()); + doLayout(); + } + + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + void info_reset() { + model.reset(); + } + + void info_add_row(int col, String name, String value) { + model.addRow(col, name, value); + } + + void info_add_row(int col, String name, String format, Object... parameters) { + info_add_row (col, name, String.format(format, parameters)); + } + + void info_add_deg(int col, String name, double v, int pos, int neg) { + int c = pos; + if (v < 0) { + c = neg; + v = -v; + } + double deg = Math.floor(v); + double min = (v - deg) * 60; + + info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min)); + } + + void info_finish() { + model.finish(); + } + + public void clear() { + model.clear(); + } + + public void show(AltosState state, int crc_errors) { + if (state == null) + return; + info_reset(); + 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); + info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); + info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); + info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); + info_add_row(0, "Temperature", "%9.2f °C", state.temperature); + info_add_row(0, "Battery", "%9.2f V", state.battery); + info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); + info_add_row(0, "Main", "%9.2f V", state.main_sense); + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); + 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) + info_add_row(1, "GPS", " unlocked"); + else + info_add_row(1, "GPS", " missing"); + info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + info_add_row(1, "GPS altitude", "%6d", state.gps.alt); + info_add_row(1, "GPS height", "%6.0f", state.gps_height); + + /* The SkyTraq GPS doesn't report these values */ + if (false) { + info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", + state.gps.ground_speed, + state.gps.course); + info_add_row(1, "GPS climb rate", "%8.1f m/s", + state.gps.climb_rate); + info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", + state.gps.h_error, state.gps.v_error); + } + info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); + + if (state.npad > 0) { + if (state.from_pad != null) { + 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'); + info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); + } + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.year, + state.gps.month, + state.gps.day); + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.hour, + state.gps.minute, + state.gps.second); + int nsat_vis = 0; + int c; + + if (state.gps.cc_gps_sat == null) + info_add_row(2, "Satellites Visible", "%4d", 0); + else { + info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); + for (c = 0; c < state.gps.cc_gps_sat.length; c++) { + info_add_row(2, "Satellite id,C/N0", + "%4d, %4d", + state.gps.cc_gps_sat[c].svid, + state.gps.cc_gps_sat[c].c_n0); + } + } + } + info_finish(); + } +} diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java new file mode 100644 index 00000000..d586033f --- /dev/null +++ b/altosui/AltosKML.java @@ -0,0 +1,169 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.*; + +public class AltosKML implements AltosWriter { + + File name; + PrintStream out; + int state = -1; + AltosRecord prev = null; + + static final String[] kml_state_colors = { + "FF000000", + "FF000000", + "FF000000", + "FF0000FF", + "FF4080FF", + "FF00FFFF", + "FFFF0000", + "FF00FF00", + "FF000000", + "FFFFFFFF" + }; + + static final String kml_header_start = + "\n" + + "\n" + + "\n" + + " AO Flight#%d S/N: %03d\n" + + " \n"; + static final String kml_header_end = + " \n" + + " 0\n"; + + static final String kml_style_start = + " \n"; + + static final String kml_placemark_start = + " \n" + + " %s\n" + + " #ao-flightstate-%s\n" + + " \n" + + " 1\n" + + " absolute\n" + + " \n"; + + static final String kml_coord_fmt = + " %12.7f, %12.7f, %12.7f \n"; + + static final String kml_placemark_end = + " \n" + + " \n" + + " \n"; + + static final String kml_footer = + "\n" + + "\n"; + + void start (AltosRecord record) { + out.printf(kml_header_start, record.flight, record.serial); + out.printf("Date: %04d-%02d-%02d\n", + record.gps.year, record.gps.month, record.gps.day); + out.printf("Time: %2d:%02d:%02d\n", + record.gps.hour, record.gps.minute, record.gps.second); + out.printf("%s", kml_header_end); + } + + boolean started = false; + + void state_start(AltosRecord record) { + String state_name = Altos.state_name(record.state); + out.printf(kml_style_start, state_name, kml_state_colors[record.state]); + out.printf("\tState: %s\n", state_name); + out.printf("%s", kml_style_end); + out.printf(kml_placemark_start, state_name, state_name); + } + + void state_end(AltosRecord record) { + out.printf("%s", kml_placemark_end); + } + + void coord(AltosRecord record) { + AltosGPS gps = record.gps; + out.printf(kml_coord_fmt, + gps.lon, gps.lat, + record.filtered_altitude(), (double) gps.alt, + record.time, gps.nsat); + } + + void end() { + out.printf("%s", kml_footer); + } + + public void close() { + if (prev != null) { + state_end(prev); + end(); + prev = null; + } + } + + public void write(AltosRecord record) { + AltosGPS gps = record.gps; + + if (gps == null) + return; + if (!started) { + start(record); + started = true; + } + if (prev != null && + prev.gps.second == record.gps.second && + prev.gps.minute == record.gps.minute && + prev.gps.hour == record.gps.hour) + return; + if (record.state != state) { + state = record.state; + if (prev != null) { + coord(record); + state_end(prev); + } + state_start(record); + } + coord(record); + prev = record; + } + + public void write(AltosRecordIterable iterable) { + for (AltosRecord record : iterable) + write(record); + } + + public AltosKML(File in_name) throws FileNotFoundException { + name = in_name; + out = new PrintStream(name); + } + + public AltosKML(String in_string) throws FileNotFoundException { + this(new File(in_string)); + } +} diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java new file mode 100644 index 00000000..d34efe6d --- /dev/null +++ b/altosui/AltosLanded.java @@ -0,0 +1,212 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLanded extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + Font label_font; + Font value_font; + + public class LandedValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + + void show(String format, double v) { + value.setText(String.format(format, v)); + } + + public LandedValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + c.weightx = 0; + c.fill = GridBagConstraints.VERTICAL; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.weightx = 1; + c.fill = GridBagConstraints.BOTH; + layout.setConstraints(value, c); + add(value); + } + } + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class Lat extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lat,"N", "S")); + else + value.setText("???"); + } + public Lat (GridBagLayout layout, int y) { + super (layout, y, "Latitude"); + } + } + + Lat lat; + + class Lon extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.gps != null) + value.setText(pos(state.gps.lon,"E", "W")); + else + value.setText("???"); + } + public Lon (GridBagLayout layout, int y) { + super (layout, y, "Longitude"); + } + } + + Lon lon; + + class Bearing extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%3.0f°", state.from_pad.bearing); + else + value.setText("???"); + } + public Bearing (GridBagLayout layout, int y) { + super (layout, y, "Bearing"); + } + } + + Bearing bearing; + + class Distance extends LandedValue { + void show (AltosState state, int crc_errors) { + if (state.from_pad != null) + show("%6.0f m", state.from_pad.distance); + else + value.setText("???"); + } + public Distance (GridBagLayout layout, int y) { + super (layout, y, "Distance"); + } + } + + Distance distance; + + class Height extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m", state.max_height); + } + public Height (GridBagLayout layout, int y) { + super (layout, y, "Maximum Height"); + } + } + + Height height; + + class Speed extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s", state.max_speed); + } + public Speed (GridBagLayout layout, int y) { + super (layout, y, "Maximum Speed"); + } + } + + Speed speed; + + class Accel extends LandedValue { + void show (AltosState state, int crc_errors) { + show("%6.0f m/s²", state.max_acceleration); + } + public Accel (GridBagLayout layout, int y) { + super (layout, y, "Maximum Acceleration"); + } + } + + Accel accel; + + public void reset() { + lat.reset(); + lon.reset(); + bearing.reset(); + distance.reset(); + height.reset(); + speed.reset(); + accel.reset(); + } + + public void show(AltosState state, int crc_errors) { + bearing.show(state, crc_errors); + distance.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + height.show(state, crc_errors); + speed.show(state, crc_errors); + accel.show(state, crc_errors); + } + + public AltosLanded() { + layout = new GridBagLayout(); + + label_font = new Font("Dialog", Font.PLAIN, 22); + value_font = new Font("Monospaced", Font.PLAIN, 22); + setLayout(layout); + + /* Elements in descent display */ + bearing = new Bearing(layout, 0); + distance = new Distance(layout, 1); + lat = new Lat(layout, 2); + lon = new Lon(layout, 3); + height = new Height(layout, 4); + speed = new Speed(layout, 5); + accel = new Accel(layout, 6); + } +} diff --git a/altosui/AltosLed.java b/altosui/AltosLed.java new file mode 100644 index 00000000..e08e9960 --- /dev/null +++ b/altosui/AltosLed.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLed extends JLabel { + ImageIcon on, off; + + ImageIcon create_icon(String path) { + java.net.URL imgURL = AltosUI.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set(boolean set) { + if (set) + setIcon(on); + else + setIcon(off); + } + + public AltosLed(String on_path, String off_path) { + on = create_icon(on_path); + off = create_icon(off_path); + setIcon(off); + } +} diff --git a/altosui/AltosLights.java b/altosui/AltosLights.java new file mode 100644 index 00000000..2fa38412 --- /dev/null +++ b/altosui/AltosLights.java @@ -0,0 +1,73 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosLights extends JComponent { + + GridBagLayout gridbag; + + AltosLed red, green; + + ImageIcon create_icon(String path, String description) { + java.net.URL imgURL = AltosUI.class.getResource(path); + if (imgURL != null) + return new ImageIcon(imgURL, description); + System.err.printf("Cannot find icon \"%s\"\n", path); + return null; + } + + public void set (boolean on) { + if (on) { + red.set(false); + green.set(true); + } else { + red.set(true); + green.set(false); + } + } + + public AltosLights() { + GridBagConstraints c; + gridbag = new GridBagLayout(); + setLayout(gridbag); + + c = new GridBagConstraints(); + red = new AltosLed("/redled.png", "/grayled.png"); + c.gridx = 0; c.gridy = 0; + c.insets = new Insets (0, 5, 0, 5); + gridbag.setConstraints(red, c); + add(red); + red.set(true); + green = new AltosLed("/greenled.png", "/grayled.png"); + c.gridx = 1; c.gridy = 0; + gridbag.setConstraints(green, c); + add(green); + green.set(false); + } +} diff --git a/altosui/AltosLine.java b/altosui/AltosLine.java new file mode 100644 index 00000000..86e9d4c6 --- /dev/null +++ b/altosui/AltosLine.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java new file mode 100644 index 00000000..dd147d21 --- /dev/null +++ b/altosui/AltosLog.java @@ -0,0 +1,115 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.lang.*; +import java.util.*; +import java.text.ParseException; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * This creates a thread to capture telemetry data and write it to + * a log file + */ +class AltosLog implements Runnable { + + LinkedBlockingQueue input_queue; + LinkedBlockingQueue pending_queue; + int serial; + int flight; + FileWriter log_file; + Thread log_thread; + + private void close_log_file() { + if (log_file != null) { + try { + log_file.close(); + } catch (IOException io) { + } + log_file = null; + } + } + + void close() { + close_log_file(); + if (log_thread != null) { + log_thread.interrupt(); + log_thread = null; + } + } + + boolean open (AltosTelemetry telem) throws IOException { + AltosFile a = new AltosFile(telem); + + log_file = new FileWriter(a, true); + if (log_file != null) { + while (!pending_queue.isEmpty()) { + try { + String s = pending_queue.take(); + log_file.write(s); + log_file.write('\n'); + } catch (InterruptedException ie) { + } + } + log_file.flush(); + } + return log_file != null; + } + + public void run () { + try { + for (;;) { + AltosLine line = input_queue.take(); + if (line.line == null) + continue; + try { + AltosTelemetry telem = new AltosTelemetry(line.line); + if (telem.serial != serial || telem.flight != flight || log_file == null) { + close_log_file(); + serial = telem.serial; + flight = telem.flight; + open(telem); + } + } catch (ParseException pe) { + } catch (AltosCRCException ce) { + } + if (log_file != null) { + log_file.write(line.line); + log_file.write('\n'); + log_file.flush(); + } else + pending_queue.put(line.line); + } + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + close(); + } + + public AltosLog (AltosSerial s) { + pending_queue = new LinkedBlockingQueue (); + input_queue = new LinkedBlockingQueue (); + s.add_monitor(input_queue); + serial = -1; + flight = -1; + log_file = null; + log_thread = new Thread(this); + log_thread.start(); + } +} diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java new file mode 100644 index 00000000..66954347 --- /dev/null +++ b/altosui/AltosPad.java @@ -0,0 +1,269 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosPad extends JComponent implements AltosFlightDisplay { + GridBagLayout layout; + + public class LaunchStatus { + JLabel label; + JTextField value; + AltosLights lights; + + void show(AltosState state, int crc_errors) {} + void reset() { + value.setText(""); + lights.set(false); + } + + public LaunchStatus (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.weighty = 1; + + lights = new AltosLights(); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(lights, c); + add(lights); + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + + } + } + + public class LaunchValue { + JLabel label; + JTextField value; + void show(AltosState state, int crc_errors) {} + + void reset() { + value.setText(""); + } + public LaunchValue (GridBagLayout layout, int y, String text) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.weighty = 1; + + label = new JLabel(text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 1; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + value = new JTextField(Altos.text_width); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = 2; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + class Battery extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.battery)); + lights.set(state.battery > 3.7); + } + public Battery (GridBagLayout layout, int y) { + super(layout, y, "Battery Voltage"); + } + } + + Battery battery; + + class Apogee extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.drogue_sense)); + lights.set(state.drogue_sense > 3.2); + } + public Apogee (GridBagLayout layout, int y) { + super(layout, y, "Apogee Igniter Voltage"); + } + } + + Apogee apogee; + + class Main extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.2f V", state.main_sense)); + lights.set(state.main_sense > 3.2); + } + public Main (GridBagLayout layout, int y) { + super(layout, y, "Main Igniter Voltage"); + } + } + + Main main; + + class GPSLocked extends LaunchStatus { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4d sats", state.gps.nsat)); + lights.set(state.gps.locked); + } + public GPSLocked (GridBagLayout layout, int y) { + super (layout, y, "GPS Locked"); + } + } + + GPSLocked gps_locked; + + class GPSReady extends LaunchStatus { + void show (AltosState state, int crc_errors) { + if (state.gps_ready) + value.setText("Ready"); + else + value.setText(String.format("Waiting %d", state.gps_waiting)); + lights.set(state.gps_ready); + } + public GPSReady (GridBagLayout layout, int y) { + super (layout, y, "GPS Ready"); + } + } + + GPSReady gps_ready; + + String pos(double p, String pos, String neg) { + String h = pos; + if (p < 0) { + h = neg; + p = -p; + } + int deg = (int) Math.floor(p); + double min = (p - Math.floor(p)) * 60.0; + return String.format("%s %4d° %9.6f", h, deg, min); + } + + class PadLat extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(pos(state.pad_lat,"N", "S")); + } + public PadLat (GridBagLayout layout, int y) { + super (layout, y, "Pad Latitude"); + } + } + + PadLat pad_lat; + + class PadLon extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(pos(state.pad_lon,"E", "W")); + } + public PadLon (GridBagLayout layout, int y) { + super (layout, y, "Pad Longitude"); + } + } + + PadLon pad_lon; + + class PadAlt extends LaunchValue { + void show (AltosState state, int crc_errors) { + value.setText(String.format("%4.0f m", state.pad_alt)); + } + public PadAlt (GridBagLayout layout, int y) { + super (layout, y, "Pad Altitude"); + } + } + + PadAlt pad_alt; + + public void reset() { + battery.reset(); + apogee.reset(); + main.reset(); + gps_locked.reset(); + gps_ready.reset(); + pad_lat.reset(); + pad_lon.reset(); + pad_alt.reset(); + } + + public void show(AltosState state, int crc_errors) { + battery.show(state, crc_errors); + apogee.show(state, crc_errors); + main.show(state, crc_errors); + gps_locked.show(state, crc_errors); + gps_ready.show(state, crc_errors); + pad_lat.show(state, crc_errors); + pad_lon.show(state, crc_errors); + pad_alt.show(state, crc_errors); + } + + public AltosPad() { + layout = new GridBagLayout(); + + setLayout(layout); + + /* Elements in pad display: + * + * Battery voltage + * Igniter continuity + * GPS lock status + * GPS ready status + * GPS location + * Pad altitude + * RSSI + */ + battery = new Battery(layout, 0); + apogee = new Apogee(layout, 1); + main = new Main(layout, 2); + gps_locked = new GPSLocked(layout, 3); + gps_ready = new GPSReady(layout, 4); + pad_lat = new PadLat(layout, 5); + pad_lon = new PadLon(layout, 6); + pad_alt = new PadAlt(layout, 7); + } +} diff --git a/altosui/AltosParse.java b/altosui/AltosParse.java new file mode 100644 index 00000000..fbfcaaee --- /dev/null +++ b/altosui/AltosParse.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.lang.*; + +public class AltosParse { + static boolean isdigit(char c) { + return '0' <= c && c <= '9'; + } + + static int parse_int(String v) throws ParseException { + try { + 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 Altos.fromhex(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing hex " + v, 0); + } + } + + static double parse_double(String v) throws ParseException { + try { + return Double.parseDouble(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing double " + v, 0); + } + } + + static double parse_coord(String coord) throws ParseException { + String[] dsf = coord.split("\\D+"); + + if (dsf.length != 3) { + throw new ParseException("error parsing coord " + coord, 0); + } + int deg = parse_int(dsf[0]); + int min = parse_int(dsf[1]); + int frac = parse_int(dsf[2]); + + double r = deg + (min + frac / 10000.0) / 60.0; + if (coord.endsWith("S") || coord.endsWith("W")) + r = -r; + return r; + } + + static String strip_suffix(String v, String suffix) { + if (v.endsWith(suffix)) + return v.substring(0, v.length() - suffix.length()); + return v; + } + + static void word(String v, String m) throws ParseException { + if (!v.equals(m)) { + throw new ParseException("error matching '" + v + "' '" + m + "'", 0); + } + } +} diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java new file mode 100644 index 00000000..e2a3df3b --- /dev/null +++ b/altosui/AltosPreferences.java @@ -0,0 +1,205 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.awt.Component; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; + +class AltosPreferences { + static Preferences preferences; + + /* logdir preference name */ + final static String logdirPreference = "LOGDIR"; + + /* channel preference name */ + final static String channelPreferenceFormat = "CHANNEL-%d"; + + /* voice preference name */ + final static String voicePreference = "VOICE"; + + /* callsign preference name */ + final static String callsignPreference = "CALLSIGN"; + + /* firmware directory preference name */ + final static String firmwaredirPreference = "FIRMWARE"; + + /* Default logdir is ~/TeleMetrum */ + final static String logdirName = "TeleMetrum"; + + /* UI Component to pop dialogs up */ + static Component component; + + /* Log directory */ + static File logdir; + + /* Channel (map serial to channel) */ + static Hashtable channels; + + /* Voice preference */ + static boolean voice; + + /* Callsign preference */ + static String callsign; + + /* Firmware directory */ + static File firmwaredir; + + public static void init(Component ui) { + preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + + component = ui; + + /* Initialize logdir from preferences */ + String logdir_string = preferences.get(logdirPreference, null); + if (logdir_string != null) + logdir = new File(logdir_string); + else { + /* Use the file system view default directory */ + logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); + if (!logdir.exists()) + logdir.mkdirs(); + } + + channels = new Hashtable(); + + voice = preferences.getBoolean(voicePreference, true); + + callsign = preferences.get(callsignPreference,"N0CALL"); + + String firmwaredir_string = preferences.get(firmwaredirPreference, null); + if (firmwaredir_string != null) + firmwaredir = new File(firmwaredir_string); + else + firmwaredir = null; + } + + static void flush_preferences() { + try { + preferences.flush(); + } catch (BackingStoreException ee) { + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + } + } + + public static void set_logdir(File new_logdir) { + logdir = new_logdir; + synchronized (preferences) { + preferences.put(logdirPreference, logdir.getPath()); + flush_preferences(); + } + } + + private static boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + } else if (!dir.isDirectory()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + public static void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + + public static File logdir() { + return logdir; + } + + public static void set_channel(int serial, int new_channel) { + channels.put(serial, new_channel); + synchronized (preferences) { + preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel); + flush_preferences(); + } + } + + public static int channel(int serial) { + if (channels.containsKey(serial)) + return channels.get(serial); + int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + channels.put(serial, channel); + return channel; + } + + public static void set_voice(boolean new_voice) { + voice = new_voice; + synchronized (preferences) { + preferences.putBoolean(voicePreference, voice); + flush_preferences(); + } + } + + public static boolean voice() { + return voice; + } + + public static void set_callsign(String new_callsign) { + callsign = new_callsign; + synchronized(preferences) { + preferences.put(callsignPreference, callsign); + flush_preferences(); + } + } + + public static String callsign() { + return callsign; + } + + public static void set_firmwaredir(File new_firmwaredir) { + firmwaredir = new_firmwaredir; + synchronized (preferences) { + preferences.put(firmwaredirPreference, firmwaredir.getPath()); + flush_preferences(); + } + } + + public static File firmwaredir() { + return firmwaredir; + } +} diff --git a/altosui/AltosReader.java b/altosui/AltosReader.java new file mode 100644 index 00000000..b9280a0c --- /dev/null +++ b/altosui/AltosReader.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; + +public class AltosReader { + public AltosRecord read() throws IOException, ParseException { return null; } + public void close() { } + public void write_comments(PrintStream out) { } +} diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java new file mode 100644 index 00000000..1160a273 --- /dev/null +++ b/altosui/AltosRecord.java @@ -0,0 +1,219 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; +import java.io.*; + +public class AltosRecord { + int version; + String callsign; + int serial; + int flight; + int rssi; + int status; + int state; + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + int flight_accel; + int ground_accel; + int flight_vel; + int flight_pres; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + AltosGPS gps; + + double time; /* seconds since boost */ + + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + static final double counts_per_kPa = 27 * 2047 / 3300; + static final double counts_at_101_3kPa = 1674.0; + + static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + public double raw_pressure() { + return barometer_to_pressure(pres); + } + + public double filtered_pressure() { + return barometer_to_pressure(flight_pres); + } + + public double ground_pressure() { + return barometer_to_pressure(ground_pres); + } + + public double filtered_altitude() { + return AltosConvert.pressure_to_altitude(filtered_pressure()); + } + + public double raw_altitude() { + return AltosConvert.pressure_to_altitude(raw_pressure()); + } + + public double ground_altitude() { + return AltosConvert.pressure_to_altitude(ground_pressure()); + } + + public double filtered_height() { + return filtered_altitude() - ground_altitude(); + } + + public double raw_height() { + return raw_altitude() - ground_altitude(); + } + + public double battery_voltage() { + return AltosConvert.cc_battery_to_voltage(batt); + } + + public double main_voltage() { + return AltosConvert.cc_ignitor_to_voltage(main); + } + + public double drogue_voltage() { + return AltosConvert.cc_ignitor_to_voltage(drogue); + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public double temperature() { + return thermometer_to_temperature(temp); + } + + double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + public double acceleration() { + return (ground_accel - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + double speed = flight_vel / (accel_counts_per_mss() * 100.0); + return speed; + } + + public String state() { + return Altos.state_name(state); + } + + public static String gets(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') { + return line; + } + line = line + (char) c; + } + return null; + } + + public AltosRecord(AltosRecord old) { + version = old.version; + callsign = old.callsign; + serial = old.serial; + flight = old.flight; + rssi = old.rssi; + status = old.status; + state = old.state; + tick = old.tick; + accel = old.accel; + pres = old.pres; + temp = old.temp; + batt = old.batt; + drogue = old.drogue; + main = old.main; + flight_accel = old.flight_accel; + ground_accel = old.ground_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + gps = new AltosGPS(old.gps); + } + + public AltosRecord() { + version = 0; + callsign = "N0CALL"; + serial = 0; + flight = 0; + rssi = 0; + status = 0; + state = Altos.ao_flight_startup; + tick = 0; + accel = 0; + pres = 0; + temp = 0; + batt = 0; + drogue = 0; + main = 0; + flight_accel = 0; + ground_accel = 0; + flight_vel = 0; + flight_pres = 0; + ground_pres = 0; + accel_plus_g = 0; + accel_minus_g = 0; + gps = new AltosGPS(); + } +} diff --git a/altosui/AltosRecordIterable.java b/altosui/AltosRecordIterable.java new file mode 100644 index 00000000..a7df92d1 --- /dev/null +++ b/altosui/AltosRecordIterable.java @@ -0,0 +1,34 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public abstract class AltosRecordIterable implements Iterable { + public abstract Iterator iterator(); + public void write_comments(PrintStream out) { } +} diff --git a/altosui/AltosReplayReader.java b/altosui/AltosReplayReader.java new file mode 100644 index 00000000..4e5e1d93 --- /dev/null +++ b/altosui/AltosReplayReader.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +/* + * Open an existing telemetry file and replay it in realtime + */ + +public class AltosReplayReader extends AltosFlightReader { + Iterator iterator; + + public AltosRecord read() { + if (iterator.hasNext()) + return iterator.next(); + return null; + } + + public void close (boolean interrupted) { + } + + void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > Altos.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + } + + public AltosReplayReader(Iterator in_iterator, String in_name) { + iterator = in_iterator; + name = in_name; + } +} diff --git a/altosui/AltosRomconfig.java b/altosui/AltosRomconfig.java new file mode 100644 index 00000000..55056b5e --- /dev/null +++ b/altosui/AltosRomconfig.java @@ -0,0 +1,147 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +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; + } +} diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java new file mode 100644 index 00000000..e1dc974e --- /dev/null +++ b/altosui/AltosRomconfigUI.java @@ -0,0 +1,186 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +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; + } +} diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java new file mode 100644 index 00000000..b19143e5 --- /dev/null +++ b/altosui/AltosSerial.java @@ -0,0 +1,253 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Deal with TeleDongle on a serial port + */ + +package altosui; + +import java.lang.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; + +import libaltosJNI.*; + +/* + * This class reads from the serial port and places each received + * line in a queue. Dealing with that queue is left up to other + * threads. + */ + +public class AltosSerial implements Runnable { + + static List devices_opened = Collections.synchronizedList(new LinkedList()); + + AltosDevice device; + SWIGTYPE_p_altos_file altos; + LinkedList> monitors; + LinkedBlockingQueue reply_queue; + Thread input_thread; + String line; + byte[] line_bytes; + int line_count; + boolean monitor_mode; + + public void run () { + int c; + + try { + for (;;) { + c = libaltos.altos_getchar(altos, 0); + if (Thread.interrupted()) + break; + if (c == libaltosConstants.LIBALTOS_ERROR) { + for (int e = 0; e < monitors.size(); e++) { + LinkedBlockingQueue 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_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 q = monitors.get(e); + q.put(new AltosLine (line)); + } + } else { +// System.out.printf("GOT: %s\n", line); + reply_queue.put(new AltosLine (line)); + } + line_count = 0; + line = ""; + } + } else { + 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++; + } + } + } + } catch (InterruptedException e) { + } + } + + public void flush_output() { + if (altos != null) + libaltos.altos_flush(altos); + } + + public void flush_input() { + flush_output(); + boolean got_some; + do { + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + got_some = !reply_queue.isEmpty(); + synchronized(this) { + if (!"VERSION".startsWith(line) && + !line.startsWith("VERSION")) + line = ""; + reply_queue.clear(); + } + } while (got_some); + } + + public String get_reply() throws InterruptedException { + flush_output(); + AltosLine line = reply_queue.take(); + return line.line; + } + + public String get_reply(int timeout) throws InterruptedException { + flush_output(); + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line == null) + return null; + return line.line; + } + + public void add_monitor(LinkedBlockingQueue q) { + set_monitor(true); + monitors.add(q); + } + + public void remove_monitor(LinkedBlockingQueue q) { + monitors.remove(q); + if (monitors.isEmpty()) + set_monitor(false); + } + + public void close() { + if (altos != null) { + libaltos.altos_close(altos); + } + if (input_thread != null) { + try { + input_thread.interrupt(); + input_thread.join(); + } catch (InterruptedException e) { + } + input_thread = null; + } + if (altos != null) { + libaltos.altos_free(altos); + altos = null; + } + synchronized (devices_opened) { + devices_opened.remove(device.getPath()); + } + } + + public void putc(char c) { + if (altos != null) + libaltos.altos_putchar(altos, c); + } + + public void print(String data) { +// System.out.printf("\"%s\" ", data); + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); + } + + public void printf(String format, Object ... arguments) { + print(String.format(format, arguments)); + } + + private void open() throws FileNotFoundException, AltosSerialInUseException { + synchronized (devices_opened) { + if (devices_opened.contains(device.getPath())) + throw new AltosSerialInUseException(device); + devices_opened.add(device.getPath()); + } + altos = libaltos.altos_open(device); + if (altos == null) { + close(); + throw new FileNotFoundException(device.toShortString()); + } + input_thread = new Thread(this); + input_thread.start(); + print("~\nE 0\n"); + set_monitor(false); + flush_output(); + } + + public void set_radio() { + set_channel(AltosPreferences.channel(device.getSerial())); + set_callsign(AltosPreferences.callsign()); + } + + public void set_channel(int 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) { + printf ("c c %s\n", callsign); + flush_output(); + } + } + + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + device = in_device; + line = ""; + monitor_mode = false; + monitors = new LinkedList> (); + reply_queue = new LinkedBlockingQueue (); + open(); + } +} diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java new file mode 100644 index 00000000..4b108c7c --- /dev/null +++ b/altosui/AltosSerialInUseException.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 libaltosJNI.*; + +public class AltosSerialInUseException extends Exception { + public altos_device device; + + public AltosSerialInUseException (altos_device in_device) { + device = in_device; + } +} diff --git a/altosui/AltosSerialMonitor.java b/altosui/AltosSerialMonitor.java new file mode 100644 index 00000000..ad0e9295 --- /dev/null +++ b/altosui/AltosSerialMonitor.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 interface AltosSerialMonitor { + void data(String data); +} diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java new file mode 100644 index 00000000..80970605 --- /dev/null +++ b/altosui/AltosSiteMap.java @@ -0,0 +1,388 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { + // preferred vertical step in a tile in naut. miles + // will actually choose a step size between x and 2x, where this + // is 1.5x + static final double tile_size_nmi = 0.75; + + static final int px_size = 512; + + static final int MAX_TILE_DELTA = 100; + + private static Point2D.Double translatePoint(Point2D.Double p, + Point2D.Double d) + { + return new Point2D.Double(p.x + d.x, p.y + d.y); + } + + static class LatLng { + public double lat, lng; + public LatLng(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } + + // based on google js + // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js + // search for fromLatLngToPoint and fromPointToLatLng + private static Point2D.Double pt(LatLng latlng, int zoom) { + double scale_x = 256/360.0 * Math.pow(2, zoom); + double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + return pt(latlng, scale_x, scale_y); + } + + private static Point2D.Double pt(LatLng latlng, + double scale_x, double scale_y) + { + Point2D.Double res = new Point2D.Double(); + double e; + + res.x = latlng.lng * scale_x; + + e = Math.sin(Math.toRadians(latlng.lat)); + e = Math.max(e,-(1-1.0E-15)); + e = Math.min(e, 1-1.0E-15 ); + + res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; + return res; + } + + static private LatLng latlng(Point2D.Double pt, + double scale_x, double scale_y) + { + double lat, lng; + double rads; + + lng = pt.x/scale_x; + rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); + lat = Math.toDegrees(rads - Math.PI/2); + + return new LatLng(lat,lng); + } + + int zoom; + double scale_x, scale_y; + + private Point2D.Double pt(double lat, double lng) { + return pt(new LatLng(lat, lng), scale_x, scale_y); + } + + private LatLng latlng(double x, double y) { + return latlng(new Point2D.Double(x,y), scale_x, scale_y); + } + private LatLng latlng(Point2D.Double pt) { + return latlng(pt, scale_x, scale_y); + } + + HashMap mapTiles = new HashMap(); + Point2D.Double centre; + + private Point2D.Double tileCoordOffset(Point p) { + return new Point2D.Double(centre.x - p.x*px_size, + centre.y - p.y * px_size); + } + + private Point tileOffset(Point2D.Double p) { + return new Point((int)Math.floor((centre.x+p.x)/px_size), + (int)Math.floor((centre.y+p.y)/px_size)); + } + + private Point2D.Double getBaseLocation(double lat, double lng) { + Point2D.Double locn, north_step; + + zoom = 2; + // stupid loop structure to please Java's control flow analysis + do { + zoom++; + scale_x = 256/360.0 * Math.pow(2, zoom); + scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); + locn = pt(lat, lng); + north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); + if (locn.y - north_step.y > px_size) + break; + } while (zoom < 22); + locn.x = -px_size * Math.floor(locn.x/px_size); + locn.y = -px_size * Math.floor(locn.y/px_size); + return locn; + } + + public void reset() { + // nothing + } + + private void bgLoadMap(final AltosSiteMapTile tile, + final File pngfile, final String pngurl) + { + //System.out.printf("Loading/fetching map %s\n", pngfile); + Thread thread = new Thread() { + public void run() { + ImageIcon res; + res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); + if (res != null) { + tile.loadMap(res); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } + }; + thread.start(); + } + + public static void prefetchMaps(double lat, double lng, int w, int h) { + AltosPreferences.init(null); + + AltosSiteMap asm = new AltosSiteMap(true); + asm.centre = asm.getBaseLocation(lat, lng); + + Point2D.Double p = new Point2D.Double(); + Point2D.Double p2; + int dx = -w/2, dy = -h/2; + for (int y = dy; y < h+dy; y++) { + for (int x = dx; x < w+dx; x++) { + LatLng map_latlng = asm.latlng( + -asm.centre.x + x*px_size + px_size/2, + -asm.centre.y + y*px_size + px_size/2); + File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); + if (pngfile.exists()) { + System.out.printf("Already have %s\n", pngfile); + } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { + System.out.printf("Fetched map %s\n", pngfile); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + } + } + } + } + + private void initMap(AltosSiteMapTile tile, Point offset) { + Point2D.Double coord = tileCoordOffset(offset); + + LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); + + File pngfile = MapFile(map_latlng.lat, map_latlng.lng); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng); + bgLoadMap(tile, pngfile, pngurl); + } + + private void initMaps(double lat, double lng) { + centre = getBaseLocation(lat, lng); + + for (Point k : mapTiles.keySet()) { + initMap(mapTiles.get(k), k); + } + } + + private File MapFile(double lat, double lng) { + char chlat = lat < 0 ? 'S' : 'N'; + char chlng = lng < 0 ? 'E' : 'W'; + if (lat < 0) lat = -lat; + if (lng < 0) lng = -lng; + return new File(AltosPreferences.logdir(), + String.format("map-%c%.6f,%c%.6f-%d.png", + chlat, lat, chlng, lng, zoom)); + } + + private String MapURL(double lat, double lng) { + return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); + } + + boolean initialised = false; + Point2D.Double last_pt = null; + int last_state = -1; + public void show(final AltosState state, final int crc_errors) { + // if insufficient gps data, nothing to update + if (state.gps == null) + return; + if (state.pad_lat == 0 && state.pad_lon == 0) + return; + if (!state.gps.locked) { + if (state.gps.nsat < 4) + return; + } + + if (!initialised) { + initMaps(state.pad_lat, state.pad_lon); + initialised = true; + } + + final Point2D.Double pt = pt(state.gps.lat, state.gps.lon); + if (last_pt == pt && last_state == state.state) + return; + + if (last_pt == null) { + last_pt = pt; + } + boolean in_any = false; + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); + tile.show(state, crc_errors, lref, ref); + if (0 <= ref.x && ref.x < px_size) + if (0 <= ref.y && ref.y < px_size) + in_any = true; + } + + Point offset = tileOffset(pt); + if (!in_any) { + Point2D.Double ref, lref; + ref = translatePoint(pt, tileCoordOffset(offset)); + lref = translatePoint(last_pt, tileCoordOffset(offset)); + + AltosSiteMapTile tile = createTile(offset); + tile.show(state, crc_errors, lref, ref); + initMap(tile, offset); + finishTileLater(tile, offset); + } + + scrollRocketToVisible(pt); + + if (offset != tileOffset(last_pt)) { + ensureTilesAround(offset); + } + + last_pt = pt; + last_state = state.state; + } + + private AltosSiteMapTile createTile(Point offset) { + AltosSiteMapTile tile = new AltosSiteMapTile(px_size); + mapTiles.put(offset, tile); + return tile; + } + private void finishTileLater(final AltosSiteMapTile tile, + final Point offset) + { + SwingUtilities.invokeLater( new Runnable() { + public void run() { + addTileAt(tile, offset); + } + } ); + } + + private void ensureTilesAround(Point base_offset) { + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + Point offset = new Point(base_offset.x + x, base_offset.y + y); + if (mapTiles.containsKey(offset)) + continue; + AltosSiteMapTile tile = createTile(offset); + initMap(tile, offset); + finishTileLater(tile, offset); + } + } + } + + private Point topleft = new Point(0,0); + private void scrollRocketToVisible(Point2D.Double pt) { + Rectangle r = comp.getVisibleRect(); + Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); + int dx = (int)copt.x - r.width/2 - r.x; + int dy = (int)copt.y - r.height/2 - r.y; + if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { + r.x += dx; + r.y += dy; + comp.scrollRectToVisible(r); + } + } + + private void addTileAt(AltosSiteMapTile tile, Point offset) { + if (Math.abs(offset.x) >= MAX_TILE_DELTA || + Math.abs(offset.y) >= MAX_TILE_DELTA) + { + System.out.printf("Rocket too far away from pad (tile %d,%d)\n", + offset.x, offset.y); + return; + } + + boolean review = false; + Rectangle r = comp.getVisibleRect(); + if (offset.x < topleft.x) { + r.x += (topleft.x - offset.x) * px_size; + topleft.x = offset.x; + review = true; + } + if (offset.y < topleft.y) { + r.y += (topleft.y - offset.y) * px_size; + topleft.y = offset.y; + review = true; + } + GridBagConstraints c = new GridBagConstraints(); + c.anchor = GridBagConstraints.CENTER; + c.fill = GridBagConstraints.BOTH; + // put some space between the map tiles, debugging only + // c.insets = new Insets(5, 5, 5, 5); + + c.gridx = offset.x + MAX_TILE_DELTA; + c.gridy = offset.y + MAX_TILE_DELTA; + layout.setConstraints(tile, c); + + comp.add(tile); + if (review) { + comp.scrollRectToVisible(r); + } + } + + private AltosSiteMap(boolean knowWhatYouAreDoing) { + if (!knowWhatYouAreDoing) { + throw new RuntimeException("Arggh."); + } + } + + JComponent comp = new JComponent() { }; + private GridBagLayout layout = new GridBagLayout(); + + public AltosSiteMap() { + GrabNDrag scroller = new GrabNDrag(comp); + + comp.setLayout(layout); + + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + Point offset = new Point(x, y); + AltosSiteMapTile t = createTile(offset); + addTileAt(t, offset); + } + } + setViewportView(comp); + setPreferredSize(new Dimension(500,200)); + } +} diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java new file mode 100644 index 00000000..2e62cc45 --- /dev/null +++ b/altosui/AltosSiteMapCache.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.net.URL; +import java.net.URLConnection; + +public class AltosSiteMapCache extends JLabel { + public static boolean fetchMap(File file, String url) { + URL u; + + try { + u = new URL(url); + } catch (java.net.MalformedURLException e) { + return false; + } + + byte[] data; + try { + URLConnection uc = u.openConnection(); + int contentLength = uc.getContentLength(); + InputStream in = new BufferedInputStream(uc.getInputStream()); + int bytesRead = 0; + int offset = 0; + data = new byte[contentLength]; + while (offset < contentLength) { + bytesRead = in.read(data, offset, data.length - offset); + if (bytesRead == -1) + break; + offset += bytesRead; + } + in.close(); + + if (offset != contentLength) { + return false; + } + } catch (IOException e) { + return false; + } + + try { + FileOutputStream out = new FileOutputStream(file); + out.write(data); + out.flush(); + out.close(); + } catch (FileNotFoundException e) { + return false; + } catch (IOException e) { + if (file.exists()) { + file.delete(); + } + return false; + } + return true; + } + + public static ImageIcon fetchAndLoadMap(File pngfile, String url) { + if (!pngfile.exists()) { + if (!fetchMap(pngfile, url)) { + return null; + } + } + return loadMap(pngfile, url); + } + + public static ImageIcon loadMap(File pngfile, String url) { + if (!pngfile.exists()) { + return null; + } + + try { + return new ImageIcon(ImageIO.read(pngfile)); + } catch (IOException e) { + System.out.printf("# IO error trying to load %s\n", pngfile); + return null; + } + } +} diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java new file mode 100644 index 00000000..8301f42b --- /dev/null +++ b/altosui/AltosSiteMapTile.java @@ -0,0 +1,112 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +public class AltosSiteMapTile extends JLayeredPane { + JLabel mapLabel; + JLabel draw; + Graphics2D g2d; + + public void loadMap(ImageIcon icn) { + mapLabel.setIcon(icn); + } + + static Color stateColors[] = { + Color.WHITE, // startup + Color.WHITE, // idle + Color.WHITE, // pad + Color.RED, // boost + Color.PINK, // fast + Color.YELLOW, // coast + Color.CYAN, // drogue + Color.BLUE, // main + Color.BLACK // landed + }; + + private boolean drawn_landed_circle = false; + private boolean drawn_boost_circle = false; + public synchronized void show(AltosState state, int crc_errors, + Point2D.Double last_pt, Point2D.Double pt) + { + if (0 <= state.state && state.state < stateColors.length) { + g2d.setColor(stateColors[state.state]); + } + g2d.draw(new Line2D.Double(last_pt, pt)); + + if (state.state == 3 && !drawn_boost_circle) { + drawn_boost_circle = true; + g2d.setColor(Color.RED); + g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); + g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); + g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); + } + if (state.state == 8 && !drawn_landed_circle) { + drawn_landed_circle = true; + g2d.setColor(Color.BLACK); + g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + + repaint(); + } + + public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { + BufferedImage img = new BufferedImage(px_size, px_size, + BufferedImage.TYPE_INT_ARGB); + Graphics2D g = img.createGraphics(); + g.setColor(c); + g.fillRect(0, 0, px_size, px_size); + l.setIcon(new ImageIcon(img)); + return g; + } + + public AltosSiteMapTile(int px_size) { + setPreferredSize(new Dimension(px_size, px_size)); + + mapLabel = new JLabel(); + fillLabel(mapLabel, Color.GRAY, px_size); + mapLabel.setOpaque(true); + mapLabel.setBounds(0, 0, px_size, px_size); + add(mapLabel, new Integer(0)); + + draw = new JLabel(); + g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); + draw.setBounds(0, 0, px_size, px_size); + draw.setOpaque(false); + + add(draw, new Integer(1)); + } +} diff --git a/altosui/AltosState.java b/altosui/AltosState.java new file mode 100644 index 00000000..ec499d5a --- /dev/null +++ b/altosui/AltosState.java @@ -0,0 +1,197 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Track flight state from telemetry or eeprom data stream + */ + +package altosui; + +public class AltosState { + AltosRecord data; + + /* derived data */ + + long report_time; + + double time_change; + int tick; + + int state; + boolean landed; + boolean ascent; /* going up? */ + + double ground_altitude; + double height; + double speed; + double acceleration; + double battery; + double temperature; + double main_sense; + double drogue_sense; + double baro_speed; + + double max_height; + double max_acceleration; + double max_speed; + + AltosGPS gps; + + double pad_lat; + double pad_lon; + double pad_alt; + + static final int MIN_PAD_SAMPLES = 10; + + int npad; + int ngps; + int gps_waiting; + boolean gps_ready; + + AltosGreatCircle from_pad; + double elevation; /* from pad */ + double range; /* total distance */ + + double gps_height; + + int speak_tick; + double speak_altitude; + + + void init (AltosRecord cur, AltosState prev_state) { + int i; + AltosRecord prev; + + data = cur; + + ground_altitude = data.ground_altitude(); + height = data.filtered_altitude() - ground_altitude; + + report_time = System.currentTimeMillis(); + + acceleration = data.acceleration(); + speed = data.accel_speed(); + temperature = data.temperature(); + drogue_sense = data.drogue_voltage(); + main_sense = data.main_voltage(); + battery = data.battery_voltage(); + tick = data.tick; + state = data.state; + + if (prev_state != null) { + + /* Preserve any existing gps data */ + npad = prev_state.npad; + ngps = prev_state.ngps; + gps = prev_state.gps; + pad_lat = prev_state.pad_lat; + pad_lon = prev_state.pad_lon; + pad_alt = prev_state.pad_alt; + max_height = prev_state.max_height; + max_acceleration = prev_state.max_acceleration; + max_speed = prev_state.max_speed; + + /* make sure the clock is monotonic */ + while (tick < prev_state.tick) + tick += 65536; + + time_change = (tick - prev_state.tick) / 100.0; + + /* compute barometric speed */ + + double height_change = height - prev_state.height; + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } else { + npad = 0; + ngps = 0; + gps = null; + baro_speed = 0; + time_change = 0; + } + + if (state == Altos.ao_flight_pad) { + + /* Track consecutive 'good' gps reports, waiting for 10 of them */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) + npad++; + else + npad = 0; + + /* Average GPS data while on the pad */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { + if (ngps > 1) { + /* filter pad position */ + pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; + pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; + pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; + } else { + pad_lat = data.gps.lat; + pad_lon = data.gps.lon; + pad_alt = data.gps.alt; + } + ngps++; + } + } + + gps_waiting = MIN_PAD_SAMPLES - npad; + if (gps_waiting < 0) + gps_waiting = 0; + + gps_ready = gps_waiting == 0; + + ascent = (Altos.ao_flight_boost <= state && + state <= Altos.ao_flight_coast); + + /* Only look at accelerometer data on the way up */ + if (ascent && acceleration > max_acceleration) + max_acceleration = acceleration; + if (ascent && speed > max_speed) + max_speed = speed; + + if (height > max_height) + max_height = height; + if (data.gps != null) { + if (gps == null || !gps.locked || data.gps.locked) + gps = data.gps; + if (ngps > 0 && gps.locked) { + from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); + } + } + elevation = 0; + range = -1; + if (ngps > 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; + } + } + + public AltosState(AltosRecord cur) { + init(cur, null); + } + + public AltosState (AltosRecord cur, AltosState prev) { + init(cur, prev); + } +} diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java new file mode 100644 index 00000000..bdb6466a --- /dev/null +++ b/altosui/AltosTelemetry.java @@ -0,0 +1,143 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The telemetry data stream is a bit of a mess at present, with no consistent + * formatting. In particular, the GPS data is formatted for viewing instead of parsing. + * However, the key feature is that every telemetry line contains all of the information + * necessary to describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + */ + +public class AltosTelemetry extends AltosRecord { + public AltosTelemetry(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + 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++]); + + 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++], "STATE"); + state = Altos.state(words[i++]); + + tick = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a:"); + accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "p:"); + pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "t:"); + temp = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "v:"); + batt = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "d:"); + drogue = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "m:"); + main = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fa:"); + flight_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "ga:"); + ground_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fv:"); + flight_vel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fp:"); + flight_pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "gp:"); + ground_pres = 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++]); + } else { + accel_plus_g = ground_accel; + accel_minus_g = ground_accel + 530; + } + + gps = new AltosGPS(words, i, version); + } +} diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java new file mode 100644 index 00000000..a71ab872 --- /dev/null +++ b/altosui/AltosTelemetryIterable.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; + +public class AltosTelemetryIterable extends AltosRecordIterable { + LinkedList records; + + public Iterator iterator () { + return records.iterator(); + } + + public AltosTelemetryIterable (FileInputStream input) { + boolean saw_boost = false; + int current_tick = 0; + int boost_tick = 0; + + records = new LinkedList (); + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) { + break; + } + try { + AltosTelemetry record = new AltosTelemetry(line); + if (record == null) + break; + if (records.isEmpty()) { + current_tick = record.tick; + } else { + int tick = record.tick | (current_tick & ~ 0xffff); + if (tick < current_tick - 0x1000) + tick += 0x10000; + current_tick = tick; + record.tick = current_tick; + } + 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) { + System.out.printf("io exception\n"); + } + + /* adjust all tick counts to be relative to boost time */ + for (AltosRecord r : this) + r.time = (r.tick - boost_tick) / 100.0; + + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java new file mode 100644 index 00000000..6c5a9397 --- /dev/null +++ b/altosui/AltosTelemetryReader.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; +import java.util.concurrent.*; + +class AltosTelemetryReader extends AltosFlightReader { + AltosDevice device; + AltosSerial serial; + AltosLog log; + + LinkedBlockingQueue telem; + + 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(boolean interrupted) { + serial.remove_monitor(telem); + log.close(); + serial.close(); + } + + void set_channel(int channel) { + serial.set_channel(channel); + AltosPreferences.set_channel(device.getSerial(), channel); + } + + public AltosTelemetryReader (AltosDevice in_device) + throws FileNotFoundException, AltosSerialInUseException, IOException { + device = in_device; + serial = new AltosSerial(device); + log = new AltosLog(serial); + name = device.toShortString(); + + telem = new LinkedBlockingQueue(); + serial.set_radio(); + serial.add_monitor(telem); + } +} diff --git a/altosui/AltosUI.app/Contents/Info.plist b/altosui/AltosUI.app/Contents/Info.plist new file mode 100644 index 00000000..97b1b59c --- /dev/null +++ b/altosui/AltosUI.app/Contents/Info.plist @@ -0,0 +1,38 @@ + + + + + CFBundleName + altosui + CFBundleVersion + 100.0 + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleGetInfoString + AltOS UI version 0.7 + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + AltosUIIcon.icns + Java + + MainClass + altosui.AltosUI + JVMVersion + 1.5+ + ClassPath + + $JAVAROOT/altosui.jar + $JAVAROOT/freetts.jar + + + + diff --git a/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub new file mode 100755 index 00000000..c661d3e1 Binary files /dev/null and b/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub differ diff --git a/altosui/AltosUI.app/Contents/PkgInfo b/altosui/AltosUI.app/Contents/PkgInfo new file mode 100644 index 00000000..8a43480f --- /dev/null +++ b/altosui/AltosUI.app/Contents/PkgInfo @@ -0,0 +1 @@ +APPLAM.O diff --git a/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns new file mode 100644 index 00000000..fe49f362 Binary files /dev/null and b/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns differ diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java new file mode 100644 index 00000000..94c4dd2a --- /dev/null +++ b/altosui/AltosUI.java @@ -0,0 +1,405 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 libaltosJNI.*; + +public class AltosUI extends JFrame { + public AltosVoice voice = new AltosVoice(); + + public static boolean load_library(Frame frame) { + if (!AltosDevice.load_library()) { + JOptionPane.showMessageDialog(frame, + String.format("No AltOS library in \"%s\"", + System.getProperty("java.library.path","")), + "Cannot load device access library", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + void telemetry_window(AltosDevice device) { + try { + AltosFlightReader reader = new AltosTelemetryReader(device); + if (reader != null) + new AltosFlightUI(voice, reader, device.getSerial()); + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(AltosUI.this, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(AltosUI.this, + device.toShortString(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); + } + } + + Container pane; + GridBagLayout gridbag; + + JButton addButton(int x, int y, String label) { + GridBagConstraints c; + JButton b; + + c = new GridBagConstraints(); + c.gridx = x; c.gridy = y; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + b = new JButton(label); + + Dimension ps = b.getPreferredSize(); + + gridbag.setConstraints(b, c); + add(b, c); + return b; + } + + public AltosUI() { + + load_library(null); + + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); + if (imgURL != null) + setIconImage(new ImageIcon(imgURL).getImage()); + + AltosPreferences.init(this); + + pane = getContentPane(); + gridbag = new GridBagLayout(); + pane.setLayout(gridbag); + + JButton b; + + b = addButton(0, 0, "Monitor Flight"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConnectToDevice(); + } + }); + b = addButton(1, 0, "Save Flight Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + SaveFlightData(); + } + }); + b = addButton(2, 0, "Replay Flight"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + Replay(); + } + }); + b = addButton(3, 0, "Graph Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + GraphData(); + } + }); + b = addButton(4, 0, "Export Data"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ExportData(); + } + }); + b = addButton(0, 1, "Configure TeleMetrum"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConfigureTeleMetrum(); + } + }); + + b = addButton(1, 1, "Configure AltosUI"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ConfigureAltosUI(); + } + }); + + b = addButton(2, 1, "Flash Image"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FlashImage(); + } + }); + + b = addButton(3, 1, "Fire Igniter"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + FireIgniter(); + } + }); + + b = addButton(4, 1, "Quit"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + + setTitle("AltOS"); + + pane.doLayout(); + pane.validate(); + + doLayout(); + validate(); + + setVisible(true); + + Insets i = getInsets(); + Dimension ps = rootPane.getPreferredSize(); + ps.width += i.left + i.right; + ps.height += i.top + i.bottom; + setPreferredSize(ps); + setSize(ps); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + } + + private void ConnectToDevice() { + AltosDevice device = AltosDeviceDialog.show(AltosUI.this, + AltosDevice.product_basestation); + + if (device != null) + telemetry_window(device); + } + + void ConfigureCallsign() { + String result; + result = JOptionPane.showInputDialog(AltosUI.this, + "Configure Callsign", + AltosPreferences.callsign()); + if (result != null) + AltosPreferences.set_callsign(result); + } + + void ConfigureTeleMetrum() { + new AltosConfig(AltosUI.this); + } + + void FlashImage() { + new AltosFlashUI(AltosUI.this); + } + + void FireIgniter() { + new AltosIgniteUI(AltosUI.this); + } + + /* + * Replay a flight from telemetry data + */ + private void Replay() { + AltosDataChooser chooser = new AltosDataChooser( + AltosUI.this); + + AltosRecordIterable iterable = chooser.runDialog(); + if (iterable != null) { + AltosFlightReader reader = new AltosReplayReader(iterable.iterator(), + chooser.filename()); + new AltosFlightUI(voice, reader); + } + } + + /* Connect to TeleMetrum, either directly or through + * a TeleDongle over the packet link + */ + private void SaveFlightData() { + 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() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosRecordIterable record_reader = chooser.runDialog(); + if (record_reader == null) + return; + new AltosCSVUI(AltosUI.this, record_reader, chooser.file()); + } + + /* Load a flight log CSV file and display a pretty graph. + */ + + private void GraphData() { + AltosDataChooser chooser; + chooser = new AltosDataChooser(this); + AltosRecordIterable record_reader = chooser.runDialog(); + if (record_reader == null) + return; + new AltosGraphUI(record_reader); + } + + private void ConfigureAltosUI() { + new AltosConfigureUI(AltosUI.this, voice); + } + + static AltosRecordIterable open_logfile(String filename) { + File file = new File (filename); + try { + FileInputStream in; + + in = new FileInputStream(file); + if (filename.endsWith("eeprom")) + return new AltosEepromIterable(in); + else + return new AltosTelemetryIterable(in); + } catch (FileNotFoundException fe) { + System.out.printf("Cannot open '%s'\n", filename); + return null; + } + } + + static AltosWriter 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 AltosWriter open_kml(String filename) { + File file = new File (filename); + try { + return new AltosKML(file); + } catch (FileNotFoundException fe) { + System.out.printf("Cannot open '%s'\n", filename); + return null; + } + } + + static final int process_csv = 1; + static final int process_kml = 2; + + static void process_file(String input, int process) { + AltosRecordIterable iterable = open_logfile(input); + if (iterable == null) + return; + if (process == 0) + process = process_csv; + if ((process & process_csv) != 0) { + String output = Altos.replace_extension(input,".csv"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_csv(output); + if (writer != null) { + writer.write(iterable); + writer.close(); + } + } + } + if ((process & process_kml) != 0) { + String output = Altos.replace_extension(input,".kml"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_kml(output); + if (writer == null) + return; + writer.write(iterable); + writer.close(); + } + } + } + + public static void main(final String[] args) { + int process = 0; + /* Handle batch-mode */ + if (args.length == 1 && args[0].equals("--help")) { + System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); + System.out.printf(" Options:\n"); + System.out.printf(" --fetchmaps \tpre-fetch maps for site map view\n"); + System.out.printf(" --replay \t\trelive the glory of past flights \n"); + System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n"); + System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n"); + } else if (args.length == 3 && args[0].equals("--fetchmaps")) { + double lat = Double.parseDouble(args[1]); + double lon = Double.parseDouble(args[2]); + AltosSiteMap.prefetchMaps(lat, lon, 5, 5); + } else if (args.length == 2 && args[0].equals("--replay")) { + String filename = args[1]; + FileInputStream in; + try { + in = new FileInputStream(filename); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", filename); + return; + } + AltosRecordIterable recs; + AltosReplayReader reader; + if (filename.endsWith("eeprom")) { + recs = new AltosEepromIterable(in); + } else { + recs = new AltosTelemetryIterable(in); + } + reader = new AltosReplayReader(recs.iterator(), filename); + AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); + flight_ui.set_exit_on_close(); + return; + } else if (args.length > 0) { + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--kml")) + process |= process_kml; + else if (args[i].equals("--csv")) + process |= process_csv; + else + process_file(args[i], process); + } + } else { + AltosUI altosui = new AltosUI(); + altosui.setVisible(true); + + AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation); + for (int i = 0; i < devices.length; i++) + altosui.telemetry_window(devices[i]); + } + } +} diff --git a/altosui/AltosVoice.java b/altosui/AltosVoice.java new file mode 100644 index 00000000..ac13ee14 --- /dev/null +++ b/altosui/AltosVoice.java @@ -0,0 +1,95 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 com.sun.speech.freetts.Voice; +import com.sun.speech.freetts.VoiceManager; +import com.sun.speech.freetts.audio.JavaClipAudioPlayer; +import java.util.concurrent.LinkedBlockingQueue; + +public class AltosVoice implements Runnable { + VoiceManager voice_manager; + Voice voice; + LinkedBlockingQueue phrases; + Thread thread; + boolean busy; + + final static String voice_name = "kevin16"; + + public void run() { + try { + 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) { + synchronized(this) { + busy = true; + phrases.put(s); + } + } + } catch (InterruptedException e) { + } + } + + public void speak(String s) { + if (AltosPreferences.voice()) + speak_always(s); + } + + public void speak(String format, Object... parameters) { + speak(String.format(format, parameters)); + } + + public AltosVoice () { + busy = false; + voice_manager = VoiceManager.getInstance(); + voice = voice_manager.getVoice(voice_name); + if (voice != null) { + voice.allocate(); + phrases = new LinkedBlockingQueue (); + thread = new Thread(this); + thread.start(); + } else { + System.out.printf("Voice manager failed to open %s\n", voice_name); + Voice[] voices = voice_manager.getVoices(); + System.out.printf("Available voices:\n"); + for (int i = 0; i < voices.length; i++) { + System.out.println(" " + voices[i].getName() + + " (" + voices[i].getDomain() + " domain)"); + } + } + } +} diff --git a/altosui/AltosWriter.java b/altosui/AltosWriter.java new file mode 100644 index 00000000..a172dff0 --- /dev/null +++ b/altosui/AltosWriter.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.*; + +public interface AltosWriter { + + public void write(AltosRecord record); + + public void write(AltosRecordIterable iterable); + + public void close(); +} diff --git a/altosui/GrabNDrag.java b/altosui/GrabNDrag.java new file mode 100644 index 00000000..e6b87b58 --- /dev/null +++ b/altosui/GrabNDrag.java @@ -0,0 +1,54 @@ +/* + * Copyright © 2010 Anthony Towns + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; + +class GrabNDrag extends MouseInputAdapter { + private JComponent scroll; + private Point startPt = new Point(); + + public GrabNDrag(JComponent scroll) { + this.scroll = scroll; + scroll.addMouseMotionListener(this); + scroll.addMouseListener(this); + scroll.setAutoscrolls(true); + } + + public void mousePressed(MouseEvent e) { + startPt.setLocation(e.getPoint()); + } + public void mouseDragged(MouseEvent e) { + int xd = e.getX() - startPt.x; + int yd = e.getY() - startPt.y; + + Rectangle r = scroll.getVisibleRect(); + r.x -= xd; + r.y -= yd; + scroll.scrollRectToVisible(r); + } +} diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi b/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi new file mode 100644 index 00000000..3ed821eb --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi @@ -0,0 +1,84 @@ +# +# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de) +# + +Name "InstDrv.dll test" + +OutFile "InstDrv-Test.exe" + +ShowInstDetails show + +ComponentText "InstDrv Plugin Usage Example" + +Page components +Page instfiles + +Section "Install a Driver" InstDriver + InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" + Pop $0 + DetailPrint "InitDriverSetup: $0" + + InstDrv::DeleteOemInfFiles /NOUNLOAD + Pop $0 + DetailPrint "DeleteOemInfFiles: $0" + StrCmp $0 "00000000" PrintInfNames ContInst1 + + PrintInfNames: + Pop $0 + DetailPrint "Deleted $0" + Pop $0 + DetailPrint "Deleted $0" + + ContInst1: + InstDrv::CreateDevice /NOUNLOAD + Pop $0 + DetailPrint "CreateDevice: $0" + + SetOutPath $TEMP + File "ircomm2k.inf" + File "ircomm2k.sys" + + InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf" + Pop $0 + DetailPrint "InstallDriver: $0" + StrCmp $0 "00000000" PrintReboot ContInst2 + + PrintReboot: + Pop $0 + DetailPrint "Reboot: $0" + + ContInst2: + InstDrv::CountDevices + Pop $0 + DetailPrint "CountDevices: $0" +SectionEnd + +Section "Uninstall the driver again" UninstDriver + InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" + Pop $0 + DetailPrint "InitDriverSetup: $0" + + InstDrv::DeleteOemInfFiles /NOUNLOAD + Pop $0 + DetailPrint "DeleteOemInfFiles: $0" + StrCmp $0 "00000000" PrintInfNames ContUninst1 + + PrintInfNames: + Pop $0 + DetailPrint "Deleted $0" + Pop $0 + DetailPrint "Deleted $0" + + ContUninst1: + InstDrv::RemoveAllDevices + Pop $0 + DetailPrint "RemoveAllDevices: $0" + StrCmp $0 "00000000" PrintReboot ContUninst2 + + PrintReboot: + Pop $0 + DetailPrint "Reboot: $0" + + ContUninst2: + Delete "$SYSDIR\system32\ircomm2k.sys" +SectionEnd \ No newline at end of file diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe new file mode 100644 index 00000000..615bae15 Binary files /dev/null and b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe differ diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c new file mode 100644 index 00000000..efe866e9 --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c @@ -0,0 +1,704 @@ +/* + +InstDrv.dll - Installs or Removes Device Drivers + +Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not required. +2. Altered versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. + +*/ + + +#include +#include +#include +#include "../exdll/exdll.h" + + +char paramBuf[1024]; +GUID devClass; +char hwIdBuf[1024]; +int initialized = 0; + + + +void* memset(void* dst, int val, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = val; + + return NULL; +} + + + +void* memcpy(void* dst, const void* src, unsigned int len) +{ + while (len-- > 0) + *((char *)dst)++ = *((char *)src)++; + + return NULL; +} + + + +int HexCharToInt(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'f')) + return c - 'a' + 10; + else if ((c >= 'A') && (c <= 'F')) + return c - 'A' + 10; + else + return -1; +} + + + +BOOLEAN HexStringToUInt(char* str, int width, void* valBuf) +{ + int i, val; + + + for (i = width - 4; i >= 0; i -= 4) + { + val = HexCharToInt(*str++); + if (val < 0) + return FALSE; + *(unsigned int *)valBuf += val << i; + } + + return TRUE; +} + + + +BOOLEAN StringToGUID(char* guidStr, GUID* pGuid) +{ + int i; + + + memset(pGuid, 0, sizeof(GUID)); + + if (*guidStr++ != '{') + return FALSE; + + if (!HexStringToUInt(guidStr, 32, &pGuid->Data1)) + return FALSE; + guidStr += 8; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data2)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + if (!HexStringToUInt(guidStr, 16, &pGuid->Data3)) + return FALSE; + guidStr += 4; + + if (*guidStr++ != '-') + return FALSE; + + for (i = 0; i < 2; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '-') + return FALSE; + + for (i = 2; i < 8; i++) + { + if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) + return FALSE; + guidStr += 2; + } + + if (*guidStr++ != '}') + return FALSE; + + return TRUE; +} + + + +DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex) +{ + DWORD buffersize = 0; + LPTSTR buffer = NULL; + DWORD dataType; + DWORD result; + + + while (1) + { + if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData)) + { + result = GetLastError(); + break; + } + + GetDeviceRegistryProperty: + if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID, + &dataType, (PBYTE)buffer, buffersize, + &buffersize)) + { + result = GetLastError(); + + if (result == ERROR_INSUFFICIENT_BUFFER) + { + if (buffer != NULL) + LocalFree(buffer); + + buffer = (LPTSTR)LocalAlloc(LPTR, buffersize); + + if (buffer == NULL) + break; + + goto GetDeviceRegistryProperty; + } + else if (result == ERROR_INVALID_DATA) + continue; // ignore invalid entries + else + break; // break on other errors + } + + if (lstrcmpi(buffer, hwIdBuf) == 0) + { + result = 0; + break; + } + } + + if (buffer != NULL) + LocalFree(buffer); + + return result; +} + + + +DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId, + HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData, + DWORD *pIndex, DWORD flags) +{ + DWORD result; + + + *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags); + if (*pDevInfoSet == INVALID_HANDLE_VALUE) + return GetLastError(); + + pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); + *pIndex = 0; + + result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex); + + if (result != 0) + SetupDiDestroyDeviceInfoList(*pDevInfoSet); + + return result; +} + + + +/* + * InstDrv::InitDriverSetup devClass drvHWID + * + * devClass - GUID of the driver's device setup class + * drvHWID - Hardware ID of the supported device + * + * Return: + * result - error message, empty on success + */ +void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + EXDLL_INIT(); + + /* convert class GUID */ + popstring(paramBuf); + + if (!StringToGUID(paramBuf, &devClass)) + { + popstring(paramBuf); + pushstring("Invalid GUID!"); + return; + } + + /* get hardware ID */ + memset(hwIdBuf, 0, sizeof(hwIdBuf)); + popstring(hwIdBuf); + + initialized = 1; + pushstring(""); +} + + + +/* + * InstDrv::CountDevices + * + * Return: + * result - Number of installed devices the driver supports + */ +void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + int count = 0; + char countBuf[16]; + DWORD index; + DWORD result; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData, + &index, DIGCF_PRESENT); + if (result != 0) + { + pushstring("0"); + return; + } + + do + { + count++; + } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0); + + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(countBuf, "%d", count); + pushstring(countBuf); +} + + + +/* + * InstDrv::CreateDevice + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfoSet; + SP_DEVINFO_DATA devInfoData; + DWORD result = 0; + char resultBuf[16]; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent); + if (devInfoSet == INVALID_HANDLE_VALUE) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + return; + } + + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL, + hwndParent, DICD_GENERATE_ID, &devInfoData)) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, + hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) + { + result = GetLastError(); + goto InstallCleanup; + } + + if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData)) + result = GetLastError(); + + InstallCleanup: + SetupDiDestroyDeviceInfoList(devInfoSet); + + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::InstallDriver infPath + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + char resultBuf[16]; + BOOL reboot; + + + EXDLL_INIT(); + popstring(paramBuf); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf, + INSTALLFLAG_FORCE, &reboot)) + { + wsprintf(resultBuf, "%08X", GetLastError()); + pushstring(resultBuf); + } + else + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } +} + + + +/* + * InstDrv::DeleteOemInfFiles + * + * Return: + * result - Windows error code + * oeminf - Path of the deleted devices setup file (oemXX.inf) + * oempnf - Path of the deleted devices setup file (oemXX.pnf) + */ +void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + SP_DRVINFO_DATA drvInfoData; + SP_DRVINFO_DETAIL_DATA drvInfoDetail; + DWORD index; + DWORD result; + char resultBuf[16]; + + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER)) + { + result = GetLastError(); + goto Cleanup2; + } + + drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); + drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); + + if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData)) + { + result = GetLastError(); + goto Cleanup3; + } + + if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData, + &drvInfoDetail, sizeof(drvInfoDetail), NULL)) + { + result = GetLastError(); + + if (result != ERROR_INSUFFICIENT_BUFFER) + goto Cleanup3; + + result = 0; + } + + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + else + { + index = lstrlen(drvInfoDetail.InfFileName); + if (index > 3) + { + lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf"); + pushstring(drvInfoDetail.InfFileName); + if (!DeleteFile(drvInfoDetail.InfFileName)) + result = GetLastError(); + } + } + + Cleanup3: + SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER); + + Cleanup2: + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::RemoveAllDevices + * + * Return: + * result - Windows error code + * reboot - non-zero if reboot is required + */ +void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + HDEVINFO devInfo; + SP_DEVINFO_DATA devInfoData; + DWORD index; + DWORD result; + char resultBuf[16]; + BOOL reboot = FALSE; + SP_DEVINSTALL_PARAMS instParams; + + + EXDLL_INIT(); + + if (!initialized) + { + pushstring("Fatal error!"); + return; + } + + result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); + if (result != 0) + goto Cleanup1; + + do + { + if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData)) + { + result = GetLastError(); + break; + } + + instParams.cbSize = sizeof(instParams); + if (!reboot && + SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) && + ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0)) + { + reboot = TRUE; + } + + result = FindNextDevice(devInfo, &devInfoData, &index); + } while (result == 0); + + SetupDiDestroyDeviceInfoList(devInfo); + + Cleanup1: + if ((result == 0) || (result == ERROR_NO_MORE_ITEMS)) + { + wsprintf(resultBuf, "%d", reboot); + pushstring(resultBuf); + pushstring("00000000"); + } + else + { + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); + } +} + + + +/* + * InstDrv::StartSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_START_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + if ((svcStatus.dwCurrentState == SERVICE_STOPPED) && + (svcStatus.dwWin32ExitCode != 0)) + result = svcStatus.dwWin32ExitCode; + else + result = ERROR_SERVICE_REQUEST_TIMEOUT; + } + } + + if (svcStatus.dwCurrentState == SERVICE_RUNNING) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +/* + * InstDrv::StopSystemService serviceName + * + * Return: + * result - Windows error code + */ +void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) +{ + SC_HANDLE managerHndl; + SC_HANDLE svcHndl; + SERVICE_STATUS svcStatus; + DWORD oldCheckPoint; + DWORD result; + char resultBuf[16]; + + + EXDLL_INIT(); + popstring(paramBuf); + + managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if (managerHndl == NULL) + { + result = GetLastError(); + goto Cleanup1; + } + + svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS); + if (svcHndl == NULL) + { + result = GetLastError(); + goto Cleanup2; + } + + if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus)) + { + result = GetLastError(); + goto Cleanup3; + } + + while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) + { + oldCheckPoint = svcStatus.dwCheckPoint; + + Sleep(svcStatus.dwWaitHint); + + if (!QueryServiceStatus(svcHndl, &svcStatus)) + { + result = GetLastError(); + break; + } + + if (oldCheckPoint >= svcStatus.dwCheckPoint) + { + result = ERROR_SERVICE_REQUEST_TIMEOUT; + break; + } + } + + if (svcStatus.dwCurrentState == SERVICE_STOPPED) + result = 0; + + Cleanup3: + CloseServiceHandle(svcHndl); + + Cleanup2: + CloseServiceHandle(managerHndl); + + Cleanup1: + wsprintf(resultBuf, "%08X", result); + pushstring(resultBuf); +} + + + +BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) +{ + return TRUE; +} diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp new file mode 100644 index 00000000..874e66c7 --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp @@ -0,0 +1,110 @@ +# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=InstDrv - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "InstDrv.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "InstDrv - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE "InstDrv - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "InstDrv - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c +# 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 +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "InstDrv - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# 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 +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 +# SUBTRACT LINK32 /nodefaultlib + +!ENDIF + +# Begin Target + +# Name "InstDrv - Win32 Release" +# Name "InstDrv - Win32 Debug" +# Begin Group "Quellcodedateien" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\InstDrv.c +# End Source File +# End Group +# Begin Group "Header-Dateien" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Ressourcendateien" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw new file mode 100644 index 00000000..b3d02f0e --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt b/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt new file mode 100644 index 00000000..e5877aa6 --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt @@ -0,0 +1,141 @@ +InstDrv.dll version 0.2 - Installs or Removes Device Drivers +------------------------------------------------------------ + + +The plugin helps you to create NSIS scripts for installing device drivers or +removing them again. It can count installed device instances, create new ones +or delete all supported device. InstDrv works on Windows 2000 or later. + + + +InstDrv::InitDriverSetup devClass drvHWID +Return: result + +To start processing a driver, first call this function. devClass is the GUID +of the device class the driver supports, drvHWID is the device hardware ID. If +you don't know what these terms mean, you may want to take a look at the +Windows DDK. This function returns an empty string on success, otherwise an +error message. + +InitDriverSetup has to be called every time after the plugin dll has been +(re-)loaded, or if you want to switch to a different driver. + + + +InstDrv::CountDevices +Return: number + +This call returns the number of installed and supported devices of the driver. + + + +InstDrv::CreateDevice +Return: result + +To create a new deviced node which the driver has to support, use this +function. You may even call it multiple times for more than one instance. The +return value is the Windows error code (in hex). Use CreateDevice before +installing or updating the driver itself. + + + +InstDrv::InstallDriver infPath +Return: result + reboot + +InstallDriver installs or updates a device driver as specified in the .inf +setup script. It returns a Windows error code (in hex) and, on success, a flag +signalling if a system reboot is required. + + + +InstDrv::DeleteOemInfFiles +Return: result + oeminf + oempnf + +DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the +oemXX.inf and oemXX.pnf files associated with the drivers. It returns a +Windows error code (in hex) and, on success, the names of the deleted files. +This functions requires that at least one device instance is still present. +So, call it before you remove the devices itself. You should also call it +before updating a driver. This avoids that the inf directory gets slowly +messed up with useless old setup scripts (which does NOT really accelerate +Windows). The error code which comes up when no device is installed is +"00000103". + + + +InstDrv::RemoveAllDevices +Return: result + reboot + +This functions deletes all devices instances the driver supported. It returns +a Windows error code (in hex) and, on success, a flag signalling if the system +needs to be rebooted. You additionally have to remove the driver binaries from +the system paths. + + + +InstDrv::StartSystemService serviceName +Return: result + +Call this function to start the provided system service. The function blocks +until the service is started or the system reported a timeout. The return value +is the Windows error code (in hex). + + + +InstDrv::StopSystemService serviceName +Return: result + +This function tries to stop the provided system service. It blocks until the +service has been shut down or the system reported a timeout. The return value +is the Windows error code (in hex). + + + +Example.nsi + +The example script installs or removes the virtual COM port driver of IrCOMM2k +(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script +are only included for demonstration purposes, they do not work without the +rest of IrCOMM2k (but they also do not cause any harm). + + + +Building the Source Code + +To build the plugin from the source code, some include files and libraries +which come with the Windows DDK are required. + + + +History + + 0.2 - fixed bug when calling InitDriverSetup the second time + - added StartSystemService and StopSystemService + + 0.1 - first release + + + +License + +Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute +it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment in the + product documentation would be appreciated but is not required. +2. Altered versions must be plainly marked as such, + and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any distribution. diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf new file mode 100644 index 00000000..ccda1d87 --- /dev/null +++ b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf @@ -0,0 +1,137 @@ +; IrCOMM2k.inf +; +; Installation file for the Virtual Infrared-COM-Port +; +; (c) Copyright 2001, 2002 Jan Kiszka +; + +[Version] +Signature="$Windows NT$" +Provider=%JK% +Class=Ports +ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318} +;DriverVer=03/26/2002,1.2.1.0 + +[DestinationDirs] +IrCOMM2k.Copy2Drivers = 12 +IrCOMM2k.Copy2Winnt = 10 +IrCOMM2k.Copy2System32 = 11 +IrCOMM2k.Copy2Help = 18 + + +; +; Driver information +; + +[Manufacturer] +%JK% = JK.Mfg + +[JK.Mfg] +%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k + + +; +; General installation section +; + +[IrCOMM2k_inst] +CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt +;AddReg = IrCOMM2k_inst_AddReg + + +; +; File sections +; + +[IrCOMM2k.Copy2Drivers] +ircomm2k.sys,,,2 + +;[IrCOMM2k.Copy2System32] +;ircomm2k.exe,,,2 +;ircomm2k.dll,,,2 + +;[IrCOMM2k.Copy2Help] +;ircomm2k.hlp,,,2 + +;[IrCOMM2k.Copy2Winnt] +;IrCOMM2k-Setup.exe,Setup.exe,,2 + + +; +; Service Installation +; + +[IrCOMM2k_inst.Services] +AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst +;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst + +[IrCOMM2k_DriverService_Inst] +DisplayName = %IrCOMM2k.DrvName% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 0 ; SERVICE_ERROR_IGNORE +ServiceBinary = %12%\ircomm2k.sys + +;[IrCOMM2k_Service_Inst] +;DisplayName = %IrCOMM2k.SvcName% +;Description = %IrCOMM2k.SvcDesc% +;ServiceType = 0x00000120 ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS +;StartType = 2 ; SERVICE_AUTO_START +;ErrorControl = 0 ; SERVICE_ERROR_IGNORE +;ServiceBinary = %11%\ircomm2k.exe +;Dependencies = IrCOMM2k +;AddReg = IrCOMM2kSvcAddReg + + +[IrCOMM2k_inst.nt.HW] +AddReg=IrCOMM2kHwAddReg + +[IrCOMM2kHwAddReg] +HKR,,PortSubClass,REG_BINARY,0x00000001 +;HKR,,TimeoutScaling,REG_DWORD,0x00000001 +;HKR,,StatusLines,REG_DWORD,0x00000000 + +;[IrCOMM2k_inst_AddReg] +;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider" +;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe" +;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 " +;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1" +;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de" +;HKLM,%UNINSTALL_KEY%,Publisher,,%JK% +;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe" + +;[IrCOMM2kSvcAddReg] +;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000 + + +[IrCOMM2k_DriverEventLog_Inst] +AddReg = IrCOMM2k_DriverEventLog_AddReg + +[IrCOMM2k_DriverEventLog_AddReg] +HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys" +HKR,,TypesSupported,REG_DWORD,7 + + +[Strings] + +; +; Non-Localizable Strings +; + +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 +SERVICEROOT = "System\CurrentControlSet\Services" +UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k" + +; +; Localizable Strings +; + +JK = "Jan Kiszka" +JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss" +IrCOMM2k.DrvName = "Virtueller Infrarot-Kommunikationsanschluss" +;IrCOMM2k.SvcName = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm" +;IrCOMM2k.SvcDesc = "Bildet über Infarot einen Kommunikationsanschluß nach." diff --git a/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys new file mode 100644 index 00000000..7882583b Binary files /dev/null and b/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys differ diff --git a/altosui/Instdrv/NSIS/Plugins/InstDrv.dll b/altosui/Instdrv/NSIS/Plugins/InstDrv.dll new file mode 100644 index 00000000..482e955e Binary files /dev/null and b/altosui/Instdrv/NSIS/Plugins/InstDrv.dll differ diff --git a/altosui/Makefile-standalone b/altosui/Makefile-standalone new file mode 100644 index 00000000..a95a5aa8 --- /dev/null +++ b/altosui/Makefile-standalone @@ -0,0 +1,184 @@ +.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 \ + AltosInfoTable.class \ + AltosLog.class \ + AltosLogfileChooser.class \ + AltosParse.class \ + AltosPreferences.class \ + AltosReader.class \ + AltosRecord.class \ + AltosSerialMonitor.class \ + AltosSerial.class \ + AltosState.class \ + AltosStatusTable.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 diff --git a/altosui/Makefile.am b/altosui/Makefile.am new file mode 100644 index 00000000..e2ff55af --- /dev/null +++ b/altosui/Makefile.am @@ -0,0 +1,272 @@ +SUBDIRS=libaltos +JAVAROOT=classes +AM_JAVACFLAGS=-encoding UTF-8 + +man_MANS=altosui.1 + +altoslibdir=$(libdir)/altos + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:libaltos:$(FREETTS)/*:/usr/share/java/*" + +bin_SCRIPTS=altosui + +altosui_JAVA = \ + GrabNDrag.java \ + AltosAscent.java \ + AltosChannelMenu.java \ + AltosConfig.java \ + AltosConfigUI.java \ + AltosConfigureUI.java \ + AltosConvert.java \ + AltosCRCException.java \ + AltosCSV.java \ + AltosCSVUI.java \ + AltosDebug.java \ + AltosDescent.java \ + AltosDeviceDialog.java \ + AltosDevice.java \ + AltosDisplayThread.java \ + AltosEepromDownload.java \ + AltosEepromMonitor.java \ + AltosEepromIterable.java \ + AltosEepromRecord.java \ + AltosFile.java \ + AltosFlash.java \ + AltosFlashUI.java \ + AltosFlightDisplay.java \ + AltosFlightInfoTableModel.java \ + AltosFlightReader.java \ + AltosFlightStatus.java \ + AltosFlightUI.java \ + AltosGPS.java \ + AltosGreatCircle.java \ + AltosHexfile.java \ + Altos.java \ + AltosIgnite.java \ + AltosIgniteUI.java \ + AltosInfoTable.java \ + AltosKML.java \ + AltosLanded.java \ + AltosLed.java \ + AltosLights.java \ + AltosLine.java \ + AltosLog.java \ + AltosPad.java \ + AltosParse.java \ + AltosPreferences.java \ + AltosReader.java \ + AltosRecord.java \ + AltosRecordIterable.java \ + AltosTelemetryReader.java \ + AltosReplayReader.java \ + AltosRomconfig.java \ + AltosRomconfigUI.java \ + AltosSerial.java \ + AltosSerialInUseException.java \ + AltosSerialMonitor.java \ + AltosSiteMap.java \ + AltosSiteMapCache.java \ + AltosSiteMapTile.java \ + AltosState.java \ + AltosTelemetry.java \ + AltosTelemetryIterable.java \ + AltosUI.java \ + AltosWriter.java \ + AltosDataPointReader.java \ + AltosDataPoint.java \ + AltosGraph.java \ + AltosGraphTime.java \ + AltosGraphUI.java \ + AltosDataChooser.java \ + AltosVoice.java + +JFREECHART_CLASS= \ + jfreechart.jar + +JCOMMON_CLASS=\ + jcommon.jar + +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 +ICONDIR=$(top_srcdir)/icon + +JAVA_ICON=$(ICONDIR)/altus-metrum-16x16.jpg + +ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ + $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ + $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png + +# icon base names for jar +ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \ + -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ + -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ + -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png + +WINDOWS_ICON=$(ICONDIR)/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) $(JFREECHART_CLASS) $(JCOMMON_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) altosui altosui-test altosui-jdb + +clean-local: + -rm -rf classes $(JAR) $(FATJAR) \ + $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ + $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ + altosui altosui-test altosui-jdb macosx linux + +if FATINSTALL + +FATTARGET=$(FATDIR)/$(VERSION) + +LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST) +MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST) +WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST) + +fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET) + +$(LINUX_DIST_TARGET): $(LINUX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(MACOSX_DIST_TARGET): $(MACOSX_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST) + mkdir -p $(FATTARGET) + cp -p $< $@ + +else +fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) +endif + + +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 \ + $(ICONJAR) \ + -C classes altosui \ + -C libaltos libaltosJNI + +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) + jar cfm $@ Manifest-fat.txt \ + $(ICONJAR) \ + -C classes altosui \ + -C libaltos libaltosJNI + +Manifest.txt: Makefile + echo 'Main-Class: altosui.AltosUI' > $@ + echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ + +Manifest-fat.txt: + echo 'Main-Class: altosui.AltosUI' > $@ + echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@ + +altosui: Makefile + echo "#!/bin/sh" > $@ + echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ + chmod +x $@ + +altosui-test: Makefile + echo "#!/bin/sh" > $@ + echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + chmod +x $@ + +altosui-jdb: Makefile + echo "#!/bin/sh" > $@ + echo 'exec jdb -classpath "classes:libaltos:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" altosui/AltosUI "$$@"' >> $@ + chmod +x $@ + +libaltos.so: + -rm -f "$@" + $(LN_S) libaltos/.libs/"$@" . + +libaltos.dylib: + -rm -f "$@" + $(LN_S) libaltos/"$@" . + +altos.dll: + -rm -f "$@" + $(LN_S) libaltos/"$@" . + +$(FREETTS_CLASS): + -rm -f "$@" + $(LN_S) "$(FREETTS)"/"$@" . + +$(JFREECHART_CLASS): + -rm -f "$@" + $(LN_S) "$(JFREECHART)"/"$@" . + +$(JCOMMON_CLASS): + -rm -f "$@" + $(LN_S) "$(JCOMMON)"/"$@" . + +$(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 $(JFREECHART_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 diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi new file mode 100644 index 00000000..37777fd6 --- /dev/null +++ b/altosui/altos-windows.nsi @@ -0,0 +1,113 @@ +!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" + + SetOutPath $INSTDIR + File "../../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 diff --git a/altosui/altosui-fat b/altosui/altosui-fat new file mode 100755 index 00000000..95b1c051 --- /dev/null +++ b/altosui/altosui-fat @@ -0,0 +1,4 @@ +#!/bin/sh +me=`which "$0"` +dir=`dirname "$me"` +exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar "$@" diff --git a/altosui/altosui.1 b/altosui/altosui.1 new file mode 100644 index 00000000..57fa4489 --- /dev/null +++ b/altosui/altosui.1 @@ -0,0 +1,46 @@ +.\" +.\" Copyright © 2010 Bdale Garbee +.\" +.\" 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 ALTOSUI 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 menu-oriented +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 can be used to configure the +TeleMetrum, and to downloads the eeprom data and store it in a file. +.P +A number of other menu options exist, including the ability to export flight +data in different formats. +.SH FILES +All data log files are recorded into a user-specified directory +(default ~/TeleMetrum). 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 AUTHOR +Keith Packard diff --git a/altosui/altusmetrum.jpg b/altosui/altusmetrum.jpg new file mode 100644 index 00000000..04027921 Binary files /dev/null and b/altosui/altusmetrum.jpg differ diff --git a/altosui/libaltos/.gitignore b/altosui/libaltos/.gitignore new file mode 100644 index 00000000..c490e6f8 --- /dev/null +++ b/altosui/libaltos/.gitignore @@ -0,0 +1,12 @@ +*.so +*.lo +*.la +*.java +*.class +.libs/ +classlibaltos.stamp +libaltos_wrap.c +libaltosJNI +cjnitest +libaltos.swig +swig_bindings/ diff --git a/altosui/libaltos/Makefile-standalone b/altosui/libaltos/Makefile-standalone new file mode 100644 index 00000000..4e438050 --- /dev/null +++ b/altosui/libaltos/Makefile-standalone @@ -0,0 +1,126 @@ +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: diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am new file mode 100644 index 00000000..388d2104 --- /dev/null +++ b/altosui/libaltos/Makefile.am @@ -0,0 +1,41 @@ +JAVAC=javac +AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) +AM_JAVACFLAGS=-encoding UTF-8 + +altoslibdir=$(libdir)/altos + +altoslib_LTLIBRARIES=libaltos.la + +libaltos_la_LDFLAGS = -version-info 1:0:1 + +libaltos_la_SOURCES=\ + libaltos.c \ + libaltos_wrap.c + +noinst_PROGRAMS=cjnitest + +cjnitest_LDADD=libaltos.la + +LIBS= + +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 + +libaltos_wrap.c: 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) libaltos_wrap.c diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll new file mode 100755 index 00000000..28e9b4ad Binary files /dev/null and b/altosui/libaltos/altos.dll differ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c new file mode 100644 index 00000000..c6d6e069 --- /dev/null +++ b/altosui/libaltos/cjnitest.c @@ -0,0 +1,43 @@ +#include +#include "libaltos.h" + +static void +altos_puts(struct altos_file *file, char *string) +{ + char c; + + while ((c = *string++)) + altos_putchar(file, c); +} + +main () +{ + struct altos_device device; + struct altos_list *list; + + altos_init(); + list = altos_list_start(); + while (altos_list_next(list, &device)) { + struct altos_file *file; + int c; + + printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, + device.name, device.serial, device.path); + + file = altos_open(&device); + if (!file) { + printf("altos_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar (c); + } + if (c != LIBALTOS_TIMEOUT) + printf ("getchar returns %d\n", c); + altos_close(file); + } + altos_list_finish(list); + altos_fini(); +} diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c new file mode 100644 index 00000000..465f0ac8 --- /dev/null +++ b/altosui/libaltos/libaltos.c @@ -0,0 +1,1028 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "libaltos.h" +#include +#include +#include + +#define USE_POLL + +PUBLIC int +altos_init(void) +{ + return LIBALTOS_SUCCESS; +} + +PUBLIC void +altos_fini(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) +{ + size_t len = strlen (s); + char *ret; + + if (len <= n) + return strdup (s); + ret = malloc(n + 1); + strncpy(ret, s, n); + ret[n] = '\0'; + return ret; +} + +#else +#define altos_strndup strndup +#endif + +/* + * Scan for Altus Metrum devices by looking through /sys + */ + +#ifdef LINUX + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +static char * +cc_fullname (char *dir, char *file) +{ + char *new; + int dlen = strlen (dir); + int flen = strlen (file); + int slen = 0; + + if (dir[dlen-1] != '/') + slen = 1; + new = malloc (dlen + slen + flen + 1); + if (!new) + return 0; + strcpy(new, dir); + if (slen) + strcat (new, "/"); + strcat(new, file); + return new; +} + +static char * +cc_basename(char *file) +{ + char *b; + + b = strrchr(file, '/'); + if (!b) + return file; + return b + 1; +} + +static char * +load_string(char *dir, char *file) +{ + char *full = cc_fullname(dir, file); + char line[4096]; + char *r; + FILE *f; + int rlen; + + f = fopen(full, "r"); + free(full); + if (!f) + return NULL; + r = fgets(line, sizeof (line), f); + fclose(f); + if (!r) + return NULL; + rlen = strlen(r); + if (r[rlen-1] == '\n') + r[rlen-1] = '\0'; + return strdup(r); +} + +static int +load_hex(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 16); + free(line); + if (end == line) + return -1; + return i; +} + +static int +load_dec(char *dir, char *file) +{ + char *line; + char *end; + long i; + + line = load_string(dir, file); + if (!line) + return -1; + i = strtol(line, &end, 10); + free(line); + if (end == line) + return -1; + return i; +} + +static int +dir_filter_tty_colon(const struct dirent *d) +{ + return strncmp(d->d_name, "tty:", 4) == 0; +} + +static int +dir_filter_tty(const struct dirent *d) +{ + return strncmp(d->d_name, "tty", 3) == 0; +} + +struct altos_usbdev { + char *sys; + char *tty; + char *manufacturer; + char *product_name; + int serial; /* AltOS always uses simple integer serial numbers */ + int idProduct; + int idVendor; +}; + +static char * +usb_tty(char *sys) +{ + char *base; + int num_configs; + int config; + struct dirent **namelist; + int interface; + int num_interfaces; + char endpoint_base[20]; + char *endpoint_full; + char *tty_dir; + int ntty; + char *tty; + + base = cc_basename(sys); + num_configs = load_hex(sys, "bNumConfigurations"); + num_interfaces = load_hex(sys, "bNumInterfaces"); + for (config = 1; config <= num_configs; config++) { + for (interface = 0; interface < num_interfaces; interface++) { + sprintf(endpoint_base, "%s:%d.%d", + base, config, interface); + endpoint_full = cc_fullname(sys, endpoint_base); + + /* Check for tty:ttyACMx style names + */ + ntty = scandir(endpoint_full, &namelist, + dir_filter_tty_colon, + alphasort); + if (ntty > 0) { + free(endpoint_full); + tty = cc_fullname("/dev", namelist[0]->d_name + 4); + free(namelist); + return tty; + } + + /* Check for tty/ttyACMx style names + */ + tty_dir = cc_fullname(endpoint_full, "tty"); + free(endpoint_full); + ntty = scandir(tty_dir, &namelist, + dir_filter_tty, + alphasort); + free (tty_dir); + if (ntty > 0) { + tty = cc_fullname("/dev", namelist[0]->d_name); + free(namelist); + return tty; + } + } + } + return NULL; +} + +static struct altos_usbdev * +usb_scan_device(char *sys) +{ + struct altos_usbdev *usbdev; + + usbdev = calloc(1, sizeof (struct altos_usbdev)); + if (!usbdev) + return NULL; + usbdev->sys = strdup(sys); + usbdev->manufacturer = load_string(sys, "manufacturer"); + usbdev->product_name = load_string(sys, "product"); + usbdev->serial = load_dec(sys, "serial"); + usbdev->idProduct = load_hex(sys, "idProduct"); + usbdev->idVendor = load_hex(sys, "idVendor"); + usbdev->tty = usb_tty(sys); + return usbdev; +} + +static void +usbdev_free(struct altos_usbdev *usbdev) +{ + free(usbdev->sys); + free(usbdev->manufacturer); + free(usbdev->product_name); + /* this can get used as a return value */ + if (usbdev->tty) + free(usbdev->tty); + free(usbdev); +} + +#define USB_DEVICES "/sys/bus/usb/devices" + +static int +dir_filter_dev(const struct dirent *d) +{ + const char *n = d->d_name; + char c; + + while ((c = *n++)) { + if (isdigit(c)) + continue; + if (c == '-') + continue; + if (c == '.' && n != d->d_name + 1) + continue; + return 0; + } + return 1; +} + +struct altos_list { + struct altos_usbdev **dev; + int current; + int ndev; +}; + +struct altos_list * +altos_list_start(void) +{ + int e; + struct dirent **ents; + char *dir; + struct altos_usbdev *dev; + struct altos_list *devs; + int n; + + devs = calloc(1, sizeof (struct altos_list)); + if (!devs) + return NULL; + + n = scandir (USB_DEVICES, &ents, + dir_filter_dev, + alphasort); + if (!n) + return 0; + for (e = 0; e < n; e++) { + dir = cc_fullname(USB_DEVICES, ents[e]->d_name); + dev = usb_scan_device(dir); + free(dir); + if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { + if (devs->dev) + devs->dev = realloc(devs->dev, + devs->ndev + 1 * sizeof (struct usbdev *)); + else + devs->dev = malloc (sizeof (struct usbdev *)); + devs->dev[devs->ndev++] = dev; + } + } + free(ents); + devs->current = 0; + return devs; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + struct altos_usbdev *dev; + if (list->current >= list->ndev) + return 0; + dev = list->dev[list->current]; + strcpy(device->name, dev->product_name); + device->vendor = dev->idVendor; + device->product = dev->idProduct; + strcpy(device->path, dev->tty); + device->serial = dev->serial; + list->current++; + return 1; +} + +void +altos_list_finish(struct altos_list *usbdevs) +{ + int i; + + if (!usbdevs) + return; + for (i = 0; i < usbdevs->ndev; i++) + usbdev_free(usbdevs->dev[i]); + free(usbdevs); +} + +#endif + +#ifdef DARWIN + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct altos_list { + io_iterator_t iterator; +}; + +static int +get_string(io_object_t object, CFStringRef entry, char *result, int result_len) +{ + CFTypeRef entry_as_string; + Boolean got_string; + + entry_as_string = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_string) { + got_string = CFStringGetCString(entry_as_string, + result, result_len, + kCFStringEncodingASCII); + + CFRelease(entry_as_string); + if (got_string) + return 1; + } + return 0; +} + +static int +get_number(io_object_t object, CFStringRef entry, int *result) +{ + CFTypeRef entry_as_number; + Boolean got_number; + + entry_as_number = IORegistryEntrySearchCFProperty (object, + kIOServicePlane, + entry, + kCFAllocatorDefault, + kIORegistryIterateRecursively); + if (entry_as_number) { + got_number = CFNumberGetValue(entry_as_number, + kCFNumberIntType, + result); + if (got_number) + return 1; + } + return 0; +} + +struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc (sizeof (struct altos_list), 1); + CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); + io_iterator_t tdIterator; + io_object_t tdObject; + kern_return_t ret; + int i; + + ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); + if (ret != kIOReturnSuccess) + return NULL; + return list; +} + +int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + io_object_t object; + char serial_string[128]; + + for (;;) { + object = IOIteratorNext(list->iterator); + if (!object) + return 0; + + if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || + !get_number (object, CFSTR(kUSBProductID), &device->product)) + continue; + if (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->name, sizeof (device->name)) && + get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { + device->serial = atoi(serial_string); + return 1; + } + } +} + +void +altos_list_finish(struct altos_list *list) +{ + IOObjectRelease (list->iterator); + free(list); +} + +#endif + +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; +#ifdef USE_POLL + int pipe[2]; +#else + int out_fd; +#endif + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +PUBLIC struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + int ret; + struct termios term; + + if (!file) + return NULL; + + file->fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->fd < 0) { + perror(device->path); + 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; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->fd != -1) { + int fd = file->fd; + file->fd = -1; +#ifdef USE_POLL + write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + close(fd); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; +#ifdef USE_POLL + ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } + return 0; +} + +PUBLIC int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == USB_BUF_SIZE) { + ret = altos_flush(file); + if (ret) { + return ret; + } + } + file->out_data[file->out_used++] = c; + ret = 0; + if (file->out_used == USB_BUF_SIZE) + ret = altos_flush(file); + return 0; +} + +#ifdef USE_POLL +#include +#endif + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif + + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + ret = poll(fd, 2, timeout); + if (ret < 0) { + 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 + } + } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } + return 0; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + +#ifdef WINDOWS + +#include +#include +#include + +struct altos_list { + HDEVINFO dev_info; + int index; +}; + +#define USB_BUF_SIZE 64 + +struct altos_file { + HANDLE handle; + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; + OVERLAPPED ov_read; + BOOL pend_read; + OVERLAPPED ov_write; +}; + +PUBLIC struct altos_list * +altos_list_start(void) +{ + struct altos_list *list = calloc(1, sizeof (struct altos_list)); + + if (!list) + return NULL; + list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, + DIGCF_ALLCLASSES|DIGCF_PRESENT); + if (list->dev_info == INVALID_HANDLE_VALUE) { + printf("SetupDiGetClassDevs failed %d\n", GetLastError()); + free(list); + return NULL; + } + list->index = 0; + return list; +} + +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device) +{ + SP_DEVINFO_DATA dev_info_data; + char port[128]; + DWORD port_len; + char friendlyname[256]; + char symbolic[256]; + DWORD symbolic_len; + HKEY dev_key; + int vid, pid; + int serial; + HRESULT result; + DWORD friendlyname_type; + DWORD friendlyname_len; + + dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); + while(SetupDiEnumDeviceInfo(list->dev_info, list->index, + &dev_info_data)) + { + list->index++; + + dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, + DICS_FLAG_GLOBAL, 0, DIREG_DEV, + KEY_READ); + if (dev_key == INVALID_HANDLE_VALUE) { + printf("cannot open device registry key\n"); + continue; + } + + /* Fetch symbolic name for this device and parse out + * the vid/pid/serial info */ + symbolic_len = sizeof(symbolic); + result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, + symbolic, &symbolic_len); + if (result != 0) { + printf("cannot find SymbolicName value\n"); + RegCloseKey(dev_key); + continue; + } + vid = pid = serial = 0; + sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, + "%04X", &vid); + sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + "%04X", &pid); + sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + "%d", &serial); + if (!USB_IS_ALTUSMETRUM(vid, pid)) { + RegCloseKey(dev_key); + continue; + } + + /* Fetch the com port name */ + port_len = sizeof (port); + result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, + port, &port_len); + RegCloseKey(dev_key); + if (result != 0) { + printf("failed to get PortName\n"); + continue; + } + + /* Fetch the device description which is the device name, + * with firmware that has unique USB ids */ + friendlyname_len = sizeof (friendlyname); + if(!SetupDiGetDeviceRegistryProperty(list->dev_info, + &dev_info_data, + SPDRP_FRIENDLYNAME, + &friendlyname_type, + (BYTE *)friendlyname, + sizeof(friendlyname), + &friendlyname_len)) + { + printf("Failed to get friendlyname\n"); + continue; + } + device->vendor = vid; + device->product = pid; + device->serial = serial; + strcpy(device->name, friendlyname); + + strcpy(device->path, port); + return 1; + } + result = GetLastError(); + if (result != ERROR_NO_MORE_ITEMS) + printf ("SetupDiEnumDeviceInfo failed error %d\n", result); + return 0; +} + +PUBLIC void +altos_list_finish(struct altos_list *list) +{ + SetupDiDestroyDeviceInfoList(list->dev_info); + free(list); +} + +static int +altos_queue_read(struct altos_file *file) +{ + DWORD got; + if (file->pend_read) + return LIBALTOS_SUCCESS; + + if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { + if (GetLastError() != ERROR_IO_PENDING) + return LIBALTOS_ERROR; + file->pend_read = TRUE; + } else { + file->pend_read = FALSE; + file->in_read = 0; + file->in_used = got; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_wait_read(struct altos_file *file, int timeout) +{ + DWORD ret; + DWORD got; + + if (!file->pend_read) + return LIBALTOS_SUCCESS; + + if (!timeout) + timeout = INFINITE; + + ret = WaitForSingleObject(file->ov_read.hEvent, timeout); + switch (ret) { + case WAIT_OBJECT_0: + if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) + 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; + } + return LIBALTOS_SUCCESS; +} + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; + + if (file->in_read < file->in_used) + return LIBALTOS_SUCCESS; + + file->in_read = file->in_used = 0; + + ret = altos_queue_read(file); + if (ret) + return ret; + ret = altos_wait_read(file, timeout); + if (ret) + return ret; + + return LIBALTOS_SUCCESS; +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + DWORD put; + char *data = file->out_data; + char used = file->out_used; + DWORD ret; + + while (used) { + 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; + } + file->out_used = 0; + return LIBALTOS_SUCCESS; +} + +PUBLIC struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (1, sizeof (struct altos_file)); + char full_name[64]; + DCB dcbSerialParams = {0}; + COMMTIMEOUTS timeouts; + + if (!file) + return NULL; + + strcpy(full_name, "\\\\.\\"); + strcat(full_name, device->path); + file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + 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 = 1 << 30; /* almost forever */ + timeouts.WriteTotalTimeoutMultiplier = 0; + 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; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->handle != INVALID_HANDLE_VALUE) { + CloseHandle(file->handle); + file->handle = INVALID_HANDLE_VALUE; + } +} + +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 LIBALTOS_SUCCESS; +} + +int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->handle == INVALID_HANDLE_VALUE) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif diff --git a/altosui/libaltos/libaltos.dylib b/altosui/libaltos/libaltos.dylib new file mode 100755 index 00000000..89aa12e7 Binary files /dev/null and b/altosui/libaltos/libaltos.dylib differ diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h new file mode 100644 index 00000000..6e94899e --- /dev/null +++ b/altosui/libaltos/libaltos.h @@ -0,0 +1,102 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _LIBALTOS_H_ +#define _LIBALTOS_H_ + +#include + +#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# ifndef BUILD_STATIC +# ifdef BUILD_DLL +# define PUBLIC __declspec(dllexport) +# else +# define PUBLIC __declspec(dllimport) +# endif +# endif /* BUILD_STATIC */ +#endif + +#ifndef PUBLIC +# define PUBLIC +#endif + +#define USB_VENDOR_FSF 0xfffe +#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF +#define USB_PRODUCT_ALTUSMETRUM 0x000a +#define USB_PRODUCT_TELEMETRUM 0x000b +#define USB_PRODUCT_TELEDONGLE 0x000c +#define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 + +#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ + (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ + (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) + +struct altos_device { + //%immutable; + int vendor; + int product; + int serial; + char name[256]; + char path[256]; + //%mutable; +}; + +#define LIBALTOS_SUCCESS 0 +#define LIBALTOS_ERROR -1 +#define LIBALTOS_TIMEOUT -2 + +/* Returns 0 for success, < 0 on error */ +PUBLIC int +altos_init(void); + +PUBLIC void +altos_fini(void); + +PUBLIC struct altos_list * +altos_list_start(void); + +/* Returns 1 for success, zero on end of list */ +PUBLIC int +altos_list_next(struct altos_list *list, struct altos_device *device); + +PUBLIC void +altos_list_finish(struct altos_list *list); + +PUBLIC struct altos_file * +altos_open(struct altos_device *device); + +PUBLIC void +altos_close(struct altos_file *file); + +PUBLIC void +altos_free(struct altos_file *file); + +/* Returns < 0 for error */ +PUBLIC int +altos_putchar(struct altos_file *file, char c); + +/* Returns < 0 for error */ +PUBLIC int +altos_flush(struct altos_file *file); + +/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ +PUBLIC int +altos_getchar(struct altos_file *file, int timeout); + +#endif /* _LIBALTOS_H_ */ diff --git a/altosui/libaltos/libaltos.i0 b/altosui/libaltos/libaltos.i0 new file mode 100644 index 00000000..d06468f5 --- /dev/null +++ b/altosui/libaltos/libaltos.i0 @@ -0,0 +1,5 @@ +%module libaltos +%{ +#include "libaltos.h" +%} + diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 54dc777a..2850e909 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view libaltos altosui +SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view diff --git a/ao-tools/altosui/.gitignore b/ao-tools/altosui/.gitignore deleted file mode 100644 index 89be1d53..00000000 --- a/ao-tools/altosui/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -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 diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml deleted file mode 100644 index 18e00fe4..00000000 --- a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui-contents.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml deleted file mode 100644 index 6170931b..00000000 --- a/ao-tools/altosui/AltOS Package Configuration.pmdoc/01altosui.xml +++ /dev/null @@ -1 +0,0 @@ -org.altusmetrum.altosUi.AltosUI.pkg0.7AltosUI.app/Applications/AltosUI.appinstallTo.pathinstallFrom.isRelativeTypeversionparentrequireAuthorizationinstallTo01altosui-contents.xml/CVS$/\.svn$/\.cvsignore$/\.cvspass$/\.DS_Store$ \ No newline at end of file diff --git a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml b/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml deleted file mode 100644 index fabe54a6..00000000 --- a/ao-tools/altosui/AltOS Package Configuration.pmdoc/index.xml +++ /dev/null @@ -1 +0,0 @@ -AltOS UI/Users/keithp/altos/ao-tools/altosui/AltosUI.pkgorg.altusmetrumInstall AltOS User Interfacealtusmetrum.jpg01altosui.xmlproperties.anywhereDomainproperties.titleproperties.customizeOptiondescriptionproperties.userDomainproperties.systemDomain \ No newline at end of file diff --git a/ao-tools/altosui/Altos.java b/ao-tools/altosui/Altos.java deleted file mode 100644 index 8ee94e04..00000000 --- a/ao-tools/altosui/Altos.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.util.*; -import java.text.*; - -public class Altos { - /* EEProm command letters */ - static final int AO_LOG_FLIGHT = 'F'; - static final int AO_LOG_SENSOR = 'A'; - static final int AO_LOG_TEMP_VOLT = 'T'; - static final int AO_LOG_DEPLOY = 'D'; - static final int AO_LOG_STATE = 'S'; - static final int AO_LOG_GPS_TIME = 'G'; - static final int AO_LOG_GPS_LAT = 'N'; - static final int AO_LOG_GPS_LON = 'W'; - static final int AO_LOG_GPS_ALT = 'H'; - static final int AO_LOG_GPS_SAT = 'V'; - static final int AO_LOG_GPS_DATE = 'Y'; - - /* Added for header fields in eeprom files */ - static final int AO_LOG_CONFIG_VERSION = 1000; - static final int AO_LOG_MAIN_DEPLOY = 1001; - static final int AO_LOG_APOGEE_DELAY = 1002; - static final int AO_LOG_RADIO_CHANNEL = 1003; - static final int AO_LOG_CALLSIGN = 1004; - static final int AO_LOG_ACCEL_CAL = 1005; - static final int AO_LOG_RADIO_CAL = 1006; - static final int AO_LOG_MANUFACTURER = 1007; - static final int AO_LOG_PRODUCT = 1008; - static final int AO_LOG_SERIAL_NUMBER = 1009; - static final int AO_LOG_SOFTWARE_VERSION = 1010; - - /* Added to flag invalid records */ - static final int AO_LOG_INVALID = -1; - - /* Flight state numbers and names */ - static final int ao_flight_startup = 0; - static final int ao_flight_idle = 1; - static final int ao_flight_pad = 2; - static final int ao_flight_boost = 3; - static final int ao_flight_fast = 4; - static final int ao_flight_coast = 5; - static final int ao_flight_drogue = 6; - static final int ao_flight_main = 7; - static final int ao_flight_landed = 8; - static final int ao_flight_invalid = 9; - - static HashMap string_to_state = new HashMap(); - - static boolean map_initialized = false; - - static final int tab_elt_pad = 5; - - static final Font label_font = new Font("Dialog", Font.PLAIN, 22); - static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); - static final Font status_font = new Font("SansSerif", Font.BOLD, 24); - - static final int text_width = 16; - - static void initialize_map() - { - string_to_state.put("startup", ao_flight_startup); - string_to_state.put("idle", ao_flight_idle); - string_to_state.put("pad", ao_flight_pad); - string_to_state.put("boost", ao_flight_boost); - string_to_state.put("fast", ao_flight_fast); - string_to_state.put("coast", ao_flight_coast); - string_to_state.put("drogue", ao_flight_drogue); - string_to_state.put("main", ao_flight_main); - string_to_state.put("landed", ao_flight_landed); - string_to_state.put("invalid", ao_flight_invalid); - map_initialized = true; - } - - static String[] state_to_string = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - static public int state(String state) { - if (!map_initialized) - initialize_map(); - if (string_to_state.containsKey(state)) - return string_to_state.get(state); - return ao_flight_invalid; - } - - static public String state_name(int state) { - if (state < 0 || state_to_string.length <= state) - return "invalid"; - return state_to_string[state]; - } - - static final int AO_GPS_VALID = (1 << 4); - static final int AO_GPS_RUNNING = (1 << 5); - 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; - } - - static String replace_extension(String input, String extension) { - int dot = input.lastIndexOf("."); - if (dot > 0) - input = input.substring(0,dot); - return input.concat(extension); - } -} diff --git a/ao-tools/altosui/AltosAscent.java b/ao-tools/altosui/AltosAscent.java deleted file mode 100644 index 64bdcf30..00000000 --- a/ao-tools/altosui/AltosAscent.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosAscent extends JComponent implements AltosFlightDisplay { - GridBagLayout layout; - - public class AscentStatus { - JLabel label; - JTextField value; - AltosLights lights; - - void show(AltosState state, int crc_errors) {} - void reset() { - value.setText(""); - lights.set(false); - } - - public AscentStatus (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - lights = new AltosLights(); - c.gridx = 0; c.gridy = y; - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(lights, c); - add(lights); - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.gridwidth = 2; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - - } - } - - public class AscentValue { - JLabel label; - JTextField value; - void show(AltosState state, int crc_errors) {} - - void reset() { - value.setText(""); - } - public AscentValue (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.gridwidth = 2; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - } - } - - public class AscentValueHold { - JLabel label; - JTextField value; - JTextField max_value; - double max; - - void show(AltosState state, int crc_errors) {} - - void reset() { - value.setText(""); - max_value.setText(""); - max = 0; - } - - void show(String format, double v) { - value.setText(String.format(format, v)); - if (v > max) { - max_value.setText(String.format(format, v)); - max = v; - } - } - public AscentValueHold (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - - max_value = new JTextField(Altos.text_width); - max_value.setFont(Altos.value_font); - max_value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 3; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(max_value, c); - add(max_value); - } - } - - - class Height extends AscentValueHold { - void show (AltosState state, int crc_errors) { - show("%6.0f m", state.height); - } - public Height (GridBagLayout layout, int y) { - super (layout, y, "Height"); - } - } - - Height height; - - class Speed extends AscentValueHold { - void show (AltosState state, int crc_errors) { - double speed = state.speed; - if (!state.ascent) - speed = state.baro_speed; - show("%6.0f m/s", speed); - } - public Speed (GridBagLayout layout, int y) { - super (layout, y, "Speed"); - } - } - - Speed speed; - - class Accel extends AscentValueHold { - void show (AltosState state, int crc_errors) { - show("%6.0f m/s²", state.acceleration); - } - public Accel (GridBagLayout layout, int y) { - super (layout, y, "Acceleration"); - } - } - - Accel accel; - - String pos(double p, String pos, String neg) { - String h = pos; - if (p < 0) { - h = neg; - p = -p; - } - int deg = (int) Math.floor(p); - double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %4d° %9.6f", h, deg, min); - } - - class Apogee extends AscentStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.drogue_sense)); - lights.set(state.drogue_sense > 3.2); - } - public Apogee (GridBagLayout layout, int y) { - super(layout, y, "Apogee Igniter Voltage"); - } - } - - Apogee apogee; - - class Main extends AscentStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.main_sense)); - lights.set(state.main_sense > 3.2); - } - public Main (GridBagLayout layout, int y) { - super(layout, y, "Main Igniter Voltage"); - } - } - - Main main; - - class Lat extends AscentValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - value.setText(pos(state.gps.lat,"N", "S")); - else - value.setText("???"); - } - public Lat (GridBagLayout layout, int y) { - super (layout, y, "Latitude"); - } - } - - Lat lat; - - class Lon extends AscentValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - value.setText(pos(state.gps.lon,"E", "W")); - else - value.setText("???"); - } - public Lon (GridBagLayout layout, int y) { - super (layout, y, "Longitude"); - } - } - - Lon lon; - - public void reset() { - lat.reset(); - lon.reset(); - main.reset(); - apogee.reset(); - height.reset(); - speed.reset(); - accel.reset(); - } - - public void show(AltosState state, int crc_errors) { - lat.show(state, crc_errors); - lon.show(state, crc_errors); - height.show(state, crc_errors); - main.show(state, crc_errors); - apogee.show(state, crc_errors); - speed.show(state, crc_errors); - accel.show(state, crc_errors); - } - - public void labels(GridBagLayout layout, int y) { - GridBagConstraints c; - JLabel cur, max; - - cur = new JLabel("Current"); - cur.setFont(Altos.label_font); - c = new GridBagConstraints(); - c.gridx = 2; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - layout.setConstraints(cur, c); - add(cur); - - max = new JLabel("Maximum"); - max.setFont(Altos.label_font); - c.gridx = 3; c.gridy = y; - layout.setConstraints(max, c); - add(max); - } - - public AltosAscent() { - layout = new GridBagLayout(); - - setLayout(layout); - - /* Elements in ascent display: - * - * lat - * lon - * height - */ - labels(layout, 0); - height = new Height(layout, 1); - speed = new Speed(layout, 2); - accel = new Accel(layout, 3); - lat = new Lat(layout, 4); - lon = new Lon(layout, 5); - apogee = new Apogee(layout, 6); - main = new Main(layout, 7); - } -} diff --git a/ao-tools/altosui/AltosCRCException.java b/ao-tools/altosui/AltosCRCException.java deleted file mode 100644 index 4a529bcf..00000000 --- a/ao-tools/altosui/AltosCRCException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - } -} diff --git a/ao-tools/altosui/AltosCSV.java b/ao-tools/altosui/AltosCSV.java deleted file mode 100644 index df98b2b4..00000000 --- a/ao-tools/altosui/AltosCSV.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.*; - -public class AltosCSV implements AltosWriter { - File name; - PrintStream out; - boolean header_written; - boolean seen_boost; - int boost_tick; - LinkedList pad_records; - AltosState state; - - static final int ALTOS_CSV_VERSION = 2; - - /* Version 2 format: - * - * General info - * version number - * serial number - * flight number - * callsign - * time (seconds since boost) - * rssi - * link quality - * - * Flight status - * state - * state name - * - * Basic sensors - * acceleration (m/s²) - * pressure (mBar) - * altitude (m) - * height (m) - * accelerometer speed (m/s) - * barometer speed (m/s) - * temp (°C) - * battery (V) - * drogue (V) - * main (V) - * - * GPS data - * connected (1/0) - * locked (1/0) - * nsat (used for solution) - * latitude (°) - * longitude (°) - * altitude (m) - * year (e.g. 2010) - * month (1-12) - * day (1-31) - * 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) - * hdop - * - * GPS Sat data - * C/N0 data for all 32 valid SDIDs - */ - - void write_general_header() { - out.printf("version,serial,flight,call,time,rssi,lqi"); - } - - void write_general(AltosRecord record) { - out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d", - ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign, - (double) record.time, - record.rssi, - record.status & 0x7f); - } - - void write_flight_header() { - out.printf("state,state_name"); - } - - void write_flight(AltosRecord record) { - 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.raw_pressure(), - record.raw_altitude(), - record.raw_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,hdop"); - } - - 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,%6.1f", - 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, - gps.hdop); - } - - void write_gps_sat_header() { - for(int i = 1; i <= 32; i++) { - out.printf("sat%02d", i); - if (i != 32) - out.printf(","); - } - } - - void write_gps_sat(AltosRecord record) { - AltosGPS gps = record.gps; - for(int i = 1; i <= 32; i++) { - int c_n0 = 0; - if (gps != null && gps.cc_gps_sat != null) { - for(int j = 0; j < gps.cc_gps_sat.length; j++) - if (gps.cc_gps_sat[j].svid == i) { - c_n0 = gps.cc_gps_sat[j].c_n0; - break; - } - } - out.printf ("%3d", c_n0); - if (i != 32) - out.printf(","); - } - } - - 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(","); write_gps_sat_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(","); - write_gps_sat(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; - } - 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(AltosRecordIterable iterable) { - iterable.write_comments(out()); - for (AltosRecord r : iterable) - write(r); - } - - public AltosCSV(File in_name) throws FileNotFoundException { - name = in_name; - out = new PrintStream(name); - pad_records = new LinkedList(); - } - - public AltosCSV(String in_string) throws FileNotFoundException { - this(new File(in_string)); - } -} diff --git a/ao-tools/altosui/AltosCSVUI.java b/ao-tools/altosui/AltosCSVUI.java deleted file mode 100644 index e1b6002d..00000000 --- a/ao-tools/altosui/AltosCSVUI.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosCSVUI - extends JDialog - implements ActionListener -{ - JFileChooser csv_chooser; - JPanel accessory; - JComboBox combo_box; - AltosRecordIterable iterable; - AltosWriter writer; - - static String[] combo_box_items = { "Comma Separated Values (.CSV)", "Googleearth Data (.KML)" }; - - void set_default_file() { - File current = csv_chooser.getSelectedFile(); - String current_name = current.getName(); - String new_name = null; - String selected = (String) combo_box.getSelectedItem(); - - if (selected.contains("CSV")) - new_name = Altos.replace_extension(current_name, ".csv"); - else if (selected.contains("KML")) - new_name = Altos.replace_extension(current_name, ".kml"); - if (new_name != null) - csv_chooser.setSelectedFile(new File(new_name)); - } - - public void actionPerformed(ActionEvent e) { - if (e.getActionCommand().equals("comboBoxChanged")) - set_default_file(); - } - - public AltosCSVUI(JFrame frame, AltosRecordIterable in_iterable, File source_file) { - iterable = in_iterable; - csv_chooser = new JFileChooser(source_file); - - accessory = new JPanel(); - accessory.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.weightx = 1; - c.weighty = 0; - c.insets = new Insets (4, 4, 4, 4); - - JLabel accessory_label = new JLabel("Export File Type"); - c.gridx = 0; - c.gridy = 0; - accessory.add(accessory_label, c); - - combo_box = new JComboBox(combo_box_items); - combo_box.addActionListener(this); - c.gridx = 0; - c.gridy = 1; - accessory.add(combo_box, c); - - csv_chooser.setAccessory(accessory); - csv_chooser.setSelectedFile(source_file); - set_default_file(); - int ret = csv_chooser.showSaveDialog(frame); - if (ret == JFileChooser.APPROVE_OPTION) { - File file = csv_chooser.getSelectedFile(); - String type = (String) combo_box.getSelectedItem(); - try { - if (type.contains("CSV")) - writer = new AltosCSV(file); - else - writer = new AltosKML(file); - writer.write(iterable); - writer.close(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - file.getName(), - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } - } -} diff --git a/ao-tools/altosui/AltosChannelMenu.java b/ao-tools/altosui/AltosChannelMenu.java deleted file mode 100644 index abbb86f4..00000000 --- a/ao-tools/altosui/AltosChannelMenu.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosChannelMenu extends JComboBox implements ActionListener { - int channel; - - public AltosChannelMenu(int current_channel) { - - channel = current_channel; - - for (int c = 0; c <= 9; c++) - addItem(String.format("Channel %1d (%7.3fMHz)", c, 434.550 + c * 0.1)); - setSelectedIndex(channel); - setMaximumRowCount(10); - } - -} diff --git a/ao-tools/altosui/AltosConfig.java b/ao-tools/altosui/AltosConfig.java deleted file mode 100644 index 1c42870f..00000000 --- a/ao-tools/altosui/AltosConfig.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -import libaltosJNI.*; - -public class AltosConfig implements Runnable, ActionListener { - - class int_ref { - int value; - - public int get() { - return value; - } - public void set(int i) { - value = i; - } - public int_ref(int i) { - value = i; - } - } - - class string_ref { - String value; - - public String get() { - return value; - } - public void set(String i) { - value = i; - } - public string_ref(String i) { - value = i; - } - } - - JFrame owner; - AltosDevice device; - AltosSerial serial_line; - boolean remote; - Thread config_thread; - int_ref serial; - int_ref main_deploy; - int_ref apogee_delay; - int_ref radio_channel; - int_ref radio_calibration; - string_ref version; - string_ref product; - string_ref callsign; - AltosConfigUI config_ui; - boolean serial_started; - - boolean get_int(String line, String label, int_ref x) { - if (line.startsWith(label)) { - try { - String tail = line.substring(label.length()).trim(); - String[] tokens = tail.split("\\s+"); - if (tokens.length > 0) { - int i = Integer.parseInt(tokens[0]); - x.set(i); - return true; - } - } catch (NumberFormatException ne) { - } - } - return false; - } - - boolean get_string(String line, String label, string_ref s) { - if (line.startsWith(label)) { - String quoted = line.substring(label.length()).trim(); - - if (quoted.startsWith("\"")) - quoted = quoted.substring(1); - if (quoted.endsWith("\"")) - quoted = quoted.substring(0,quoted.length()-1); - s.set(quoted); - return true; - } else { - return false; - } - } - - void start_serial() throws InterruptedException { - serial_started = true; - if (remote) { - serial_line.set_radio(); - serial_line.printf("p\nE 0\n"); - serial_line.flush_input(); - } - } - - void stop_serial() throws InterruptedException { - if (!serial_started) - return; - serial_started = false; - if (remote) { - serial_line.printf("~"); - serial_line.flush_output(); - } - } - - void get_data() throws InterruptedException, TimeoutException { - try { - start_serial(); - serial_line.printf("c s\nv\n"); - for (;;) { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - get_int(line, "serial-number", serial); - get_int(line, "Main deploy:", main_deploy); - get_int(line, "Apogee delay:", apogee_delay); - get_int(line, "Radio channel:", radio_channel); - get_int(line, "Radio cal:", radio_calibration); - get_string(line, "Callsign:", callsign); - get_string(line,"software-version", version); - get_string(line,"product", product); - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } - } finally { - stop_serial(); - } - } - - void init_ui () throws InterruptedException, TimeoutException { - config_ui = new AltosConfigUI(owner, remote); - config_ui.addActionListener(this); - set_ui(); - } - - void abort() { - JOptionPane.showMessageDialog(owner, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); - try { - stop_serial(); - } catch (InterruptedException ie) { - } - serial_line.close(); - serial_line = null; - } - - void set_ui() throws InterruptedException, TimeoutException { - if (serial_line != null) - get_data(); - config_ui.set_serial(serial.get()); - config_ui.set_product(product.get()); - config_ui.set_version(version.get()); - config_ui.set_main_deploy(main_deploy.get()); - config_ui.set_apogee_delay(apogee_delay.get()); - config_ui.set_radio_channel(radio_channel.get()); - config_ui.set_radio_calibration(radio_calibration.get()); - config_ui.set_callsign(callsign.get()); - config_ui.set_clean(); - } - - void run_dialog() { - } - - void save_data() { - main_deploy.set(config_ui.main_deploy()); - apogee_delay.set(config_ui.apogee_delay()); - radio_channel.set(config_ui.radio_channel()); - radio_calibration.set(config_ui.radio_calibration()); - callsign.set(config_ui.callsign()); - try { - start_serial(); - serial_line.printf("c m %d\n", main_deploy.get()); - serial_line.printf("c d %d\n", apogee_delay.get()); - if (!remote) { - serial_line.printf("c r %d\n", radio_channel.get()); - serial_line.printf("c f %d\n", radio_calibration.get()); - } - serial_line.printf("c c %s\n", callsign.get()); - serial_line.printf("c w\n"); - } catch (InterruptedException ie) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - } - } - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - try { - if (cmd.equals("Save")) { - save_data(); - set_ui(); - } else if (cmd.equals("Reset")) { - set_ui(); - } else if (cmd.equals("Reboot")) { - if (serial_line != null) { - start_serial(); - serial_line.printf("r eboot\n"); - serial_line.flush_output(); - stop_serial(); - serial_line.close(); - } - } else if (cmd.equals("Close")) { - if (serial_line != null) - serial_line.close(); - } - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } - } - - public void run () { - try { - init_ui(); - config_ui.make_visible(); - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } - } - - public AltosConfig(JFrame given_owner) { - owner = given_owner; - - serial = new int_ref(0); - main_deploy = new int_ref(250); - apogee_delay = new int_ref(0); - radio_channel = new int_ref(0); - radio_calibration = new int_ref(1186611); - callsign = new string_ref("N0CALL"); - version = new string_ref("unknown"); - product = new string_ref("unknown"); - - device = AltosDeviceDialog.show(owner, AltosDevice.product_any); - if (device != null) { - try { - serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) - remote = true; - config_thread = new Thread(this); - config_thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(owner, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosConfigUI.java b/ao-tools/altosui/AltosConfigUI.java deleted file mode 100644 index cfa5d7b9..00000000 --- a/ao-tools/altosui/AltosConfigUI.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.concurrent.LinkedBlockingQueue; - -import libaltosJNI.*; - -public class AltosConfigUI - extends JDialog - implements ActionListener, ItemListener, DocumentListener -{ - - Container pane; - Box box; - JLabel product_label; - JLabel version_label; - JLabel serial_label; - JLabel main_deploy_label; - JLabel apogee_delay_label; - JLabel radio_channel_label; - JLabel radio_calibration_label; - JLabel callsign_label; - - public boolean dirty; - - JFrame owner; - JLabel product_value; - JLabel version_value; - JLabel serial_value; - JComboBox main_deploy_value; - JComboBox apogee_delay_value; - JComboBox radio_channel_value; - JTextField radio_calibration_value; - JTextField callsign_value; - - JButton save; - JButton reset; - JButton reboot; - JButton close; - - ActionListener listener; - - static String[] main_deploy_values = { - "100", "150", "200", "250", "300", "350", - "400", "450", "500" - }; - - static String[] apogee_delay_values = { - "0", "1", "2", "3", "4", "5" - }; - - static String[] radio_channel_values = new String[10]; - { - for (int i = 0; i <= 9; i++) - radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)", - i, 434.550 + i * 0.1); - } - - /* A window listener to catch closing events and tell the config code */ - class ConfigListener extends WindowAdapter { - AltosConfigUI ui; - - public ConfigListener(AltosConfigUI this_ui) { - ui = this_ui; - } - - public void windowClosing(WindowEvent e) { - ui.actionPerformed(new ActionEvent(e.getSource(), - ActionEvent.ACTION_PERFORMED, - "Close")); - } - } - - /* Build the UI using a grid bag */ - public AltosConfigUI(JFrame in_owner, boolean remote) { - super (in_owner, "Configure TeleMetrum", false); - - 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()); - - /* Product */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - product_label = new JLabel("Product:"); - pane.add(product_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 0; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - product_value = new JLabel(""); - pane.add(product_value, c); - - /* Version */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 1; - c.gridwidth = 4; - 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 = new GridBagConstraints(); - c.gridx = 4; c.gridy = 1; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - version_value = new JLabel(""); - pane.add(version_value, c); - - /* Serial */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 2; - c.gridwidth = 4; - 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 = new GridBagConstraints(); - c.gridx = 4; c.gridy = 2; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - serial_value = new JLabel(""); - pane.add(serial_value, c); - - /* Main deploy */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 3; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - main_deploy_label = new JLabel("Main Deploy Altitude(m):"); - pane.add(main_deploy_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 3; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - main_deploy_value = new JComboBox(main_deploy_values); - main_deploy_value.setEditable(true); - main_deploy_value.addItemListener(this); - pane.add(main_deploy_value, c); - - /* Apogee delay */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 4; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - apogee_delay_label = new JLabel("Apogee Delay(s):"); - pane.add(apogee_delay_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 4; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - apogee_delay_value = new JComboBox(apogee_delay_values); - apogee_delay_value.setEditable(true); - apogee_delay_value.addItemListener(this); - pane.add(apogee_delay_value, c); - - /* Radio channel */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 5; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - radio_channel_label = new JLabel("Radio Channel:"); - pane.add(radio_channel_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 5; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - radio_channel_value = new JComboBox(radio_channel_values); - radio_channel_value.setEditable(false); - radio_channel_value.addItemListener(this); - if (remote) - radio_channel_value.setEnabled(false); - pane.add(radio_channel_value, c); - - /* Radio Calibration */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 6; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - radio_calibration_label = new JLabel("RF Calibration:"); - pane.add(radio_calibration_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 6; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - radio_calibration_value = new JTextField(String.format("%d", 1186611)); - radio_calibration_value.getDocument().addDocumentListener(this); - if (remote) - radio_calibration_value.setEnabled(false); - pane.add(radio_calibration_value, c); - - /* Callsign */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 7; - c.gridwidth = 4; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - c.ipady = 5; - callsign_label = new JLabel("Callsign:"); - pane.add(callsign_label, c); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 7; - c.gridwidth = 4; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - c.ipady = 5; - callsign_value = new JTextField(AltosPreferences.callsign()); - callsign_value.getDocument().addDocumentListener(this); - pane.add(callsign_value, c); - - /* Buttons */ - c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_START; - c.insets = il; - save = new JButton("Save"); - pane.add(save, c); - save.addActionListener(this); - save.setActionCommand("Save"); - - c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 8; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = il; - reset = new JButton("Reset"); - pane.add(reset, c); - reset.addActionListener(this); - reset.setActionCommand("Reset"); - - c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 8; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = il; - reboot = new JButton("Reboot"); - pane.add(reboot, c); - reboot.addActionListener(this); - reboot.setActionCommand("Reboot"); - - c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 8; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.LINE_END; - c.insets = il; - close = new JButton("Close"); - pane.add(close, c); - close.addActionListener(this); - close.setActionCommand("Close"); - - addWindowListener(new ConfigListener(this)); - } - - /* Once the initial values are set, the config code will show the dialog */ - public void make_visible() { - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - /* If any values have been changed, confirm before closing */ - public boolean check_dirty(String operation) { - if (dirty) { - Object[] options = { String.format("%s anyway", operation), "Keep editing" }; - int i; - i = JOptionPane.showOptionDialog(this, - String.format("Configuration modified. %s anyway?", operation), - "Configuration Modified", - JOptionPane.DEFAULT_OPTION, - JOptionPane.WARNING_MESSAGE, - null, options, options[1]); - if (i != 0) - return false; - } - return true; - } - - /* Listen for events from our buttons */ - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - - if (cmd.equals("Close") || cmd.equals("Reboot")) - if (!check_dirty(cmd)) - return; - listener.actionPerformed(e); - if (cmd.equals("Close") || cmd.equals("Reboot")) { - setVisible(false); - dispose(); - } - dirty = false; - } - - /* ItemListener interface method */ - public void itemStateChanged(ItemEvent e) { - dirty = true; - } - - /* DocumentListener interface methods */ - public void changedUpdate(DocumentEvent e) { - dirty = true; - } - - public void insertUpdate(DocumentEvent e) { - dirty = true; - } - - public void removeUpdate(DocumentEvent e) { - dirty = true; - } - - /* Let the config code hook on a listener */ - public void addActionListener(ActionListener l) { - listener = l; - } - - /* set and get all of the dialog values */ - public void set_product(String product) { - product_value.setText(product); - } - - public void set_version(String version) { - version_value.setText(version); - } - - public void set_serial(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - public void set_main_deploy(int new_main_deploy) { - main_deploy_value.setSelectedItem(Integer.toString(new_main_deploy)); - } - - public int main_deploy() { - return Integer.parseInt(main_deploy_value.getSelectedItem().toString()); - } - - public void set_apogee_delay(int new_apogee_delay) { - apogee_delay_value.setSelectedItem(Integer.toString(new_apogee_delay)); - } - - public int apogee_delay() { - return Integer.parseInt(apogee_delay_value.getSelectedItem().toString()); - } - - public void set_radio_channel(int new_radio_channel) { - radio_channel_value.setSelectedIndex(new_radio_channel); - } - - public int radio_channel() { - return radio_channel_value.getSelectedIndex(); - } - - public void set_radio_calibration(int new_radio_calibration) { - radio_calibration_value.setText(String.format("%d", new_radio_calibration)); - } - - public int radio_calibration() { - return Integer.parseInt(radio_calibration_value.getText()); - } - - public void set_callsign(String new_callsign) { - callsign_value.setText(new_callsign); - } - - public String callsign() { - return callsign_value.getText(); - } - - public void set_clean() { - dirty = false; - } - - } \ No newline at end of file diff --git a/ao-tools/altosui/AltosConfigureUI.java b/ao-tools/altosui/AltosConfigureUI.java deleted file mode 100644 index 153c59fd..00000000 --- a/ao-tools/altosui/AltosConfigureUI.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.concurrent.LinkedBlockingQueue; - -public class AltosConfigureUI - extends JDialog - implements DocumentListener -{ - JFrame owner; - AltosVoice voice; - Container pane; - - JRadioButton enable_voice; - JButton test_voice; - JButton close; - - JButton configure_log; - JTextField log_directory; - - JLabel callsign_label; - JTextField callsign_value; - - /* DocumentListener interface methods */ - public void changedUpdate(DocumentEvent e) { - AltosPreferences.set_callsign(callsign_value.getText()); - } - - public void insertUpdate(DocumentEvent e) { - changedUpdate(e); - } - - public void removeUpdate(DocumentEvent e) { - changedUpdate(e); - } - - public AltosConfigureUI(JFrame in_owner, AltosVoice in_voice) { - super(in_owner, "Configure AltosUI", false); - - GridBagConstraints c; - - Insets insets = new Insets(4, 4, 4, 4); - - owner = in_owner; - voice = in_voice; - pane = getContentPane(); - pane.setLayout(new GridBagLayout()); - - c = new GridBagConstraints(); - c.insets = insets; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - - /* Nice label at the top */ - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - pane.add(new JLabel ("Configure AltOS UI"), c); - - /* Voice settings */ - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Voice"), c); - - enable_voice = new JRadioButton("Enable", AltosPreferences.voice()); - enable_voice.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - JRadioButton item = (JRadioButton) e.getSource(); - boolean enabled = item.isSelected(); - AltosPreferences.set_voice(enabled); - if (enabled) - voice.speak_always("Enable voice."); - else - voice.speak_always("Disable voice."); - } - }); - c.gridx = 1; - c.gridy = 1; - c.gridwidth = 1; - c.weightx = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(enable_voice, c); - - c.gridx = 2; - c.gridy = 1; - c.gridwidth = 1; - c.weightx = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.EAST; - test_voice = new JButton("Test Voice"); - test_voice.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - voice.speak("That's one small step for man; one giant leap for mankind."); - } - }); - pane.add(test_voice, c); - - /* Log directory settings */ - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Log Directory"), c); - - configure_log = new JButton(AltosPreferences.logdir().getPath()); - configure_log.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - AltosPreferences.ConfigureLog(); - configure_log.setText(AltosPreferences.logdir().getPath()); - } - }); - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(configure_log, c); - - /* Callsign setting */ - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 1; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(new JLabel("Callsign"), c); - - callsign_value = new JTextField(AltosPreferences.callsign()); - callsign_value.getDocument().addDocumentListener(this); - c.gridx = 1; - c.gridy = 3; - c.gridwidth = 2; - c.fill = GridBagConstraints.BOTH; - c.anchor = GridBagConstraints.WEST; - pane.add(callsign_value, c); - - /* And a close button at the bottom */ - close = new JButton("Close"); - close.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - setVisible(false); - } - }); - c.gridx = 0; - c.gridy = 4; - c.gridwidth = 3; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - pane.add(close, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } -} diff --git a/ao-tools/altosui/AltosConvert.java b/ao-tools/altosui/AltosConvert.java deleted file mode 100644 index 8cc1df27..00000000 --- a/ao-tools/altosui/AltosConvert.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Sensor data conversion functions - */ -package altosui; - -public class AltosConvert { - /* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ - return 0; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted altitude */ - for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - base_pressure *= Math.pow(base, exponent); - } - base_temperature += delta_z * lapse_rate[layer_number]; - } - - /* calculate the pressure at the inputted altitude */ - delta_z = altitude - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - pressure = base_pressure * Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - pressure = base_pressure * Math.pow(base, exponent); - } - - return pressure; - } - - -/* outputs the altitude associated with the given pressure. the altitude - returned is measured with respect to the mean sea level */ - static double - pressure_to_altitude(double pressure) - { - - double next_base_temperature = LAYER0_BASE_TEMPERATURE; - double next_base_pressure = LAYER0_BASE_PRESSURE; - - double altitude; - double base_pressure; - double base_temperature; - double base; /* base for function to determine base pressure of next layer */ - double exponent; /* exponent for function to determine base pressure - of next layer */ - double coefficient; - int layer_number; /* identifies layer in the atmosphere */ - int delta_z; /* difference between two altitudes */ - - if (pressure < 0) /* illegal pressure */ - return -1; - if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ - return MAXIMUM_ALTITUDE; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted pressure. */ - layer_number = -1; - do { - layer_number++; - base_pressure = next_base_pressure; - base_temperature = next_base_temperature; - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - next_base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - next_base_pressure *= Math.pow(base, exponent); - } - next_base_temperature += delta_z * lapse_rate[layer_number]; - } - while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); - - /* calculate the altitude associated with the inputted pressure */ - if (lapse_rate[layer_number] == 0.0) { - coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) - * base_temperature; - altitude = base_altitude[layer_number] - + coefficient * Math.log(pressure / base_pressure); - } - else { - base = pressure / base_pressure; - exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] - / GRAVITATIONAL_ACCELERATION; - coefficient = base_temperature / lapse_rate[layer_number]; - altitude = base_altitude[layer_number] - + coefficient * (Math.pow(base, exponent) - 1); - } - - return altitude; - } - - static double - cc_battery_to_voltage(double battery) - { - return battery / 32767.0 * 5.0; - } - - static double - cc_ignitor_to_voltage(double ignite) - { - return ignite / 32767 * 15.0; - } -} diff --git a/ao-tools/altosui/AltosDataChooser.java b/ao-tools/altosui/AltosDataChooser.java deleted file mode 100644 index 15de05c2..00000000 --- a/ao-tools/altosui/AltosDataChooser.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -public class AltosDataChooser extends JFileChooser { - JFrame frame; - String filename; - File file; - - public String filename() { - return filename; - } - - public File file() { - return file; - } - - public AltosRecordIterable runDialog() { - int ret; - - ret = showOpenDialog(frame); - if (ret == APPROVE_OPTION) { - file = getSelectedFile(); - if (file == null) - return null; - filename = file.getName(); - try { - if (filename.endsWith("eeprom")) { - FileInputStream in = new FileInputStream(file); - return new AltosEepromIterable(in); - } else if (filename.endsWith("telem")) { - FileInputStream in = new FileInputStream(file); - return new AltosTelemetryIterable(in); - } else { - throw new FileNotFoundException(); - } - } catch (FileNotFoundException fe) { - JOptionPane.showMessageDialog(frame, - filename, - "Cannot open file", - JOptionPane.ERROR_MESSAGE); - } - } - return null; - } - - public AltosDataChooser(JFrame in_frame) { - frame = in_frame; - setDialogTitle("Select Flight Record File"); - setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom")); - setCurrentDirectory(AltosPreferences.logdir()); - } -} diff --git a/ao-tools/altosui/AltosDataPoint.java b/ao-tools/altosui/AltosDataPoint.java deleted file mode 100644 index 66313e03..00000000 --- a/ao-tools/altosui/AltosDataPoint.java +++ /dev/null @@ -1,29 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -interface AltosDataPoint { - int version(); - int serial(); - int flight(); - String callsign(); - double time(); - double rssi(); - - int state(); - String state_name(); - - double acceleration(); - double pressure(); - double altitude(); - double height(); - double accel_speed(); - double baro_speed(); - double temperature(); - double battery_voltage(); - double drogue_voltage(); - double main_voltage(); -} - diff --git a/ao-tools/altosui/AltosDataPointReader.java b/ao-tools/altosui/AltosDataPointReader.java deleted file mode 100644 index 7704310b..00000000 --- a/ao-tools/altosui/AltosDataPointReader.java +++ /dev/null @@ -1,72 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -import java.io.IOException; -import java.text.ParseException; -import java.lang.UnsupportedOperationException; -import java.util.NoSuchElementException; -import java.util.Iterator; - -class AltosDataPointReader implements Iterable { - Iterator iter; - AltosState state; - AltosRecord record; - - public AltosDataPointReader(Iterable reader) { - this.iter = reader.iterator(); - this.state = null; - } - - private void read_next_record() - throws NoSuchElementException - { - record = iter.next(); - state = new AltosState(record, state); - } - - private AltosDataPoint current_dp() { - assert this.record != null; - - return new AltosDataPoint() { - public int version() { return record.version; } - public int serial() { return record.serial; } - public int flight() { return record.flight; } - public String callsign() { return record.callsign; } - public double time() { return record.time; } - public double rssi() { return record.rssi; } - - public int state() { return record.state; } - public String state_name() { return record.state(); } - - public double acceleration() { return record.acceleration(); } - public double pressure() { return record.raw_pressure(); } - public double altitude() { return record.raw_altitude(); } - public double height() { return record.raw_height(); } - public double accel_speed() { return record.accel_speed(); } - public double baro_speed() { return state.baro_speed; } - public double temperature() { return record.temperature(); } - public double battery_voltage() { return record.battery_voltage(); } - public double drogue_voltage() { return record.drogue_voltage(); } - public double main_voltage() { return record.main_voltage(); } - }; - } - - public Iterator iterator() { - return new Iterator() { - public void remove() { - throw new UnsupportedOperationException(); - } - public boolean hasNext() { - return iter.hasNext(); - } - public AltosDataPoint next() { - read_next_record(); - return current_dp(); - } - }; - } -} - diff --git a/ao-tools/altosui/AltosDebug.java b/ao-tools/altosui/AltosDebug.java deleted file mode 100644 index 8d435b66..00000000 --- a/ao-tools/altosui/AltosDebug.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; -import java.util.*; - -import libaltosJNI.*; - -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"); - } - - public AltosDebug (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { - super(in_device); - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosDescent.java b/ao-tools/altosui/AltosDescent.java deleted file mode 100644 index 16ccd458..00000000 --- a/ao-tools/altosui/AltosDescent.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosDescent extends JComponent implements AltosFlightDisplay { - GridBagLayout layout; - - public abstract class DescentStatus { - JLabel label; - JTextField value; - AltosLights lights; - - abstract void show(AltosState state, int crc_errors); - void reset() { - value.setText(""); - lights.set(false); - } - - public DescentStatus (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - lights = new AltosLights(); - c.gridx = 0; c.gridy = y; - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(lights, c); - add(lights); - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.gridwidth = 3; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 4; c.gridy = y; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - - } - } - - public abstract class DescentValue { - JLabel label; - JTextField value; - - void reset() { - value.setText(""); - } - - abstract void show(AltosState state, int crc_errors); - - void show(String format, double v) { - value.setText(String.format(format, v)); - } - - void show(String v) { - value.setText(v); - } - - public DescentValue (GridBagLayout layout, int x, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = x + 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - add(label, c); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 2; c.gridy = y; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - add(value, c); - } - } - - public abstract class DescentDualValue { - JLabel label; - JTextField value1; - JTextField value2; - - void reset() { - value1.setText(""); - value2.setText(""); - } - - abstract void show(AltosState state, int crc_errors); - void show(String v1, String v2) { - value1.setText(v1); - value2.setText(v2); - } - void show(String f1, double v1, String f2, double v2) { - value1.setText(String.format(f1, v1)); - value2.setText(String.format(f2, v2)); - } - - public DescentDualValue (GridBagLayout layout, int x, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = x + 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value1 = new JTextField(Altos.text_width); - value1.setFont(Altos.value_font); - value1.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 2; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value1, c); - add(value1); - - value2 = new JTextField(Altos.text_width); - value2.setFont(Altos.value_font); - value2.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = x + 4; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - c.gridwidth = 1; - layout.setConstraints(value2, c); - add(value2); - } - } - - class Height extends DescentValue { - void show (AltosState state, int crc_errors) { - show("%6.0f m", state.height); - } - public Height (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Height"); - } - } - - Height height; - - class Speed extends DescentValue { - void show (AltosState state, int crc_errors) { - double speed = state.speed; - if (!state.ascent) - speed = state.baro_speed; - show("%6.0f m/s", speed); - } - public Speed (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Speed"); - } - } - - Speed speed; - - String pos(double p, String pos, String neg) { - String h = pos; - if (p < 0) { - h = neg; - p = -p; - } - int deg = (int) Math.floor(p); - double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %d° %9.6f", h, deg, min); - } - - class Lat extends DescentValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - show(pos(state.gps.lat,"N", "S")); - else - show("???"); - } - public Lat (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Latitude"); - } - } - - Lat lat; - - class Lon extends DescentValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - show(pos(state.gps.lon,"W", "E")); - else - show("???"); - } - public Lon (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Longitude"); - } - } - - Lon lon; - - class Apogee extends DescentStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.drogue_sense)); - lights.set(state.drogue_sense > 3.2); - } - public Apogee (GridBagLayout layout, int y) { - super(layout, y, "Apogee Igniter Voltage"); - } - } - - Apogee apogee; - - class Main extends DescentStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.main_sense)); - lights.set(state.main_sense > 3.2); - } - public Main (GridBagLayout layout, int y) { - super(layout, y, "Main Igniter Voltage"); - } - } - - Main main; - - class Bearing extends DescentDualValue { - void show (AltosState state, int crc_errors) { - if (state.from_pad != null) { - show( String.format("%3.0f°", state.from_pad.bearing), - state.from_pad.bearing_words( - AltosGreatCircle.BEARING_LONG)); - } else { - show("???", "???"); - } - } - public Bearing (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Bearing"); - } - } - - Bearing bearing; - - class Range extends DescentValue { - void show (AltosState state, int crc_errors) { - show("%6.0f m", state.range); - } - public Range (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Range"); - } - } - - Range range; - - class Elevation extends DescentValue { - void show (AltosState state, int crc_errors) { - show("%3.0f°", state.elevation); - } - public Elevation (GridBagLayout layout, int x, int y) { - super (layout, x, y, "Elevation"); - } - } - - Elevation elevation; - - public void reset() { - lat.reset(); - lon.reset(); - height.reset(); - speed.reset(); - bearing.reset(); - range.reset(); - elevation.reset(); - main.reset(); - apogee.reset(); - } - - public void show(AltosState state, int crc_errors) { - height.show(state, crc_errors); - speed.show(state, crc_errors); - bearing.show(state, crc_errors); - range.show(state, crc_errors); - elevation.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); - main.show(state, crc_errors); - apogee.show(state, crc_errors); - } - - public AltosDescent() { - layout = new GridBagLayout(); - - setLayout(layout); - - /* Elements in descent display */ - speed = new Speed(layout, 0, 0); - height = new Height(layout, 2, 0); - elevation = new Elevation(layout, 0, 1); - range = new Range(layout, 2, 1); - bearing = new Bearing(layout, 0, 2); - lat = new Lat(layout, 0, 3); - lon = new Lon(layout, 2, 3); - - apogee = new Apogee(layout, 4); - main = new Main(layout, 5); - } -} diff --git a/ao-tools/altosui/AltosDevice.java b/ao-tools/altosui/AltosDevice.java deleted file mode 100644 index f0fda57b..00000000 --- a/ao-tools/altosui/AltosDevice.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.util.*; -import libaltosJNI.*; - -public class AltosDevice extends altos_device { - - static public boolean initialized = false; - static public boolean loaded_library = false; - - public static boolean load_library() { - if (!initialized) { - try { - System.loadLibrary("altos"); - libaltos.altos_init(); - loaded_library = true; - } catch (UnsatisfiedLinkError e) { - loaded_library = false; - } - initialized = true; - } - return loaded_library; - } - - static int usb_vendor_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_VENDOR_ALTUSMETRUM; - return 0x000a; - } - - static int usb_product_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; - return 0x000a; - } - - static int usb_product_altusmetrum_min() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; - return 0x000a; - } - - static int usb_product_altusmetrum_max() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; - return 0x000d; - } - - static int usb_product_telemetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEMETRUM; - return 0x000b; - } - - static int usb_product_teledongle() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEDONGLE; - return 0x000c; - } - - static int usb_product_teleterra() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELETERRA; - return 0x000d; - } - - public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); - public final static int product_altusmetrum = usb_product_altusmetrum(); - public final static int product_telemetrum = usb_product_telemetrum(); - public final static int product_teledongle = usb_product_teledongle(); - public final static int product_teleterra = usb_product_teleterra(); - public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); - public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - - - public final static int product_any = 0x10000; - public final static int product_basestation = 0x10000 + 1; - - public String toString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%-20.20s %4d %s", - getName(), getSerial(), getPath()); - } - - public String toShortString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%s %d %s", - name, getSerial(), getPath()); - - } - - public boolean isAltusMetrum() { - if (getVendor() != vendor_altusmetrum) - return false; - if (getProduct() < product_altusmetrum_min) - return false; - if (getProduct() > product_altusmetrum_max) - return false; - return true; - } - - public boolean matchProduct(int want_product) { - - if (!isAltusMetrum()) - return false; - - if (want_product == product_any) - return true; - - if (want_product == product_basestation) - return matchProduct(product_teledongle) || matchProduct(product_teleterra); - - int have_product = getProduct(); - - if (have_product == product_altusmetrum) /* old devices match any request */ - return true; - - if (want_product == have_product) - return true; - - return false; - } - - static AltosDevice[] list(int product) { - if (!load_library()) - return null; - - SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - - ArrayList device_list = new ArrayList(); - if (list != null) { - SWIGTYPE_p_altos_file file; - - for (;;) { - AltosDevice device = new AltosDevice(); - if (libaltos.altos_list_next(list, device) == 0) - break; - if (device.matchProduct(product)) - device_list.add(device); - } - libaltos.altos_list_finish(list); - } - - AltosDevice[] devices = new AltosDevice[device_list.size()]; - for (int i = 0; i < device_list.size(); i++) - devices[i] = device_list.get(i); - return devices; - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosDeviceDialog.java b/ao-tools/altosui/AltosDeviceDialog.java deleted file mode 100644 index 2966ad1e..00000000 --- a/ao-tools/altosui/AltosDeviceDialog.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.util.*; -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import libaltosJNI.libaltos; -import libaltosJNI.altos_device; -import libaltosJNI.SWIGTYPE_p_altos_file; -import libaltosJNI.SWIGTYPE_p_altos_list; - -public class AltosDeviceDialog extends JDialog implements ActionListener { - - private static AltosDeviceDialog dialog; - private static AltosDevice value = null; - private JList list; - - public static AltosDevice show (Component frameComp, int product) { - - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDevice[] devices; - devices = AltosDevice.list(product); - - if (devices != null && devices.length > 0) { - value = null; - dialog = new AltosDeviceDialog(frame, frameComp, - devices, - devices[0]); - - dialog.setVisible(true); - return value; - } else { - /* check for missing altos JNI library, which - * will put up its own error dialog - */ - if (AltosUI.load_library(frame)) { - JOptionPane.showMessageDialog(frame, - "No AltOS devices available", - "No AltOS devices", - JOptionPane.ERROR_MESSAGE); - } - return null; - } - } - - private AltosDeviceDialog (Frame frame, Component location, - AltosDevice[] devices, - AltosDevice initial) { - super(frame, "Device Selection", true); - - value = null; - - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(this); - - final JButton selectButton = new JButton("Select"); - selectButton.setActionCommand("select"); - selectButton.addActionListener(this); - getRootPane().setDefaultButton(selectButton); - - list = new JList(devices) { - //Subclass JList to workaround bug 4832765, which can cause the - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - }; - - list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - list.setLayoutOrientation(JList.HORIZONTAL_WRAP); - list.setVisibleRowCount(-1); - list.addMouseListener(new MouseAdapter() { - public void mouseClicked(MouseEvent e) { - if (e.getClickCount() == 2) { - selectButton.doClick(); //emulate button click - } - } - }); - JScrollPane listScroller = new JScrollPane(list); - listScroller.setPreferredSize(new Dimension(400, 80)); - listScroller.setAlignmentX(LEFT_ALIGNMENT); - - //Create a container so that we can add a title around - //the scroll pane. Can't add a title directly to the - //scroll pane because its background would be white. - //Lay out the label and scroll pane from top to bottom. - JPanel listPane = new JPanel(); - listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); - - JLabel label = new JLabel("Select Device"); - label.setLabelFor(list); - listPane.add(label); - listPane.add(Box.createRigidArea(new Dimension(0,5))); - listPane.add(listScroller); - listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - - //Lay out the buttons from left to right. - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); - buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); - buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancelButton); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(selectButton); - - //Put everything together, using the content pane's BorderLayout. - Container contentPane = getContentPane(); - contentPane.add(listPane, BorderLayout.CENTER); - contentPane.add(buttonPane, BorderLayout.PAGE_END); - - //Initialize values. - list.setSelectedValue(initial, true); - pack(); - setLocationRelativeTo(location); - } - - //Handle clicks on the Set and Cancel buttons. - public void actionPerformed(ActionEvent e) { - if ("select".equals(e.getActionCommand())) - AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue()); - AltosDeviceDialog.dialog.setVisible(false); - } - -} diff --git a/ao-tools/altosui/AltosDisplayThread.java b/ao-tools/altosui/AltosDisplayThread.java deleted file mode 100644 index 3e719130..00000000 --- a/ao-tools/altosui/AltosDisplayThread.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosDisplayThread extends Thread { - - Frame parent; - IdleThread idle_thread; - AltosVoice voice; - String name; - AltosFlightReader reader; - int crc_errors; - AltosFlightDisplay display; - - synchronized void show(AltosState state, int crc_errors) { - if (state != null) - display.show(state, crc_errors); - } - - class IdleThread extends Thread { - - boolean started; - private AltosState state; - int reported_landing; - int report_interval; - long report_time; - - public synchronized void report(boolean last) { - if (state == null) - return; - - /* reset the landing count once we hear about a new flight */ - if (state.state < Altos.ao_flight_drogue) - reported_landing = 0; - - /* Shut up once the rocket is on the ground */ - if (reported_landing > 2) { - return; - } - - /* If the rocket isn't on the pad, then report height */ - if (Altos.ao_flight_drogue <= state.state && - state.state < Altos.ao_flight_landed && - state.range >= 0) - { - voice.speak("Height %d, bearing %s %d, elevation %d, range %d.\n", - (int) (state.height + 0.5), - state.from_pad.bearing_words( - AltosGreatCircle.BEARING_VOICE), - (int) (state.from_pad.bearing + 0.5), - (int) (state.elevation + 0.5), - (int) (state.range + 0.5)); - } else if (state.state > Altos.ao_flight_pad) { - voice.speak("%d meters", (int) (state.height + 0.5)); - } else { - reported_landing = 0; - } - - /* If the rocket is coming down, check to see if it has landed; - * either we've got a landed report or we haven't heard from it in - * a long time - */ - if (state.state >= Altos.ao_flight_drogue && - (last || - System.currentTimeMillis() - state.report_time >= 15000 || - state.state == Altos.ao_flight_landed)) - { - if (Math.abs(state.baro_speed) < 20 && state.height < 100) - voice.speak("rocket landed safely"); - else - voice.speak("rocket may have crashed"); - if (state.from_pad != null) - voice.speak("Bearing %d degrees, range %d meters.", - (int) (state.from_pad.bearing + 0.5), - (int) (state.from_pad.distance + 0.5)); - ++reported_landing; - if (state.state != Altos.ao_flight_landed) { - state.state = Altos.ao_flight_landed; - show(state, 0); - } - } - } - - long now () { - return System.currentTimeMillis(); - } - - void set_report_time() { - report_time = now() + report_interval; - } - - public void run () { - try { - for (;;) { - 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 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(); - } - - public IdleThread() { - state = null; - reported_landing = 0; - report_interval = 10000; - } - } - - 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) { - voice.speak("GPS ready"); - ret = true; - } - else if (old_state != null) { - voice.speak("GPS lost"); - ret = true; - } - } - old_state = state; - return ret; - } - - public void run() { - boolean interrupted = false; - String line; - AltosState state = null; - AltosState old_state = null; - boolean told; - - idle_thread = new IdleThread(); - - display.reset(); - try { - for (;;) { - try { - AltosRecord record = reader.read(); - if (record == null) - break; - old_state = state; - state = new AltosState(record, state); - reader.update(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(parent, - String.format("Error reading from \"%s\"", name), - "Telemetry Read Error", - JOptionPane.ERROR_MESSAGE); - } finally { - if (!interrupted) - idle_thread.report(true); - reader.close(interrupted); - idle_thread.interrupt(); - try { - idle_thread.join(); - } catch (InterruptedException ie) {} - } - } - - public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosFlightDisplay in_display, AltosFlightReader in_reader) { - parent = in_parent; - voice = in_voice; - display = in_display; - reader = in_reader; - } -} diff --git a/ao-tools/altosui/AltosEepromDownload.java b/ao-tools/altosui/AltosEepromDownload.java deleted file mode 100644 index 02fc36f2..00000000 --- a/ao-tools/altosui/AltosEepromDownload.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -import libaltosJNI.*; - -public class AltosEepromDownload implements Runnable { - - static final String[] state_names = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - int checksum(int[] line) { - int csum = 0x5a; - for (int i = 1; i < line.length; i++) - csum += line[i]; - return csum & 0xff; - } - - void FlushPending(FileWriter file, LinkedList pending) throws IOException { - while (!pending.isEmpty()) { - file.write(pending.remove()); - } - } - - JFrame frame; - AltosDevice device; - AltosSerial serial_line; - boolean remote; - Thread eeprom_thread; - AltosEepromMonitor monitor; - - void CaptureLog() throws IOException, InterruptedException, TimeoutException { - int serial = 0; - int block, state_block = 0; - int addr; - int flight = 0; - int year = 0, month = 0, day = 0; - int state = 0; - boolean done = false; - boolean want_file = false; - boolean any_valid; - FileWriter eeprom_file = null; - AltosFile eeprom_name; - LinkedList eeprom_pending = new LinkedList(); - - serial_line.printf("\nc s\nv\n"); - - /* Pull the serial number out of the version information */ - - for (;;) { - String line = serial_line.get_reply(5000); - - if (line == null) - throw new TimeoutException(); - if (line.startsWith("serial-number")) { - try { - serial = Integer.parseInt(line.substring(13).trim()); - } catch (NumberFormatException ne) { - serial = 0; - } - } - - eeprom_pending.add(String.format("%s\n", line)); - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } - if (serial == 0) - throw new IOException("no serial number found"); - - monitor.set_serial(serial); - /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - - state = 0; state_block = 0; - for (block = 0; !done && block < 511; block++) { - serial_line.printf("e %x\n", block); - any_valid = false; - monitor.set_value(state_names[state], state, block - state_block); - for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - int[] values = ParseHex(line); - - 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]); - } else if (checksum(values) != 0) { - System.out.printf("invalid checksum at 0x%x\n", - block * 256 + values[0]); - } else { - any_valid = true; - int cmd = values[1]; - int tick = values[3] + (values[4] << 8); - int a = values[5] + (values[6] << 8); - int b = values[7] + (values[8] << 8); - - if (cmd == Altos.AO_LOG_FLIGHT) { - flight = b; - monitor.set_flight(flight); - } - - /* Monitor state transitions to update display */ - if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { - if (a > Altos.ao_flight_pad) - want_file = true; - if (a > state) - state_block = block; - state = a; - } - - if (cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (a & 0xff); - month = (a >> 8) & 0xff; - day = (b & 0xff); - want_file = true; - } - - if (eeprom_file == null) { - if (serial != 0 && flight != 0 && want_file) { - if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); - else - eeprom_name = new AltosFile(serial, flight, "eeprom"); - - monitor.set_file(eeprom_name.getName()); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - eeprom_pending = null; - } - } - } - - String log_line = String.format("%c %4x %4x %4x\n", - cmd, tick, a, b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - - if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { - done = true; - } - } - addr += 8; - } - if (!any_valid) - done = true; - } - if (eeprom_file == null) { - eeprom_name = new AltosFile(serial,flight,"eeprom"); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - } - } - if (eeprom_file != null) { - eeprom_file.flush(); - eeprom_file.close(); - } - } - - public void run () { - if (remote) { - serial_line.set_radio(); - serial_line.printf("p\nE 0\n"); - serial_line.flush_input(); - } - - monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); - monitor.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - eeprom_thread.interrupt(); - } - }); - try { - CaptureLog(); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException ie) { - } catch (TimeoutException te) { - JOptionPane.showMessageDialog(frame, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); - } - if (remote) - serial_line.printf("~"); - monitor.done(); - serial_line.flush_output(); - serial_line.close(); - } - - public AltosEepromDownload(JFrame given_frame) { - frame = given_frame; - device = AltosDeviceDialog.show(frame, AltosDevice.product_any); - - remote = false; - - if (device != null) { - try { - serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) - remote = true; - eeprom_thread = new Thread(this); - eeprom_thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } - } -} diff --git a/ao-tools/altosui/AltosEepromIterable.java b/ao-tools/altosui/AltosEepromIterable.java deleted file mode 100644 index f8e6d7e5..00000000 --- a/ao-tools/altosui/AltosEepromIterable.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -/* - * AltosRecords with an index field so they can be sorted by tick while preserving - * the original ordering for elements with matching ticks - */ -class AltosOrderedRecord extends AltosEepromRecord implements Comparable { - - public int index; - - public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) - throws ParseException { - super(line); - if (prev_tick_valid) { - tick |= (prev_tick & ~0xffff); - if (tick < prev_tick) { - if (prev_tick - tick > 0x8000) - tick += 0x10000; - } else { - if (tick - prev_tick > 0x8000) - tick -= 0x10000; - } - } - 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) - return tick_diff; - return index - o.index; - } -} - -public class AltosEepromIterable extends AltosRecordIterable { - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - - static final int seen_basic = seen_flight|seen_sensor|seen_temp_volt|seen_deploy; - - AltosEepromRecord flight_record; - AltosEepromRecord gps_date_record; - - TreeSet records; - - LinkedList list; - - class EepromState { - int seen; - int n_pad_samples; - double ground_pres; - int gps_tick; - int boost_tick; - - EepromState() { - seen = 0; - n_pad_samples = 0; - ground_pres = 0.0; - gps_tick = 0; - } - } - - void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { - state.tick = record.tick; - switch (record.cmd) { - case Altos.AO_LOG_FLIGHT: - eeprom.seen |= seen_flight; - state.ground_accel = record.a; - state.flight_accel = record.a; - state.flight = record.b; - eeprom.boost_tick = record.tick; - break; - case Altos.AO_LOG_SENSOR: - state.accel = record.a; - state.pres = record.b; - if (state.state < Altos.ao_flight_boost) { - eeprom.n_pad_samples++; - eeprom.ground_pres += state.pres; - state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); - state.flight_pres = state.ground_pres; - } else { - state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - state.flight_vel += (state.accel_plus_g - state.accel); - } - eeprom.seen |= seen_sensor; - break; - case Altos.AO_LOG_TEMP_VOLT: - state.temp = record.a; - state.batt = record.b; - eeprom.seen |= seen_temp_volt; - break; - case Altos.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - eeprom.seen |= seen_deploy; - break; - case Altos.AO_LOG_STATE: - state.state = record.a; - break; - case Altos.AO_LOG_GPS_TIME: - eeprom.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); - - int flags = (record.b >> 8); - state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; - state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; - state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; - state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> - Altos.AO_GPS_NUM_SAT_SHIFT; - break; - case Altos.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case Altos.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case Altos.AO_LOG_GPS_ALT: - state.gps.alt = record.a; - break; - case Altos.AO_LOG_GPS_SAT: - if (state.tick == eeprom.gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); - } - break; - case Altos.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - - case Altos.AO_LOG_CONFIG_VERSION: - break; - case Altos.AO_LOG_MAIN_DEPLOY: - break; - case Altos.AO_LOG_APOGEE_DELAY: - break; - case Altos.AO_LOG_RADIO_CHANNEL: - break; - case Altos.AO_LOG_CALLSIGN: - state.callsign = record.data; - break; - case Altos.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; - break; - case Altos.AO_LOG_RADIO_CAL: - break; - case Altos.AO_LOG_MANUFACTURER: - 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; - } - } - - LinkedList make_list() { - LinkedList list = new LinkedList(); - Iterator iterator = records.iterator(); - AltosOrderedRecord record = null; - AltosRecord state = new AltosRecord(); - boolean last_reported = false; - EepromState eeprom = new EepromState(); - - state.state = Altos.ao_flight_pad; - state.accel_plus_g = 15758; - state.accel_minus_g = 16294; - - /* Pull in static data from the flight and gps_date records */ - if (flight_record != null) - update_state(state, flight_record, eeprom); - if (gps_date_record != null) - update_state(state, gps_date_record, eeprom); - - while (iterator.hasNext()) { - record = iterator.next(); - if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - } - update_state(state, record, eeprom); - } - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - return list; - } - - public Iterator iterator() { - if (list == null) - list = make_list(); - return list.iterator(); - } - - public void write_comments(PrintStream out) { - Iterator iterator = records.iterator(); - out.printf("# Comments\n"); - while (iterator.hasNext()) { - AltosOrderedRecord record = iterator.next(); - switch (record.cmd) { - case Altos.AO_LOG_CONFIG_VERSION: - out.printf("# Config version: %s\n", record.data); - break; - case Altos.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); - break; - case Altos.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); - break; - case Altos.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); - break; - case Altos.AO_LOG_CALLSIGN: - out.printf("# Callsign: %s\n", record.data); - break; - case Altos.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); - break; - case Altos.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); - break; - case Altos.AO_LOG_MANUFACTURER: - out.printf ("# Manufacturer: %s\n", record.data); - break; - case Altos.AO_LOG_PRODUCT: - out.printf ("# Product: %s\n", record.data); - break; - case Altos.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); - break; - case Altos.AO_LOG_SOFTWARE_VERSION: - out.printf ("# Software version: %s\n", record.data); - break; - } - } - } - - /* - * 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; - - /* Make sure this looks like a good GPS value */ - if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) - flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); - flags |= Altos.AO_GPS_RUNNING; - flags |= Altos.AO_GPS_VALID; - - 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 - * are sometimes out of order with GPS data getting timestamps - * matching the first packet out of the GPS unit but not - * written until the final GPS packet has been received. - */ - public AltosEepromIterable (FileInputStream input) { - records = new TreeSet(); - - AltosOrderedRecord last_gps_time = null; - - int index = 0; - int prev_tick = 0; - boolean prev_tick_valid = false; - boolean missing_time = false; - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) - break; - AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); - if (record == null) - break; - if (record.cmd == Altos.AO_LOG_INVALID) - continue; - prev_tick = record.tick; - if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) - prev_tick_valid = true; - if (record.cmd == Altos.AO_LOG_FLIGHT) { - flight_record = record; - continue; - } - - /* 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) { - gps_date_record = record; - continue; - } - - /* 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 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); - - /* Bail after reading the 'landed' record; we're all done */ - if (record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_landed) - break; - } - } catch (IOException io) { - } catch (ParseException pe) { - } - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/ao-tools/altosui/AltosEepromMonitor.java b/ao-tools/altosui/AltosEepromMonitor.java deleted file mode 100644 index 7ff00ead..00000000 --- a/ao-tools/altosui/AltosEepromMonitor.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosEepromMonitor extends JDialog { - - Container pane; - Box box; - JLabel serial_label; - JLabel flight_label; - JLabel file_label; - JLabel serial_value; - JLabel flight_value; - JLabel file_value; - JButton cancel; - JProgressBar pbar; - int min_state, max_state; - - public AltosEepromMonitor(JFrame owner, int in_min_state, int in_max_state) { - super (owner, "Download Flight Data", false); - - 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; - flight_label = new JLabel("Flight:"); - pane.add(flight_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; - flight_value = new JLabel(""); - pane.add(flight_value, c); - - c = new GridBagConstraints(); - c.fill = GridBagConstraints.NONE; - c.gridx = 0; c.gridy = 2; - 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 = 2; - c.anchor = GridBagConstraints.LINE_START; - c.insets = ir; - file_value = new JLabel(""); - pane.add(file_value, c); - - min_state = in_min_state; - max_state = in_max_state; - pbar = new JProgressBar(); - pbar.setMinimum(0); - pbar.setMaximum((max_state - min_state) * 100); - pbar.setValue(0); - pbar.setString("startup"); - 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 = 3; - 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 = 4; - c.gridwidth = GridBagConstraints.REMAINDER; - Insets ic = new Insets(4,4,4,4); - c.insets = ic; - pane.add(cancel, c); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - } - - public void addActionListener (ActionListener l) { - cancel.addActionListener(l); - } - - public void set_value(String state_name, int in_state, int in_block) { - int block = in_block; - int state = in_state; - - if (block > 100) - block = 100; - if (state < min_state) state = min_state; - if (state >= max_state) state = max_state - 1; - state -= min_state; - - int pos = state * 100 + block; - - pbar.setString(state_name); - pbar.setValue(pos); - } - - public void set_serial(int serial) { - serial_value.setText(String.format("%d", serial)); - } - - public void set_flight(int flight) { - flight_value.setText(String.format("%d", flight)); - } - - public void set_file(String file) { - file_value.setText(String.format("%s", file)); - } - - public void done() { - setVisible(false); - dispose(); - } -} diff --git a/ao-tools/altosui/AltosEepromRecord.java b/ao-tools/altosui/AltosEepromRecord.java deleted file mode 100644 index 5a673817..00000000 --- a/ao-tools/altosui/AltosEepromRecord.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosEepromRecord { - public int cmd; - public int tick; - public int a; - public int b; - public String data; - public boolean tick_valid; - - public AltosEepromRecord (String line) { - tick_valid = false; - tick = 0; - a = 0; - b = 0; - data = null; - if (line == null) { - cmd = Altos.AO_LOG_INVALID; - data = ""; - } else { - try { - String[] tokens = line.split("\\s+"); - - 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; - } -} diff --git a/ao-tools/altosui/AltosFile.java b/ao-tools/altosui/AltosFile.java deleted file mode 100644 index 06360572..00000000 --- a/ao-tools/altosui/AltosFile.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.File; -import java.util.*; - -class AltosFile extends File { - - public AltosFile(int year, int month, int day, int serial, int flight, String extension) { - super (AltosPreferences.logdir(), - String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - year, month, day, serial, flight, extension)); - } - - public AltosFile(int serial, int flight, String extension) { - this(Calendar.getInstance().get(Calendar.YEAR), - Calendar.getInstance().get(Calendar.MONTH) + 1, - Calendar.getInstance().get(Calendar.DAY_OF_MONTH), - serial, - flight, - extension); - } - - public AltosFile(AltosTelemetry telem) { - this(telem.serial, telem.flight, "telem"); - } -} diff --git a/ao-tools/altosui/AltosFlash.java b/ao-tools/altosui/AltosFlash.java deleted file mode 100644 index 3af25c23..00000000 --- a/ao-tools/altosui/AltosFlash.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -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 AltosFlash(File in_file, AltosDevice in_debug_dongle) - throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException { - file = in_file; - debug_dongle = in_debug_dongle; - debug = new AltosDebug(in_debug_dongle); - input = new FileInputStream(file); - image = new AltosHexfile(input); - if (!debug.check_connection()) { - debug.close(); - throw new IOException("Debug port not connected"); - } - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosFlashUI.java b/ao-tools/altosui/AltosFlashUI.java deleted file mode 100644 index f63097ac..00000000 --- a/ao-tools/altosui/AltosFlashUI.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -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() { - try { - flash = new AltosFlash(file, debug_dongle); - flash.addActionListener(this); - 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 (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - debug_dongle.toShortString()), - "Device in use", - 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.product_any); - - if (debug_dongle == null) - return; - - JFileChooser hexfile_chooser = new JFileChooser(); - - File firmwaredir = AltosPreferences.firmwaredir(); - if (firmwaredir != null) - hexfile_chooser.setCurrentDirectory(firmwaredir); - - 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(); - - if (file != null) - AltosPreferences.set_firmwaredir(file.getParentFile()); - - thread = new Thread(this); - thread.start(); - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosFlightDisplay.java b/ao-tools/altosui/AltosFlightDisplay.java deleted file mode 100644 index d18d1d1f..00000000 --- a/ao-tools/altosui/AltosFlightDisplay.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 interface AltosFlightDisplay { - void reset(); - - void show(AltosState state, int crc_errors); -} diff --git a/ao-tools/altosui/AltosFlightInfoTableModel.java b/ao-tools/altosui/AltosFlightInfoTableModel.java deleted file mode 100644 index e23eff68..00000000 --- a/ao-tools/altosui/AltosFlightInfoTableModel.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosFlightInfoTableModel extends AbstractTableModel { - final static private String[] columnNames = {"Field", "Value"}; - - int rows; - int cols; - private String[][] data; - - public int getColumnCount() { return cols; } - public int getRowCount() { return rows; } - public String getColumnName(int col) { return columnNames[col & 1]; } - - public Object getValueAt(int row, int col) { - if (row >= rows || col >= cols) - return ""; - return data[row][col]; - } - - int[] current_row; - - public void reset() { - for (int i = 0; i < cols / 2; i++) - current_row[i] = 0; - } - - public void clear() { - reset(); - for (int c = 0; c < cols; c++) - for (int r = 0; r < rows; r++) - data[r][c] = ""; - fireTableDataChanged(); - } - - public void addRow(int col, String name, String value) { - if (current_row[col] < rows) { - data[current_row[col]][col * 2] = name; - data[current_row[col]][col * 2 + 1] = value; - } - current_row[col]++; - } - - public void finish() { - for (int c = 0; c < cols / 2; c++) - while (current_row[c] < rows) - addRow(c, "", ""); - fireTableDataChanged(); - } - - public AltosFlightInfoTableModel (int in_rows, int in_cols) { - rows = in_rows; - cols = in_cols * 2; - data = new String[rows][cols]; - current_row = new int[in_cols]; - } -} diff --git a/ao-tools/altosui/AltosFlightReader.java b/ao-tools/altosui/AltosFlightReader.java deleted file mode 100644 index 3d59de9a..00000000 --- a/ao-tools/altosui/AltosFlightReader.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.io.*; - -public class AltosFlightReader { - String name; - - int serial; - - void init() { } - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } - - void close(boolean interrupted) { } - - void set_channel(int channel) { } - - void update(AltosState state) throws InterruptedException { } -} diff --git a/ao-tools/altosui/AltosFlightStatus.java b/ao-tools/altosui/AltosFlightStatus.java deleted file mode 100644 index 59c9e9db..00000000 --- a/ao-tools/altosui/AltosFlightStatus.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { - GridBagLayout layout; - - public class FlightValue { - JLabel label; - JTextField value; - - void show(AltosState state, int crc_errors) {} - - void reset() { - value.setText(""); - } - public FlightValue (GridBagLayout layout, int x, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(5, 5, 5, 5); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.status_font); - label.setHorizontalAlignment(SwingConstants.CENTER); - c.gridx = x; c.gridy = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(""); - value.setFont(Altos.status_font); - value.setHorizontalAlignment(SwingConstants.CENTER); - c.gridx = x; c.gridy = 1; - layout.setConstraints(value, c); - add(value); - } - } - - class Call extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(state.data.callsign); - } - public Call (GridBagLayout layout, int x) { - super (layout, x, "Callsign"); - } - } - - Call call; - - class Serial extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(String.format("%d", state.data.serial)); - } - public Serial (GridBagLayout layout, int x) { - super (layout, x, "Serial"); - } - } - - Serial serial; - - class Flight extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(String.format("%d", state.data.flight)); - } - public Flight (GridBagLayout layout, int x) { - super (layout, x, "Flight"); - } - } - - Flight flight; - - class FlightState extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(state.data.state()); - } - public FlightState (GridBagLayout layout, int x) { - super (layout, x, "State"); - } - } - - FlightState flight_state; - - class RSSI extends FlightValue { - void show(AltosState state, int crc_errors) { - value.setText(String.format("%d", state.data.rssi)); - } - public RSSI (GridBagLayout layout, int x) { - super (layout, x, "RSSI (dBm)"); - } - } - - RSSI rssi; - - public void reset () { - call.reset(); - serial.reset(); - flight.reset(); - flight_state.reset(); - rssi.reset(); - } - - public void show (AltosState state, int crc_errors) { - call.show(state, crc_errors); - serial.show(state, crc_errors); - flight.show(state, crc_errors); - flight_state.show(state, crc_errors); - rssi.show(state, crc_errors); - } - - public int height() { - Dimension d = layout.preferredLayoutSize(this); - return d.height; - } - - public AltosFlightStatus() { - layout = new GridBagLayout(); - - setLayout(layout); - - call = new Call(layout, 0); - serial = new Serial(layout, 1); - flight = new Flight(layout, 2); - flight_state = new FlightState(layout, 3); - rssi = new RSSI(layout, 4); - } -} diff --git a/ao-tools/altosui/AltosFlightStatusTableModel.java b/ao-tools/altosui/AltosFlightStatusTableModel.java deleted file mode 100644 index 4c24b6ac..00000000 --- a/ao-tools/altosui/AltosFlightStatusTableModel.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosFlightStatusTableModel extends AbstractTableModel { - private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; - private Object[] data = { 0, "idle", 0, 0 }; - - public int getColumnCount() { return columnNames.length; } - public int getRowCount() { return 2; } - public Object getValueAt(int row, int col) { - if (row == 0) - return columnNames[col]; - return data[col]; - } - - public void setValueAt(Object value, int col) { - data[col] = value; - fireTableCellUpdated(1, col); - } - - public void setValueAt(Object value, int row, int col) { - setValueAt(value, col); - } - - public void set(AltosState state) { - setValueAt(String.format("%1.0f", state.height), 0); - setValueAt(state.data.state(), 1); - setValueAt(state.data.rssi, 2); - double speed = state.baro_speed; - if (state.ascent) - speed = state.speed; - setValueAt(String.format("%1.0f", speed), 3); - } -} diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java deleted file mode 100644 index 24d25bd7..00000000 --- a/ao-tools/altosui/AltosFlightUI.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosFlightUI extends JFrame implements AltosFlightDisplay { - String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; - Object[][] statusData = { { "0", "pad", "-50", "0" } }; - - AltosVoice voice; - AltosFlightReader reader; - AltosDisplayThread thread; - - JTabbedPane pane; - - AltosPad pad; - AltosAscent ascent; - AltosDescent descent; - AltosLanded landed; - AltosSiteMap sitemap; - - private AltosFlightStatus flightStatus; - private AltosInfoTable flightInfo; - - static final int tab_pad = 1; - static final int tab_ascent = 2; - static final int tab_descent = 3; - static final int tab_landed = 4; - - int cur_tab = 0; - - boolean exit_on_close = false; - - int which_tab(AltosState state) { - if (state.state < Altos.ao_flight_boost) - return tab_pad; - if (state.state <= Altos.ao_flight_coast) - return tab_ascent; - if (state.state <= Altos.ao_flight_main) - return tab_descent; - return tab_landed; - } - - void stop_display() { - if (thread != null && thread.isAlive()) { - thread.interrupt(); - try { - thread.join(); - } catch (InterruptedException ie) {} - } - thread = null; - } - - void disconnect() { - stop_display(); - } - - public void reset() { - pad.reset(); - ascent.reset(); - descent.reset(); - landed.reset(); - flightInfo.clear(); - sitemap.reset(); - } - - public void show(AltosState state, int crc_errors) { - int tab = which_tab(state); - pad.show(state, crc_errors); - ascent.show(state, crc_errors); - descent.show(state, crc_errors); - landed.show(state, crc_errors); - if (tab != cur_tab) { - switch (tab) { - case tab_pad: - pane.setSelectedComponent(pad); - break; - case tab_ascent: - pane.setSelectedComponent(ascent); - break; - case tab_descent: - pane.setSelectedComponent(descent); - break; - case tab_landed: - pane.setSelectedComponent(landed); - } - cur_tab = tab; - } - flightStatus.show(state, crc_errors); - flightInfo.show(state, crc_errors); - sitemap.show(state, crc_errors); - } - - public void set_exit_on_close() { - exit_on_close = true; - } - - Container bag; - JComboBox channels; - - public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { - AltosPreferences.init(this); - - voice = in_voice; - reader = in_reader; - - bag = getContentPane(); - bag.setLayout(new GridBagLayout()); - - GridBagConstraints c = new GridBagConstraints(); - - java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); - if (imgURL != null) - setIconImage(new ImageIcon(imgURL).getImage()); - - setTitle(String.format("AltOS %s", reader.name)); - - /* Stick channel selector at top of table for telemetry monitoring */ - if (serial >= 0) { - // Channel menu - channels = new AltosChannelMenu(AltosPreferences.channel(serial)); - channels.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int channel = channels.getSelectedIndex(); - reader.set_channel(channel); - } - }); - c.gridx = 0; - c.gridy = 0; - c.anchor = GridBagConstraints.WEST; - bag.add (channels, c); - } - - /* Flight status is always visible */ - flightStatus = new AltosFlightStatus(); - c.gridx = 0; - c.gridy = 1; - c.fill = GridBagConstraints.HORIZONTAL; - c.weightx = 1; - bag.add(flightStatus, c); - - /* The rest of the window uses a tabbed pane to - * show one of the alternate data views - */ - pane = new JTabbedPane(); - - pad = new AltosPad(); - pane.add("Launch Pad", pad); - - ascent = new AltosAscent(); - pane.add("Ascent", ascent); - - descent = new AltosDescent(); - pane.add("Descent", descent); - - landed = new AltosLanded(); - pane.add("Landed", landed); - - flightInfo = new AltosInfoTable(); - pane.add("Table", new JScrollPane(flightInfo)); - - sitemap = new AltosSiteMap(); - pane.add("Site Map", sitemap); - - /* Make the tabbed pane use the rest of the window space */ - c.gridx = 0; - c.gridy = 2; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - c.weighty = 1; - bag.add(pane, c); - - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - disconnect(); - setVisible(false); - dispose(); - if (exit_on_close) - System.exit(0); - } - }); - - pack(); - setVisible(true); - - thread = new AltosDisplayThread(this, voice, this, reader); - - thread.start(); - } - - public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) { - this(in_voice, in_reader, -1); - } -} diff --git a/ao-tools/altosui/AltosGPS.java b/ao-tools/altosui/AltosGPS.java deleted file mode 100644 index 83821842..00000000 --- a/ao-tools/altosui/AltosGPS.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; - -public class AltosGPS { - public class AltosGPSSat { - int svid; - int c_n0; - } - - int nsat; - boolean locked; - boolean connected; - boolean date_valid; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - int year; - int month; - int day; - int hour; - int minute; - int second; - - int gps_extended; /* has extra data */ - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless? */ - int h_error; /* m */ - int v_error; /* m */ - - AltosGPSSat[] cc_gps_sat; /* tracking data */ - - 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 = AltosParse.parse_int(hms[0]); - minute = AltosParse.parse_int(hms[1]); - second = AltosParse.parse_int(hms[2]); - } - - void ClearGPSTime() { - year = month = day = 0; - hour = minute = second = 0; - } - - 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"); - - connected = false; - locked = false; - lat = lon = 0; - alt = 0; - ClearGPSTime(); - if ((words[i]).equals("unlocked")) { - connected = true; - i++; - } else if ((words[i]).equals("not-connected")) { - i++; - } else if (words.length >= 40) { - locked = true; - connected = true; - - 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(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++; - } - 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) { - lat = in_lat / 10.0e7; - } - - public void set_longitude(int in_lon) { - lon = in_lon / 10.0e7; - } - - public void set_time(int hour, int minute, int second) { - hour = hour; - minute = minute; - second = second; - } - - public void set_date(int year, int month, int day) { - year = year; - month = month; - day = day; - } - - public void set_flags(int flags) { - flags = flags; - } - - public void set_altitude(int altitude) { - altitude = altitude; - } - - public void add_sat(int svid, int c_n0) { - if (cc_gps_sat == null) { - cc_gps_sat = new AltosGPS.AltosGPSSat[1]; - } else { - AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1]; - for (int i = 0; i < cc_gps_sat.length; i++) - new_gps_sat[i] = cc_gps_sat[i]; - cc_gps_sat = new_gps_sat; - } - AltosGPS.AltosGPSSat sat = new AltosGPS.AltosGPSSat(); - sat.svid = svid; - sat.c_n0 = c_n0; - cc_gps_sat[cc_gps_sat.length - 1] = sat; - } - - public AltosGPS() { - ClearGPSTime(); - cc_gps_sat = null; - } - - public AltosGPS(AltosGPS old) { - 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 */ - year = old.year; - month = old.month; - day = old.day; - hour = old.hour; - minute = old.minute; - second = old.second; - - gps_extended = old.gps_extended; /* has extra data */ - ground_speed = old.ground_speed; /* m/s */ - course = old.course; /* degrees */ - climb_rate = old.climb_rate; /* m/s */ - hdop = old.hdop; /* unitless? */ - h_error = old.h_error; /* m */ - v_error = old.v_error; /* m */ - - if (old.cc_gps_sat != null) { - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i] = new AltosGPSSat(); - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; - } - } - } -} diff --git a/ao-tools/altosui/AltosGraph.java b/ao-tools/altosui/AltosGraph.java deleted file mode 100644 index 58c27979..00000000 --- a/ao-tools/altosui/AltosGraph.java +++ /dev/null @@ -1,25 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -import java.io.*; - -import org.jfree.chart.JFreeChart; -import org.jfree.chart.ChartUtilities; - -abstract class AltosGraph { - public String filename; - public abstract void addData(AltosDataPoint d); - public abstract JFreeChart createChart(); - public void toPNG() throws java.io.IOException { toPNG(300, 500); } - public void toPNG(int width, int height) - throws java.io.IOException - { - File pngout = new File(filename); - JFreeChart chart = createChart(); - ChartUtilities.saveChartAsPNG(pngout, chart, width, height); - System.out.println("Created " + filename); - } -} diff --git a/ao-tools/altosui/AltosGraphTime.java b/ao-tools/altosui/AltosGraphTime.java deleted file mode 100644 index a5451280..00000000 --- a/ao-tools/altosui/AltosGraphTime.java +++ /dev/null @@ -1,233 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -import java.awt.Color; -import java.util.ArrayList; -import java.util.HashMap; - -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.AxisLocation; -import org.jfree.chart.axis.NumberAxis; -import org.jfree.chart.labels.StandardXYToolTipGenerator; -import org.jfree.chart.plot.PlotOrientation; -import org.jfree.chart.plot.XYPlot; -import org.jfree.chart.plot.ValueMarker; -import org.jfree.chart.renderer.xy.StandardXYItemRenderer; -import org.jfree.chart.renderer.xy.XYItemRenderer; -import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer; -import org.jfree.data.xy.XYSeries; -import org.jfree.data.xy.XYSeriesCollection; -import org.jfree.ui.RectangleAnchor; -import org.jfree.ui.TextAnchor; - -class AltosGraphTime extends AltosGraph { - static interface Element { - void attachGraph(AltosGraphTime g); - void gotTimeData(double time, AltosDataPoint d); - void addToPlot(AltosGraphTime g, XYPlot plot); - } - - static class TimeAxis implements Element { - private int axis; - private Color color; - private String label; - private AxisLocation locn; - private double min_y = Double.NaN; - - public TimeAxis(int axis, String label, Color color, AxisLocation locn) - { - this.axis = axis; - this.color = color; - this.label = label; - this.locn = locn; - } - - public void setLowerBound(double min_y) { - this.min_y = min_y; - } - - public void attachGraph(AltosGraphTime g) { return; } - public void gotTimeData(double time, AltosDataPoint d) { return; } - - public void addToPlot(AltosGraphTime g, XYPlot plot) { - NumberAxis numAxis = new NumberAxis(label); - if (!Double.isNaN(min_y)) - numAxis.setLowerBound(min_y); - plot.setRangeAxis(axis, numAxis); - plot.setRangeAxisLocation(axis, locn); - numAxis.setLabelPaint(color); - numAxis.setTickLabelPaint(color); - numAxis.setAutoRangeIncludesZero(false); - } - } - - abstract static class TimeSeries implements Element { - protected XYSeries series; - private String axisName; - private Color color; - - public TimeSeries(String axisName, String label, Color color) { - this.series = new XYSeries(label); - this.axisName = axisName; - this.color = color; - } - - public void attachGraph(AltosGraphTime g) { - g.setAxis(this, axisName, color); - } - abstract public void gotTimeData(double time, AltosDataPoint d); - - public void addToPlot(AltosGraphTime g, XYPlot plot) { - XYSeriesCollection dataset = new XYSeriesCollection(); - dataset.addSeries(this.series); - - XYItemRenderer renderer = new StandardXYItemRenderer(); - renderer.setSeriesPaint(0, color); - - int dataNum = g.getDataNum(this); - int axisNum = g.getAxisNum(this); - - plot.setDataset(dataNum, dataset); - plot.mapDatasetToRangeAxis(dataNum, axisNum); - plot.setRenderer(dataNum, renderer); - } - } - - static class StateMarker implements Element { - private double val = Double.NaN; - private String name; - private int state; - - StateMarker(int state, String name) { - this.state = state; - this.name = name; - } - - public void attachGraph(AltosGraphTime g) { return; } - public void gotTimeData(double time, AltosDataPoint d) { - if (Double.isNaN(val) || time < val) { - if (d.state() == state) { - val = time; - } - } - } - - public void addToPlot(AltosGraphTime g, XYPlot plot) { - if (Double.isNaN(val)) - return; - - ValueMarker m = new ValueMarker(val); - m.setLabel(name); - m.setLabelAnchor(RectangleAnchor.TOP_RIGHT); - m.setLabelTextAnchor(TextAnchor.TOP_LEFT); - plot.addDomainMarker(m); - } - } - - private String callsign = null; - private Integer serial = null; - private Integer flight = null; - - private String title; - private ArrayList elements; - private HashMap axes; - private HashMap datasets; - private ArrayList datasetAxis; - - public AltosGraphTime(String title) { - this.filename = title.toLowerCase().replaceAll("[^a-z0-9]","_")+".png"; - this.title = title; - this.elements = new ArrayList(); - this.axes = new HashMap(); - this.datasets = new HashMap(); - this.datasetAxis = new ArrayList(); - } - - public AltosGraphTime addElement(Element e) { - e.attachGraph(this); - elements.add(e); - return this; - } - - public void setAxis(Element ds, String axisName, Color color) { - Integer axisNum = axes.get(axisName); - int dsNum = datasetAxis.size(); - if (axisNum == null) { - axisNum = newAxis(axisName, color); - } - datasets.put(ds, dsNum); - datasetAxis.add(axisNum); - } - - public int getAxisNum(Element ds) { - return datasetAxis.get( datasets.get(ds) ).intValue(); - } - public int getDataNum(Element ds) { - return datasets.get(ds).intValue(); - } - - private Integer newAxis(String name, Color color) { - int cnt = axes.size(); - AxisLocation locn = AxisLocation.BOTTOM_OR_LEFT; - if (cnt > 0) { - locn = AxisLocation.TOP_OR_RIGHT; - } - Integer res = new Integer(cnt); - axes.put(name, res); - this.addElement(new TimeAxis(cnt, name, color, locn)); - return res; - } - - public void addData(AltosDataPoint d) { - double time = d.time(); - for (Element e : elements) { - e.gotTimeData(time, d); - } - if (callsign == null) callsign = d.callsign(); - if (serial == null) serial = new Integer(d.serial()); - if (flight == null) flight = new Integer(d.flight()); - } - - public JFreeChart createChart() { - NumberAxis xAxis = new NumberAxis("Time (s)"); - xAxis.setAutoRangeIncludesZero(false); - XYItemRenderer renderer = new XYLineAndShapeRenderer(true, false); - XYPlot plot = new XYPlot(); - plot.setDomainAxis(xAxis); - plot.setRenderer(renderer); - plot.setOrientation(PlotOrientation.VERTICAL); - - if (serial != null && flight != null) { - title = serial + "/" + flight + ": " + title; - } - if (callsign != null) { - title = callsign + " - " + title; - } - - renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator()); - JFreeChart chart = new JFreeChart(title, JFreeChart.DEFAULT_TITLE_FONT, - plot, true); - ChartUtilities.applyCurrentTheme(chart); - - plot.setDomainPannable(true); - plot.setRangePannable(true); - - for (Element e : elements) { - e.addToPlot(this, plot); - } - - return chart; - } - - public void toPNG() throws java.io.IOException { - if (axes.size() > 1) { - toPNG(800, 500); - } else { - toPNG(300, 500); - } - } -} diff --git a/ao-tools/altosui/AltosGraphUI.java b/ao-tools/altosui/AltosGraphUI.java deleted file mode 100644 index cd158651..00000000 --- a/ao-tools/altosui/AltosGraphUI.java +++ /dev/null @@ -1,274 +0,0 @@ - -// Copyright (c) 2010 Anthony Towns -// GPL v2 or later - -package altosui; - -import java.io.*; -import java.util.ArrayList; - -import javax.swing.JFrame; -import java.awt.Color; - -import org.jfree.chart.ChartPanel; -import org.jfree.chart.ChartUtilities; -import org.jfree.chart.JFreeChart; -import org.jfree.chart.axis.AxisLocation; -import org.jfree.ui.ApplicationFrame; -import org.jfree.ui.RefineryUtilities; - -public class AltosGraphUI extends JFrame -{ - static final private Color red = new Color(194,31,31); - static final private Color green = new Color(31,194,31); - static final private Color blue = new Color(31,31,194); - static final private Color black = new Color(31,31,31); - - static private class OverallGraphs { - AltosGraphTime.Element height = - new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) { - public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.height()); - } - }; - - AltosGraphTime.Element speed = - new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { - public void gotTimeData(double time, AltosDataPoint d) { - if (d.state() < Altos.ao_flight_drogue) { - series.add(time, d.accel_speed()); - } else { - series.add(time, d.baro_speed()); - } - } - }; - - AltosGraphTime.Element acceleration = - new AltosGraphTime.TimeSeries("Acceleration (m/s\u00B2)", - "Axial Acceleration", blue) - { - public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.acceleration()); - } - }; - - AltosGraphTime.Element temperature = - new AltosGraphTime.TimeSeries("Temperature (\u00B0C)", - "Board temperature", red) - { - public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.temperature()); - } - }; - - AltosGraphTime.Element drogue_voltage = - new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) - { - public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.drogue_voltage()); - } - }; - - AltosGraphTime.Element main_voltage = - new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) - { - public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.main_voltage()); - } - }; - - AltosGraphTime.Element e_pad = new AltosGraphTime.StateMarker(Altos.ao_flight_pad, "Pad"); - AltosGraphTime.Element e_boost = new AltosGraphTime.StateMarker(Altos.ao_flight_boost, "Boost"); - AltosGraphTime.Element e_fast = new AltosGraphTime.StateMarker(Altos.ao_flight_fast, "Fast"); - AltosGraphTime.Element e_coast = new AltosGraphTime.StateMarker(Altos.ao_flight_coast, "Coast"); - AltosGraphTime.Element e_drogue = new AltosGraphTime.StateMarker(Altos.ao_flight_drogue, "Drogue"); - AltosGraphTime.Element e_main = new AltosGraphTime.StateMarker(Altos.ao_flight_main, "Main"); - AltosGraphTime.Element e_landed = new AltosGraphTime.StateMarker(Altos.ao_flight_landed, "Landed"); - - protected AltosGraphTime myAltosGraphTime(String suffix) { - return (new AltosGraphTime("Overall " + suffix)) - .addElement(e_boost) - .addElement(e_drogue) - .addElement(e_main) - .addElement(e_landed); - } - - public ArrayList graphs() { - ArrayList graphs = new ArrayList(); - - graphs.add( myAltosGraphTime("Summary") - .addElement(height) - .addElement(speed) - .addElement(acceleration) ); - - graphs.add( myAltosGraphTime("Altitude") - .addElement(height) ); - - graphs.add( myAltosGraphTime("Speed") - .addElement(speed) ); - - graphs.add( myAltosGraphTime("Acceleration") - .addElement(acceleration) ); - - graphs.add( myAltosGraphTime("Temperature") - .addElement(temperature) ); - - graphs.add( myAltosGraphTime("Continuity") - .addElement(drogue_voltage) - .addElement(main_voltage) ); - - return graphs; - } - } - - static private class AscentGraphs extends OverallGraphs { - protected AltosGraphTime myAltosGraphTime(String suffix) { - return (new AltosGraphTime("Ascent " + suffix) { - public void addData(AltosDataPoint d) { - int state = d.state(); - if (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast) { - super.addData(d); - } - } - }).addElement(e_boost) - .addElement(e_fast) - .addElement(e_coast); - } - } - - static private class DescentGraphs extends OverallGraphs { - protected AltosGraphTime myAltosGraphTime(String suffix) { - return (new AltosGraphTime("Descent " + suffix) { - public void addData(AltosDataPoint d) { - int state = d.state(); - if (Altos.ao_flight_drogue <= state && state <= Altos.ao_flight_main) { - super.addData(d); - } - } - }).addElement(e_drogue) - .addElement(e_main); - // ((XYGraph)graph[8]).ymin = new Double(-50); - } - } - - public AltosGraphUI(AltosRecordIterable records) { - super("Altos Graph"); - - Iterable reader = new AltosDataPointReader (records); - if (reader == null) - return; - - init(reader, 0); - } - - public AltosGraphUI(Iterable data, int which) - { - super("Altos Graph"); - init(data, which); - } - - private void init(Iterable data, int which) { - AltosGraph graph = createGraph(data, which); - - JFreeChart chart = graph.createChart(); - ChartPanel chartPanel = new ChartPanel(chart); - chartPanel.setMouseWheelEnabled(true); - chartPanel.setPreferredSize(new java.awt.Dimension(800, 500)); - setContentPane(chartPanel); - - pack(); - - RefineryUtilities.centerFrameOnScreen(this); - - setDefaultCloseOperation(DISPOSE_ON_CLOSE); - setVisible(true); - } - - private static AltosGraph createGraph(Iterable data, - int which) - { - return createGraphsWhich(data, which).get(0); - } - - private static ArrayList createGraphs( - Iterable data) - { - return createGraphsWhich(data, -1); - } - - private static ArrayList createGraphsWhich( - Iterable data, int which) - { - ArrayList graph = new ArrayList(); - graph.addAll((new OverallGraphs()).graphs()); - graph.addAll((new AscentGraphs()).graphs()); - graph.addAll((new DescentGraphs()).graphs()); - - if (which > 0) { - if (which >= graph.size()) { - which = 0; - } - AltosGraph g = graph.get(which); - graph = new ArrayList(); - graph.add(g); - } - - for (AltosDataPoint dp : data) { - for (AltosGraph g : graph) { - g.addData(dp); - } - } - - return graph; - } -} - -/* gnuplot bits... - * -300x400 - --------------------------------------------------------- -TOO HARD! :) - -"ascent-gps-accuracy.png" "Vertical error margin to apogee - GPS v Baro (m)" - 5:($7 < 6 ? $24-$11 : 1/0) -"descent-gps-accuracy.png" "Vertical error margin during descent - GPS v Baro (m)" - 5:($7 < 6 ? 1/0 : $24-$11) - -set output "overall-gps-accuracy.png" -set ylabel "distance above sea level (m)" -plot "telemetry.csv" using 5:11 with lines ti "baro altitude" axis x1y1, \ - "telemetry.csv" using 5:24 with lines ti "gps altitude" axis x1y1 - -set term png tiny size 700,700 enhanced -set xlabel "m" -set ylabel "m" -set polar -set grid polar -set rrange[*:*] -set angles degrees - -set output "overall-gps-path.png" -#:30 with yerrorlines -plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0) with lines ti "pad", \ - "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0) with lines ti "boost", \ - "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0) with lines ti "fast", \ - "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0) with lines ti "coast", \ - "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ - "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ - "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" - -set output "ascent-gps-path.png" -plot "telemetry.csv" using (90-$33):($7 == 2 ? $31 : 1/0):30 with lines ti "pad", \ - "telemetry.csv" using (90-$33):($7 == 3 ? $31 : 1/0):20 with lines ti "boost", \ - "telemetry.csv" using (90-$33):($7 == 4 ? $31 : 1/0):10 with lines ti "fast", \ - "telemetry.csv" using (90-$33):($7 == 5 ? $31 : 1/0):5 with lines ti "coast" - -set output "descent-gps-path.png" -plot "telemetry.csv" using (90-$33):($7 == 6 ? $31 : 1/0) with lines ti "drogue", \ - "telemetry.csv" using (90-$33):($7 == 7 ? $31 : 1/0) with lines ti "main", \ - "telemetry.csv" using (90-$33):($7 == 8 ? $31 : 1/0) with lines ti "landed" - - */ - - diff --git a/ao-tools/altosui/AltosGreatCircle.java b/ao-tools/altosui/AltosGreatCircle.java deleted file mode 100644 index fb1b6ab3..00000000 --- a/ao-tools/altosui/AltosGreatCircle.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.Math; - -public class AltosGreatCircle { - double distance; - double bearing; - - double sqr(double a) { return a * a; } - - static final double rad = Math.PI / 180; - static final double earth_radius = 6371.2 * 1000; /* in meters */ - - static int BEARING_LONG = 0; - static int BEARING_SHORT = 1; - static int BEARING_VOICE = 2; - String bearing_words(int length) { - String [][] bearing_string = { - { - "North", "North North East", "North East", "East North East", - "East", "East South East", "South East", "South South East", - "South", "South South West", "South West", "West South West", - "West", "West North West", "North West", "North North West" - }, { - "N", "NNE", "NE", "ENE", - "E", "ESE", "SE", "SSE", - "S", "SSW", "SW", "WSW", - "W", "WNW", "NW", "NNW" - }, { - "north", "nor nor east", "north east", "east nor east", - "east", "east sow east", "south east", "sow sow east", - "south", "sow sow west", "south west", "west sow west", - "west", "west nor west", "north west", "nor nor west " - } - }; - return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; - } - - public AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) - { - double lat1 = rad * start_lat; - double lon1 = rad * -start_lon; - double lat2 = rad * end_lat; - double lon2 = rad * -end_lon; - - double d_lon = lon2 - lon1; - - /* From http://en.wikipedia.org/wiki/Great-circle_distance */ - double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + - sqr(Math.cos(lat1) * Math.sin(lat2) - - Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); - double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); - double d = Math.atan2(vdn,vdd); - double course; - - if (Math.cos(lat1) < 1e-20) { - if (lat1 > 0) - course = Math.PI; - else - course = -Math.PI; - } else { - if (d < 1e-10) - course = 0; - else - course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / - (Math.sin(d)*Math.cos(lat1))); - if (Math.sin(lon2-lon1) > 0) - course = 2 * Math.PI-course; - } - 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; - } -} diff --git a/ao-tools/altosui/AltosHexfile.java b/ao-tools/altosui/AltosHexfile.java deleted file mode 100644 index 19e35ae1..00000000 --- a/ao-tools/altosui/AltosHexfile.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 record_list = new LinkedList(); - 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 diff --git a/ao-tools/altosui/AltosIgnite.java b/ao-tools/altosui/AltosIgnite.java deleted file mode 100644 index 3cbd8a75..00000000 --- a/ao-tools/altosui/AltosIgnite.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.concurrent.*; - -public class AltosIgnite { - AltosDevice device; - AltosSerial serial; - boolean remote; - boolean serial_started; - final static int None = 0; - final static int Apogee = 1; - final static int Main = 2; - - final static int Unknown = 0; - final static int Ready = 1; - final static int Active = 2; - final static int Open = 3; - - private void start_serial() throws InterruptedException { - serial_started = true; - if (remote) { - serial.set_radio(); - serial.printf("p\nE 0\n"); - serial.flush_input(); - } - } - - private void stop_serial() throws InterruptedException { - if (!serial_started) - return; - serial_started = false; - if (serial == null) - return; - if (remote) { - serial.printf("~"); - serial.flush_output(); - } - } - - class string_ref { - String value; - - public String get() { - return value; - } - public void set(String i) { - value = i; - } - public string_ref() { - value = null; - } - } - - private boolean get_string(String line, String label, string_ref s) { - if (line.startsWith(label)) { - String quoted = line.substring(label.length()).trim(); - - if (quoted.startsWith("\"")) - quoted = quoted.substring(1); - if (quoted.endsWith("\"")) - quoted = quoted.substring(0,quoted.length()-1); - s.set(quoted); - return true; - } else { - return false; - } - } - - private int status(String status_name) { - if (status_name.equals("unknown")) - return Unknown; - if (status_name.equals("ready")) - return Ready; - if (status_name.equals("active")) - return Active; - if (status_name.equals("open")) - return Open; - return Unknown; - } - - public int status(int igniter) throws InterruptedException, TimeoutException { - int status = Unknown; - if (serial == null) - return status; - string_ref status_name = new string_ref(); - start_serial(); - serial.printf("t\n"); - for (;;) { - String line = serial.get_reply(5000); - if (line == null) - throw new TimeoutException(); - if (get_string(line, "Igniter: drogue Status: ", status_name)) - if (igniter == Apogee) - status = status(status_name.get()); - if (get_string(line, "Igniter: main Status: ", status_name)) { - if (igniter == Main) - status = status(status_name.get()); - break; - } - } - stop_serial(); - return status; - } - - public String status_string(int status) { - switch (status) { - case Unknown: return "Unknown"; - case Ready: return "Ready"; - case Active: return "Active"; - case Open: return "Open"; - default: return "Unknown"; - } - } - - public void fire(int igniter) { - if (serial == null) - return; - try { - start_serial(); - switch (igniter) { - case Main: - serial.printf("i DoIt main\n"); - break; - case Apogee: - serial.printf("i DoIt drogue\n"); - break; - } - } catch (InterruptedException ie) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - } - } - - public void close() { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - serial.close(); - serial = null; - } - - public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { - - device = in_device; - serial = new AltosSerial(device); - remote = false; - - if (!device.matchProduct(AltosDevice.product_telemetrum)) - remote = true; - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosIgniteUI.java b/ao-tools/altosui/AltosIgniteUI.java deleted file mode 100644 index d542729c..00000000 --- a/ao-tools/altosui/AltosIgniteUI.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.concurrent.*; - -public class AltosIgniteUI - extends JDialog - implements ActionListener -{ - AltosDevice device; - AltosIgnite ignite; - JFrame owner; - JLabel label; - JRadioButton apogee; - JLabel apogee_status_label; - JRadioButton main; - JLabel main_status_label; - JToggleButton arm; - JButton fire; - javax.swing.Timer timer; - - int apogee_status; - int main_status; - - final static int timeout = 1 * 1000; - - int time_remaining; - boolean timer_running; - - void set_arm_text() { - if (arm.isSelected()) - arm.setText(String.format("%d", time_remaining)); - else - arm.setText("Arm"); - } - - void start_timer() { - time_remaining = 10; - set_arm_text(); - timer_running = true; - } - - void stop_timer() { - time_remaining = 0; - arm.setSelected(false); - arm.setEnabled(false); - fire.setEnabled(false); - timer_running = false; - set_arm_text(); - } - - void cancel () { - apogee.setSelected(false); - main.setSelected(false); - fire.setEnabled(false); - stop_timer(); - } - - void get_ignite_status() throws InterruptedException, TimeoutException { - apogee_status = ignite.status(AltosIgnite.Apogee); - main_status = ignite.status(AltosIgnite.Main); - } - - void set_ignite_status() throws InterruptedException, TimeoutException { - get_ignite_status(); - apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status))); - main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status))); - } - - void close() { - timer.stop(); - setVisible(false); - ignite.close(); - } - - void abort() { - close(); - JOptionPane.showMessageDialog(owner, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); - } - - void tick_timer() { - if (timer_running) { - --time_remaining; - if (time_remaining <= 0) - cancel(); - else - set_arm_text(); - } - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } - } - - void fire() { - if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) { - int igniter = AltosIgnite.None; - if (apogee.isSelected() && !main.isSelected()) - igniter = AltosIgnite.Apogee; - else if (main.isSelected() && !apogee.isSelected()) - igniter = AltosIgnite.Main; - ignite.fire(igniter); - cancel(); - } - } - - public void actionPerformed(ActionEvent e) { - String cmd = e.getActionCommand(); - if (cmd.equals("apogee") || cmd.equals("main")) { - stop_timer(); - } - - if (cmd.equals("apogee") && apogee.isSelected()) { - main.setSelected(false); - arm.setEnabled(true); - } - if (cmd.equals("main") && main.isSelected()) { - apogee.setSelected(false); - arm.setEnabled(true); - } - - if (cmd.equals("arm")) { - if (arm.isSelected()) { - fire.setEnabled(true); - start_timer(); - } else - cancel(); - } - if (cmd.equals("fire")) - fire(); - if (cmd.equals("tick")) - tick_timer(); - if (cmd.equals("close")) { - close(); - } - } - - /* A window listener to catch closing events and tell the config code */ - class ConfigListener extends WindowAdapter { - AltosIgniteUI ui; - - public ConfigListener(AltosIgniteUI this_ui) { - ui = this_ui; - } - - public void windowClosing(WindowEvent e) { - ui.actionPerformed(new ActionEvent(e.getSource(), - ActionEvent.ACTION_PERFORMED, - "close")); - } - } - - private boolean open() { - device = AltosDeviceDialog.show(owner, AltosDevice.product_any); - if (device != null) { - try { - ignite = new AltosIgnite(device); - return true; - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(owner, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } - return false; - } - - public AltosIgniteUI(JFrame in_owner) { - - owner = in_owner; - apogee_status = AltosIgnite.Unknown; - main_status = AltosIgnite.Unknown; - - if (!open()) - return; - - Container pane = getContentPane(); - GridBagConstraints c = new GridBagConstraints(); - Insets i = new Insets(4,4,4,4); - - timer = new javax.swing.Timer(timeout, this); - timer.setActionCommand("tick"); - timer_running = false; - timer.restart(); - - owner = in_owner; - - pane.setLayout(new GridBagLayout()); - - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 2; - c.anchor = GridBagConstraints.CENTER; - label = new JLabel ("Fire Igniter"); - pane.add(label, c); - - c.gridx = 0; - c.gridy = 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - apogee = new JRadioButton ("Apogee"); - pane.add(apogee, c); - apogee.addActionListener(this); - apogee.setActionCommand("apogee"); - - c.gridx = 1; - c.gridy = 1; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - apogee_status_label = new JLabel(); - pane.add(apogee_status_label, c); - - c.gridx = 0; - c.gridy = 2; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - main = new JRadioButton ("Main"); - pane.add(main, c); - main.addActionListener(this); - main.setActionCommand("main"); - - c.gridx = 1; - c.gridy = 2; - c.gridwidth = 1; - c.anchor = GridBagConstraints.WEST; - main_status_label = new JLabel(); - pane.add(main_status_label, c); - - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - return; - } catch (TimeoutException te) { - abort(); - return; - } - - c.gridx = 0; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - arm = new JToggleButton ("Arm"); - pane.add(arm, c); - arm.addActionListener(this); - arm.setActionCommand("arm"); - arm.setEnabled(false); - - c.gridx = 1; - c.gridy = 3; - c.gridwidth = 1; - c.anchor = GridBagConstraints.CENTER; - fire = new JButton ("Fire"); - fire.setEnabled(false); - pane.add(fire, c); - fire.addActionListener(this); - fire.setActionCommand("fire"); - - pack(); - setLocationRelativeTo(owner); - setVisible(true); - - addWindowListener(new ConfigListener(this)); - } -} \ No newline at end of file diff --git a/ao-tools/altosui/AltosInfoTable.java b/ao-tools/altosui/AltosInfoTable.java deleted file mode 100644 index 723f8301..00000000 --- a/ao-tools/altosui/AltosInfoTable.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosInfoTable extends JTable { - private AltosFlightInfoTableModel model; - - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); - - static final int info_columns = 3; - static final int info_rows = 17; - - int desired_row_height() { - FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); - return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; - } - - public AltosInfoTable() { - super(new AltosFlightInfoTableModel(info_rows, info_columns)); - model = (AltosFlightInfoTableModel) getModel(); - setFont(infoValueFont); - setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); - setShowGrid(true); - setRowHeight(desired_row_height()); - doLayout(); - } - - public Dimension getPreferredScrollableViewportSize() { - return getPreferredSize(); - } - - void info_reset() { - model.reset(); - } - - void info_add_row(int col, String name, String value) { - model.addRow(col, name, value); - } - - void info_add_row(int col, String name, String format, Object... parameters) { - info_add_row (col, name, String.format(format, parameters)); - } - - void info_add_deg(int col, String name, double v, int pos, int neg) { - int c = pos; - if (v < 0) { - c = neg; - v = -v; - } - double deg = Math.floor(v); - double min = (v - deg) * 60; - - info_add_row(col, name, String.format("%3.0f°%08.5f'", deg, min)); - } - - void info_finish() { - model.finish(); - } - - public void clear() { - model.clear(); - } - - public void show(AltosState state, int crc_errors) { - if (state == null) - return; - info_reset(); - 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); - info_add_row(0, "Max acceleration", "%8.1f m/s²", state.max_acceleration); - info_add_row(0, "Speed", "%8.1f m/s", state.ascent ? state.speed : state.baro_speed); - info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); - info_add_row(0, "Temperature", "%9.2f °C", state.temperature); - info_add_row(0, "Battery", "%9.2f V", state.battery); - info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); - info_add_row(0, "Main", "%9.2f V", state.main_sense); - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); - 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) - info_add_row(1, "GPS", " unlocked"); - else - info_add_row(1, "GPS", " missing"); - info_add_row(1, "Satellites", "%6d", state.data.gps.nsat); - info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); - info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - info_add_row(1, "GPS altitude", "%6d", state.gps.alt); - info_add_row(1, "GPS height", "%6.0f", state.gps_height); - - /* The SkyTraq GPS doesn't report these values */ - if (false) { - info_add_row(1, "GPS ground speed", "%8.1f m/s %3d°", - state.gps.ground_speed, - state.gps.course); - info_add_row(1, "GPS climb rate", "%8.1f m/s", - state.gps.climb_rate); - info_add_row(1, "GPS error", "%6d m(h)%3d m(v)", - state.gps.h_error, state.gps.v_error); - } - info_add_row(1, "GPS hdop", "%8.1f", state.gps.hdop); - - if (state.npad > 0) { - if (state.from_pad != null) { - 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'); - info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); - } - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.year, - state.gps.month, - state.gps.day); - info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.hour, - state.gps.minute, - state.gps.second); - int nsat_vis = 0; - int c; - - if (state.gps.cc_gps_sat == null) - info_add_row(2, "Satellites Visible", "%4d", 0); - else { - info_add_row(2, "Satellites Visible", "%4d", state.gps.cc_gps_sat.length); - for (c = 0; c < state.gps.cc_gps_sat.length; c++) { - info_add_row(2, "Satellite id,C/N0", - "%4d, %4d", - state.gps.cc_gps_sat[c].svid, - state.gps.cc_gps_sat[c].c_n0); - } - } - } - info_finish(); - } -} diff --git a/ao-tools/altosui/AltosKML.java b/ao-tools/altosui/AltosKML.java deleted file mode 100644 index d586033f..00000000 --- a/ao-tools/altosui/AltosKML.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.*; - -public class AltosKML implements AltosWriter { - - File name; - PrintStream out; - int state = -1; - AltosRecord prev = null; - - static final String[] kml_state_colors = { - "FF000000", - "FF000000", - "FF000000", - "FF0000FF", - "FF4080FF", - "FF00FFFF", - "FFFF0000", - "FF00FF00", - "FF000000", - "FFFFFFFF" - }; - - static final String kml_header_start = - "\n" + - "\n" + - "\n" + - " AO Flight#%d S/N: %03d\n" + - " \n"; - static final String kml_header_end = - " \n" + - " 0\n"; - - static final String kml_style_start = - " \n"; - - static final String kml_placemark_start = - " \n" + - " %s\n" + - " #ao-flightstate-%s\n" + - " \n" + - " 1\n" + - " absolute\n" + - " \n"; - - static final String kml_coord_fmt = - " %12.7f, %12.7f, %12.7f \n"; - - static final String kml_placemark_end = - " \n" + - " \n" + - " \n"; - - static final String kml_footer = - "\n" + - "\n"; - - void start (AltosRecord record) { - out.printf(kml_header_start, record.flight, record.serial); - out.printf("Date: %04d-%02d-%02d\n", - record.gps.year, record.gps.month, record.gps.day); - out.printf("Time: %2d:%02d:%02d\n", - record.gps.hour, record.gps.minute, record.gps.second); - out.printf("%s", kml_header_end); - } - - boolean started = false; - - void state_start(AltosRecord record) { - String state_name = Altos.state_name(record.state); - out.printf(kml_style_start, state_name, kml_state_colors[record.state]); - out.printf("\tState: %s\n", state_name); - out.printf("%s", kml_style_end); - out.printf(kml_placemark_start, state_name, state_name); - } - - void state_end(AltosRecord record) { - out.printf("%s", kml_placemark_end); - } - - void coord(AltosRecord record) { - AltosGPS gps = record.gps; - out.printf(kml_coord_fmt, - gps.lon, gps.lat, - record.filtered_altitude(), (double) gps.alt, - record.time, gps.nsat); - } - - void end() { - out.printf("%s", kml_footer); - } - - public void close() { - if (prev != null) { - state_end(prev); - end(); - prev = null; - } - } - - public void write(AltosRecord record) { - AltosGPS gps = record.gps; - - if (gps == null) - return; - if (!started) { - start(record); - started = true; - } - if (prev != null && - prev.gps.second == record.gps.second && - prev.gps.minute == record.gps.minute && - prev.gps.hour == record.gps.hour) - return; - if (record.state != state) { - state = record.state; - if (prev != null) { - coord(record); - state_end(prev); - } - state_start(record); - } - coord(record); - prev = record; - } - - public void write(AltosRecordIterable iterable) { - for (AltosRecord record : iterable) - write(record); - } - - public AltosKML(File in_name) throws FileNotFoundException { - name = in_name; - out = new PrintStream(name); - } - - public AltosKML(String in_string) throws FileNotFoundException { - this(new File(in_string)); - } -} diff --git a/ao-tools/altosui/AltosLanded.java b/ao-tools/altosui/AltosLanded.java deleted file mode 100644 index d34efe6d..00000000 --- a/ao-tools/altosui/AltosLanded.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosLanded extends JComponent implements AltosFlightDisplay { - GridBagLayout layout; - Font label_font; - Font value_font; - - public class LandedValue { - JLabel label; - JTextField value; - void show(AltosState state, int crc_errors) {} - - void reset() { - value.setText(""); - } - - void show(String format, double v) { - value.setText(String.format(format, v)); - } - - public LandedValue (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 0; c.gridy = y; - c.insets = new Insets(10, 10, 10, 10); - c.anchor = GridBagConstraints.WEST; - c.weightx = 0; - c.fill = GridBagConstraints.VERTICAL; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 1; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.weightx = 1; - c.fill = GridBagConstraints.BOTH; - layout.setConstraints(value, c); - add(value); - } - } - - String pos(double p, String pos, String neg) { - String h = pos; - if (p < 0) { - h = neg; - p = -p; - } - int deg = (int) Math.floor(p); - double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %4d° %9.6f", h, deg, min); - } - - class Lat extends LandedValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - value.setText(pos(state.gps.lat,"N", "S")); - else - value.setText("???"); - } - public Lat (GridBagLayout layout, int y) { - super (layout, y, "Latitude"); - } - } - - Lat lat; - - class Lon extends LandedValue { - void show (AltosState state, int crc_errors) { - if (state.gps != null) - value.setText(pos(state.gps.lon,"E", "W")); - else - value.setText("???"); - } - public Lon (GridBagLayout layout, int y) { - super (layout, y, "Longitude"); - } - } - - Lon lon; - - class Bearing extends LandedValue { - void show (AltosState state, int crc_errors) { - if (state.from_pad != null) - show("%3.0f°", state.from_pad.bearing); - else - value.setText("???"); - } - public Bearing (GridBagLayout layout, int y) { - super (layout, y, "Bearing"); - } - } - - Bearing bearing; - - class Distance extends LandedValue { - void show (AltosState state, int crc_errors) { - if (state.from_pad != null) - show("%6.0f m", state.from_pad.distance); - else - value.setText("???"); - } - public Distance (GridBagLayout layout, int y) { - super (layout, y, "Distance"); - } - } - - Distance distance; - - class Height extends LandedValue { - void show (AltosState state, int crc_errors) { - show("%6.0f m", state.max_height); - } - public Height (GridBagLayout layout, int y) { - super (layout, y, "Maximum Height"); - } - } - - Height height; - - class Speed extends LandedValue { - void show (AltosState state, int crc_errors) { - show("%6.0f m/s", state.max_speed); - } - public Speed (GridBagLayout layout, int y) { - super (layout, y, "Maximum Speed"); - } - } - - Speed speed; - - class Accel extends LandedValue { - void show (AltosState state, int crc_errors) { - show("%6.0f m/s²", state.max_acceleration); - } - public Accel (GridBagLayout layout, int y) { - super (layout, y, "Maximum Acceleration"); - } - } - - Accel accel; - - public void reset() { - lat.reset(); - lon.reset(); - bearing.reset(); - distance.reset(); - height.reset(); - speed.reset(); - accel.reset(); - } - - public void show(AltosState state, int crc_errors) { - bearing.show(state, crc_errors); - distance.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); - height.show(state, crc_errors); - speed.show(state, crc_errors); - accel.show(state, crc_errors); - } - - public AltosLanded() { - layout = new GridBagLayout(); - - label_font = new Font("Dialog", Font.PLAIN, 22); - value_font = new Font("Monospaced", Font.PLAIN, 22); - setLayout(layout); - - /* Elements in descent display */ - bearing = new Bearing(layout, 0); - distance = new Distance(layout, 1); - lat = new Lat(layout, 2); - lon = new Lon(layout, 3); - height = new Height(layout, 4); - speed = new Speed(layout, 5); - accel = new Accel(layout, 6); - } -} diff --git a/ao-tools/altosui/AltosLed.java b/ao-tools/altosui/AltosLed.java deleted file mode 100644 index e08e9960..00000000 --- a/ao-tools/altosui/AltosLed.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosLed extends JLabel { - ImageIcon on, off; - - ImageIcon create_icon(String path) { - java.net.URL imgURL = AltosUI.class.getResource(path); - if (imgURL != null) - return new ImageIcon(imgURL); - System.err.printf("Cannot find icon \"%s\"\n", path); - return null; - } - - public void set(boolean set) { - if (set) - setIcon(on); - else - setIcon(off); - } - - public AltosLed(String on_path, String off_path) { - on = create_icon(on_path); - off = create_icon(off_path); - setIcon(off); - } -} diff --git a/ao-tools/altosui/AltosLights.java b/ao-tools/altosui/AltosLights.java deleted file mode 100644 index 2fa38412..00000000 --- a/ao-tools/altosui/AltosLights.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosLights extends JComponent { - - GridBagLayout gridbag; - - AltosLed red, green; - - ImageIcon create_icon(String path, String description) { - java.net.URL imgURL = AltosUI.class.getResource(path); - if (imgURL != null) - return new ImageIcon(imgURL, description); - System.err.printf("Cannot find icon \"%s\"\n", path); - return null; - } - - public void set (boolean on) { - if (on) { - red.set(false); - green.set(true); - } else { - red.set(true); - green.set(false); - } - } - - public AltosLights() { - GridBagConstraints c; - gridbag = new GridBagLayout(); - setLayout(gridbag); - - c = new GridBagConstraints(); - red = new AltosLed("/redled.png", "/grayled.png"); - c.gridx = 0; c.gridy = 0; - c.insets = new Insets (0, 5, 0, 5); - gridbag.setConstraints(red, c); - add(red); - red.set(true); - green = new AltosLed("/greenled.png", "/grayled.png"); - c.gridx = 1; c.gridy = 0; - gridbag.setConstraints(green, c); - add(green); - green.set(false); - } -} diff --git a/ao-tools/altosui/AltosLine.java b/ao-tools/altosui/AltosLine.java deleted file mode 100644 index 86e9d4c6..00000000 --- a/ao-tools/altosui/AltosLine.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 diff --git a/ao-tools/altosui/AltosLog.java b/ao-tools/altosui/AltosLog.java deleted file mode 100644 index dd147d21..00000000 --- a/ao-tools/altosui/AltosLog.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.lang.*; -import java.util.*; -import java.text.ParseException; -import java.util.concurrent.LinkedBlockingQueue; - -/* - * This creates a thread to capture telemetry data and write it to - * a log file - */ -class AltosLog implements Runnable { - - LinkedBlockingQueue input_queue; - LinkedBlockingQueue pending_queue; - int serial; - int flight; - FileWriter log_file; - Thread log_thread; - - private void close_log_file() { - if (log_file != null) { - try { - log_file.close(); - } catch (IOException io) { - } - log_file = null; - } - } - - void close() { - close_log_file(); - if (log_thread != null) { - log_thread.interrupt(); - log_thread = null; - } - } - - boolean open (AltosTelemetry telem) throws IOException { - AltosFile a = new AltosFile(telem); - - log_file = new FileWriter(a, true); - if (log_file != null) { - while (!pending_queue.isEmpty()) { - try { - String s = pending_queue.take(); - log_file.write(s); - log_file.write('\n'); - } catch (InterruptedException ie) { - } - } - log_file.flush(); - } - return log_file != null; - } - - public void run () { - try { - for (;;) { - AltosLine line = input_queue.take(); - if (line.line == null) - continue; - try { - AltosTelemetry telem = new AltosTelemetry(line.line); - if (telem.serial != serial || telem.flight != flight || log_file == null) { - close_log_file(); - serial = telem.serial; - flight = telem.flight; - open(telem); - } - } catch (ParseException pe) { - } catch (AltosCRCException ce) { - } - if (log_file != null) { - log_file.write(line.line); - log_file.write('\n'); - log_file.flush(); - } else - pending_queue.put(line.line); - } - } catch (InterruptedException ie) { - } catch (IOException ie) { - } - close(); - } - - public AltosLog (AltosSerial s) { - pending_queue = new LinkedBlockingQueue (); - input_queue = new LinkedBlockingQueue (); - s.add_monitor(input_queue); - serial = -1; - flight = -1; - log_file = null; - log_thread = new Thread(this); - log_thread.start(); - } -} diff --git a/ao-tools/altosui/AltosPad.java b/ao-tools/altosui/AltosPad.java deleted file mode 100644 index 66954347..00000000 --- a/ao-tools/altosui/AltosPad.java +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public class AltosPad extends JComponent implements AltosFlightDisplay { - GridBagLayout layout; - - public class LaunchStatus { - JLabel label; - JTextField value; - AltosLights lights; - - void show(AltosState state, int crc_errors) {} - void reset() { - value.setText(""); - lights.set(false); - } - - public LaunchStatus (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.weighty = 1; - - lights = new AltosLights(); - c.gridx = 0; c.gridy = y; - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(lights, c); - add(lights); - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - - } - } - - public class LaunchValue { - JLabel label; - JTextField value; - void show(AltosState state, int crc_errors) {} - - void reset() { - value.setText(""); - } - public LaunchValue (GridBagLayout layout, int y, String text) { - GridBagConstraints c = new GridBagConstraints(); - c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); - c.weighty = 1; - - label = new JLabel(text); - label.setFont(Altos.label_font); - label.setHorizontalAlignment(SwingConstants.LEFT); - c.gridx = 1; c.gridy = y; - c.anchor = GridBagConstraints.WEST; - c.fill = GridBagConstraints.VERTICAL; - c.weightx = 0; - layout.setConstraints(label, c); - add(label); - - value = new JTextField(Altos.text_width); - value.setFont(Altos.value_font); - value.setHorizontalAlignment(SwingConstants.RIGHT); - c.gridx = 2; c.gridy = y; - c.anchor = GridBagConstraints.EAST; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - layout.setConstraints(value, c); - add(value); - } - } - - class Battery extends LaunchStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.battery)); - lights.set(state.battery > 3.7); - } - public Battery (GridBagLayout layout, int y) { - super(layout, y, "Battery Voltage"); - } - } - - Battery battery; - - class Apogee extends LaunchStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.drogue_sense)); - lights.set(state.drogue_sense > 3.2); - } - public Apogee (GridBagLayout layout, int y) { - super(layout, y, "Apogee Igniter Voltage"); - } - } - - Apogee apogee; - - class Main extends LaunchStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.2f V", state.main_sense)); - lights.set(state.main_sense > 3.2); - } - public Main (GridBagLayout layout, int y) { - super(layout, y, "Main Igniter Voltage"); - } - } - - Main main; - - class GPSLocked extends LaunchStatus { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4d sats", state.gps.nsat)); - lights.set(state.gps.locked); - } - public GPSLocked (GridBagLayout layout, int y) { - super (layout, y, "GPS Locked"); - } - } - - GPSLocked gps_locked; - - class GPSReady extends LaunchStatus { - void show (AltosState state, int crc_errors) { - if (state.gps_ready) - value.setText("Ready"); - else - value.setText(String.format("Waiting %d", state.gps_waiting)); - lights.set(state.gps_ready); - } - public GPSReady (GridBagLayout layout, int y) { - super (layout, y, "GPS Ready"); - } - } - - GPSReady gps_ready; - - String pos(double p, String pos, String neg) { - String h = pos; - if (p < 0) { - h = neg; - p = -p; - } - int deg = (int) Math.floor(p); - double min = (p - Math.floor(p)) * 60.0; - return String.format("%s %4d° %9.6f", h, deg, min); - } - - class PadLat extends LaunchValue { - void show (AltosState state, int crc_errors) { - value.setText(pos(state.pad_lat,"N", "S")); - } - public PadLat (GridBagLayout layout, int y) { - super (layout, y, "Pad Latitude"); - } - } - - PadLat pad_lat; - - class PadLon extends LaunchValue { - void show (AltosState state, int crc_errors) { - value.setText(pos(state.pad_lon,"E", "W")); - } - public PadLon (GridBagLayout layout, int y) { - super (layout, y, "Pad Longitude"); - } - } - - PadLon pad_lon; - - class PadAlt extends LaunchValue { - void show (AltosState state, int crc_errors) { - value.setText(String.format("%4.0f m", state.pad_alt)); - } - public PadAlt (GridBagLayout layout, int y) { - super (layout, y, "Pad Altitude"); - } - } - - PadAlt pad_alt; - - public void reset() { - battery.reset(); - apogee.reset(); - main.reset(); - gps_locked.reset(); - gps_ready.reset(); - pad_lat.reset(); - pad_lon.reset(); - pad_alt.reset(); - } - - public void show(AltosState state, int crc_errors) { - battery.show(state, crc_errors); - apogee.show(state, crc_errors); - main.show(state, crc_errors); - gps_locked.show(state, crc_errors); - gps_ready.show(state, crc_errors); - pad_lat.show(state, crc_errors); - pad_lon.show(state, crc_errors); - pad_alt.show(state, crc_errors); - } - - public AltosPad() { - layout = new GridBagLayout(); - - setLayout(layout); - - /* Elements in pad display: - * - * Battery voltage - * Igniter continuity - * GPS lock status - * GPS ready status - * GPS location - * Pad altitude - * RSSI - */ - battery = new Battery(layout, 0); - apogee = new Apogee(layout, 1); - main = new Main(layout, 2); - gps_locked = new GPSLocked(layout, 3); - gps_ready = new GPSReady(layout, 4); - pad_lat = new PadLat(layout, 5); - pad_lon = new PadLon(layout, 6); - pad_alt = new PadAlt(layout, 7); - } -} diff --git a/ao-tools/altosui/AltosParse.java b/ao-tools/altosui/AltosParse.java deleted file mode 100644 index fbfcaaee..00000000 --- a/ao-tools/altosui/AltosParse.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.lang.*; - -public class AltosParse { - static boolean isdigit(char c) { - return '0' <= c && c <= '9'; - } - - static int parse_int(String v) throws ParseException { - try { - 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 Altos.fromhex(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing hex " + v, 0); - } - } - - static double parse_double(String v) throws ParseException { - try { - return Double.parseDouble(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing double " + v, 0); - } - } - - static double parse_coord(String coord) throws ParseException { - String[] dsf = coord.split("\\D+"); - - if (dsf.length != 3) { - throw new ParseException("error parsing coord " + coord, 0); - } - int deg = parse_int(dsf[0]); - int min = parse_int(dsf[1]); - int frac = parse_int(dsf[2]); - - double r = deg + (min + frac / 10000.0) / 60.0; - if (coord.endsWith("S") || coord.endsWith("W")) - r = -r; - return r; - } - - static String strip_suffix(String v, String suffix) { - if (v.endsWith(suffix)) - return v.substring(0, v.length() - suffix.length()); - return v; - } - - static void word(String v, String m) throws ParseException { - if (!v.equals(m)) { - throw new ParseException("error matching '" + v + "' '" + m + "'", 0); - } - } -} diff --git a/ao-tools/altosui/AltosPreferences.java b/ao-tools/altosui/AltosPreferences.java deleted file mode 100644 index e2a3df3b..00000000 --- a/ao-tools/altosui/AltosPreferences.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.awt.Component; -import javax.swing.*; -import javax.swing.filechooser.FileSystemView; - -class AltosPreferences { - static Preferences preferences; - - /* logdir preference name */ - final static String logdirPreference = "LOGDIR"; - - /* channel preference name */ - final static String channelPreferenceFormat = "CHANNEL-%d"; - - /* voice preference name */ - final static String voicePreference = "VOICE"; - - /* callsign preference name */ - final static String callsignPreference = "CALLSIGN"; - - /* firmware directory preference name */ - final static String firmwaredirPreference = "FIRMWARE"; - - /* Default logdir is ~/TeleMetrum */ - final static String logdirName = "TeleMetrum"; - - /* UI Component to pop dialogs up */ - static Component component; - - /* Log directory */ - static File logdir; - - /* Channel (map serial to channel) */ - static Hashtable channels; - - /* Voice preference */ - static boolean voice; - - /* Callsign preference */ - static String callsign; - - /* Firmware directory */ - static File firmwaredir; - - public static void init(Component ui) { - preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - - component = ui; - - /* Initialize logdir from preferences */ - String logdir_string = preferences.get(logdirPreference, null); - if (logdir_string != null) - logdir = new File(logdir_string); - else { - /* Use the file system view default directory */ - logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); - if (!logdir.exists()) - logdir.mkdirs(); - } - - channels = new Hashtable(); - - voice = preferences.getBoolean(voicePreference, true); - - callsign = preferences.get(callsignPreference,"N0CALL"); - - String firmwaredir_string = preferences.get(firmwaredirPreference, null); - if (firmwaredir_string != null) - firmwaredir = new File(firmwaredir_string); - else - firmwaredir = null; - } - - static void flush_preferences() { - try { - preferences.flush(); - } catch (BackingStoreException ee) { - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); - } - } - - public static void set_logdir(File new_logdir) { - logdir = new_logdir; - synchronized (preferences) { - preferences.put(logdirPreference, logdir.getPath()); - flush_preferences(); - } - } - - private static boolean check_dir(File dir) { - if (!dir.exists()) { - if (!dir.mkdirs()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Cannot create directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - } else if (!dir.isDirectory()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Is not a directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - return true; - } - - /* Configure the log directory. This is where all telemetry and eeprom files - * will be written to, and where replay will look for telemetry files - */ - public static void ConfigureLog() { - JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); - - logdir_chooser.setDialogTitle("Configure Data Logging Directory"); - logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { - File dir = logdir_chooser.getSelectedFile(); - if (check_dir(dir)) - set_logdir(dir); - } - } - - public static File logdir() { - return logdir; - } - - public static void set_channel(int serial, int new_channel) { - channels.put(serial, new_channel); - synchronized (preferences) { - preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel); - flush_preferences(); - } - } - - public static int channel(int serial) { - if (channels.containsKey(serial)) - return channels.get(serial); - int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); - channels.put(serial, channel); - return channel; - } - - public static void set_voice(boolean new_voice) { - voice = new_voice; - synchronized (preferences) { - preferences.putBoolean(voicePreference, voice); - flush_preferences(); - } - } - - public static boolean voice() { - return voice; - } - - public static void set_callsign(String new_callsign) { - callsign = new_callsign; - synchronized(preferences) { - preferences.put(callsignPreference, callsign); - flush_preferences(); - } - } - - public static String callsign() { - return callsign; - } - - public static void set_firmwaredir(File new_firmwaredir) { - firmwaredir = new_firmwaredir; - synchronized (preferences) { - preferences.put(firmwaredirPreference, firmwaredir.getPath()); - flush_preferences(); - } - } - - public static File firmwaredir() { - return firmwaredir; - } -} diff --git a/ao-tools/altosui/AltosReader.java b/ao-tools/altosui/AltosReader.java deleted file mode 100644 index b9280a0c..00000000 --- a/ao-tools/altosui/AltosReader.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; - -public class AltosReader { - public AltosRecord read() throws IOException, ParseException { return null; } - public void close() { } - public void write_comments(PrintStream out) { } -} diff --git a/ao-tools/altosui/AltosRecord.java b/ao-tools/altosui/AltosRecord.java deleted file mode 100644 index 1160a273..00000000 --- a/ao-tools/altosui/AltosRecord.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.HashMap; -import java.io.*; - -public class AltosRecord { - int version; - String callsign; - int serial; - int flight; - int rssi; - int status; - int state; - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - int flight_accel; - int ground_accel; - int flight_vel; - int flight_pres; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - AltosGPS gps; - - double time; /* seconds since boost */ - - /* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - - static final double counts_per_kPa = 27 * 2047 / 3300; - static final double counts_at_101_3kPa = 1674.0; - - static double - barometer_to_pressure(double count) - { - return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; - } - - public double raw_pressure() { - return barometer_to_pressure(pres); - } - - public double filtered_pressure() { - return barometer_to_pressure(flight_pres); - } - - public double ground_pressure() { - return barometer_to_pressure(ground_pres); - } - - public double filtered_altitude() { - return AltosConvert.pressure_to_altitude(filtered_pressure()); - } - - public double raw_altitude() { - return AltosConvert.pressure_to_altitude(raw_pressure()); - } - - public double ground_altitude() { - return AltosConvert.pressure_to_altitude(ground_pressure()); - } - - public double filtered_height() { - return filtered_altitude() - ground_altitude(); - } - - public double raw_height() { - return raw_altitude() - ground_altitude(); - } - - public double battery_voltage() { - return AltosConvert.cc_battery_to_voltage(batt); - } - - public double main_voltage() { - return AltosConvert.cc_ignitor_to_voltage(main); - } - - public double drogue_voltage() { - return AltosConvert.cc_ignitor_to_voltage(drogue); - } - - /* Value for the CC1111 built-in temperature sensor - * Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - */ - - static double - thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - - public double temperature() { - return thermometer_to_temperature(temp); - } - - double accel_counts_per_mss() { - double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; - - return counts_per_g / 9.80665; - } - public double acceleration() { - return (ground_accel - accel) / accel_counts_per_mss(); - } - - public double accel_speed() { - double speed = flight_vel / (accel_counts_per_mss() * 100.0); - return speed; - } - - public String state() { - return Altos.state_name(state); - } - - public static String gets(FileInputStream s) throws IOException { - int c; - String line = ""; - - while ((c = s.read()) != -1) { - if (c == '\r') - continue; - if (c == '\n') { - return line; - } - line = line + (char) c; - } - return null; - } - - public AltosRecord(AltosRecord old) { - version = old.version; - callsign = old.callsign; - serial = old.serial; - flight = old.flight; - rssi = old.rssi; - status = old.status; - state = old.state; - tick = old.tick; - accel = old.accel; - pres = old.pres; - temp = old.temp; - batt = old.batt; - drogue = old.drogue; - main = old.main; - flight_accel = old.flight_accel; - ground_accel = old.ground_accel; - flight_vel = old.flight_vel; - flight_pres = old.flight_pres; - ground_pres = old.ground_pres; - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - gps = new AltosGPS(old.gps); - } - - public AltosRecord() { - version = 0; - callsign = "N0CALL"; - serial = 0; - flight = 0; - rssi = 0; - status = 0; - state = Altos.ao_flight_startup; - tick = 0; - accel = 0; - pres = 0; - temp = 0; - batt = 0; - drogue = 0; - main = 0; - flight_accel = 0; - ground_accel = 0; - flight_vel = 0; - flight_pres = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; - gps = new AltosGPS(); - } -} diff --git a/ao-tools/altosui/AltosRecordIterable.java b/ao-tools/altosui/AltosRecordIterable.java deleted file mode 100644 index a7df92d1..00000000 --- a/ao-tools/altosui/AltosRecordIterable.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public abstract class AltosRecordIterable implements Iterable { - public abstract Iterator iterator(); - public void write_comments(PrintStream out) { } -} diff --git a/ao-tools/altosui/AltosReplayReader.java b/ao-tools/altosui/AltosReplayReader.java deleted file mode 100644 index 4e5e1d93..00000000 --- a/ao-tools/altosui/AltosReplayReader.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -/* - * Open an existing telemetry file and replay it in realtime - */ - -public class AltosReplayReader extends AltosFlightReader { - Iterator iterator; - - public AltosRecord read() { - if (iterator.hasNext()) - return iterator.next(); - return null; - } - - public void close (boolean interrupted) { - } - - void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > Altos.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - } - - public AltosReplayReader(Iterator in_iterator, String in_name) { - iterator = in_iterator; - name = in_name; - } -} diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java deleted file mode 100644 index 55056b5e..00000000 --- a/ao-tools/altosui/AltosRomconfig.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -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; - } -} diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java deleted file mode 100644 index e1dc974e..00000000 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; - -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; - } -} diff --git a/ao-tools/altosui/AltosSerial.java b/ao-tools/altosui/AltosSerial.java deleted file mode 100644 index b19143e5..00000000 --- a/ao-tools/altosui/AltosSerial.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Deal with TeleDongle on a serial port - */ - -package altosui; - -import java.lang.*; -import java.io.*; -import java.util.concurrent.*; -import java.util.*; - -import libaltosJNI.*; - -/* - * This class reads from the serial port and places each received - * line in a queue. Dealing with that queue is left up to other - * threads. - */ - -public class AltosSerial implements Runnable { - - static List devices_opened = Collections.synchronizedList(new LinkedList()); - - AltosDevice device; - SWIGTYPE_p_altos_file altos; - LinkedList> monitors; - LinkedBlockingQueue reply_queue; - Thread input_thread; - String line; - byte[] line_bytes; - int line_count; - boolean monitor_mode; - - public void run () { - int c; - - try { - for (;;) { - c = libaltos.altos_getchar(altos, 0); - if (Thread.interrupted()) - break; - if (c == libaltosConstants.LIBALTOS_ERROR) { - for (int e = 0; e < monitors.size(); e++) { - LinkedBlockingQueue 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_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 q = monitors.get(e); - q.put(new AltosLine (line)); - } - } else { -// System.out.printf("GOT: %s\n", line); - reply_queue.put(new AltosLine (line)); - } - line_count = 0; - line = ""; - } - } else { - 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++; - } - } - } - } catch (InterruptedException e) { - } - } - - public void flush_output() { - if (altos != null) - libaltos.altos_flush(altos); - } - - public void flush_input() { - flush_output(); - boolean got_some; - do { - try { - Thread.sleep(100); - } catch (InterruptedException ie) { - } - got_some = !reply_queue.isEmpty(); - synchronized(this) { - if (!"VERSION".startsWith(line) && - !line.startsWith("VERSION")) - line = ""; - reply_queue.clear(); - } - } while (got_some); - } - - public String get_reply() throws InterruptedException { - flush_output(); - AltosLine line = reply_queue.take(); - return line.line; - } - - public String get_reply(int timeout) throws InterruptedException { - flush_output(); - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line == null) - return null; - return line.line; - } - - public void add_monitor(LinkedBlockingQueue q) { - set_monitor(true); - monitors.add(q); - } - - public void remove_monitor(LinkedBlockingQueue q) { - monitors.remove(q); - if (monitors.isEmpty()) - set_monitor(false); - } - - public void close() { - if (altos != null) { - libaltos.altos_close(altos); - } - if (input_thread != null) { - try { - input_thread.interrupt(); - input_thread.join(); - } catch (InterruptedException e) { - } - input_thread = null; - } - if (altos != null) { - libaltos.altos_free(altos); - altos = null; - } - synchronized (devices_opened) { - devices_opened.remove(device.getPath()); - } - } - - public void putc(char c) { - if (altos != null) - libaltos.altos_putchar(altos, c); - } - - public void print(String data) { -// System.out.printf("\"%s\" ", data); - for (int i = 0; i < data.length(); i++) - putc(data.charAt(i)); - } - - public void printf(String format, Object ... arguments) { - print(String.format(format, arguments)); - } - - private void open() throws FileNotFoundException, AltosSerialInUseException { - synchronized (devices_opened) { - if (devices_opened.contains(device.getPath())) - throw new AltosSerialInUseException(device); - devices_opened.add(device.getPath()); - } - altos = libaltos.altos_open(device); - if (altos == null) { - close(); - throw new FileNotFoundException(device.toShortString()); - } - input_thread = new Thread(this); - input_thread.start(); - print("~\nE 0\n"); - set_monitor(false); - flush_output(); - } - - public void set_radio() { - set_channel(AltosPreferences.channel(device.getSerial())); - set_callsign(AltosPreferences.callsign()); - } - - public void set_channel(int 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) { - printf ("c c %s\n", callsign); - flush_output(); - } - } - - public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { - device = in_device; - line = ""; - monitor_mode = false; - monitors = new LinkedList> (); - reply_queue = new LinkedBlockingQueue (); - open(); - } -} diff --git a/ao-tools/altosui/AltosSerialInUseException.java b/ao-tools/altosui/AltosSerialInUseException.java deleted file mode 100644 index 4b108c7c..00000000 --- a/ao-tools/altosui/AltosSerialInUseException.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 libaltosJNI.*; - -public class AltosSerialInUseException extends Exception { - public altos_device device; - - public AltosSerialInUseException (altos_device in_device) { - device = in_device; - } -} diff --git a/ao-tools/altosui/AltosSerialMonitor.java b/ao-tools/altosui/AltosSerialMonitor.java deleted file mode 100644 index ad0e9295..00000000 --- a/ao-tools/altosui/AltosSerialMonitor.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 interface AltosSerialMonitor { - void data(String data); -} diff --git a/ao-tools/altosui/AltosSiteMap.java b/ao-tools/altosui/AltosSiteMap.java deleted file mode 100644 index 80970605..00000000 --- a/ao-tools/altosui/AltosSiteMap.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.event.MouseInputAdapter; -import javax.imageio.ImageIO; -import javax.swing.table.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.lang.Math; -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; - -public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { - // preferred vertical step in a tile in naut. miles - // will actually choose a step size between x and 2x, where this - // is 1.5x - static final double tile_size_nmi = 0.75; - - static final int px_size = 512; - - static final int MAX_TILE_DELTA = 100; - - private static Point2D.Double translatePoint(Point2D.Double p, - Point2D.Double d) - { - return new Point2D.Double(p.x + d.x, p.y + d.y); - } - - static class LatLng { - public double lat, lng; - public LatLng(double lat, double lng) { - this.lat = lat; - this.lng = lng; - } - } - - // based on google js - // http://maps.gstatic.com/intl/en_us/mapfiles/api-3/2/10/main.js - // search for fromLatLngToPoint and fromPointToLatLng - private static Point2D.Double pt(LatLng latlng, int zoom) { - double scale_x = 256/360.0 * Math.pow(2, zoom); - double scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - return pt(latlng, scale_x, scale_y); - } - - private static Point2D.Double pt(LatLng latlng, - double scale_x, double scale_y) - { - Point2D.Double res = new Point2D.Double(); - double e; - - res.x = latlng.lng * scale_x; - - e = Math.sin(Math.toRadians(latlng.lat)); - e = Math.max(e,-(1-1.0E-15)); - e = Math.min(e, 1-1.0E-15 ); - - res.y = 0.5*Math.log((1+e)/(1-e))*-scale_y; - return res; - } - - static private LatLng latlng(Point2D.Double pt, - double scale_x, double scale_y) - { - double lat, lng; - double rads; - - lng = pt.x/scale_x; - rads = 2 * Math.atan(Math.exp(-pt.y/scale_y)); - lat = Math.toDegrees(rads - Math.PI/2); - - return new LatLng(lat,lng); - } - - int zoom; - double scale_x, scale_y; - - private Point2D.Double pt(double lat, double lng) { - return pt(new LatLng(lat, lng), scale_x, scale_y); - } - - private LatLng latlng(double x, double y) { - return latlng(new Point2D.Double(x,y), scale_x, scale_y); - } - private LatLng latlng(Point2D.Double pt) { - return latlng(pt, scale_x, scale_y); - } - - HashMap mapTiles = new HashMap(); - Point2D.Double centre; - - private Point2D.Double tileCoordOffset(Point p) { - return new Point2D.Double(centre.x - p.x*px_size, - centre.y - p.y * px_size); - } - - private Point tileOffset(Point2D.Double p) { - return new Point((int)Math.floor((centre.x+p.x)/px_size), - (int)Math.floor((centre.y+p.y)/px_size)); - } - - private Point2D.Double getBaseLocation(double lat, double lng) { - Point2D.Double locn, north_step; - - zoom = 2; - // stupid loop structure to please Java's control flow analysis - do { - zoom++; - scale_x = 256/360.0 * Math.pow(2, zoom); - scale_y = 256/(2.0*Math.PI) * Math.pow(2, zoom); - locn = pt(lat, lng); - north_step = pt(lat+tile_size_nmi*4/3/60.0, lng); - if (locn.y - north_step.y > px_size) - break; - } while (zoom < 22); - locn.x = -px_size * Math.floor(locn.x/px_size); - locn.y = -px_size * Math.floor(locn.y/px_size); - return locn; - } - - public void reset() { - // nothing - } - - private void bgLoadMap(final AltosSiteMapTile tile, - final File pngfile, final String pngurl) - { - //System.out.printf("Loading/fetching map %s\n", pngfile); - Thread thread = new Thread() { - public void run() { - ImageIcon res; - res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); - if (res != null) { - tile.loadMap(res); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); - } - } - }; - thread.start(); - } - - public static void prefetchMaps(double lat, double lng, int w, int h) { - AltosPreferences.init(null); - - AltosSiteMap asm = new AltosSiteMap(true); - asm.centre = asm.getBaseLocation(lat, lng); - - Point2D.Double p = new Point2D.Double(); - Point2D.Double p2; - int dx = -w/2, dy = -h/2; - for (int y = dy; y < h+dy; y++) { - for (int x = dx; x < w+dx; x++) { - LatLng map_latlng = asm.latlng( - -asm.centre.x + x*px_size + px_size/2, - -asm.centre.y + y*px_size + px_size/2); - File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); - if (pngfile.exists()) { - System.out.printf("Already have %s\n", pngfile); - } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { - System.out.printf("Fetched map %s\n", pngfile); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); - } - } - } - } - - private void initMap(AltosSiteMapTile tile, Point offset) { - Point2D.Double coord = tileCoordOffset(offset); - - LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); - - File pngfile = MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng); - bgLoadMap(tile, pngfile, pngurl); - } - - private void initMaps(double lat, double lng) { - centre = getBaseLocation(lat, lng); - - for (Point k : mapTiles.keySet()) { - initMap(mapTiles.get(k), k); - } - } - - private File MapFile(double lat, double lng) { - char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; - if (lat < 0) lat = -lat; - if (lng < 0) lng = -lng; - return new File(AltosPreferences.logdir(), - String.format("map-%c%.6f,%c%.6f-%d.png", - chlat, lat, chlng, lng, zoom)); - } - - private String MapURL(double lat, double lng) { - return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); - } - - boolean initialised = false; - Point2D.Double last_pt = null; - int last_state = -1; - public void show(final AltosState state, final int crc_errors) { - // if insufficient gps data, nothing to update - if (state.gps == null) - return; - if (state.pad_lat == 0 && state.pad_lon == 0) - return; - if (!state.gps.locked) { - if (state.gps.nsat < 4) - return; - } - - if (!initialised) { - initMaps(state.pad_lat, state.pad_lon); - initialised = true; - } - - final Point2D.Double pt = pt(state.gps.lat, state.gps.lon); - if (last_pt == pt && last_state == state.state) - return; - - if (last_pt == null) { - last_pt = pt; - } - boolean in_any = false; - for (Point offset : mapTiles.keySet()) { - AltosSiteMapTile tile = mapTiles.get(offset); - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - tile.show(state, crc_errors, lref, ref); - if (0 <= ref.x && ref.x < px_size) - if (0 <= ref.y && ref.y < px_size) - in_any = true; - } - - Point offset = tileOffset(pt); - if (!in_any) { - Point2D.Double ref, lref; - ref = translatePoint(pt, tileCoordOffset(offset)); - lref = translatePoint(last_pt, tileCoordOffset(offset)); - - AltosSiteMapTile tile = createTile(offset); - tile.show(state, crc_errors, lref, ref); - initMap(tile, offset); - finishTileLater(tile, offset); - } - - scrollRocketToVisible(pt); - - if (offset != tileOffset(last_pt)) { - ensureTilesAround(offset); - } - - last_pt = pt; - last_state = state.state; - } - - private AltosSiteMapTile createTile(Point offset) { - AltosSiteMapTile tile = new AltosSiteMapTile(px_size); - mapTiles.put(offset, tile); - return tile; - } - private void finishTileLater(final AltosSiteMapTile tile, - final Point offset) - { - SwingUtilities.invokeLater( new Runnable() { - public void run() { - addTileAt(tile, offset); - } - } ); - } - - private void ensureTilesAround(Point base_offset) { - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - Point offset = new Point(base_offset.x + x, base_offset.y + y); - if (mapTiles.containsKey(offset)) - continue; - AltosSiteMapTile tile = createTile(offset); - initMap(tile, offset); - finishTileLater(tile, offset); - } - } - } - - private Point topleft = new Point(0,0); - private void scrollRocketToVisible(Point2D.Double pt) { - Rectangle r = comp.getVisibleRect(); - Point2D.Double copt = translatePoint(pt, tileCoordOffset(topleft)); - int dx = (int)copt.x - r.width/2 - r.x; - int dy = (int)copt.y - r.height/2 - r.y; - if (Math.abs(dx) > r.width/4 || Math.abs(dy) > r.height/4) { - r.x += dx; - r.y += dy; - comp.scrollRectToVisible(r); - } - } - - private void addTileAt(AltosSiteMapTile tile, Point offset) { - if (Math.abs(offset.x) >= MAX_TILE_DELTA || - Math.abs(offset.y) >= MAX_TILE_DELTA) - { - System.out.printf("Rocket too far away from pad (tile %d,%d)\n", - offset.x, offset.y); - return; - } - - boolean review = false; - Rectangle r = comp.getVisibleRect(); - if (offset.x < topleft.x) { - r.x += (topleft.x - offset.x) * px_size; - topleft.x = offset.x; - review = true; - } - if (offset.y < topleft.y) { - r.y += (topleft.y - offset.y) * px_size; - topleft.y = offset.y; - review = true; - } - GridBagConstraints c = new GridBagConstraints(); - c.anchor = GridBagConstraints.CENTER; - c.fill = GridBagConstraints.BOTH; - // put some space between the map tiles, debugging only - // c.insets = new Insets(5, 5, 5, 5); - - c.gridx = offset.x + MAX_TILE_DELTA; - c.gridy = offset.y + MAX_TILE_DELTA; - layout.setConstraints(tile, c); - - comp.add(tile); - if (review) { - comp.scrollRectToVisible(r); - } - } - - private AltosSiteMap(boolean knowWhatYouAreDoing) { - if (!knowWhatYouAreDoing) { - throw new RuntimeException("Arggh."); - } - } - - JComponent comp = new JComponent() { }; - private GridBagLayout layout = new GridBagLayout(); - - public AltosSiteMap() { - GrabNDrag scroller = new GrabNDrag(comp); - - comp.setLayout(layout); - - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { - Point offset = new Point(x, y); - AltosSiteMapTile t = createTile(offset); - addTileAt(t, offset); - } - } - setViewportView(comp); - setPreferredSize(new Dimension(500,200)); - } -} diff --git a/ao-tools/altosui/AltosSiteMapCache.java b/ao-tools/altosui/AltosSiteMapCache.java deleted file mode 100644 index 2e62cc45..00000000 --- a/ao-tools/altosui/AltosSiteMapCache.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.imageio.ImageIO; -import javax.swing.table.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.net.URL; -import java.net.URLConnection; - -public class AltosSiteMapCache extends JLabel { - public static boolean fetchMap(File file, String url) { - URL u; - - try { - u = new URL(url); - } catch (java.net.MalformedURLException e) { - return false; - } - - byte[] data; - try { - URLConnection uc = u.openConnection(); - int contentLength = uc.getContentLength(); - InputStream in = new BufferedInputStream(uc.getInputStream()); - int bytesRead = 0; - int offset = 0; - data = new byte[contentLength]; - while (offset < contentLength) { - bytesRead = in.read(data, offset, data.length - offset); - if (bytesRead == -1) - break; - offset += bytesRead; - } - in.close(); - - if (offset != contentLength) { - return false; - } - } catch (IOException e) { - return false; - } - - try { - FileOutputStream out = new FileOutputStream(file); - out.write(data); - out.flush(); - out.close(); - } catch (FileNotFoundException e) { - return false; - } catch (IOException e) { - if (file.exists()) { - file.delete(); - } - return false; - } - return true; - } - - public static ImageIcon fetchAndLoadMap(File pngfile, String url) { - if (!pngfile.exists()) { - if (!fetchMap(pngfile, url)) { - return null; - } - } - return loadMap(pngfile, url); - } - - public static ImageIcon loadMap(File pngfile, String url) { - if (!pngfile.exists()) { - return null; - } - - try { - return new ImageIcon(ImageIO.read(pngfile)); - } catch (IOException e) { - System.out.printf("# IO error trying to load %s\n", pngfile); - return null; - } - } -} diff --git a/ao-tools/altosui/AltosSiteMapTile.java b/ao-tools/altosui/AltosSiteMapTile.java deleted file mode 100644 index 8301f42b..00000000 --- a/ao-tools/altosui/AltosSiteMapTile.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.imageio.ImageIO; -import javax.swing.table.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.lang.Math; -import java.awt.geom.Point2D; -import java.awt.geom.Line2D; - -public class AltosSiteMapTile extends JLayeredPane { - JLabel mapLabel; - JLabel draw; - Graphics2D g2d; - - public void loadMap(ImageIcon icn) { - mapLabel.setIcon(icn); - } - - static Color stateColors[] = { - Color.WHITE, // startup - Color.WHITE, // idle - Color.WHITE, // pad - Color.RED, // boost - Color.PINK, // fast - Color.YELLOW, // coast - Color.CYAN, // drogue - Color.BLUE, // main - Color.BLACK // landed - }; - - private boolean drawn_landed_circle = false; - private boolean drawn_boost_circle = false; - public synchronized void show(AltosState state, int crc_errors, - Point2D.Double last_pt, Point2D.Double pt) - { - if (0 <= state.state && state.state < stateColors.length) { - g2d.setColor(stateColors[state.state]); - } - g2d.draw(new Line2D.Double(last_pt, pt)); - - if (state.state == 3 && !drawn_boost_circle) { - drawn_boost_circle = true; - g2d.setColor(Color.RED); - g2d.drawOval((int)last_pt.x-5, (int)last_pt.y-5, 10, 10); - g2d.drawOval((int)last_pt.x-20, (int)last_pt.y-20, 40, 40); - g2d.drawOval((int)last_pt.x-35, (int)last_pt.y-35, 70, 70); - } - if (state.state == 8 && !drawn_landed_circle) { - drawn_landed_circle = true; - g2d.setColor(Color.BLACK); - g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); - g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); - g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); - } - - repaint(); - } - - public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { - BufferedImage img = new BufferedImage(px_size, px_size, - BufferedImage.TYPE_INT_ARGB); - Graphics2D g = img.createGraphics(); - g.setColor(c); - g.fillRect(0, 0, px_size, px_size); - l.setIcon(new ImageIcon(img)); - return g; - } - - public AltosSiteMapTile(int px_size) { - setPreferredSize(new Dimension(px_size, px_size)); - - mapLabel = new JLabel(); - fillLabel(mapLabel, Color.GRAY, px_size); - mapLabel.setOpaque(true); - mapLabel.setBounds(0, 0, px_size, px_size); - add(mapLabel, new Integer(0)); - - draw = new JLabel(); - g2d = fillLabel(draw, new Color(127, 127, 127, 0), px_size); - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, - RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); - draw.setBounds(0, 0, px_size, px_size); - draw.setOpaque(false); - - add(draw, new Integer(1)); - } -} diff --git a/ao-tools/altosui/AltosState.java b/ao-tools/altosui/AltosState.java deleted file mode 100644 index ec499d5a..00000000 --- a/ao-tools/altosui/AltosState.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Track flight state from telemetry or eeprom data stream - */ - -package altosui; - -public class AltosState { - AltosRecord data; - - /* derived data */ - - long report_time; - - double time_change; - int tick; - - int state; - boolean landed; - boolean ascent; /* going up? */ - - double ground_altitude; - double height; - double speed; - double acceleration; - double battery; - double temperature; - double main_sense; - double drogue_sense; - double baro_speed; - - double max_height; - double max_acceleration; - double max_speed; - - AltosGPS gps; - - double pad_lat; - double pad_lon; - double pad_alt; - - static final int MIN_PAD_SAMPLES = 10; - - int npad; - int ngps; - int gps_waiting; - boolean gps_ready; - - AltosGreatCircle from_pad; - double elevation; /* from pad */ - double range; /* total distance */ - - double gps_height; - - int speak_tick; - double speak_altitude; - - - void init (AltosRecord cur, AltosState prev_state) { - int i; - AltosRecord prev; - - data = cur; - - ground_altitude = data.ground_altitude(); - height = data.filtered_altitude() - ground_altitude; - - report_time = System.currentTimeMillis(); - - acceleration = data.acceleration(); - speed = data.accel_speed(); - temperature = data.temperature(); - drogue_sense = data.drogue_voltage(); - main_sense = data.main_voltage(); - battery = data.battery_voltage(); - tick = data.tick; - state = data.state; - - if (prev_state != null) { - - /* Preserve any existing gps data */ - npad = prev_state.npad; - ngps = prev_state.ngps; - gps = prev_state.gps; - pad_lat = prev_state.pad_lat; - pad_lon = prev_state.pad_lon; - pad_alt = prev_state.pad_alt; - max_height = prev_state.max_height; - max_acceleration = prev_state.max_acceleration; - max_speed = prev_state.max_speed; - - /* make sure the clock is monotonic */ - while (tick < prev_state.tick) - tick += 65536; - - time_change = (tick - prev_state.tick) / 100.0; - - /* compute barometric speed */ - - double height_change = height - prev_state.height; - if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; - } else { - npad = 0; - ngps = 0; - gps = null; - baro_speed = 0; - time_change = 0; - } - - if (state == Altos.ao_flight_pad) { - - /* Track consecutive 'good' gps reports, waiting for 10 of them */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) - npad++; - else - npad = 0; - - /* Average GPS data while on the pad */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { - if (ngps > 1) { - /* filter pad position */ - pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; - pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; - pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; - } else { - pad_lat = data.gps.lat; - pad_lon = data.gps.lon; - pad_alt = data.gps.alt; - } - ngps++; - } - } - - gps_waiting = MIN_PAD_SAMPLES - npad; - if (gps_waiting < 0) - gps_waiting = 0; - - gps_ready = gps_waiting == 0; - - ascent = (Altos.ao_flight_boost <= state && - state <= Altos.ao_flight_coast); - - /* Only look at accelerometer data on the way up */ - if (ascent && acceleration > max_acceleration) - max_acceleration = acceleration; - if (ascent && speed > max_speed) - max_speed = speed; - - if (height > max_height) - max_height = height; - if (data.gps != null) { - if (gps == null || !gps.locked || data.gps.locked) - gps = data.gps; - if (ngps > 0 && gps.locked) { - from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); - } - } - elevation = 0; - range = -1; - if (ngps > 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; - } - } - - public AltosState(AltosRecord cur) { - init(cur, null); - } - - public AltosState (AltosRecord cur, AltosState prev) { - init(cur, prev); - } -} diff --git a/ao-tools/altosui/AltosTelemetry.java b/ao-tools/altosui/AltosTelemetry.java deleted file mode 100644 index bdb6466a..00000000 --- a/ao-tools/altosui/AltosTelemetry.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -/* - * Telemetry data contents - */ - - -/* - * The telemetry data stream is a bit of a mess at present, with no consistent - * formatting. In particular, the GPS data is formatted for viewing instead of parsing. - * However, the key feature is that every telemetry line contains all of the information - * necessary to describe the current rocket state, including the calibration values - * for accelerometer and barometer. - * - * GPS unlocked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ - * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ - * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 - * - * GPS locked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ - * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ - * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ - * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ - * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ - * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 - */ - -public class AltosTelemetry extends AltosRecord { - public AltosTelemetry(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; - - 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++]); - - 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++], "STATE"); - state = Altos.state(words[i++]); - - tick = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a:"); - accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "p:"); - pres = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "t:"); - temp = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "v:"); - batt = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "d:"); - drogue = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "m:"); - main = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fa:"); - flight_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "ga:"); - ground_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fv:"); - flight_vel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fp:"); - flight_pres = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "gp:"); - ground_pres = 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++]); - } else { - accel_plus_g = ground_accel; - accel_minus_g = ground_accel + 530; - } - - gps = new AltosGPS(words, i, version); - } -} diff --git a/ao-tools/altosui/AltosTelemetryIterable.java b/ao-tools/altosui/AltosTelemetryIterable.java deleted file mode 100644 index a71ab872..00000000 --- a/ao-tools/altosui/AltosTelemetryIterable.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; - -public class AltosTelemetryIterable extends AltosRecordIterable { - LinkedList records; - - public Iterator iterator () { - return records.iterator(); - } - - public AltosTelemetryIterable (FileInputStream input) { - boolean saw_boost = false; - int current_tick = 0; - int boost_tick = 0; - - records = new LinkedList (); - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) { - break; - } - try { - AltosTelemetry record = new AltosTelemetry(line); - if (record == null) - break; - if (records.isEmpty()) { - current_tick = record.tick; - } else { - int tick = record.tick | (current_tick & ~ 0xffff); - if (tick < current_tick - 0x1000) - tick += 0x10000; - current_tick = tick; - record.tick = current_tick; - } - 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) { - System.out.printf("io exception\n"); - } - - /* adjust all tick counts to be relative to boost time */ - for (AltosRecord r : this) - r.time = (r.tick - boost_tick) / 100.0; - - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java deleted file mode 100644 index 6c5a9397..00000000 --- a/ao-tools/altosui/AltosTelemetryReader.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.io.*; -import java.util.concurrent.*; - -class AltosTelemetryReader extends AltosFlightReader { - AltosDevice device; - AltosSerial serial; - AltosLog log; - - LinkedBlockingQueue telem; - - 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(boolean interrupted) { - serial.remove_monitor(telem); - log.close(); - serial.close(); - } - - void set_channel(int channel) { - serial.set_channel(channel); - AltosPreferences.set_channel(device.getSerial(), channel); - } - - public AltosTelemetryReader (AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, IOException { - device = in_device; - serial = new AltosSerial(device); - log = new AltosLog(serial); - name = device.toShortString(); - - telem = new LinkedBlockingQueue(); - serial.set_radio(); - serial.add_monitor(telem); - } -} diff --git a/ao-tools/altosui/AltosUI.app/Contents/Info.plist b/ao-tools/altosui/AltosUI.app/Contents/Info.plist deleted file mode 100644 index 97b1b59c..00000000 --- a/ao-tools/altosui/AltosUI.app/Contents/Info.plist +++ /dev/null @@ -1,38 +0,0 @@ - - - - - CFBundleName - altosui - CFBundleVersion - 100.0 - CFBundleAllowMixedLocalizations - true - CFBundleExecutable - JavaApplicationStub - CFBundleDevelopmentRegion - English - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleGetInfoString - AltOS UI version 0.7 - CFBundleInfoDictionaryVersion - 6.0 - CFBundleIconFile - AltosUIIcon.icns - Java - - MainClass - altosui.AltosUI - JVMVersion - 1.5+ - ClassPath - - $JAVAROOT/altosui.jar - $JAVAROOT/freetts.jar - - - - diff --git a/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub b/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub deleted file mode 100755 index c661d3e1..00000000 Binary files a/ao-tools/altosui/AltosUI.app/Contents/MacOS/JavaApplicationStub and /dev/null differ diff --git a/ao-tools/altosui/AltosUI.app/Contents/PkgInfo b/ao-tools/altosui/AltosUI.app/Contents/PkgInfo deleted file mode 100644 index 8a43480f..00000000 --- a/ao-tools/altosui/AltosUI.app/Contents/PkgInfo +++ /dev/null @@ -1 +0,0 @@ -APPLAM.O diff --git a/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns b/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns deleted file mode 100644 index fe49f362..00000000 Binary files a/ao-tools/altosui/AltosUI.app/Contents/Resources/AltosUIIcon.icns and /dev/null differ diff --git a/ao-tools/altosui/AltosUI.java b/ao-tools/altosui/AltosUI.java deleted file mode 100644 index 94c4dd2a..00000000 --- a/ao-tools/altosui/AltosUI.java +++ /dev/null @@ -1,405 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 libaltosJNI.*; - -public class AltosUI extends JFrame { - public AltosVoice voice = new AltosVoice(); - - public static boolean load_library(Frame frame) { - if (!AltosDevice.load_library()) { - JOptionPane.showMessageDialog(frame, - String.format("No AltOS library in \"%s\"", - System.getProperty("java.library.path","")), - "Cannot load device access library", - JOptionPane.ERROR_MESSAGE); - return false; - } - return true; - } - - void telemetry_window(AltosDevice device) { - try { - AltosFlightReader reader = new AltosTelemetryReader(device); - if (reader != null) - new AltosFlightUI(voice, reader, device.getSerial()); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(AltosUI.this, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(AltosUI.this, - device.toShortString(), - "Unkonwn I/O error", - JOptionPane.ERROR_MESSAGE); - } - } - - Container pane; - GridBagLayout gridbag; - - JButton addButton(int x, int y, String label) { - GridBagConstraints c; - JButton b; - - c = new GridBagConstraints(); - c.gridx = x; c.gridy = y; - c.fill = GridBagConstraints.BOTH; - c.weightx = 1; - c.weighty = 1; - b = new JButton(label); - - Dimension ps = b.getPreferredSize(); - - gridbag.setConstraints(b, c); - add(b, c); - return b; - } - - public AltosUI() { - - load_library(null); - - java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); - if (imgURL != null) - setIconImage(new ImageIcon(imgURL).getImage()); - - AltosPreferences.init(this); - - pane = getContentPane(); - gridbag = new GridBagLayout(); - pane.setLayout(gridbag); - - JButton b; - - b = addButton(0, 0, "Monitor Flight"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConnectToDevice(); - } - }); - b = addButton(1, 0, "Save Flight Data"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - SaveFlightData(); - } - }); - b = addButton(2, 0, "Replay Flight"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - Replay(); - } - }); - b = addButton(3, 0, "Graph Data"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - GraphData(); - } - }); - b = addButton(4, 0, "Export Data"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ExportData(); - } - }); - b = addButton(0, 1, "Configure TeleMetrum"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConfigureTeleMetrum(); - } - }); - - b = addButton(1, 1, "Configure AltosUI"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - ConfigureAltosUI(); - } - }); - - b = addButton(2, 1, "Flash Image"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - FlashImage(); - } - }); - - b = addButton(3, 1, "Fire Igniter"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - FireIgniter(); - } - }); - - b = addButton(4, 1, "Quit"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - System.exit(0); - } - }); - - setTitle("AltOS"); - - pane.doLayout(); - pane.validate(); - - doLayout(); - validate(); - - setVisible(true); - - Insets i = getInsets(); - Dimension ps = rootPane.getPreferredSize(); - ps.width += i.left + i.right; - ps.height += i.top + i.bottom; - setPreferredSize(ps); - setSize(ps); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - System.exit(0); - } - }); - } - - private void ConnectToDevice() { - AltosDevice device = AltosDeviceDialog.show(AltosUI.this, - AltosDevice.product_basestation); - - if (device != null) - telemetry_window(device); - } - - void ConfigureCallsign() { - String result; - result = JOptionPane.showInputDialog(AltosUI.this, - "Configure Callsign", - AltosPreferences.callsign()); - if (result != null) - AltosPreferences.set_callsign(result); - } - - void ConfigureTeleMetrum() { - new AltosConfig(AltosUI.this); - } - - void FlashImage() { - new AltosFlashUI(AltosUI.this); - } - - void FireIgniter() { - new AltosIgniteUI(AltosUI.this); - } - - /* - * Replay a flight from telemetry data - */ - private void Replay() { - AltosDataChooser chooser = new AltosDataChooser( - AltosUI.this); - - AltosRecordIterable iterable = chooser.runDialog(); - if (iterable != null) { - AltosFlightReader reader = new AltosReplayReader(iterable.iterator(), - chooser.filename()); - new AltosFlightUI(voice, reader); - } - } - - /* Connect to TeleMetrum, either directly or through - * a TeleDongle over the packet link - */ - private void SaveFlightData() { - 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() { - AltosDataChooser chooser; - chooser = new AltosDataChooser(this); - AltosRecordIterable record_reader = chooser.runDialog(); - if (record_reader == null) - return; - new AltosCSVUI(AltosUI.this, record_reader, chooser.file()); - } - - /* Load a flight log CSV file and display a pretty graph. - */ - - private void GraphData() { - AltosDataChooser chooser; - chooser = new AltosDataChooser(this); - AltosRecordIterable record_reader = chooser.runDialog(); - if (record_reader == null) - return; - new AltosGraphUI(record_reader); - } - - private void ConfigureAltosUI() { - new AltosConfigureUI(AltosUI.this, voice); - } - - static AltosRecordIterable open_logfile(String filename) { - File file = new File (filename); - try { - FileInputStream in; - - in = new FileInputStream(file); - if (filename.endsWith("eeprom")) - return new AltosEepromIterable(in); - else - return new AltosTelemetryIterable(in); - } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); - return null; - } - } - - static AltosWriter 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 AltosWriter open_kml(String filename) { - File file = new File (filename); - try { - return new AltosKML(file); - } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); - return null; - } - } - - static final int process_csv = 1; - static final int process_kml = 2; - - static void process_file(String input, int process) { - AltosRecordIterable iterable = open_logfile(input); - if (iterable == null) - return; - if (process == 0) - process = process_csv; - if ((process & process_csv) != 0) { - String output = Altos.replace_extension(input,".csv"); - System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); - if (input.equals(output)) { - System.out.printf("Not processing '%s'\n", input); - } else { - AltosWriter writer = open_csv(output); - if (writer != null) { - writer.write(iterable); - writer.close(); - } - } - } - if ((process & process_kml) != 0) { - String output = Altos.replace_extension(input,".kml"); - System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); - if (input.equals(output)) { - System.out.printf("Not processing '%s'\n", input); - } else { - AltosWriter writer = open_kml(output); - if (writer == null) - return; - writer.write(iterable); - writer.close(); - } - } - } - - public static void main(final String[] args) { - int process = 0; - /* Handle batch-mode */ - if (args.length == 1 && args[0].equals("--help")) { - System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); - System.out.printf(" Options:\n"); - System.out.printf(" --fetchmaps \tpre-fetch maps for site map view\n"); - System.out.printf(" --replay \t\trelive the glory of past flights \n"); - System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n"); - System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n"); - } else if (args.length == 3 && args[0].equals("--fetchmaps")) { - double lat = Double.parseDouble(args[1]); - double lon = Double.parseDouble(args[2]); - AltosSiteMap.prefetchMaps(lat, lon, 5, 5); - } else if (args.length == 2 && args[0].equals("--replay")) { - String filename = args[1]; - FileInputStream in; - try { - in = new FileInputStream(filename); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); - return; - } - AltosRecordIterable recs; - AltosReplayReader reader; - if (filename.endsWith("eeprom")) { - recs = new AltosEepromIterable(in); - } else { - recs = new AltosTelemetryIterable(in); - } - reader = new AltosReplayReader(recs.iterator(), filename); - AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); - flight_ui.set_exit_on_close(); - return; - } else if (args.length > 0) { - for (int i = 0; i < args.length; i++) { - if (args[i].equals("--kml")) - process |= process_kml; - else if (args[i].equals("--csv")) - process |= process_csv; - else - process_file(args[i], process); - } - } else { - AltosUI altosui = new AltosUI(); - altosui.setVisible(true); - - AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation); - for (int i = 0; i < devices.length; i++) - altosui.telemetry_window(devices[i]); - } - } -} diff --git a/ao-tools/altosui/AltosVoice.java b/ao-tools/altosui/AltosVoice.java deleted file mode 100644 index ac13ee14..00000000 --- a/ao-tools/altosui/AltosVoice.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 com.sun.speech.freetts.Voice; -import com.sun.speech.freetts.VoiceManager; -import com.sun.speech.freetts.audio.JavaClipAudioPlayer; -import java.util.concurrent.LinkedBlockingQueue; - -public class AltosVoice implements Runnable { - VoiceManager voice_manager; - Voice voice; - LinkedBlockingQueue phrases; - Thread thread; - boolean busy; - - final static String voice_name = "kevin16"; - - public void run() { - try { - 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) { - synchronized(this) { - busy = true; - phrases.put(s); - } - } - } catch (InterruptedException e) { - } - } - - public void speak(String s) { - if (AltosPreferences.voice()) - speak_always(s); - } - - public void speak(String format, Object... parameters) { - speak(String.format(format, parameters)); - } - - public AltosVoice () { - busy = false; - voice_manager = VoiceManager.getInstance(); - voice = voice_manager.getVoice(voice_name); - if (voice != null) { - voice.allocate(); - phrases = new LinkedBlockingQueue (); - thread = new Thread(this); - thread.start(); - } else { - System.out.printf("Voice manager failed to open %s\n", voice_name); - Voice[] voices = voice_manager.getVoices(); - System.out.printf("Available voices:\n"); - for (int i = 0; i < voices.length; i++) { - System.out.println(" " + voices[i].getName() - + " (" + voices[i].getDomain() + " domain)"); - } - } - } -} diff --git a/ao-tools/altosui/AltosWriter.java b/ao-tools/altosui/AltosWriter.java deleted file mode 100644 index a172dff0..00000000 --- a/ao-tools/altosui/AltosWriter.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.*; - -public interface AltosWriter { - - public void write(AltosRecord record); - - public void write(AltosRecordIterable iterable); - - public void close(); -} diff --git a/ao-tools/altosui/GrabNDrag.java b/ao-tools/altosui/GrabNDrag.java deleted file mode 100644 index e6b87b58..00000000 --- a/ao-tools/altosui/GrabNDrag.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2010 Anthony Towns - * - * 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.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.event.MouseInputAdapter; -import javax.imageio.ImageIO; -import javax.swing.table.*; -import java.io.*; -import java.util.*; -import java.text.*; - -class GrabNDrag extends MouseInputAdapter { - private JComponent scroll; - private Point startPt = new Point(); - - public GrabNDrag(JComponent scroll) { - this.scroll = scroll; - scroll.addMouseMotionListener(this); - scroll.addMouseListener(this); - scroll.setAutoscrolls(true); - } - - public void mousePressed(MouseEvent e) { - startPt.setLocation(e.getPoint()); - } - public void mouseDragged(MouseEvent e) { - int xd = e.getX() - startPt.x; - int yd = e.getY() - startPt.y; - - Rectangle r = scroll.getVisibleRect(); - r.x -= xd; - r.y -= yd; - scroll.scrollRectToVisible(r); - } -} diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi deleted file mode 100644 index 3ed821eb..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Example.nsi +++ /dev/null @@ -1,84 +0,0 @@ -# -# InstDrv Example, (c) 2003 Jan Kiszka (Jan Kiszka@web.de) -# - -Name "InstDrv.dll test" - -OutFile "InstDrv-Test.exe" - -ShowInstDetails show - -ComponentText "InstDrv Plugin Usage Example" - -Page components -Page instfiles - -Section "Install a Driver" InstDriver - InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" - Pop $0 - DetailPrint "InitDriverSetup: $0" - - InstDrv::DeleteOemInfFiles /NOUNLOAD - Pop $0 - DetailPrint "DeleteOemInfFiles: $0" - StrCmp $0 "00000000" PrintInfNames ContInst1 - - PrintInfNames: - Pop $0 - DetailPrint "Deleted $0" - Pop $0 - DetailPrint "Deleted $0" - - ContInst1: - InstDrv::CreateDevice /NOUNLOAD - Pop $0 - DetailPrint "CreateDevice: $0" - - SetOutPath $TEMP - File "ircomm2k.inf" - File "ircomm2k.sys" - - InstDrv::InstallDriver /NOUNLOAD "$TEMP\ircomm2k.inf" - Pop $0 - DetailPrint "InstallDriver: $0" - StrCmp $0 "00000000" PrintReboot ContInst2 - - PrintReboot: - Pop $0 - DetailPrint "Reboot: $0" - - ContInst2: - InstDrv::CountDevices - Pop $0 - DetailPrint "CountDevices: $0" -SectionEnd - -Section "Uninstall the driver again" UninstDriver - InstDrv::InitDriverSetup /NOUNLOAD "{4d36e978-e325-11ce-bfc1-08002be10318}" "IrCOMM2k" - Pop $0 - DetailPrint "InitDriverSetup: $0" - - InstDrv::DeleteOemInfFiles /NOUNLOAD - Pop $0 - DetailPrint "DeleteOemInfFiles: $0" - StrCmp $0 "00000000" PrintInfNames ContUninst1 - - PrintInfNames: - Pop $0 - DetailPrint "Deleted $0" - Pop $0 - DetailPrint "Deleted $0" - - ContUninst1: - InstDrv::RemoveAllDevices - Pop $0 - DetailPrint "RemoveAllDevices: $0" - StrCmp $0 "00000000" PrintReboot ContUninst2 - - PrintReboot: - Pop $0 - DetailPrint "Reboot: $0" - - ContUninst2: - Delete "$SYSDIR\system32\ircomm2k.sys" -SectionEnd \ No newline at end of file diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe deleted file mode 100644 index 615bae15..00000000 Binary files a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv-Test.exe and /dev/null differ diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c deleted file mode 100644 index efe866e9..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - -InstDrv.dll - Installs or Removes Device Drivers - -Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute -it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment in the - product documentation would be appreciated but is not required. -2. Altered versions must be plainly marked as such, - and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any distribution. - -*/ - - -#include -#include -#include -#include "../exdll/exdll.h" - - -char paramBuf[1024]; -GUID devClass; -char hwIdBuf[1024]; -int initialized = 0; - - - -void* memset(void* dst, int val, unsigned int len) -{ - while (len-- > 0) - *((char *)dst)++ = val; - - return NULL; -} - - - -void* memcpy(void* dst, const void* src, unsigned int len) -{ - while (len-- > 0) - *((char *)dst)++ = *((char *)src)++; - - return NULL; -} - - - -int HexCharToInt(char c) -{ - if ((c >= '0') && (c <= '9')) - return c - '0'; - else if ((c >= 'a') && (c <= 'f')) - return c - 'a' + 10; - else if ((c >= 'A') && (c <= 'F')) - return c - 'A' + 10; - else - return -1; -} - - - -BOOLEAN HexStringToUInt(char* str, int width, void* valBuf) -{ - int i, val; - - - for (i = width - 4; i >= 0; i -= 4) - { - val = HexCharToInt(*str++); - if (val < 0) - return FALSE; - *(unsigned int *)valBuf += val << i; - } - - return TRUE; -} - - - -BOOLEAN StringToGUID(char* guidStr, GUID* pGuid) -{ - int i; - - - memset(pGuid, 0, sizeof(GUID)); - - if (*guidStr++ != '{') - return FALSE; - - if (!HexStringToUInt(guidStr, 32, &pGuid->Data1)) - return FALSE; - guidStr += 8; - - if (*guidStr++ != '-') - return FALSE; - - if (!HexStringToUInt(guidStr, 16, &pGuid->Data2)) - return FALSE; - guidStr += 4; - - if (*guidStr++ != '-') - return FALSE; - - if (!HexStringToUInt(guidStr, 16, &pGuid->Data3)) - return FALSE; - guidStr += 4; - - if (*guidStr++ != '-') - return FALSE; - - for (i = 0; i < 2; i++) - { - if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) - return FALSE; - guidStr += 2; - } - - if (*guidStr++ != '-') - return FALSE; - - for (i = 2; i < 8; i++) - { - if (!HexStringToUInt(guidStr, 8, &pGuid->Data4[i])) - return FALSE; - guidStr += 2; - } - - if (*guidStr++ != '}') - return FALSE; - - return TRUE; -} - - - -DWORD FindNextDevice(HDEVINFO devInfoSet, SP_DEVINFO_DATA* pDevInfoData, DWORD* pIndex) -{ - DWORD buffersize = 0; - LPTSTR buffer = NULL; - DWORD dataType; - DWORD result; - - - while (1) - { - if (!SetupDiEnumDeviceInfo(devInfoSet, (*pIndex)++, pDevInfoData)) - { - result = GetLastError(); - break; - } - - GetDeviceRegistryProperty: - if (!SetupDiGetDeviceRegistryProperty(devInfoSet, pDevInfoData, SPDRP_HARDWAREID, - &dataType, (PBYTE)buffer, buffersize, - &buffersize)) - { - result = GetLastError(); - - if (result == ERROR_INSUFFICIENT_BUFFER) - { - if (buffer != NULL) - LocalFree(buffer); - - buffer = (LPTSTR)LocalAlloc(LPTR, buffersize); - - if (buffer == NULL) - break; - - goto GetDeviceRegistryProperty; - } - else if (result == ERROR_INVALID_DATA) - continue; // ignore invalid entries - else - break; // break on other errors - } - - if (lstrcmpi(buffer, hwIdBuf) == 0) - { - result = 0; - break; - } - } - - if (buffer != NULL) - LocalFree(buffer); - - return result; -} - - - -DWORD FindFirstDevice(HWND hwndParent, const GUID* pDevClass, const LPTSTR hwId, - HDEVINFO* pDevInfoSet, SP_DEVINFO_DATA* pDevInfoData, - DWORD *pIndex, DWORD flags) -{ - DWORD result; - - - *pDevInfoSet = SetupDiGetClassDevs((GUID*)pDevClass, NULL, hwndParent, flags); - if (*pDevInfoSet == INVALID_HANDLE_VALUE) - return GetLastError(); - - pDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA); - *pIndex = 0; - - result = FindNextDevice(*pDevInfoSet, pDevInfoData, pIndex); - - if (result != 0) - SetupDiDestroyDeviceInfoList(*pDevInfoSet); - - return result; -} - - - -/* - * InstDrv::InitDriverSetup devClass drvHWID - * - * devClass - GUID of the driver's device setup class - * drvHWID - Hardware ID of the supported device - * - * Return: - * result - error message, empty on success - */ -void __declspec(dllexport) InitDriverSetup(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - EXDLL_INIT(); - - /* convert class GUID */ - popstring(paramBuf); - - if (!StringToGUID(paramBuf, &devClass)) - { - popstring(paramBuf); - pushstring("Invalid GUID!"); - return; - } - - /* get hardware ID */ - memset(hwIdBuf, 0, sizeof(hwIdBuf)); - popstring(hwIdBuf); - - initialized = 1; - pushstring(""); -} - - - -/* - * InstDrv::CountDevices - * - * Return: - * result - Number of installed devices the driver supports - */ -void __declspec(dllexport) CountDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - HDEVINFO devInfoSet; - SP_DEVINFO_DATA devInfoData; - int count = 0; - char countBuf[16]; - DWORD index; - DWORD result; - - - EXDLL_INIT(); - - if (!initialized) - { - pushstring("Fatal error!"); - return; - } - - result = FindFirstDevice(hwndParent, &devClass, hwIdBuf, &devInfoSet, &devInfoData, - &index, DIGCF_PRESENT); - if (result != 0) - { - pushstring("0"); - return; - } - - do - { - count++; - } while (FindNextDevice(devInfoSet, &devInfoData, &index) == 0); - - SetupDiDestroyDeviceInfoList(devInfoSet); - - wsprintf(countBuf, "%d", count); - pushstring(countBuf); -} - - - -/* - * InstDrv::CreateDevice - * - * Return: - * result - Windows error code - */ -void __declspec(dllexport) CreateDevice(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - HDEVINFO devInfoSet; - SP_DEVINFO_DATA devInfoData; - DWORD result = 0; - char resultBuf[16]; - - - EXDLL_INIT(); - - if (!initialized) - { - pushstring("Fatal error!"); - return; - } - - devInfoSet = SetupDiCreateDeviceInfoList(&devClass, hwndParent); - if (devInfoSet == INVALID_HANDLE_VALUE) - { - wsprintf(resultBuf, "%08X", GetLastError()); - pushstring(resultBuf); - return; - } - - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - if (!SetupDiCreateDeviceInfo(devInfoSet, hwIdBuf, &devClass, NULL, - hwndParent, DICD_GENERATE_ID, &devInfoData)) - { - result = GetLastError(); - goto InstallCleanup; - } - - if (!SetupDiSetDeviceRegistryProperty(devInfoSet, &devInfoData, SPDRP_HARDWAREID, - hwIdBuf, (lstrlen(hwIdBuf)+2)*sizeof(TCHAR))) - { - result = GetLastError(); - goto InstallCleanup; - } - - if (!SetupDiCallClassInstaller(DIF_REGISTERDEVICE, devInfoSet, &devInfoData)) - result = GetLastError(); - - InstallCleanup: - SetupDiDestroyDeviceInfoList(devInfoSet); - - wsprintf(resultBuf, "%08X", result); - pushstring(resultBuf); -} - - - -/* - * InstDrv::InstallDriver infPath - * - * Return: - * result - Windows error code - * reboot - non-zero if reboot is required - */ -void __declspec(dllexport) InstallDriver(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - char resultBuf[16]; - BOOL reboot; - - - EXDLL_INIT(); - popstring(paramBuf); - - if (!initialized) - { - pushstring("Fatal error!"); - return; - } - - if (!UpdateDriverForPlugAndPlayDevices(hwndParent, hwIdBuf, paramBuf, - INSTALLFLAG_FORCE, &reboot)) - { - wsprintf(resultBuf, "%08X", GetLastError()); - pushstring(resultBuf); - } - else - { - wsprintf(resultBuf, "%d", reboot); - pushstring(resultBuf); - pushstring("00000000"); - } -} - - - -/* - * InstDrv::DeleteOemInfFiles - * - * Return: - * result - Windows error code - * oeminf - Path of the deleted devices setup file (oemXX.inf) - * oempnf - Path of the deleted devices setup file (oemXX.pnf) - */ -void __declspec(dllexport) DeleteOemInfFiles(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - HDEVINFO devInfo; - SP_DEVINFO_DATA devInfoData; - SP_DRVINFO_DATA drvInfoData; - SP_DRVINFO_DETAIL_DATA drvInfoDetail; - DWORD index; - DWORD result; - char resultBuf[16]; - - - if (!initialized) - { - pushstring("Fatal error!"); - return; - } - - result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); - if (result != 0) - goto Cleanup1; - - if (!SetupDiBuildDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER)) - { - result = GetLastError(); - goto Cleanup2; - } - - drvInfoData.cbSize = sizeof(SP_DRVINFO_DATA); - drvInfoDetail.cbSize = sizeof(SP_DRVINFO_DETAIL_DATA); - - if (!SetupDiEnumDriverInfo(devInfo, &devInfoData, SPDIT_COMPATDRIVER, 0, &drvInfoData)) - { - result = GetLastError(); - goto Cleanup3; - } - - if (!SetupDiGetDriverInfoDetail(devInfo, &devInfoData, &drvInfoData, - &drvInfoDetail, sizeof(drvInfoDetail), NULL)) - { - result = GetLastError(); - - if (result != ERROR_INSUFFICIENT_BUFFER) - goto Cleanup3; - - result = 0; - } - - pushstring(drvInfoDetail.InfFileName); - if (!DeleteFile(drvInfoDetail.InfFileName)) - result = GetLastError(); - else - { - index = lstrlen(drvInfoDetail.InfFileName); - if (index > 3) - { - lstrcpy(drvInfoDetail.InfFileName+index-3, "pnf"); - pushstring(drvInfoDetail.InfFileName); - if (!DeleteFile(drvInfoDetail.InfFileName)) - result = GetLastError(); - } - } - - Cleanup3: - SetupDiDestroyDriverInfoList(devInfo, &devInfoData, SPDIT_COMPATDRIVER); - - Cleanup2: - SetupDiDestroyDeviceInfoList(devInfo); - - Cleanup1: - wsprintf(resultBuf, "%08X", result); - pushstring(resultBuf); -} - - - -/* - * InstDrv::RemoveAllDevices - * - * Return: - * result - Windows error code - * reboot - non-zero if reboot is required - */ -void __declspec(dllexport) RemoveAllDevices(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - HDEVINFO devInfo; - SP_DEVINFO_DATA devInfoData; - DWORD index; - DWORD result; - char resultBuf[16]; - BOOL reboot = FALSE; - SP_DEVINSTALL_PARAMS instParams; - - - EXDLL_INIT(); - - if (!initialized) - { - pushstring("Fatal error!"); - return; - } - - result = FindFirstDevice(NULL, &devClass, hwIdBuf, &devInfo, &devInfoData, &index, 0); - if (result != 0) - goto Cleanup1; - - do - { - if (!SetupDiCallClassInstaller(DIF_REMOVE, devInfo, &devInfoData)) - { - result = GetLastError(); - break; - } - - instParams.cbSize = sizeof(instParams); - if (!reboot && - SetupDiGetDeviceInstallParams(devInfo, &devInfoData, &instParams) && - ((instParams.Flags & (DI_NEEDRESTART|DI_NEEDREBOOT)) != 0)) - { - reboot = TRUE; - } - - result = FindNextDevice(devInfo, &devInfoData, &index); - } while (result == 0); - - SetupDiDestroyDeviceInfoList(devInfo); - - Cleanup1: - if ((result == 0) || (result == ERROR_NO_MORE_ITEMS)) - { - wsprintf(resultBuf, "%d", reboot); - pushstring(resultBuf); - pushstring("00000000"); - } - else - { - wsprintf(resultBuf, "%08X", result); - pushstring(resultBuf); - } -} - - - -/* - * InstDrv::StartSystemService serviceName - * - * Return: - * result - Windows error code - */ -void __declspec(dllexport) StartSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - SC_HANDLE managerHndl; - SC_HANDLE svcHndl; - SERVICE_STATUS svcStatus; - DWORD oldCheckPoint; - DWORD result; - char resultBuf[16]; - - - EXDLL_INIT(); - popstring(paramBuf); - - managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (managerHndl == NULL) - { - result = GetLastError(); - goto Cleanup1; - } - - svcHndl = OpenService(managerHndl, paramBuf, SERVICE_START | SERVICE_QUERY_STATUS); - if (svcHndl == NULL) - { - result = GetLastError(); - goto Cleanup2; - } - - if (!StartService(svcHndl, 0, NULL) || !QueryServiceStatus(svcHndl, &svcStatus)) - { - result = GetLastError(); - goto Cleanup3; - } - - while (svcStatus.dwCurrentState == SERVICE_START_PENDING) - { - oldCheckPoint = svcStatus.dwCheckPoint; - - Sleep(svcStatus.dwWaitHint); - - if (!QueryServiceStatus(svcHndl, &svcStatus)) - { - result = GetLastError(); - break; - } - - if (oldCheckPoint >= svcStatus.dwCheckPoint) - { - if ((svcStatus.dwCurrentState == SERVICE_STOPPED) && - (svcStatus.dwWin32ExitCode != 0)) - result = svcStatus.dwWin32ExitCode; - else - result = ERROR_SERVICE_REQUEST_TIMEOUT; - } - } - - if (svcStatus.dwCurrentState == SERVICE_RUNNING) - result = 0; - - Cleanup3: - CloseServiceHandle(svcHndl); - - Cleanup2: - CloseServiceHandle(managerHndl); - - Cleanup1: - wsprintf(resultBuf, "%08X", result); - pushstring(resultBuf); -} - - - -/* - * InstDrv::StopSystemService serviceName - * - * Return: - * result - Windows error code - */ -void __declspec(dllexport) StopSystemService(HWND hwndParent, int string_size, char *variables, stack_t **stacktop) -{ - SC_HANDLE managerHndl; - SC_HANDLE svcHndl; - SERVICE_STATUS svcStatus; - DWORD oldCheckPoint; - DWORD result; - char resultBuf[16]; - - - EXDLL_INIT(); - popstring(paramBuf); - - managerHndl = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); - if (managerHndl == NULL) - { - result = GetLastError(); - goto Cleanup1; - } - - svcHndl = OpenService(managerHndl, paramBuf, SERVICE_STOP | SERVICE_QUERY_STATUS); - if (svcHndl == NULL) - { - result = GetLastError(); - goto Cleanup2; - } - - if (!ControlService(svcHndl, SERVICE_CONTROL_STOP, &svcStatus)) - { - result = GetLastError(); - goto Cleanup3; - } - - while (svcStatus.dwCurrentState == SERVICE_STOP_PENDING) - { - oldCheckPoint = svcStatus.dwCheckPoint; - - Sleep(svcStatus.dwWaitHint); - - if (!QueryServiceStatus(svcHndl, &svcStatus)) - { - result = GetLastError(); - break; - } - - if (oldCheckPoint >= svcStatus.dwCheckPoint) - { - result = ERROR_SERVICE_REQUEST_TIMEOUT; - break; - } - } - - if (svcStatus.dwCurrentState == SERVICE_STOPPED) - result = 0; - - Cleanup3: - CloseServiceHandle(svcHndl); - - Cleanup2: - CloseServiceHandle(managerHndl); - - Cleanup1: - wsprintf(resultBuf, "%08X", result); - pushstring(resultBuf); -} - - - -BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved) -{ - return TRUE; -} diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp deleted file mode 100644 index 874e66c7..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsp +++ /dev/null @@ -1,110 +0,0 @@ -# Microsoft Developer Studio Project File - Name="InstDrv" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** NICHT BEARBEITEN ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=InstDrv - Win32 Debug -!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE -!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl -!MESSAGE -!MESSAGE NMAKE /f "InstDrv.mak". -!MESSAGE -!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben -!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: -!MESSAGE -!MESSAGE NMAKE /f "InstDrv.mak" CFG="InstDrv - Win32 Debug" -!MESSAGE -!MESSAGE Für die Konfiguration stehen zur Auswahl: -!MESSAGE -!MESSAGE "InstDrv - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library") -!MESSAGE "InstDrv - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "InstDrv - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "INSTDRV_EXPORTS" /YX /FD /c -# 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 -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x407 /d "NDEBUG" -# ADD RSC /l 0x407 /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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 -# SUBTRACT LINK32 /pdb:none - -!ELSEIF "$(CFG)" == "InstDrv - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# 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 -# 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 -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x407 /d "_DEBUG" -# ADD RSC /l 0x407 /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# 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 -# 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 -# SUBTRACT LINK32 /nodefaultlib - -!ENDIF - -# Begin Target - -# Name "InstDrv - Win32 Release" -# Name "InstDrv - Win32 Debug" -# Begin Group "Quellcodedateien" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\InstDrv.c -# End Source File -# End Group -# Begin Group "Header-Dateien" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# End Group -# Begin Group "Ressourcendateien" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# End Group -# End Target -# End Project diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw deleted file mode 100644 index b3d02f0e..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/InstDrv.dsw +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! - -############################################################################### - -Project: "InstDrv"=.\InstDrv.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt deleted file mode 100644 index e5877aa6..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/Readme.txt +++ /dev/null @@ -1,141 +0,0 @@ -InstDrv.dll version 0.2 - Installs or Removes Device Drivers ------------------------------------------------------------- - - -The plugin helps you to create NSIS scripts for installing device drivers or -removing them again. It can count installed device instances, create new ones -or delete all supported device. InstDrv works on Windows 2000 or later. - - - -InstDrv::InitDriverSetup devClass drvHWID -Return: result - -To start processing a driver, first call this function. devClass is the GUID -of the device class the driver supports, drvHWID is the device hardware ID. If -you don't know what these terms mean, you may want to take a look at the -Windows DDK. This function returns an empty string on success, otherwise an -error message. - -InitDriverSetup has to be called every time after the plugin dll has been -(re-)loaded, or if you want to switch to a different driver. - - - -InstDrv::CountDevices -Return: number - -This call returns the number of installed and supported devices of the driver. - - - -InstDrv::CreateDevice -Return: result - -To create a new deviced node which the driver has to support, use this -function. You may even call it multiple times for more than one instance. The -return value is the Windows error code (in hex). Use CreateDevice before -installing or updating the driver itself. - - - -InstDrv::InstallDriver infPath -Return: result - reboot - -InstallDriver installs or updates a device driver as specified in the .inf -setup script. It returns a Windows error code (in hex) and, on success, a flag -signalling if a system reboot is required. - - - -InstDrv::DeleteOemInfFiles -Return: result - oeminf - oempnf - -DeleteOemInfFiles tries to clean up the Windows inf directory by deleting the -oemXX.inf and oemXX.pnf files associated with the drivers. It returns a -Windows error code (in hex) and, on success, the names of the deleted files. -This functions requires that at least one device instance is still present. -So, call it before you remove the devices itself. You should also call it -before updating a driver. This avoids that the inf directory gets slowly -messed up with useless old setup scripts (which does NOT really accelerate -Windows). The error code which comes up when no device is installed is -"00000103". - - - -InstDrv::RemoveAllDevices -Return: result - reboot - -This functions deletes all devices instances the driver supported. It returns -a Windows error code (in hex) and, on success, a flag signalling if the system -needs to be rebooted. You additionally have to remove the driver binaries from -the system paths. - - - -InstDrv::StartSystemService serviceName -Return: result - -Call this function to start the provided system service. The function blocks -until the service is started or the system reported a timeout. The return value -is the Windows error code (in hex). - - - -InstDrv::StopSystemService serviceName -Return: result - -This function tries to stop the provided system service. It blocks until the -service has been shut down or the system reported a timeout. The return value -is the Windows error code (in hex). - - - -Example.nsi - -The example script installs or removes the virtual COM port driver of IrCOMM2k -(2.0.0-alpha8, see www.ircomm2k.de/english). The driver and its setup script -are only included for demonstration purposes, they do not work without the -rest of IrCOMM2k (but they also do not cause any harm). - - - -Building the Source Code - -To build the plugin from the source code, some include files and libraries -which come with the Windows DDK are required. - - - -History - - 0.2 - fixed bug when calling InitDriverSetup the second time - - added StartSystemService and StopSystemService - - 0.1 - first release - - - -License - -Copyright © 2003 Jan Kiszka (Jan.Kiszka@web.de) - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute -it freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment in the - product documentation would be appreciated but is not required. -2. Altered versions must be plainly marked as such, - and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any distribution. diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf deleted file mode 100644 index ccda1d87..00000000 --- a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.inf +++ /dev/null @@ -1,137 +0,0 @@ -; IrCOMM2k.inf -; -; Installation file for the Virtual Infrared-COM-Port -; -; (c) Copyright 2001, 2002 Jan Kiszka -; - -[Version] -Signature="$Windows NT$" -Provider=%JK% -Class=Ports -ClassGUID={4d36e978-e325-11ce-bfc1-08002be10318} -;DriverVer=03/26/2002,1.2.1.0 - -[DestinationDirs] -IrCOMM2k.Copy2Drivers = 12 -IrCOMM2k.Copy2Winnt = 10 -IrCOMM2k.Copy2System32 = 11 -IrCOMM2k.Copy2Help = 18 - - -; -; Driver information -; - -[Manufacturer] -%JK% = JK.Mfg - -[JK.Mfg] -%JK.DeviceDescIrCOMM% = IrCOMM2k_inst,IrCOMM2k - - -; -; General installation section -; - -[IrCOMM2k_inst] -CopyFiles = IrCOMM2k.Copy2Drivers ;,IrCOMM2k.Copy2System32,IrCOMM2k.Copy2Help,IrCOMM2k.Copy2Winnt -;AddReg = IrCOMM2k_inst_AddReg - - -; -; File sections -; - -[IrCOMM2k.Copy2Drivers] -ircomm2k.sys,,,2 - -;[IrCOMM2k.Copy2System32] -;ircomm2k.exe,,,2 -;ircomm2k.dll,,,2 - -;[IrCOMM2k.Copy2Help] -;ircomm2k.hlp,,,2 - -;[IrCOMM2k.Copy2Winnt] -;IrCOMM2k-Setup.exe,Setup.exe,,2 - - -; -; Service Installation -; - -[IrCOMM2k_inst.Services] -AddService = IrCOMM2k,0x00000002,IrCOMM2k_DriverService_Inst,IrCOMM2k_DriverEventLog_Inst -;AddService = IrCOMM2kSvc,,IrCOMM2k_Service_Inst - -[IrCOMM2k_DriverService_Inst] -DisplayName = %IrCOMM2k.DrvName% -ServiceType = 1 ; SERVICE_KERNEL_DRIVER -StartType = 3 ; SERVICE_DEMAND_START -ErrorControl = 0 ; SERVICE_ERROR_IGNORE -ServiceBinary = %12%\ircomm2k.sys - -;[IrCOMM2k_Service_Inst] -;DisplayName = %IrCOMM2k.SvcName% -;Description = %IrCOMM2k.SvcDesc% -;ServiceType = 0x00000120 ; SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS -;StartType = 2 ; SERVICE_AUTO_START -;ErrorControl = 0 ; SERVICE_ERROR_IGNORE -;ServiceBinary = %11%\ircomm2k.exe -;Dependencies = IrCOMM2k -;AddReg = IrCOMM2kSvcAddReg - - -[IrCOMM2k_inst.nt.HW] -AddReg=IrCOMM2kHwAddReg - -[IrCOMM2kHwAddReg] -HKR,,PortSubClass,REG_BINARY,0x00000001 -;HKR,,TimeoutScaling,REG_DWORD,0x00000001 -;HKR,,StatusLines,REG_DWORD,0x00000000 - -;[IrCOMM2k_inst_AddReg] -;HKR,,EnumPropPages32,,"ircomm2k.dll,IrCOMM2kPropPageProvider" -;HKLM,%UNINSTALL_KEY%,DisplayIcon,0x00020000,"%windir%\IrCOMM2k-Setup.exe" -;HKLM,%UNINSTALL_KEY%,DisplayName,,"IrCOMM2k 1.2.1 " -;HKLM,%UNINSTALL_KEY%,DisplayVersion,,"1.2.1" -;HKLM,%UNINSTALL_KEY%,HelpLink,,"http://www.ircomm2k.de" -;HKLM,%UNINSTALL_KEY%,Publisher,,%JK% -;HKLM,%UNINSTALL_KEY%,UninstallString,0x00020000,"%windir%\IrCOMM2k-Setup.exe" - -;[IrCOMM2kSvcAddReg] -;HKR,Parameters,ActiveConnectOnly,REG_DWORD,0x00000000 - - -[IrCOMM2k_DriverEventLog_Inst] -AddReg = IrCOMM2k_DriverEventLog_AddReg - -[IrCOMM2k_DriverEventLog_AddReg] -HKR,,EventMessageFile,REG_EXPAND_SZ,"%SystemRoot%\System32\IoLogMsg.dll;%SystemRoot%\System32\drivers\ircomm2k.sys" -HKR,,TypesSupported,REG_DWORD,7 - - -[Strings] - -; -; Non-Localizable Strings -; - -REG_SZ = 0x00000000 -REG_MULTI_SZ = 0x00010000 -REG_EXPAND_SZ = 0x00020000 -REG_BINARY = 0x00000001 -REG_DWORD = 0x00010001 -SERVICEROOT = "System\CurrentControlSet\Services" -UNINSTALL_KEY = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IrCOMM2k" - -; -; Localizable Strings -; - -JK = "Jan Kiszka" -JK.DeviceDescIrCOMM = "Virtueller Infrarot-Kommunikationsanschluss" -IrCOMM2k.DrvName = "Virtueller Infrarot-Kommunikationsanschluss" -;IrCOMM2k.SvcName = "Virtueller Infrarot-Kommunikationsanschluß, Dienstprogramm" -;IrCOMM2k.SvcDesc = "Bildet über Infarot einen Kommunikationsanschluß nach." diff --git a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys b/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys deleted file mode 100644 index 7882583b..00000000 Binary files a/ao-tools/altosui/Instdrv/NSIS/Contrib/InstDrv/ircomm2k.sys and /dev/null differ diff --git a/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll b/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll deleted file mode 100644 index 482e955e..00000000 Binary files a/ao-tools/altosui/Instdrv/NSIS/Plugins/InstDrv.dll and /dev/null differ diff --git a/ao-tools/altosui/Makefile-standalone b/ao-tools/altosui/Makefile-standalone deleted file mode 100644 index a95a5aa8..00000000 --- a/ao-tools/altosui/Makefile-standalone +++ /dev/null @@ -1,184 +0,0 @@ -.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 \ - AltosInfoTable.class \ - AltosLog.class \ - AltosLogfileChooser.class \ - AltosParse.class \ - AltosPreferences.class \ - AltosReader.class \ - AltosRecord.class \ - AltosSerialMonitor.class \ - AltosSerial.class \ - AltosState.class \ - AltosStatusTable.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 diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am deleted file mode 100644 index 93a43b12..00000000 --- a/ao-tools/altosui/Makefile.am +++ /dev/null @@ -1,271 +0,0 @@ -JAVAROOT=classes -AM_JAVACFLAGS=-encoding UTF-8 - -man_MANS=altosui.1 - -altoslibdir=$(libdir)/altos - -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../libaltos:$(FREETTS)/*:/usr/share/java/*" - -bin_SCRIPTS=altosui - -altosui_JAVA = \ - GrabNDrag.java \ - AltosAscent.java \ - AltosChannelMenu.java \ - AltosConfig.java \ - AltosConfigUI.java \ - AltosConfigureUI.java \ - AltosConvert.java \ - AltosCRCException.java \ - AltosCSV.java \ - AltosCSVUI.java \ - AltosDebug.java \ - AltosDescent.java \ - AltosDeviceDialog.java \ - AltosDevice.java \ - AltosDisplayThread.java \ - AltosEepromDownload.java \ - AltosEepromMonitor.java \ - AltosEepromIterable.java \ - AltosEepromRecord.java \ - AltosFile.java \ - AltosFlash.java \ - AltosFlashUI.java \ - AltosFlightDisplay.java \ - AltosFlightInfoTableModel.java \ - AltosFlightReader.java \ - AltosFlightStatus.java \ - AltosFlightUI.java \ - AltosGPS.java \ - AltosGreatCircle.java \ - AltosHexfile.java \ - Altos.java \ - AltosIgnite.java \ - AltosIgniteUI.java \ - AltosInfoTable.java \ - AltosKML.java \ - AltosLanded.java \ - AltosLed.java \ - AltosLights.java \ - AltosLine.java \ - AltosLog.java \ - AltosPad.java \ - AltosParse.java \ - AltosPreferences.java \ - AltosReader.java \ - AltosRecord.java \ - AltosRecordIterable.java \ - AltosTelemetryReader.java \ - AltosReplayReader.java \ - AltosRomconfig.java \ - AltosRomconfigUI.java \ - AltosSerial.java \ - AltosSerialInUseException.java \ - AltosSerialMonitor.java \ - AltosSiteMap.java \ - AltosSiteMapCache.java \ - AltosSiteMapTile.java \ - AltosState.java \ - AltosTelemetry.java \ - AltosTelemetryIterable.java \ - AltosUI.java \ - AltosWriter.java \ - AltosDataPointReader.java \ - AltosDataPoint.java \ - AltosGraph.java \ - AltosGraphTime.java \ - AltosGraphUI.java \ - AltosDataChooser.java \ - AltosVoice.java - -JFREECHART_CLASS= \ - jfreechart.jar - -JCOMMON_CLASS=\ - jcommon.jar - -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 -ICONDIR=$(top_srcdir)/icon - -JAVA_ICON=$(ICONDIR)/altus-metrum-16x16.jpg - -ICONS= $(ICONDIR)/redled.png $(ICONDIR)/redoff.png \ - $(ICONDIR)/greenled.png $(ICONDIR)/greenoff.png \ - $(ICONDIR)/grayled.png $(ICONDIR)/grayoff.png - -# icon base names for jar -ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \ - -C $(ICONDIR) redled.png -C $(ICONDIR) redoff.png \ - -C $(ICONDIR) greenled.png -C $(ICONDIR) greenoff.png \ - -C $(ICONDIR) grayon.png -C $(ICONDIR) grayled.png - -WINDOWS_ICON=$(ICONDIR)/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) $(JFREECHART_CLASS) $(JCOMMON_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) altosui altosui-test altosui-jdb - -clean-local: - -rm -rf classes $(JAR) $(FATJAR) \ - $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ - $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ - altosui altosui-test altosui-jdb macosx linux - -if FATINSTALL - -FATTARGET=$(FATDIR)/$(VERSION) - -LINUX_DIST_TARGET=$(FATTARGET)/$(LINUX_DIST) -MACOSX_DIST_TARGET=$(FATTARGET)/$(MACOSX_DIST) -WINDOWS_DIST_TARGET=$(FATTARGET)/$(WINDOWS_DIST) - -fat: $(LINUX_DIST_TARGET) $(MACOSX_DIST_TARGET) $(WINDOWS_DIST_TARGET) - -$(LINUX_DIST_TARGET): $(LINUX_DIST) - mkdir -p $(FATTARGET) - cp -p $< $@ - -$(MACOSX_DIST_TARGET): $(MACOSX_DIST) - mkdir -p $(FATTARGET) - cp -p $< $@ - -$(WINDOWS_DIST_TARGET): $(WINDOWS_DIST) - mkdir -p $(FATTARGET) - cp -p $< $@ - -else -fat: $(LINUX_DIST) $(MACOSX_DIST) $(WINDOWS_DIST) -endif - - -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 \ - $(ICONJAR) \ - -C classes altosui \ - -C ../libaltos libaltosJNI - -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) - jar cfm $@ Manifest-fat.txt \ - $(ICONJAR) \ - -C classes altosui \ - -C ../libaltos libaltosJNI - -Manifest.txt: Makefile - echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ - -Manifest-fat.txt: - echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@ - -altosui: Makefile - echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="$(altoslibdir)" -jar "$(altosuidir)/altosui.jar" "$$@"' >> $@ - chmod +x $@ - -altosui-test: Makefile - echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" -jar altosui.jar "$$@"' >> $@ - chmod +x $@ - -altosui-jdb: Makefile - echo "#!/bin/sh" > $@ - echo 'exec jdb -classpath "classes:../libaltos:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="../libaltos/.libs" altosui/AltosUI "$$@"' >> $@ - chmod +x $@ - -libaltos.so: - -rm -f "$@" - $(LN_S) ../libaltos/.libs/"$@" . - -libaltos.dylib: - -rm -f "$@" - $(LN_S) ../libaltos/"$@" . - -altos.dll: - -rm -f "$@" - $(LN_S) ../libaltos/"$@" . - -$(FREETTS_CLASS): - -rm -f "$@" - $(LN_S) "$(FREETTS)"/"$@" . - -$(JFREECHART_CLASS): - -rm -f "$@" - $(LN_S) "$(JFREECHART)"/"$@" . - -$(JCOMMON_CLASS): - -rm -f "$@" - $(LN_S) "$(JCOMMON)"/"$@" . - -$(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 $(JFREECHART_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 diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi deleted file mode 100644 index 37777fd6..00000000 --- a/ao-tools/altosui/altos-windows.nsi +++ /dev/null @@ -1,113 +0,0 @@ -!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" - - SetOutPath $INSTDIR - File "../../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 diff --git a/ao-tools/altosui/altosui-fat b/ao-tools/altosui/altosui-fat deleted file mode 100755 index 95b1c051..00000000 --- a/ao-tools/altosui/altosui-fat +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -me=`which "$0"` -dir=`dirname "$me"` -exec java -cp "$dir/*" -Djava.library.path="$dir" -jar "$dir"/altosui-fat.jar "$@" diff --git a/ao-tools/altosui/altosui.1 b/ao-tools/altosui/altosui.1 deleted file mode 100644 index 57fa4489..00000000 --- a/ao-tools/altosui/altosui.1 +++ /dev/null @@ -1,46 +0,0 @@ -.\" -.\" Copyright © 2010 Bdale Garbee -.\" -.\" 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 ALTOSUI 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 menu-oriented -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 can be used to configure the -TeleMetrum, and to downloads the eeprom data and store it in a file. -.P -A number of other menu options exist, including the ability to export flight -data in different formats. -.SH FILES -All data log files are recorded into a user-specified directory -(default ~/TeleMetrum). 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 AUTHOR -Keith Packard diff --git a/ao-tools/altosui/altusmetrum.jpg b/ao-tools/altosui/altusmetrum.jpg deleted file mode 100644 index 04027921..00000000 Binary files a/ao-tools/altosui/altusmetrum.jpg and /dev/null differ diff --git a/ao-tools/libaltos/.gitignore b/ao-tools/libaltos/.gitignore deleted file mode 100644 index c490e6f8..00000000 --- a/ao-tools/libaltos/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -*.so -*.lo -*.la -*.java -*.class -.libs/ -classlibaltos.stamp -libaltos_wrap.c -libaltosJNI -cjnitest -libaltos.swig -swig_bindings/ diff --git a/ao-tools/libaltos/Makefile-standalone b/ao-tools/libaltos/Makefile-standalone deleted file mode 100644 index 4e438050..00000000 --- a/ao-tools/libaltos/Makefile-standalone +++ /dev/null @@ -1,126 +0,0 @@ -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: diff --git a/ao-tools/libaltos/Makefile.am b/ao-tools/libaltos/Makefile.am deleted file mode 100644 index 388d2104..00000000 --- a/ao-tools/libaltos/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -JAVAC=javac -AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -AM_JAVACFLAGS=-encoding UTF-8 - -altoslibdir=$(libdir)/altos - -altoslib_LTLIBRARIES=libaltos.la - -libaltos_la_LDFLAGS = -version-info 1:0:1 - -libaltos_la_SOURCES=\ - libaltos.c \ - libaltos_wrap.c - -noinst_PROGRAMS=cjnitest - -cjnitest_LDADD=libaltos.la - -LIBS= - -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 - -libaltos_wrap.c: 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) libaltos_wrap.c diff --git a/ao-tools/libaltos/altos.dll b/ao-tools/libaltos/altos.dll deleted file mode 100755 index 28e9b4ad..00000000 Binary files a/ao-tools/libaltos/altos.dll and /dev/null differ diff --git a/ao-tools/libaltos/cjnitest.c b/ao-tools/libaltos/cjnitest.c deleted file mode 100644 index c6d6e069..00000000 --- a/ao-tools/libaltos/cjnitest.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include "libaltos.h" - -static void -altos_puts(struct altos_file *file, char *string) -{ - char c; - - while ((c = *string++)) - altos_putchar(file, c); -} - -main () -{ - struct altos_device device; - struct altos_list *list; - - altos_init(); - list = altos_list_start(); - while (altos_list_next(list, &device)) { - struct altos_file *file; - int c; - - printf ("%04x:%04x %-20s %4d %s\n", device.vendor, device.product, - device.name, device.serial, device.path); - - file = altos_open(&device); - if (!file) { - printf("altos_open failed\n"); - continue; - } - altos_puts(file,"v\nc s\n"); - altos_flush(file); - while ((c = altos_getchar(file, 100)) >= 0) { - putchar (c); - } - if (c != LIBALTOS_TIMEOUT) - printf ("getchar returns %d\n", c); - altos_close(file); - } - altos_list_finish(list); - altos_fini(); -} diff --git a/ao-tools/libaltos/libaltos.c b/ao-tools/libaltos/libaltos.c deleted file mode 100644 index 465f0ac8..00000000 --- a/ao-tools/libaltos/libaltos.c +++ /dev/null @@ -1,1028 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "libaltos.h" -#include -#include -#include - -#define USE_POLL - -PUBLIC int -altos_init(void) -{ - return LIBALTOS_SUCCESS; -} - -PUBLIC void -altos_fini(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) -{ - size_t len = strlen (s); - char *ret; - - if (len <= n) - return strdup (s); - ret = malloc(n + 1); - strncpy(ret, s, n); - ret[n] = '\0'; - return ret; -} - -#else -#define altos_strndup strndup -#endif - -/* - * Scan for Altus Metrum devices by looking through /sys - */ - -#ifdef LINUX - -#define _GNU_SOURCE -#include -#include -#include -#include -#include - -static char * -cc_fullname (char *dir, char *file) -{ - char *new; - int dlen = strlen (dir); - int flen = strlen (file); - int slen = 0; - - if (dir[dlen-1] != '/') - slen = 1; - new = malloc (dlen + slen + flen + 1); - if (!new) - return 0; - strcpy(new, dir); - if (slen) - strcat (new, "/"); - strcat(new, file); - return new; -} - -static char * -cc_basename(char *file) -{ - char *b; - - b = strrchr(file, '/'); - if (!b) - return file; - return b + 1; -} - -static char * -load_string(char *dir, char *file) -{ - char *full = cc_fullname(dir, file); - char line[4096]; - char *r; - FILE *f; - int rlen; - - f = fopen(full, "r"); - free(full); - if (!f) - return NULL; - r = fgets(line, sizeof (line), f); - fclose(f); - if (!r) - return NULL; - rlen = strlen(r); - if (r[rlen-1] == '\n') - r[rlen-1] = '\0'; - return strdup(r); -} - -static int -load_hex(char *dir, char *file) -{ - char *line; - char *end; - long i; - - line = load_string(dir, file); - if (!line) - return -1; - i = strtol(line, &end, 16); - free(line); - if (end == line) - return -1; - return i; -} - -static int -load_dec(char *dir, char *file) -{ - char *line; - char *end; - long i; - - line = load_string(dir, file); - if (!line) - return -1; - i = strtol(line, &end, 10); - free(line); - if (end == line) - return -1; - return i; -} - -static int -dir_filter_tty_colon(const struct dirent *d) -{ - return strncmp(d->d_name, "tty:", 4) == 0; -} - -static int -dir_filter_tty(const struct dirent *d) -{ - return strncmp(d->d_name, "tty", 3) == 0; -} - -struct altos_usbdev { - char *sys; - char *tty; - char *manufacturer; - char *product_name; - int serial; /* AltOS always uses simple integer serial numbers */ - int idProduct; - int idVendor; -}; - -static char * -usb_tty(char *sys) -{ - char *base; - int num_configs; - int config; - struct dirent **namelist; - int interface; - int num_interfaces; - char endpoint_base[20]; - char *endpoint_full; - char *tty_dir; - int ntty; - char *tty; - - base = cc_basename(sys); - num_configs = load_hex(sys, "bNumConfigurations"); - num_interfaces = load_hex(sys, "bNumInterfaces"); - for (config = 1; config <= num_configs; config++) { - for (interface = 0; interface < num_interfaces; interface++) { - sprintf(endpoint_base, "%s:%d.%d", - base, config, interface); - endpoint_full = cc_fullname(sys, endpoint_base); - - /* Check for tty:ttyACMx style names - */ - ntty = scandir(endpoint_full, &namelist, - dir_filter_tty_colon, - alphasort); - if (ntty > 0) { - free(endpoint_full); - tty = cc_fullname("/dev", namelist[0]->d_name + 4); - free(namelist); - return tty; - } - - /* Check for tty/ttyACMx style names - */ - tty_dir = cc_fullname(endpoint_full, "tty"); - free(endpoint_full); - ntty = scandir(tty_dir, &namelist, - dir_filter_tty, - alphasort); - free (tty_dir); - if (ntty > 0) { - tty = cc_fullname("/dev", namelist[0]->d_name); - free(namelist); - return tty; - } - } - } - return NULL; -} - -static struct altos_usbdev * -usb_scan_device(char *sys) -{ - struct altos_usbdev *usbdev; - - usbdev = calloc(1, sizeof (struct altos_usbdev)); - if (!usbdev) - return NULL; - usbdev->sys = strdup(sys); - usbdev->manufacturer = load_string(sys, "manufacturer"); - usbdev->product_name = load_string(sys, "product"); - usbdev->serial = load_dec(sys, "serial"); - usbdev->idProduct = load_hex(sys, "idProduct"); - usbdev->idVendor = load_hex(sys, "idVendor"); - usbdev->tty = usb_tty(sys); - return usbdev; -} - -static void -usbdev_free(struct altos_usbdev *usbdev) -{ - free(usbdev->sys); - free(usbdev->manufacturer); - free(usbdev->product_name); - /* this can get used as a return value */ - if (usbdev->tty) - free(usbdev->tty); - free(usbdev); -} - -#define USB_DEVICES "/sys/bus/usb/devices" - -static int -dir_filter_dev(const struct dirent *d) -{ - const char *n = d->d_name; - char c; - - while ((c = *n++)) { - if (isdigit(c)) - continue; - if (c == '-') - continue; - if (c == '.' && n != d->d_name + 1) - continue; - return 0; - } - return 1; -} - -struct altos_list { - struct altos_usbdev **dev; - int current; - int ndev; -}; - -struct altos_list * -altos_list_start(void) -{ - int e; - struct dirent **ents; - char *dir; - struct altos_usbdev *dev; - struct altos_list *devs; - int n; - - devs = calloc(1, sizeof (struct altos_list)); - if (!devs) - return NULL; - - n = scandir (USB_DEVICES, &ents, - dir_filter_dev, - alphasort); - if (!n) - return 0; - for (e = 0; e < n; e++) { - dir = cc_fullname(USB_DEVICES, ents[e]->d_name); - dev = usb_scan_device(dir); - free(dir); - if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { - if (devs->dev) - devs->dev = realloc(devs->dev, - devs->ndev + 1 * sizeof (struct usbdev *)); - else - devs->dev = malloc (sizeof (struct usbdev *)); - devs->dev[devs->ndev++] = dev; - } - } - free(ents); - devs->current = 0; - return devs; -} - -int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - struct altos_usbdev *dev; - if (list->current >= list->ndev) - return 0; - dev = list->dev[list->current]; - strcpy(device->name, dev->product_name); - device->vendor = dev->idVendor; - device->product = dev->idProduct; - strcpy(device->path, dev->tty); - device->serial = dev->serial; - list->current++; - return 1; -} - -void -altos_list_finish(struct altos_list *usbdevs) -{ - int i; - - if (!usbdevs) - return; - for (i = 0; i < usbdevs->ndev; i++) - usbdev_free(usbdevs->dev[i]); - free(usbdevs); -} - -#endif - -#ifdef DARWIN - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct altos_list { - io_iterator_t iterator; -}; - -static int -get_string(io_object_t object, CFStringRef entry, char *result, int result_len) -{ - CFTypeRef entry_as_string; - Boolean got_string; - - entry_as_string = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_string) { - got_string = CFStringGetCString(entry_as_string, - result, result_len, - kCFStringEncodingASCII); - - CFRelease(entry_as_string); - if (got_string) - return 1; - } - return 0; -} - -static int -get_number(io_object_t object, CFStringRef entry, int *result) -{ - CFTypeRef entry_as_number; - Boolean got_number; - - entry_as_number = IORegistryEntrySearchCFProperty (object, - kIOServicePlane, - entry, - kCFAllocatorDefault, - kIORegistryIterateRecursively); - if (entry_as_number) { - got_number = CFNumberGetValue(entry_as_number, - kCFNumberIntType, - result); - if (got_number) - return 1; - } - return 0; -} - -struct altos_list * -altos_list_start(void) -{ - struct altos_list *list = calloc (sizeof (struct altos_list), 1); - CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); - io_iterator_t tdIterator; - io_object_t tdObject; - kern_return_t ret; - int i; - - ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator); - if (ret != kIOReturnSuccess) - return NULL; - return list; -} - -int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - io_object_t object; - char serial_string[128]; - - for (;;) { - object = IOIteratorNext(list->iterator); - if (!object) - return 0; - - if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) || - !get_number (object, CFSTR(kUSBProductID), &device->product)) - continue; - if (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->name, sizeof (device->name)) && - get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) { - device->serial = atoi(serial_string); - return 1; - } - } -} - -void -altos_list_finish(struct altos_list *list) -{ - IOObjectRelease (list->iterator); - free(list); -} - -#endif - -#ifdef POSIX_TTY - -#include -#include -#include -#include -#include - -#define USB_BUF_SIZE 64 - -struct altos_file { - int fd; -#ifdef USE_POLL - int pipe[2]; -#else - int out_fd; -#endif - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; -}; - -PUBLIC struct altos_file * -altos_open(struct altos_device *device) -{ - struct altos_file *file = calloc (sizeof (struct altos_file), 1); - int ret; - struct termios term; - - if (!file) - return NULL; - - file->fd = open(device->path, O_RDWR | O_NOCTTY); - if (file->fd < 0) { - perror(device->path); - 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; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->fd != -1) { - int fd = file->fd; - file->fd = -1; -#ifdef USE_POLL - write(file->pipe[1], "\r", 1); -#else - close(file->out_fd); - file->out_fd = -1; -#endif - close(fd); - } -} - -PUBLIC void -altos_free(struct altos_file *file) -{ - altos_close(file); - free(file); -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - if (file->out_used && 0) { - printf ("flush \""); - fwrite(file->out_data, 1, file->out_used, stdout); - printf ("\"\n"); - } - while (file->out_used) { - int ret; - - if (file->fd < 0) - return -EBADF; -#ifdef USE_POLL - ret = write (file->fd, file->out_data, file->out_used); -#else - ret = write (file->out_fd, file->out_data, file->out_used); -#endif - if (ret < 0) - return -errno; - if (ret) { - memmove(file->out_data, file->out_data + ret, - file->out_used - ret); - file->out_used -= ret; - } - } - return 0; -} - -PUBLIC int -altos_putchar(struct altos_file *file, char c) -{ - int ret; - - if (file->out_used == USB_BUF_SIZE) { - ret = altos_flush(file); - if (ret) { - return ret; - } - } - file->out_data[file->out_used++] = c; - ret = 0; - if (file->out_used == USB_BUF_SIZE) - ret = altos_flush(file); - return 0; -} - -#ifdef USE_POLL -#include -#endif - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; -#ifdef USE_POLL - struct pollfd fd[2]; -#endif - - if (timeout == 0) - timeout = -1; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; -#ifdef USE_POLL - fd[0].fd = file->fd; - fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; - ret = poll(fd, 2, timeout); - if (ret < 0) { - 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 - } - } - if (file->in_used && 0) { - printf ("fill \""); - fwrite(file->in_data, 1, file->in_used, stdout); - printf ("\"\n"); - } - return 0; -} - -PUBLIC int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - return file->in_data[file->in_read++]; -} - -#endif /* POSIX_TTY */ - -#ifdef WINDOWS - -#include -#include -#include - -struct altos_list { - HDEVINFO dev_info; - int index; -}; - -#define USB_BUF_SIZE 64 - -struct altos_file { - HANDLE handle; - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; - OVERLAPPED ov_read; - BOOL pend_read; - OVERLAPPED ov_write; -}; - -PUBLIC struct altos_list * -altos_list_start(void) -{ - struct altos_list *list = calloc(1, sizeof (struct altos_list)); - - if (!list) - return NULL; - list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, - DIGCF_ALLCLASSES|DIGCF_PRESENT); - if (list->dev_info == INVALID_HANDLE_VALUE) { - printf("SetupDiGetClassDevs failed %d\n", GetLastError()); - free(list); - return NULL; - } - list->index = 0; - return list; -} - -PUBLIC int -altos_list_next(struct altos_list *list, struct altos_device *device) -{ - SP_DEVINFO_DATA dev_info_data; - char port[128]; - DWORD port_len; - char friendlyname[256]; - char symbolic[256]; - DWORD symbolic_len; - HKEY dev_key; - int vid, pid; - int serial; - HRESULT result; - DWORD friendlyname_type; - DWORD friendlyname_len; - - dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA); - while(SetupDiEnumDeviceInfo(list->dev_info, list->index, - &dev_info_data)) - { - list->index++; - - dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data, - DICS_FLAG_GLOBAL, 0, DIREG_DEV, - KEY_READ); - if (dev_key == INVALID_HANDLE_VALUE) { - printf("cannot open device registry key\n"); - continue; - } - - /* Fetch symbolic name for this device and parse out - * the vid/pid/serial info */ - symbolic_len = sizeof(symbolic); - result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, - symbolic, &symbolic_len); - if (result != 0) { - printf("cannot find SymbolicName value\n"); - RegCloseKey(dev_key); - continue; - } - vid = pid = serial = 0; - sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, - "%04X", &vid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, - "%04X", &pid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, - "%d", &serial); - if (!USB_IS_ALTUSMETRUM(vid, pid)) { - RegCloseKey(dev_key); - continue; - } - - /* Fetch the com port name */ - port_len = sizeof (port); - result = RegQueryValueEx(dev_key, "PortName", NULL, NULL, - port, &port_len); - RegCloseKey(dev_key); - if (result != 0) { - printf("failed to get PortName\n"); - continue; - } - - /* Fetch the device description which is the device name, - * with firmware that has unique USB ids */ - friendlyname_len = sizeof (friendlyname); - if(!SetupDiGetDeviceRegistryProperty(list->dev_info, - &dev_info_data, - SPDRP_FRIENDLYNAME, - &friendlyname_type, - (BYTE *)friendlyname, - sizeof(friendlyname), - &friendlyname_len)) - { - printf("Failed to get friendlyname\n"); - continue; - } - device->vendor = vid; - device->product = pid; - device->serial = serial; - strcpy(device->name, friendlyname); - - strcpy(device->path, port); - return 1; - } - result = GetLastError(); - if (result != ERROR_NO_MORE_ITEMS) - printf ("SetupDiEnumDeviceInfo failed error %d\n", result); - return 0; -} - -PUBLIC void -altos_list_finish(struct altos_list *list) -{ - SetupDiDestroyDeviceInfoList(list->dev_info); - free(list); -} - -static int -altos_queue_read(struct altos_file *file) -{ - DWORD got; - if (file->pend_read) - return LIBALTOS_SUCCESS; - - if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { - if (GetLastError() != ERROR_IO_PENDING) - return LIBALTOS_ERROR; - file->pend_read = TRUE; - } else { - file->pend_read = FALSE; - file->in_read = 0; - file->in_used = got; - } - return LIBALTOS_SUCCESS; -} - -static int -altos_wait_read(struct altos_file *file, int timeout) -{ - DWORD ret; - DWORD got; - - if (!file->pend_read) - return LIBALTOS_SUCCESS; - - if (!timeout) - timeout = INFINITE; - - ret = WaitForSingleObject(file->ov_read.hEvent, timeout); - switch (ret) { - case WAIT_OBJECT_0: - if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) - 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; - } - return LIBALTOS_SUCCESS; -} - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; - - if (file->in_read < file->in_used) - return LIBALTOS_SUCCESS; - - file->in_read = file->in_used = 0; - - ret = altos_queue_read(file); - if (ret) - return ret; - ret = altos_wait_read(file, timeout); - if (ret) - return ret; - - return LIBALTOS_SUCCESS; -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - DWORD put; - char *data = file->out_data; - char used = file->out_used; - DWORD ret; - - while (used) { - 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; - } - file->out_used = 0; - return LIBALTOS_SUCCESS; -} - -PUBLIC struct altos_file * -altos_open(struct altos_device *device) -{ - struct altos_file *file = calloc (1, sizeof (struct altos_file)); - char full_name[64]; - DCB dcbSerialParams = {0}; - COMMTIMEOUTS timeouts; - - if (!file) - return NULL; - - strcpy(full_name, "\\\\.\\"); - strcat(full_name, device->path); - file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE, - 0, NULL, OPEN_EXISTING, - 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 = 1 << 30; /* almost forever */ - timeouts.WriteTotalTimeoutMultiplier = 0; - 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; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->handle != INVALID_HANDLE_VALUE) { - CloseHandle(file->handle); - file->handle = INVALID_HANDLE_VALUE; - } -} - -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 LIBALTOS_SUCCESS; -} - -int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->handle == INVALID_HANDLE_VALUE) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - return file->in_data[file->in_read++]; -} - -#endif diff --git a/ao-tools/libaltos/libaltos.dylib b/ao-tools/libaltos/libaltos.dylib deleted file mode 100755 index 89aa12e7..00000000 Binary files a/ao-tools/libaltos/libaltos.dylib and /dev/null differ diff --git a/ao-tools/libaltos/libaltos.h b/ao-tools/libaltos/libaltos.h deleted file mode 100644 index 6e94899e..00000000 --- a/ao-tools/libaltos/libaltos.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _LIBALTOS_H_ -#define _LIBALTOS_H_ - -#include - -#if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) -# ifndef BUILD_STATIC -# ifdef BUILD_DLL -# define PUBLIC __declspec(dllexport) -# else -# define PUBLIC __declspec(dllimport) -# endif -# endif /* BUILD_STATIC */ -#endif - -#ifndef PUBLIC -# define PUBLIC -#endif - -#define USB_VENDOR_FSF 0xfffe -#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF -#define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_TELEMETRUM 0x000b -#define USB_PRODUCT_TELEDONGLE 0x000c -#define USB_PRODUCT_TELETERRA 0x000d -#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 - -#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ - (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ - (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) - -struct altos_device { - //%immutable; - int vendor; - int product; - int serial; - char name[256]; - char path[256]; - //%mutable; -}; - -#define LIBALTOS_SUCCESS 0 -#define LIBALTOS_ERROR -1 -#define LIBALTOS_TIMEOUT -2 - -/* Returns 0 for success, < 0 on error */ -PUBLIC int -altos_init(void); - -PUBLIC void -altos_fini(void); - -PUBLIC struct altos_list * -altos_list_start(void); - -/* Returns 1 for success, zero on end of list */ -PUBLIC int -altos_list_next(struct altos_list *list, struct altos_device *device); - -PUBLIC void -altos_list_finish(struct altos_list *list); - -PUBLIC struct altos_file * -altos_open(struct altos_device *device); - -PUBLIC void -altos_close(struct altos_file *file); - -PUBLIC void -altos_free(struct altos_file *file); - -/* Returns < 0 for error */ -PUBLIC int -altos_putchar(struct altos_file *file, char c); - -/* Returns < 0 for error */ -PUBLIC int -altos_flush(struct altos_file *file); - -/* Returns < 0 for error or timeout. timeout of 0 == wait forever */ -PUBLIC int -altos_getchar(struct altos_file *file, int timeout); - -#endif /* _LIBALTOS_H_ */ diff --git a/ao-tools/libaltos/libaltos.i0 b/ao-tools/libaltos/libaltos.i0 deleted file mode 100644 index d06468f5..00000000 --- a/ao-tools/libaltos/libaltos.i0 +++ /dev/null @@ -1,5 +0,0 @@ -%module libaltos -%{ -#include "libaltos.h" -%} - diff --git a/configure.ac b/configure.ac index 903c5765..22af00ab 100644 --- a/configure.ac +++ b/configure.ac @@ -133,6 +133,8 @@ PKG_CHECK_MODULES([SNDFILE], [sndfile]) AC_OUTPUT([ Makefile +altosui/Makefile +altosui/libaltos/Makefile ao-tools/Makefile ao-tools/lib/Makefile ao-tools/ao-rawload/Makefile @@ -144,8 +146,6 @@ ao-tools/ao-list/Makefile 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 ]) -- cgit v1.2.3 From 915f881d61294dc6f5a6a3e8d75567e18492a631 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Thu, 25 Nov 2010 09:52:30 +1000 Subject: doc: Document altosui "Site Map" tab --- doc/telemetrum-doc.xsl | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 8f554d88..f7c8627c 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -1044,6 +1044,27 @@ during the flight are displayed for your admiring observers.
+
+ Site Map + + When the rocket gets a GPS fix, the Site Map tab will map + the rocket's position to make it easier for you to locate the + rocket, both while it is in the air, and when it has landed. The + rocket's state is indicated by colour: white for pad, red for + boost, pink for fast, yellow for coast, light blue for drogue, + dark blue for main, and black for landed. + + + The map's scale is approximately 3m (10ft) per pixel. The map + can be dragged using the left mouse button. The map will attempt + to keep the rocket roughly centred while data is being received. + + + Images are fetched automatically via the Google Maps Static API, + and are cached for reuse. If map images cannot be downloaded, + the rocket's path will be traced on a dark grey background + instead. +
Save Flight Data -- cgit v1.2.3 From b372f3c0ee4ec49aabe61c169cb1eb9bb4fb2cfc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 18:50:46 -0800 Subject: Missing change to top level Makefile to build altosui Signed-off-by: Keith Packard --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 264e577a..2c412bf9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src ao-tools ao-utils +SUBDIRS=src altosui ao-tools ao-utils EXTRA_DIST = ChangeLog -- cgit v1.2.3 From 7cd1c7765d137df711caeeb69abaaba1b36e0a65 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Nov 2010 20:53:36 -0700 Subject: fix missing section close in Site Map content --- doc/telemetrum-doc.xsl | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index f7c8627c..4e71464d 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -1065,6 +1065,7 @@ the rocket's path will be traced on a dark grey background instead. +
Save Flight Data -- cgit v1.2.3 From 8a68c1da253c0b29a7cb9c7540c20585ad6e3dec Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Nov 2010 21:21:53 -0700 Subject: tweak rev history --- doc/telemetrum-doc.xsl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index 4e71464d..ef10ee40 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -29,8 +29,9 @@ 0.3 - 23 November 2010 - New section on AltosUI mostly by Keith + 24 November 2010 + New section on AltosUI mostly by Keith with contributions + from Anthony Towns. Many other updates. 0.2 -- cgit v1.2.3 From 4e47c44d335276cf0dc5ed3a0756e50c98c1b9b9 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Nov 2010 21:44:53 -0700 Subject: manually fold in documentation work from the master branch --- doc/telemetrum-doc.xsl | 256 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 208 insertions(+), 48 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index ef10ee40..e75e10b5 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -28,20 +28,9 @@ - 0.3 + 0.8 24 November 2010 - New section on AltosUI mostly by Keith with contributions - from Anthony Towns. Many other updates. - - - 0.2 - 18 July 2010 - Significant update - - - 0.1 - 30 March 2010 - Initial content + Updated for software version 0.8 @@ -87,52 +76,40 @@ The first thing to do after you check the inventory of parts in your "starter kit" is to charge the battery by plugging it into the - corresponding socket of the TeleMetrum and then using the USB A to B + corresponding socket of the TeleMetrum and then using the USB A to +mini B cable to plug the Telemetrum into your computer's USB socket. The TeleMetrum circuitry will charge the battery whenever it is plugged - into the usb socket. The TeleMetrum's on-off switch does NOT control - the charging circuitry. When the GPS chip is initially searching for - satellites, the unit will pull more current than it can pull from the - usb port, so the battery must be plugged in order to get a good - satellite lock. Once GPS is locked the current consumption goes back + in, because the TeleMetrum's on-off switch does NOT control the + charging circuitry. When the GPS chip is initially searching for + satellites, TeleMetrum will consume more current than it can pull + from the usb port, so the battery must be attached in order to get + satellite lock. Once GPS is locked, the current consumption goes back down enough to enable charging while running. So it's a good idea to fully charge the battery as your first item of business so there is no issue getting and maintaining satellite lock. The yellow charge indicator led will go out when the - battery is nearly full and the charger goes to trickle charge. + battery is nearly full and the charger goes to trickle charge. It + can takeseveral hours to fully recharge a deeply discharged battery. - The other active device in the starter kit is the half-duplex TeleDongle - rf link. If you plug it in to your computer it should "just work", - showing up as a serial port device. If you are using Linux and are + The other active device in the starter kit is the TeleDongle USB to + RF interface. If you plug it in to your Mac or Linux computer it should + "just work", showing up as a serial port device. Windows systems need + driver information that is part of the AltOS download to know that the + existing USB modem driver will work. If you are using Linux and are having problems, try moving to a fresher kernel (2.6.33 or newer), as - there were some ugly USB serial driver bugs in earlier versions. - - - Next you should obtain and install the AltOS utilities. The first - generation sofware was written for Linux only. New software is coming - soon that will also run on Windows and Mac. For now, we'll concentrate - on Linux. If you are using Debian, an 'altos' package already exists, - see http://altusmetrum.org/AltOS for details on how to install it. - User-contributed directions for building packages on ArchLinux may be - found in the contrib/arch-linux directory as PKGBUILD files. - Between the debian/rules file and the PKGBUILD files in - contrib, you should find enough information to learn how to build the - software for any other version of Linux. + the USB serial driver had ugly bugs in some earlier versions. - When you have successfully installed the software suite (either from - compiled source code or as the pre-built Debian package) you will - have 10 or so executable programs all of which have names beginning - with 'ao-'. - ('ao-view' is the lone GUI-based program, the rest are command-line - oriented.) You will also have man pages, that give you basic info - on each program. - You will also get this documentation in two file types in the doc/ - directory, telemetrum-doc.pdf and telemetrum-doc.html. - Finally you will have a couple control files that allow the ao-view - GUI-based program to appear in your menu of programs (under - the 'Internet' category). + Next you should obtain and install the AltOS utilities. These include + the AltosUI ground station program, current firmware images for + TeleMetrum and TeleDongle, and a number of standalone utilities that + are rarely needed. Pre-built binary packages are available for Debian + Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode + and build instructions for some other Linux variants are also available. + The latest version may always be downloaded from + http://altusmetrum.org/AltOS. Both Telemetrum and TeleDongle can be directly communicated @@ -764,8 +741,191 @@ sensor... nothing is permanently "lost" or "damaged" if the calibration is poor. + + In the unlikely event an accel cal that goes badly, it is possible + that TeleMetrum may always come up in 'pad mode' and as such not be + listening to either the USB or radio interfaces. If that happens, + there is a special hook in the firmware to force the board back + in to 'idle mode' so you can re-do the cal. To use this hook, you + just need to ground the SPI clock pin at power-on. This pin is + available as pin 2 on the 8-pin companion connector, and pin 1 is + ground. So either carefully install a fine-gauge wire jumper + between the two pins closest to the index hole end of the 8-pin + connector, or plug in the programming cable to the 8-pin connector + and use a small screwdriver or similar to short the two pins closest + to the index post on the 4-pin end of the programming cable, and + power up the board. It should come up in 'idle mode' (two beeps). +
+ + + +
+ Updating Device Firmware + + The big conceptual thing to realize is that you have to use a + TeleDongle as a programmer to update a TeleMetrum, and vice versa. + Due to limited memory resources in the cc1111, we don't support + programming either unit directly over USB. + + + You may wish to begin by ensuring you have current firmware images. + These are distributed as part of the AltOS software bundle that + also includes the AltosUI ground station program. Newer ground + station versions typically work fine with older firmware versions, + so you don't need to update your devices just to try out new + software features. You can always download the most recent + version from http://www.altusmetrum.org/AltOS/. + + + We recommend updating TeleMetrum first, before updating TeleDongle. + +
+ Updating TeleMetrum Firmware + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the + matching connector on the TeleDongle, and the 4-pin end to the + matching connector on the TeleMetrum. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMetrum, which should have a + name in the form telemetrum-v1.0-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMetrum with new firmware, showing a progress bar. + + + Confirm that the TeleMetrum board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. + + + If something goes wrong, give it another try. + + +
+
+ Updating TeleDongle Firmware + + Updating TeleDongle's firmware is just like updating TeleMetrum + firmware, but you switch which board is the programmer and which + is the programming target. + + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Find the USB cable that you got as part of the starter kit, and + plug the "mini" end in to the mating connector on TeleMetrum. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the (latching) + matching connector on the TeleMetrum, and the 4-pin end to the + matching connector on the TeleDongle. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board. + + + Plug both TeleMetrum and TeleDongle into your computer's USB + ports, and power up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleMetrum device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleDongle, which should have a + name in the form teledongle-v0.2-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. The TeleDongle + serial number is on the "bottom" of the circuit board, and can + usually be read through the translucent blue plastic case without + needing to remove the board from the case. + + + Hit the 'OK' button and the software should proceed to flash + the TeleDongle with new firmware, showing a progress bar. + + + Confirm that the TeleDongle board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. Once you're happy, remove the programming cable + and put the cover back on the TeleDongle. + + + If something goes wrong, give it another try. + + + + Be careful removing the programming cable from the locking 8-pin + connector on TeleMetrum. You'll need a fingernail or perhaps a thin + screwdriver or knife blade to gently pry the locking ears out + slightly to extract the connector. We used a locking connector on + TeleMetrum to help ensure that the cabling to companion boards + used in a rocket don't ever come loose accidentally in flight. + +
+
+ + + -- cgit v1.2.3 From bcf78b67717374b5971820021b83061e2e9734cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 21:39:18 -0800 Subject: doc: Reformat altos to use sections for each function This places them in the TOC, making them easier to find. Signed-off-by: Keith Packard --- doc/altos.xsl | 2105 +++++++++++++++++++++++++++------------------------------ 1 file changed, 983 insertions(+), 1122 deletions(-) diff --git a/doc/altos.xsl b/doc/altos.xsl index 9a88a5b5..295864fe 100644 --- a/doc/altos.xsl +++ b/doc/altos.xsl @@ -1,6 +1,6 @@ +"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd"> AltOS @@ -37,41 +37,41 @@ AltOS is a operating system built for the 8051-compatible processor found in the TI cc1111 microcontroller. It's designed to be small and easy to program with. The main features are: - - - Multi-tasking. While the 8051 doesn't provide separate - address spaces, it's often easier to write code that operates - in separate threads instead of tying everything into one giant - event loop. - - - - Non-preemptive. This increases latency for thread - switching but reduces the number of places where context - switching can occur. It also simplifies the operating system - design somewhat. Nothing in the target system (rocket flight - control) has tight timing requirements, and so this seems like - a reasonable compromise. - - - - Sleep/wakeup scheduling. Taken directly from ancient - Unix designs, these two provide the fundemental scheduling - primitive within AltOS. - - - - Mutexes. As a locking primitive, mutexes are easier to - use than semaphores, at least in my experience. - - - - Timers. Tasks can set an alarm which will abort any - pending sleep, allowing operations to time-out instead of - blocking forever. - - - + + + Multi-tasking. While the 8051 doesn't provide separate + address spaces, it's often easier to write code that operates + in separate threads instead of tying everything into one giant + event loop. + + + + Non-preemptive. This increases latency for thread + switching but reduces the number of places where context + switching can occur. It also simplifies the operating system + design somewhat. Nothing in the target system (rocket flight + control) has tight timing requirements, and so this seems like + a reasonable compromise. + + + + Sleep/wakeup scheduling. Taken directly from ancient + Unix designs, these two provide the fundemental scheduling + primitive within AltOS. + + + + Mutexes. As a locking primitive, mutexes are easier to + use than semaphores, at least in my experience. + + + + Timers. Tasks can set an alarm which will abort any + pending sleep, allowing operations to time-out instead of + blocking forever. + + + The device drivers and other subsystems in AltOS are @@ -82,28 +82,28 @@ may add tasks to the scheduler to handle the device. A typical main program, thus, looks like: -void -main(void) -{ - ao_clock_init(); + void + main(void) + { + ao_clock_init(); - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_slave_init(); - ao_packet_master_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_slave_init(); + ao_packet_master_init(); + #if HAS_DBG + ao_dbg_init(); + #endif + ao_config_init(); + ao_start_scheduler(); + } As you can see, a long sequence of subsystems are initialized and then the scheduler is started. @@ -137,96 +137,79 @@ main(void) code but makes the resulting code far smaller and more efficient. - - SDCC 8051 memory spaces - - __data - - - The 8051 can directly address these 128 bytes of - memory. This makes them precious so they should be - reserved for frequently addressed values. Oh, just to - confuse things further, the 8 general registers in the - CPU are actually stored in this memory space. There are - magic instructions to 'bank switch' among 4 banks of - these registers located at 0x00 - 0x1F. AltOS uses only - the first bank at 0x00 - 0x07, leaving the other 24 - bytes available for other data. - - - - - __idata - - - There are an additional 128 bytes of internal memory - that share the same address space as __data but which - cannot be directly addressed. The stack normally - occupies this space and so AltOS doesn't place any - static storage here. - - - - - __xdata - - - This is additional general memory accessed through a - single 16-bit address register. The CC1111F32 has 32kB - of memory available here. Most program data should live - in this memory space. - - - - - __pdata - - - This is an alias for the first 256 bytes of __xdata - memory, but uses a shorter addressing mode with - single global 8-bit value for the high 8 bits of the - address and any of several 8-bit registers for the low 8 - bits. AltOS uses a few bits of this memory, it should - probably use more. - - - - - __code - - - All executable code must live in this address space, but - you can stick read-only data here too. It is addressed - using the 16-bit address register and special 'code' - access opcodes. Anything read-only should live in this space. - - - - - __bit - - - The 8051 has 128 bits of bit-addressible memory that - lives in the __data segment from 0x20 through - 0x2f. Special instructions access these bits - in a single atomic operation. This isn't so much a - separate address space as a special addressing mode for - a few bytes in the __data segment. - - - - - __sfr, __sfr16, __sfr32, __sbit - - - Access to physical registers in the device use this mode - which declares the variable name, it's type and the - address it lives at. No memory is allocated for these - variables. - - - - +
+ __data + + The 8051 can directly address these 128 bytes of + memory. This makes them precious so they should be + reserved for frequently addressed values. Oh, just to + confuse things further, the 8 general registers in the + CPU are actually stored in this memory space. There are + magic instructions to 'bank switch' among 4 banks of + these registers located at 0x00 - 0x1F. AltOS uses only + the first bank at 0x00 - 0x07, leaving the other 24 + bytes available for other data. + +
+
+ __idata + + There are an additional 128 bytes of internal memory + that share the same address space as __data but which + cannot be directly addressed. The stack normally + occupies this space and so AltOS doesn't place any + static storage here. + +
+
+ __xdata + + This is additional general memory accessed through a + single 16-bit address register. The CC1111F32 has 32kB + of memory available here. Most program data should live + in this memory space. + +
+
+ __pdata + + This is an alias for the first 256 bytes of __xdata + memory, but uses a shorter addressing mode with + single global 8-bit value for the high 8 bits of the + address and any of several 8-bit registers for the low 8 + bits. AltOS uses a few bits of this memory, it should + probably use more. + +
+
+ __code + + All executable code must live in this address space, but + you can stick read-only data here too. It is addressed + using the 16-bit address register and special 'code' + access opcodes. Anything read-only should live in this space. + +
+
+ __bit + + The 8051 has 128 bits of bit-addressible memory that + lives in the __data segment from 0x20 through + 0x2f. Special instructions access these bits + in a single atomic operation. This isn't so much a + separate address space as a special addressing mode for + a few bytes in the __data segment. + +
+
+ __sfr, __sfr16, __sfr32, __sbit + + Access to physical registers in the device use this mode + which declares the variable name, it's type and the + address it lives at. No memory is allocated for these + variables. + +
Function calls on the 8051 @@ -305,124 +288,139 @@ main(void) This chapter documents how to create, destroy and schedule AltOS tasks. - - AltOS Task Functions - - ao_add_task - - -void -ao_add_task(__xdata struct ao_task * task, - void (*start)(void), - __code char *name); - - - This initializes the statically allocated task structure, - assigns a name to it (not used for anything but the task - display), and the start address. It does not switch to the - new task. 'start' must not ever return; there is no place - to return to. - - - - - ao_exit - - -void -ao_exit(void) - - - This terminates the current task. - - - - - ao_sleep - - -void -ao_sleep(__xdata void *wchan) - - - This suspends the current task until 'wchan' is signaled - by ao_wakeup, or until the timeout, set by ao_alarm, - fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise - it returns 1. This is the only way to switch to another task. - - - - - ao_wakeup - - -void -ao_wakeup(__xdata void *wchan) - - - Wake all tasks blocked on 'wchan'. This makes them - available to be run again, but does not actually switch - to another task. - - - - - ao_alarm - - -void -ao_alarm(uint16_t delay) - - - Schedules an alarm to fire in at least 'delay' ticks. If - the task is asleep when the alarm fires, it will wakeup - and ao_sleep will return 1. - - - - - ao_wake_task - - -void -ao_wake_task(__xdata struct ao_task *task) - - - Force a specific task to wake up, independent of which - 'wchan' it is waiting for. - - - - - ao_start_scheduler - - -void -ao_start_scheduler(void) - - - This is called from 'main' when the system is all - initialized and ready to run. It will not return. - - - - - ao_clock_init - - -void -ao_clock_init(void) - - - This turns on the external 48MHz clock then switches the - hardware to using it. This is required by many of the - internal devices like USB. It should be called by the - 'main' function first, before initializing any of the - other devices in the system. - - - - +
+ ao_add_task + + void + ao_add_task(__xdata struct ao_task * task, + void (*start)(void), + __code char *name); + + + This initializes the statically allocated task structure, + assigns a name to it (not used for anything but the task + display), and the start address. It does not switch to the + new task. 'start' must not ever return; there is no place + to return to. + +
+
+ ao_exit + + void + ao_exit(void) + + + This terminates the current task. + +
+
+ ao_sleep + + void + ao_sleep(__xdata void *wchan) + + + This suspends the current task until 'wchan' is signaled + by ao_wakeup, or until the timeout, set by ao_alarm, + fires. If 'wchan' is signaled, ao_sleep returns 0, otherwise + it returns 1. This is the only way to switch to another task. + + + Because ao_wakeup wakes every task waiting on a particular + location, ao_sleep should be used in a loop that first + checks the desired condition, blocks in ao_sleep and then + rechecks until the condition is satisfied. If the + location may be signaled from an interrupt handler, the + code will need to block interrupts by using the __critical + label around the block of code. Here's a complete example: + + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); + + +
+
+ ao_wakeup + + void + ao_wakeup(__xdata void *wchan) + + + Wake all tasks blocked on 'wchan'. This makes them + available to be run again, but does not actually switch + to another task. Here's an example of using this: + + if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } + + Note that this need not be enclosed in __critical as the + ao_sleep block can only be run from normal mode, and so + this sequence can never be interrupted with execution of + the other sequence. + +
+
+ ao_alarm + + void + ao_alarm(uint16_t delay) + + + Schedules an alarm to fire in at least 'delay' ticks. If + the task is asleep when the alarm fires, it will wakeup + and ao_sleep will return 1. + + ao_alarm(ao_packet_master_delay); + __critical while (!ao_radio_dma_done) + if (ao_sleep(&ao_radio_dma_done) != 0) + ao_radio_abort(); + + In this example, a timeout is set before waiting for + incoming radio data. If no data is received before the + timeout fires, ao_sleep will return 1 and then this code + will abort the radio receive operation. + +
+
+ ao_wake_task + + void + ao_wake_task(__xdata struct ao_task *task) + + + Force a specific task to wake up, independent of which + 'wchan' it is waiting for. + +
+
+ ao_start_scheduler + + void + ao_start_scheduler(void) + + + This is called from 'main' when the system is all + initialized and ready to run. It will not return. + +
+
+ ao_clock_init + + void + ao_clock_init(void) + + + This turns on the external 48MHz clock then switches the + hardware to using it. This is required by many of the + internal devices like USB. It should be called by the + 'main' function first, before initializing any of the + other devices in the system. + +
Timer Functions @@ -435,62 +433,51 @@ ao_clock_init(void) that the ADC values are sampled at a regular rate, independent of any scheduling jitter. - - AltOS Timer Functions - - ao_time - - -uint16_t -ao_time(void) - - - Returns the current system tick count. Note that this is - only a 16 bit value, and so it wraps every 655.36 seconds. - - - - - ao_delay - - -void -ao_delay(uint16_t ticks); - - - Suspend the current task for at least 'ticks' clock units. - - - - - ao_timer_set_adc_interval - - -void -ao_timer_set_adc_interval(uint8_t interval); - - - This sets the number of ticks between ADC samples. If set - to 0, no ADC samples are generated. AltOS uses this to - slow down the ADC sampling rate to save power. - - - - - ao_timer_init - - -void -ao_timer_init(void) - - - This turns on the 100Hz tick using the CC1111 timer 1. It - is required for any of the time-based functions to - work. It should be called by 'main' before ao_start_scheduler. - - - - +
+ ao_time + + uint16_t + ao_time(void) + + + Returns the current system tick count. Note that this is + only a 16 bit value, and so it wraps every 655.36 seconds. + +
+
+ ao_delay + + void + ao_delay(uint16_t ticks); + + + Suspend the current task for at least 'ticks' clock units. + +
+
+ ao_timer_set_adc_interval + + void + ao_timer_set_adc_interval(uint8_t interval); + + + This sets the number of ticks between ADC samples. If set + to 0, no ADC samples are generated. AltOS uses this to + slow down the ADC sampling rate to save power. + +
+
+ ao_timer_init + + void + ao_timer_init(void) + + + This turns on the 100Hz tick using the CC1111 timer 1. It + is required for any of the time-based functions to + work. It should be called by 'main' before ao_start_scheduler. + +
AltOS Mutexes @@ -502,35 +489,28 @@ ao_timer_init(void) already held by the current task or releasing a mutex not held by the current task will both cause a panic. - - Mutex Functions - - ao_mutex_get - - -void -ao_mutex_get(__xdata uint8_t *mutex); - - - Acquires the specified mutex, blocking if the mutex is - owned by another task. - - - - - ao_mutex_put - - -void -ao_mutex_put(__xdata uint8_t *mutex); - - - Releases the specified mutex, waking up all tasks waiting - for it. - - - - +
+ ao_mutex_get + + void + ao_mutex_get(__xdata uint8_t *mutex); + + + Acquires the specified mutex, blocking if the mutex is + owned by another task. + +
+
+ ao_mutex_put + + void + ao_mutex_put(__xdata uint8_t *mutex); + + + Releases the specified mutex, waking up all tasks waiting + for it. + +
CC1111 DMA engine @@ -554,86 +534,73 @@ ao_mutex_put(__xdata uint8_t *mutex); hardware device. When copying data from memory to hardware, the transfer is usually initiated by software. - - AltOS DMA functions - - ao_dma_alloc - - -uint8_t -ao_dma_alloc(__xdata uint8_t *done) - - - Allocates a DMA engine, returning the identifier. Whenever - this DMA engine completes a transfer. 'done' is cleared - when the DMA is started, and then receives the - AO_DMA_DONE bit on a successful transfer or the - AO_DMA_ABORTED bit if ao_dma_abort was called. Note that - it is possible to get both bits if the transfer was - aborted after it had finished. - - - - - ao_dma_set_transfer - - -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1) - - - Initializes the specified dma engine to copy data - from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and - cfg1 are values directly out of the CC1111 documentation - and tell the DMA engine what the transfer unit size, - direction and step are. - - - - - ao_dma_start - - -void -ao_dma_start(uint8_t id); - - - Arm the specified DMA engine and await a signal from - either hardware or software to start transferring data. - - - - - ao_dma_trigger - - -void -ao_dma_trigger(uint8_t id) - - - Trigger the specified DMA engine to start copying data. - - - - - ao_dma_abort - - -void -ao_dma_abort(uint8_t id) - - - Terminate any in-progress DMA transation, marking its - 'done' variable with the AO_DMA_ABORTED bit. - - - - +
+ ao_dma_alloc + + uint8_t + ao_dma_alloc(__xdata uint8_t *done) + + + Allocates a DMA engine, returning the identifier. Whenever + this DMA engine completes a transfer. 'done' is cleared + when the DMA is started, and then receives the + AO_DMA_DONE bit on a successful transfer or the + AO_DMA_ABORTED bit if ao_dma_abort was called. Note that + it is possible to get both bits if the transfer was + aborted after it had finished. + +
+
+ ao_dma_set_transfer + + void + ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) + + + Initializes the specified dma engine to copy data + from 'srcaddr' to 'dstaddr' for 'count' units. cfg0 and + cfg1 are values directly out of the CC1111 documentation + and tell the DMA engine what the transfer unit size, + direction and step are. + +
+
+ ao_dma_start + + void + ao_dma_start(uint8_t id); + + + Arm the specified DMA engine and await a signal from + either hardware or software to start transferring data. + +
+
+ ao_dma_trigger + + void + ao_dma_trigger(uint8_t id) + + + Trigger the specified DMA engine to start copying data. + +
+
+ ao_dma_abort + + void + ao_dma_abort(uint8_t id) + + + Terminate any in-progress DMA transation, marking its + 'done' variable with the AO_DMA_ABORTED bit. + +
SDCC Stdio interface @@ -646,82 +613,71 @@ ao_dma_abort(uint8_t id) channels; output is always delivered to the channel which provided the most recent input. - - SDCC stdio functions - - putchar - - -void -putchar(char c) - - - Delivers a single character to the current console - device. - - - - - getchar - - -char -getchar(void) - - - Reads a single character from any of the available - console devices. The current console device is set to - that which delivered this character. This blocks until - a character is available. - - - - - flush - - -void -flush(void) - - - Flushes the current console device output buffer. Any - pending characters will be delivered to the target device. -xo - - - - ao_add_stdio - - -void -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char), - void (*flush)(void)) - - - This adds another console device to the available - list. - - - 'pollchar' returns either an available character or - AO_READ_AGAIN if none is available. Significantly, it does - not block. The device driver must set 'ao_stdin_ready' to - 1 and call ao_wakeup(&ao_stdin_ready) when it receives - input to tell getchar that more data is available, at - which point 'pollchar' will be called again. - - - 'putchar' queues a character for output, flushing if the output buffer is - full. It may block in this case. - - - 'flush' forces the output buffer to be flushed. It may - block until the buffer is delivered, but it is not - required to do so. - - - - +
+ putchar + + void + putchar(char c) + + + Delivers a single character to the current console + device. + +
+
+ getchar + + char + getchar(void) + + + Reads a single character from any of the available + console devices. The current console device is set to + that which delivered this character. This blocks until + a character is available. + +
+
+ flush + + void + flush(void) + + + Flushes the current console device output buffer. Any + pending characters will be delivered to the target device. + xo +
+
+ ao_add_stdio + + void + ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) + + + This adds another console device to the available + list. + + + 'pollchar' returns either an available character or + AO_READ_AGAIN if none is available. Significantly, it does + not block. The device driver must set 'ao_stdin_ready' to + 1 and call ao_wakeup(&ao_stdin_ready) when it receives + input to tell getchar that more data is available, at + which point 'pollchar' will be called again. + + + 'putchar' queues a character for output, flushing if the output buffer is + full. It may block in this case. + + + 'flush' forces the output buffer to be flushed. It may + block until the buffer is delivered, but it is not + required to do so. + +
Command line interface @@ -732,176 +688,155 @@ ao_add_stdio(char (*pollchar)(void), character to invoke it, the remaining characters on the line are available as parameters to the command. - - AltOS command line parsing functions - - ao_cmd_register - - -void -ao_cmd_register(__code struct ao_cmds *cmds) - - - This registers a set of commands with the command - parser. There is a fixed limit on the number of command - sets, the system will panic if too many are registered. - Each command is defined by a struct ao_cmds entry: - -struct ao_cmds { - char cmd; - void (*func)(void); - const char *help; -}; - - 'cmd' is the character naming the command. 'func' is the - function to invoke and 'help' is a string displayed by the - '?' command. Syntax errors found while executing 'func' - should be indicated by modifying the global ao_cmd_status - variable with one of the following values: - - - ao_cmd_success - - - The command was parsed successfully. There is no - need to assign this value, it is the default. - - - - - ao_cmd_lex_error - - - A token in the line was invalid, such as a number - containing invalid characters. The low-level - lexing functions already assign this value as needed. - - - - - ao_syntax_error - - - The command line is invalid for some reason other - than invalid tokens. - - - - - - - - - ao_cmd_lex - - -void -ao_cmd_lex(void); - - - This gets the next character out of the command line - buffer and sticks it into ao_cmd_lex_c. At the end of the - line, ao_cmd_lex_c will get a newline ('\n') character. - - - - - ao_cmd_put16 - - -void -ao_cmd_put16(uint16_t v); - - - Writes 'v' as four hexadecimal characters. - - - - - ao_cmd_put8 - - -void -ao_cmd_put8(uint8_t v); - - - Writes 'v' as two hexadecimal characters. - - - - - ao_cmd_white - - -void -ao_cmd_white(void) - - - This skips whitespace by calling ao_cmd_lex while - ao_cmd_lex_c is either a space or tab. It does not skip - any characters if ao_cmd_lex_c already non-white. - - - - - ao_cmd_hex - - -void -ao_cmd_hex(void) - - - This reads a 16-bit hexadecimal value from the command - line with optional leading whitespace. The resulting value - is stored in ao_cmd_lex_i; - - - - - ao_cmd_decimal - - -void -ao_cmd_decimal(void) - - - This reads a 32-bit decimal value from the command - line with optional leading whitespace. The resulting value - is stored in ao_cmd_lex_u32 and the low 16 bits are stored - in ao_cmd_lex_i; - - - - - ao_match_word - - -uint8_t -ao_match_word(__code char *word) - - - This checks to make sure that 'word' occurs on the command - line. It does not skip leading white space. If 'word' is - found, then 1 is returned. Otherwise, ao_cmd_status is set to - ao_cmd_syntax_error and 0 is returned. - - - - - ao_cmd_init - - -void -ao_cmd_init(void - - - Initializes the command system, setting up the built-in - commands and adding a task to run the command processing - loop. It should be called by 'main' before ao_start_scheduler. - - - - +
+ ao_cmd_register + + void + ao_cmd_register(__code struct ao_cmds *cmds) + + + This registers a set of commands with the command + parser. There is a fixed limit on the number of command + sets, the system will panic if too many are registered. + Each command is defined by a struct ao_cmds entry: + + struct ao_cmds { + char cmd; + void (*func)(void); + const char *help; + }; + + 'cmd' is the character naming the command. 'func' is the + function to invoke and 'help' is a string displayed by the + '?' command. Syntax errors found while executing 'func' + should be indicated by modifying the global ao_cmd_status + variable with one of the following values: + + + ao_cmd_success + + + The command was parsed successfully. There is no + need to assign this value, it is the default. + + + + + ao_cmd_lex_error + + + A token in the line was invalid, such as a number + containing invalid characters. The low-level + lexing functions already assign this value as needed. + + + + + ao_syntax_error + + + The command line is invalid for some reason other + than invalid tokens. + + + + + +
+
+ ao_cmd_lex + + void + ao_cmd_lex(void); + + + This gets the next character out of the command line + buffer and sticks it into ao_cmd_lex_c. At the end of the + line, ao_cmd_lex_c will get a newline ('\n') character. + +
+
+ ao_cmd_put16 + + void + ao_cmd_put16(uint16_t v); + + + Writes 'v' as four hexadecimal characters. + +
+
+ ao_cmd_put8 + + void + ao_cmd_put8(uint8_t v); + + + Writes 'v' as two hexadecimal characters. + +
+
+ ao_cmd_white + + void + ao_cmd_white(void) + + + This skips whitespace by calling ao_cmd_lex while + ao_cmd_lex_c is either a space or tab. It does not skip + any characters if ao_cmd_lex_c already non-white. + +
+
+ ao_cmd_hex + + void + ao_cmd_hex(void) + + + This reads a 16-bit hexadecimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_i; + +
+
+ ao_cmd_decimal + + void + ao_cmd_decimal(void) + + + This reads a 32-bit decimal value from the command + line with optional leading whitespace. The resulting value + is stored in ao_cmd_lex_u32 and the low 16 bits are stored + in ao_cmd_lex_i; + +
+
+ ao_match_word + + uint8_t + ao_match_word(__code char *word) + + + This checks to make sure that 'word' occurs on the command + line. It does not skip leading white space. If 'word' is + found, then 1 is returned. Otherwise, ao_cmd_status is set to + ao_cmd_syntax_error and 0 is returned. + +
+
+ ao_cmd_init + + void + ao_cmd_init(void + + + Initializes the command system, setting up the built-in + commands and adding a task to run the command processing + loop. It should be called by 'main' before ao_start_scheduler. + +
CC1111 USB target device @@ -921,121 +856,104 @@ ao_cmd_init(void USB link. Alternatively, the functions can be accessed directly to provide for USB-specific I/O. - - AltOS USB functions - - ao_usb_flush - - -void -ao_usb_flush(void); - - - Flushes any pending USB output. This queues an 'IN' packet - to be delivered to the USB host if there is pending data, - or if the last IN packet was full to indicate to the host - that there isn't any more pending data available. - - - - - ao_usb_putchar - - -void -ao_usb_putchar(char c); - - - If there is a pending 'IN' packet awaiting delivery to the - host, this blocks until that has been fetched. Then, this - adds a byte to the pending IN packet for delivery to the - USB host. If the USB packet is full, this queues the 'IN' - packet for delivery. - - - - - ao_usb_pollchar - - -char -ao_usb_pollchar(void); - - - If there are no characters remaining in the last 'OUT' - packet received, this returns AO_READ_AGAIN. Otherwise, it - returns the next character, reporting to the host that it - is ready for more data when the last character is gone. - - - - - ao_usb_getchar - - -char -ao_usb_getchar(void); - - - This uses ao_pollchar to receive the next character, - blocking while ao_pollchar returns AO_READ_AGAIN. - - - - - ao_usb_disable - - -void -ao_usb_disable(void); - - - This turns off the USB controller. It will no longer - respond to host requests, nor return characters. Calling - any of the i/o routines while the USB device is disabled - is undefined, and likely to break things. Disabling the - USB device when not needed saves power. - - - Note that neither TeleDongle nor TeleMetrum are able to - signal to the USB host that they have disconnected, so - after disabling the USB device, it's likely that the cable - will need to be disconnected and reconnected before it - will work again. - - - - - ao_usb_enable - - -void -ao_usb_enable(void); - - - This turns the USB controller on again after it has been - disabled. See the note above about needing to physically - remove and re-insert the cable to get the host to - re-initialize the USB link. - - - - - ao_usb_init - - -void -ao_usb_init(void); - - - This turns the USB controller on, adds a task to handle - the control end point and adds the usb I/O functions to - the stdio system. Call this from main before - ao_start_scheduler. - - - - +
+ ao_usb_flush + + void + ao_usb_flush(void); + + + Flushes any pending USB output. This queues an 'IN' packet + to be delivered to the USB host if there is pending data, + or if the last IN packet was full to indicate to the host + that there isn't any more pending data available. + +
+
+ ao_usb_putchar + + void + ao_usb_putchar(char c); + + + If there is a pending 'IN' packet awaiting delivery to the + host, this blocks until that has been fetched. Then, this + adds a byte to the pending IN packet for delivery to the + USB host. If the USB packet is full, this queues the 'IN' + packet for delivery. + +
+
+ ao_usb_pollchar + + char + ao_usb_pollchar(void); + + + If there are no characters remaining in the last 'OUT' + packet received, this returns AO_READ_AGAIN. Otherwise, it + returns the next character, reporting to the host that it + is ready for more data when the last character is gone. + +
+
+ ao_usb_getchar + + char + ao_usb_getchar(void); + + + This uses ao_pollchar to receive the next character, + blocking while ao_pollchar returns AO_READ_AGAIN. + +
+
+ ao_usb_disable + + void + ao_usb_disable(void); + + + This turns off the USB controller. It will no longer + respond to host requests, nor return characters. Calling + any of the i/o routines while the USB device is disabled + is undefined, and likely to break things. Disabling the + USB device when not needed saves power. + + + Note that neither TeleDongle nor TeleMetrum are able to + signal to the USB host that they have disconnected, so + after disabling the USB device, it's likely that the cable + will need to be disconnected and reconnected before it + will work again. + +
+
+ ao_usb_enable + + void + ao_usb_enable(void); + + + This turns the USB controller on again after it has been + disabled. See the note above about needing to physically + remove and re-insert the cable to get the host to + re-initialize the USB link. + +
+
+ ao_usb_init + + void + ao_usb_init(void); + + + This turns the USB controller on, adds a task to handle + the control end point and adds the usb I/O functions to + the stdio system. Call this from main before + ao_start_scheduler. + +
CC1111 Serial peripheral @@ -1052,77 +970,64 @@ ao_usb_init(void); To prevent loss of data, AltOS provides receive and transmit fifos of 32 characters each. - - AltOS serial functions - - ao_serial_getchar - - -char -ao_serial_getchar(void); - - - Returns the next character from the receive fifo, blocking - until a character is received if the fifo is empty. - - - - - ao_serial_putchar - - -void -ao_serial_putchar(char c); - - - Adds a character to the transmit fifo, blocking if the - fifo is full. Starts transmitting characters. - - - - - ao_serial_drain - - -void -ao_serial_drain(void); - - - Blocks until the transmit fifo is empty. Used internally - when changing serial speeds. - - - - - ao_serial_set_speed - - -void -ao_serial_set_speed(uint8_t speed); - - - Changes the serial baud rate to one of - AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or - AO_SERIAL_SPEED_57600. This first flushes the transmit - fifo using ao_serial_drain. - - - - - ao_serial_init - - -void -ao_serial_init(void) - - - Initializes the serial peripheral. Call this from 'main' - before jumping to ao_start_scheduler. The default speed - setting is AO_SERIAL_SPEED_4800. - - - - +
+ ao_serial_getchar + + char + ao_serial_getchar(void); + + + Returns the next character from the receive fifo, blocking + until a character is received if the fifo is empty. + +
+
+ ao_serial_putchar + + void + ao_serial_putchar(char c); + + + Adds a character to the transmit fifo, blocking if the + fifo is full. Starts transmitting characters. + +
+
+ ao_serial_drain + + void + ao_serial_drain(void); + + + Blocks until the transmit fifo is empty. Used internally + when changing serial speeds. + +
+
+ ao_serial_set_speed + + void + ao_serial_set_speed(uint8_t speed); + + + Changes the serial baud rate to one of + AO_SERIAL_SPEED_4800, AO_SERIAL_SPEED_9600 or + AO_SERIAL_SPEED_57600. This first flushes the transmit + fifo using ao_serial_drain. + +
+
+ ao_serial_init + + void + ao_serial_init(void) + + + Initializes the serial peripheral. Call this from 'main' + before jumping to ao_start_scheduler. The default speed + setting is AO_SERIAL_SPEED_4800. + +
CC1111 Radio peripheral @@ -1177,265 +1082,221 @@ ao_serial_init(void) - - AltOS radio functions - - ao_radio_set_telemetry - - -void -ao_radio_set_telemetry(void); - - - Configures the radio to send or receive telemetry - packets. This includes packet length, modulation scheme and - other RF parameters. It does not include the base frequency - or channel though. Those are set at the time of transmission - or reception, in case the values are changed by the user. - - - - - ao_radio_set_packet - - -void -ao_radio_set_packet(void); - - - Configures the radio to send or receive packet data. This - includes packet length, modulation scheme and other RF - parameters. It does not include the base frequency or - channel though. Those are set at the time of transmission or - reception, in case the values are changed by the user. - - - - - ao_radio_set_rdf - - -void -ao_radio_set_rdf(void); - - - Configures the radio to send RDF 'packets'. An RDF 'packet' - is a sequence of hex 0x55 bytes sent at a base bit rate of - 2kbps using a 5kHz deviation. All of the error correction - and data whitening logic is turned off so that the resulting - modulation is received as a 1kHz tone by a conventional 70cm - FM audio receiver. - - - - - ao_radio_idle - - -void -ao_radio_idle(void); - - - Sets the radio device to idle mode, waiting until it reaches - that state. This will terminate any in-progress transmit or - receive operation. - - - - - ao_radio_get - - -void -ao_radio_get(void); - - - Acquires the radio mutex and then configures the radio - frequency using the global radio calibration and channel - values. - - - - - ao_radio_put - - -void -ao_radio_put(void); - - - Releases the radio mutex. - - - - - ao_radio_abort - - -void -ao_radio_abort(void); - - - Aborts any transmission or reception process by aborting the - associated DMA object and calling ao_radio_idle to terminate - the radio operation. - - - - - - AltOS radio telemetry functions - - In telemetry mode, you can send or receive a telemetry - packet. The data from receiving a packet also includes the RSSI - and status values supplied by the receiver. These are added - after the telemetry data. - - - ao_radio_send - - -void -ao_radio_send(__xdata struct ao_telemetry *telemetry); - - - This sends the specific telemetry packet, waiting for the - transmission to complete. The radio must have been set to - telemetry mode. This function calls ao_radio_get() before - sending, and ao_radio_put() afterwards, to correctly - serialize access to the radio device. - - - - - ao_radio_recv - - -void -ao_radio_recv(__xdata struct ao_radio_recv *radio); - - - This blocks waiting for a telemetry packet to be received. - The radio must have been set to telemetry mode. This - function calls ao_radio_get() before receiving, and - ao_radio_put() afterwards, to correctly serialize access - to the radio device. This returns non-zero if a packet was - received, or zero if the operation was aborted (from some - other task calling ao_radio_abort()). - - - - - - AltOS radio direction finding function - - In radio direction finding mode, there's just one function to - use - - - ao_radio_rdf - - -void -ao_radio_rdf(int ms); - - - This sends an RDF packet lasting for the specified amount - of time. The maximum length is 1020 ms. - - - - - - Packet mode functions - - Packet mode is asymmetrical and is configured at compile time - for either master or slave mode (but not both). The basic I/O - functions look the same at both ends, but the internals are - different, along with the initialization steps. - - - ao_packet_putchar - - -void -ao_packet_putchar(char c); - - - If the output queue is full, this first blocks waiting for - that data to be delivered. Then, queues a character for - packet transmission. On the master side, this will - transmit a packet if the output buffer is full. On the - slave side, any pending data will be sent the next time - the master polls for data. - - - - - ao_packet_pollchar - - -char -ao_packet_pollchar(void); - - - This returns a pending input character if available, - otherwise returns AO_READ_AGAIN. On the master side, if - this empties the buffer, it triggers a poll for more data. - - - - - ao_packet_slave_start - - -void -ao_packet_slave_start(void); - - - This is available only on the slave side and starts a task - to listen for packet data. - - - - - ao_packet_slave_stop - - -void -ao_packet_slave_stop(void); - - - Disables the packet slave task, stopping the radio receiver. - - - - - ao_packet_slave_init - - -void -ao_packet_slave_init(void); - - - Adds the packet stdio functions to the stdio package so - that when packet slave mode is enabled, characters will - get send and received through the stdio functions. - - - - - ao_packet_master_init - - -void -ao_packet_master_init(void); - - - Adds the 'p' packet forward command to start packet mode. - - - - +
+ ao_radio_set_telemetry + + void + ao_radio_set_telemetry(void); + + + Configures the radio to send or receive telemetry + packets. This includes packet length, modulation scheme and + other RF parameters. It does not include the base frequency + or channel though. Those are set at the time of transmission + or reception, in case the values are changed by the user. + +
+
+ ao_radio_set_packet + + void + ao_radio_set_packet(void); + + + Configures the radio to send or receive packet data. This + includes packet length, modulation scheme and other RF + parameters. It does not include the base frequency or + channel though. Those are set at the time of transmission or + reception, in case the values are changed by the user. + +
+
+ ao_radio_set_rdf + + void + ao_radio_set_rdf(void); + + + Configures the radio to send RDF 'packets'. An RDF 'packet' + is a sequence of hex 0x55 bytes sent at a base bit rate of + 2kbps using a 5kHz deviation. All of the error correction + and data whitening logic is turned off so that the resulting + modulation is received as a 1kHz tone by a conventional 70cm + FM audio receiver. + +
+
+ ao_radio_idle + + void + ao_radio_idle(void); + + + Sets the radio device to idle mode, waiting until it reaches + that state. This will terminate any in-progress transmit or + receive operation. + +
+
+ ao_radio_get + + void + ao_radio_get(void); + + + Acquires the radio mutex and then configures the radio + frequency using the global radio calibration and channel + values. + +
+
+ ao_radio_put + + void + ao_radio_put(void); + + + Releases the radio mutex. + +
+
+ ao_radio_abort + + void + ao_radio_abort(void); + + + Aborts any transmission or reception process by aborting the + associated DMA object and calling ao_radio_idle to terminate + the radio operation. + +
+ + In telemetry mode, you can send or receive a telemetry + packet. The data from receiving a packet also includes the RSSI + and status values supplied by the receiver. These are added + after the telemetry data. + +
+ ao_radio_send + + void + ao_radio_send(__xdata struct ao_telemetry *telemetry); + + + This sends the specific telemetry packet, waiting for the + transmission to complete. The radio must have been set to + telemetry mode. This function calls ao_radio_get() before + sending, and ao_radio_put() afterwards, to correctly + serialize access to the radio device. + +
+
+ ao_radio_recv + + void + ao_radio_recv(__xdata struct ao_radio_recv *radio); + + + This blocks waiting for a telemetry packet to be received. + The radio must have been set to telemetry mode. This + function calls ao_radio_get() before receiving, and + ao_radio_put() afterwards, to correctly serialize access + to the radio device. This returns non-zero if a packet was + received, or zero if the operation was aborted (from some + other task calling ao_radio_abort()). + +
+ + In radio direction finding mode, there's just one function to + use + +
+ ao_radio_rdf + + void + ao_radio_rdf(int ms); + + + This sends an RDF packet lasting for the specified amount + of time. The maximum length is 1020 ms. + +
+ + Packet mode is asymmetrical and is configured at compile time + for either master or slave mode (but not both). The basic I/O + functions look the same at both ends, but the internals are + different, along with the initialization steps. + +
+ ao_packet_putchar + + void + ao_packet_putchar(char c); + + + If the output queue is full, this first blocks waiting for + that data to be delivered. Then, queues a character for + packet transmission. On the master side, this will + transmit a packet if the output buffer is full. On the + slave side, any pending data will be sent the next time + the master polls for data. + +
+
+ ao_packet_pollchar + + char + ao_packet_pollchar(void); + + + This returns a pending input character if available, + otherwise returns AO_READ_AGAIN. On the master side, if + this empties the buffer, it triggers a poll for more data. + +
+
+ ao_packet_slave_start + + void + ao_packet_slave_start(void); + + + This is available only on the slave side and starts a task + to listen for packet data. + +
+
+ ao_packet_slave_stop + + void + ao_packet_slave_stop(void); + + + Disables the packet slave task, stopping the radio receiver. + +
+
+ ao_packet_slave_init + + void + ao_packet_slave_init(void); + + + Adds the packet stdio functions to the stdio package so + that when packet slave mode is enabled, characters will + get send and received through the stdio functions. + +
+
+ ao_packet_master_init + + void + ao_packet_master_init(void); + + + Adds the 'p' packet forward command to start packet mode. + +
-- cgit v1.2.3 From 554bdd25e132dbaec322bc11f94093d2c2e78751 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 22:49:33 -0800 Subject: doc: Add more authors, fix URL formatting, note that AltosUI actually exists Add aj and bfinch as authors. Insert an acknowledgements section. Fill in the Fire Igniter section in the AltosUI chapter. Then change the section talking about the future plans for Java to mention that they actually exist now. Signed-off-by: Keith Packard --- doc/telemetrum-doc.xsl | 111 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 87 insertions(+), 24 deletions(-) diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl index e75e10b5..0c20b285 100644 --- a/doc/telemetrum-doc.xsl +++ b/doc/telemetrum-doc.xsl @@ -2,8 +2,8 @@ - TeleMetrum - Owner's Manual for the TeleMetrum System + The Altus Metrum System + Owner's Manual for TeleMetrum and TeleDongle Devices Bdale @@ -13,6 +13,14 @@ Keith Packard + + Bob + Finch + + + Anthony + Towns + 2010 Bdale Garbee and Keith Packard @@ -34,6 +42,34 @@ + + + Thanks to Bob Finch, W9YA, NAR 12965, TRA 12350 for writing "The + Mere-Mortals Quick Start/Usage Guide to the Altus Metrum Starter + Kit" which has turned into the Getting Started chapter in this + book. Bob was one of our first customers for a production + TeleMetrum, and the enthusiasm that led to his contribution of + this section is immensely gratifying and highy appreciated! + + + And thanks to Anthony (AJ) Towns for contributing the + AltosUI graphing and site map code and documentation. Free + software means that our customers and friends can become our + collaborators, and we certainly appreciate this level of + contribution. + + + Have fun using these products, and we hope to meet all of you + out on the rocket flight line somewhere. + +Bdale Garbee, KB0G +NAR #87103, TRA #12201 + +Keith Packard, KD7SQG +NAR #88757, TRA #12200 + + + Introduction and Overview @@ -66,18 +102,11 @@ Getting Started - - This chapter began as "The Mere-Mortals Quick Start/Usage Guide to - the Altus Metrum Starter Kit" by Bob Finch, W9YA, NAR 12965, TRA 12350, - w9ya@amsat.org. Bob was one of our first customers for a production - TeleMetrum, and the enthusiasm that led to his contribution of this - section is immensely gratifying and highy appreciated! - The first thing to do after you check the inventory of parts in your "starter kit" is to charge the battery by plugging it into the corresponding socket of the TeleMetrum and then using the USB A to -mini B + mini B cable to plug the Telemetrum into your computer's USB socket. The TeleMetrum circuitry will charge the battery whenever it is plugged in, because the TeleMetrum's on-off switch does NOT control the @@ -90,7 +119,7 @@ mini B first item of business so there is no issue getting and maintaining satellite lock. The yellow charge indicator led will go out when the battery is nearly full and the charger goes to trickle charge. It - can takeseveral hours to fully recharge a deeply discharged battery. + can take several hours to fully recharge a deeply discharged battery. The other active device in the starter kit is the TeleDongle USB to @@ -99,7 +128,7 @@ mini B driver information that is part of the AltOS download to know that the existing USB modem driver will work. If you are using Linux and are having problems, try moving to a fresher kernel (2.6.33 or newer), as - the USB serial driver had ugly bugs in some earlier versions. + the USB serial driver had ugly bugs in some earlier versions. Next you should obtain and install the AltOS utilities. These include @@ -109,7 +138,7 @@ mini B Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode and build instructions for some other Linux variants are also available. The latest version may always be downloaded from - http://altusmetrum.org/AltOS. + . Both Telemetrum and TeleDongle can be directly communicated @@ -642,7 +671,7 @@ mini B primary and backup pyrotechnic charges do not fire simultaneously. - To set the apogee delay, use the [FIXME] command. + To set the apogee delay, use the 'c d' command. As with all 'c' sub-commands, follow this with a 'c w' to write the change to the parameter block in the on-board DataFlash chip. @@ -670,7 +699,7 @@ mini B simultaneously. - To set the main deployment altitude, use the [FIXME] command. + To set the main deployment altitude, use the 'c m' command. As with all 'c' sub-commands, follow this with a 'c w' to write the change to the parameter block in the on-board DataFlash chip. @@ -776,7 +805,7 @@ mini B station versions typically work fine with older firmware versions, so you don't need to update your devices just to try out new software features. You can always download the most recent - version from http://www.altusmetrum.org/AltOS/. + version from . We recommend updating TeleMetrum first, before updating TeleDongle. @@ -958,6 +987,19 @@ mini B the list of devices is presented and AltosUI will use packet command mode. + + One oddity in the current interface is how AltosUI selects the + channel for packet mode communications. Instead of providing + an interface to specifically configure the channel, it uses + whatever channel was most recently selected for the target + TeleDongle device in Monitor Flight mode. If you haven't ever + used that mode with the TeleDongle in question, select the + Monitor Flight button from the top level UI, pick the + appropriate TeleDongle device. Once the flight monitoring + window is open, select the desired channel and then close it + down again. All Packet Command Mode operations will now use + that channel. + @@ -1529,6 +1571,28 @@ mini B
Fire Igniter + This activates the igniter circuits in TeleMetrum to help test + recovery systems deployment. Because this command can operate + over the Packet Command Link, you can prepare the rocket as + for flight and then test the recovery system without needing + to snake wires inside the airframe. + + + Selecting the 'Fire Igniter' button brings up the usual device + selection dialog. Pick the desired TeleDongle or TeleMetrum + device. This brings up another window which shows the current + continutity test status for both apogee and main charges. + + + Next, select the desired igniter to fire. This will enable the + 'Arm' button. + + + Select the 'Arm' button. This enables the 'Fire' button. The + word 'Arm' is replaced by a countdown timer indicating that + you have 10 seconds to press the 'Fire' button or the system + will deactivate, at which point you start over again at + selecting the desired igniter.
@@ -1537,16 +1601,16 @@ mini B
Being Legal - First off, in the US, you need an [amateur radio license](../Radio) or + First off, in the US, you need an amateur radio license or other authorization to legally operate the radio transmitters that are part of our products.
In the Rocket - In the rocket itself, you just need a [TeleMetrum](../TeleMetrum) board and + In the rocket itself, you just need a TeleMetrum board and a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a [TeleMetrum](../TeleMetrum) for hours. + alkaline battery, and will run a TeleMetrum for hours. By default, we ship TeleMetrum with a simple wire antenna. If your @@ -1560,16 +1624,15 @@ mini B On the Ground To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our [TeleDongle](../TeleDongle) units. The + feedline connected to one of our TeleDongle units. The TeleDongle in turn plugs directly into the USB port on a notebook computer. Because TeleDongle looks like a simple serial port, your computer does not require special device drivers... just plug it in. - Right now, all of our application software is written for Linux. However, - because we understand that many people run Windows or MacOS, we are working - on a new ground station program written in Java that should work on all - operating systems. + The GUI tool, AltosUI, is written in Java and runs across + Linux, Mac OS and Windows. There's also a suite of C tools + for Linux which can perform most of the same tasks. After the flight, you can use the RF link to extract the more detailed data -- cgit v1.2.3 From cb08bc264c71ca972027392b42f347a03df76a43 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 22:55:08 -0800 Subject: doc: Rename telemetrum-doc as altusmetrum Signed-off-by: Keith Packard --- doc/Makefile | 10 +- doc/altusmetrum.xsl | 1734 +++++++++++++++++++++++++++++++++++++++++++++++ doc/telemetrum-doc.xsl | 1735 ------------------------------------------------ 3 files changed, 1739 insertions(+), 1740 deletions(-) create mode 100644 doc/altusmetrum.xsl delete mode 100644 doc/telemetrum-doc.xsl diff --git a/doc/Makefile b/doc/Makefile index 65917ea2..14f9bee2 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,8 +2,8 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -HTML=telemetrum-doc.html altos.html -PDF=telemetrum-doc.pdf altos.pdf +HTML=altusmetrum.html altos.html +PDF=altusmetrum.pdf altos.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl @@ -23,7 +23,7 @@ PDFSTYLE= all: $(HTML) $(PDF) publish: $(DOC) - cp $(DOC)telemetrum-doc.html home/bdale/web/altusmetrum/TeleMetrum/doc/ + cp $(DOC)altusmetrum.html home/bdale/web/altusmetrum/TeleMetrum/doc/ (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/TeleMetrum/doc/* ; git push) clean: @@ -32,6 +32,6 @@ clean: distclean: rm -f *.html *.pdf *.fo -indent: telemetrum-doc.xsl - xmlindent -i 2 < telemetrum-doc.xsl > telemetrum-doc.new +indent: altusmetrum.xsl + xmlindent -i 2 < altusmetrum.xsl > altusmetrum.new diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl new file mode 100644 index 00000000..8d4230f8 --- /dev/null +++ b/doc/altusmetrum.xsl @@ -0,0 +1,1734 @@ + + + + The Altus Metrum System + An Owner's Manual for TeleMetrum and TeleDongle Devices + + + Bdale + Garbee + + + Keith + Packard + + + Bob + Finch + + + Anthony + Towns + + + 2010 + Bdale Garbee and Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.8 + 24 November 2010 + Updated for software version 0.8 + + + + + + Thanks to Bob Finch, W9YA, NAR 12965, TRA 12350 for writing "The + Mere-Mortals Quick Start/Usage Guide to the Altus Metrum Starter + Kit" which has turned into the Getting Started chapter in this + book. Bob was one of our first customers for a production + TeleMetrum, and the enthusiasm that led to his contribution of + this section is immensely gratifying and highy appreciated! + + + And thanks to Anthony (AJ) Towns for contributing the + AltosUI graphing and site map code and documentation. Free + software means that our customers and friends can become our + collaborators, and we certainly appreciate this level of + contribution. + + + Have fun using these products, and we hope to meet all of you + out on the rocket flight line somewhere. + +Bdale Garbee, KB0G +NAR #87103, TRA #12201 + +Keith Packard, KD7SQG +NAR #88757, TRA #12200 + + + + + Introduction and Overview + + Welcome to the Altus Metrum community! Our circuits and software reflect + our passion for both hobby rocketry and Free Software. We hope their + capabilities and performance will delight you in every way, but by + releasing all of our hardware and software designs under open licenses, + we also hope to empower you to take as active a role in our collective + future as you wish! + + + The focal point of our community is TeleMetrum, a dual deploy altimeter + with fully integrated GPS and radio telemetry as standard features, and + a "companion interface" that will support optional capabilities in the + future. + + + Complementing TeleMetrum is TeleDongle, a USB to RF interface for + communicating with TeleMetrum. Combined with your choice of antenna and + notebook computer, TeleDongle and our associated user interface software + form a complete ground station capable of logging and displaying in-flight + telemetry, aiding rocket recovery, then processing and archiving flight + data for analysis and review. + + + More products will be added to the Altus Metrum family over time, and + we currently envision that this will be a single, comprehensive manual + for the entire product family. + + + + Getting Started + + The first thing to do after you check the inventory of parts in your + "starter kit" is to charge the battery by plugging it into the + corresponding socket of the TeleMetrum and then using the USB A to + mini B + cable to plug the Telemetrum into your computer's USB socket. The + TeleMetrum circuitry will charge the battery whenever it is plugged + in, because the TeleMetrum's on-off switch does NOT control the + charging circuitry. When the GPS chip is initially searching for + satellites, TeleMetrum will consume more current than it can pull + from the usb port, so the battery must be attached in order to get + satellite lock. Once GPS is locked, the current consumption goes back + down enough to enable charging while + running. So it's a good idea to fully charge the battery as your + first item of business so there is no issue getting and maintaining + satellite lock. The yellow charge indicator led will go out when the + battery is nearly full and the charger goes to trickle charge. It + can take several hours to fully recharge a deeply discharged battery. + + + The other active device in the starter kit is the TeleDongle USB to + RF interface. If you plug it in to your Mac or Linux computer it should + "just work", showing up as a serial port device. Windows systems need + driver information that is part of the AltOS download to know that the + existing USB modem driver will work. If you are using Linux and are + having problems, try moving to a fresher kernel (2.6.33 or newer), as + the USB serial driver had ugly bugs in some earlier versions. + + + Next you should obtain and install the AltOS utilities. These include + the AltosUI ground station program, current firmware images for + TeleMetrum and TeleDongle, and a number of standalone utilities that + are rarely needed. Pre-built binary packages are available for Debian + Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode + and build instructions for some other Linux variants are also available. + The latest version may always be downloaded from + . + + + Both Telemetrum and TeleDongle can be directly communicated + with using USB ports. The first thing you should try after getting + both units plugged into to your computer's usb port(s) is to run + 'ao-list' from a terminal-window to see what port-device-name each + device has been assigned by the operating system. + You will need this information to access the devices via their + respective on-board firmware and data using other command line + programs in the AltOS software suite. + + + To access the device's firmware for configuration you need a terminal + program such as you would use to talk to a modem. The software + authors prefer using the program 'cu' which comes from the UUCP package + on most Unix-like systems such as Linux. An example command line for + cu might be 'cu -l /dev/ttyACM0', substituting the correct number + indicated from running the + ao-list program. Another reasonable terminal program for Linux is + 'cutecom'. The default 'escape' + character used by CU (i.e. the character you use to + issue commands to cu itself instead of sending the command as input + to the connected device) is a '~'. You will need this for use in + only two different ways during normal operations. First is to exit + the program by sending a '~.' which is called a 'escape-disconnect' + and allows you to close-out from 'cu'. The + second use will be outlined later. + + + Both TeleMetrum and TeleDongle share the concept of a two level + command set in their firmware. + The first layer has several single letter commands. Once + you are using 'cu' (or 'cutecom') sending (typing) a '?' + returns a full list of these + commands. The second level are configuration sub-commands accessed + using the 'c' command, for + instance typing 'c?' will give you this second level of commands + (all of which require the + letter 'c' to access). Please note that most configuration options + are stored only in DataFlash memory, and only TeleMetrum has this + memory to save the various values entered like the channel number + and your callsign when powered off. TeleDongle requires that you + set these each time you plug it in, which ao-view can help with. + + + Try setting these config ('c' or second level menu) values. A good + place to start is by setting your call sign. By default, the boards + use 'N0CALL' which is cute, but not exactly legal! + Spend a few minutes getting comfortable with the units, their + firmware, and 'cu' (or possibly 'cutecom'). + For instance, try to send + (type) a 'c r 2' and verify the channel change by sending a 'c s'. + Verify you can connect and disconnect from the units while in your + terminal program by sending the escape-disconnect mentioned above. + + + Note that the 'reboot' command, which is very useful on TeleMetrum, + will likely just cause problems with the dongle. The *correct* way + to reset the dongle is just to unplug and re-plug it. + + + A fun thing to do at the launch site and something you can do while + learning how to use these units is to play with the rf-link access + of the TeleMetrum from the TeleDongle. Be aware that you *must* create + some physical separation between the devices, otherwise the link will + not function due to signal overload in the receivers in each device. + + + Now might be a good time to take a break and read the rest of this + manual, particularly about the two "modes" that the TeleMetrum + can be placed in and how the position of the TeleMetrum when booting + up will determine whether the unit is in "pad" or "idle" mode. + + + You can access a TeleMetrum in idle mode from the Teledongle's USB + connection using the rf link + by issuing a 'p' command to the TeleDongle. Practice connecting and + disconnecting ('~~' while using 'cu') from the TeleMetrum. If + you cannot escape out of the "p" command, (by using a '~~' when in + CU) then it is likely that your kernel has issues. Try a newer version. + + + Using this rf link allows you to configure the TeleMetrum, test + fire e-matches and igniters from the flight line, check pyro-match + continuity and so forth. You can leave the unit turned on while it + is in 'idle mode' and then place the + rocket vertically on the launch pad, walk away and then issue a + reboot command. The TeleMetrum will reboot and start sending data + having changed to the "pad" mode. If the TeleDongle is not receiving + this data, you can disconnect 'cu' from the Teledongle using the + procedures mentioned above and THEN connect to the TeleDongle from + inside 'ao-view'. If this doesn't work, disconnect from the + TeleDongle, unplug it, and try again after plugging it back in. + + + Eventually the GPS will find enough satellites, lock in on them, + and 'ao-view' will both auditorially announce and visually indicate + that GPS is ready. + Now you can launch knowing that you have a good data path and + good satellite lock for flight data and recovery. Remember + you MUST tell ao-view to connect to the TeleDongle explicitly in + order for ao-view to be able to receive data. + + + Both RDF (radio direction finding) tones from the TeleMetrum and + GPS trekking data are available and together are very useful in + locating the rocket once it has landed. (The last good GPS data + received before touch-down will be on the data screen of 'ao-view'.) + + + Once you have recovered the rocket you can download the eeprom + contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over + either a USB cable or over the radio link using TeleDongle. + And by following the man page for 'ao-postflight' you can create + various data output reports, graphs, and even kml data to see the + flight trajectory in google-earth. (Moving the viewing angle making + sure to connect the yellow lines while in google-earth is the proper + technique.) + + + As for ao-view.... some things are in the menu but don't do anything + very useful. The developers have stopped working on ao-view to focus + on a new, cross-platform ground station program. So ao-view may or + may not be updated in the future. Mostly you just use + the Log and Device menus. It has a wonderful display of the incoming + flight data and I am sure you will enjoy what it has to say to you + once you enable the voice output! + +
+ FAQ + + The altimeter (TeleMetrum) seems to shut off when disconnected from the + computer. Make sure the battery is adequately charged. Remember the + unit will pull more power than the USB port can deliver before the + GPS enters "locked" mode. The battery charges best when TeleMetrum + is turned off. + + + It's impossible to stop the TeleDongle when it's in "p" mode, I have + to unplug the USB cable? Make sure you have tried to "escape out" of + this mode. If this doesn't work the reboot procedure for the + TeleDongle *is* to simply unplug it. 'cu' however will retain it's + outgoing buffer IF your "escape out" ('~~') does not work. + At this point using either 'ao-view' (or possibly + 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed + communication. + + + The amber LED (on the TeleMetrum/altimeter) lights up when both + battery and USB are connected. Does this mean it's charging? + Yes, the yellow LED indicates the charging at the 'regular' rate. + If the led is out but the unit is still plugged into a USB port, + then the battery is being charged at a 'trickle' rate. + + + There are no "dit-dah-dah-dit" sound like the manual mentions? + That's the "pad" mode. Weak batteries might be the problem. + It is also possible that the unit is horizontal and the output + is instead a "dit-dit" meaning 'idle'. + + + It's unclear how to use 'ao-view' and other programs when 'cu' + is running. You cannot have more than one program connected to + the TeleDongle at one time without apparent data loss as the + incoming data will not make it to both programs intact. + Disconnect whatever programs aren't currently being used. + + + How do I save flight data? + Live telemetry is written to file(s) whenever 'ao-view' is connected + to the TeleDongle. The file area defaults to ~/altos + but is easily changed using the menus in 'ao-view'. The files that + are written end in '.telem'. The after-flight + data-dumped files will end in .eeprom and represent continuous data + unlike the rf-linked .telem files that are subject to the + turnarounds/data-packaging time slots in the half-duplex rf data path. + See the above instructions on what and how to save the eeprom stored + data after physically retrieving your TeleMetrum. Make sure to save + the on-board data after each flight, as the current firmware will + over-write any previous flight data during a new flight. + +
+
+ + Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, support for optional separate pyro + battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + + + + Handling Precautions + + TeleMetrum is a sophisticated electronic device. When handled gently and + properly installed in an airframe, it will deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. + + + The Lithium Polymer rechargeable batteries used with TeleMetrum have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. + + + The TeleMetrum barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in a 29mm airframe with a + see-through plastic payload bay. + + + The TeleMetrum barometric sensor sampling port must be able to + "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. + + + As with all other rocketry electronics, TeleMetrum must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + + Hardware Overview + + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. + + + A typical TeleMetrum installation using the on-board GPS antenna and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. + + + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, you can do so by adding + a second 2mm connector to position B2 on the board and cutting the + thick pcb trace connecting the LiPo battery to the pyro circuit between + the two silk screen marks on the surface mount side of the board shown + here [insert photo] + + + We offer two choices of pyro and power switch connector, or you can + choose neither and solder wires directly to the board. All three choices + are reasonable depending on the constraints of your airframe. Our + favorite option when there is sufficient room above the board is to use + the Tyco pin header with polarization and locking. If you choose this + option, you crimp individual wires for the power switch and e-matches + into a mating connector, and installing and removing the TeleMetrum + board from an airframe is as easy as plugging or unplugging two + connectors. If the airframe will not support this much height or if + you want to be able to directly attach e-match leads to the board, we + offer a screw terminal block. This is very similar to what most other + altimeter vendors provide and so may be the most familiar option. + You'll need a very small straight blade screwdriver to connect + and disconnect the board in this case, such as you might find in a + jeweler's screwdriver set. Finally, you can forego both options and + solder wires directly to the board, which may be the best choice for + minimum diameter and/or minimum mass designs. + + + For most airframes, the integrated GPS antenna and wire UHF antenna are + a great combination. However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to use + off-board external antennas instead. In this case, you can order + TeleMetrum with an SMA connector for the UHF antenna connection, and + you can unplug the integrated GPS antenna and select an appropriate + off-board GPS antenna with cable terminating in a U.FL connector. + + + + System Operation +
+ Firmware Modes + + The AltOS firmware build for TeleMetrum has two fundamental modes, + "idle" and "flight". Which of these modes the firmware operates in + is determined by the orientation of the rocket (well, actually the + board, of course...) at the time power is switched on. If the rocket + is "nose up", then TeleMetrum assumes it's on a rail or rod being + prepared for launch, so the firmware chooses flight mode. However, + if the rocket is more or less horizontal, the firmware instead enters + idle mode. + + + At power on, you will hear three beeps + ("S" in Morse code for startup) and then a pause while + TeleMetrum completes initialization and self tests, and decides which + mode to enter next. + + + In flight or "pad" mode, TeleMetrum turns on the GPS system, + engages the flight + state machine, goes into transmit-only mode on the RF link sending + telemetry, and waits for launch to be detected. Flight mode is + indicated by an audible "di-dah-dah-dit" ("P" for pad) on the + beeper, followed by + beeps indicating the state of the pyrotechnic igniter continuity. + One beep indicates apogee continuity, two beeps indicate + main continuity, three beeps indicate both apogee and main continuity, + and one longer "brap" sound indicates no continuity. For a dual + deploy flight, make sure you're getting three beeps before launching! + For apogee-only or motor eject flights, do what makes sense. + + + In idle mode, you will hear an audible "di-dit" ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. TeleMetrum also listens on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. + Idle mode is useful for configuring TeleMetrum, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. + + + One "neat trick" of particular value when TeleMetrum is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + TeleMetrum to reboot, realize it's now nose-up, and thus choose + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters! + +
+
+ GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! + + + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. + +
+
+ Ground Testing + + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum-equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! + + + Just prep the rocket for flight, then power up TeleMetrum while the + airframe is horizontal. This will cause the firmware to go into + "idle" mode, in which the normal flight state machine is disabled and + charges will not fire without manual command. Then, establish an + RF packet connection from a TeleDongle-equipped computer using the + P command from a safe distance. You can now command TeleMetrum to + fire the apogee or main charges to complete your testing. + + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. + +
+
+ Radio Link + + The chip our boards are based on incorporates an RF transceiver, but + it's not a full duplex system... each end can only be transmitting or + receiving at any given moment. So we had to decide how to manage the + link. + + + By design, TeleMetrum firmware listens for an RF connection when + it's in "idle mode" (turned on while the rocket is horizontal), which + allows us to use the RF link to configure the rocket, do things like + ejection tests, and extract data after a flight without having to + crack open the airframe. However, when the board is in "flight + mode" (turned on when the rocket is vertical) the TeleMetrum only + transmits and doesn't listen at all. That's because we want to put + ultimate priority on event detection and getting telemetry out of + the rocket and out over + the RF link in case the rocket crashes and we aren't able to extract + data later... + + + We don't use a 'normal packet radio' mode because they're just too + inefficient. The GFSK modulation we use is just FSK with the + baseband pulses passed through a + Gaussian filter before they go into the modulator to limit the + transmitted bandwidth. When combined with the hardware forward error + correction support in the cc1111 chip, this allows us to have a very + robust 38.4 kilobit data link with only 10 milliwatts of transmit power, + a whip antenna in the rocket, and a hand-held Yagi on the ground. We've + had flights to above 21k feet AGL with good reception, and calculations + suggest we should be good to well over 40k feet AGL with a 5-element yagi on + the ground. We hope to fly boards to higher altitudes soon, and would + of course appreciate customer feedback on performance in higher + altitude flights! + +
+
+ Configurable Parameters + + Configuring a TeleMetrum board for flight is very simple. Because we + have both acceleration and pressure sensors, there is no need to set + a "mach delay", for example. The few configurable parameters can all + be set using a simple terminal program over the USB port or RF link + via TeleDongle. + +
+ Radio Channel + + Our firmware supports 10 channels. The default channel 0 corresponds + to a center frequency of 434.550 Mhz, and channels are spaced every + 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. + At any given launch, we highly recommend coordinating who will use + each channel and when to avoid interference. And of course, both + TeleMetrum and TeleDongle must be configured to the same channel to + successfully communicate with each other. + + + To set the radio channel, use the 'c r' command, like 'c r 3' to set + channel 3. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip on + your TeleMetrum board if you want the change to stay in place across reboots. + +
+
+ Apogee Delay + + Apogee delay is the number of seconds after TeleMetrum detects flight + apogee that the drogue charge should be fired. In most cases, this + should be left at the default of 0. However, if you are flying + redundant electronics such as for an L3 certification, you may wish + to set one of your altimeters to a positive delay so that both + primary and backup pyrotechnic charges do not fire simultaneously. + + + To set the apogee delay, use the 'c d' command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + Please note that the TeleMetrum apogee detection algorithm always + fires a fraction of a second *after* apogee. If you are also flying + an altimeter like the PerfectFlite MAWD, which only supports selecting + 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 + seconds delay and set the TeleMetrum to fire your backup 2 or 3 + seconds later to avoid any chance of both charges firing + simultaneously. We've flown several airframes this way quite happily, + including Keith's successful L3 cert. + +
+
+ Main Deployment Altitude + + By default, TeleMetrum will fire the main deployment charge at an + elevation of 250 meters (about 820 feet) above ground. We think this + is a good elevation for most airframes, but feel free to change this + to suit. In particular, if you are flying two altimeters, you may + wish to set the + deployment elevation for the backup altimeter to be something lower + than the primary so that both pyrotechnic charges don't fire + simultaneously. + + + To set the main deployment altitude, use the 'c m' command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+
+ Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 Mhz + crystal on the board. The actual frequency of this oscillator must be + measured to generate a calibration constant. While our GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to channel 0, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 Mhz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + +
+
+ Accelerometer + + The accelerometer we use has its own 5 volt power supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratiometric to + the ADC converter, and calibration is required. We also support the + use of any of several accelerometers from a Freescale family that + includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header extracted by ao-dumplog after flight. + Note that we always store and return raw ADC samples for each + sensor... nothing is permanently "lost" or "damaged" if the + calibration is poor. + + + In the unlikely event an accel cal that goes badly, it is possible + that TeleMetrum may always come up in 'pad mode' and as such not be + listening to either the USB or radio interfaces. If that happens, + there is a special hook in the firmware to force the board back + in to 'idle mode' so you can re-do the cal. To use this hook, you + just need to ground the SPI clock pin at power-on. This pin is + available as pin 2 on the 8-pin companion connector, and pin 1 is + ground. So either carefully install a fine-gauge wire jumper + between the two pins closest to the index hole end of the 8-pin + connector, or plug in the programming cable to the 8-pin connector + and use a small screwdriver or similar to short the two pins closest + to the index post on the 4-pin end of the programming cable, and + power up the board. It should come up in 'idle mode' (two beeps). + +
+
+ + + +
+ Updating Device Firmware + + The big conceptual thing to realize is that you have to use a + TeleDongle as a programmer to update a TeleMetrum, and vice versa. + Due to limited memory resources in the cc1111, we don't support + programming either unit directly over USB. + + + You may wish to begin by ensuring you have current firmware images. + These are distributed as part of the AltOS software bundle that + also includes the AltosUI ground station program. Newer ground + station versions typically work fine with older firmware versions, + so you don't need to update your devices just to try out new + software features. You can always download the most recent + version from . + + + We recommend updating TeleMetrum first, before updating TeleDongle. + +
+ Updating TeleMetrum Firmware + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the + matching connector on the TeleDongle, and the 4-pin end to the + matching connector on the TeleMetrum. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMetrum, which should have a + name in the form telemetrum-v1.0-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMetrum with new firmware, showing a progress bar. + + + Confirm that the TeleMetrum board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. + + + If something goes wrong, give it another try. + + +
+
+ Updating TeleDongle Firmware + + Updating TeleDongle's firmware is just like updating TeleMetrum + firmware, but you switch which board is the programmer and which + is the programming target. + + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Find the USB cable that you got as part of the starter kit, and + plug the "mini" end in to the mating connector on TeleMetrum. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the (latching) + matching connector on the TeleMetrum, and the 4-pin end to the + matching connector on the TeleDongle. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board. + + + Plug both TeleMetrum and TeleDongle into your computer's USB + ports, and power up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleMetrum device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleDongle, which should have a + name in the form teledongle-v0.2-0.7.1.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. The TeleDongle + serial number is on the "bottom" of the circuit board, and can + usually be read through the translucent blue plastic case without + needing to remove the board from the case. + + + Hit the 'OK' button and the software should proceed to flash + the TeleDongle with new firmware, showing a progress bar. + + + Confirm that the TeleDongle board seems to have updated ok, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. Once you're happy, remove the programming cable + and put the cover back on the TeleDongle. + + + If something goes wrong, give it another try. + + + + Be careful removing the programming cable from the locking 8-pin + connector on TeleMetrum. You'll need a fingernail or perhaps a thin + screwdriver or knife blade to gently pry the locking ears out + slightly to extract the connector. We used a locking connector on + TeleMetrum to help ensure that the cabling to companion boards + used in a rocket don't ever come loose accidentally in flight. + +
+
+ + + +
+ + + AltosUI + + The AltosUI program provides a graphical user interface for + interacting with the Altus Metrum product family, including + TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, + configure TeleMetrum and TeleDongle devices and many other + tasks. The primary interface window provides a selection of + buttons, one for each major activity in the system. This manual + is split into chapters, each of which documents one of the tasks + provided from the top-level toolbar. + +
+ Packet Command Mode + Controlling TeleMetrum Over The Radio Link + + One of the unique features of the Altos Metrum environment is + the ability to create a two way command link between TeleDongle + and TeleMetrum using the digital radio transceivers built into + each device. This allows you to interact with TeleMetrum from + afar, as if it were directly connected to the computer. + + + Any operation which can be performed with TeleMetrum + can either be done with TeleMetrum directly connected to + the computer via the USB cable, or through the packet + link. Simply select the appropriate TeleDongle device when + the list of devices is presented and AltosUI will use packet + command mode. + + + One oddity in the current interface is how AltosUI selects the + channel for packet mode communications. Instead of providing + an interface to specifically configure the channel, it uses + whatever channel was most recently selected for the target + TeleDongle device in Monitor Flight mode. If you haven't ever + used that mode with the TeleDongle in question, select the + Monitor Flight button from the top level UI, pick the + appropriate TeleDongle device. Once the flight monitoring + window is open, select the desired channel and then close it + down again. All Packet Command Mode operations will now use + that channel. + + + + + Save Flight Data—Recover flight data from the rocket without + opening it up. + + + + + Configure TeleMetrum—Reset apogee delays or main deploy + heights to respond to changing launch conditions. You can + also 'reboot' the TeleMetrum device. Use this to remotely + enable the flight computer by turning TeleMetrum on while + horizontal, then once the airframe is oriented for launch, + you can reboot TeleMetrum and have it restart in pad mode + without having to climb the scary ladder. + + + + + Fire Igniters—Test your deployment charges without snaking + wires out through holes in the airframe. Simply assembly the + rocket as if for flight with the apogee and main charges + loaded, then remotely command TeleMetrum to fire the + igniters. + + + + + Packet command mode uses the same RF channels as telemetry + mode. Configure the desired TeleDongle channel using the + flight monitor window channel selector and then close that + window before performing the desired operation. + + + TeleMetrum only enables packet command mode in 'idle' mode, so + make sure you have TeleMetrum lying horizontally when you turn + it on. Otherwise, TeleMetrum will start in 'pad' mode ready for + flight and will not be listening for command packets from TeleDongle. + + + When packet command mode is enabled, you can monitor the link + by watching the lights on the TeleDongle and TeleMetrum + devices. The red LED will flash each time TeleDongle or + TeleMetrum transmit a packet while the green LED will light up + on TeleDongle while it is waiting to receive a packet from + TeleMetrum. + +
+
+ Monitor Flight + Receive, Record and Display Telemetry Data + + Selecting this item brings up a dialog box listing all of the + connected TeleDongle devices. When you choose one of these, + AltosUI will create a window to display telemetry data as + received by the selected TeleDongle device. + + + All telemetry data received are automatically recorded in + suitable log files. The name of the files includes the current + date and rocket serial and flight numbers. + + + The radio channel being monitored by the TeleDongle device is + displayed at the top of the window. You can configure the + channel by clicking on the channel box and selecting the desired + channel. AltosUI remembers the last channel selected for each + TeleDongle and selects that automatically the next time you use + that device. + + + Below the TeleDongle channel selector, the window contains a few + significant pieces of information about the TeleMetrum providing + the telemetry data stream: + + + + The TeleMetrum callsign + + + The TeleMetrum serial number + + + The flight number. Each TeleMetrum remembers how many + times it has flown. + + + + + The rocket flight state. Each flight passes through several + states including Pad, Boost, Fast, Coast, Drogue, Main and + Landed. + + + + + The Received Signal Strength Indicator value. This lets + you know how strong a signal TeleDongle is receiving. The + radio inside TeleDongle operates down to about -99dBm; + weaker signals may not be receiveable. The packet link uses + error correction and detection techniques which prevent + incorrect data from being reported. + + + + + Finally, the largest portion of the window contains a set of + tabs, each of which contain some information about the rocket. + They're arranged in 'flight order' so that as the flight + progresses, the selected tab automatically switches to display + data relevant to the current state of the flight. You can select + other tabs at any time. The final 'table' tab contains all of + the telemetry data in one place. + +
+ Launch Pad + + The 'Launch Pad' tab shows information used to decide when the + rocket is ready for flight. The first elements include red/green + indicators, if any of these is red, you'll want to evaluate + whether the rocket is ready to launch: + + + + Battery Voltage. This indicates whether the LiPo battery + powering the TeleMetrum has sufficient charge to last for + the duration of the flight. A value of more than + 3.7V is required for a 'GO' status. + + + + + Apogee Igniter Voltage. This indicates whether the apogee + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + Main Igniter Voltage. This indicates whether the main + igniter has continuity. If the igniter has a low + resistance, then the voltage measured here will be close + to the LiPo battery voltage. A value greater than 3.2V is + required for a 'GO' status. + + + + + GPS Locked. This indicates whether the GPS receiver is + currently able to compute position information. GPS requires + at least 4 satellites to compute an accurate position. + + + + + GPS Ready. This indicates whether GPS has reported at least + 10 consecutive positions without losing lock. This ensures + that the GPS receiver has reliable reception from the + satellites. + + + + + The LaunchPad tab also shows the computed launch pad position + and altitude, averaging many reported positions to improve the + accuracy of the fix. + + +
+
+ Ascent + + This tab is shown during Boost, Fast and Coast + phases. The information displayed here helps monitor the + rocket as it heads towards apogee. + + + The height, speed and acceleration are shown along with the + maxium values for each of them. This allows you to quickly + answer the most commonly asked questions you'll hear during + flight. + + + The current latitude and longitude reported by the GPS are + also shown. Note that under high acceleration, these values + may not get updated as the GPS receiver loses position + fix. Once the rocket starts coasting, the receiver should + start reporting position again. + + + Finally, the current igniter voltages are reported as in the + Launch Pad tab. This can help diagnose deployment failures + caused by wiring which comes loose under high acceleration. + +
+
+ Descent + + Once the rocket has reached apogee and (we hope) activated the + apogee charge, attention switches to tracking the rocket on + the way back to the ground, and for dual-deploy flights, + waiting for the main charge to fire. + + + To monitor whether the apogee charge operated correctly, the + current descent rate is reported along with the current + height. Good descent rates generally range from 15-30m/s. + + + To help locate the rocket in the sky, use the elevation and + bearing information to figure out where to look. Elevation is + in degrees above the horizon. Bearing is reported in degrees + relative to true north. Range can help figure out how big the + rocket will appear. Note that all of these values are relative + to the pad location. If the elevation is near 90°, the rocket + is over the pad, not over you. + + + Finally, the igniter voltages are reported in this tab as + well, both to monitor the main charge as well as to see what + the status of the apogee charge is. + +
+
+ Landed + + Once the rocket is on the ground, attention switches to + recovery. While the radio signal is generally lost once the + rocket is on the ground, the last reported GPS position is + generally within a short distance of the actual landing location. + + + The last reported GPS position is reported both by + latitude and longitude as well as a bearing and distance from + the launch pad. The distance should give you a good idea of + whether you'll want to walk or hitch a ride. Take the reported + latitude and longitude and enter them into your handheld GPS + unit and have that compute a track to the landing location. + + + Finally, the maximum height, speed and acceleration reported + during the flight are displayed for your admiring observers. + +
+
+ Site Map + + When the rocket gets a GPS fix, the Site Map tab will map + the rocket's position to make it easier for you to locate the + rocket, both while it is in the air, and when it has landed. The + rocket's state is indicated by colour: white for pad, red for + boost, pink for fast, yellow for coast, light blue for drogue, + dark blue for main, and black for landed. + + + The map's scale is approximately 3m (10ft) per pixel. The map + can be dragged using the left mouse button. The map will attempt + to keep the rocket roughly centred while data is being received. + + + Images are fetched automatically via the Google Maps Static API, + and are cached for reuse. If map images cannot be downloaded, + the rocket's path will be traced on a dark grey background + instead. + +
+
+
+ Save Flight Data + + TeleMetrum records flight data to its internal flash memory. + This data is recorded at a much higher rate than the telemetry + system can handle, and is not subject to radio drop-outs. As + such, it provides a more complete and precise record of the + flight. The 'Save Flight Data' button allows you to read the + flash memory and write it to disk. + + + Clicking on the 'Save Flight Data' button brings up a list of + connected TeleMetrum and TeleDongle devices. If you select a + TeleMetrum device, the flight data will be downloaded from that + device directly. If you select a TeleDongle device, flight data + will be downloaded from a TeleMetrum device connected via the + packet command link to the specified TeleDongle. See the chapter + on Packet Command Mode for more information about this. + + + The filename for the data is computed automatically from the recorded + flight date, TeleMetrum serial number and flight number + information. + +
+
+ Replay Flight + + Select this button and you are prompted to select a flight + record file, either a .telem file recording telemetry data or a + .eeprom file containing flight data saved from the TeleMetrum + flash memory. + + + Once a flight record is selected, the flight monitor interface + is displayed and the flight is re-enacted in real time. Check + the Monitor Flight chapter above to learn how this window operates. + +
+
+ Graph Data + + Select this button and you are prompted to select a flight + record file, either a .telem file recording telemetry data or a + .eeprom file containing flight data saved from the TeleMetrum + flash memory. + + + Once a flight record is selected, the acceleration (blue), + velocity (green) and altitude (red) of the flight are plotted and + displayed, measured in metric units. + + + The graph can be zoomed into a particular area by clicking and + dragging down and to the right. Once zoomed, the graph can be + reset by clicking and dragging up and to the left. Holding down + control and clicking and dragging allows the graph to be panned. + The right mouse button causes a popup menu to be displayed, giving + you the option save or print the plot. + + + Note that telemetry files will generally produce poor graphs + due to the lower sampling rate and missed telemetry packets, + and will also often have significant amounts of data received + while the rocket was waiting on the pad. Use saved flight data + for graphing where possible. + +
+
+ Export Data + + This tool takes the raw data files and makes them available for + external analysis. When you select this button, you are prompted to select a flight + data file (either .eeprom or .telem will do, remember that + .eeprom files contain higher resolution and more continuous + data). Next, a second dialog appears which is used to select + where to write the resulting file. It has a selector to choose + between CSV and KML file formats. + +
+ Comma Separated Value Format + + This is a text file containing the data in a form suitable for + import into a spreadsheet or other external data analysis + tool. The first few lines of the file contain the version and + configuration information from the TeleMetrum device, then + there is a single header line which labels all of the + fields. All of these lines start with a '#' character which + most tools can be configured to skip over. + + + The remaining lines of the file contain the data, with each + field separated by a comma and at least one space. All of + the sensor values are converted to standard units, with the + barometric data reported in both pressure, altitude and + height above pad units. + +
+
+ Keyhole Markup Language (for Google Earth) + + This is the format used by + Googleearth to provide an overlay within that + application. With this, you can use Googleearth to see the + whole flight path in 3D. + +
+
+
+ Configure TeleMetrum + + Select this button and then select either a TeleMetrum or + TeleDongle Device from the list provided. Selecting a TeleDongle + device will use Packet Comamnd Mode to configure remote + TeleMetrum device. Learn how to use this in the Packet Command + Mode chapter. + + + The first few lines of the dialog provide information about the + connected TeleMetrum device, including the product name, + software version and hardware serial number. Below that are the + individual configuration entries. + + + At the bottom of the dialog, there are four buttons: + + + + + Save. This writes any changes to the TeleMetrum + configuration parameter block in flash memory. If you don't + press this button, any changes you make will be lost. + + + + + Reset. This resets the dialog to the most recently saved values, + erasing any changes you have made. + + + + + Reboot. This reboots the TeleMetrum device. Use this to + switch from idle to pad mode by rebooting once the rocket is + oriented for flight. + + + + + Close. This closes the dialog. Any unsaved changes will be + lost. + + + + + The rest of the dialog contains the parameters to be configured. + +
+ Main Deploy Altitude + + This sets the altitude (above the recorded pad altitude) at + which the 'main' igniter will fire. The drop-down menu shows + some common values, but you can edit the text directly and + choose whatever you like. If the apogee charge fires below + this altitude, then the main charge will fire two seconds + after the apogee charge fires. + +
+
+ Apogee Delay + + When flying redundant electronics, it's often important to + ensure that multiple apogee charges don't fire at precisely + the same time as that can overpressurize the apogee deployment + bay and cause a structural failure of the airframe. The Apogee + Delay parameter tells the flight computer to fire the apogee + charge a certain number of seconds after apogee has been + detected. + +
+
+ Radio Channel + + This configures which of the 10 radio channels to use for both + telemetry and packet command mode. Note that if you set this + value via packet command mode, you will have to reconfigure + the TeleDongle channel before you will be able to use packet + command mode again. + +
+
+ Radio Calibration + + The radios in every Altus Metrum device are calibrated at the + factory to ensure that they transmit and receive on the + specified frequency for each channel. You can adjust that + calibration by changing this value. To change the TeleDongle's + calibration, you must reprogram the unit completely. + +
+
+ Callsign + + This sets the callsign included in each telemetry packet. Set this + as needed to conform to your local radio regulations. + +
+
+
+ Configure AltosUI + + This button presents a dialog so that you can configure the AltosUI global settings. + +
+ Voice Settings + + AltosUI provides voice annoucements during flight so that you + can keep your eyes on the sky and still get information about + the current flight status. However, sometimes you don't want + to hear them. + + + + Enable—turns all voice announcements on and off + + + + Test Voice—Plays a short message allowing you to verify + that the audio systme is working and the volume settings + are reasonable + + + +
+
+ Log Directory + + AltosUI logs all telemetry data and saves all TeleMetrum flash + data to this directory. This directory is also used as the + staring point when selecting data files for display or export. + + + Click on the directory name to bring up a directory choosing + dialog, select a new directory and click 'Select Directory' to + change where AltosUI reads and writes data files. + +
+
+ Callsign + + This value is used in command packet mode and is transmitted + in each packet sent from TeleDongle and received from + TeleMetrum. It is not used in telemetry mode as that transmits + packets only from TeleMetrum to TeleDongle. Configure this + with the AltosUI operators callsign as needed to comply with + your local radio regulations. + +
+
+
+ Flash Image + + This reprograms any Altus Metrum device by using a TeleMetrum or + TeleDongle as a programming dongle. Please read the directions + for connecting the programming cable in the main TeleMetrum + manual before reading these instructions. + + + Once you have the programmer and target devices connected, + push the 'Flash Image' button. That will present a dialog box + listing all of the connected devices. Carefully select the + programmer device, not the device to be programmed. + + + Next, select the image to flash to the device. These are named + with the product name and firmware version. The file selector + will start in the directory containing the firmware included + with the AltosUI package. Navigate to the directory containing + the desired firmware if it isn't there. + + + Next, a small dialog containing the device serial number and + RF calibration values should appear. If these values are + incorrect (possibly due to a corrupted image in the device), + enter the correct values here. + + + Finally, a dialog containing a progress bar will follow the + programming process. + + + When programming is complete, the target device will + reboot. Note that if the target device is connected via USB, you + will have to unplug it and then plug it back in for the USB + connection to reset so that you can communicate with the device + again. + +
+
+ Fire Igniter + + This activates the igniter circuits in TeleMetrum to help test + recovery systems deployment. Because this command can operate + over the Packet Command Link, you can prepare the rocket as + for flight and then test the recovery system without needing + to snake wires inside the airframe. + + + Selecting the 'Fire Igniter' button brings up the usual device + selection dialog. Pick the desired TeleDongle or TeleMetrum + device. This brings up another window which shows the current + continutity test status for both apogee and main charges. + + + Next, select the desired igniter to fire. This will enable the + 'Arm' button. + + + Select the 'Arm' button. This enables the 'Fire' button. The + word 'Arm' is replaced by a countdown timer indicating that + you have 10 seconds to press the 'Fire' button or the system + will deactivate, at which point you start over again at + selecting the desired igniter. + +
+
+ + Using Altus Metrum Products +
+ Being Legal + + First off, in the US, you need an amateur radio license or + other authorization to legally operate the radio transmitters that are part + of our products. + +
+ In the Rocket + + In the rocket itself, you just need a TeleMetrum board and + a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + alkaline battery, and will run a TeleMetrum for hours. + + + By default, we ship TeleMetrum with a simple wire antenna. If your + electronics bay or the airframe it resides within is made of carbon fiber, + which is opaque to RF signals, you may choose to have an SMA connector + installed so that you can run a coaxial cable to an antenna mounted + elsewhere in the rocket. + +
+
+ On the Ground + + To receive the data stream from the rocket, you need an antenna and short + feedline connected to one of our TeleDongle units. The + TeleDongle in turn plugs directly into the USB port on a notebook + computer. Because TeleDongle looks like a simple serial port, your computer + does not require special device drivers... just plug it in. + + + The GUI tool, AltosUI, is written in Java and runs across + Linux, Mac OS and Windows. There's also a suite of C tools + for Linux which can perform most of the same tasks. + + + After the flight, you can use the RF link to extract the more detailed data + logged in the rocket, or you can use a mini USB cable to plug into the + TeleMetrum board directly. Pulling out the data without having to open up + the rocket is pretty cool! A USB cable is also how you charge the LiPo + battery, so you'll want one of those anyway... the same cable used by lots + of digital cameras and other modern electronic stuff will work fine. + + + If your rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a waypoint for the last reported rocket + position before touch-down. This makes looking for your rocket a lot like + Geo-Cacheing... just go to the waypoint and look around starting from there. + + + You may also enjoy having a ham radio "HT" that covers the 70cm band... you + can use that with your antenna to direction-find the rocket on the ground + the same way you can use a Walston or Beeline tracker. This can be handy + if the rocket is hiding in sage brush or a tree, or if the last GPS position + doesn't get you close enough because the rocket dropped into a canyon, or + the wind is blowing it across a dry lake bed, or something like that... Keith + and Bdale both currently own and use the Yaesu VX-7R at launches. + + + So, to recap, on the ground the hardware you'll need includes: + + + an antenna and feedline + + + a TeleDongle + + + a notebook computer + + + optionally, a handheld GPS receiver + + + optionally, an HT or receiver covering 435 Mhz + + + + + The best hand-held commercial directional antennas we've found for radio + direction finding rockets are from + + Arrow Antennas. + + The 440-3 and 440-5 are both good choices for finding a + TeleMetrum-equipped rocket when used with a suitable 70cm HT. + +
+
+ Data Analysis + + Our software makes it easy to log the data from each flight, both the + telemetry received over the RF link during the flight itself, and the more + complete data log recorded in the DataFlash memory on the TeleMetrum + board. Once this data is on your computer, our postflight tools make it + easy to quickly get to the numbers everyone wants, like apogee altitude, + max acceleration, and max velocity. You can also generate and view a + standard set of plots showing the altitude, acceleration, and + velocity of the rocket during flight. And you can even export a data file + useable with Google Maps and Google Earth for visualizing the flight path + in two or three dimensions! + + + Our ultimate goal is to emit a set of files for each flight that can be + published as a web page per flight, or just viewed on your local disk with + a web browser. + +
+
+ Future Plans + + In the future, we intend to offer "companion boards" for the rocket that will + plug in to TeleMetrum to collect additional data, provide more pyro channels, + and so forth. A reference design for a companion board will be documented + soon, and will be compatible with open source Arduino programming tools. + + + We are also working on the design of a hand-held ground terminal that will + allow monitoring the rocket's status, collecting data during flight, and + logging data after flight without the need for a notebook computer on the + flight line. Particularly since it is so difficult to read most notebook + screens in direct sunlight, we think this will be a great thing to have. + + + Because all of our work is open, both the hardware designs and the software, + if you have some great idea for an addition to the current Altus Metrum family, + feel free to dive in and help! Or let us know what you'd like to see that + we aren't already working on, and maybe we'll get excited about it too... + +
+
+
+
diff --git a/doc/telemetrum-doc.xsl b/doc/telemetrum-doc.xsl deleted file mode 100644 index 0c20b285..00000000 --- a/doc/telemetrum-doc.xsl +++ /dev/null @@ -1,1735 +0,0 @@ - - - - The Altus Metrum System - Owner's Manual for TeleMetrum and TeleDongle Devices - - - Bdale - Garbee - - - Keith - Packard - - - Bob - Finch - - - Anthony - Towns - - - 2010 - Bdale Garbee and Keith Packard - - - - This document is released under the terms of the - - Creative Commons ShareAlike 3.0 - - license. - - - - - 0.8 - 24 November 2010 - Updated for software version 0.8 - - - - - - Thanks to Bob Finch, W9YA, NAR 12965, TRA 12350 for writing "The - Mere-Mortals Quick Start/Usage Guide to the Altus Metrum Starter - Kit" which has turned into the Getting Started chapter in this - book. Bob was one of our first customers for a production - TeleMetrum, and the enthusiasm that led to his contribution of - this section is immensely gratifying and highy appreciated! - - - And thanks to Anthony (AJ) Towns for contributing the - AltosUI graphing and site map code and documentation. Free - software means that our customers and friends can become our - collaborators, and we certainly appreciate this level of - contribution. - - - Have fun using these products, and we hope to meet all of you - out on the rocket flight line somewhere. - -Bdale Garbee, KB0G -NAR #87103, TRA #12201 - -Keith Packard, KD7SQG -NAR #88757, TRA #12200 - - - - - Introduction and Overview - - Welcome to the Altus Metrum community! Our circuits and software reflect - our passion for both hobby rocketry and Free Software. We hope their - capabilities and performance will delight you in every way, but by - releasing all of our hardware and software designs under open licenses, - we also hope to empower you to take as active a role in our collective - future as you wish! - - - The focal point of our community is TeleMetrum, a dual deploy altimeter - with fully integrated GPS and radio telemetry as standard features, and - a "companion interface" that will support optional capabilities in the - future. - - - Complementing TeleMetrum is TeleDongle, a USB to RF interface for - communicating with TeleMetrum. Combined with your choice of antenna and - notebook computer, TeleDongle and our associated user interface software - form a complete ground station capable of logging and displaying in-flight - telemetry, aiding rocket recovery, then processing and archiving flight - data for analysis and review. - - - More products will be added to the Altus Metrum family over time, and - we currently envision that this will be a single, comprehensive manual - for the entire product family. - - - - Getting Started - - The first thing to do after you check the inventory of parts in your - "starter kit" is to charge the battery by plugging it into the - corresponding socket of the TeleMetrum and then using the USB A to - mini B - cable to plug the Telemetrum into your computer's USB socket. The - TeleMetrum circuitry will charge the battery whenever it is plugged - in, because the TeleMetrum's on-off switch does NOT control the - charging circuitry. When the GPS chip is initially searching for - satellites, TeleMetrum will consume more current than it can pull - from the usb port, so the battery must be attached in order to get - satellite lock. Once GPS is locked, the current consumption goes back - down enough to enable charging while - running. So it's a good idea to fully charge the battery as your - first item of business so there is no issue getting and maintaining - satellite lock. The yellow charge indicator led will go out when the - battery is nearly full and the charger goes to trickle charge. It - can take several hours to fully recharge a deeply discharged battery. - - - The other active device in the starter kit is the TeleDongle USB to - RF interface. If you plug it in to your Mac or Linux computer it should - "just work", showing up as a serial port device. Windows systems need - driver information that is part of the AltOS download to know that the - existing USB modem driver will work. If you are using Linux and are - having problems, try moving to a fresher kernel (2.6.33 or newer), as - the USB serial driver had ugly bugs in some earlier versions. - - - Next you should obtain and install the AltOS utilities. These include - the AltosUI ground station program, current firmware images for - TeleMetrum and TeleDongle, and a number of standalone utilities that - are rarely needed. Pre-built binary packages are available for Debian - Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode - and build instructions for some other Linux variants are also available. - The latest version may always be downloaded from - . - - - Both Telemetrum and TeleDongle can be directly communicated - with using USB ports. The first thing you should try after getting - both units plugged into to your computer's usb port(s) is to run - 'ao-list' from a terminal-window to see what port-device-name each - device has been assigned by the operating system. - You will need this information to access the devices via their - respective on-board firmware and data using other command line - programs in the AltOS software suite. - - - To access the device's firmware for configuration you need a terminal - program such as you would use to talk to a modem. The software - authors prefer using the program 'cu' which comes from the UUCP package - on most Unix-like systems such as Linux. An example command line for - cu might be 'cu -l /dev/ttyACM0', substituting the correct number - indicated from running the - ao-list program. Another reasonable terminal program for Linux is - 'cutecom'. The default 'escape' - character used by CU (i.e. the character you use to - issue commands to cu itself instead of sending the command as input - to the connected device) is a '~'. You will need this for use in - only two different ways during normal operations. First is to exit - the program by sending a '~.' which is called a 'escape-disconnect' - and allows you to close-out from 'cu'. The - second use will be outlined later. - - - Both TeleMetrum and TeleDongle share the concept of a two level - command set in their firmware. - The first layer has several single letter commands. Once - you are using 'cu' (or 'cutecom') sending (typing) a '?' - returns a full list of these - commands. The second level are configuration sub-commands accessed - using the 'c' command, for - instance typing 'c?' will give you this second level of commands - (all of which require the - letter 'c' to access). Please note that most configuration options - are stored only in DataFlash memory, and only TeleMetrum has this - memory to save the various values entered like the channel number - and your callsign when powered off. TeleDongle requires that you - set these each time you plug it in, which ao-view can help with. - - - Try setting these config ('c' or second level menu) values. A good - place to start is by setting your call sign. By default, the boards - use 'N0CALL' which is cute, but not exactly legal! - Spend a few minutes getting comfortable with the units, their - firmware, and 'cu' (or possibly 'cutecom'). - For instance, try to send - (type) a 'c r 2' and verify the channel change by sending a 'c s'. - Verify you can connect and disconnect from the units while in your - terminal program by sending the escape-disconnect mentioned above. - - - Note that the 'reboot' command, which is very useful on TeleMetrum, - will likely just cause problems with the dongle. The *correct* way - to reset the dongle is just to unplug and re-plug it. - - - A fun thing to do at the launch site and something you can do while - learning how to use these units is to play with the rf-link access - of the TeleMetrum from the TeleDongle. Be aware that you *must* create - some physical separation between the devices, otherwise the link will - not function due to signal overload in the receivers in each device. - - - Now might be a good time to take a break and read the rest of this - manual, particularly about the two "modes" that the TeleMetrum - can be placed in and how the position of the TeleMetrum when booting - up will determine whether the unit is in "pad" or "idle" mode. - - - You can access a TeleMetrum in idle mode from the Teledongle's USB - connection using the rf link - by issuing a 'p' command to the TeleDongle. Practice connecting and - disconnecting ('~~' while using 'cu') from the TeleMetrum. If - you cannot escape out of the "p" command, (by using a '~~' when in - CU) then it is likely that your kernel has issues. Try a newer version. - - - Using this rf link allows you to configure the TeleMetrum, test - fire e-matches and igniters from the flight line, check pyro-match - continuity and so forth. You can leave the unit turned on while it - is in 'idle mode' and then place the - rocket vertically on the launch pad, walk away and then issue a - reboot command. The TeleMetrum will reboot and start sending data - having changed to the "pad" mode. If the TeleDongle is not receiving - this data, you can disconnect 'cu' from the Teledongle using the - procedures mentioned above and THEN connect to the TeleDongle from - inside 'ao-view'. If this doesn't work, disconnect from the - TeleDongle, unplug it, and try again after plugging it back in. - - - Eventually the GPS will find enough satellites, lock in on them, - and 'ao-view' will both auditorially announce and visually indicate - that GPS is ready. - Now you can launch knowing that you have a good data path and - good satellite lock for flight data and recovery. Remember - you MUST tell ao-view to connect to the TeleDongle explicitly in - order for ao-view to be able to receive data. - - - Both RDF (radio direction finding) tones from the TeleMetrum and - GPS trekking data are available and together are very useful in - locating the rocket once it has landed. (The last good GPS data - received before touch-down will be on the data screen of 'ao-view'.) - - - Once you have recovered the rocket you can download the eeprom - contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over - either a USB cable or over the radio link using TeleDongle. - And by following the man page for 'ao-postflight' you can create - various data output reports, graphs, and even kml data to see the - flight trajectory in google-earth. (Moving the viewing angle making - sure to connect the yellow lines while in google-earth is the proper - technique.) - - - As for ao-view.... some things are in the menu but don't do anything - very useful. The developers have stopped working on ao-view to focus - on a new, cross-platform ground station program. So ao-view may or - may not be updated in the future. Mostly you just use - the Log and Device menus. It has a wonderful display of the incoming - flight data and I am sure you will enjoy what it has to say to you - once you enable the voice output! - -
- FAQ - - The altimeter (TeleMetrum) seems to shut off when disconnected from the - computer. Make sure the battery is adequately charged. Remember the - unit will pull more power than the USB port can deliver before the - GPS enters "locked" mode. The battery charges best when TeleMetrum - is turned off. - - - It's impossible to stop the TeleDongle when it's in "p" mode, I have - to unplug the USB cable? Make sure you have tried to "escape out" of - this mode. If this doesn't work the reboot procedure for the - TeleDongle *is* to simply unplug it. 'cu' however will retain it's - outgoing buffer IF your "escape out" ('~~') does not work. - At this point using either 'ao-view' (or possibly - 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed - communication. - - - The amber LED (on the TeleMetrum/altimeter) lights up when both - battery and USB are connected. Does this mean it's charging? - Yes, the yellow LED indicates the charging at the 'regular' rate. - If the led is out but the unit is still plugged into a USB port, - then the battery is being charged at a 'trickle' rate. - - - There are no "dit-dah-dah-dit" sound like the manual mentions? - That's the "pad" mode. Weak batteries might be the problem. - It is also possible that the unit is horizontal and the output - is instead a "dit-dit" meaning 'idle'. - - - It's unclear how to use 'ao-view' and other programs when 'cu' - is running. You cannot have more than one program connected to - the TeleDongle at one time without apparent data loss as the - incoming data will not make it to both programs intact. - Disconnect whatever programs aren't currently being used. - - - How do I save flight data? - Live telemetry is written to file(s) whenever 'ao-view' is connected - to the TeleDongle. The file area defaults to ~/altos - but is easily changed using the menus in 'ao-view'. The files that - are written end in '.telem'. The after-flight - data-dumped files will end in .eeprom and represent continuous data - unlike the rf-linked .telem files that are subject to the - turnarounds/data-packaging time slots in the half-duplex rf data path. - See the above instructions on what and how to save the eeprom stored - data after physically retrieving your TeleMetrum. Make sure to save - the on-board data after each flight, as the current firmware will - over-write any previous flight data during a new flight. - -
-
- - Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - - - - Handling Precautions - - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. - - - The Lithium Polymer rechargeable batteries used with TeleMetrum have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. - - - The TeleMetrum barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe with a - see-through plastic payload bay. - - - The TeleMetrum barometric sensor sampling port must be able to - "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. - - - As with all other rocketry electronics, TeleMetrum must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. - - - - Hardware Overview - - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. - - - A typical TeleMetrum installation using the on-board GPS antenna and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. - - - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] - - - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar option. - You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. - - - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. - - - - System Operation -
- Firmware Modes - - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. - - - At power on, you will hear three beeps - ("S" in Morse code for startup) and then a pause while - TeleMetrum completes initialization and self tests, and decides which - mode to enter next. - - - In flight or "pad" mode, TeleMetrum turns on the GPS system, - engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when TeleMetrum is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! - -
-
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. - -
-
- Ground Testing - - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! - - - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. - - - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. - -
-
- Radio Link - - The chip our boards are based on incorporates an RF transceiver, but - it's not a full duplex system... each end can only be transmitting or - receiving at any given moment. So we had to decide how to manage the - link. - - - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which - allows us to use the RF link to configure the rocket, do things like - ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only - transmits and doesn't listen at all. That's because we want to put - ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract - data later... - - - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a - Gaussian filter before they go into the modulator to limit the - transmitted bandwidth. When combined with the hardware forward error - correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had flights to above 21k feet AGL with good reception, and calculations - suggest we should be good to well over 40k feet AGL with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! - -
-
- Configurable Parameters - - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. - -
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip on - your TeleMetrum board if you want the change to stay in place across reboots. - -
-
- Apogee Delay - - Apogee delay is the number of seconds after TeleMetrum detects flight - apogee that the drogue charge should be fired. In most cases, this - should be left at the default of 0. However, if you are flying - redundant electronics such as for an L3 certification, you may wish - to set one of your altimeters to a positive delay so that both - primary and backup pyrotechnic charges do not fire simultaneously. - - - To set the apogee delay, use the 'c d' command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - Please note that the TeleMetrum apogee detection algorithm always - fires a fraction of a second *after* apogee. If you are also flying - an altimeter like the PerfectFlite MAWD, which only supports selecting - 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 - seconds delay and set the TeleMetrum to fire your backup 2 or 3 - seconds later to avoid any chance of both charges firing - simultaneously. We've flown several airframes this way quite happily, - including Keith's successful L3 cert. - -
-
- Main Deployment Altitude - - By default, TeleMetrum will fire the main deployment charge at an - elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this - to suit. In particular, if you are flying two altimeters, you may - wish to set the - deployment elevation for the backup altimeter to be something lower - than the primary so that both pyrotechnic charges don't fire - simultaneously. - - - To set the main deployment altitude, use the 'c m' command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
-
- Calibration - - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. - -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 Mhz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - -
-
- Accelerometer - - The accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - - - In the unlikely event an accel cal that goes badly, it is possible - that TeleMetrum may always come up in 'pad mode' and as such not be - listening to either the USB or radio interfaces. If that happens, - there is a special hook in the firmware to force the board back - in to 'idle mode' so you can re-do the cal. To use this hook, you - just need to ground the SPI clock pin at power-on. This pin is - available as pin 2 on the 8-pin companion connector, and pin 1 is - ground. So either carefully install a fine-gauge wire jumper - between the two pins closest to the index hole end of the 8-pin - connector, or plug in the programming cable to the 8-pin connector - and use a small screwdriver or similar to short the two pins closest - to the index post on the 4-pin end of the programming cable, and - power up the board. It should come up in 'idle mode' (two beeps). - -
-
- - - -
- Updating Device Firmware - - The big conceptual thing to realize is that you have to use a - TeleDongle as a programmer to update a TeleMetrum, and vice versa. - Due to limited memory resources in the cc1111, we don't support - programming either unit directly over USB. - - - You may wish to begin by ensuring you have current firmware images. - These are distributed as part of the AltOS software bundle that - also includes the AltosUI ground station program. Newer ground - station versions typically work fine with older firmware versions, - so you don't need to update your devices just to try out new - software features. You can always download the most recent - version from . - - - We recommend updating TeleMetrum first, before updating TeleDongle. - -
- Updating TeleMetrum Firmware - - - Find the 'programming cable' that you got as part of the starter - kit, that has a red 8-pin MicroMaTch connector on one end and a - red 4-pin MicroMaTch connector on the other end. - - - Take the 2 screws out of the TeleDongle case to get access - to the circuit board. - - - Plug the 8-pin end of the programming cable to the - matching connector on the TeleDongle, and the 4-pin end to the - matching connector on the TeleMetrum. - Note that each MicroMaTch connector has an alignment pin that - goes through a hole in the PC board when you have the cable - oriented correctly. - - - Attach a battery to the TeleMetrum board. - - - Plug the TeleDongle into your computer's USB port, and power - up the TeleMetrum. - - - Run AltosUI, and select 'Flash Image' from the File menu. - - - Pick the TeleDongle device from the list, identifying it as the - programming device. - - - Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.0-0.7.1.ihx. It should be visible - in the default directory, if not you may have to poke around - your system to find it. - - - Make sure the configuration parameters are reasonable - looking. If the serial number and/or RF configuration - values aren't right, you'll need to change them. - - - Hit the 'OK' button and the software should proceed to flash - the TeleMetrum with new firmware, showing a progress bar. - - - Confirm that the TeleMetrum board seems to have updated ok, which you - can do by plugging in to it over USB and using a terminal program - to connect to the board and issue the 'v' command to check - the version, etc. - - - If something goes wrong, give it another try. - - -
-
- Updating TeleDongle Firmware - - Updating TeleDongle's firmware is just like updating TeleMetrum - firmware, but you switch which board is the programmer and which - is the programming target. - - - - Find the 'programming cable' that you got as part of the starter - kit, that has a red 8-pin MicroMaTch connector on one end and a - red 4-pin MicroMaTch connector on the other end. - - - Find the USB cable that you got as part of the starter kit, and - plug the "mini" end in to the mating connector on TeleMetrum. - - - Take the 2 screws out of the TeleDongle case to get access - to the circuit board. - - - Plug the 8-pin end of the programming cable to the (latching) - matching connector on the TeleMetrum, and the 4-pin end to the - matching connector on the TeleDongle. - Note that each MicroMaTch connector has an alignment pin that - goes through a hole in the PC board when you have the cable - oriented correctly. - - - Attach a battery to the TeleMetrum board. - - - Plug both TeleMetrum and TeleDongle into your computer's USB - ports, and power up the TeleMetrum. - - - Run AltosUI, and select 'Flash Image' from the File menu. - - - Pick the TeleMetrum device from the list, identifying it as the - programming device. - - - Select the image you want put on the TeleDongle, which should have a - name in the form teledongle-v0.2-0.7.1.ihx. It should be visible - in the default directory, if not you may have to poke around - your system to find it. - - - Make sure the configuration parameters are reasonable - looking. If the serial number and/or RF configuration - values aren't right, you'll need to change them. The TeleDongle - serial number is on the "bottom" of the circuit board, and can - usually be read through the translucent blue plastic case without - needing to remove the board from the case. - - - Hit the 'OK' button and the software should proceed to flash - the TeleDongle with new firmware, showing a progress bar. - - - Confirm that the TeleDongle board seems to have updated ok, which you - can do by plugging in to it over USB and using a terminal program - to connect to the board and issue the 'v' command to check - the version, etc. Once you're happy, remove the programming cable - and put the cover back on the TeleDongle. - - - If something goes wrong, give it another try. - - - - Be careful removing the programming cable from the locking 8-pin - connector on TeleMetrum. You'll need a fingernail or perhaps a thin - screwdriver or knife blade to gently pry the locking ears out - slightly to extract the connector. We used a locking connector on - TeleMetrum to help ensure that the cabling to companion boards - used in a rocket don't ever come loose accidentally in flight. - -
-
- - - -
- - - AltosUI - - The AltosUI program provides a graphical user interface for - interacting with the Altus Metrum product family, including - TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, - configure TeleMetrum and TeleDongle devices and many other - tasks. The primary interface window provides a selection of - buttons, one for each major activity in the system. This manual - is split into chapters, each of which documents one of the tasks - provided from the top-level toolbar. - -
- Packet Command Mode - Controlling TeleMetrum Over The Radio Link - - One of the unique features of the Altos Metrum environment is - the ability to create a two way command link between TeleDongle - and TeleMetrum using the digital radio transceivers built into - each device. This allows you to interact with TeleMetrum from - afar, as if it were directly connected to the computer. - - - Any operation which can be performed with TeleMetrum - can either be done with TeleMetrum directly connected to - the computer via the USB cable, or through the packet - link. Simply select the appropriate TeleDongle device when - the list of devices is presented and AltosUI will use packet - command mode. - - - One oddity in the current interface is how AltosUI selects the - channel for packet mode communications. Instead of providing - an interface to specifically configure the channel, it uses - whatever channel was most recently selected for the target - TeleDongle device in Monitor Flight mode. If you haven't ever - used that mode with the TeleDongle in question, select the - Monitor Flight button from the top level UI, pick the - appropriate TeleDongle device. Once the flight monitoring - window is open, select the desired channel and then close it - down again. All Packet Command Mode operations will now use - that channel. - - - - - Save Flight Data—Recover flight data from the rocket without - opening it up. - - - - - Configure TeleMetrum—Reset apogee delays or main deploy - heights to respond to changing launch conditions. You can - also 'reboot' the TeleMetrum device. Use this to remotely - enable the flight computer by turning TeleMetrum on while - horizontal, then once the airframe is oriented for launch, - you can reboot TeleMetrum and have it restart in pad mode - without having to climb the scary ladder. - - - - - Fire Igniters—Test your deployment charges without snaking - wires out through holes in the airframe. Simply assembly the - rocket as if for flight with the apogee and main charges - loaded, then remotely command TeleMetrum to fire the - igniters. - - - - - Packet command mode uses the same RF channels as telemetry - mode. Configure the desired TeleDongle channel using the - flight monitor window channel selector and then close that - window before performing the desired operation. - - - TeleMetrum only enables packet command mode in 'idle' mode, so - make sure you have TeleMetrum lying horizontally when you turn - it on. Otherwise, TeleMetrum will start in 'pad' mode ready for - flight and will not be listening for command packets from TeleDongle. - - - When packet command mode is enabled, you can monitor the link - by watching the lights on the TeleDongle and TeleMetrum - devices. The red LED will flash each time TeleDongle or - TeleMetrum transmit a packet while the green LED will light up - on TeleDongle while it is waiting to receive a packet from - TeleMetrum. - -
-
- Monitor Flight - Receive, Record and Display Telemetry Data - - Selecting this item brings up a dialog box listing all of the - connected TeleDongle devices. When you choose one of these, - AltosUI will create a window to display telemetry data as - received by the selected TeleDongle device. - - - All telemetry data received are automatically recorded in - suitable log files. The name of the files includes the current - date and rocket serial and flight numbers. - - - The radio channel being monitored by the TeleDongle device is - displayed at the top of the window. You can configure the - channel by clicking on the channel box and selecting the desired - channel. AltosUI remembers the last channel selected for each - TeleDongle and selects that automatically the next time you use - that device. - - - Below the TeleDongle channel selector, the window contains a few - significant pieces of information about the TeleMetrum providing - the telemetry data stream: - - - - The TeleMetrum callsign - - - The TeleMetrum serial number - - - The flight number. Each TeleMetrum remembers how many - times it has flown. - - - - - The rocket flight state. Each flight passes through several - states including Pad, Boost, Fast, Coast, Drogue, Main and - Landed. - - - - - The Received Signal Strength Indicator value. This lets - you know how strong a signal TeleDongle is receiving. The - radio inside TeleDongle operates down to about -99dBm; - weaker signals may not be receiveable. The packet link uses - error correction and detection techniques which prevent - incorrect data from being reported. - - - - - Finally, the largest portion of the window contains a set of - tabs, each of which contain some information about the rocket. - They're arranged in 'flight order' so that as the flight - progresses, the selected tab automatically switches to display - data relevant to the current state of the flight. You can select - other tabs at any time. The final 'table' tab contains all of - the telemetry data in one place. - -
- Launch Pad - - The 'Launch Pad' tab shows information used to decide when the - rocket is ready for flight. The first elements include red/green - indicators, if any of these is red, you'll want to evaluate - whether the rocket is ready to launch: - - - - Battery Voltage. This indicates whether the LiPo battery - powering the TeleMetrum has sufficient charge to last for - the duration of the flight. A value of more than - 3.7V is required for a 'GO' status. - - - - - Apogee Igniter Voltage. This indicates whether the apogee - igniter has continuity. If the igniter has a low - resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is - required for a 'GO' status. - - - - - Main Igniter Voltage. This indicates whether the main - igniter has continuity. If the igniter has a low - resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is - required for a 'GO' status. - - - - - GPS Locked. This indicates whether the GPS receiver is - currently able to compute position information. GPS requires - at least 4 satellites to compute an accurate position. - - - - - GPS Ready. This indicates whether GPS has reported at least - 10 consecutive positions without losing lock. This ensures - that the GPS receiver has reliable reception from the - satellites. - - - - - The LaunchPad tab also shows the computed launch pad position - and altitude, averaging many reported positions to improve the - accuracy of the fix. - - -
-
- Ascent - - This tab is shown during Boost, Fast and Coast - phases. The information displayed here helps monitor the - rocket as it heads towards apogee. - - - The height, speed and acceleration are shown along with the - maxium values for each of them. This allows you to quickly - answer the most commonly asked questions you'll hear during - flight. - - - The current latitude and longitude reported by the GPS are - also shown. Note that under high acceleration, these values - may not get updated as the GPS receiver loses position - fix. Once the rocket starts coasting, the receiver should - start reporting position again. - - - Finally, the current igniter voltages are reported as in the - Launch Pad tab. This can help diagnose deployment failures - caused by wiring which comes loose under high acceleration. - -
-
- Descent - - Once the rocket has reached apogee and (we hope) activated the - apogee charge, attention switches to tracking the rocket on - the way back to the ground, and for dual-deploy flights, - waiting for the main charge to fire. - - - To monitor whether the apogee charge operated correctly, the - current descent rate is reported along with the current - height. Good descent rates generally range from 15-30m/s. - - - To help locate the rocket in the sky, use the elevation and - bearing information to figure out where to look. Elevation is - in degrees above the horizon. Bearing is reported in degrees - relative to true north. Range can help figure out how big the - rocket will appear. Note that all of these values are relative - to the pad location. If the elevation is near 90°, the rocket - is over the pad, not over you. - - - Finally, the igniter voltages are reported in this tab as - well, both to monitor the main charge as well as to see what - the status of the apogee charge is. - -
-
- Landed - - Once the rocket is on the ground, attention switches to - recovery. While the radio signal is generally lost once the - rocket is on the ground, the last reported GPS position is - generally within a short distance of the actual landing location. - - - The last reported GPS position is reported both by - latitude and longitude as well as a bearing and distance from - the launch pad. The distance should give you a good idea of - whether you'll want to walk or hitch a ride. Take the reported - latitude and longitude and enter them into your handheld GPS - unit and have that compute a track to the landing location. - - - Finally, the maximum height, speed and acceleration reported - during the flight are displayed for your admiring observers. - -
-
- Site Map - - When the rocket gets a GPS fix, the Site Map tab will map - the rocket's position to make it easier for you to locate the - rocket, both while it is in the air, and when it has landed. The - rocket's state is indicated by colour: white for pad, red for - boost, pink for fast, yellow for coast, light blue for drogue, - dark blue for main, and black for landed. - - - The map's scale is approximately 3m (10ft) per pixel. The map - can be dragged using the left mouse button. The map will attempt - to keep the rocket roughly centred while data is being received. - - - Images are fetched automatically via the Google Maps Static API, - and are cached for reuse. If map images cannot be downloaded, - the rocket's path will be traced on a dark grey background - instead. - -
-
-
- Save Flight Data - - TeleMetrum records flight data to its internal flash memory. - This data is recorded at a much higher rate than the telemetry - system can handle, and is not subject to radio drop-outs. As - such, it provides a more complete and precise record of the - flight. The 'Save Flight Data' button allows you to read the - flash memory and write it to disk. - - - Clicking on the 'Save Flight Data' button brings up a list of - connected TeleMetrum and TeleDongle devices. If you select a - TeleMetrum device, the flight data will be downloaded from that - device directly. If you select a TeleDongle device, flight data - will be downloaded from a TeleMetrum device connected via the - packet command link to the specified TeleDongle. See the chapter - on Packet Command Mode for more information about this. - - - The filename for the data is computed automatically from the recorded - flight date, TeleMetrum serial number and flight number - information. - -
-
- Replay Flight - - Select this button and you are prompted to select a flight - record file, either a .telem file recording telemetry data or a - .eeprom file containing flight data saved from the TeleMetrum - flash memory. - - - Once a flight record is selected, the flight monitor interface - is displayed and the flight is re-enacted in real time. Check - the Monitor Flight chapter above to learn how this window operates. - -
-
- Graph Data - - Select this button and you are prompted to select a flight - record file, either a .telem file recording telemetry data or a - .eeprom file containing flight data saved from the TeleMetrum - flash memory. - - - Once a flight record is selected, the acceleration (blue), - velocity (green) and altitude (red) of the flight are plotted and - displayed, measured in metric units. - - - The graph can be zoomed into a particular area by clicking and - dragging down and to the right. Once zoomed, the graph can be - reset by clicking and dragging up and to the left. Holding down - control and clicking and dragging allows the graph to be panned. - The right mouse button causes a popup menu to be displayed, giving - you the option save or print the plot. - - - Note that telemetry files will generally produce poor graphs - due to the lower sampling rate and missed telemetry packets, - and will also often have significant amounts of data received - while the rocket was waiting on the pad. Use saved flight data - for graphing where possible. - -
-
- Export Data - - This tool takes the raw data files and makes them available for - external analysis. When you select this button, you are prompted to select a flight - data file (either .eeprom or .telem will do, remember that - .eeprom files contain higher resolution and more continuous - data). Next, a second dialog appears which is used to select - where to write the resulting file. It has a selector to choose - between CSV and KML file formats. - -
- Comma Separated Value Format - - This is a text file containing the data in a form suitable for - import into a spreadsheet or other external data analysis - tool. The first few lines of the file contain the version and - configuration information from the TeleMetrum device, then - there is a single header line which labels all of the - fields. All of these lines start with a '#' character which - most tools can be configured to skip over. - - - The remaining lines of the file contain the data, with each - field separated by a comma and at least one space. All of - the sensor values are converted to standard units, with the - barometric data reported in both pressure, altitude and - height above pad units. - -
-
- Keyhole Markup Language (for Google Earth) - - This is the format used by - Googleearth to provide an overlay within that - application. With this, you can use Googleearth to see the - whole flight path in 3D. - -
-
-
- Configure TeleMetrum - - Select this button and then select either a TeleMetrum or - TeleDongle Device from the list provided. Selecting a TeleDongle - device will use Packet Comamnd Mode to configure remote - TeleMetrum device. Learn how to use this in the Packet Command - Mode chapter. - - - The first few lines of the dialog provide information about the - connected TeleMetrum device, including the product name, - software version and hardware serial number. Below that are the - individual configuration entries. - - - At the bottom of the dialog, there are four buttons: - - - - - Save. This writes any changes to the TeleMetrum - configuration parameter block in flash memory. If you don't - press this button, any changes you make will be lost. - - - - - Reset. This resets the dialog to the most recently saved values, - erasing any changes you have made. - - - - - Reboot. This reboots the TeleMetrum device. Use this to - switch from idle to pad mode by rebooting once the rocket is - oriented for flight. - - - - - Close. This closes the dialog. Any unsaved changes will be - lost. - - - - - The rest of the dialog contains the parameters to be configured. - -
- Main Deploy Altitude - - This sets the altitude (above the recorded pad altitude) at - which the 'main' igniter will fire. The drop-down menu shows - some common values, but you can edit the text directly and - choose whatever you like. If the apogee charge fires below - this altitude, then the main charge will fire two seconds - after the apogee charge fires. - -
-
- Apogee Delay - - When flying redundant electronics, it's often important to - ensure that multiple apogee charges don't fire at precisely - the same time as that can overpressurize the apogee deployment - bay and cause a structural failure of the airframe. The Apogee - Delay parameter tells the flight computer to fire the apogee - charge a certain number of seconds after apogee has been - detected. - -
-
- Radio Channel - - This configures which of the 10 radio channels to use for both - telemetry and packet command mode. Note that if you set this - value via packet command mode, you will have to reconfigure - the TeleDongle channel before you will be able to use packet - command mode again. - -
-
- Radio Calibration - - The radios in every Altus Metrum device are calibrated at the - factory to ensure that they transmit and receive on the - specified frequency for each channel. You can adjust that - calibration by changing this value. To change the TeleDongle's - calibration, you must reprogram the unit completely. - -
-
- Callsign - - This sets the callsign included in each telemetry packet. Set this - as needed to conform to your local radio regulations. - -
-
-
- Configure AltosUI - - This button presents a dialog so that you can configure the AltosUI global settings. - -
- Voice Settings - - AltosUI provides voice annoucements during flight so that you - can keep your eyes on the sky and still get information about - the current flight status. However, sometimes you don't want - to hear them. - - - - Enable—turns all voice announcements on and off - - - - Test Voice—Plays a short message allowing you to verify - that the audio systme is working and the volume settings - are reasonable - - - -
-
- Log Directory - - AltosUI logs all telemetry data and saves all TeleMetrum flash - data to this directory. This directory is also used as the - staring point when selecting data files for display or export. - - - Click on the directory name to bring up a directory choosing - dialog, select a new directory and click 'Select Directory' to - change where AltosUI reads and writes data files. - -
-
- Callsign - - This value is used in command packet mode and is transmitted - in each packet sent from TeleDongle and received from - TeleMetrum. It is not used in telemetry mode as that transmits - packets only from TeleMetrum to TeleDongle. Configure this - with the AltosUI operators callsign as needed to comply with - your local radio regulations. - -
-
-
- Flash Image - - This reprograms any Altus Metrum device by using a TeleMetrum or - TeleDongle as a programming dongle. Please read the directions - for connecting the programming cable in the main TeleMetrum - manual before reading these instructions. - - - Once you have the programmer and target devices connected, - push the 'Flash Image' button. That will present a dialog box - listing all of the connected devices. Carefully select the - programmer device, not the device to be programmed. - - - Next, select the image to flash to the device. These are named - with the product name and firmware version. The file selector - will start in the directory containing the firmware included - with the AltosUI package. Navigate to the directory containing - the desired firmware if it isn't there. - - - Next, a small dialog containing the device serial number and - RF calibration values should appear. If these values are - incorrect (possibly due to a corrupted image in the device), - enter the correct values here. - - - Finally, a dialog containing a progress bar will follow the - programming process. - - - When programming is complete, the target device will - reboot. Note that if the target device is connected via USB, you - will have to unplug it and then plug it back in for the USB - connection to reset so that you can communicate with the device - again. - -
-
- Fire Igniter - - This activates the igniter circuits in TeleMetrum to help test - recovery systems deployment. Because this command can operate - over the Packet Command Link, you can prepare the rocket as - for flight and then test the recovery system without needing - to snake wires inside the airframe. - - - Selecting the 'Fire Igniter' button brings up the usual device - selection dialog. Pick the desired TeleDongle or TeleMetrum - device. This brings up another window which shows the current - continutity test status for both apogee and main charges. - - - Next, select the desired igniter to fire. This will enable the - 'Arm' button. - - - Select the 'Arm' button. This enables the 'Fire' button. The - word 'Arm' is replaced by a countdown timer indicating that - you have 10 seconds to press the 'Fire' button or the system - will deactivate, at which point you start over again at - selecting the desired igniter. - -
-
- - Using Altus Metrum Products -
- Being Legal - - First off, in the US, you need an amateur radio license or - other authorization to legally operate the radio transmitters that are part - of our products. - -
- In the Rocket - - In the rocket itself, you just need a TeleMetrum board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a TeleMetrum for hours. - - - By default, we ship TeleMetrum with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, - which is opaque to RF signals, you may choose to have an SMA connector - installed so that you can run a coaxial cable to an antenna mounted - elsewhere in the rocket. - -
-
- On the Ground - - To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our TeleDongle units. The - TeleDongle in turn plugs directly into the USB port on a notebook - computer. Because TeleDongle looks like a simple serial port, your computer - does not require special device drivers... just plug it in. - - - The GUI tool, AltosUI, is written in Java and runs across - Linux, Mac OS and Windows. There's also a suite of C tools - for Linux which can perform most of the same tasks. - - - After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the - TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo - battery, so you'll want one of those anyway... the same cable used by lots - of digital cameras and other modern electronic stuff will work fine. - - - If your rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket - position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. - - - You may also enjoy having a ham radio "HT" that covers the 70cm band... you - can use that with your antenna to direction-find the rocket on the ground - the same way you can use a Walston or Beeline tracker. This can be handy - if the rocket is hiding in sage brush or a tree, or if the last GPS position - doesn't get you close enough because the rocket dropped into a canyon, or - the wind is blowing it across a dry lake bed, or something like that... Keith - and Bdale both currently own and use the Yaesu VX-7R at launches. - - - So, to recap, on the ground the hardware you'll need includes: - - - an antenna and feedline - - - a TeleDongle - - - a notebook computer - - - optionally, a handheld GPS receiver - - - optionally, an HT or receiver covering 435 Mhz - - - - - The best hand-held commercial directional antennas we've found for radio - direction finding rockets are from - - Arrow Antennas. - - The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. - -
-
- Data Analysis - - Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum - board. Once this data is on your computer, our postflight tools make it - easy to quickly get to the numbers everyone wants, like apogee altitude, - max acceleration, and max velocity. You can also generate and view a - standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file - useable with Google Maps and Google Earth for visualizing the flight path - in two or three dimensions! - - - Our ultimate goal is to emit a set of files for each flight that can be - published as a web page per flight, or just viewed on your local disk with - a web browser. - -
-
- Future Plans - - In the future, we intend to offer "companion boards" for the rocket that will - plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. - - - We are also working on the design of a hand-held ground terminal that will - allow monitoring the rocket's status, collecting data during flight, and - logging data after flight without the need for a notebook computer on the - flight line. Particularly since it is so difficult to read most notebook - screens in direct sunlight, we think this will be a great thing to have. - - - Because all of our work is open, both the hardware designs and the software, - if you have some great idea for an addition to the current Altus Metrum family, - feel free to dive in and help! Or let us know what you'd like to see that - we aren't already working on, and maybe we'll get excited about it too... - -
-
-
-
- -- cgit v1.2.3 From 4893ed50bc14772986ac02f9b39928f1882da923 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 23:54:08 -0800 Subject: Revert "altos: Don't abort radio transmissions with ao_radio_abort" This reverts commit 54468e5dc567aaac5c5c20e921859b7cec28bb88. With this patch in place, TD could not be placed in 'packet' mode. --- src/ao_radio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/ao_radio.c b/src/ao_radio.c index 67d5f6ba..cafa7010 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,11 +432,8 @@ ao_radio_rdf(int ms) void ao_radio_abort(void) { - /* Only abort if a task is waiting to receive data */ - if (RFST == RFST_SRX) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); } void -- cgit v1.2.3 From 3d98440d53378aaa6da87ed65e9abb2f96f7ee49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 11:16:28 -0800 Subject: altosui: Make windows bits build after moving altosui directory Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 37777fd6..d7c4b32a 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -9,7 +9,7 @@ InstallDir "$PROGRAMFILES\AltusMetrum" InstallDirRegKey HKLM "Software\AltusMetrum" "Install_Dir" LicenseText "GNU General Public License Version 2" -LicenseData "../../COPYING" +LicenseData "../COPYING" ; Need admin privs for Vista or Win7 RequestExecutionLevel admin @@ -38,11 +38,11 @@ Section "Install Driver" InstDriver InstDrv::DeleteOemInfFiles /NOUNLOAD InstDrv::CreateDevice /NOUNLOAD SetOutPath $TEMP - File "../../telemetrum.inf" + File "../telemetrum.inf" InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf" SetOutPath $INSTDIR - File "../../telemetrum.inf" + File "../telemetrum.inf" SectionEnd Section "AltosUI Application" @@ -59,7 +59,7 @@ Section "AltosUI Application" File "*.dll" - File "../../icon/*.ico" + File "../icon/*.ico" CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico" SectionEnd @@ -72,8 +72,8 @@ 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" + File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" + File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" SectionEnd -- cgit v1.2.3 From f88bde21d76a4ff91099a5051153ebace1619978 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 11:16:55 -0800 Subject: altosui: Hack up standalone makefile to maybe build altosui again This isn't tested, but at least the paths are more likely to be correct Signed-off-by: Keith Packard --- altosui/Makefile-standalone | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/altosui/Makefile-standalone b/altosui/Makefile-standalone index a95a5aa8..0d9931d5 100644 --- a/altosui/Makefile-standalone +++ b/altosui/Makefile-standalone @@ -44,8 +44,8 @@ CLASSFILES=\ AltosRomconfigUI.class \ AltosVoice.class -JAVA_ICON=../../icon/altus-metrum-16x16.jpg -WINDOWS_ICON=../../icon/altus-metrum.ico +JAVA_ICON=../icon/altus-metrum-16x16.jpg +WINDOWS_ICON=../icon/altus-metrum.ico # where altosui.jar gets installed ALTOSLIB=/usr/share/java @@ -64,7 +64,7 @@ FREETTSJAR= \ $(FREETTSLIB)/freetts.jar # The current hex files -HEXLIB=../../src +HEXLIB=../src HEXFILES = \ $(HEXLIB)/telemetrum-v1.0.ihx \ $(HEXLIB)/teledongle-v0.2.ihx @@ -105,11 +105,11 @@ classes/altosui: classes/libaltosJNI: mkdir -p classes - ln -sf ../../libaltos/libaltosJNI classes/libaltosJNI + ln -sf ../libaltos/libaltosJNI classes/libaltosJNI classes/images: mkdir -p classes/images - ln -sf ../../$(JAVA_ICON) classes/images + ln -sf ../$(JAVA_ICON) classes/images altosui: echo "#!/bin/sh" > $@ @@ -128,7 +128,7 @@ fat/altosui.jar: $(CLASSFILES) $(JAVA_ICON) fat/classes/Manifest.txt 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 + 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 @@ -153,7 +153,7 @@ distclean: clean FAT_FILES=$(FATJAR) $(FREETTSJAR) $(HEXFILES) -LINUX_FILES=$(FAT_FILES) ../libaltos/libaltos.so fat/altosui +LINUX_FILES=$(FAT_FILES) libaltos/libaltos.so fat/altosui $(LINUX_TGZ): $(LINUX_FILES) rm -f $@ mkdir -p linux/AltOS @@ -161,7 +161,7 @@ $(LINUX_TGZ): $(LINUX_FILES) cp $(LINUX_FILES) linux/AltOS cd linux && tar czf ../$@ AltOS -DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) ../libaltos/libaltos.dylib +DARWIN_RESOURCES=$(FATJAR) $(FREETTSJAR) libaltos/libaltos.dylib DARWIN_EXTRA=$(HEXFILES) DARWIN_FILES=$(DARWIN_RESOURCES) $(DARWIN_EXTRA) @@ -174,7 +174,7 @@ $(DARWIN_ZIP): $(DARWIN_FILES) cp $(DARWIN_EXTRA) darwin/AltOS cd darwin && zip -r ../$@ AltosUI.app AltOS -WINDOWS_FILES = $(FAT_FILES) ../libaltos/altos.dll ../../telemetrum.inf $(WINDOWS_ICON) +WINDOWS_FILES = $(FAT_FILES) libaltos/altos.dll ../telemetrum.inf $(WINDOWS_ICON) $(WINDOWS_EXE): $(WINDOWS_FILES) altos-windows.nsi rm -f $@ -- cgit v1.2.3 From b74cec6cd0bc043f53e9e28472765aa343136813 Mon Sep 17 00:00:00 2001 From: Bob Finch Date: Thu, 25 Nov 2010 13:30:48 -0700 Subject: Updated AltOS PKGBUILD to track makefile changes --- contrib/arch-linux/PKGBUILD-git.altos | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contrib/arch-linux/PKGBUILD-git.altos b/contrib/arch-linux/PKGBUILD-git.altos index 0a3ecec5..4210bc3a 100644 --- a/contrib/arch-linux/PKGBUILD-git.altos +++ b/contrib/arch-linux/PKGBUILD-git.altos @@ -1,6 +1,6 @@ # Original contributor: Bob Finch pkgname=altos-git -pkgver=20101031 +pkgver=20101125 pkgrel=1 pkgdesc="Software solutions for high powered rocketry avionics" arch=('i686' 'x86_64') @@ -51,7 +51,7 @@ build() { # --with-fat-dir=$srcdir # Use this ^ for placing all 3 "fat" packages (linux,mac,windows) into a numbered dir. - cd "$srcdir/$_gitname-build/ao-tools/$_pkgname/" + cd "$srcdir/$_gitname-build/$_pkgname/" sed -i 's:\$(datadir)/java:\$(datadir)/java/altos:' Makefile # This ^ places altosui.jar in an 'altos' subdirectory. sed -i 's:\${exec_prefix}/bin:\${exec_prefix}/share/java/altos:' Makefile @@ -61,7 +61,7 @@ build() { sed -i 's:cp -p $(JFREECHART_CLASS):cp -p $(JFREECHART_CLASS) $(JCOMMON_CLASS):' Makefile # This ^ includes jcommon.jar in the macosx fat package. - cd "$srcdir/$_gitname-build/ao-tools/$_libname/" + cd "$srcdir/$_gitname-build/$_pkgname/$_libname/" sed -i 's:$(JVM_INCLUDE):/opt/java/include\ -I/opt/java/include/linux:' Makefile # This ^ enables both jni.h and jni_md.h to be found as required. @@ -75,7 +75,7 @@ build() { cd "$srcdir/$_gitname-build/doc" make all - cd "$srcdir/$_gitname-build/ao-tools/altosui" + cd "$srcdir/$_gitname-build/$_pkgname" make fat } -- cgit v1.2.3 From 12fb7f0e70cd244475d84469f93283112478d1e1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 15:56:42 -0800 Subject: altosui: Only call swing display functions from main thread. Swing insists that all display functions be called from a single thread, and the flight window wasn't following this for display updates. Use SwingUtilities.invokeLater to make sure the flight UI updates happen in the right context. Fixes a UI freeze on Mac OS. Signed-off-by: Keith Packard --- altosui/AltosDisplayThread.java | 49 +++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index 3e719130..84abfae9 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -38,11 +38,45 @@ public class AltosDisplayThread extends Thread { int crc_errors; AltosFlightDisplay display; - synchronized void show(AltosState state, int crc_errors) { + void show_internal(AltosState state, int crc_errors) { if (state != null) display.show(state, crc_errors); } + void show_safely(AltosState in_state, int in_crc_errors) { + final AltosState state = in_state; + final int crc_errors = in_crc_errors; + Runnable r = new Runnable() { + public void run() { + try { + show_internal(state, crc_errors); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + void reading_error_internal(String name) { + JOptionPane.showMessageDialog(parent, + String.format("Error reading from \"%s\"", name), + "Telemetry Read Error", + JOptionPane.ERROR_MESSAGE); + } + + void reading_error_safely(String in_name) { + final String name = in_name; + Runnable r = new Runnable() { + public void run() { + try { + reading_error_internal(name); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + class IdleThread extends Thread { boolean started; @@ -102,7 +136,7 @@ public class AltosDisplayThread extends Thread { ++reported_landing; if (state.state != Altos.ao_flight_landed) { state.state = Altos.ao_flight_landed; - show(state, 0); + show_safely(state, 0); } } } @@ -202,7 +236,6 @@ public class AltosDisplayThread extends Thread { idle_thread = new IdleThread(); - display.reset(); try { for (;;) { try { @@ -212,23 +245,20 @@ public class AltosDisplayThread extends Thread { old_state = state; state = new AltosState(record, state); reader.update(state); - show(state, crc_errors); + show_safely(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); + show_safely(state, crc_errors); } } } catch (InterruptedException ee) { interrupted = true; } catch (IOException ie) { - JOptionPane.showMessageDialog(parent, - String.format("Error reading from \"%s\"", name), - "Telemetry Read Error", - JOptionPane.ERROR_MESSAGE); + reading_error_safely(name); } finally { if (!interrupted) idle_thread.report(true); @@ -245,5 +275,6 @@ public class AltosDisplayThread extends Thread { voice = in_voice; display = in_display; reader = in_reader; + display.reset(); } } -- cgit v1.2.3 From 6d3612e267cd4c1e7fdd74fc33952b3f26f870f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 16:09:37 -0800 Subject: altosui: Eliminate unnecessary thread from config UI There's no reason to use a thread to run a dialog box, and swing doesn't like threads anyways. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 1c42870f..38e1484e 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -30,7 +30,7 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosConfig implements Runnable, ActionListener { +public class AltosConfig implements ActionListener { class int_ref { int value; @@ -64,7 +64,6 @@ public class AltosConfig implements Runnable, ActionListener { AltosDevice device; AltosSerial serial_line; boolean remote; - Thread config_thread; int_ref serial; int_ref main_deploy; int_ref apogee_delay; @@ -241,17 +240,6 @@ public class AltosConfig implements Runnable, ActionListener { } } - public void run () { - try { - init_ui(); - config_ui.make_visible(); - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } - } - public AltosConfig(JFrame given_owner) { owner = given_owner; @@ -270,8 +258,14 @@ public class AltosConfig implements Runnable, ActionListener { serial_line = new AltosSerial(device); if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; - config_thread = new Thread(this); - config_thread.start(); + try { + init_ui(); + config_ui.make_visible(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, String.format("Cannot open device \"%s\"", -- cgit v1.2.3 From 7f88520089660845009148b69bfcea6c9dff9672 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 16:23:18 -0800 Subject: altosui: Flight data download GUI operations called only from main thread Swing doesn't like UI functions being called from non-dispatch thread, so fix up the eeprom download code to use SwingUtilities.invokeLater to make sure this works right. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 49 ++++++++++++++++++-------- altosui/AltosEepromMonitor.java | 76 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 02fc36f2..e5ff766c 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -214,6 +214,27 @@ public class AltosEepromDownload implements Runnable { } } + private void show_error_internal(String message, String title) { + JOptionPane.showMessageDialog(frame, + message, + title, + JOptionPane.ERROR_MESSAGE); + } + + private void show_error(String in_message, String in_title) { + final String message = in_message; + final String title = in_title; + Runnable r = new Runnable() { + public void run() { + try { + show_error_internal(message, title); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + public void run () { if (remote) { serial_line.set_radio(); @@ -221,26 +242,16 @@ public class AltosEepromDownload implements Runnable { serial_line.flush_input(); } - monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); - monitor.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - eeprom_thread.interrupt(); - } - }); try { CaptureLog(); } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); + show_error (device.toShortString(), + ee.getLocalizedMessage()); } catch (InterruptedException ie) { } catch (TimeoutException te) { - JOptionPane.showMessageDialog(frame, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); + show_error (String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed"); } if (remote) serial_line.printf("~"); @@ -260,6 +271,14 @@ public class AltosEepromDownload implements Runnable { serial_line = new AltosSerial(device); if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (eeprom_thread != null) + eeprom_thread.interrupt(); + } + }); + eeprom_thread = new Thread(this); eeprom_thread.start(); } catch (FileNotFoundException ee) { diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index 7ff00ead..13a49a95 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -141,7 +141,7 @@ public class AltosEepromMonitor extends JDialog { cancel.addActionListener(l); } - public void set_value(String state_name, int in_state, int in_block) { + private void set_value_internal(String state_name, int in_state, int in_block) { int block = in_block; int state = in_state; @@ -157,20 +157,86 @@ public class AltosEepromMonitor extends JDialog { pbar.setValue(pos); } - public void set_serial(int serial) { + public void set_value(String in_state_name, int in_state, int in_block) { + final String state_name = in_state_name; + final int state = in_state; + final int block = in_block; + Runnable r = new Runnable() { + public void run() { + try { + set_value_internal(state_name, state, block); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_serial_internal(int serial) { serial_value.setText(String.format("%d", serial)); } - public void set_flight(int flight) { + public void set_serial(int in_serial) { + final int serial = in_serial; + Runnable r = new Runnable() { + public void run() { + try { + set_serial_internal(serial); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_flight_internal(int flight) { flight_value.setText(String.format("%d", flight)); } - public void set_file(String file) { + public void set_flight(int in_flight) { + final int flight = in_flight; + Runnable r = new Runnable() { + public void run() { + try { + set_flight_internal(flight); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void set_file_internal(String file) { file_value.setText(String.format("%s", file)); } - public void done() { + public void set_file(String in_file) { + final String file = in_file; + Runnable r = new Runnable() { + public void run() { + try { + set_file_internal(file); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + private void done_internal() { setVisible(false); dispose(); } + + public void done() { + Runnable r = new Runnable() { + public void run() { + try { + done_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } } -- cgit v1.2.3 From adbb14c63d85b7a54223f88ac623571456f4a462 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 16:28:04 -0800 Subject: altosui: Remove gratuitous threading from device flashing UI There's no need for a thread here, and swing doesn't want us to use one anyways. Signed-off-by: Keith Packard --- altosui/AltosFlashUI.java | 83 ++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 44 deletions(-) diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index f63097ac..0b61f041 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -30,7 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosFlashUI extends JDialog - implements Runnable, ActionListener + implements ActionListener { Container pane; Box box; @@ -64,47 +64,6 @@ public class AltosFlashUI } } - public void run() { - try { - flash = new AltosFlash(file, debug_dongle); - flash.addActionListener(this); - 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 (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - debug_dongle.toShortString()), - "Device in use", - 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(); @@ -212,7 +171,43 @@ public class AltosFlashUI if (file != null) AltosPreferences.set_firmwaredir(file.getParentFile()); - thread = new Thread(this); - thread.start(); + try { + flash = new AltosFlash(file, debug_dongle); + flash.addActionListener(this); + 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 (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + debug_dongle.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException e) { + JOptionPane.showMessageDialog(frame, + e.getMessage(), + file.toString(), + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + } finally { + abort(); + } + dispose(); } } \ No newline at end of file -- cgit v1.2.3 From b8f05cdc0e9b4a96852eed9d38ff6d5950e2d2ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Nov 2010 17:29:28 -0800 Subject: altosui: Clean up flash code to ensure swing gets called from right thread This moves all of the flash code to a separate thread and passes messages back to the swing thread to keep the UI up to date. Signed-off-by: Keith Packard --- altosui/AltosFlash.java | 202 +++++++++++++++++++++++++++------------------- altosui/AltosFlashUI.java | 25 +++--- 2 files changed, 132 insertions(+), 95 deletions(-) diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java index 3af25c23..802adc8c 100644 --- a/altosui/AltosFlash.java +++ b/altosui/AltosFlash.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosFlash { +public class AltosFlash implements Runnable { File file; FileInputStream input; AltosHexfile image; @@ -197,23 +197,36 @@ public class AltosFlash { }; 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; + if (debug != null) { + 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"); } - 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(String in_s, int in_percent) { + final String s = in_s; + final int percent = in_percent; + if (listener != null && !aborted) { + Runnable r = new Runnable() { + public void run() { + try { + listener.actionPerformed(new ActionEvent(this, + percent, + s)); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } } void action(int part, int total) { @@ -223,7 +236,7 @@ public class AltosFlash { percent); } - void run(int pc) throws IOException, InterruptedException { + void altos_run(int pc) throws IOException, InterruptedException { debug.set_pc(pc); int set_pc = debug.get_pc(); if (pc != set_pc) @@ -239,74 +252,96 @@ public class AltosFlash { 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); + Thread thread; + + public void run() { + try { + 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; + + if (debug != null) { + /* 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); + + altos_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])); + } else { + Thread.sleep(100); + } + + remain -= this_time; + flash_addr += this_time; + image_start += this_time; + + action(image.data.length - remain, image.data.length); + } + if (!aborted) { + action("done", 100); + if (debug != null) { + debug.set_pc(image.address); + debug.resume(); + } + } + if (debug != null) + debug.close(); + } catch (IOException ie) { + action(ie.getMessage(), -1); + abort(); + } catch (InterruptedException ie) { + abort(); } - if (!aborted) { - action("done", 100); - debug.set_pc(image.address); - debug.resume(); - } - debug.close(); } - public void abort() { + public void flash() { + thread = new Thread(this); + thread.start(); + } + + synchronized public void abort() { aborted = true; - debug.close(); + if (debug != null) + debug.close(); } public void addActionListener(ActionListener l) { @@ -314,6 +349,8 @@ public class AltosFlash { } public boolean check_rom_config() { + if (debug == null) + return true; if (rom_config == null) rom_config = debug.romconfig(); return rom_config != null && rom_config.valid(); @@ -333,10 +370,11 @@ public class AltosFlash { throws IOException, FileNotFoundException, AltosSerialInUseException, InterruptedException { file = in_file; debug_dongle = in_debug_dongle; - debug = new AltosDebug(in_debug_dongle); + if (debug_dongle != null) + debug = new AltosDebug(in_debug_dongle); input = new FileInputStream(file); image = new AltosHexfile(input); - if (!debug.check_connection()) { + if (debug != null && !debug.check_connection()) { debug.close(); throw new IOException("Debug port not connected"); } diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 0b61f041..0302ccd3 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -49,13 +49,21 @@ public class AltosFlashUI public void actionPerformed(ActionEvent e) { if (e.getSource() == cancel) { - abort(); + setVisible(false); dispose(); } else { String cmd = e.getActionCommand(); - if (cmd.equals("done")) - ; - else if (cmd.equals("start")) { + if (e.getID() == -1) { + JOptionPane.showMessageDialog(frame, + e.getActionCommand(), + file.toString(), + JOptionPane.ERROR_MESSAGE); + setVisible(false); + dispose(); + } else if (cmd.equals("done")) { + setVisible(false); + dispose(); + } else if (cmd.equals("start")) { setVisible(true); } else { pbar.setValue(e.getID()); @@ -64,11 +72,6 @@ public class AltosFlashUI } } - public void abort() { - if (flash != null) - flash.abort(); - } - public void build_dialog() { GridBagConstraints c; Insets il = new Insets(4,4,4,4); @@ -186,7 +189,6 @@ public class AltosFlashUI file_value.setText(file.toString()); setVisible(true); flash.flash(); - flash = null; } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, @@ -205,9 +207,6 @@ public class AltosFlashUI file.toString(), JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { - } finally { - abort(); } - dispose(); } } \ No newline at end of file -- cgit v1.2.3 From ab6c9c983a2830bc8807e1b75d2576141b73632d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Nov 2010 19:30:02 -0700 Subject: update fat target in Makefiles to reflect move of altosui and libaltos --- Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2c412bf9..0767ccde 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,5 +14,5 @@ dist-hook: ChangeLog fat: cd src && $(MAKE) all - cd ao-tools/libaltos && $(MAKE) all - cd ao-tools/altosui && $(MAKE) fat + cd altosui/libaltos && $(MAKE) all + cd altosui && $(MAKE) fat -- cgit v1.2.3 From da3b39d6b1b5ba48686c2a4add4b5448fd5711af Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Nov 2010 22:29:01 -0700 Subject: changed main document name from telemetrum-doc to altusmetrum --- debian/docs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/docs b/debian/docs index 6eac4541..13fda8f2 100644 --- a/debian/docs +++ b/debian/docs @@ -1,4 +1,4 @@ NEWS README -doc/telemetrum-doc.html -doc/telemetrum-doc.pdf +doc/altusmetrum.html +doc/altusmetrum.pdf -- cgit v1.2.3 From f834b22905db87557f729f942607dc363b013694 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Nov 2010 22:31:33 -0700 Subject: update changelogs for Debian build --- ChangeLog | 1210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 204 +++++++++ 2 files changed, 1414 insertions(+) diff --git a/ChangeLog b/ChangeLog index c248fe08..3c6fd159 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1213 @@ +commit da3b39d6b1b5ba48686c2a4add4b5448fd5711af +Author: Bdale Garbee +Date: Thu Nov 25 22:29:01 2010 -0700 + + changed main document name from telemetrum-doc to altusmetrum + +commit ab6c9c983a2830bc8807e1b75d2576141b73632d +Author: Bdale Garbee +Date: Thu Nov 25 19:30:02 2010 -0700 + + update fat target in Makefiles to reflect move of altosui and libaltos + +commit b8f05cdc0e9b4a96852eed9d38ff6d5950e2d2ed +Author: Keith Packard +Date: Thu Nov 25 17:29:28 2010 -0800 + + altosui: Clean up flash code to ensure swing gets called from right thread + + This moves all of the flash code to a separate thread and passes + messages back to the swing thread to keep the UI up to date. + + Signed-off-by: Keith Packard + +commit adbb14c63d85b7a54223f88ac623571456f4a462 +Author: Keith Packard +Date: Thu Nov 25 16:28:04 2010 -0800 + + altosui: Remove gratuitous threading from device flashing UI + + There's no need for a thread here, and swing doesn't want us to use + one anyways. + + Signed-off-by: Keith Packard + +commit 7f88520089660845009148b69bfcea6c9dff9672 +Author: Keith Packard +Date: Thu Nov 25 16:23:18 2010 -0800 + + altosui: Flight data download GUI operations called only from main thread + + Swing doesn't like UI functions being called from non-dispatch thread, + so fix up the eeprom download code to use SwingUtilities.invokeLater + to make sure this works right. + + Signed-off-by: Keith Packard + +commit 6d3612e267cd4c1e7fdd74fc33952b3f26f870f5 +Author: Keith Packard +Date: Thu Nov 25 16:09:37 2010 -0800 + + altosui: Eliminate unnecessary thread from config UI + + There's no reason to use a thread to run a dialog box, and + swing doesn't like threads anyways. + + Signed-off-by: Keith Packard + +commit 12fb7f0e70cd244475d84469f93283112478d1e1 +Author: Keith Packard +Date: Thu Nov 25 15:56:42 2010 -0800 + + altosui: Only call swing display functions from main thread. + + Swing insists that all display functions be called from a single + thread, and the flight window wasn't following this for display + updates. Use SwingUtilities.invokeLater to make sure the flight UI + updates happen in the right context. + + Fixes a UI freeze on Mac OS. + + Signed-off-by: Keith Packard + +commit b74cec6cd0bc043f53e9e28472765aa343136813 +Author: Bob Finch +Date: Thu Nov 25 13:30:48 2010 -0700 + + Updated AltOS PKGBUILD to track makefile changes + +commit f88bde21d76a4ff91099a5051153ebace1619978 +Author: Keith Packard +Date: Thu Nov 25 11:16:55 2010 -0800 + + altosui: Hack up standalone makefile to maybe build altosui again + + This isn't tested, but at least the paths are more likely to be correct + + Signed-off-by: Keith Packard + +commit 3d98440d53378aaa6da87ed65e9abb2f96f7ee49 +Author: Keith Packard +Date: Thu Nov 25 11:16:28 2010 -0800 + + altosui: Make windows bits build after moving altosui directory + + Signed-off-by: Keith Packard + +commit 4893ed50bc14772986ac02f9b39928f1882da923 +Author: Keith Packard +Date: Wed Nov 24 23:54:08 2010 -0800 + + Revert "altos: Don't abort radio transmissions with ao_radio_abort" + + This reverts commit 54468e5dc567aaac5c5c20e921859b7cec28bb88. + + With this patch in place, TD could not be placed in 'packet' mode. + +commit cb08bc264c71ca972027392b42f347a03df76a43 +Author: Keith Packard +Date: Wed Nov 24 22:55:08 2010 -0800 + + doc: Rename telemetrum-doc as altusmetrum + + Signed-off-by: Keith Packard + +commit 554bdd25e132dbaec322bc11f94093d2c2e78751 +Author: Keith Packard +Date: Wed Nov 24 22:49:33 2010 -0800 + + doc: Add more authors, fix URL formatting, note that AltosUI actually exists + + Add aj and bfinch as authors. Insert an acknowledgements section. Fill + in the Fire Igniter section in the AltosUI chapter. Then change the + section talking about the future plans for Java to mention that they + actually exist now. + + Signed-off-by: Keith Packard + +commit bcf78b67717374b5971820021b83061e2e9734cf +Author: Keith Packard +Date: Wed Nov 24 21:39:18 2010 -0800 + + doc: Reformat altos to use sections for each function + + This places them in the TOC, making them easier to find. + + Signed-off-by: Keith Packard + +commit 51c7741040d95c5deece939dae5e4136cc04afc4 +Merge: d1dbe3b 4e47c44 +Author: Keith Packard +Date: Wed Nov 24 21:00:52 2010 -0800 + + Merge branch 'buttonbox' + + Conflicts: + doc/telemetrum-doc.xsl + + Pull the buttbox version of the docs in as it had been updated. + + Signed-off-by: Keith Packard + +commit 4e47c44d335276cf0dc5ed3a0756e50c98c1b9b9 +Author: Bdale Garbee +Date: Wed Nov 24 21:44:53 2010 -0700 + + manually fold in documentation work from the master branch + +commit 8a68c1da253c0b29a7cb9c7540c20585ad6e3dec +Author: Bdale Garbee +Date: Wed Nov 24 21:21:53 2010 -0700 + + tweak rev history + +commit 7cd1c7765d137df711caeeb69abaaba1b36e0a65 +Author: Bdale Garbee +Date: Wed Nov 24 20:53:36 2010 -0700 + + fix missing section close in Site Map content + +commit db2b19b8f0d452d682d53c7ed0ff6e359b46efa0 +Merge: b372f3c 915f881 +Author: Keith Packard +Date: Wed Nov 24 18:57:35 2010 -0800 + + Merge remote branch 'aj/buttonbox' into buttonbox + +commit b372f3c0ee4ec49aabe61c169cb1eb9bb4fb2cfc +Author: Keith Packard +Date: Wed Nov 24 18:50:46 2010 -0800 + + Missing change to top level Makefile to build altosui + + Signed-off-by: Keith Packard + +commit 915f881d61294dc6f5a6a3e8d75567e18492a631 +Author: Anthony Towns +Date: Thu Nov 25 09:52:30 2010 +1000 + + doc: Document altosui "Site Map" tab + +commit f01096c4b42f9a4720ed0414826c2a283a992545 +Merge: 357826a 3fbefb3 +Author: Anthony Towns +Date: Thu Nov 25 09:10:50 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 3fbefb3eea981d34a09496cf8abf0119de2e35bf +Author: Keith Packard +Date: Wed Nov 24 14:57:57 2010 -0800 + + Move altosui to the top level, placing libaltos inside it. + + Signed-off-by: Keith Packard + +commit 357826aa9c7b42c59f5d52b8eb016d73b6da0c7f +Author: Anthony Towns +Date: Thu Nov 25 09:07:34 2010 +1000 + + docs: Document altosui "Graph Data" button + +commit 7811e6dfa6caf10251da7df7c24b98cdc3787892 +Merge: 71b1949 7a50837 +Author: Anthony Towns +Date: Thu Nov 25 08:47:36 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 7a50837ea0d92db3f469f197ec8210aee22aa143 +Author: Keith Packard +Date: Wed Nov 24 10:55:18 2010 -0800 + + altosui: Make sure packet mode is turned off when the connection fails + + When the packet connection times out, turn packet mode off when + closing the serial port. + + Signed-off-by: Keith Packard + +commit 7d90e2f6009e060fb59c519f7e564483a7ca6872 +Author: Keith Packard +Date: Tue Nov 23 20:17:44 2010 -0800 + + altosui: Let people fire igniters that don't read as 'ready' + + This provides for igniter testing with LEDs or other materials that + don't look like regular igniters. + + Signed-off-by: Keith Packard + +commit f3233985a132e1d660e6df12d0056b6729f16faf +Author: Keith Packard +Date: Tue Nov 23 19:09:31 2010 -0800 + + altosui: Disable radio configation over packet link. + + Attempting to configure the radio over the packet link will only end + up confusing the user, so disable it. This also works around a bug in + older TM code which would lock up when trying to do this. + + Signed-off-by: Keith Packard + +commit 6cd9be22f06f21d12ee2f668989d83d3c61d14c0 +Author: Keith Packard +Date: Tue Nov 23 19:08:07 2010 -0800 + + altosui: New AltosSerial.set_radio function sets channel/call + + Use this anytime you need to set the device radio channel and call + sign, either for telemetry reception or packet mode origination. This + uses the saved callsign and per-device radio channel number. Do not + use this when opening a telemetrum as there won't be a saved channel number. + + Signed-off-by: Keith Packard + +commit ed7cf7d262fcf7c0c677c2fb981582b571de9e5e +Author: Keith Packard +Date: Tue Nov 23 19:04:55 2010 -0800 + + altosui: Make AltosSerial.flush_input keep reading while non-empty + + Flushing the input buffer can take a while, especially over the packet + link. Keep reading while stuff is appearing on the reply queue. + + Signed-off-by: Keith Packard + +commit 3b9db8c82d26a6a2e43d4ca40742fc1bdc502380 +Author: Keith Packard +Date: Tue Nov 23 19:02:54 2010 -0800 + + altos: Make radio test command careful with the radio mutex. + + Remember whether the radio test mode is on or off and don't try to do + either of them twice to prevent the mutex from being acquired or + released twice. + + Signed-off-by: Keith Packard + +commit 54468e5dc567aaac5c5c20e921859b7cec28bb88 +Author: Keith Packard +Date: Tue Nov 23 18:57:49 2010 -0800 + + altos: Don't abort radio transmissions with ao_radio_abort + + We only want to abort pending radio reception to release the radio for + other use, or to change the radio channel. Let radio transmission + proceed. This fixes a problem with using packet mode to configure the + radio channel; if the packet transmission is aborted, the TM ends up + wedged. + + Signed-off-by: Keith Packard + +commit d873dc28f0752aeb58a6263e42bdd5b9095bd392 +Author: Keith Packard +Date: Tue Nov 23 18:56:46 2010 -0800 + + altos: remove unused variable from ao_igniter + + The 'status' variable used to hold a reported status value from the + igniter after firing, but we ignore that now. + + Signed-off-by: Keith Packard + +commit 71b1949e50f4533bcf44537da65b19bc67863c8e +Merge: a79225c f1892b1 +Author: Anthony Towns +Date: Wed Nov 24 12:14:11 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit f1892b137b1de3d6caf0293bd40ed5c3e4948066 +Author: Bdale Garbee +Date: Tue Nov 23 18:58:11 2010 -0700 + + lose the placeholder on how GPS works, as it's going to be a + while before I tackle that, if ever. + +commit a79225c215f17fa5218ddd9db4fc3f5c563a9f74 +Merge: 84cd5d4 853b711 +Author: Anthony Towns +Date: Wed Nov 24 11:55:14 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 853b7112e34212040c4cb7289f9cfdb2f3ea9f90 +Author: Bdale Garbee +Date: Tue Nov 23 18:53:18 2010 -0700 + + merge Keith's AltosUI documention into "the big book" + +commit 84cd5d42d8b5659463544fe2a400758b56478609 +Author: Anthony Towns +Date: Wed Nov 24 02:13:32 2010 +1000 + + altosui: sitemap uses rocket gps if no pad gps + +commit c7119c21baa9d4ca681975b8613ade6593f65577 +Author: Anthony Towns +Date: Wed Nov 24 02:11:36 2010 +1000 + + altosui: don't switch away from user selected tab + +commit ae55a107f12546dc65f04618c7abc17beb920d73 +Merge: d1005f6 737f2fd +Author: Anthony Towns +Date: Wed Nov 24 01:53:46 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 737f2fdd012202f453120ece117ae5e859b32082 +Author: Keith Packard +Date: Mon Nov 22 22:26:19 2010 -0800 + + doc: Add internal documentation for AltOS + + Signed-off-by: Keith Packard + +commit 5523e7d55ecc8d310e495fa4f5115f7483c42d65 +Author: Bdale Garbee +Date: Mon Nov 22 21:07:10 2010 -0700 + + add a rudimentary --help for command line use + +commit d1005f68376d695039c314b8d7a68bbf9acbca4f +Merge: 9a83e0d 22c0978 +Author: Anthony Towns +Date: Tue Nov 23 10:14:55 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 22c09781af1df4b38562b577e9926c23e4a397f2 +Merge: b27327a a79606a +Author: Keith Packard +Date: Mon Nov 22 16:02:22 2010 -0800 + + Merge remote branch 'origin/buttonbox' into buttonbox + +commit b27327a05d249eaf969b67d2a8d12fc6a93841f0 +Author: Keith Packard +Date: Mon Nov 22 15:56:04 2010 -0800 + + altos: assume igniter worked. + + Many igniters don't go open when fired, so there's no way + to know if they worked. Assume they did as a failed igniter is + unlikely to do anything when fired again anyways. + + Signed-off-by: Keith Packard + +commit 68323cbb222f1f33198a42abaa0550af22f75a93 +Author: Keith Packard +Date: Mon Nov 22 15:53:27 2010 -0800 + + altosui: Close serial port when debug link fails + + If the debug connection isn't working, close down the serial port when + reporting the failure. + + Signed-off-by: Keith Packard + +commit 9a83e0dc79f7a7467c7814d58daa2a2b89e50972 +Merge: 902735f a79606a +Author: Anthony Towns +Date: Tue Nov 23 08:07:04 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit a79606a6507fc01a74910f7959e84c4e9a730714 +Author: Bob Finch +Date: Mon Nov 22 12:24:42 2010 -0700 + + Added PKGBUILDs for deps into contribs + +commit 377ee7e90ecd028f984cd1abce96b2efc3b5b977 +Author: Keith Packard +Date: Sun Nov 21 14:03:17 2010 -0800 + + altos: Add on/off modes to 'C' command + + This lets the user turn the radio on/off and then invoke other commands. + + Signed-off-by: Keith Packard + +commit 902735ffbfdd97672d52b09f17cdcd619193fd05 +Author: Anthony Towns +Date: Mon Nov 22 05:29:26 2010 +1000 + + altosui: keep sitemap more centred on rocket + +commit b85df38b5611e45cb9296df07b720badf74ac26e +Author: Anthony Towns +Date: Mon Nov 22 05:22:17 2010 +1000 + + altosui: improve sitemap scrolling behaviour + +commit 4a9ded5b39ed08e13abc2cddba8b712f62b983f2 +Author: Anthony Towns +Date: Sun Nov 21 17:39:50 2010 +1000 + + AltosSiteMap: ensure buffer around active tile + +commit ec47bc93a487614714a752cb30ec9fe3d8f72929 +Merge: 0393830 e7954c8 +Author: Anthony Towns +Date: Sun Nov 21 16:08:37 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit e7954c820763f80e993f9f822e837725cf36af84 +Author: Keith Packard +Date: Sat Nov 20 22:03:26 2010 -0800 + + altosui: When fixing eeprom gps time information, make GPS data valid + + Eeprom files may be missing the GPS time (due to a firmware bug). Working + around this involves finding the next valid GPS time and using that to + create a fake GPS time entry. However, that next GPS time may not + be locked or may have few sats as it is from the boost stage of the + flight. Fix this by simply forcing the fake time packet to have + 4 sats and be locked. + + Signed-off-by: Keith Packard + +commit 0393830f85da5efc96bbdf0d9769b66019c34b33 +Author: Anthony Towns +Date: Sun Nov 21 15:13:35 2010 +1000 + + AltosSiteMap: limit nr of tiles to 200x200 + +commit a08b2a6363c194195db92029743f6612676373ce +Author: Anthony Towns +Date: Sun Nov 21 15:03:21 2010 +1000 + + AltosSiteMap: never accept 0,0 as lat/long + +commit 84e570d8a8a52e0d358582135ec1b3a12be94c26 +Author: Anthony Towns +Date: Sun Nov 21 14:45:10 2010 +1000 + + AltosSiteMap: refactor tile collection + +commit 71e487344395a8efc9cd279aad92f601ff4c6d3d +Author: Anthony Towns +Date: Sun Nov 21 14:05:00 2010 +1000 + + AltosSiteMap: thread safe tile addition + +commit c040bcd06679484175542208fb564d0271a7fc1b +Author: Anthony Towns +Date: Sun Nov 21 13:19:36 2010 +1000 + + AltosSiteMap: try to get new tile construction right + +commit c3994dd82d489289ebc99ff9c5fa88f560c023ac +Author: Anthony Towns +Date: Sun Nov 21 13:07:11 2010 +1000 + + AltosSiteMap: extend map if rocket goes far away + +commit 835b903727a2eabda8d9659cc46e53301f92897c +Merge: 440a0f3 8789135 +Author: Anthony Towns +Date: Sun Nov 21 11:15:02 2010 +1000 + + Merge branch 'sitemap' into buttonbox + + Conflicts: + ao-tools/altosui/AltosSiteMap.java + +commit 878913551a1e4e3c8f2b39fa4aeb234880735a1c +Author: Anthony Towns +Date: Sun Nov 21 10:55:22 2010 +1000 + + AltosSiteMap: explain tile size better + +commit 440a0f3f5130eb0c8e614691892be8c94e7fd3c3 +Author: Keith Packard +Date: Sat Nov 20 16:55:12 2010 -0800 + + altosui: Set site map flight path lines to 6 pixels anti-aliased. + + Much more visible over the map. + + Signed-off-by: Keith Packard + +commit 2a7dc3ba36bac81640a9498e0d0caf1470b57c19 +Merge: e5b1ada ece2c86 +Author: Anthony Towns +Date: Sun Nov 21 10:45:15 2010 +1000 + + Merge branch 'buttonbox' into sitemap + + Conflicts: + ao-tools/altosui/AltosFlightUI.java + +commit 8df185cd95cfecbed8272dd1275d077c5b45535b +Merge: ece2c86 1e71264 +Author: Keith Packard +Date: Sat Nov 20 16:35:48 2010 -0800 + + Merge remote branch 'aj/sitemap' into buttonbox + + Conflicts: + ao-tools/altosui/AltosFlightUI.java + + Signed-off-by: Keith Packard + +commit e5b1adae9b23b98a6321986f5cd67c9d3166b87f +Author: Anthony Towns +Date: Sun Nov 21 10:34:39 2010 +1000 + + AltosSiteMap: better gps check, lower zoom + +commit ece2c86e2641b2cd613791293526c492b1606aa1 +Author: Keith Packard +Date: Sat Nov 20 16:19:42 2010 -0800 + + altosui: Rewrite info table to mix with scroll pane well. Fix startup size + + Using a single table for the info table means that the scroll pane + automatically picks up the table headers and shows them above the + scrollable view. + + This patch also fixes the application size at startup so that no + scrollbar is required in the info table, and the window is < 800x600. + + Signed-off-by: Keith Packard + +commit 1e712647dd6df1e77650db705f3ac32a3c8f6907 +Author: Anthony Towns +Date: Sun Nov 21 08:58:44 2010 +1000 + + altosui: reindent + +commit a59a204e188e40ec8848a0dc63d6de710cee3039 +Merge: 8263630 37f0201 +Author: Anthony Towns +Date: Sun Nov 21 08:56:13 2010 +1000 + + Merge branch 'buttonbox' into sitemap + +commit 82636305021c41d676f5f0f11378724fe0de0079 +Author: Anthony Towns +Date: Sun Nov 21 08:44:13 2010 +1000 + + AltosSiteMap: be more polite about preferred size + +commit 37f0201d724693528f37ac7d275f68f90cf94da0 +Author: Keith Packard +Date: Sat Nov 20 14:31:23 2010 -0800 + + altosui: change descent tab formatting to four columns + + This places labels to the left of each field. For igniter voltages, + it uses three columns for the labels. + + Signed-off-by: Keith Packard + +commit 66ebd954d9c9a44a8db0ee713c682e39306fabd8 +Author: Anthony Towns +Date: Sun Nov 21 08:28:24 2010 +1000 + + Add GrabNDrag.java + +commit 72f5e05f9f0055f2cef8b840812f090556c94338 +Author: Anthony Towns +Date: Sun Nov 21 08:18:39 2010 +1000 + + AltosSiteMap: major refactoring + +commit b47517d4c2e49f6f7b9954d2c85f96397fe1103e +Author: Keith Packard +Date: Sat Nov 20 14:06:37 2010 -0800 + + altosui: re-indent + +commit 6f8bc2ad20b715343e0510563ab0f14787ef3e07 +Author: Anthony Towns +Date: Sun Nov 21 01:34:52 2010 +1000 + + AltosDescent: switch elev from height to range + +commit 89f44c5587ea4f927d5e398b6af919df0d6561c3 +Author: Anthony Towns +Date: Sun Nov 21 01:27:01 2010 +1000 + + AltosAscent/Descent: tidy up layout + +commit 51e403145d28ac913e36d205077a613845596be2 +Author: Anthony Towns +Date: Sun Nov 21 00:17:51 2010 +1000 + + AltosSiteMapTile: draw boost circle as well as landed + +commit 25ffe1cc7823895886b4777f310b4bda1c80133b +Author: Anthony Towns +Date: Sun Nov 21 00:07:16 2010 +1000 + + AltosSiteMap: automatic fetching of map data + +commit 20f714bbe3137de8fb7491b39985021fd1774930 +Author: Anthony Towns +Date: Sat Nov 20 22:49:51 2010 +1000 + + AltosSiteMapTile: seperate map and drawing layers + +commit 58f8d069ce9488e2987b8e92caa69fe68cda7569 +Author: Anthony Towns +Date: Sat Nov 20 21:06:37 2010 +1000 + + AltosSiteMap: add autoscroll and grabndrag scroll + +commit 74cab8503b51ba6fb05a4d12a031c749e870b0ef +Merge: 0ecf033 9a99cab +Author: Anthony Towns +Date: Sat Nov 20 18:20:45 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 0ecf033110084f1a8be98282d7029dc14f70dab5 +Merge: 081fbd5 71c41ea +Author: Anthony Towns +Date: Sat Nov 20 18:14:30 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit 9a99cabc1c34c657fc95246192ba6d330f5f22d3 +Author: Keith Packard +Date: Sat Nov 20 00:13:58 2010 -0800 + + altosui: Fix channel changing in flight UI to actually work + + Replacing the menu with a combo box required reworking the way events + are delivered from that widget back to the channel changing + function. Just delete the old magic and use the JComboBox action + listener directly. + + Signed-off-by: Keith Packard + +commit 71c41eadd12c3ece5fffce7669e4991778046d4e +Author: Keith Packard +Date: Sat Nov 20 00:09:03 2010 -0800 + + altosui: Initialize display thread state in constructor instead of run + + Some state will get set before run is called, initializing it there + can be too late. + + Signed-off-by: Keith Packard + +commit 081fbd5715f9d3d81d98e149fb95d40447c07a79 +Merge: 90b9bc4 7920ed5 +Author: Anthony Towns +Date: Sat Nov 20 17:40:49 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + + Conflicts: + ao-tools/altosui/AltosFlightUI.java + +commit 7920ed5c34b088f45ce4213b061ddd1ffe22cee8 +Author: Keith Packard +Date: Fri Nov 19 23:18:51 2010 -0800 + + altosui: calling thread.interrupt with null thread doesn't work well + + This was a left-over from debugging the previous patch. + + Signed-off-by: Keith Packard + +commit 8c8dc3794c7b5fa5a5b43b1c461d6c8bb3ab425d +Author: Keith Packard +Date: Fri Nov 19 23:09:15 2010 -0800 + + altosui: When switching log files, don't terminate log thread + + The log thread automatically switches output files when the incoming + telemetry changes. Don't use 'close' for that as 'close' terminates + the log thread as well as closing the file. Create a new + 'close_log_file' function which just closes the file. + + Signed-off-by: Keith Packard + +commit 594e80572821f1848db062d0cff18ca8bf0d90ce +Author: Keith Packard +Date: Fri Nov 19 22:44:48 2010 -0800 + + altosui: switch channel selector to combo box. Shorten displayed device names + + A combo box displays the current value, which is quite nice to + have. Add a 'toShortString' for AltosDevice so that the window frames + and error messages don't have extra spaces generated by the + altos_device toString method. + + Signed-off-by: Keith Packard + +commit fa07afc73bc5eccff8464a2def05ad600da33c97 +Author: Bdale Garbee +Date: Fri Nov 19 23:33:42 2010 -0700 + + update turnon scripts to use stashed copies of stable release firmware + +commit 9ffc2eb53a47e435f39b02896b0e43ae5f47f450 +Author: Keith Packard +Date: Fri Nov 19 18:25:48 2010 -0800 + + altosui: Use timeouts to recover from broken packet links. + + This puts timeouts every place the system reads from the packet link + and aborts the in-progress operation if it takes more than a second to + get a response. + + Also mixed in here are persistent igniter status displays for the + ejection testing UI. + + Signed-off-by: Keith Packard + +commit 68078eab3c07d8dc83302747cf6f3dcb1797c6ce +Author: Keith Packard +Date: Fri Nov 19 20:44:29 2010 +0800 + + doc: Document the 'Flash Image' operation. + + Signed-off-by: Keith Packard + +commit b4bdda65488e8ef27d2889cb6cc8eda3c5d50e0a +Author: Keith Packard +Date: Fri Nov 19 20:29:14 2010 +0800 + + doc: git ignore generated doc files + + Signed-off-by: Keith Packard + +commit f0542085de2139ef562af068ec05fa73f47c73b1 +Author: Keith Packard +Date: Fri Nov 19 20:26:49 2010 +0800 + + doc: Add preliminary altosui documentation + + Also, update the Makefile to allow for further documents to be added + without a lot of custom rules. + + Signed-off-by: Keith Packard + +commit 0e7a10f71803d60f8b34c5a91efd220449442769 +Author: Keith Packard +Date: Fri Nov 19 17:16:03 2010 +0800 + + altosui: Clean up global AltosUI configuration settings dialog + + This dialog had a mish-mash of styles and was confusing. + Now it's got a label for each line, and suitable setters for + each element + + Signed-off-by: Keith Packard + +commit 8f72f08839346fb225238420324f0edcd070e531 +Author: Keith Packard +Date: Fri Nov 19 17:14:17 2010 +0800 + + altosui: Unify datafile selection to AltosDataChooser + + Instead of having several separate intefaces, use a single dialog for + selecting data files for graph/export/replay. + + Signed-off-by: Keith Packard + +commit 24ffcf86c43290ce0f70fb4ee0984b3debdb8a5f +Author: Keith Packard +Date: Fri Nov 19 15:41:30 2010 +0800 + + altosui: Add igniter ground testing code + + Not yet hooked up, but the UI is finished. + + Signed-off-by: Keith Packard + +commit 90b9bc4475011bead7117ed72fa5efa0f77b2813 +Author: Anthony Towns +Date: Fri Nov 19 13:30:00 2010 +1000 + + AltosSiteMapTile: adjust scale to 1 nmi per tile + +commit fa45336062523838ba8abb08427cdc4d9c7de7a8 +Author: Anthony Towns +Date: Fri Nov 19 13:17:29 2010 +1000 + + AltosSiteMapTile: adjust centering calculation + +commit fda93afcd8aa4133b0e5f008b824d072e338d0ed +Author: Anthony Towns +Date: Fri Nov 19 13:02:05 2010 +1000 + + AltosSiteMapTile: autoscale to about 2 nmi per tile + +commit 483346a03c94b200692f5e6d59f3feee4dcf2ace +Author: Anthony Towns +Date: Fri Nov 19 12:09:46 2010 +1000 + + altosui: tile site maps + +commit 939be6793238a275b7682ecc376fed14379cf044 +Merge: e68fe94 1a4b6e9 +Author: Anthony Towns +Date: Thu Nov 18 05:54:06 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + + Conflicts: + ao-tools/altosui/AltosFlightUI.java + +commit 1a4b6e96f823035b113f01d1bdfd61afc1f33e25 +Author: Keith Packard +Date: Tue Nov 16 22:46:29 2010 +0800 + + altosui: Add igniter status to ascent and descent tabs + + Monitor igniters during all phases of the flight. + + Signed-off-by: Keith Packard + +commit d0eb41619544ead6d9dab3a8d024a12936c9cdd0 +Author: Keith Packard +Date: Tue Nov 16 22:20:00 2010 +0800 + + altosui: Cleanup flight UI layout + + Use common constants for fonts and insets + Shrink fonts so that the window is < 600 pixels tall. + + Signed-off-by: Keith Packard + +commit fcca333cda64be35f0c9fb0109eef1be3709dddd +Author: Keith Packard +Date: Tue Nov 16 21:49:59 2010 +0800 + + altosui: Add callsign configuration in AltosUI configuration dialog + + This callsign is used during packet communication. + + Signed-off-by: Keith Packard + +commit d1dbe3b69e6f95ef8ecd4cf959863b922ab47c66 +Author: Bdale Garbee +Date: Mon Nov 15 11:08:00 2010 -0700 + + add a paragraph about forcing TM back to idle mode if an accel cal goes badly + +commit 39e371561469d8e5059638ffa4e7075f391de268 +Author: Keith Packard +Date: Mon Nov 15 23:14:51 2010 +0800 + + altosui: add reboot button to telemetrum configuration UI + + This lets you reconfigure and reboot telemetrum, including over the + radio link. + + Signed-off-by: Keith Packard + +commit 257e97137325f5dbbd6aa034f20fd6937b67df90 +Author: Keith Packard +Date: Mon Nov 15 22:38:35 2010 +0800 + + altosui: eliminate menu bar, moving elements to buttons. + + This adds a new 'configure AltosUI' dialog to set the log directory + and voice preferences. + + Signed-off-by: Keith Packard + +commit 524644d8d8ce3f8a5a914ecfc7e2a8d474d89095 +Author: Keith Packard +Date: Mon Nov 15 22:04:44 2010 +0800 + + altosui: oops, missed a file in the previous commit + + AltosSerialInUseException.java just defines a new exception, thanks to + java for making this live in a separate file. + + Signed-off-by: Keith Packard + +commit 511903704f7e1b22e88dd3e3cc35fd3c0583820e +Author: Keith Packard +Date: Sun Nov 14 03:26:57 2010 -0800 + + altosui: With --replay option, exit when replay window is closed + + Otherwise, the application hangs around forever. + + Signed-off-by: Keith Packard + +commit 11c95f687b1f68d35fa1a0af2c4e7982b8bb226a +Author: Keith Packard +Date: Sat Nov 13 17:09:51 2010 -0800 + + altosui: Replace flight status table with labels, fix resize. + + There's no reason to use a table for the flight status data, + replace that with a selection of widgets instead. + + Also, set all of the grid bag constraints for the various flight + status displays so that resize does something sensible. + + Adds a scrollbar to the table display so that it can shrink. + + Signed-off-by: Keith Packard + +commit dcfa56498d1b65a213b8aba9cbd6c4806532383c +Author: Keith Packard +Date: Sat Nov 13 16:07:04 2010 -0800 + + altosui: Open serial device at 'new' time. Prohibit duplicate opens. + + With the per-serial UI, there's never a reason to create a serial + device without opening it right away. This eliminates the bug caused + by not opening the serial device for telemetry reception. + + Serial devices can now be opened only once; this eliminates errors + when trying to reflash or configure devices while receiving telemetry. + + Signed-off-by: Keith Packard + +commit 8463ffcaca6bcd31e645aba71c171f548dce96d8 +Author: Keith Packard +Date: Sat Nov 13 15:19:14 2010 -0800 + + altosui: Eliminate unncessary import altosui lines + + Java appears to automatically import every module from the current + package. + + Signed-off-by: Keith Packard + +commit 566c6486c8815ae241e0b116a93b1a0ff4783831 +Author: Bdale Garbee +Date: Sat Nov 13 12:19:12 2010 -0700 + + continuing to work on the docs + +commit e68fe9454352087889c560d95797922493117acb +Author: Anthony Towns +Date: Sun Nov 14 00:59:01 2010 +1000 + + AltosSiteMap: add targeting circles around landing site + +commit 1e7e02987276847274493312202d22222c953149 +Author: Anthony Towns +Date: Sun Nov 14 00:57:45 2010 +1000 + + AltosTelemetryReader: actually open serial port + +commit 9c32b93ef5fb43558fb0179ea1b047e35b7ed6e8 +Merge: 991541f a6f30fa +Author: Anthony Towns +Date: Sun Nov 14 00:29:11 2010 +1000 + + Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox + +commit a6f30fae906bd87dff192c5fd4d10df283f99930 +Author: Keith Packard +Date: Fri Nov 12 17:02:22 2010 -0800 + + altosui: Add RF calibration to TeleMetrum config dialog + + I think that's the last user-settable value. + + Signed-off-by: Keith Packard + +commit 1bdc6166f3bc5ce3f8e55acb1484923781412e21 +Merge: f111871 5c6a533 +Author: Bdale Garbee +Date: Fri Nov 12 17:32:43 2010 -0700 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit f1118717780a81f9257d2eed7828b66538deb8a8 +Author: Bdale Garbee +Date: Fri Nov 12 17:32:21 2010 -0700 + + fold in content from Keith's email on the re-flashing subject + +commit 7def9dd0d0a4ce9cf7c65de573100e664f278717 +Author: Bdale Garbee +Date: Fri Nov 12 10:58:54 2010 -0700 + + first cut at instructions on how to re-flash TM and TD devices based on email + reply to a user who asked + +commit 991541f57f065f429c6ec425efd6ac731280b2c1 +Author: Anthony Towns +Date: Fri Nov 12 23:42:42 2010 +1000 + + better error behaviour if no map + +commit 1bcfa22de7821984149db10cb79913efed36b41e +Author: Anthony Towns +Date: Fri Nov 12 23:29:40 2010 +1000 + + pull up maps for arbitrary locations + +commit beb6c881ec006241c7d2820c64e5381131d41180 +Author: Anthony Towns +Date: Fri Nov 12 03:24:26 2010 +1000 + + make infotable scrollable, revert its fontsize to 14 + +commit 0327c1da01a3f6ede01f05c1d775651a57fd0c68 +Author: Anthony Towns +Date: Fri Nov 12 02:08:58 2010 +1000 + + tabs -> spaces + +commit 81e7b43ecad666e2e2310c7c94184f888bc86585 +Author: Anthony Towns +Date: Fri Nov 12 02:07:41 2010 +1000 + + add site map tab, at least for QRS launches + +commit 5394548fa5c7bdbfcc01e8aa19e93e1cf6345e2a +Merge: 891e629 75f7698 +Author: Keith Packard +Date: Wed Nov 10 22:11:21 2010 -0800 + + Merge remote branch 'aj/buttonbox' into buttonbox + +commit 75f7698b99a661ed17a91748a99699fa6761772a +Author: Anthony Towns +Date: Thu Nov 11 16:06:32 2010 +1000 + + add compass bearing during descent + +commit cc0a730de093c49be2a921101d27622b6f592e92 +Author: Anthony Towns +Date: Thu Nov 11 15:57:52 2010 +1000 + + add compass bearing to voice output + +commit 317ec72a34906faad88c6924e634617b074e71db +Author: Anthony Towns +Date: Thu Nov 11 15:52:01 2010 +1000 + + use grayled.png for off + +commit 8503943e3613f8670b128012b12ff14fb54321d7 +Author: Anthony Towns +Date: Thu Nov 11 15:45:43 2010 +1000 + + reduce font size for FlightInfoTable + +commit 3ffaa5d1c00b28be20fd4a26deb7bd41d953e92a +Author: Anthony Towns +Date: Thu Nov 11 15:43:05 2010 +1000 + + read preferences for --replay + +commit 1f3e091efdfb2fe6f06a066cac60f5d267b94856 +Author: Anthony Towns +Date: Thu Nov 11 15:40:37 2010 +1000 + + add --replay command line argument + +commit b16b873723ee3e5097e6725c59ce191119439ad7 +Author: Anthony Towns +Date: Thu Nov 11 15:38:27 2010 +1000 + + use value_font for values + +commit 891e629f6ba20654b614f3ca7211a0f1c92670cb +Author: Keith Packard +Date: Wed Nov 10 16:28:19 2010 -0800 + + altos: Use grey leds when unlit - easier to see + +commit 5c6a5335a057be0219450b4b9889c647d8d4a012 +Author: Bob Finch +Date: Mon Nov 1 14:36:41 2010 -0600 + + Updated PKGBUILD-git.altos + + Signed-off-by: Keith Packard + +commit b0d31910da592e2f67c47c8fc3e15ce8135d5094 +Author: Keith Packard +Date: Tue Nov 9 23:34:32 2010 -0800 + + altosui: Add ascent, descent and landed tabs + + This completes the set of tabs for in-flight status information. + + Signed-off-by: Keith Packard + +commit 22d00785188a880700cd372528189a7a15278da9 +Author: Keith Packard +Date: Tue Nov 9 14:40:58 2010 -0800 + + altosui: Add tab UI with 'pad' mode. + + This creates a multi-tab interface for flight monitoring + and includes a special tab for 'pad' mode. + + Signed-off-by: Keith Packard + +commit eb77e806ded99532dc7eaa39c1893f075b028af6 +Author: Keith Packard +Date: Tue Nov 9 10:21:34 2010 -0800 + + altosui: Create abstract interface for flight data display + + This allows the implementation of the flight data display to occur in + the flight UI instead of the display thread. + + Signed-off-by: Keith Packard + +commit a0a92c605e238277c9881545a7226e53b5dbc295 +Author: Keith Packard +Date: Mon Nov 8 22:17:26 2010 -0800 + + altosui: Fix more calls to AltosPreferences.channel() + + Oops. Two more. + + Signed-off-by: Keith Packard + +commit 94f4a50d6430cc8280cbdaa9f39d3cb858d0e077 +Author: Keith Packard +Date: Mon Nov 8 22:10:46 2010 -0800 + + altosui: Fix channel setting at serial open time + + Was using the previous non-device-specific preferences API. + + Signed-off-by: Keith Packard + +commit 6b17d276271faa8a420a1c8f6be17faaa0c7043c +Author: Keith Packard +Date: Mon Nov 8 22:07:04 2010 -0800 + + altosui: Create buttons for main actions + + Signed-off-by: Keith Packard + +commit 16916be51d746b1e1057b3219e5bec8f8814259e +Author: Keith Packard +Date: Fri Nov 5 23:44:47 2010 -0700 + + altosui: Split out flight monitoring to separate window + + This creates a per-TD (or replay) window to contain the flight + monitoring information, allowing multiple monitors. + + This also adds per-TD preferences for monitoring channel. + + Signed-off-by: Keith Packard + +commit ca931b1c484bd6b64617370e81b16e169fdae1c2 +Author: Bdale Garbee +Date: Wed Oct 6 17:47:44 2010 -0600 + + update changelogs for Debian build + commit 811ced628d586134224c1b501b40ce9eb435fc7c Author: Keith Packard Date: Wed Oct 6 16:42:27 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 604f7dc7..4e9a9966 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,207 @@ +altos (0.7.1+168+gcb08bc2) unstable; urgency=low + + [ Keith Packard ] + * altosui: Split out flight monitoring to separate window + * altosui: Create buttons for main actions + * altosui: Fix channel setting at serial open time + * altosui: Fix more calls to AltosPreferences.channel() + * altosui: Create abstract interface for flight data display + * altosui: Add tab UI with 'pad' mode. + * altosui: Add ascent, descent and landed tabs + + [ Bob Finch ] + * Updated PKGBUILD-git.altos + + [ Keith Packard ] + * altos: Use grey leds when unlit - easier to see + + [ Anthony Towns ] + * use value_font for values + * add --replay command line argument + * read preferences for --replay + * reduce font size for FlightInfoTable + * use grayled.png for off + * add compass bearing to voice output + * add compass bearing during descent + * add site map tab, at least for QRS launches + * tabs -> spaces + * make infotable scrollable, revert its fontsize to 14 + * pull up maps for arbitrary locations + * better error behaviour if no map + + [ Bdale Garbee ] + * first cut at instructions on how to re-flash TM and TD devices based + on email + * fold in content from Keith's email on the re-flashing subject + + [ Keith Packard ] + * altosui: Add RF calibration to TeleMetrum config dialog + + [ Anthony Towns ] + * AltosTelemetryReader: actually open serial port + * AltosSiteMap: add targeting circles around landing site + + [ Bdale Garbee ] + * continuing to work on the docs + + [ Keith Packard ] + * altosui: Eliminate unncessary import altosui lines + * altosui: Open serial device at 'new' time. Prohibit duplicate opens. + * altosui: Replace flight status table with labels, fix resize. + * altosui: With --replay option, exit when replay window is closed + * altosui: oops, missed a file in the previous commit + * altosui: eliminate menu bar, moving elements to buttons. + * altosui: add reboot button to telemetrum configuration UI + + [ Bdale Garbee ] + * add a paragraph about forcing TM back to idle mode if an accel cal + goes badly + + [ Keith Packard ] + * altosui: Add callsign configuration in AltosUI configuration dialog + * altosui: Cleanup flight UI layout + * altosui: Add igniter status to ascent and descent tabs + + [ Anthony Towns ] + * altosui: tile site maps + * AltosSiteMapTile: autoscale to about 2 nmi per tile + * AltosSiteMapTile: adjust centering calculation + * AltosSiteMapTile: adjust scale to 1 nmi per tile + + [ Keith Packard ] + * altosui: Add igniter ground testing code + * altosui: Unify datafile selection to AltosDataChooser + * altosui: Clean up global AltosUI configuration settings dialog + * doc: Add preliminary altosui documentation + * doc: git ignore generated doc files + * doc: Document the 'Flash Image' operation. + * altosui: Use timeouts to recover from broken packet links. + + [ Bdale Garbee ] + * update turnon scripts to use stashed copies of stable release + firmware + + [ Keith Packard ] + * altosui: switch channel selector to combo box. Shorten displayed + device names + * altosui: When switching log files, don't terminate log thread + * altosui: calling thread.interrupt with null thread doesn't work well + * altosui: Initialize display thread state in constructor instead of + run + * altosui: Fix channel changing in flight UI to actually work + + [ Anthony Towns ] + * AltosSiteMap: add autoscroll and grabndrag scroll + * AltosSiteMapTile: seperate map and drawing layers + * AltosSiteMap: automatic fetching of map data + * AltosSiteMapTile: draw boost circle as well as landed + * AltosAscent/Descent: tidy up layout + * AltosDescent: switch elev from height to range + + [ Keith Packard ] + * altosui: re-indent + + [ Anthony Towns ] + * AltosSiteMap: major refactoring + * Add GrabNDrag.java + + [ Keith Packard ] + * altosui: change descent tab formatting to four columns + + [ Anthony Towns ] + * AltosSiteMap: be more polite about preferred size + * altosui: reindent + + [ Keith Packard ] + * altosui: Rewrite info table to mix with scroll pane well. Fix + startup size + + [ Anthony Towns ] + * AltosSiteMap: better gps check, lower zoom + + [ Keith Packard ] + * altosui: Set site map flight path lines to 6 pixels anti-aliased. + + [ Anthony Towns ] + * AltosSiteMap: explain tile size better + * AltosSiteMap: extend map if rocket goes far away + * AltosSiteMap: try to get new tile construction right + * AltosSiteMap: thread safe tile addition + * AltosSiteMap: refactor tile collection + * AltosSiteMap: never accept 0,0 as lat/long + * AltosSiteMap: limit nr of tiles to 200x200 + + [ Keith Packard ] + * altosui: When fixing eeprom gps time information, make GPS data + valid + + [ Anthony Towns ] + * AltosSiteMap: ensure buffer around active tile + * altosui: improve sitemap scrolling behaviour + * altosui: keep sitemap more centred on rocket + + [ Keith Packard ] + * altos: Add on/off modes to 'C' command + + [ Bob Finch ] + * Added PKGBUILDs for deps into contribs + + [ Keith Packard ] + * altosui: Close serial port when debug link fails + * altos: assume igniter worked. + + [ Bdale Garbee ] + * add a rudimentary --help for command line use + + [ Keith Packard ] + * doc: Add internal documentation for AltOS + + [ Anthony Towns ] + * altosui: don't switch away from user selected tab + * altosui: sitemap uses rocket gps if no pad gps + + [ Bdale Garbee ] + * merge Keith's AltosUI documention into "the big book" + * lose the placeholder on how GPS works, as it's going to be a + + [ Keith Packard ] + * altos: remove unused variable from ao_igniter + * altos: Don't abort radio transmissions with ao_radio_abort + * altos: Make radio test command careful with the radio mutex. + * altosui: Make AltosSerial.flush_input keep reading while non-empty + * altosui: New AltosSerial.set_radio function sets channel/call + * altosui: Disable radio configation over packet link. + * altosui: Let people fire igniters that don't read as 'ready' + * altosui: Make sure packet mode is turned off when the connection + fails + + [ Anthony Towns ] + * docs: Document altosui "Graph Data" button + + [ Keith Packard ] + * Move altosui to the top level, placing libaltos inside it. + + [ Anthony Towns ] + * doc: Document altosui "Site Map" tab + + [ Keith Packard ] + * Missing change to top level Makefile to build altosui + + [ Bdale Garbee ] + * fix missing section close in Site Map content + * tweak rev history + * manually fold in documentation work from the master branch + + [ Keith Packard ] + * doc: Reformat altos to use sections for each function + * doc: Add more authors, fix URL formatting, note that AltosUI + actually exists + * doc: Rename telemetrum-doc as altusmetrum + + [ Bdale Garbee ] + + -- Bdale Garbee Thu, 25 Nov 2010 01:10:18 -0700 + altos (0.7.1+36+g811ced6) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From cd414e2c04ce5ecbc75f19325a6d6f82cd489fb3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Nov 2010 16:30:29 -0800 Subject: altosui: Correct windows hardware IDs for nsis installer file Need real hardware IDs (encoded USB ids) to get windows to auto-install the driver? Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index d7c4b32a..7cf51212 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -31,7 +31,10 @@ UninstPage instfiles ; And the stuff to install Section "Install Driver" InstDriver - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum" + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000A + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000B + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000C + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D Pop $0 DetailPrint "InitDriverSetup: $0" @@ -103,7 +106,10 @@ Section "Uninstall" RMDir "$INSTDIR" ; Remove devices - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} "Altus Metrum" + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000A + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000B + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000C + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D InstDrv::DeleteOemInfFiles /NOUNLOAD InstDrv::RemoveAllDevices -- cgit v1.2.3 From 641c5373724d34c3adfcf42420a528d6bba736b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Nov 2010 22:35:18 -0800 Subject: windows: try harder to get windows install to work Add devIDs to .nsi file. Fix install section name mapping from the hot-plug info. Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 21 ++++++++++++++++++++- telemetrum.inf | 20 ++++++++++---------- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 7cf51212..0e985967 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -31,15 +31,34 @@ UninstPage instfiles ; And the stuff to install Section "Install Driver" InstDriver + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000A + Pop $0 + DetailPrint "InitDriverSetup: $0" + InstDrv::DeleteOemInfFiles /NOUNLOAD + InstDrv::CreateDevice /NOUNLOAD + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000B + Pop $0 + DetailPrint "InitDriverSetup: $0" + InstDrv::DeleteOemInfFiles /NOUNLOAD + InstDrv::CreateDevice /NOUNLOAD + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000C - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D Pop $0 DetailPrint "InitDriverSetup: $0" + InstDrv::DeleteOemInfFiles /NOUNLOAD + InstDrv::CreateDevice /NOUNLOAD + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D + Pop $0 + DetailPrint "InitDriverSetup: $0" InstDrv::DeleteOemInfFiles /NOUNLOAD InstDrv::CreateDevice /NOUNLOAD + + SetOutPath $WINDIR\Inf + File "../telemetrum.inf" + SetOutPath $TEMP File "../telemetrum.inf" InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf" diff --git a/telemetrum.inf b/telemetrum.inf index 0d1a5534..54f8f020 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -11,6 +11,12 @@ DriverVer = 08/05/2010,7.1.0.0 [Manufacturer] %Mfg% = Models, NTx86, NTamd64, NTia64 +[Models] +%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A +%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B +%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C +%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D + [Models.NTx86] %AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A %TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B @@ -33,10 +39,7 @@ DriverVer = 08/05/2010,7.1.0.0 DefaultDestDir=12 [ControlFlags] -ExcludeFromSelect=USB\VID_FFFE&PID_000A -ExcludeFromSelect=USB\VID_FFFE&PID_000B -ExcludeFromSelect=USB\VID_FFFE&PID_000C -ExcludeFromSelect=USB\VID_FFFE&PID_000D +ExcludeFromSelect=* [Strings] Mfg = "altusmetrum.org" @@ -45,32 +48,29 @@ TeleMetrum = "TeleMetrum" TeleDongle = "TeleDongle" TeleTerra = "TeleTerra" - ;---------------------------------------------------------------------------- ; Installation sections ;---------------------------------------------------------------------------- -[TELEMETRUM.NT] +[TELEMETRUM] include=mdmcpq.inf CopyFiles=FakeModemCopyFileSection AddReg = All, mfglt, Modem.AddReg, VerboseResultCodes, Uninstall.AddReg -[TELEMETRUM.NT.HW] +[TELEMETRUM.HW] Include=mdmcpq.inf AddReg=LowerFilterAddReg -[TELEMETRUM.NT.Services] +[TELEMETRUM.Services] Include=mdmcpq.inf AddService=usbser, 0x00000000, LowerFilter_Service_Inst - ;---------------------------------------------------------------------------- ; AddReg sections ;---------------------------------------------------------------------------- [Modem.AddReg] HKR,, Properties, 1, C0,01,00,00, 00,00,00,00, FF,00,00,00, 07,00,00,00, 0F,00,00,00, F7,0F,00,00, 00,84,03,00, C0,DA,00,00 - ;---------------------------------------------------------------------------- ; Common Registry Sections ; -- cgit v1.2.3 From 26369a92398f4ebe3fcd54ce34cebffae0cfdf07 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Nov 2010 22:39:31 -0800 Subject: windows: remove some non-existent .inf file section references The mfglt and VerboseResultCodes sections are not present in the .inf file, so remove refernces to them. Signed-off-by: Keith Packard --- telemetrum.inf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telemetrum.inf b/telemetrum.inf index 54f8f020..1f4c0144 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -55,7 +55,7 @@ TeleTerra = "TeleTerra" [TELEMETRUM] include=mdmcpq.inf CopyFiles=FakeModemCopyFileSection -AddReg = All, mfglt, Modem.AddReg, VerboseResultCodes, Uninstall.AddReg +AddReg = All, Modem.AddReg, Uninstall.AddReg [TELEMETRUM.HW] Include=mdmcpq.inf -- cgit v1.2.3 From 42c2394ccc1a1ee6dc134ed963a4f79acf031d0b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Nov 2010 23:04:50 -0800 Subject: windows: more .inf file hacking Add a LayoutFile reference Add the FakeModemCopyFileSection Copy AltosMetrum.Install section to AltusMetrum.Install.NT section. I don't know what this might do; existing files seem inconsistent. Signed-off-by: Keith Packard --- telemetrum.inf | 117 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/telemetrum.inf b/telemetrum.inf index 1f4c0144..765bbbb0 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -4,89 +4,96 @@ [Version] Signature = "$Windows NT$" Class = Modem -ClassGUID ={4D36E96D-E325-11CE-BFC1-08002BE10318} +ClassGUID = {4D36E96D-E325-11CE-BFC1-08002BE10318} +LayoutFile = layout.inf Provider = %Mfg% DriverVer = 08/05/2010,7.1.0.0 +[DestinationDirs] +FakeModemCopyFileSection = 12 +DefaultDestDir = 12 + +[ControlFlags] +ExcludeFromSelect = * + [Manufacturer] %Mfg% = Models, NTx86, NTamd64, NTia64 [Models] -%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B -%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C -%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D [Models.NTx86] -%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B -%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C -%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D [Models.NTamd64] -%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B -%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C -%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D [Models.NTia64] -%AltusMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000A -%TeleMetrum% = TELEMETRUM, USB\VID_FFFE&PID_000B -%TeleDongle% = TELEMETRUM, USB\VID_FFFE&PID_000C -%TeleTerra% = TELEMETRUM, USB\VID_FFFE&PID_000D - -[DestinationDirs] -DefaultDestDir=12 - -[ControlFlags] -ExcludeFromSelect=* +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D [Strings] -Mfg = "altusmetrum.org" -AltusMetrum = "AltusMetrum" -TeleMetrum = "TeleMetrum" -TeleDongle = "TeleDongle" -TeleTerra = "TeleTerra" +Mfg = "altusmetrum.org" +AltusMetrum = "AltusMetrum" +TeleMetrum = "TeleMetrum" +TeleDongle = "TeleDongle" +TeleTerra = "TeleTerra" ;---------------------------------------------------------------------------- ; Installation sections ;---------------------------------------------------------------------------- -[TELEMETRUM] -include=mdmcpq.inf -CopyFiles=FakeModemCopyFileSection -AddReg = All, Modem.AddReg, Uninstall.AddReg +[AltusMetrum.Install] +include = mdmcpq.inf +CopyFiles = FakeModemCopyFileSection +AddReg = All.AddReg, Modem.AddReg, Uninstall.AddReg + +[AltusMetrum.Install.Services] +include = mdmcpq.inf +AddService = usbser, 0x00000000, LowerFilter_Service_Inst -[TELEMETRUM.HW] -Include=mdmcpq.inf -AddReg=LowerFilterAddReg +[AltusMetrum.Install.HW] +include = mdmcpq.inf +AddReg = LowerFilterAddReg -[TELEMETRUM.Services] -Include=mdmcpq.inf -AddService=usbser, 0x00000000, LowerFilter_Service_Inst +[AltusMetrum.Install.NT] +include = mdmcpq.inf +CopyFiles = FakeModemCopyFileSection +AddReg = All.AddReg, Modem.AddReg, Uninstall.AddReg + +[AltusMetrum.Install.NT.Services] +include = mdmcpq.inf +AddService = usbser, 0x00000000, LowerFilter_Service_Inst + +[AltusMetrum.Install.NT.HW] +include = mdmcpq.inf +AddReg = LowerFilterAddReg ;---------------------------------------------------------------------------- ; AddReg sections ;---------------------------------------------------------------------------- + +[All.AddReg] +HKR,,FriendlyDriver,, Unimodem.vxd +HKR,,DevLoader,, *vcomm +HKR,,ConfigDialog,, modemui.dll +HKR,,EnumPropPages,, "modemui.dll,EnumPropPages" +HKR,,PortSubClass, 1, 02 +HKR,,DeviceType, 1, 01 + [Modem.AddReg] HKR,, Properties, 1, C0,01,00,00, 00,00,00,00, FF,00,00,00, 07,00,00,00, 0F,00,00,00, F7,0F,00,00, 00,84,03,00, C0,DA,00,00 -;---------------------------------------------------------------------------- -; Common Registry Sections -; -; The [All] section is installed for all modems. -; -;---------------------------------------------------------------------------- -[All] -HKR,,FriendlyDriver,,Unimodem.vxd -HKR,,DevLoader,,*vcomm -HKR,,PortSubClass,1,02 -HKR,,ConfigDialog,,modemui.dll -HKR,,EnumPropPages,,"modemui.dll,EnumPropPages" -HKR,,DeviceType,1,01 -HKR,,OCM2KXP,1,01 -HKR,, DCB, 1, 1c,00,00,00, 00,C2,01,00, 15,20,00,00, 00,00, 0a,00, 0a,00, 08, 00, 00, 11, 13, 00, 00, 00 - [Uninstall.AddReg] HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TeleMetrum%,DisplayName,,"%TeleMetrum%" - -- cgit v1.2.3 From b09d3e11c32abd07f8e11b483ac4b57148f4f2d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Nov 2010 23:08:41 -0800 Subject: windows: Bump .inf file version --- telemetrum.inf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/telemetrum.inf b/telemetrum.inf index 765bbbb0..f7a729b8 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -7,7 +7,7 @@ Class = Modem ClassGUID = {4D36E96D-E325-11CE-BFC1-08002BE10318} LayoutFile = layout.inf Provider = %Mfg% -DriverVer = 08/05/2010,7.1.0.0 +DriverVer = 08/05/2010,7.1.1.0 [DestinationDirs] FakeModemCopyFileSection = 12 -- cgit v1.2.3 From 5e23bcc2d2ad33a839fedd2158213098a05cd9ae Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:21:31 -0700 Subject: declaring 0.8 released --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 22af00ab..781f8776 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.7.1) +AC_INIT([altos], 0.8) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 2615289265b6f8fa08827be794b4eee569fc6333 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:23:17 -0700 Subject: update changelogs for Debian build --- ChangeLog | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 14 ++++++++++++ 2 files changed, 79 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3c6fd159..0ab31594 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,68 @@ +commit 5e23bcc2d2ad33a839fedd2158213098a05cd9ae +Author: Bdale Garbee +Date: Sun Nov 28 18:21:31 2010 -0700 + + declaring 0.8 released + +commit b09d3e11c32abd07f8e11b483ac4b57148f4f2d8 +Author: Keith Packard +Date: Sat Nov 27 23:08:41 2010 -0800 + + windows: Bump .inf file version + +commit 42c2394ccc1a1ee6dc134ed963a4f79acf031d0b +Author: Keith Packard +Date: Sat Nov 27 23:04:50 2010 -0800 + + windows: more .inf file hacking + + Add a LayoutFile reference + Add the FakeModemCopyFileSection + + Copy AltosMetrum.Install section to AltusMetrum.Install.NT section. I + don't know what this might do; existing files seem inconsistent. + + Signed-off-by: Keith Packard + +commit 26369a92398f4ebe3fcd54ce34cebffae0cfdf07 +Author: Keith Packard +Date: Sat Nov 27 22:39:31 2010 -0800 + + windows: remove some non-existent .inf file section references + + The mfglt and VerboseResultCodes sections are not present in the .inf + file, so remove refernces to them. + + Signed-off-by: Keith Packard + +commit 641c5373724d34c3adfcf42420a528d6bba736b9 +Author: Keith Packard +Date: Sat Nov 27 22:35:18 2010 -0800 + + windows: try harder to get windows install to work + + Add devIDs to .nsi file. Fix install section name mapping from the + hot-plug info. + + Signed-off-by: Keith Packard + +commit cd414e2c04ce5ecbc75f19325a6d6f82cd489fb3 +Author: Keith Packard +Date: Sat Nov 27 16:30:29 2010 -0800 + + altosui: Correct windows hardware IDs for nsis installer file + + Need real hardware IDs (encoded USB ids) to get windows to + auto-install the driver? + + Signed-off-by: Keith Packard + +commit f834b22905db87557f729f942607dc363b013694 +Author: Bdale Garbee +Date: Thu Nov 25 22:31:33 2010 -0700 + + update changelogs for Debian build + commit da3b39d6b1b5ba48686c2a4add4b5448fd5711af Author: Bdale Garbee Date: Thu Nov 25 22:29:01 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 4e9a9966..8f823b15 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +altos (0.8) unstable; urgency=low + + [ Keith Packard ] + * altosui: Correct windows hardware IDs for nsis installer file + * windows: try harder to get windows install to work + * windows: remove some non-existent .inf file section references + * windows: more .inf file hacking + * windows: Bump .inf file version + + [ Bdale Garbee ] + * declaring 0.8 released + + -- Bdale Garbee Sun, 28 Nov 2010 18:22:27 -0700 + altos (0.7.1+168+gcb08bc2) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 263cf6c4fc5c1a240d719bb0ceb33393864fb3d6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:24:00 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0ab31594..d8b8fda9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 2615289265b6f8fa08827be794b4eee569fc6333 +Author: Bdale Garbee +Date: Sun Nov 28 18:23:17 2010 -0700 + + update changelogs for Debian build + commit 5e23bcc2d2ad33a839fedd2158213098a05cd9ae Author: Bdale Garbee Date: Sun Nov 28 18:21:31 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 8f823b15..d0843604 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.8+1+g2615289) unstable; urgency=low + + * UNRELEASED + + -- Bdale Garbee Sun, 28 Nov 2010 18:23:49 -0700 + altos (0.8) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From a375942979dbcd8239d8c0addb10616e6048f6ea Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:31:26 -0700 Subject: rewind changelog to recover from stupid build failure --- debian/changelog | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/debian/changelog b/debian/changelog index d0843604..4e9a9966 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,23 +1,3 @@ -altos (0.8+1+g2615289) unstable; urgency=low - - * UNRELEASED - - -- Bdale Garbee Sun, 28 Nov 2010 18:23:49 -0700 - -altos (0.8) unstable; urgency=low - - [ Keith Packard ] - * altosui: Correct windows hardware IDs for nsis installer file - * windows: try harder to get windows install to work - * windows: remove some non-existent .inf file section references - * windows: more .inf file hacking - * windows: Bump .inf file version - - [ Bdale Garbee ] - * declaring 0.8 released - - -- Bdale Garbee Sun, 28 Nov 2010 18:22:27 -0700 - altos (0.7.1+168+gcb08bc2) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 6f3c72462af86a7d9dec20f4c813a524a5be9fbb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:32:17 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 17 +++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/ChangeLog b/ChangeLog index d8b8fda9..f19255fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit a375942979dbcd8239d8c0addb10616e6048f6ea +Author: Bdale Garbee +Date: Sun Nov 28 18:31:26 2010 -0700 + + rewind changelog to recover from stupid build failure + +commit 263cf6c4fc5c1a240d719bb0ceb33393864fb3d6 +Author: Bdale Garbee +Date: Sun Nov 28 18:24:00 2010 -0700 + + update changelogs for Debian build + commit 2615289265b6f8fa08827be794b4eee569fc6333 Author: Bdale Garbee Date: Sun Nov 28 18:23:17 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 4e9a9966..05574ed0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +altos (0.8) unstable; urgency=low + + [ Keith Packard ] + * altosui: Correct windows hardware IDs for nsis installer file + * windows: try harder to get windows install to work + * windows: remove some non-existent .inf file section references + * windows: more .inf file hacking + * windows: Bump .inf file version + + [ Bdale Garbee ] + * declaring 0.8 released + * update changelogs for Debian build + * update changelogs for Debian build + * rewind changelog to recover from stupid build failure + + -- Bdale Garbee Sun, 28 Nov 2010 18:32:12 -0700 + altos (0.7.1+168+gcb08bc2) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 13cea7a96821165a10a8b2433af1da7508882b0a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 18:48:31 -0700 Subject: moved doc dir in web content to AltOS tree --- doc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 14f9bee2..a64ae560 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -23,8 +23,8 @@ PDFSTYLE= all: $(HTML) $(PDF) publish: $(DOC) - cp $(DOC)altusmetrum.html home/bdale/web/altusmetrum/TeleMetrum/doc/ - (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/TeleMetrum/doc/* ; git push) + cp $(DOC)altusmetrum.html /home/bdale/web/altusmetrum/AltOS/doc/ + (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/AltOS/doc/* ; git push) clean: rm -f *.html *.pdf *.fo -- cgit v1.2.3 From f39698bbc12afdfadfac56c90030e16db93cf4fc Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 19:46:03 -0700 Subject: fix publish target in doc/Makefile --- doc/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index a64ae560..ef3ef6d1 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -23,8 +23,12 @@ PDFSTYLE= all: $(HTML) $(PDF) publish: $(DOC) - cp $(DOC)altusmetrum.html /home/bdale/web/altusmetrum/AltOS/doc/ - (cd /home/bdale/web/altusmetrum ; echo "update docs" | git commit -F - /home/bdale/web/altusmetrum/AltOS/doc/* ; git push) + cp $(DOC) /home/bdale/web/altusmetrum/AltOS/doc/ + (cd /home/bdale/web/altusmetrum ; \ + git add /home/bdale/web/altusmetrum/AltOS/doc/* ; \ + echo "update docs" | \ + git commit -F - /home/bdale/web/altusmetrum/AltOS/doc/* ; \ + git push) clean: rm -f *.html *.pdf *.fo -- cgit v1.2.3 From e840b6594b8a939f148fa7231e1b06a280d94074 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Nov 2010 22:42:43 -0700 Subject: fix section layering --- doc/altusmetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 8d4230f8..d90f331c 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1605,6 +1605,7 @@ NAR #88757, TRA #12200 other authorization to legally operate the radio transmitters that are part of our products.
+
In the Rocket @@ -1728,7 +1729,6 @@ NAR #88757, TRA #12200 feel free to dive in and help! Or let us know what you'd like to see that we aren't already working on, and maybe we'll get excited about it too... -
-- cgit v1.2.3 From 61a924099800494b589cbbb87c65b552ccbd8394 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Nov 2010 14:40:27 -0700 Subject: fix an Altos vs Altus typo in the docs --- doc/altusmetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index d90f331c..7a80ba13 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -973,7 +973,7 @@ NAR #88757, TRA #12200 Packet Command Mode Controlling TeleMetrum Over The Radio Link - One of the unique features of the Altos Metrum environment is + One of the unique features of the Altus Metrum environment is the ability to create a two way command link between TeleDongle and TeleMetrum using the digital radio transceivers built into each device. This allows you to interact with TeleMetrum from -- cgit v1.2.3 From 3e2220a180f95971d222a597d2057ca328c27356 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Nov 2010 21:29:14 -0700 Subject: adding Bdale's release process document to the source tree --- debian/Releasing | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 debian/Releasing diff --git a/debian/Releasing b/debian/Releasing new file mode 100644 index 00000000..efa6809d --- /dev/null +++ b/debian/Releasing @@ -0,0 +1,28 @@ +These are Bdale's notes on how to do a release. + + update the version in configure.ac and commit + + git tag -a + + git-buildpackage --git-ignore-new + + use --git-ignore-new so trash in checked-out tree doesn't + cause the build to fail! + + at this point, we have Debian packages + + make distclean + + ./autogen.sh --with-fat-dir=/home/bdale/web/altusmetrum/AltOS/releases + make fat + + this pushes packages for each platform to web site + + - go edit ~/web/altusmetrum/AltOS/releases/.mdwn to include + release date and explicit ref to dir contents so the AltOS page + shows versioned links, commit and push + + (cd doc ; make publish) + + this pushes fresh documents to the web site + -- cgit v1.2.3 From b727156ef0a7fb6e442ca28be27eb344a213ecf8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Nov 2010 20:17:35 -0800 Subject: windows: Add jfreechart.jar and jcommon.jar to windows install image These are necessary for the Graph Data button to do anything useful. Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 0e985967..9bbfb885 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -78,6 +78,8 @@ Section "AltosUI Application" File "cmu_us_kal.jar" File "en_us.jar" File "freetts.jar" + File "jfreechart.jar" + File "jcommon.jar" File "*.dll" -- cgit v1.2.3 From f0a4deee23984a8f779917bbeaf74a66a0abf592 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Nov 2010 20:34:27 -0800 Subject: Move "Releasing" to top level This file documents the AltOS release process for all systems. Signed-off-by: Keith Packard --- Releasing | 27 +++++++++++++++++++++++++++ debian/Releasing | 28 ---------------------------- 2 files changed, 27 insertions(+), 28 deletions(-) create mode 100644 Releasing delete mode 100644 debian/Releasing diff --git a/Releasing b/Releasing new file mode 100644 index 00000000..a7263c61 --- /dev/null +++ b/Releasing @@ -0,0 +1,27 @@ +These are Bdale's notes on how to do a release. + + update the version in configure.ac and commit + + git tag -a + + git-buildpackage --git-ignore-new + + use --git-ignore-new so trash in checked-out tree doesn't + cause the build to fail! + + at this point, we have Debian packages + + make distclean + + ./autogen.sh --with-fat-dir=/home/bdale/web/altusmetrum/AltOS/releases + make fat + + this pushes packages for each platform to web site + + - go edit ~/web/altusmetrum/AltOS/releases/.mdwn to include + release date and explicit ref to dir contents so the AltOS page + shows versioned links, commit and push + + (cd doc ; make publish) + + this pushes fresh documents to the web site diff --git a/debian/Releasing b/debian/Releasing deleted file mode 100644 index efa6809d..00000000 --- a/debian/Releasing +++ /dev/null @@ -1,28 +0,0 @@ -These are Bdale's notes on how to do a release. - - update the version in configure.ac and commit - - git tag -a - - git-buildpackage --git-ignore-new - - use --git-ignore-new so trash in checked-out tree doesn't - cause the build to fail! - - at this point, we have Debian packages - - make distclean - - ./autogen.sh --with-fat-dir=/home/bdale/web/altusmetrum/AltOS/releases - make fat - - this pushes packages for each platform to web site - - - go edit ~/web/altusmetrum/AltOS/releases/.mdwn to include - release date and explicit ref to dir contents so the AltOS page - shows versioned links, commit and push - - (cd doc ; make publish) - - this pushes fresh documents to the web site - -- cgit v1.2.3 From 5f3f11e11dff9b9f4d1dde279c0d474de0de12a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Nov 2010 20:41:49 -0800 Subject: Add minimal release testing plan to Releasing Signed-off-by: Keith Packard --- Releasing | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Releasing b/Releasing index a7263c61..3307b535 100644 --- a/Releasing +++ b/Releasing @@ -25,3 +25,20 @@ These are Bdale's notes on how to do a release. (cd doc ; make publish) this pushes fresh documents to the web site + +Testing before a release + + To verify that a build works, the following need to be checked + on each platform: + + 1) Install package + + 2) Connect TM *and* TD devices. Verify that you can Monitor + Flight from the TD and Configure Telemetrum from the TM. + + 3) Replay Flight, using your favorite .eeprom file. Check + each tab, especially the 'Site Map' tab. Make sure the + sound works. + + 4) Graph Data. Graph a favorite .eeprom file. Make sure you + can zoom in on some region of the graph. -- cgit v1.2.3 From 11b3f9ff715017a2dec02003275885334f22c009 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Nov 2010 21:46:02 -0700 Subject: releasing 0.8.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 781f8776..ecaeab63 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.8) +AC_INIT([altos], 0.8.1) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 3696b30a8d1eb351353d84b5f7af8eeff55c468b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 29 Nov 2010 21:47:13 -0700 Subject: update changelogs for Debian build --- ChangeLog | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 19 +++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/ChangeLog b/ChangeLog index f19255fc..0771552c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,73 @@ +commit 11b3f9ff715017a2dec02003275885334f22c009 +Author: Bdale Garbee +Date: Mon Nov 29 21:46:02 2010 -0700 + + releasing 0.8.1 + +commit 5f3f11e11dff9b9f4d1dde279c0d474de0de12a5 +Author: Keith Packard +Date: Mon Nov 29 20:41:49 2010 -0800 + + Add minimal release testing plan to Releasing + + Signed-off-by: Keith Packard + +commit f0a4deee23984a8f779917bbeaf74a66a0abf592 +Author: Keith Packard +Date: Mon Nov 29 20:34:27 2010 -0800 + + Move "Releasing" to top level + + This file documents the AltOS release process for all systems. + + Signed-off-by: Keith Packard + +commit b727156ef0a7fb6e442ca28be27eb344a213ecf8 +Author: Keith Packard +Date: Mon Nov 29 20:17:35 2010 -0800 + + windows: Add jfreechart.jar and jcommon.jar to windows install image + + These are necessary for the Graph Data button to do anything useful. + + Signed-off-by: Keith Packard + +commit 3e2220a180f95971d222a597d2057ca328c27356 +Author: Bdale Garbee +Date: Mon Nov 29 21:29:14 2010 -0700 + + adding Bdale's release process document to the source tree + +commit 61a924099800494b589cbbb87c65b552ccbd8394 +Author: Bdale Garbee +Date: Mon Nov 29 14:40:27 2010 -0700 + + fix an Altos vs Altus typo in the docs + +commit e840b6594b8a939f148fa7231e1b06a280d94074 +Author: Bdale Garbee +Date: Sun Nov 28 22:42:43 2010 -0700 + + fix section layering + +commit f39698bbc12afdfadfac56c90030e16db93cf4fc +Author: Bdale Garbee +Date: Sun Nov 28 19:46:03 2010 -0700 + + fix publish target in doc/Makefile + +commit 13cea7a96821165a10a8b2433af1da7508882b0a +Author: Bdale Garbee +Date: Sun Nov 28 18:48:31 2010 -0700 + + moved doc dir in web content to AltOS tree + +commit 6f3c72462af86a7d9dec20f4c813a524a5be9fbb +Author: Bdale Garbee +Date: Sun Nov 28 18:32:17 2010 -0700 + + update changelogs for Debian build + commit a375942979dbcd8239d8c0addb10616e6048f6ea Author: Bdale Garbee Date: Sun Nov 28 18:31:26 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 05574ed0..13c9b1bc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +altos (0.8.1) unstable; urgency=low + + [ Bdale Garbee ] + * moved doc dir in web content to AltOS tree + * fix publish target in doc/Makefile + * fix section layering + * fix an Altos vs Altus typo in the docs + * adding Bdale's release process document to the source tree + + [ Keith Packard ] + * windows: Add jfreechart.jar and jcommon.jar to windows install image + * Move "Releasing" to top level + * Add minimal release testing plan to Releasing + + [ Bdale Garbee ] + * releasing 0.8.1 + + -- Bdale Garbee Mon, 29 Nov 2010 21:46:54 -0700 + altos (0.8) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From ea7130e953622884afc348265f5a4c58f9876823 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 1 Dec 2010 00:00:58 -0700 Subject: modify Debian package build to deliver one copy of background.png for the themes and symlink it into place for gdm and slim --- debian/altos.install | 3 +-- debian/dirs | 2 +- debian/rules | 4 ++++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/debian/altos.install b/debian/altos.install index 8be48ca3..c23e1628 100644 --- a/debian/altos.install +++ b/debian/altos.install @@ -3,10 +3,9 @@ debian/altos.list etc/apt/sources.list.d debian/altusmetrum.xpm usr/share/pixmaps src/*.ihx usr/share/altos src/*.map usr/share/altos -themes/background.png usr/share/slim/themes/altusmetrum +themes/background.png usr/share/altos/themes themes/slim/panel.png usr/share/slim/themes/altusmetrum themes/slim/slim.theme usr/share/slim/themes/altusmetrum -themes/background.png usr/share/gdm/themes/altusmetrum themes/gdm/altusmetrum.xml /usr/share/gdm/themes/altusmetrum themes/gdm/GdmGreeterTheme.desktop /usr/share/gdm/themes/altusmetrum themes/gdm/screenshot.png /usr/share/gdm/themes/altusmetrum diff --git a/debian/dirs b/debian/dirs index 7b4dffb8..1cffaa67 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,7 +1,7 @@ etc/apt/sources.list.d usr/bin usr/lib/altos -usr/share/altos +usr/share/altos/themes usr/share/applications usr/share/gdm/themes/altusmetrum usr/share/java diff --git a/debian/rules b/debian/rules index 53a8a340..e0f1f72c 100755 --- a/debian/rules +++ b/debian/rules @@ -53,6 +53,10 @@ binary-arch: install dh_installdocs dh_installexamples dh_install + ln -s /usr/share/altos/themes/background.png \ + /usr/share/gdm/themes/altusmetrum/background.png + ln -s /usr/share/altos/themes/background.png \ + /usr/share/slim/themes/altusmetrum/background.png dh_installmenu # dh_installdebconf # dh_installlogrotate -- cgit v1.2.3 From f95220b6f0cc74928e0e7d7c7e1f443eafc32a02 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 1 Dec 2010 00:03:23 -0700 Subject: update changelogs for Debian build --- ChangeLog | 13 +++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0771552c..5339335c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +commit ea7130e953622884afc348265f5a4c58f9876823 +Author: Bdale Garbee +Date: Wed Dec 1 00:00:58 2010 -0700 + + modify Debian package build to deliver one copy of background.png for + the themes and symlink it into place for gdm and slim + +commit 3696b30a8d1eb351353d84b5f7af8eeff55c468b +Author: Bdale Garbee +Date: Mon Nov 29 21:47:13 2010 -0700 + + update changelogs for Debian build + commit 11b3f9ff715017a2dec02003275885334f22c009 Author: Bdale Garbee Date: Mon Nov 29 21:46:02 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 13c9b1bc..eed330fe 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.8.1+2+gea7130e) unstable; urgency=low + + * modify Debian package build to deliver one copy of background.png + for + + -- Bdale Garbee Wed, 01 Dec 2010 00:03:14 -0700 + altos (0.8.1) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From ea95c060f8bd959cefc60dd6d411151f3c91384e Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 1 Dec 2010 00:12:05 -0700 Subject: fix symlink paths in rules file --- debian/rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/rules b/debian/rules index e0f1f72c..83f3a53f 100755 --- a/debian/rules +++ b/debian/rules @@ -54,9 +54,9 @@ binary-arch: install dh_installexamples dh_install ln -s /usr/share/altos/themes/background.png \ - /usr/share/gdm/themes/altusmetrum/background.png + debian/altos/usr/share/gdm/themes/altusmetrum/background.png ln -s /usr/share/altos/themes/background.png \ - /usr/share/slim/themes/altusmetrum/background.png + debian/altos/usr/share/slim/themes/altusmetrum/background.png dh_installmenu # dh_installdebconf # dh_installlogrotate -- cgit v1.2.3 From b8d2eb5509096fd5bd04598b1312077659109620 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 1 Dec 2010 00:15:17 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 5339335c..c177e93d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit ea95c060f8bd959cefc60dd6d411151f3c91384e +Author: Bdale Garbee +Date: Wed Dec 1 00:12:05 2010 -0700 + + fix symlink paths in rules file + +commit f95220b6f0cc74928e0e7d7c7e1f443eafc32a02 +Author: Bdale Garbee +Date: Wed Dec 1 00:03:23 2010 -0700 + + update changelogs for Debian build + commit ea7130e953622884afc348265f5a4c58f9876823 Author: Bdale Garbee Date: Wed Dec 1 00:00:58 2010 -0700 diff --git a/debian/changelog b/debian/changelog index eed330fe..7b1be3a9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.8.1+4+gea95c06) unstable; urgency=low + + * fix symlink paths in rules file + + -- Bdale Garbee Wed, 01 Dec 2010 00:14:24 -0700 + altos (0.8.1+2+gea7130e) unstable; urgency=low * modify Debian package build to deliver one copy of background.png -- cgit v1.2.3 From b62580855c5144f5bc7e0172289bce08814d9472 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Tue, 14 Dec 2010 03:40:18 +1000 Subject: altosui: move maps to subdir, fix E/W mismatch --- altosui/AltosPreferences.java | 13 +++++++++++++ altosui/AltosSiteMap.java | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index e2a3df3b..c6ae6cbd 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -52,6 +52,9 @@ class AltosPreferences { /* Log directory */ static File logdir; + /* Map directory -- hangs of logdir */ + static File mapdir; + /* Channel (map serial to channel) */ static Hashtable channels; @@ -79,6 +82,9 @@ class AltosPreferences { if (!logdir.exists()) logdir.mkdirs(); } + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); channels = new Hashtable(); @@ -106,6 +112,9 @@ class AltosPreferences { public static void set_logdir(File new_logdir) { logdir = new_logdir; + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); synchronized (preferences) { preferences.put(logdirPreference, logdir.getPath()); flush_preferences(); @@ -151,6 +160,10 @@ class AltosPreferences { return logdir; } + public static File mapdir() { + return mapdir; + } + public static void set_channel(int serial, int new_channel) { channels.put(serial, new_channel); synchronized (preferences) { diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index d4a4cbf4..d6bd6d1f 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -211,10 +211,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { private File MapFile(double lat, double lng) { char chlat = lat < 0 ? 'S' : 'N'; - char chlng = lng < 0 ? 'E' : 'W'; + char chlng = lng < 0 ? 'W' : 'E'; if (lat < 0) lat = -lat; if (lng < 0) lng = -lng; - return new File(AltosPreferences.logdir(), + return new File(AltosPreferences.mapdir(), String.format("map-%c%.6f,%c%.6f-%d.png", chlat, lat, chlng, lng, zoom)); } -- cgit v1.2.3 From 07213dc34fa20470a4b36a327a83d75b0f010ebb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Nov 2010 16:14:15 -0800 Subject: altos: clean up radio abort paths. Share radio code. Instead of aborting the DMA and radio operation and expecting that to be handled reasonably by the radio receiving task, rewrite things so that the abort function just wakes the receiving task while that terminates the DMA and cleans up the radio. This eliminates all kinds of nasty bugs dealing with radio abort smashing the radio registers at the wrong time, or interrupting a radio transmission. Signed-off-by: Keith Packard --- src/ao.h | 31 ++++++++-------- src/ao_config.c | 2 +- src/ao_dma.c | 4 +-- src/ao_monitor.c | 6 ++-- src/ao_packet.c | 98 ++++++++++++++++++++++---------------------------- src/ao_packet_master.c | 5 +-- src/ao_packet_slave.c | 7 ++-- src/ao_radio.c | 68 +++++++++++++++++++++-------------- src/ao_telemetry.c | 2 +- 9 files changed, 109 insertions(+), 114 deletions(-) diff --git a/src/ao.h b/src/ao.h index 5b174947..58659af5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -391,14 +391,10 @@ ao_cmd_init(void); * ao_dma.c */ -/* Allocate a DMA channel. the 'done' parameter will be set - * when the dma is finished or aborted and will be used to - * wakeup any waiters +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters */ -#define AO_DMA_DONE 1 -#define AO_DMA_ABORTED 2 - uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -838,6 +834,15 @@ struct ao_telemetry { struct ao_gps_tracking_data gps_tracking; }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ +struct ao_telemetry_recv { + struct ao_telemetry telemetry; + int8_t rssi; + uint8_t status; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -880,22 +885,16 @@ void ao_radio_set_rdf(void); void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; - -struct ao_radio_recv { - struct ao_telemetry telemetry; - int8_t rssi; - uint8_t status; -}; +ao_radio_send(__xdata void *data, uint8_t size) __reentrant; uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; void -ao_radio_rdf(int ms); +ao_radio_recv_abort(void); void -ao_radio_abort(void); +ao_radio_rdf(int ms); void ao_radio_rdf_abort(void); diff --git a/src/ao_config.c b/src/ao_config.c index 88b52dc0..fd33e2cc 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -141,7 +141,7 @@ ao_config_radio_channel_set(void) __reentrant ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_channel_show(); - ao_radio_abort(); + ao_radio_recv_abort(); } #if HAS_ADC diff --git a/src/ao_dma.c b/src/ao_dma.c index 946666ab..6052964a 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -107,8 +107,6 @@ ao_dma_abort(uint8_t id) uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; - *(ao_dma_done[id]) |= AO_DMA_ABORTED; - ao_wakeup(ao_dma_done[id]); } void @@ -124,7 +122,7 @@ ao_dma_isr(void) __interrupt 8 DMAIF = 0; /* Clear the completed ID */ DMAIRQ = ~mask; - *(ao_dma_done[id]) |= AO_DMA_DONE; + *(ao_dma_done[id]) = 1; ao_wakeup(ao_dma_done[id]); break; } diff --git a/src/ao_monitor.c b/src/ao_monitor.c index f019d3b4..1e7f5102 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -23,7 +23,7 @@ __pdata uint8_t ao_monitor_led; void ao_monitor(void) { - __xdata struct ao_radio_recv recv; + __xdata struct ao_telemetry_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; uint8_t state; int16_t rssi; @@ -31,7 +31,7 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (!ao_radio_recv(&recv)) + if (!ao_radio_recv(&recv, sizeof (recv))) continue; state = recv.telemetry.flight_state; @@ -85,7 +85,7 @@ ao_set_monitor(uint8_t monitoring) ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); if (!ao_monitoring) - ao_radio_abort(); + ao_radio_recv_abort(); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c index d52f2a68..9896149c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -33,8 +33,6 @@ void ao_packet_send(void) { ao_led_on(AO_LED_RED); - ao_radio_get(); - /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -43,22 +41,7 @@ ao_packet_send(void) ao_packet_tx_used = 0; ao_wakeup(&tx_data); } - ao_radio_done = 0; - ao_dma_set_transfer(ao_radio_dma, - &ao_tx_packet, - &RFDXADDR, - sizeof (struct ao_packet), - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_STX; - __critical while (!ao_radio_done) - ao_sleep(&ao_radio_done); - ao_radio_put(); + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); ao_led_off(AO_LED_RED); } @@ -70,51 +53,56 @@ ao_packet_recv(void) #ifdef AO_LED_GREEN ao_led_on(AO_LED_GREEN); #endif - ao_radio_get(); - ao_dma_set_transfer(ao_radio_dma, - &RFDXADDR, - &ao_rx_packet, - sizeof (struct ao_packet_recv), - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_SRX; - __critical while (!ao_radio_dma_done) - if (ao_sleep(&ao_radio_dma_done) != 0) - ao_radio_abort(); - dma_done = ao_radio_dma_done; - ao_radio_put(); + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif - if (dma_done & AO_DMA_DONE) { - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return AO_DMA_ABORTED; - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) { - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - ao_wakeup(&ao_stdin_ready); - } - } - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); } } - return dma_done; + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; } #ifndef PACKET_HAS_MASTER diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 641b49f4..3b23ad92 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -77,8 +77,6 @@ ao_packet_master_check_busy(void) void ao_packet_master(void) { - uint8_t status; - ao_config_get(); ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; @@ -92,8 +90,7 @@ ao_packet_master(void) ao_packet_master_busy(); ao_packet_master_check_busy(); ao_alarm(ao_packet_master_delay); - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { + if (ao_packet_recv()) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) continue; diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 9b78767f..3040d781 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,14 +20,11 @@ void ao_packet_slave(void) { - uint8_t status; - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { + if (ao_packet_recv()) { memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); ao_packet_send(); } @@ -47,7 +44,7 @@ ao_packet_slave_stop(void) { if (ao_packet_enable) { ao_packet_enable = 0; - ao_radio_abort(); + ao_radio_recv_abort(); while (ao_packet_task.wchan) { ao_wake_task(&ao_packet_task); ao_yield(); diff --git a/src/ao_radio.c b/src/ao_radio.c index cafa7010..362b73aa 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -272,6 +272,7 @@ static __code uint8_t packet_setup[] = { __xdata uint8_t ao_radio_dma; __xdata uint8_t ao_radio_dma_done; __xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_abort; __xdata uint8_t ao_radio_mutex; void @@ -279,7 +280,7 @@ ao_radio_general_isr(void) __interrupt 16 { S1CON &= ~0x03; if (RFIF & RFIF_IM_TIMEOUT) { - ao_dma_abort(ao_radio_dma); + ao_radio_recv_abort(); RFIF &= ~ RFIF_IM_TIMEOUT; } else if (RFIF & RFIF_IM_DONE) { ao_radio_done = 1; @@ -338,14 +339,14 @@ ao_radio_get(void) void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +ao_radio_send(__xdata void *packet, uint8_t size) __reentrant { ao_radio_get(); ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, - telemetry, + packet, &RFDXADDR, - sizeof (struct ao_telemetry), + size, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, @@ -360,13 +361,14 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant } uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant +ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant { + ao_radio_abort = 0; ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, - radio, - sizeof (struct ao_radio_recv), + packet, + size, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, @@ -375,13 +377,32 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_SRX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_dma_done && !ao_radio_abort) + ao_sleep(&ao_radio_dma_done); + + /* If recv was aborted, clean up by stopping the DMA engine + * and idling the radio + */ + if (!ao_radio_dma_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } ao_radio_put(); - return (ao_radio_dma_done & AO_DMA_DONE); + return ao_radio_dma_done; +} + +/* + * Wake up a task waiting to receive a radio packet + * and tell them to abort the transfer + */ + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_running; __xdata ao_radio_rdf_value = 0x55; void @@ -390,8 +411,9 @@ ao_radio_rdf(int ms) uint8_t i; uint8_t pkt_len; + ao_radio_abort = 0; ao_radio_get(); - ao_radio_rdf_running = 1; + ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; @@ -419,28 +441,22 @@ ao_radio_rdf(int ms) DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); - ao_radio_rdf_running = 0; - ao_radio_idle(); + __critical while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + if (!ao_radio_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; ao_radio_put(); } -void -ao_radio_abort(void) -{ - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); -} - void ao_radio_rdf_abort(void) { - if (ao_radio_rdf_running) - ao_radio_abort(); + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); } diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 88ac142c..277c3ce0 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -52,7 +52,7 @@ ao_telemetry(void) memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry); + ao_radio_send(&telemetry, sizeof (telemetry)); ao_delay(ao_telemetry_interval); if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) -- cgit v1.2.3 From 484b44e81b655f1ecb48256095382a56d2839bae Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Nov 2010 17:39:40 -0800 Subject: altos: eliminate ao_wake_task Waking up a task waiting on some random object is a bad idea. Fix the waiters to look for suitable signalling. Signed-off-by: Keith Packard --- src/ao.h | 4 ---- src/ao_packet.c | 2 +- src/ao_packet_master.c | 16 +++++++--------- src/ao_packet_slave.c | 7 ++++--- src/ao_radio.c | 7 ++++++- src/ao_task.c | 9 +-------- 6 files changed, 19 insertions(+), 26 deletions(-) diff --git a/src/ao.h b/src/ao.h index 58659af5..9682e42f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -69,10 +69,6 @@ ao_sleep(__xdata void *wchan); void ao_wakeup(__xdata void *wchan); -/* Wake up a specific task */ -void -ao_wake_task(__xdata struct ao_task *task); - /* set an alarm to go off in 'delay' ticks */ void ao_alarm(uint16_t delay); diff --git a/src/ao_packet.c b/src/ao_packet.c index 9896149c..f627e02b 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -117,7 +117,7 @@ ao_packet_flush(void) * then poke the master to send all queued data */ if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); + ao_wakeup(&ao_packet_master_sleeping); } #endif /* PACKET_HAS_MASTER */ diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 3b23ad92..0808bc80 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -21,16 +21,13 @@ static char ao_packet_getchar(void) __critical { char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) - { + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { if (!ao_packet_enable) break; if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); + ao_wakeup(&ao_packet_master_sleeping); ao_usb_flush(); ao_sleep(&ao_stdin_ready); - if (!ao_packet_enable) - break; } return c; } @@ -41,7 +38,7 @@ ao_packet_echo(void) __reentrant uint8_t c; while (ao_packet_enable) { c = ao_packet_getchar(); - if (ao_packet_enable) + if (c != AO_READ_AGAIN) ao_usb_putchar(c); } ao_exit(); @@ -97,7 +94,8 @@ ao_packet_master(void) if (ao_rx_packet.packet.len) ao_packet_master_busy(); ao_packet_master_sleeping = 1; - ao_delay(ao_packet_master_delay); + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); ao_packet_master_sleeping = 0; } } @@ -126,8 +124,8 @@ ao_packet_forward(void) __reentrant ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - if (ao_packet_echo_task.wchan) - ao_wake_task(&ao_packet_echo_task); + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); ao_delay(AO_MS_TO_TICKS(10)); } } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 3040d781..39d04bbb 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -44,12 +44,13 @@ ao_packet_slave_stop(void) { if (ao_packet_enable) { ao_packet_enable = 0; - ao_radio_recv_abort(); while (ao_packet_task.wchan) { - ao_wake_task(&ao_packet_task); - ao_yield(); + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); } + ao_radio_get(); ao_radio_set_telemetry(); + ao_radio_put(); } } diff --git a/src/ao_radio.c b/src/ao_radio.c index 362b73aa..7b7c5161 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -377,8 +377,13 @@ ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_SRX; + + /* Wait for DMA to be done, for the radio receive process to + * get aborted or for a receive timeout to fire + */ __critical while (!ao_radio_dma_done && !ao_radio_abort) - ao_sleep(&ao_radio_dma_done); + if (ao_sleep(&ao_radio_dma_done)) + break; /* If recv was aborted, clean up by stopping the DMA engine * and idling the radio diff --git a/src/ao_task.c b/src/ao_task.c index 72c9d7d6..35f34b49 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -204,12 +204,11 @@ ao_sleep(__xdata void *wchan) ao_cur_task->wchan = wchan; } ao_yield(); + ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; - ao_cur_task->alarm = 0; return 1; } - ao_cur_task->alarm = 0; return 0; } @@ -233,12 +232,6 @@ ao_alarm(uint16_t delay) ao_cur_task->alarm = 1; } -void -ao_wake_task(__xdata struct ao_task *task) -{ - task->wchan = NULL; -} - void ao_exit(void) __critical { -- cgit v1.2.3 From 4a42f9d5c20dcaf5fd7591ccf9e32c6130d9d538 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Nov 2010 00:22:14 -0800 Subject: windows: Add compatibility IDs to telemetrum.inf This will allow the .nsi file to reference just the compatibility ID instead of needing to have all of the USB IDs listed. Signed-off-by: Keith Packard --- telemetrum.inf | 65 ++++++++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/telemetrum.inf b/telemetrum.inf index f7a729b8..b4a84b97 100755 --- a/telemetrum.inf +++ b/telemetrum.inf @@ -5,68 +5,48 @@ Signature = "$Windows NT$" Class = Modem ClassGUID = {4D36E96D-E325-11CE-BFC1-08002BE10318} -LayoutFile = layout.inf Provider = %Mfg% DriverVer = 08/05/2010,7.1.1.0 +PnpLockDown = 0 +DriverPackageDisplayName = %DriverName% [DestinationDirs] FakeModemCopyFileSection = 12 DefaultDestDir = 12 [ControlFlags] -ExcludeFromSelect = * [Manufacturer] %Mfg% = Models, NTx86, NTamd64, NTia64 [Models] -%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A -%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B -%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C -%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A, AltusMetrumSerial +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B, AltusMetrumSerial +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C, AltusMetrumSerial +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D, AltusMetrumSerial [Models.NTx86] -%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A -%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B -%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C -%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A, AltusMetrumSerial +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B, AltusMetrumSerial +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C, AltusMetrumSerial +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D, AltusMetrumSerial [Models.NTamd64] -%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A -%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B -%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C -%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A, AltusMetrumSerial +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B, AltusMetrumSerial +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C, AltusMetrumSerial +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D, AltusMetrumSerial [Models.NTia64] -%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A -%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B -%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C -%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D - -[Strings] -Mfg = "altusmetrum.org" -AltusMetrum = "AltusMetrum" -TeleMetrum = "TeleMetrum" -TeleDongle = "TeleDongle" -TeleTerra = "TeleTerra" +%AltusMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000A, AltusMetrumSerial +%TeleMetrum% = AltusMetrum.Install, USB\VID_FFFE&PID_000B, AltusMetrumSerial +%TeleDongle% = AltusMetrum.Install, USB\VID_FFFE&PID_000C, AltusMetrumSerial +%TeleTerra% = AltusMetrum.Install, USB\VID_FFFE&PID_000D, AltusMetrumSerial ;---------------------------------------------------------------------------- ; Installation sections ;---------------------------------------------------------------------------- -[AltusMetrum.Install] -include = mdmcpq.inf -CopyFiles = FakeModemCopyFileSection -AddReg = All.AddReg, Modem.AddReg, Uninstall.AddReg - -[AltusMetrum.Install.Services] -include = mdmcpq.inf -AddService = usbser, 0x00000000, LowerFilter_Service_Inst - -[AltusMetrum.Install.HW] -include = mdmcpq.inf -AddReg = LowerFilterAddReg - [AltusMetrum.Install.NT] include = mdmcpq.inf CopyFiles = FakeModemCopyFileSection @@ -97,3 +77,12 @@ HKR,, Properties, 1, C0,01,00,00, 00,00,00,00, FF,00,00,00, 07,00,00,00, 0F,00,0 [Uninstall.AddReg] HKLM,Software\Microsoft\Windows\CurrentVersion\Uninstall\%TeleMetrum%,DisplayName,,"%TeleMetrum%" + +[Strings] +Mfg = "altusmetrum.org" +AltusMetrum = "AltusMetrum" +TeleMetrum = "TeleMetrum" +TeleDongle = "TeleDongle" +TeleTerra = "TeleTerra" +DriverName = "Altus Metrum Device Driver" + -- cgit v1.2.3 From 51c410c1c952e0e9bcf1b2c438813de63753be5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Nov 2010 00:24:54 -0800 Subject: windows: Update NSIS installer file to use compatibility IDs This allows the file to contain a single InitDriverSetup function, making things shorter and (I hope) clearer. --- altosui/altos-windows.nsi | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 9bbfb885..6f296f18 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -32,39 +32,22 @@ UninstPage instfiles Section "Install Driver" InstDriver - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000A + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial Pop $0 DetailPrint "InitDriverSetup: $0" InstDrv::DeleteOemInfFiles /NOUNLOAD InstDrv::CreateDevice /NOUNLOAD - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000B - Pop $0 - DetailPrint "InitDriverSetup: $0" - InstDrv::DeleteOemInfFiles /NOUNLOAD - InstDrv::CreateDevice /NOUNLOAD - - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000C - Pop $0 - DetailPrint "InitDriverSetup: $0" - InstDrv::DeleteOemInfFiles /NOUNLOAD - InstDrv::CreateDevice /NOUNLOAD - - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D - Pop $0 - DetailPrint "InitDriverSetup: $0" - InstDrv::DeleteOemInfFiles /NOUNLOAD - InstDrv::CreateDevice /NOUNLOAD - - SetOutPath $WINDIR\Inf - File "../telemetrum.inf" - SetOutPath $TEMP File "../telemetrum.inf" InstDrv::InstallDriver /NOUNLOAD "$TEMP\telemetrum.inf" SetOutPath $INSTDIR File "../telemetrum.inf" + + SetOutPath $WINDIR\Inf + File "../telemetrum.inf" + SectionEnd Section "AltosUI Application" @@ -127,10 +110,7 @@ Section "Uninstall" RMDir "$INSTDIR" ; Remove devices - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000A - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000B - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000C - InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} USB\VID_FFFE&PID_000D + InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial InstDrv::DeleteOemInfFiles /NOUNLOAD InstDrv::RemoveAllDevices -- cgit v1.2.3 From 9f7296b3feab872bf51fc369ade69cc1e7cf7a3f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Dec 2010 21:06:22 -0800 Subject: altos: Split out SPI driver. For TM with the companion connector, the SPI bus will be shared among multiple devices. Split out the existing SPI code into a common driver, with the SPI bus protected by a mutex. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 ++ src/ao.h | 13 +++ src/ao_ee.c | 133 ++-------------------------- src/ao_flash.c | 137 ++-------------------------- src/ao_pins.h | 22 +++++ src/ao_spi.c | 157 +++++++++++++++++++++++++++++++++ src/ao_telemetrum.c | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 1 + src/telemetrum-v1.0/Makefile.defs | 1 + 10 files changed, 217 insertions(+), 255 deletions(-) create mode 100644 src/ao_spi.c diff --git a/src/Makefile.proto b/src/Makefile.proto index b23eb257..c79638ac 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -71,6 +71,12 @@ TELE_DRIVER_SRC = \ ao_convert.c \ ao_serial.c +# +# Spi bus driver +# +SPI_DRIVER_SRC = \ + ao_spi.c + # # Debug dongle driver (only on TI) # diff --git a/src/ao.h b/src/ao.h index 9682e42f..69f4665b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -736,6 +736,19 @@ void ao_serial_init(void); #endif +/* + * ao_spi.c + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + /* * ao_gps.c */ diff --git a/src/ao_ee.c b/src/ao_ee.c index 26cfb7fd..36c8a100 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -25,15 +25,8 @@ #define EE_CS P1_2 #define EE_CS_INDEX 2 -__xdata uint8_t ao_ee_dma_in_done; -__xdata uint8_t ao_ee_dma_out_done; __xdata uint8_t ao_ee_mutex; -uint8_t ao_ee_dma_out_id; -uint8_t ao_ee_dma_in_id; - -static __xdata uint8_t ao_ee_const = 0xff; - #define ao_ee_delay() do { \ _asm nop _endasm; \ _asm nop _endasm; \ @@ -54,82 +47,6 @@ void ao_ee_cs_high(void) ao_ee_delay(); } -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -static void -ao_ee_send(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_ee_dma_in_id, - &U0DBUFXADDR, - &ao_ee_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_ee_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_ee_dma_in_id); - ao_dma_start(ao_ee_dma_out_id); - ao_dma_trigger(ao_ee_dma_out_id); - __critical while (!ao_ee_dma_in_done) - ao_sleep(&ao_ee_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -static void -ao_ee_recv(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_ee_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_ee_dma_out_id, - &ao_ee_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_ee_dma_in_id); - ao_dma_start(ao_ee_dma_out_id); - ao_dma_trigger(ao_ee_dma_out_id); - __critical while (!ao_ee_dma_in_done) - ao_sleep(&ao_ee_dma_in_done); -} #define EE_BLOCK 256 @@ -143,7 +60,7 @@ ao_ee_write_enable(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WREN; - ao_ee_send(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1); ao_ee_cs_high(); } @@ -152,8 +69,8 @@ ao_ee_rdsr(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_RDSR; - ao_ee_send(&ao_ee_instruction, 1); - ao_ee_recv(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1); + ao_spi_recv(&ao_ee_instruction, 1); ao_ee_cs_high(); return ao_ee_instruction.instruction; } @@ -164,7 +81,7 @@ ao_ee_wrsr(uint8_t status) ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WRSR; ao_ee_instruction.address[0] = status; - ao_ee_send(&ao_ee_instruction, 2); + ao_spi_send(&ao_ee_instruction, 2); ao_ee_cs_high(); } @@ -191,8 +108,8 @@ ao_ee_write_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_ee_send(&ao_ee_instruction, 4); - ao_ee_send(ao_ee_data, EE_BLOCK); + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_send(ao_ee_data, EE_BLOCK); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -210,8 +127,8 @@ ao_ee_read_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_ee_send(&ao_ee_instruction, 4); - ao_ee_recv(ao_ee_data, EE_BLOCK); + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_recv(ao_ee_data, EE_BLOCK); ao_ee_cs_high(); } @@ -423,39 +340,5 @@ ao_ee_init(void) P1DIR |= (1 << EE_CS_INDEX); P1SEL &= ~(1 << EE_CS_INDEX); - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_ee_dma_out_id = ao_dma_alloc(&ao_ee_dma_out_done); - - /* Set up IN DMA */ - ao_ee_dma_in_id = ao_dma_alloc(&ao_ee_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock, - * while the 25LC1024 is limited to 20MHz. So, - * use the 3MHz clock (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); ao_cmd_register(&ao_ee_cmds[0]); } diff --git a/src/ao_flash.c b/src/ao_flash.c index 638e51e0..4f3618ee 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -18,22 +18,11 @@ #include "ao.h" #include "at45db161d.h" -/* - * Using SPI on USART 0, with P1_1 as the chip select - */ - #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 -__xdata uint8_t ao_flash_dma_in_done; -__xdata uint8_t ao_flash_dma_out_done; __xdata uint8_t ao_flash_mutex; -uint8_t ao_flash_dma_out_id; -uint8_t ao_flash_dma_in_id; - -static __xdata uint8_t ao_flash_const = 0xff; - #define ao_flash_delay() do { \ _asm nop _endasm; \ _asm nop _endasm; \ @@ -54,83 +43,6 @@ void ao_flash_cs_high(void) ao_flash_delay(); } -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -static void -ao_flash_send(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_flash_dma_in_id, - &U0DBUFXADDR, - &ao_flash_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_flash_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_flash_dma_in_id); - ao_dma_start(ao_flash_dma_out_id); - ao_dma_trigger(ao_flash_dma_out_id); - __critical while (!ao_flash_dma_in_done) - ao_sleep(&ao_flash_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -static void -ao_flash_recv(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_flash_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_flash_dma_out_id, - &ao_flash_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_flash_dma_in_id); - ao_dma_start(ao_flash_dma_out_id); - ao_dma_trigger(ao_flash_dma_out_id); - __critical while (!ao_flash_dma_in_done) - ao_sleep(&ao_flash_dma_in_done); -} - struct ao_flash_instruction { uint8_t instruction; uint8_t address[3]; @@ -144,7 +56,7 @@ ao_flash_set_pagesize_512(void) ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_flash_send(&ao_flash_instruction, 4); + ao_spi_send(&ao_flash_instruction, 4); ao_flash_cs_high(); } @@ -154,8 +66,8 @@ ao_flash_read_status(void) { ao_flash_cs_low(); ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_flash_send(&ao_flash_instruction, 1); - ao_flash_recv(&ao_flash_instruction, 1); + ao_spi_send(&ao_flash_instruction, 1); + ao_spi_recv(&ao_flash_instruction, 1); ao_flash_cs_high(); return ao_flash_instruction.instruction; } @@ -268,8 +180,8 @@ ao_flash_write_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_flash_send(&ao_flash_instruction, 4); - ao_flash_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -286,8 +198,8 @@ ao_flash_read_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_flash_send(&ao_flash_instruction, 4); - ao_flash_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE); ao_flash_cs_high(); } @@ -543,40 +455,5 @@ ao_ee_init(void) FLASH_CS = 1; P1DIR |= (1 << FLASH_CS_INDEX); P1SEL &= ~(1 << FLASH_CS_INDEX); - - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_flash_dma_out_id = ao_dma_alloc(&ao_flash_dma_out_done); - - /* Set up IN DMA */ - ao_flash_dma_in_id = ao_dma_alloc(&ao_flash_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock, - * while the at45db161d.h is limited to 20MHz. So, - * use the 3MHz clock (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); ao_cmd_register(&ao_flash_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index e9a265b0..edbb4908 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -31,6 +31,8 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEDONGLE_V_0_2) @@ -45,6 +47,8 @@ #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -60,6 +64,8 @@ #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEDONGLE_V_0_1) @@ -74,6 +80,8 @@ #define AO_LED_RED 2 #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 #endif #if defined(TIDONGLE) @@ -87,6 +95,8 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 #endif #if DBG_ON_P1 @@ -125,6 +135,18 @@ #endif /* DBG_ON_P0 */ +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + #ifndef HAS_SERIAL_1 #error Please define HAS_SERIAL_1 #endif diff --git a/src/ao_spi.c b/src/ao_spi.c new file mode 100644 index 00000000..bd52a0d4 --- /dev/null +++ b/src/ao_spi.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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" + +__xdata uint8_t ao_spi_mutex; +__xdata uint8_t ao_spi_dma_in_done; +__xdata uint8_t ao_spi_dma_out_done; + +uint8_t ao_spi_dma_out_id; +uint8_t ao_spi_dma_in_id; + +static __xdata uint8_t ao_spi_const = 0xff; + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + ao_mutex_get(&ao_spi_mutex); + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + &ao_spi_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); + ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + ao_mutex_get(&ao_spi_mutex); + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + &ao_spi_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); + ao_mutex_put(&ao_spi_mutex); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +void +ao_spi_init(void) +{ + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); + + /* Set up IN DMA */ + ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); +} diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index fd0adae8..1209c820 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -48,6 +48,7 @@ main(void) ao_adc_init(); ao_beep_init(); ao_cmd_init(); + ao_spi_init(); ao_ee_init(); ao_flight_init(); ao_log_init(); diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index a7310fbc..ac8dcdb9 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sirf-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ $(SIRF_DRIVER_SRC) \ $(DBG_SRC) diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index 000287ba..e032d1eb 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sky-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index 010578df..a60a501a 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v1.0-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(FLASH_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) -- cgit v1.2.3 From 5688af4e4d7ca8e559d758257e79b7979f1cc924 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Dec 2010 21:13:56 -0800 Subject: altos: Add telemetrum-v1.1 directory This just clones the v1.0 build; changes will be added on top of this. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_pins.h | 15 +++++++++++++++ src/telemetrum-v1.1/.gitignore | 2 ++ src/telemetrum-v1.1/.sdcdbrc | 1 + src/telemetrum-v1.1/Makefile | 1 + src/telemetrum-v1.1/Makefile.defs | 12 ++++++++++++ 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/telemetrum-v1.1/.gitignore create mode 100644 src/telemetrum-v1.1/.sdcdbrc create mode 100644 src/telemetrum-v1.1/Makefile create mode 100644 src/telemetrum-v1.1/Makefile.defs diff --git a/src/Makefile b/src/Makefile index 95d24425..a6615321 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ CC=sdcc include Version -SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=telemetrum-v1.1 telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test all: all-recursive diff --git a/src/ao_pins.h b/src/ao_pins.h index edbb4908..b5089b85 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,6 +28,21 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 diff --git a/src/telemetrum-v1.1/.gitignore b/src/telemetrum-v1.1/.gitignore new file mode 100644 index 00000000..c2212151 --- /dev/null +++ b/src/telemetrum-v1.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-* +ao_product.h diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v1.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs new file mode 100644 index 00000000..a230203a --- /dev/null +++ b/src/telemetrum-v1.1/Makefile.defs @@ -0,0 +1,12 @@ +PROG = telemetrum-v1.1-$(VERSION).ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v1.1 +PRODUCT_DEF=-DTELEMETRUM_V_1_1 +IDPRODUCT=0x000b -- cgit v1.2.3 From f3f1b1488bdc92fa9277dc549ba9f3210a8d4c8c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 11:28:35 -0800 Subject: altos: packet and usb i/o routines use 'char', not 'uint8_t' Just fixing the type of a local variable holding a character passed from the packet link to usb. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 0808bc80..5f79885c 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -35,7 +35,7 @@ ao_packet_getchar(void) __critical static void ao_packet_echo(void) __reentrant { - uint8_t c; + char c; while (ao_packet_enable) { c = ao_packet_getchar(); if (c != AO_READ_AGAIN) -- cgit v1.2.3 From ddcc94da4326f9ce954bd31a46b36165c58e6c18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 12:51:39 -0800 Subject: altos: Simplify storage API This removes the config-specific APIs and exposes global variables for the available storage space, block size and config storage location. Signed-off-by: Keith Packard --- src/ao.h | 44 +++++++--------- src/ao_config.c | 7 ++- src/ao_ee.c | 95 +++++++++++++++------------------- src/ao_flash.c | 146 ++++++++++++++++++---------------------------------- src/ao_log.c | 25 +++++---- src/ao_telemetrum.c | 2 +- src/at45db161d.h | 7 --- 7 files changed, 133 insertions(+), 193 deletions(-) diff --git a/src/ao.h b/src/ao.h index 69f4665b..67337de7 100644 --- a/src/ao.h +++ b/src/ao.h @@ -430,42 +430,38 @@ void ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; /* - * ao_ee.c + * Storage interface, provided by one of the eeprom or flash + * drivers */ -/* - * We reserve the last block on the device for - * configuration space. Writes and reads in this - * area return errors. - */ +/* Total bytes of available storage */ +extern __xdata uint32_t ao_storage_total; -#define AO_EE_BLOCK_SIZE ((uint16_t) (256)) -#define AO_EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) -#define AO_EE_DATA_SIZE (AO_EE_DEVICE_SIZE - (uint32_t) AO_EE_BLOCK_SIZE) -#define AO_EE_CONFIG_BLOCK ((uint16_t) (AO_EE_DATA_SIZE / AO_EE_BLOCK_SIZE)) +/* Block size - device is erased in these units. At least 256 bytes */ +extern __xdata uint32_t ao_storage_block; -void -ao_ee_flush(void) __reentrant; +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __xdata uint32_t ao_storage_config; -/* Write to the eeprom */ -uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void); -/* Read from the eeprom */ -uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; +/* Flush any pending write data */ +void +ao_storage_flush(void) __reentrant; -/* Write the config block (at the end of the eeprom) */ +/* Write data. Returns 0 on failure, 1 on success */ uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant; +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; -/* Read the config block (at the end of the eeprom) */ +/* Read data. Returns 0 on failure, 1 on success */ uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant; +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; -/* Initialize the EEPROM code */ +/* Initialize the storage code */ void -ao_ee_init(void); +ao_storage_init(void); /* * ao_log.c diff --git a/src/ao_config.c b/src/ao_config.c index fd33e2cc..2153b841 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -32,7 +32,9 @@ __xdata uint8_t ao_config_mutex; static void _ao_config_put(void) { - ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config)); + ao_storage_setup(); + ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_storage_flush(); } #endif @@ -42,7 +44,8 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM - ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config)); + ao_storage_setup(); + ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; diff --git a/src/ao_ee.c b/src/ao_ee.c index 36c8a100..6fe88252 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -18,6 +18,18 @@ #include "ao.h" #include "25lc1024.h" +#define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + /* * Using SPI on USART 0, with P1_2 as the chip select */ @@ -25,7 +37,7 @@ #define EE_CS P1_2 #define EE_CS_INDEX 2 -__xdata uint8_t ao_ee_mutex; +static __xdata uint8_t ao_ee_mutex; #define ao_ee_delay() do { \ _asm nop _endasm; \ @@ -33,23 +45,20 @@ __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -void ao_ee_cs_low(void) +static void ao_ee_cs_low(void) { ao_ee_delay(); EE_CS = 0; ao_ee_delay(); } -void ao_ee_cs_high(void) +static void ao_ee_cs_high(void) { ao_ee_delay(); EE_CS = 1; ao_ee_delay(); } - -#define EE_BLOCK 256 - struct ao_ee_instruction { uint8_t instruction; uint8_t address[3]; @@ -87,7 +96,7 @@ ao_ee_wrsr(uint8_t status) #define EE_BLOCK_NONE 0xffff -static __xdata uint8_t ao_ee_data[EE_BLOCK]; +static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; static __pdata uint8_t ao_ee_block_dirty; @@ -109,7 +118,7 @@ ao_ee_write_block(void) ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -128,7 +137,7 @@ ao_ee_read_block(void) ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); ao_ee_cs_high(); } @@ -152,13 +161,13 @@ ao_ee_fill(uint16_t block) } uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint8_t this_off; - if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE) + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -166,7 +175,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant * a single block */ this_off = pos; - this_len = 256 - (uint16_t) this_off; + this_len = EE_BLOCK_SIZE - (uint16_t) this_off; block = (uint16_t) (pos >> 8); if (this_len > len) this_len = len; @@ -175,7 +184,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { - if (this_len != 256) + if (this_len != EE_BLOCK_SIZE) ao_ee_fill(block); else { ao_ee_flush_internal(); @@ -194,13 +203,13 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint8_t this_off; - if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE) + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -208,7 +217,7 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant * a single block */ this_off = pos; - this_len = 256 - (uint16_t) this_off; + this_len = EE_BLOCK_SIZE - (uint16_t) this_off; block = (uint16_t) (pos >> 8); if (this_len > len) this_len = len; @@ -230,47 +239,17 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } void -ao_ee_flush(void) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - } ao_mutex_put(&ao_ee_mutex); -} - -/* - * Read/write the config block, which is in - * the last block of the ao_eeprom - */ -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +ao_storage_flush(void) __reentrant { - if (len > AO_EE_BLOCK_SIZE) - return 0; ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(AO_EE_CONFIG_BLOCK); - memcpy(ao_ee_data, buf, len); - ao_ee_block_dirty = 1; ao_ee_flush_internal(); } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - if (len > AO_EE_BLOCK_SIZE) - return 0; - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(AO_EE_CONFIG_BLOCK); - memcpy(buf, ao_ee_data, len); - } ao_mutex_put(&ao_ee_mutex); - return 1; } static void ee_dump(void) __reentrant { - uint8_t b; + static __xdata uint8_t b; uint16_t block; uint8_t i; @@ -286,7 +265,7 @@ ee_dump(void) __reentrant ao_cmd_put16((uint16_t) i); } putchar(' '); - ao_ee_read(((uint32_t) block << 8) | i, &b, 1); + ao_storage_read(((uint32_t) block << 8) | i, &b, 1); ao_cmd_put8(b); ++i; } while (i != 0); @@ -299,7 +278,7 @@ ee_store(void) __reentrant uint16_t block; uint8_t i; uint16_t len; - uint8_t b; + static __xdata uint8_t b; uint32_t addr; ao_cmd_hex(); @@ -316,10 +295,10 @@ ee_store(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; b = ao_cmd_lex_i; - ao_ee_write(addr, &b, 1); + ao_storage_write(addr, &b, 1); addr++; } - ao_ee_flush(); + ao_storage_flush(); } __code struct ao_cmds ao_ee_cmds[] = { @@ -328,12 +307,22 @@ __code struct ao_cmds ao_ee_cmds[] = { { 0, ee_store, NULL }, }; +void +ao_storage_setup(void) +{ + if (ao_storage_total == 0) { + ao_storage_total = EE_DEVICE_SIZE; + ao_storage_block = EE_BLOCK_SIZE; + ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + } +} + /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_ee_init(void) +ao_storage_init(void) { /* set up CS */ EE_CS = 1; diff --git a/src/ao_flash.c b/src/ao_flash.c index 4f3618ee..3a06bae1 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -18,9 +18,20 @@ #include "ao.h" #include "at45db161d.h" +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 +#define FLASH_BLOCK_SIZE_MAX 512 + __xdata uint8_t ao_flash_mutex; #define ao_flash_delay() do { \ @@ -79,12 +90,12 @@ static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; static __pdata uint8_t ao_flash_block_dirty; static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; -static __data uint32_t ao_flash_device_size; static __data uint8_t ao_flash_block_shift; static __data uint16_t ao_flash_block_size; +static __data uint16_t ao_flash_block_mask; -static void -ao_flash_setup(void) +void +ao_storage_setup(void) { uint8_t status; @@ -114,43 +125,47 @@ ao_flash_setup(void) /* AT45DB321D */ case 0x34: ao_flash_block_shift = 9; - ao_flash_device_size = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB161D */ case 0x2c: ao_flash_block_shift = 9; - ao_flash_device_size = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB081D */ case 0x24: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB041D */ case 0x1c: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 512 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); break; /* AT45DB021D */ case 0x14: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 256 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); break; /* AT45DB011D */ case 0x0c: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 128 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); break; default: ao_panic(AO_PANIC_FLASH); } ao_flash_block_size = 1 << ao_flash_block_shift; + + ao_storage_block = ao_flash_block_size; + ao_storage_config = ao_storage_total - ao_storage_block; + ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); } @@ -181,7 +196,7 @@ ao_flash_write_block(void) ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(ao_flash_data, ao_storage_block); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -199,7 +214,7 @@ ao_flash_read_block(void) ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_recv(ao_flash_data, ao_flash_block_size); ao_flash_cs_high(); } @@ -223,29 +238,29 @@ ao_flash_fill(uint16_t block) } uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint16_t this_off; - ao_flash_setup(); - if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { /* Compute portion of transfer within * a single block */ - this_off = (uint16_t) pos & FLASH_BLOCK_MASK; - this_len = FLASH_BLOCK_SIZE - this_off; - block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + this_off = (uint16_t) pos & ao_flash_block_mask; + this_len = ao_flash_block_size - this_off; + block = (uint16_t) (pos >> ao_flash_block_shift); if (this_len > len) this_len = len; /* Transfer the data */ ao_mutex_get(&ao_flash_mutex); { - if (this_len != FLASH_BLOCK_SIZE) + if (this_len != ao_flash_block_size) ao_flash_fill(block); else { ao_flash_flush_internal(); @@ -264,14 +279,14 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint16_t this_off; - ao_flash_setup(); - if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -279,9 +294,9 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* Compute portion of transfer within * a single block */ - this_off = (uint16_t) pos & FLASH_BLOCK_MASK; - this_len = FLASH_BLOCK_SIZE - this_off; - block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + this_off = (uint16_t) pos & ao_flash_block_mask; + this_len = ao_flash_block_size - this_off; + block = (uint16_t) (pos >> ao_flash_block_shift); if (this_len > len) this_len = len; @@ -300,50 +315,17 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } void -ao_ee_flush(void) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - } ao_mutex_put(&ao_flash_mutex); -} - -/* - * Read/write the config block, which is in - * the last block of the flash - */ - -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +ao_storage_flush(void) __reentrant { - ao_flash_setup(); - if (len > FLASH_BLOCK_SIZE) - return 0; ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(FLASH_CONFIG_BLOCK); - memcpy(ao_flash_data, buf, len); - ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - ao_flash_setup(); - if (len > FLASH_BLOCK_SIZE) - return 0; - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(FLASH_CONFIG_BLOCK); - memcpy(buf, ao_flash_data, len); - } ao_mutex_put(&ao_flash_mutex); - return 1; } static void flash_dump(void) __reentrant { - uint8_t b; + static __xdata uint8_t b; uint16_t block; uint8_t i; @@ -359,7 +341,7 @@ flash_dump(void) __reentrant ao_cmd_put16((uint16_t) i); } putchar(' '); - ao_ee_read(((uint32_t) block << 8) | i, &b, 1); + ao_storage_read(((uint32_t) block << 8) | i, &b, 1); ao_cmd_put8(b); ++i; } while (i != 0); @@ -372,7 +354,7 @@ flash_store(void) __reentrant uint16_t block; uint8_t i; uint16_t len; - uint8_t b; + static __xdata uint8_t b; uint32_t addr; ao_cmd_hex(); @@ -389,33 +371,10 @@ flash_store(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; b = ao_cmd_lex_i; - ao_ee_write(addr, &b, 1); + ao_storage_write(addr, &b, 1); addr++; } - ao_ee_flush(); -} - -void -ao_ee_dump_config(void) __reentrant -{ - uint16_t i; - printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = FLASH_BLOCK_NONE; - ao_flash_fill(FLASH_CONFIG_BLOCK); - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_cmd_put8(ao_flash_data[i]); - ++i; - } while (i < sizeof (ao_config)); - } ao_mutex_put(&ao_flash_mutex); + ao_storage_flush(); } static void @@ -423,18 +382,15 @@ flash_status(void) __reentrant { uint8_t status; - ao_flash_setup(); + ao_storage_setup(); ao_mutex_get(&ao_flash_mutex); { status = ao_flash_read_status(); printf ("Flash status: 0x%02x\n", status); - printf ("Flash block shift: %d\n", FLASH_BLOCK_SHIFT); - printf ("Flash block size: %d\n", FLASH_BLOCK_SIZE); - printf ("Flash block mask: %d\n", FLASH_BLOCK_MASK); - printf ("Flash device size: %ld\n", FLASH_DEVICE_SIZE); - printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); - printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); + printf ("Flash block shift: %d\n", ao_flash_block_shift); + printf ("Flash block size: %d\n", ao_flash_block_size); + printf ("Flash block mask: %d\n", ao_flash_block_mask); + printf ("Flash device size: %ld\n", ao_storage_total); } ao_mutex_put(&ao_flash_mutex); - ao_ee_dump_config(); } __code struct ao_cmds ao_flash_cmds[] = { @@ -449,7 +405,7 @@ __code struct ao_cmds ao_flash_cmds[] = { * the SPI interface */ void -ao_ee_init(void) +ao_storage_init(void) { /* set up CS */ FLASH_CS = 1; diff --git a/src/ao_log.c b/src/ao_log.c index 18bdb8c8..30acc50a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -18,6 +18,7 @@ #include "ao.h" static __pdata uint32_t ao_log_current_pos; +static __pdata uint32_t ao_log_end_pos; static __pdata uint32_t ao_log_start_pos; static __xdata uint8_t ao_log_running; static __xdata uint8_t ao_log_mutex; @@ -41,16 +42,14 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos) + ao_log_running = 0; if (ao_log_running) { wrote = 1; - ao_ee_write(ao_log_current_pos, - (uint8_t *) log, - sizeof (struct ao_log_record)); + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); ao_log_current_pos += sizeof (struct ao_log_record); - if (ao_log_current_pos >= AO_EE_DATA_SIZE) - ao_log_current_pos = 0; - if (ao_log_current_pos == ao_log_start_pos) - ao_log_running = 0; } } ao_mutex_put(&ao_log_mutex); return wrote; @@ -59,7 +58,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant void ao_log_flush(void) { - ao_ee_flush(); + ao_storage_flush(); } __xdata struct ao_log_record log; @@ -76,7 +75,7 @@ ao_log_dump_check_data(void) static void ao_log_scan(void) { - if (!ao_ee_read(0, (uint8_t *) &log, sizeof (struct ao_log_record))) + if (!ao_storage_read(0, &log, sizeof (struct ao_log_record))) ao_panic(AO_PANIC_LOG); if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { ao_flight_number = log.u.flight.flight + 1; @@ -97,6 +96,12 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { + ao_storage_setup(); + + /* For now, use all of the available space */ + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + ao_log_scan(); while (!ao_log_running) @@ -179,8 +184,6 @@ ao_log_init(void) ao_log_running = 0; /* For now, just log the flight starting at the begining of eeprom */ - ao_log_start_pos = 0; - ao_log_current_pos = ao_log_start_pos; ao_log_state = ao_flight_invalid; /* Create a task to log events to eeprom */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 1209c820..ed43c447 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -49,7 +49,7 @@ main(void) ao_beep_init(); ao_cmd_init(); ao_spi_init(); - ao_ee_init(); + ao_storage_init(); ao_flight_init(); ao_log_init(); ao_report_init(); diff --git a/src/at45db161d.h b/src/at45db161d.h index 8b72e647..96042459 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -26,13 +26,6 @@ * area return errors. */ -#define FLASH_BLOCK_SIZE_MAX 512 -#define FLASH_BLOCK_SHIFT (ao_flash_block_shift) -#define FLASH_BLOCK_SIZE (ao_flash_block_size) -#define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) -#define FLASH_DEVICE_SIZE (ao_flash_device_size) -#define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) -#define FLASH_CONFIG_BLOCK ((uint16_t) (FLASH_DATA_SIZE / FLASH_BLOCK_SIZE)) #define FLASH_READ 0x03 #define FLASH_WRITE 0x82 -- cgit v1.2.3 From e4ba9bf4291bf17c777c8c3ef7c71e4a30b9947a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 17:34:58 -0800 Subject: altos: Require manual flight erasing. This supports flash chips that require larger erase blocks. Signed-off-by: Keith Packard --- src/ao.h | 11 +++ src/ao_config.c | 20 +++-- src/ao_ee.c | 12 +++ src/ao_flash.c | 12 +++ src/ao_log.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 265 insertions(+), 21 deletions(-) diff --git a/src/ao.h b/src/ao.h index 67337de7..f23e4134 100644 --- a/src/ao.h +++ b/src/ao.h @@ -443,6 +443,8 @@ extern __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ extern __xdata uint32_t ao_storage_config; +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + /* Initialize above values. Can only be called once the OS is running */ void ao_storage_setup(void); @@ -459,6 +461,10 @@ ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; uint8_t ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos); + /* Initialize the storage code */ void ao_storage_init(void); @@ -993,9 +999,14 @@ struct ao_config { extern __xdata struct ao_config ao_config; +#define AO_CONFIG_MAX_SIZE 128 + void ao_config_get(void); +void +ao_config_put(void); + void ao_config_init(void); diff --git a/src/ao_config.c b/src/ao_config.c index 2153b841..2673e472 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -36,6 +36,14 @@ _ao_config_put(void) ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); ao_storage_flush(); } + +void +ao_config_put(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_put(); + ao_mutex_put(&ao_config_mutex); +} #endif static void @@ -288,13 +296,13 @@ struct ao_config_var { const char *help; }; -void +static void ao_config_help(void) __reentrant; -void +static void ao_config_show(void) __reentrant; -void +static void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { @@ -348,7 +356,7 @@ ao_config_set(void) ao_cmd_status = ao_cmd_syntax_error; } -void +static void ao_config_help(void) __reentrant { uint8_t cmd; @@ -356,7 +364,7 @@ ao_config_help(void) __reentrant puts (ao_config_vars[cmd].help); } -void +static void ao_config_show(void) __reentrant { uint8_t cmd; @@ -368,7 +376,7 @@ ao_config_show(void) __reentrant } #if HAS_EEPROM -void +static void ao_config_write(void) __reentrant { uint8_t saved = 0; diff --git a/src/ao_ee.c b/src/ao_ee.c index 6fe88252..575a7b30 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -246,6 +246,18 @@ ao_storage_flush(void) __reentrant } ao_mutex_put(&ao_ee_mutex); } +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + uint16_t block = (uint16_t) (pos >> 8); + ao_ee_fill(block); + memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + static void ee_dump(void) __reentrant { diff --git a/src/ao_flash.c b/src/ao_flash.c index 3a06bae1..bc8b56ad 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -322,6 +322,18 @@ ao_storage_flush(void) __reentrant } ao_mutex_put(&ao_flash_mutex); } +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + ao_flash_fill(block); + memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + static void flash_dump(void) __reentrant { diff --git a/src/ao_log.c b/src/ao_log.c index 30acc50a..132512e6 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -61,6 +61,8 @@ ao_log_flush(void) ao_storage_flush(); } +static void ao_log_scan(void); + __xdata struct ao_log_record log; __xdata uint16_t ao_flight_number; @@ -72,21 +74,6 @@ ao_log_dump_check_data(void) return 1; } -static void -ao_log_scan(void) -{ - if (!ao_storage_read(0, &log, sizeof (struct ao_log_record))) - ao_panic(AO_PANIC_LOG); - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { - ao_flight_number = log.u.flight.flight + 1; - if (ao_flight_number == 0) - ao_flight_number = 1; - } else { - ao_flight_number = 1; - } - ao_wakeup(&ao_flight_number); -} - __xdata uint8_t ao_log_adc_pos; __xdata enum flight_state ao_log_state; @@ -161,6 +148,160 @@ ao_log(void) } } +/* + * When erasing a flight log, make sure the config block + * has an up-to-date version of the current flight number + */ + +struct ao_log_erase { + uint8_t unused; + uint16_t flight; +}; + +static __xdata struct ao_log_erase erase; + +#define LOG_MAX_ERASE 16 + +static uint32_t +ao_log_erase_pos(uint8_t i) +{ + return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; +} + +static void +ao_log_write_erase(uint8_t pos) +{ + erase.unused = 0x00; + erase.flight = ao_flight_number; + ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + +static void +ao_log_read_erase(uint8_t pos) +{ + ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + + +static void +ao_log_erase_mark(void) +{ + uint8_t i; + + for (i = 0; i < LOG_MAX_ERASE; i++) { + ao_log_read_erase(i); + if (erase.unused == 0 && erase.flight == ao_flight_number) + return; + if (erase.unused == 0xff) { + ao_log_write_erase(i); + return; + } + } + ao_config_put(); +} + +static void +ao_log_erase(uint8_t pos) +{ + ao_config_get(); + (void) pos; +// ao_log_current_pos = pos * ao_config.flight_log_max; +// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; +// if (ao_log_end_pos > ao_storage_config) +// return; + + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + + while (ao_log_current_pos < ao_log_end_pos) { + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } +} + +static uint16_t +ao_log_flight(uint8_t slot) +{ + (void) slot; + if (!ao_storage_read(0, + &log, + sizeof (struct ao_log_record))) + ao_panic(AO_PANIC_LOG); + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} + +static void +ao_log_scan(void) +{ + uint8_t log_slot; + uint8_t log_avail = 0; + uint16_t log_flight; + + ao_config_get(); + + ao_flight_number = 0; + + /* Scan the log space looking for an empty one, and find the biggest flight number */ + log_slot = 0; + { + log_flight = ao_log_flight(log_slot); + if (log_flight) { + if (++log_flight == 0) + log_flight = 1; + if (ao_flight_number == 0 || + (int16_t) (log_flight - ao_flight_number) > 0) { + ao_flight_number = log_flight; + } + } else + log_avail |= 1 << log_slot; + } + + /* Now look through the log of flight numbers from erase operations and + * see if the last one is bigger than what we found above + */ + for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { + ao_log_read_erase(log_slot); + if (erase.unused == 0) { + if (ao_flight_number == 0 || + (int16_t) (erase.flight - ao_flight_number) > 0) + ao_flight_number = erase.flight; + break; + } + } + if (ao_flight_number == 0) + ao_flight_number = 1; + + /* With a flight number in hand, find a place to write a new log, + * use the target flight number to index the available log slots so + * that we write logs to each spot about the same number of times. + */ + + /* If there are no log slots available, then + * do not log the next flight + */ + if (!log_avail) { + ao_log_current_pos = 0; + ao_log_end_pos = 0; + } else { + log_slot = ao_flight_number % log_slot; + while (!((log_avail & (1 << log_slot)))) { + if ((1 << log_slot) > log_avail) + log_slot = 0; + else + log_slot++; + } +// ao_log_current_pos = log_slot * ao_config.flight_log_max; +// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + } + + ao_wakeup(&ao_flight_number); +} + void ao_log_start(void) { @@ -178,6 +319,64 @@ ao_log_stop(void) static __xdata struct ao_task ao_log_task; +void +ao_log_list(void) __reentrant +{ + uint8_t slot; + uint16_t flight; + + slot = 0; + { + flight = ao_log_flight(slot); + if (flight) + printf ("Flight %d\n", flight); + } +} + +void +ao_log_delete(void) __reentrant +{ + uint8_t slot; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + slot = 0; + /* Look for the flight log matching the requested flight */ + { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + while (ao_log_current_pos < ao_log_end_pos) { + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + if (ao_storage_read(ao_log_current_pos, + &log, + sizeof (struct ao_log_record))) { + for (slot = 0; slot < sizeof (struct ao_log_record); slot++) + if (((uint8_t *) &log)[slot] != 0xff) + break; + if (slot == sizeof (struct ao_log_record)) + break; + } + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } + puts("Erased\n"); + return; + } + } + printf("No such flight: %d\n", ao_cmd_lex_i); +} + +__code struct ao_cmds ao_log_cmds[] = { + { 'l', ao_log_list, "l List stored flight logs" }, + { 'd', ao_log_delete, "d Delete stored flight" }, + { 0, ao_log_delete, NULL }, +}; + void ao_log_init(void) { @@ -186,6 +385,8 @@ ao_log_init(void) /* For now, just log the flight starting at the begining of eeprom */ ao_log_state = ao_flight_invalid; + ao_cmd_register(&ao_log_cmds[0]); + /* Create a task to log events to eeprom */ ao_add_task(&ao_log_task, ao_log, "log"); } -- cgit v1.2.3 From 569a1dac55b70c30f01afa7bcb74442ecdd85d85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 22:37:38 -0800 Subject: altos: Move common storage code to ao_storage.c. Add M25P80 driver This reworks the storage API so that you erase blocks and then store data to them so that the M25P80 driver will work. Signed-off-by: Keith Packard --- src/Makefile.proto | 10 + src/ao.h | 45 +++-- src/ao_config.c | 2 + src/ao_ee.c | 157 ++++------------ src/ao_flash.c | 166 ++++------------- src/ao_log.c | 7 +- src/ao_m25.c | 380 ++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 2 + src/ao_storage.c | 164 ++++++++++++++++ src/at45db161d.h | 1 + src/telemetrum-v1.1/Makefile.defs | 2 +- 11 files changed, 662 insertions(+), 274 deletions(-) create mode 100644 src/ao_m25.c create mode 100644 src/ao_storage.c diff --git a/src/Makefile.proto b/src/Makefile.proto index c79638ac..709cbca7 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -94,14 +94,24 @@ TM_DRIVER_SRC = \ # # 25LC1024 driver source EE_DRIVER_SRC = \ + ao_storage.c \ ao_ee.c # # AT45DB161D driver source FLASH_DRIVER_SRC = \ + ao_storage.c \ ao_flash.c +# +# Numonyx M25P80 driver source +# + +M25_DRIVER_SRC = \ + ao_storage.c \ + ao_m25.c + # # SiRF driver source # diff --git a/src/ao.h b/src/ao.h index f23e4134..e1306c79 100644 --- a/src/ao.h +++ b/src/ao.h @@ -443,16 +443,15 @@ extern __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ extern __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __xdata uint16_t ao_storage_unit; + #define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) /* Initialize above values. Can only be called once the OS is running */ void ao_storage_setup(void); -/* Flush any pending write data */ -void -ao_storage_flush(void) __reentrant; - /* Write data. Returns 0 on failure, 1 on success */ uint8_t ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; @@ -463,12 +462,36 @@ ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_storage_erase(uint32_t pos); +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; /* Initialize the storage code */ void ao_storage_init(void); +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + /* * ao_log.c */ @@ -581,14 +604,6 @@ ao_log_flush(void); */ extern __xdata uint16_t ao_flight_number; -/* Retrieve first log record for the current flight */ -uint8_t -ao_log_dump_first(void); - -/* return next log record for the current flight */ -uint8_t -ao_log_dump_next(void); - /* Logging thread main routine */ void ao_log(void); @@ -605,6 +620,10 @@ ao_log_stop(void); void ao_log_init(void); +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + /* * ao_flight.c */ diff --git a/src/ao_config.c b/src/ao_config.c index 2673e472..38b72798 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -33,7 +33,9 @@ static void _ao_config_put(void) { ao_storage_setup(); + ao_storage_erase(ao_storage_config); ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_log_write_erase(0); ao_storage_flush(); } diff --git a/src/ao_ee.c b/src/ao_ee.c index 575a7b30..7de05b7b 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -30,6 +30,9 @@ __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + /* * Using SPI on USART 0, with P1_2 as the chip select */ @@ -161,80 +164,34 @@ ao_ee_fill(uint16_t block) } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint8_t this_off; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = pos; - this_len = EE_BLOCK_SIZE - (uint16_t) this_off; - block = (uint16_t) (pos >> 8); - if (this_len > len) - this_len = len; - if (this_len & 0xff00) - ao_panic(AO_PANIC_EE); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - if (this_len != EE_BLOCK_SIZE) - ao_ee_fill(block); - else { - ao_ee_flush_internal(); - ao_ee_block = block; - } - memcpy(ao_ee_data + this_off, buf, this_len); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + uint16_t block = (uint16_t) (pos >> 8); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + if (len != EE_BLOCK_SIZE) + ao_ee_fill(block); + else { + ao_ee_flush_internal(); + ao_ee_block = block; + } + memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); return 1; } uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint8_t this_off; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = pos; - this_len = EE_BLOCK_SIZE - (uint16_t) this_off; - block = (uint16_t) (pos >> 8); - if (this_len > len) - this_len = len; - if (this_len & 0xff00) - ao_panic(AO_PANIC_EE); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(block); - memcpy(buf, ao_ee_data + this_off, this_len); - } ao_mutex_put(&ao_ee_mutex); + uint16_t block = (uint16_t) (pos >> 8); - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_fill(block); + memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + } ao_mutex_put(&ao_ee_mutex); return 1; } @@ -258,67 +215,11 @@ ao_storage_erase(uint32_t pos) __reentrant return 1; } -static void -ee_dump(void) __reentrant -{ - static __xdata uint8_t b; - uint16_t block; - uint8_t i; - - ao_cmd_hex(); - block = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_storage_read(((uint32_t) block << 8) | i, &b, 1); - ao_cmd_put8(b); - ++i; - } while (i != 0); - putchar('\n'); -} - static void ee_store(void) __reentrant { - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - uint32_t addr; - - ao_cmd_hex(); - block = ao_cmd_lex_i; - ao_cmd_hex(); - i = ao_cmd_lex_i; - addr = ((uint32_t) block << 8) | i; - ao_cmd_hex(); - len = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - while (len--) { - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - b = ao_cmd_lex_i; - ao_storage_write(addr, &b, 1); - addr++; - } - ao_storage_flush(); } -__code struct ao_cmds ao_ee_cmds[] = { - { 'e', ee_dump, "e Dump a block of EEPROM data" }, - { 'w', ee_store, "w ... Write data to EEPROM" }, - { 0, ee_store, NULL }, -}; - void ao_storage_setup(void) { @@ -326,20 +227,24 @@ ao_storage_setup(void) ao_storage_total = EE_DEVICE_SIZE; ao_storage_block = EE_BLOCK_SIZE; ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + ao_storage_unit = EE_BLOCK_SIZE; } } +void +ao_storage_device_info(void) __reentrant +{ +} + /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_storage_init(void) +ao_storage_device_init(void) { /* set up CS */ EE_CS = 1; P1DIR |= (1 << EE_CS_INDEX); P1SEL &= ~(1 << EE_CS_INDEX); - - ao_cmd_register(&ao_ee_cmds[0]); } diff --git a/src/ao_flash.c b/src/ao_flash.c index bc8b56ad..1201a0e5 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -27,6 +27,9 @@ __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 @@ -162,9 +165,11 @@ ao_storage_setup(void) ao_panic(AO_PANIC_FLASH); } ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_block_mask = ao_flash_block_size - 1; ao_storage_block = ao_flash_block_size; ao_storage_config = ao_storage_total - ao_storage_block; + ao_storage_unit = ao_flash_block_size; ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); @@ -238,79 +243,38 @@ ao_flash_fill(uint16_t block) } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint16_t this_off; + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & ao_flash_block_mask; - this_len = ao_flash_block_size - this_off; - block = (uint16_t) (pos >> ao_flash_block_shift); - if (this_len > len) - this_len = len; - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - if (this_len != ao_flash_block_size) - ao_flash_fill(block); - else { - ao_flash_flush_internal(); - ao_flash_block = block; - } - memcpy(ao_flash_data + this_off, buf, this_len); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (len != ao_flash_block_size) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + buf, + len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); return 1; } uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint16_t this_off; + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & ao_flash_block_mask; - this_len = ao_flash_block_size - this_off; - block = (uint16_t) (pos >> ao_flash_block_shift); - if (this_len > len) - this_len = len; - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); - memcpy(buf, ao_flash_data + this_off, this_len); - } ao_mutex_put(&ao_flash_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, + ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + len); + } ao_mutex_put(&ao_flash_mutex); return 1; } @@ -325,8 +289,9 @@ ao_storage_flush(void) __reentrant uint8_t ao_storage_erase(uint32_t pos) __reentrant { + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + ao_mutex_get(&ao_flash_mutex); { - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); ao_flash_fill(block); memset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; @@ -334,63 +299,8 @@ ao_storage_erase(uint32_t pos) __reentrant return 1; } -static void -flash_dump(void) __reentrant -{ - static __xdata uint8_t b; - uint16_t block; - uint8_t i; - - ao_cmd_hex(); - block = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_storage_read(((uint32_t) block << 8) | i, &b, 1); - ao_cmd_put8(b); - ++i; - } while (i != 0); - putchar('\n'); -} - -static void -flash_store(void) __reentrant -{ - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - uint32_t addr; - - ao_cmd_hex(); - block = ao_cmd_lex_i; - ao_cmd_hex(); - i = ao_cmd_lex_i; - addr = ((uint32_t) block << 8) | i; - ao_cmd_hex(); - len = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - while (len--) { - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - b = ao_cmd_lex_i; - ao_storage_write(addr, &b, 1); - addr++; - } - ao_storage_flush(); -} - -static void -flash_status(void) __reentrant +void +ao_storage_device_info(void) __reentrant { uint8_t status; @@ -405,23 +315,15 @@ flash_status(void) __reentrant } ao_mutex_put(&ao_flash_mutex); } -__code struct ao_cmds ao_flash_cmds[] = { - { 'e', flash_dump, "e Dump a block of flash data" }, - { 'w', flash_store, "w ... Write data to flash" }, - { 'f', flash_status, "f Show flash status register" }, - { 0, flash_store, NULL }, -}; - /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_storage_init(void) +ao_storage_device_init(void) { /* set up CS */ FLASH_CS = 1; P1DIR |= (1 << FLASH_CS_INDEX); P1SEL &= ~(1 << FLASH_CS_INDEX); - ao_cmd_register(&ao_flash_cmds[0]); } diff --git a/src/ao_log.c b/src/ao_log.c index 132512e6..9ca033e1 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -168,7 +168,7 @@ ao_log_erase_pos(uint8_t i) return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; } -static void +void ao_log_write_erase(uint8_t pos) { erase.unused = 0x00; @@ -364,13 +364,16 @@ ao_log_delete(void) __reentrant ao_storage_erase(ao_log_current_pos); ao_log_current_pos += ao_storage_block; } - puts("Erased\n"); + puts("Erased"); return; } } + ao_log_erase_mark(); printf("No such flight: %d\n", ao_cmd_lex_i); } + + __code struct ao_cmds ao_log_cmds[] = { { 'l', ao_log_list, "l List stored flight logs" }, { 'd', ao_log_delete, "d Delete stored flight" }, diff --git a/src/ao_m25.c b/src/ao_m25.c new file mode 100644 index 00000000..afd5df76 --- /dev/null +++ b/src/ao_m25.c @@ -0,0 +1,380 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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" + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + +/* + * Each flash chip is arranged in 64kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 256 byte pages and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +#define M25_WREN 0x06 /* Write Enable */ +#define M25_WRDI 0x04 /* Write Disable */ +#define M25_RDID 0x9f /* Read Identification */ +#define M25_RDSR 0x05 /* Read Status Register */ +#define M25_WRSR 0x01 /* Write Status Register */ +#define M25_READ 0x03 /* Read Data Bytes */ +#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define M25_PP 0x02 /* Page Program */ +#define M25_SE 0xd8 /* Sector Erase */ +#define M25_BE 0xc7 /* Bulk Erase */ +#define M25_DP 0xb9 /* Deep Power-down */ + +/* RDID response */ +#define M25_MANUF_OFFSET 0 +#define M25_MEMORY_TYPE_OFFSET 1 +#define M25_CAPACITY_OFFSET 2 +#define M25_UID_OFFSET 3 +#define M25_CFI_OFFSET 4 +#define M25_RDID_LEN 4 /* that's all we need */ + +#define M25_CAPACITY_128KB 0x11 +#define M25_CAPACITY_256KB 0x12 +#define M25_CAPACITY_512KB 0x13 +#define M25_CAPACITY_1MB 0x14 +#define M25_CAPACITY_2MB 0x15 + +/* + * Status register bits + */ + +#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ +#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ +#define M25_STATUS_BP_SHIFT (2) +#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ +#define M25_STATUS_WIP (1 << 0) /* Write in progress */ + +/* + * On teleterra, the m25 chip select pins are + * wired on P0_0 through P0_3. + */ + +#if M25_MAX_CHIPS > 1 +static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ +static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ +static uint8_t ao_m25_numchips; /* number of chips detected */ +#endif +static uint8_t ao_m25_total; /* total sectors available */ +static uint8_t ao_m25_wip; /* write in progress */ + +static __xdata uint8_t ao_m25_mutex; + +/* + * This little array is abused to send and receive data. A particular + * caution -- the read and write addresses are written into the last + * three bytes of the array by ao_m25_set_page_address and then the + * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither + * of which touch those last three bytes. + */ + +static __xdata uint8_t ao_m25_instruction[4]; + +#define M25_SELECT(cs) (SPI_CS_PORT &= ~(cs)) +#define M25_DESELECT(cs) (SPI_CS_PORT |= (cs)) + +#define M25_BLOCK_SHIFT 16 +#define M25_BLOCK 65536L +#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) +#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) + +/* + * Block until the specified chip is done writing + */ +static void +ao_m25_wait_wip(uint8_t cs) +{ + if (ao_m25_wip & cs) { + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDSR; + ao_spi_send(ao_m25_instruction, 1); + do { + ao_spi_recv(ao_m25_instruction, 1); + } while (ao_m25_instruction[0] & M25_STATUS_WIP); + M25_DESELECT(cs); + ao_m25_wip &= ~cs; + } +} + +/* + * Set the write enable latch so that page program and sector + * erase commands will work. Also mark the chip as busy writing + * so that future operations will block until the WIP bit goes off + */ +static void +ao_m25_write_enable(uint8_t cs) +{ + M25_SELECT(cs); + ao_m25_instruction[0] = M25_WREN; + ao_spi_send(&ao_m25_instruction, 1); + M25_DESELECT(cs); + ao_m25_wip |= cs; +} + + +/* + * Returns the number of 64kB sectors + */ +static uint8_t +ao_m25_read_capacity(uint8_t cs) +{ + uint8_t capacity; + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + /* Check to see if the chip is present */ + if (ao_m25_instruction[0] == 0xff) + return 0; + capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; + + /* Sanity check capacity number */ + if (capacity < 0x11 || 0x1f < capacity) + return 0; + return 1 << (capacity - 0x10); +} + +static uint8_t +ao_m25_set_address(uint32_t pos) +{ + uint8_t chip; +#if M25_MAX_CHIPS > 1 + uint8_t size; + + for (chip = 0; chip < ao_m25_numchips; chip++) { + size = ao_m25_size[chip]; + if (M25_POS_TO_SECTOR(pos) < size) + break; + pos -= M25_SECTOR_TO_POS(size); + } + if (chip == ao_m25_numchips) + return 0xff; + + chip = ao_m25_pin[chip]; +#else + chip = M25_CS_MASK; +#endif + ao_m25_wait_wip(chip); + + ao_m25_instruction[1] = pos >> 16; + ao_m25_instruction[2] = pos >> 8; + ao_m25_instruction[3] = pos; + return chip; +} + +/* + * Scan the possible chip select lines + * to see which flash chips are connected + */ +static uint8_t +ao_m25_scan(void) +{ +#if M25_MAX_CHIPS > 1 + uint8_t pin, size; +#endif + + if (ao_m25_total) + return 1; + +#if M25_MAX_CHIPS > 1 + ao_m25_numchips = 0; + for (pin = 1; pin != 0; pin <<= 1) { + if (M25_CS_MASK & pin) { + size = ao_m25_read_capacity(pin); + if (size != 0) { + ao_m25_size[ao_m25_numchips] = size; + ao_m25_pin[ao_m25_numchips] = pin; + ao_m25_total += size; + ao_m25_numchips++; + } + } + } +#else + ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); +#endif + if (!ao_m25_total) + return 0; + ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); + ao_storage_block = M25_BLOCK; + ao_storage_config = ao_storage_total - M25_BLOCK; + ao_storage_unit = 256; + return 1; +} + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + ao_m25_wait_wip(cs); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_SE; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + M25_DESELECT(cs); + ao_m25_wip |= cs; + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_PP; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + /* No need to use the FAST_READ as we're running at only 8MHz */ + ao_m25_instruction[0] = M25_READ; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_recv(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t cs; +#if M25_MAX_CHIPS > 1 + uint8_t chip; +#endif + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); + +#if M25_MAX_CHIPS > 1 + printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); + for (chip = 0; chip < ao_m25_numchips; chip++) + printf ("Flash chip %d select %02x size %d\n", + chip, ao_m25_pin[chip], ao_m25_size[chip]); +#else + printf ("Detected chips 1 size %d\n", ao_m25_total); +#endif + + printf ("Available chips:\n"); + for (cs = 1; cs != 0; cs <<= 1) { + if ((M25_CS_MASK & cs) == 0) + continue; + + ao_mutex_get(&ao_m25_mutex); + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", + cs, + ao_m25_instruction[M25_MANUF_OFFSET], + ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], + ao_m25_instruction[M25_CAPACITY_OFFSET], + ao_m25_instruction[M25_UID_OFFSET]); + ao_mutex_put(&ao_m25_mutex); + } +} + +void +ao_storage_device_init(void) +{ + /* Set up chip select wires */ + SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ + SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ + SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +} diff --git a/src/ao_pins.h b/src/ao_pins.h index b5089b85..9446964e 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -48,6 +48,8 @@ #define HAS_EXTERNAL_TEMP 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 #endif #if defined(TELEDONGLE_V_0_2) diff --git a/src/ao_storage.c b/src/ao_storage.c new file mode 100644 index 00000000..25a7c8b9 --- /dev/null +++ b/src/ao_storage.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_read(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_write(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +static __xdata uint8_t storage_data[8]; + +static void +ao_storage_dump(void) __reentrant +{ + uint8_t i, j; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + for (i = 0; ; i += 8) { + if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, + storage_data, + 8)) { + ao_cmd_put16((uint16_t) i); + for (j = 0; j < 7; j++) { + putchar(' '); + ao_cmd_put8(storage_data[j]); + } + putchar ('\n'); + } + if (i == 248) + break; + } +} + +static void +ao_storage_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + static __xdata uint8_t b; + uint32_t addr; + + ao_cmd_hex(); + block = ao_cmd_lex_i; + ao_cmd_hex(); + i = ao_cmd_lex_i; + addr = ((uint32_t) block << 8) | i; + ao_cmd_hex(); + len = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + while (len--) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + b = ao_cmd_lex_i; + ao_storage_write(addr, &b, 1); + addr++; + } +} + +void +ao_storage_zap(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); +} + +void +ao_storage_info(void) __reentrant +{ + printf("Storage size: %ld\n", ao_storage_total); + printf("Storage erase unit: %ld\n", ao_storage_block); + ao_storage_device_info(); +} + +__code struct ao_cmds ao_storage_cmds[] = { + { 'f', ao_storage_info, "f Show storage info" }, + { 'e', ao_storage_dump, "e Dump a block of flash data" }, + { 'w', ao_storage_store,"w ... Write data to flash" }, + { 'z', ao_storage_zap, "z Erase flash containing " }, + { 0, ao_storage_zap, NULL }, +}; + +void +ao_storage_init(void) +{ + ao_storage_device_init(); + ao_cmd_register(&ao_storage_cmds[0]); +} diff --git a/src/at45db161d.h b/src/at45db161d.h index 96042459..9ee6f1b6 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -29,6 +29,7 @@ #define FLASH_READ 0x03 #define FLASH_WRITE 0x82 +#define FLASH_PAGE_ERASE 0x81 #define FLASH_READ_STATUS 0xd7 #define FLASH_SET_CONFIG 0x3d diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs index a230203a..f38226c6 100644 --- a/src/telemetrum-v1.1/Makefile.defs +++ b/src/telemetrum-v1.1/Makefile.defs @@ -3,7 +3,7 @@ PROG = telemetrum-v1.1-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ $(SPI_DRIVER_SRC) \ - $(FLASH_DRIVER_SRC) \ + $(M25_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) -- cgit v1.2.3 From e991f52276248fa08d96fbecc458bc478e98d299 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 23:35:31 -0800 Subject: altos: Rip out 'optimization' in ao_log_scan Remove premature optimization to avoid re-scanning the flight logs for the best empty entry. Signed-off-by: Keith Packard --- src/ao_log.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) diff --git a/src/ao_log.c b/src/ao_log.c index 9ca033e1..00bb46d3 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -234,9 +234,10 @@ ao_log_flight(uint8_t slot) } static void -ao_log_scan(void) +ao_log_scan(void) __reentrant { uint8_t log_slot; + uint8_t log_slots; uint8_t log_avail = 0; uint16_t log_flight; @@ -244,7 +245,7 @@ ao_log_scan(void) ao_flight_number = 0; - /* Scan the log space looking for an empty one, and find the biggest flight number */ + /* Scan the log space looking for the biggest flight number */ log_slot = 0; { log_flight = ao_log_flight(log_slot); @@ -256,8 +257,9 @@ ao_log_scan(void) ao_flight_number = log_flight; } } else - log_avail |= 1 << log_slot; + log_avail = 1; } + log_slots = log_slot + 1; /* Now look through the log of flight numbers from erase operations and * see if the last one is bigger than what we found above @@ -279,25 +281,12 @@ ao_log_scan(void) * that we write logs to each spot about the same number of times. */ - /* If there are no log slots available, then - * do not log the next flight - */ - if (!log_avail) { - ao_log_current_pos = 0; - ao_log_end_pos = 0; - } else { - log_slot = ao_flight_number % log_slot; - while (!((log_avail & (1 << log_slot)))) { - if ((1 << log_slot) > log_avail) - log_slot = 0; - else - log_slot++; - } -// ao_log_current_pos = log_slot * ao_config.flight_log_max; -// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + /* Find a log slot for the next flight, if available */ + if (log_avail) { ao_log_current_pos = 0; ao_log_end_pos = ao_storage_config; - } + } else + ao_log_current_pos = ao_log_end_pos = 0; ao_wakeup(&ao_flight_number); } -- cgit v1.2.3 From 408a3e04362d626778640dd0ce7d356d3863de53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 23:38:13 -0800 Subject: altos: Mark end of available flight list with 'done' to make the UI code easier to write Signed-off-by: Keith Packard --- src/ao_log.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_log.c b/src/ao_log.c index 00bb46d3..21d0bc34 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -320,6 +320,7 @@ ao_log_list(void) __reentrant if (flight) printf ("Flight %d\n", flight); } + printf ("done\n"); } void -- cgit v1.2.3 From 3bcf14f12f6681888c3162d0f33ef2d454eb75dd Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 7 Jan 2011 00:52:50 -0700 Subject: update changelogs for Debian build --- ChangeLog | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 21 ++++++++ 2 files changed, 166 insertions(+) diff --git a/ChangeLog b/ChangeLog index c177e93d..6b4ac361 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,148 @@ +commit 408a3e04362d626778640dd0ce7d356d3863de53 +Author: Keith Packard +Date: Thu Jan 6 23:38:13 2011 -0800 + + altos: Mark end of available flight list with 'done' to make the UI + code easier to write + + Signed-off-by: Keith Packard + +commit e991f52276248fa08d96fbecc458bc478e98d299 +Author: Keith Packard +Date: Thu Jan 6 23:35:31 2011 -0800 + + altos: Rip out 'optimization' in ao_log_scan + + Remove premature optimization to avoid re-scanning the flight logs for + the best empty entry. + + Signed-off-by: Keith Packard + +commit 569a1dac55b70c30f01afa7bcb74442ecdd85d85 +Author: Keith Packard +Date: Thu Jan 6 22:37:38 2011 -0800 + + altos: Move common storage code to ao_storage.c. Add M25P80 driver + + This reworks the storage API so that you erase blocks and then store + data to them so that the M25P80 driver will work. + + Signed-off-by: Keith Packard + +commit e4ba9bf4291bf17c777c8c3ef7c71e4a30b9947a +Author: Keith Packard +Date: Thu Jan 6 17:34:58 2011 -0800 + + altos: Require manual flight erasing. + + This supports flash chips that require larger erase blocks. + + Signed-off-by: Keith Packard + +commit ddcc94da4326f9ce954bd31a46b36165c58e6c18 +Author: Keith Packard +Date: Thu Jan 6 12:51:39 2011 -0800 + + altos: Simplify storage API + + This removes the config-specific APIs and exposes global variables for + the available storage space, block size and config storage location. + + Signed-off-by: Keith Packard + +commit f3f1b1488bdc92fa9277dc549ba9f3210a8d4c8c +Author: Keith Packard +Date: Thu Jan 6 11:28:35 2011 -0800 + + altos: packet and usb i/o routines use 'char', not 'uint8_t' + + Just fixing the type of a local variable holding a character + passed from the packet link to usb. + + Signed-off-by: Keith Packard + +commit 5688af4e4d7ca8e559d758257e79b7979f1cc924 +Author: Keith Packard +Date: Wed Dec 22 21:13:56 2010 -0800 + + altos: Add telemetrum-v1.1 directory + + This just clones the v1.0 build; changes will be added on top of this. + + Signed-off-by: Keith Packard + +commit 9f7296b3feab872bf51fc369ade69cc1e7cf7a3f +Author: Keith Packard +Date: Wed Dec 22 21:06:22 2010 -0800 + + altos: Split out SPI driver. + + For TM with the companion connector, the SPI bus will be shared among + multiple devices. Split out the existing SPI code into a common + driver, with the SPI bus protected by a mutex. + + Signed-off-by: Keith Packard + +commit 51c410c1c952e0e9bcf1b2c438813de63753be5f +Author: Keith Packard +Date: Sun Nov 28 00:24:54 2010 -0800 + + windows: Update NSIS installer file to use compatibility IDs + + This allows the file to contain a single InitDriverSetup function, + making things shorter and (I hope) clearer. + +commit 4a42f9d5c20dcaf5fd7591ccf9e32c6130d9d538 +Author: Keith Packard +Date: Sun Nov 28 00:22:14 2010 -0800 + + windows: Add compatibility IDs to telemetrum.inf + + This will allow the .nsi file to reference just the compatibility ID + instead of needing to have all of the USB IDs listed. + + Signed-off-by: Keith Packard + +commit 484b44e81b655f1ecb48256095382a56d2839bae +Author: Keith Packard +Date: Fri Nov 26 17:39:40 2010 -0800 + + altos: eliminate ao_wake_task + + Waking up a task waiting on some random object is a bad idea. Fix + the waiters to look for suitable signalling. + + Signed-off-by: Keith Packard + +commit 07213dc34fa20470a4b36a327a83d75b0f010ebb +Author: Keith Packard +Date: Fri Nov 26 16:14:15 2010 -0800 + + altos: clean up radio abort paths. Share radio code. + + Instead of aborting the DMA and radio operation and expecting that to + be handled reasonably by the radio receiving task, rewrite things so + that the abort function just wakes the receiving task while that + terminates the DMA and cleans up the radio. + + This eliminates all kinds of nasty bugs dealing with radio abort + smashing the radio registers at the wrong time, or interrupting a + radio transmission. + + Signed-off-by: Keith Packard + +commit b62580855c5144f5bc7e0172289bce08814d9472 +Author: Anthony Towns +Date: Tue Dec 14 03:40:18 2010 +1000 + + altosui: move maps to subdir, fix E/W mismatch + +commit b8d2eb5509096fd5bd04598b1312077659109620 +Author: Bdale Garbee +Date: Wed Dec 1 00:15:17 2010 -0700 + + update changelogs for Debian build + commit ea95c060f8bd959cefc60dd6d411151f3c91384e Author: Bdale Garbee Date: Wed Dec 1 00:12:05 2010 -0700 diff --git a/debian/changelog b/debian/changelog index 7b1be3a9..cf13a14b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,24 @@ +altos (0.8.1+18+g408a3e0) unstable; urgency=low + + [ Anthony Towns ] + * altosui: move maps to subdir, fix E/W mismatch + + [ Keith Packard ] + * altos: clean up radio abort paths. Share radio code. + * altos: eliminate ao_wake_task + * windows: Add compatibility IDs to telemetrum.inf + * windows: Update NSIS installer file to use compatibility IDs + * altos: Split out SPI driver. + * altos: Add telemetrum-v1.1 directory + * altos: packet and usb i/o routines use 'char', not 'uint8_t' + * altos: Simplify storage API + * altos: Require manual flight erasing. + * altos: Move common storage code to ao_storage.c. Add M25P80 driver + * altos: Rip out 'optimization' in ao_log_scan + * altos: Mark end of available flight list with 'done' to make the UI + + -- Bdale Garbee Fri, 07 Jan 2011 00:51:41 -0700 + altos (0.8.1+4+gea95c06) unstable; urgency=low * fix symlink paths in rules file -- cgit v1.2.3 From a9b210bc33cd95e7108ab51925fdf0d5e8deaf7e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 10:05:11 -0800 Subject: altos: Add configuration parameter for maximum flight log size This parameter will permit available storage to be split into multiple separate flight logs. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_config.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index e1306c79..a5890d47 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1002,7 +1002,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 3 +#define AO_CONFIG_MINOR 4 struct ao_config { uint8_t major; @@ -1014,6 +1014,7 @@ struct ao_config { uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ uint32_t radio_cal; /* minor version 3 */ + uint32_t flight_log_max; /* minor version 4 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 38b72798..ebfb0386 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 256 * (uint32_t) 1024) #if HAS_EEPROM static void @@ -83,6 +84,9 @@ _ao_config_get(void) /* Fixups for minor version 3 */ if (ao_config.minor < 3) ao_config.radio_cal = ao_radio_cal; + /* Fixups for minor version 4 */ + if (ao_config.minor < 4) + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -291,6 +295,30 @@ ao_config_radio_cal_set(void) __reentrant ao_config_radio_cal_show(); } +#if HAS_EEPROM +void +ao_config_log_show(void) __reentrant +{ + printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +} + +void +ao_config_log_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) + printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); + ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); +} +#endif /* HAS_EEPROM */ + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -324,6 +352,10 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ADC */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, +#if HAS_EEPROM + { 'l', ao_config_log_set, ao_config_log_show, + "l Set flight log size in kB" }, +#endif { 's', ao_config_show, ao_config_show, "s Show current config values" }, #if HAS_EEPROM -- cgit v1.2.3 From 2722703bd848b07a02d3ce0c83a502eca52a9f1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 14:58:39 -0800 Subject: altos: support storage of multiple flights. This adds the logging support for dealing with multiple flights Signed-off-by: Keith Packard --- src/ao.h | 4 ++ src/ao_config.c | 20 ++++++---- src/ao_log.c | 120 +++++++++++++++++++++++++++++++------------------------ src/ao_storage.c | 24 ++++++++++- 4 files changed, 105 insertions(+), 63 deletions(-) diff --git a/src/ao.h b/src/ao.h index a5890d47..ad02a829 100644 --- a/src/ao.h +++ b/src/ao.h @@ -624,6 +624,10 @@ ao_log_init(void); void ao_log_write_erase(uint8_t pos); +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + /* * ao_flight.c */ diff --git a/src/ao_config.c b/src/ao_config.c index ebfb0386..a3e0a64f 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,7 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 256 * (uint32_t) 1024) +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #if HAS_EEPROM static void @@ -308,14 +308,18 @@ ao_config_log_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); - if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) + if (ao_log_present()) + printf("Storage must be empty before changing log size\n"); + else if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); - ao_config.flight_log_max = ao_cmd_lex_u32 << 10; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + else { + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); + } } #endif /* HAS_EEPROM */ diff --git a/src/ao_log.c b/src/ao_log.c index 21d0bc34..47f24f01 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -85,10 +85,6 @@ ao_log(void) { ao_storage_setup(); - /* For now, use all of the available space */ - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - ao_log_scan(); while (!ao_log_running) @@ -200,66 +196,64 @@ ao_log_erase_mark(void) ao_config_put(); } -static void -ao_log_erase(uint8_t pos) +static uint8_t +ao_log_slots() { - ao_config_get(); - (void) pos; -// ao_log_current_pos = pos * ao_config.flight_log_max; -// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; -// if (ao_log_end_pos > ao_storage_config) -// return; - - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - - while (ao_log_current_pos < ao_log_end_pos) { - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; - } + return (uint8_t) (ao_storage_config / ao_config.flight_log_max); +} + +static uint32_t +ao_log_pos(uint8_t slot) +{ + return ((slot) * ao_config.flight_log_max); } static uint16_t ao_log_flight(uint8_t slot) { - (void) slot; - if (!ao_storage_read(0, + if (!ao_storage_read(ao_log_pos(slot), &log, sizeof (struct ao_log_record))) - ao_panic(AO_PANIC_LOG); + return 0; if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) return log.u.flight.flight; return 0; } -static void -ao_log_scan(void) __reentrant +static uint16_t +ao_log_max_flight(void) { uint8_t log_slot; uint8_t log_slots; - uint8_t log_avail = 0; uint16_t log_flight; - - ao_config_get(); - - ao_flight_number = 0; + uint16_t max_flight = 0; /* Scan the log space looking for the biggest flight number */ - log_slot = 0; - { + log_slots = ao_log_slots(); + for (log_slot = 0; log_slot < log_slots; log_slot++) { log_flight = ao_log_flight(log_slot); - if (log_flight) { - if (++log_flight == 0) - log_flight = 1; - if (ao_flight_number == 0 || - (int16_t) (log_flight - ao_flight_number) > 0) { - ao_flight_number = log_flight; - } - } else - log_avail = 1; + if (!log_flight) + continue; + if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) + max_flight = log_flight; } - log_slots = log_slot + 1; + return max_flight; +} + +static void +ao_log_scan(void) __reentrant +{ + uint8_t log_slot; + uint8_t log_slots; + uint8_t log_want; + + ao_config_get(); + + ao_flight_number = ao_log_max_flight(); + if (ao_flight_number) + if (++ao_flight_number == 0) + ao_flight_number = 1; /* Now look through the log of flight numbers from erase operations and * see if the last one is bigger than what we found above @@ -282,11 +276,19 @@ ao_log_scan(void) __reentrant */ /* Find a log slot for the next flight, if available */ - if (log_avail) { - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - } else - ao_log_current_pos = ao_log_end_pos = 0; + ao_log_current_pos = ao_log_end_pos = 0; + log_slots = ao_log_slots(); + log_want = (ao_flight_number - 1) % log_slots; + log_slot = log_want; + do { + if (ao_log_flight(log_slot) == 0) { + ao_log_current_pos = ao_log_pos(log_slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + break; + } + if (++log_slot >= log_slots) + log_slot = 0; + } while (log_slot != log_want); ao_wakeup(&ao_flight_number); } @@ -306,19 +308,28 @@ ao_log_stop(void) ao_log_flush(); } +uint8_t +ao_log_present(void) +{ + return ao_log_max_flight() != 0; +} + static __xdata struct ao_task ao_log_task; void ao_log_list(void) __reentrant { uint8_t slot; + uint8_t slots; uint16_t flight; - slot = 0; + slots = ao_log_slots(); + for (slot = 0; slot < slots; slot++) { flight = ao_log_flight(slot); if (flight) - printf ("Flight %d\n", flight); + printf ("flight %d start %ld end %ld\n", + flight, ao_log_pos(slot), ao_log_pos(slot+1)); } printf ("done\n"); } @@ -327,15 +338,18 @@ void ao_log_delete(void) __reentrant { uint8_t slot; + uint8_t slots; + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - slot = 0; + + slots = ao_log_slots(); /* Look for the flight log matching the requested flight */ - { + for (slot = 0; slot < slots; slot++) { if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { /* * Check to see if we've reached the end of diff --git a/src/ao_storage.c b/src/ao_storage.c index 25a7c8b9..c4beedd2 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -103,6 +103,10 @@ ao_storage_dump(void) __reentrant } } +#if 0 + +/* not enough space for this today + */ static void ao_storage_store(void) __reentrant { @@ -130,6 +134,7 @@ ao_storage_store(void) __reentrant addr++; } } +#endif void ao_storage_zap(void) __reentrant @@ -140,6 +145,18 @@ ao_storage_zap(void) __reentrant ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); } +void +ao_storage_zapall(void) __reentrant +{ + uint32_t pos; + + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + ao_storage_erase(pos); +} + void ao_storage_info(void) __reentrant { @@ -151,8 +168,11 @@ ao_storage_info(void) __reentrant __code struct ao_cmds ao_storage_cmds[] = { { 'f', ao_storage_info, "f Show storage info" }, { 'e', ao_storage_dump, "e Dump a block of flash data" }, - { 'w', ao_storage_store,"w ... Write data to flash" }, - { 'z', ao_storage_zap, "z Erase flash containing " }, +#if 0 + { 'w', ao_storage_store, "w ... Write data to flash" }, + #endif + { 'z', ao_storage_zap, "z Erase flash containing " }, + { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, { 0, ao_storage_zap, NULL }, }; -- cgit v1.2.3 From d8c9684239b67a69a4a3d24202a6df0d73c4f7f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:54:54 -0800 Subject: altos: Speed up at45 and 25lc erase speeds No need to read the block to be erased before erasing it. Signed-off-by: Keith Packard --- src/ao_ee.c | 9 +++++---- src/ao_flash.c | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ao_ee.c b/src/ao_ee.c index 7de05b7b..e3b41103 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -19,6 +19,7 @@ #include "25lc1024.h" #define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_BLOCK_SHIFT 8 #define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) /* Total bytes of available storage */ @@ -166,7 +167,7 @@ ao_ee_fill(uint16_t block) uint8_t ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block = (uint16_t) (pos >> 8); + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { @@ -185,7 +186,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra uint8_t ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block = (uint16_t) (pos >> 8); + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { @@ -207,8 +208,8 @@ uint8_t ao_storage_erase(uint32_t pos) __reentrant { ao_mutex_get(&ao_ee_mutex); { - uint16_t block = (uint16_t) (pos >> 8); - ao_ee_fill(block); + ao_ee_flush_internal(); + ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); diff --git a/src/ao_flash.c b/src/ao_flash.c index 1201a0e5..3a264ceb 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -289,10 +289,9 @@ ao_storage_flush(void) __reentrant uint8_t ao_storage_erase(uint32_t pos) __reentrant { - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); + ao_flash_flush_internal(); + ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); memset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; } ao_mutex_put(&ao_flash_mutex); -- cgit v1.2.3 From 1cc08af4f4a1ff61fc0deca3bdd95e8a5ca8ec5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:55:54 -0800 Subject: altos: white space fix Signed-off-by: Keith Packard --- src/ao_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_storage.c b/src/ao_storage.c index c4beedd2..c51bec4a 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -170,7 +170,7 @@ __code struct ao_cmds ao_storage_cmds[] = { { 'e', ao_storage_dump, "e Dump a block of flash data" }, #if 0 { 'w', ao_storage_store, "w ... Write data to flash" }, - #endif +#endif { 'z', ao_storage_zap, "z Erase flash containing " }, { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, { 0, ao_storage_zap, NULL }, -- cgit v1.2.3 From edd22ee49adf60c35f2fe6ba97c111b7ad4131c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:56:06 -0800 Subject: altos: report flight log offsets in hex block numbers instead of bytes makes them compatible with the 'e' command. Signed-off-by: Keith Packard --- src/ao_log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ao_log.c b/src/ao_log.c index 47f24f01..f319834a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -328,8 +328,10 @@ ao_log_list(void) __reentrant { flight = ao_log_flight(slot); if (flight) - printf ("flight %d start %ld end %ld\n", - flight, ao_log_pos(slot), ao_log_pos(slot+1)); + printf ("flight %d start %x end %x\n", + flight, + (uint16_t) (ao_log_pos(slot) >> 8), + (uint16_t) (ao_log_pos(slot+1) >> 8)); } printf ("done\n"); } -- cgit v1.2.3 From 73620c41017c1774d6190dfd4be5b742eb64f8d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:13:28 -0800 Subject: altos: ensure erase mark is written when erasing flights It was getting called only when *failing* to erase a flight (oops), secondly, it wasn't getting written because ao_storage_flush wasn't getting called. Signed-off-by: Keith Packard --- src/ao_log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ao_log.c b/src/ao_log.c index f319834a..55b9dfff 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -170,6 +170,7 @@ ao_log_write_erase(uint8_t pos) erase.unused = 0x00; erase.flight = ao_flight_number; ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_storage_flush(); } static void @@ -350,6 +351,7 @@ ao_log_delete(void) __reentrant /* Look for the flight log matching the requested flight */ for (slot = 0; slot < slots; slot++) { if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); ao_log_current_pos = ao_log_pos(slot); ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { @@ -374,7 +376,6 @@ ao_log_delete(void) __reentrant return; } } - ao_log_erase_mark(); printf("No such flight: %d\n", ao_cmd_lex_i); } -- cgit v1.2.3 From bbddcae2a15b6d430e84956ddf26955aa9173cc0 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 20:18:25 -0800 Subject: altos: Optimize Morse code generation This reduces the size of data and code needed to report the flight states Signed-off-by: Keith Packard --- src/ao_report.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/src/ao_report.c b/src/ao_report.c index 3b469de6..511b4f16 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -17,17 +17,24 @@ #include "ao.h" -static const char * __xdata flight_reports[] = { - "...", /* startup, 'S' */ - "..", /* idle 'I' */ - ".--.", /* pad 'P' */ - "-...", /* boost 'B' */ - "..-.", /* fast 'F' */ - "-.-.", /* coast 'C' */ - "-..", /* drogue 'D' */ - "--", /* main 'M' */ - ".-..", /* landed 'L' */ - ".-.-.-", /* invalid */ +#define BIT(i,x) ((x) ? (1 << (i)) : 0) +#define MORSE1(a) (1 | BIT(3,a)) +#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) +#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) +#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) +#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) + +static const uint8_t flight_reports[] = { + MORSE3(0,0,0), /* startup, 'S' */ + MORSE2(0,0), /* idle 'I' */ + MORSE4(0,1,1,0), /* pad 'P' */ + MORSE4(1,0,0,0), /* boost 'B' */ + MORSE4(0,0,1,0), /* fast 'F' */ + MORSE4(1,0,1,0), /* coast 'C' */ + MORSE3(1,0,0), /* drogue 'D' */ + MORSE2(1,1), /* main 'M' */ + MORSE4(0,1,0,0), /* landed 'L' */ + MORSE4(1,0,0,1), /* invalid 'X' */ }; #if 1 @@ -42,17 +49,18 @@ static __xdata enum ao_flight_state ao_report_state; static void ao_report_beep(void) __reentrant { - char *r = flight_reports[ao_flight_state]; - char c; + uint8_t r = flight_reports[ao_flight_state]; + uint8_t l = r & 7; if (!r) return; - while (c = *r++) { - if (c == '.') - signal(AO_MS_TO_TICKS(200)); - else + while (l--) { + if (r & 8) signal(AO_MS_TO_TICKS(600)); + else + signal(AO_MS_TO_TICKS(200)); pause(AO_MS_TO_TICKS(200)); + r >>= 1; } pause(AO_MS_TO_TICKS(400)); } -- cgit v1.2.3 From 00891b40754962ef6530b237ef52017bb58112d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:25:09 -0800 Subject: altos: Check requested log max size against available space Make sure the amount of memory requested for a single log isn't more than is available on the device. Signed-off-by: Keith Packard --- src/ao_config.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index a3e0a64f..e97b7eb1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -305,17 +305,22 @@ ao_config_log_show(void) __reentrant void ao_config_log_set(void) __reentrant { + uint16_t block = (uint16_t) (ao_storage_block >> 10); + uint16_t config = (uint16_t) (ao_storage_config >> 10); + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; if (ao_log_present()) printf("Storage must be empty before changing log size\n"); - else if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) - printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); + else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) + printf("Flight log size must be multiple of %d kB\n", block); + else if (ao_cmd_lex_i > config) + printf("Flight log max %d kB\n", config); else { ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_log_show(); -- cgit v1.2.3 From 52ac83fedbfd380d14d4df2e79992bbdfba3552a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:26:39 -0800 Subject: altos: Check for full log and complain Reports special tone along with the continuity checks. Reports flight 0 in telemetry. Signed-off-by: Keith Packard --- src/ao.h | 4 ++++ src/ao_log.c | 6 ++++++ src/ao_report.c | 10 ++++++++++ src/ao_telemetry.c | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index ad02a829..37a39a79 100644 --- a/src/ao.h +++ b/src/ao.h @@ -628,6 +628,10 @@ ao_log_write_erase(uint8_t pos); uint8_t ao_log_present(void); +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + /* * ao_flight.c */ diff --git a/src/ao_log.c b/src/ao_log.c index 55b9dfff..ba019992 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -315,6 +315,12 @@ ao_log_present(void) return ao_log_max_flight() != 0; } +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos == ao_log_end_pos; +} + static __xdata struct ao_task ao_log_task; void diff --git a/src/ao_report.c b/src/ao_report.c index 511b4f16..cc8b512b 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -128,6 +128,16 @@ ao_report_continuity(void) __reentrant ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); } } + if (ao_log_full()) { + pause(AO_MS_TO_TICKS(100)); + c = 2; + while (c--) { + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + } + } c = 50; while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 277c3ce0..22ab1d67 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -34,7 +34,7 @@ ao_telemetry(void) ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; - telemetry.flight = ao_flight_number; + telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); -- cgit v1.2.3 From ca66f86a899c191b6362a334417fc84a79349677 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:46:29 -0800 Subject: altosui: Add configuration of flight log size This adds to the TeleMetrum configuration UI the ability to set the maximum flight log size. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 7 ++++++ altosui/AltosConfigUI.java | 53 ++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 38e1484e..47de6156 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -69,6 +69,7 @@ public class AltosConfig implements ActionListener { int_ref apogee_delay; int_ref radio_channel; int_ref radio_calibration; + int_ref flight_log_max; string_ref version; string_ref product; string_ref callsign; @@ -138,6 +139,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Apogee delay:", apogee_delay); get_int(line, "Radio channel:", radio_channel); get_int(line, "Radio cal:", radio_calibration); + get_int(line, "Max flight log:", flight_log_max); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -181,6 +183,7 @@ public class AltosConfig implements ActionListener { config_ui.set_apogee_delay(apogee_delay.get()); config_ui.set_radio_channel(radio_channel.get()); config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); } @@ -193,6 +196,7 @@ public class AltosConfig implements ActionListener { apogee_delay.set(config_ui.apogee_delay()); radio_channel.set(config_ui.radio_channel()); radio_calibration.set(config_ui.radio_calibration()); + flight_log_max.set(config_ui.flight_log_max()); callsign.set(config_ui.callsign()); try { start_serial(); @@ -203,6 +207,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c f %d\n", radio_calibration.get()); } serial_line.printf("c c %s\n", callsign.get()); + if (flight_log_max.get() != 0) + serial_line.printf("c l %d\n", flight_log_max.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { } finally { @@ -248,6 +254,7 @@ public class AltosConfig implements ActionListener { apogee_delay = new int_ref(0); radio_channel = new int_ref(0); radio_calibration = new int_ref(1186611); + flight_log_max = new int_ref(0); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index cfa5d7b9..e09eab25 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -45,6 +45,7 @@ public class AltosConfigUI JLabel apogee_delay_label; JLabel radio_channel_label; JLabel radio_calibration_label; + JLabel flight_log_max_label; JLabel callsign_label; public boolean dirty; @@ -57,6 +58,7 @@ public class AltosConfigUI JComboBox apogee_delay_value; JComboBox radio_channel_value; JTextField radio_calibration_value; + JComboBox flight_log_max_value; JTextField callsign_value; JButton save; @@ -75,6 +77,12 @@ public class AltosConfigUI "0", "1", "2", "3", "4", "5" }; + static String[] flight_log_max_values = { + "64", "128", "192", "256", "320", + "384", "448", "512", "576", "640", + "704", "768", "832", "896", "960", + }; + static String[] radio_channel_values = new String[10]; { for (int i = 0; i <= 9; i++) @@ -296,9 +304,33 @@ public class AltosConfigUI callsign_value.getDocument().addDocumentListener(this); pane.add(callsign_value, c); - /* Buttons */ + /* Flight log max */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 8; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + flight_log_max_label = new JLabel("Maximum Flight Log Size:"); + pane.add(flight_log_max_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 8; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + flight_log_max_value = new JComboBox(flight_log_max_values); + flight_log_max_value.setEditable(true); + flight_log_max_value.addItemListener(this); + pane.add(flight_log_max_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 9; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -309,7 +341,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 8; + c.gridx = 2; c.gridy = 9; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -320,7 +352,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 8; + c.gridx = 4; c.gridy = 9; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -331,7 +363,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 8; + c.gridx = 6; c.gridy = 9; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -459,8 +491,17 @@ public class AltosConfigUI return callsign_value.getText(); } + public void set_flight_log_max(int new_flight_log_max) { + if (new_flight_log_max == 0) + flight_log_max_value.setEnabled(false); + flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max)); + } + + public int flight_log_max() { + return Integer.parseInt(flight_log_max_value.getSelectedItem().toString()); + } + public void set_clean() { dirty = false; } - - } \ No newline at end of file +} -- cgit v1.2.3 From 57de960b8148bf485607898c3d66af6994d76481 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 20:52:33 -0800 Subject: altos: Remove unused accel_vel_mach and accel_vel_boost variables Presumably left-over debugging code. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 980c16be..5567d87f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -84,9 +84,6 @@ __xdata uint8_t ao_flight_force_idle; #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) -int32_t accel_vel_mach; -int32_t accel_vel_boost; - /* * Barometer calibration * @@ -214,8 +211,6 @@ ao_flight(void) ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - accel_vel_mach = ACCEL_VEL_MACH; - accel_vel_boost = ACCEL_VEL_BOOST; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; -- cgit v1.2.3 From c437b14b7fc7afdfc7b809a04d7fa29d5e742307 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 21:00:10 -0800 Subject: altos: Remove redundant initialization of ao_interval variables These are all initialized in the ao_flight_drogue state transition. Signed-off-by: Keith Packard --- src/ao_flight.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 5567d87f..7fe85cb1 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -463,11 +463,5 @@ void ao_flight_init(void) { ao_flight_state = ao_flight_startup; - ao_interval_min_accel = 0; - ao_interval_max_accel = 0x7fff; - ao_interval_min_pres = 0; - ao_interval_max_pres = 0x7fff; - ao_interval_end = AO_INTERVAL_TICKS; - ao_add_task(&flight_task, ao_flight, "flight"); } -- cgit v1.2.3 From bd2480fd757b67557d9c7de42e402034002c3e37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Jan 2011 15:39:24 -0800 Subject: altosui: Split eeprom download code apart Create separate 'download config data', 'read single record' and 'read block' functions. This code will be shared with future multi-log reading code for new firmware. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 109 +++++++++++++++++++ altosui/AltosEepromBlock.java | 82 ++++++++++++++ altosui/AltosEepromDownload.java | 230 ++++++++++++++------------------------- altosui/AltosEepromRecord.java | 47 +++++++- altosui/Makefile.am | 2 + 5 files changed, 318 insertions(+), 152 deletions(-) create mode 100644 altosui/AltosConfigData.java create mode 100644 altosui/AltosEepromBlock.java diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java new file mode 100644 index 00000000..8c32ed86 --- /dev/null +++ b/altosui/AltosConfigData.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosConfigData implements Iterable { + + /* Version information */ + String manufacturer; + String product; + String version; + int serial; + + /* Strings returned */ + LinkedList lines; + + /* Config information */ + int config_major; + int config_minor; + int main_deploy; + int apogee_delay; + int radio_channel; + String callsign; + int accel_cal_plus, accel_cal_minus; + int radio_calibration; + int flight_log_max; + + + static String get_string(String line, String label) throws ParseException { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + return quoted; + } + throw new ParseException("mismatch", 0); + } + + static int get_int(String line, String label) throws NumberFormatException, ParseException { + if (line.startsWith(label)) { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) + return Integer.parseInt(tokens[0]); + } + throw new ParseException("mismatch", 0); + } + + public Iterator iterator() { + return lines.iterator(); + } + + public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { + serial_line.printf("c s\nv\n"); + lines = new LinkedList(); + for (;;) { + String line = serial_line.get_reply(5000); + if (line == null) + throw new TimeoutException(); + if (line.contains("Syntax error")) + continue; + lines.add(line); + try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} + try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} + try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} + try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} + try { version = get_string(line,"software-version"); } catch (Exception e) {} + try { product = get_string(line,"product"); } catch (Exception e) {} + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + } + +} \ No newline at end of file diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java new file mode 100644 index 00000000..0c1a4a92 --- /dev/null +++ b/altosui/AltosEepromBlock.java @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; +import java.lang.reflect.Array; + +import libaltosJNI.*; + +public class AltosEepromBlock extends ArrayList { + boolean has_flight; + int flight; + boolean has_state; + int state; + boolean has_date; + int year, month, day; + + public AltosEepromBlock (AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { + int addr; + boolean done = false; + + has_flight = false; + has_state = false; + has_date = false; + serial_line.printf("e %x\n", block); + for (addr = 0; !done && addr < 0x100;) { + try { + AltosEepromRecord r = new AltosEepromRecord(serial_line, block * 256 + addr); + + if (r.cmd == Altos.AO_LOG_FLIGHT) { + flight = r.b; + has_flight = true; + } + + /* Monitor state transitions to update display */ + if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { + if (!has_state || r.a > state) { + state = r.a; + has_state = true; + } + } + + if (r.cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + has_date = true; + } + + if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) + done = true; + add(addr / 8, r); + } catch (ParseException pe) { + } + addr += 8; + } + } +} \ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index e5ff766c..9a748710 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -32,182 +32,105 @@ import libaltosJNI.*; public class AltosEepromDownload implements Runnable { - static final String[] state_names = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - int checksum(int[] line) { - int csum = 0x5a; - for (int i = 1; i < line.length; i++) - csum += line[i]; - return csum & 0xff; - } - - void FlushPending(FileWriter file, LinkedList pending) throws IOException { - while (!pending.isEmpty()) { - file.write(pending.remove()); - } - } - JFrame frame; AltosDevice device; AltosSerial serial_line; boolean remote; Thread eeprom_thread; AltosEepromMonitor monitor; + int serial = 0; + int flight = 0; + int year = 0, month = 0, day = 0; + boolean want_file = false; + FileWriter eeprom_file = null; + LinkedList eeprom_pending = new LinkedList(); + AltosConfigData config_data; + + private void FlushPending() throws IOException { + for (String s : config_data) { + eeprom_file.write(s); + eeprom_file.write('\n'); + } - void CaptureLog() throws IOException, InterruptedException, TimeoutException { - int serial = 0; - int block, state_block = 0; - int addr; - int flight = 0; - int year = 0, month = 0, day = 0; - int state = 0; - boolean done = false; - boolean want_file = false; - boolean any_valid; - FileWriter eeprom_file = null; - AltosFile eeprom_name; - LinkedList eeprom_pending = new LinkedList(); - - serial_line.printf("\nc s\nv\n"); - - /* Pull the serial number out of the version information */ + for (String s : eeprom_pending) + eeprom_file.write(s); + } - for (;;) { - String line = serial_line.get_reply(5000); + private void CheckFile(boolean force) throws IOException { + if (eeprom_file != null) + return; + if (force || (flight != 0 && want_file)) { + AltosFile eeprom_name; + if (year != 0 && month != 0 && day != 0) + eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); + else + eeprom_name = new AltosFile(serial, flight, "eeprom"); - if (line == null) - throw new TimeoutException(); - if (line.startsWith("serial-number")) { - try { - serial = Integer.parseInt(line.substring(13).trim()); - } catch (NumberFormatException ne) { - serial = 0; - } + eeprom_file = new FileWriter(eeprom_name); + if (eeprom_file != null) { + monitor.set_file(eeprom_name.getName()); + FlushPending(); + eeprom_pending = null; } + } + } - eeprom_pending.add(String.format("%s\n", line)); + void CaptureLog(int start_block, int end_block) throws IOException, InterruptedException, TimeoutException { + int block, state_block = 0; + int state = 0; + boolean done = false; + int record; - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } + config_data = new AltosConfigData(serial_line); + serial = config_data.serial; if (serial == 0) throw new IOException("no serial number found"); monitor.set_serial(serial); /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - state = 0; state_block = 0; - for (block = 0; !done && block < 511; block++) { - serial_line.printf("e %x\n", block); - any_valid = false; - monitor.set_value(state_names[state], state, block - state_block); - for (addr = 0; addr < 0x100;) { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - int[] values = ParseHex(line); - - 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]); - } else if (checksum(values) != 0) { - System.out.printf("invalid checksum at 0x%x\n", - block * 256 + values[0]); - } else { - any_valid = true; - int cmd = values[1]; - int tick = values[3] + (values[4] << 8); - int a = values[5] + (values[6] << 8); - int b = values[7] + (values[8] << 8); + state = 0; state_block = start_block; + for (block = start_block; !done && block < end_block; block++) { + monitor.set_value(Altos.state_to_string[state], state, block - state_block); - if (cmd == Altos.AO_LOG_FLIGHT) { - flight = b; - monitor.set_flight(flight); - } - - /* Monitor state transitions to update display */ - if (cmd == Altos.AO_LOG_STATE && a <= Altos.ao_flight_landed) { - if (a > Altos.ao_flight_pad) - want_file = true; - if (a > state) - state_block = block; - state = a; - } + AltosEepromBlock eeblock = new AltosEepromBlock(serial_line, block); + if (eeblock.has_flight) { + flight = eeblock.flight; + monitor.set_flight(flight); + } + if (eeblock.has_date) { + year = eeblock.year; + month = eeblock.month; + day = eeblock.day; + want_file = true; + } - if (cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (a & 0xff); - month = (a >> 8) & 0xff; - day = (b & 0xff); - want_file = true; - } + if (eeblock.size() == 0 || + eeblock.has_state && eeblock.state == Altos.ao_flight_landed) + done = true; - if (eeprom_file == null) { - if (serial != 0 && flight != 0 && want_file) { - if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); - else - eeprom_name = new AltosFile(serial, flight, "eeprom"); + /* Monitor state transitions to update display */ + if (eeblock.has_state) { + if (eeblock.state > Altos.ao_flight_pad) + want_file = true; + if (eeblock.state > state) + state = eeblock.state; + } - monitor.set_file(eeprom_name.getName()); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); - eeprom_pending = null; - } - } - } + CheckFile(true); - String log_line = String.format("%c %4x %4x %4x\n", - cmd, tick, a, b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); + for (record = 0; record < eeblock.size(); record++) { + AltosEepromRecord r = eeblock.get(record); - if (cmd == Altos.AO_LOG_STATE && a == Altos.ao_flight_landed) { - done = true; - } - } - addr += 8; - } - if (!any_valid) - done = true; - } - if (eeprom_file == null) { - eeprom_name = new AltosFile(serial,flight,"eeprom"); - eeprom_file = new FileWriter(eeprom_name); - if (eeprom_file != null) { - FlushPending(eeprom_file, eeprom_pending); + String log_line = String.format("%c %4x %4x %4x\n", + r.cmd, r.tick, r.a, r.b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); } } + CheckFile(true); if (eeprom_file != null) { eeprom_file.flush(); eeprom_file.close(); @@ -235,6 +158,8 @@ public class AltosEepromDownload implements Runnable { SwingUtilities.invokeLater(r); } + int start_block, end_block; + public void run () { if (remote) { serial_line.set_radio(); @@ -243,7 +168,7 @@ public class AltosEepromDownload implements Runnable { } try { - CaptureLog(); + CaptureLog(start_block, end_block); } catch (IOException ee) { show_error (device.toShortString(), ee.getLocalizedMessage()); @@ -271,6 +196,7 @@ public class AltosEepromDownload implements Runnable { serial_line = new AltosSerial(device); if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); monitor.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -280,6 +206,8 @@ public class AltosEepromDownload implements Runnable { }); eeprom_thread = new Thread(this); + start_block = 0; + end_block = 0xfff; eeprom_thread.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 5a673817..e61a7159 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -26,7 +26,9 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; + +import libaltosJNI.*; public class AltosEepromRecord { public int cmd; @@ -36,6 +38,49 @@ public class AltosEepromRecord { public String data; public boolean tick_valid; + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + int checksum(int[] line) { + int csum = 0x5a; + for (int i = 1; i < line.length; i++) + csum += line[i]; + return csum & 0xff; + } + + public AltosEepromRecord (AltosSerial serial_line, int addr) + throws TimeoutException, ParseException, InterruptedException { + String line = serial_line.get_reply(5000); + if (line == null) + throw new TimeoutException(); + int[] values = ParseHex(line); + + if (values == null) + throw new ParseException(String.format("invalid line %s", line), 0); + if (values[0] != (addr & 0xff)) + throw new ParseException(String.format("data address out of sync at 0x%x", + addr), 0); + if (checksum(values) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", addr), 0); + + cmd = values[1]; + tick = values[3] + (values[4] << 8); + a = values[5] + (values[6] << 8); + b = values[7] + (values[8] << 8); + data = null; + tick_valid = true; + } + public AltosEepromRecord (String line) { tick_valid = false; tick = 0; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e2ff55af..8cdd64cc 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -15,6 +15,7 @@ altosui_JAVA = \ AltosAscent.java \ AltosChannelMenu.java \ AltosConfig.java \ + AltosConfigData.java \ AltosConfigUI.java \ AltosConfigureUI.java \ AltosConvert.java \ @@ -26,6 +27,7 @@ altosui_JAVA = \ AltosDeviceDialog.java \ AltosDevice.java \ AltosDisplayThread.java \ + AltosEepromBlock.java \ AltosEepromDownload.java \ AltosEepromMonitor.java \ AltosEepromIterable.java \ -- cgit v1.2.3 From 7ad419d81c90ef6a16656970466313767fef830f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Jan 2011 21:26:41 -0800 Subject: altos: oops -- 'e' command was only showing 7 of the 8 bytes per line Just a silly off-by-one error when printing out the data received from flash. Signed-off-by: Keith Packard --- src/ao_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_storage.c b/src/ao_storage.c index c51bec4a..709259ee 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -92,7 +92,7 @@ ao_storage_dump(void) __reentrant storage_data, 8)) { ao_cmd_put16((uint16_t) i); - for (j = 0; j < 7; j++) { + for (j = 0; j < 8; j++) { putchar(' '); ao_cmd_put8(storage_data[j]); } -- cgit v1.2.3 From 440d52e34364fdeeddc76a2d744cc6d1c934364f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Jan 2011 21:28:07 -0800 Subject: altosui: Add support for parsing list of flights from the 'l' command This adds parsing support to enumerate the available flights, but does not yet provide any UI to use it. Signed-off-by: Keith Packard --- altosui/AltosEepromBlock.java | 24 ++++++++- altosui/AltosEepromDownload.java | 13 ++--- altosui/AltosEepromList.java | 103 +++++++++++++++++++++++++++++++++++++++ altosui/AltosEepromLog.java | 98 +++++++++++++++++++++++++++++++++++++ altosui/AltosEepromRecord.java | 6 ++- altosui/AltosSerial.java | 10 ++++ altosui/Makefile.am | 2 + 7 files changed, 247 insertions(+), 9 deletions(-) create mode 100644 altosui/AltosEepromList.java create mode 100644 altosui/AltosEepromLog.java diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java index 0c1a4a92..f223f3fb 100644 --- a/altosui/AltosEepromBlock.java +++ b/altosui/AltosEepromBlock.java @@ -38,6 +38,12 @@ public class AltosEepromBlock extends ArrayList { int state; boolean has_date; int year, month, day; + boolean has_lat; + double lat; + boolean has_lon; + double lon; + boolean has_time; + int hour, minute, second; public AltosEepromBlock (AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { int addr; @@ -46,6 +52,9 @@ public class AltosEepromBlock extends ArrayList { has_flight = false; has_state = false; has_date = false; + has_lat = false; + has_lon = false; + has_time = false; serial_line.printf("e %x\n", block); for (addr = 0; !done && addr < 0x100;) { try { @@ -70,7 +79,20 @@ public class AltosEepromBlock extends ArrayList { day = (r.b & 0xff); has_date = true; } - + if (r.cmd == Altos.AO_LOG_GPS_TIME) { + hour = (r.a & 0xff); + minute = (r.a >> 8); + second = (r.b & 0xff); + has_time = true; + } + if (r.cmd == Altos.AO_LOG_GPS_LAT) { + lat = (double) (r.a | (r.b << 16)) / 1e7; + has_lat = true; + } + if (r.cmd == Altos.AO_LOG_GPS_LON) { + lon = (double) (r.a | (r.b << 16)) / 1e7; + has_lon = true; + } if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) done = true; add(addr / 8, r); diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 9a748710..ca31fdcf 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -161,11 +161,12 @@ public class AltosEepromDownload implements Runnable { int start_block, end_block; public void run () { - if (remote) { - serial_line.set_radio(); - serial_line.printf("p\nE 0\n"); - serial_line.flush_input(); - } + try { + new AltosEepromList(serial_line, remote); + } catch (Exception ee) { } + + if (remote) + serial_line.start_remote(); try { CaptureLog(start_block, end_block); @@ -179,7 +180,7 @@ public class AltosEepromDownload implements Runnable { "Connection Failed"); } if (remote) - serial_line.printf("~"); + serial_line.stop_remote(); monitor.done(); serial_line.flush_output(); serial_line.close(); diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java new file mode 100644 index 00000000..ac4a29de --- /dev/null +++ b/altosui/AltosEepromList.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +class AltosEepromFlight { + int flight; + int start; + int end; + + public AltosEepromFlight(int in_flight, int in_start, int in_end) { + flight = in_flight; + start = in_start; + end = in_end; + } +} + +public class AltosEepromList extends ArrayList { + AltosConfigData config_data; + + public AltosEepromList (AltosSerial serial_line, boolean remote) throws IOException, InterruptedException, TimeoutException { + try { + if (remote) + serial_line.start_remote(); + config_data = new AltosConfigData (serial_line); + if (config_data.serial == 0) + throw new IOException("no serial number found"); + + ArrayList flights = new ArrayList(); + if (config_data.flight_log_max != 0) { + serial_line.printf("l\n"); + for (;;) { + String line = serial_line.get_reply(5000); + if (line == null) + throw new TimeoutException(); + if (line.contains("done")) + break; + if (line.contains("Syntax")) + continue; + String[] tokens = line.split("\\s+"); + System.out.printf("got line %s (%d tokens)\n", line, tokens.length); + if (tokens.length < 6) + break; + + int flight = -1, start = -1, end = -1; + try { + if (tokens[0].equals("flight")) + flight = AltosParse.parse_int(tokens[1]); + if (tokens[2].equals("start")) + start = AltosParse.parse_hex(tokens[3]); + if (tokens[4].equals("end")) + end = AltosParse.parse_hex(tokens[5]); + System.out.printf("parsed flight %d %x %x\n", flight, start, end); + if (flight > 0 && start >= 0 && end > 0) + flights.add(new AltosEepromFlight(flight, start, end)); + } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); } + } + } else { + flights.add(new AltosEepromFlight(0, 0, 0xfff)); + } + for (AltosEepromFlight flight : flights) { + System.out.printf("Scanning flight %d %x %x\n", flight.flight, flight.start, flight.end); + add(new AltosEepromLog(serial_line, config_data.serial, + flight.start, flight.end)); + } + } finally { + if (remote) + serial_line.stop_remote(); + serial_line.flush_output(); + } + for (int i = 0; i < size(); i++) { + AltosEepromLog l = get(i); + System.out.printf("Found flight %d at %x - %x\n", l.flight, l.start_block, l.end_block); + } + } +} \ No newline at end of file diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java new file mode 100644 index 00000000..36289b42 --- /dev/null +++ b/altosui/AltosEepromLog.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosEepromLog { + int serial; + boolean has_flight; + int flight; + int start_block; + int end_block; + + boolean has_gps; + int year, month, day; + int hour, minute, second; + double lat, lon; + + public AltosEepromLog(AltosSerial serial_line, int in_serial, + int in_start_block, int in_end_block) + throws InterruptedException, TimeoutException { + + int block; + boolean has_date = false, has_time = false, has_lat = false, has_lon = false; + + start_block = in_start_block; + end_block = in_end_block; + serial = in_serial; + + if (in_end_block > in_start_block + 2) + in_end_block = in_start_block + 2; + + for (block = in_start_block; block < in_end_block; block++) { + AltosEepromBlock eeblock = new AltosEepromBlock(serial_line, block); + if (eeblock.has_flight) { + flight = eeblock.flight; + has_flight = true; + } + if (eeblock.has_date) { + year = eeblock.year; + month = eeblock.month; + day = eeblock.day; + has_date = true; + } + if (eeblock.has_time) { + hour = eeblock.hour; + minute = eeblock.minute; + second = eeblock.second; + has_time = true; + } + if (eeblock.has_lat) { + lat = eeblock.lat; + has_lat = true; + } + if (eeblock.has_lon) { + lon = eeblock.lon; + has_lon = true; + } + if (has_date && has_time && has_lat && has_lon) + has_gps = true; + if (has_gps && has_flight) + break; + } + System.out.printf("Serial %d start block %d end block %d\n", + serial, start_block, end_block); + if (has_flight) + System.out.printf("Flight %d\n", flight); + if (has_gps) + System.out.printf("%d-%d-%d %d:%02d:%02d Lat %f Lon %f\n", + year, month, day, hour, minute, second, lat, lon); + } +} diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index e61a7159..584a04b7 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -65,8 +65,10 @@ public class AltosEepromRecord { throw new TimeoutException(); int[] values = ParseHex(line); - if (values == null) - throw new ParseException(String.format("invalid line %s", line), 0); + if (values == null || values.length < 9) { + System.out.printf("invalid line %s", line); + throw new ParseException(String.format("inalid line %s", line), 0); + } if (values[0] != (addr & 0xff)) throw new ParseException(String.format("data address out of sync at 0x%x", addr), 0); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index b19143e5..6dce6f3d 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -242,6 +242,16 @@ public class AltosSerial implements Runnable { } } + public void start_remote() { + set_radio(); + printf("p\nE 0\n"); + flush_input(); + } + + public void stop_remote() { + printf ("~"); + } + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; line = ""; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 8cdd64cc..58d23787 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -29,6 +29,8 @@ altosui_JAVA = \ AltosDisplayThread.java \ AltosEepromBlock.java \ AltosEepromDownload.java \ + AltosEepromList.java \ + AltosEepromLog.java \ AltosEepromMonitor.java \ AltosEepromIterable.java \ AltosEepromRecord.java \ -- cgit v1.2.3 From 8801b8c1947bd39f7c985b91a2ba8dbc81bcc91a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 12 Jan 2011 12:40:45 -0800 Subject: altosui: Add eeprom 'manage' ui to download and delete multiple flights This shows the list of available flights and provides options to download and/or delete each one. Signed-off-by: Keith Packard --- altosui/AltosEepromDelete.java | 148 ++++++++++++++++++++++++++++++++++++ altosui/AltosEepromDownload.java | 124 +++++++++++++++---------------- altosui/AltosEepromList.java | 31 +++++++- altosui/AltosEepromLog.java | 16 ++++ altosui/AltosEepromManage.java | 157 +++++++++++++++++++++++++++++++++++++++ altosui/AltosEepromMonitor.java | 18 +++++ altosui/AltosEepromSelect.java | 132 ++++++++++++++++++++++++++++++++ altosui/AltosUI.java | 2 +- altosui/Makefile.am | 3 + 9 files changed, 565 insertions(+), 66 deletions(-) create mode 100644 altosui/AltosEepromDelete.java create mode 100644 altosui/AltosEepromManage.java create mode 100644 altosui/AltosEepromSelect.java diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java new file mode 100644 index 00000000..c95eda15 --- /dev/null +++ b/altosui/AltosEepromDelete.java @@ -0,0 +1,148 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosEepromDelete implements Runnable { + AltosEepromList flights; + Thread eeprom_thread; + AltosSerial serial_line; + boolean remote; + JFrame frame; + ActionListener listener; + boolean success; + + private void DeleteLog (AltosEepromLog log) + throws IOException, InterruptedException, TimeoutException { + + if (flights.config_data.flight_log_max != 0) { + + /* Devices with newer firmware can erase the + * flash blocks containing each flight + */ + serial_line.flush_input(); + serial_line.printf("d %d\n", log.flight); + System.out.printf("Attempt to delete flight %d\n", log.flight); + for (;;) { + /* It can take a while to erase the flash... */ + String line = serial_line.get_reply(20000); + System.out.printf("got back line %s\n", line); + if (line == null) + throw new TimeoutException(); + if (line.equals("Erased")) + break; + if (line.startsWith("No such")) + throw new IOException(line); + } + } + } + + private void show_error_internal(String message, String title) { + JOptionPane.showMessageDialog(frame, + message, + title, + JOptionPane.ERROR_MESSAGE); + } + + private void show_error(String in_message, String in_title) { + final String message = in_message; + final String title = in_title; + Runnable r = new Runnable() { + public void run() { + try { + show_error_internal(message, title); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + if (remote) + serial_line.start_remote(); + + success = false; + try { + for (AltosEepromLog log : flights) { + if (log.delete) { + DeleteLog(log); + } + } + System.out.printf("All flights successfully deleted\n"); + success = true; + } catch (IOException ee) { + show_error (ee.getLocalizedMessage(), + serial_line.device.toShortString()); + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + show_error (String.format("Connection to \"%s\" failed", + serial_line.device.toShortString()), + "Connection Failed"); + } + if (remote) + serial_line.stop_remote(); + serial_line.flush_output(); + serial_line.close(); + if (listener != null) { + Runnable r = new Runnable() { + public void run() { + try { + listener.actionPerformed(new ActionEvent(this, + success ? 1 : 0, + "delete")); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } + } + + public void start() { + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } + + public void addActionListener(ActionListener l) { + listener = l; + } + + public AltosEepromDelete(JFrame given_frame, + AltosSerial given_serial_line, + boolean given_remote, + AltosEepromList given_flights) { + frame = given_frame; + serial_line = given_serial_line; + remote = given_remote; + flights = given_flights; + success = false; + } +} \ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index ca31fdcf..5d19acec 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -33,21 +33,21 @@ import libaltosJNI.*; public class AltosEepromDownload implements Runnable { JFrame frame; - AltosDevice device; AltosSerial serial_line; boolean remote; Thread eeprom_thread; AltosEepromMonitor monitor; - int serial = 0; int flight = 0; int year = 0, month = 0, day = 0; boolean want_file = false; FileWriter eeprom_file = null; LinkedList eeprom_pending = new LinkedList(); - AltosConfigData config_data; + AltosEepromList flights; + ActionListener listener; + boolean success; private void FlushPending() throws IOException { - for (String s : config_data) { + for (String s : flights.config_data) { eeprom_file.write(s); eeprom_file.write('\n'); } @@ -62,9 +62,9 @@ public class AltosEepromDownload implements Runnable { if (force || (flight != 0 && want_file)) { AltosFile eeprom_name; if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, "eeprom"); + eeprom_name = new AltosFile(year, month, day, flights.config_data.serial, flight, "eeprom"); else - eeprom_name = new AltosFile(serial, flight, "eeprom"); + eeprom_name = new AltosFile(flights.config_data.serial, flight, "eeprom"); eeprom_file = new FileWriter(eeprom_name); if (eeprom_file != null) { @@ -75,25 +75,24 @@ public class AltosEepromDownload implements Runnable { } } - void CaptureLog(int start_block, int end_block) throws IOException, InterruptedException, TimeoutException { + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; int state = 0; boolean done = false; int record; - config_data = new AltosConfigData(serial_line); - serial = config_data.serial; - if (serial == 0) + if (flights.config_data.serial == 0) throw new IOException("no serial number found"); - monitor.set_serial(serial); + monitor.set_serial(flights.config_data.serial); /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - state = 0; state_block = start_block; - for (block = start_block; !done && block < end_block; block++) { + state = 0; state_block = log.start_block; + for (block = log.start_block; !done && block < log.end_block; block++) { monitor.set_value(Altos.state_to_string[state], state, block - state_block); AltosEepromBlock eeblock = new AltosEepromBlock(serial_line, block); + if (eeblock.has_flight) { flight = eeblock.flight; monitor.set_flight(flight); @@ -117,7 +116,7 @@ public class AltosEepromDownload implements Runnable { state = eeblock.state; } - CheckFile(true); + CheckFile(false); for (record = 0; record < eeblock.size(); record++) { AltosEepromRecord r = eeblock.get(record); @@ -158,76 +157,73 @@ public class AltosEepromDownload implements Runnable { SwingUtilities.invokeLater(r); } - int start_block, end_block; - public void run () { - try { - new AltosEepromList(serial_line, remote); - } catch (Exception ee) { } - if (remote) serial_line.start_remote(); try { - CaptureLog(start_block, end_block); + for (AltosEepromLog log : flights) { + if (log.download) { + monitor.reset(); + CaptureLog(log); + } + } + System.out.printf("All flights successfully downloaded\n"); + success = true; } catch (IOException ee) { - show_error (device.toShortString(), + show_error (serial_line.device.toShortString(), ee.getLocalizedMessage()); } catch (InterruptedException ie) { } catch (TimeoutException te) { show_error (String.format("Connection to \"%s\" failed", - device.toShortString()), + serial_line.device.toShortString()), "Connection Failed"); } if (remote) serial_line.stop_remote(); monitor.done(); serial_line.flush_output(); - serial_line.close(); + if (listener != null) { + Runnable r = new Runnable() { + public void run() { + try { + listener.actionPerformed(new ActionEvent(this, + success ? 1 : 0, + "download")); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } } - public AltosEepromDownload(JFrame given_frame) { - frame = given_frame; - device = AltosDeviceDialog.show(frame, AltosDevice.product_any); + public void start() { + eeprom_thread = new Thread(this); + eeprom_thread.start(); + } - remote = false; + public void addActionListener(ActionListener l) { + listener = l; + } - if (device != null) { - try { - serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) - remote = true; + public AltosEepromDownload(JFrame given_frame, + AltosSerial given_serial_line, + boolean given_remote, + AltosEepromList given_flights) { - monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); - monitor.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if (eeprom_thread != null) - eeprom_thread.interrupt(); - } - }); - - eeprom_thread = new Thread(this); - start_block = 0; - end_block = 0xfff; - eeprom_thread.start(); - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(frame, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } - } + frame = given_frame; + serial_line = given_serial_line; + remote = given_remote; + flights = given_flights; + success = false; + + monitor = new AltosEepromMonitor(frame, Altos.ao_flight_boost, Altos.ao_flight_landed); + monitor.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (eeprom_thread != null) + eeprom_thread.interrupt(); + } + }); } } diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index ac4a29de..a932dd12 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -30,6 +30,12 @@ import java.util.concurrent.*; import libaltosJNI.*; +/* + * Temporary structure to hold the list of stored flights; + * each of these will be queried in turn to generate more + * complete information + */ + class AltosEepromFlight { int flight; int start; @@ -42,10 +48,16 @@ class AltosEepromFlight { } } +/* + * Construct a list of flights available in a connected device + */ + public class AltosEepromList extends ArrayList { AltosConfigData config_data; - public AltosEepromList (AltosSerial serial_line, boolean remote) throws IOException, InterruptedException, TimeoutException { + public AltosEepromList (AltosSerial serial_line, boolean remote) + throws IOException, InterruptedException, TimeoutException + { try { if (remote) serial_line.start_remote(); @@ -54,7 +66,13 @@ public class AltosEepromList extends ArrayList { throw new IOException("no serial number found"); ArrayList flights = new ArrayList(); + if (config_data.flight_log_max != 0) { + + /* Devices with newer firmware will support the 'l' + * command which will list the region of storage + * occupied by each available flight + */ serial_line.printf("l\n"); for (;;) { String line = serial_line.get_reply(5000); @@ -83,8 +101,19 @@ public class AltosEepromList extends ArrayList { } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); } } } else { + + /* Older devices will hold only a single + * flight. This also assumes that any older + * device will have a 1MB flash device + */ flights.add(new AltosEepromFlight(0, 0, 0xfff)); } + + /* With the list of flights collected, collect more complete + * information on them by reading the first block or two of + * data. This will add GPS coordinates and a date. For older + * firmware, this will also extract the flight number. + */ for (AltosEepromFlight flight : flights) { System.out.printf("Scanning flight %d %x %x\n", flight.flight, flight.start, flight.end); add(new AltosEepromLog(serial_line, config_data.serial, diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index 36289b42..f284f103 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -30,6 +30,10 @@ import java.util.concurrent.*; import libaltosJNI.*; +/* + * Extract a bit of information from an eeprom-stored flight log. + */ + public class AltosEepromLog { int serial; boolean has_flight; @@ -42,6 +46,9 @@ public class AltosEepromLog { int hour, minute, second; double lat, lon; + boolean download; + boolean delete; + public AltosEepromLog(AltosSerial serial_line, int in_serial, int in_start_block, int in_end_block) throws InterruptedException, TimeoutException { @@ -53,6 +60,15 @@ public class AltosEepromLog { end_block = in_end_block; serial = in_serial; + /* + * By default, request that every log be downloaded but not deleted + */ + download = true; + delete = false; + /* + * Only look in the first two blocks so that this + * process doesn't take a long time + */ if (in_end_block > in_start_block + 2) in_end_block = in_start_block + 2; diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java new file mode 100644 index 00000000..b64ee525 --- /dev/null +++ b/altosui/AltosEepromManage.java @@ -0,0 +1,157 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosEepromManage implements ActionListener { + + JFrame frame; + boolean remote; + AltosDevice device; + AltosSerial serial_line; + AltosEepromList flights; + AltosEepromDownload download; + AltosEepromDelete delete; + boolean any_download; + boolean any_delete; + + public void finish() { + if (serial_line != null) { + serial_line.flush_output(); + serial_line.close(); + serial_line = null; + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + boolean success = e.getID() != 0; + + System.out.printf("Eeprom manager action %s %d\n", cmd, e.getID()); + if (cmd.equals("download")) { + if (success) { + System.out.printf("Download succeeded\n"); + if (any_delete) + delete.start(); + else + finish(); + } + } else if (cmd.equals("delete")) { + if (success) + System.out.printf("Delete succeeded\n"); + finish(); + } + } + + public AltosEepromManage(JFrame given_frame) { + + frame = given_frame; + device = AltosDeviceDialog.show(frame, AltosDevice.product_any); + + remote = false; + any_download = false; + any_delete = false; + + if (device != null) { + try { + serial_line = new AltosSerial(device); + if (!device.matchProduct(AltosDevice.product_telemetrum)) + remote = true; + + flights = new AltosEepromList(serial_line, remote); + + if (flights.size() == 0) { + } else { + AltosEepromSelect select = new AltosEepromSelect(frame, flights); + + if (select.run()) { + for (AltosEepromLog flight : flights) { + any_download = any_download || flight.download; + any_delete = any_delete || flight.delete; + } + if (any_download) { + download = new AltosEepromDownload(frame, + serial_line, + remote, + flights); + download.addActionListener(this); + } + + if (any_delete) { + delete = new AltosEepromDelete(frame, + serial_line, + remote, + flights); + delete.addActionListener(this); + } + + /* + * Start flight log download + */ + + if (any_download) + download.start(); + else if (any_delete) + delete.start(); + else + finish(); + } + } + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(frame, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(frame, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(frame, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + finish(); + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(frame, + String.format("Communications failed with \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + finish(); + } catch (InterruptedException ie) { + finish(); + } + } + } +} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index 13a49a95..b9d913fa 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -239,4 +239,22 @@ public class AltosEepromMonitor extends JDialog { }; SwingUtilities.invokeLater(r); } + + private void reset_internal() { + set_value_internal("startup",min_state,0); + set_flight_internal(0); + set_file_internal(""); + } + + public void reset() { + Runnable r = new Runnable() { + public void run() { + try { + reset_internal(); + } catch (Exception ex) { + } + } + }; + SwingUtilities.invokeLater(r); + } } diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java new file mode 100644 index 00000000..104d3180 --- /dev/null +++ b/altosui/AltosEepromSelect.java @@ -0,0 +1,132 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.util.*; +import javax.swing.*; +import javax.swing.border.*; +import java.awt.*; +import java.awt.event.*; +import libaltosJNI.libaltos; +import libaltosJNI.altos_device; +import libaltosJNI.SWIGTYPE_p_altos_file; +import libaltosJNI.SWIGTYPE_p_altos_list; + +class AltosEepromItem extends JPanel implements ActionListener { + AltosEepromLog log; + JCheckBox download; + JCheckBox delete; + JLabel label; + + public void actionPerformed(ActionEvent e) { + System.out.printf("eeprom item action %s %d\n", e.getActionCommand(), e.getID()); + if (e.getSource() == download) { + log.download = download.isSelected(); + System.out.printf("download set to %b\n", log.download); + } else if (e.getSource() == delete) { + log.delete = delete.isSelected(); + System.out.printf("delete set to %b\n", log.delete); + } + } + + public AltosEepromItem(AltosEepromLog in_log) { + log = in_log; + + download = new JCheckBox("Download", log.download); + download.addActionListener(this); + add(download); + delete = new JCheckBox("Delete", log.delete); + delete.addActionListener(this); + add(delete); + label = new JLabel(String.format("Flight %d %4d-%02d-%02d", + log.flight, log.year, log.month, log.day)); + add(label); + } +} + +public class AltosEepromSelect extends JDialog implements ActionListener { + private JList list; + private JFrame frame; + JButton ok; + JButton cancel; + boolean success; + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("ok")) + success = true; + setVisible(false); + } + + public boolean run() { + success = false; + setLocationRelativeTo(frame); + setVisible(true); + return success; + } + + public AltosEepromSelect (JFrame in_frame, + AltosEepromList flights) { + + super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true); + frame = in_frame; + + JLabel selectLabel = new JLabel("Select flights to download and/or delete", SwingConstants.CENTER); + + JPanel labelPane = new JPanel(); + labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS)); + labelPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0)); + labelPane.add(Box.createHorizontalGlue()); + labelPane.add(selectLabel); + labelPane.add(Box.createHorizontalGlue()); + + JPanel flightPane = new JPanel(); + flightPane.setLayout(new BoxLayout(flightPane, BoxLayout.Y_AXIS)); + flightPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + for (AltosEepromLog flight : flights) { + flightPane.add(new AltosEepromItem(flight)); + } + + ok = new JButton("OK"); + ok.addActionListener(this); + ok.setActionCommand("ok"); + + cancel = new JButton("Cancel"); + cancel.addActionListener(this); + cancel.setActionCommand("cancel"); + + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.X_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancel); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(ok); + + Container contentPane = getContentPane(); + + contentPane.add(labelPane, BorderLayout.PAGE_START); + contentPane.add(flightPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + pack(); + } +} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 94c4dd2a..90e3d7f0 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -245,7 +245,7 @@ public class AltosUI extends JFrame { * a TeleDongle over the packet link */ private void SaveFlightData() { - new AltosEepromDownload(AltosUI.this); + new AltosEepromManage(AltosUI.this); } /* Load a flight log file and write out a CSV file containing diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 58d23787..196d7032 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -28,12 +28,15 @@ altosui_JAVA = \ AltosDevice.java \ AltosDisplayThread.java \ AltosEepromBlock.java \ + AltosEepromDelete.java \ AltosEepromDownload.java \ AltosEepromList.java \ AltosEepromLog.java \ + AltosEepromManage.java \ AltosEepromMonitor.java \ AltosEepromIterable.java \ AltosEepromRecord.java \ + AltosEepromSelect.java \ AltosFile.java \ AltosFlash.java \ AltosFlashUI.java \ -- cgit v1.2.3 From d794ef9e0fbe4d13259db1bbd69f01717c14400b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 12 Jan 2011 12:41:26 -0800 Subject: altos: check for valid flight number in ao_log_delete Zero is not a valid flight number, and ao_log_flight uses that to indicate 'no flight in this slot'. Check the user-provided input for zero before looking through the slots. Signed-off-by: Keith Packard --- src/ao_log.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/ao_log.c b/src/ao_log.c index ba019992..8666482b 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -355,31 +355,33 @@ ao_log_delete(void) __reentrant slots = ao_log_slots(); /* Look for the flight log matching the requested flight */ - for (slot = 0; slot < slots; slot++) { - if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_erase_mark(); - ao_log_current_pos = ao_log_pos(slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - while (ao_log_current_pos < ao_log_end_pos) { - /* - * Check to see if we've reached the end of - * the used memory to avoid re-erasing the same - * memory over and over again - */ - if (ao_storage_read(ao_log_current_pos, - &log, - sizeof (struct ao_log_record))) { - for (slot = 0; slot < sizeof (struct ao_log_record); slot++) - if (((uint8_t *) &log)[slot] != 0xff) + if (ao_cmd_lex_i) { + for (slot = 0; slot < slots; slot++) { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + while (ao_log_current_pos < ao_log_end_pos) { + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + if (ao_storage_read(ao_log_current_pos, + &log, + sizeof (struct ao_log_record))) { + for (slot = 0; slot < sizeof (struct ao_log_record); slot++) + if (((uint8_t *) &log)[slot] != 0xff) + break; + if (slot == sizeof (struct ao_log_record)) break; - if (slot == sizeof (struct ao_log_record)) - break; + } + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; } - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; + puts("Erased"); + return; } - puts("Erased"); - return; } } printf("No such flight: %d\n", ao_cmd_lex_i); -- cgit v1.2.3 From 97b1ca994599ad262400eb3c685799582f7f1b94 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 14 Jan 2011 14:30:49 -0700 Subject: update changelogs for Debian build --- ChangeLog | 187 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 35 +++++++++++ 2 files changed, 222 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6b4ac361..589faa31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,190 @@ +commit d794ef9e0fbe4d13259db1bbd69f01717c14400b +Author: Keith Packard +Date: Wed Jan 12 12:41:26 2011 -0800 + + altos: check for valid flight number in ao_log_delete + + Zero is not a valid flight number, and ao_log_flight uses that to + indicate 'no flight in this slot'. Check the user-provided input for + zero before looking through the slots. + + Signed-off-by: Keith Packard + +commit 8801b8c1947bd39f7c985b91a2ba8dbc81bcc91a +Author: Keith Packard +Date: Wed Jan 12 12:40:45 2011 -0800 + + altosui: Add eeprom 'manage' ui to download and delete multiple flights + + This shows the list of available flights and provides options to + download and/or delete each one. + + Signed-off-by: Keith Packard + +commit 440d52e34364fdeeddc76a2d744cc6d1c934364f +Author: Keith Packard +Date: Tue Jan 11 21:28:07 2011 -0800 + + altosui: Add support for parsing list of flights from the 'l' command + + This adds parsing support to enumerate the available flights, but does + not yet provide any UI to use it. + + Signed-off-by: Keith Packard + +commit 7ad419d81c90ef6a16656970466313767fef830f +Author: Keith Packard +Date: Tue Jan 11 21:26:41 2011 -0800 + + altos: oops -- 'e' command was only showing 7 of the 8 bytes per line + + Just a silly off-by-one error when printing out the data received from flash. + + Signed-off-by: Keith Packard + +commit bd2480fd757b67557d9c7de42e402034002c3e37 +Author: Keith Packard +Date: Tue Jan 11 15:39:24 2011 -0800 + + altosui: Split eeprom download code apart + + Create separate 'download config data', 'read single record' and 'read + block' functions. This code will be shared with future multi-log + reading code for new firmware. + + Signed-off-by: Keith Packard + +commit c437b14b7fc7afdfc7b809a04d7fa29d5e742307 +Author: Anthony Towns +Date: Fri Jan 7 21:00:10 2011 -0800 + + altos: Remove redundant initialization of ao_interval variables + + These are all initialized in the ao_flight_drogue state transition. + + Signed-off-by: Keith Packard + +commit 57de960b8148bf485607898c3d66af6994d76481 +Author: Anthony Towns +Date: Fri Jan 7 20:52:33 2011 -0800 + + altos: Remove unused accel_vel_mach and accel_vel_boost variables + + Presumably left-over debugging code. + + Signed-off-by: Keith Packard + +commit ca66f86a899c191b6362a334417fc84a79349677 +Author: Keith Packard +Date: Fri Jan 7 20:46:29 2011 -0800 + + altosui: Add configuration of flight log size + + This adds to the TeleMetrum configuration UI the ability to set the + maximum flight log size. + + Signed-off-by: Keith Packard + +commit 52ac83fedbfd380d14d4df2e79992bbdfba3552a +Author: Keith Packard +Date: Fri Jan 7 20:26:39 2011 -0800 + + altos: Check for full log and complain + + Reports special tone along with the continuity checks. + Reports flight 0 in telemetry. + + Signed-off-by: Keith Packard + +commit 00891b40754962ef6530b237ef52017bb58112d5 +Author: Keith Packard +Date: Fri Jan 7 20:25:09 2011 -0800 + + altos: Check requested log max size against available space + + Make sure the amount of memory requested for a single log isn't more + than is available on the device. + + Signed-off-by: Keith Packard + +commit bbddcae2a15b6d430e84956ddf26955aa9173cc0 +Author: Anthony Towns +Date: Fri Jan 7 20:18:25 2011 -0800 + + altos: Optimize Morse code generation + + This reduces the size of data and code needed to report the + flight states + + Signed-off-by: Keith Packard + +commit 73620c41017c1774d6190dfd4be5b742eb64f8d3 +Author: Keith Packard +Date: Fri Jan 7 20:13:28 2011 -0800 + + altos: ensure erase mark is written when erasing flights + + It was getting called only when *failing* to erase a flight (oops), + secondly, it wasn't getting written because ao_storage_flush wasn't + getting called. + + Signed-off-by: Keith Packard + +commit edd22ee49adf60c35f2fe6ba97c111b7ad4131c2 +Author: Keith Packard +Date: Fri Jan 7 17:56:06 2011 -0800 + + altos: report flight log offsets in hex block numbers instead of bytes + + makes them compatible with the 'e' command. + + Signed-off-by: Keith Packard + +commit 1cc08af4f4a1ff61fc0deca3bdd95e8a5ca8ec5c +Author: Keith Packard +Date: Fri Jan 7 17:55:54 2011 -0800 + + altos: white space fix + + Signed-off-by: Keith Packard + +commit d8c9684239b67a69a4a3d24202a6df0d73c4f7f5 +Author: Keith Packard +Date: Fri Jan 7 17:54:54 2011 -0800 + + altos: Speed up at45 and 25lc erase speeds + + No need to read the block to be erased before erasing it. + + Signed-off-by: Keith Packard + +commit 2722703bd848b07a02d3ce0c83a502eca52a9f1d +Author: Keith Packard +Date: Fri Jan 7 14:58:39 2011 -0800 + + altos: support storage of multiple flights. + + This adds the logging support for dealing with multiple flights + + Signed-off-by: Keith Packard + +commit a9b210bc33cd95e7108ab51925fdf0d5e8deaf7e +Author: Keith Packard +Date: Fri Jan 7 10:05:11 2011 -0800 + + altos: Add configuration parameter for maximum flight log size + + This parameter will permit available storage to be split into multiple + separate flight logs. + + Signed-off-by: Keith Packard + +commit 3bcf14f12f6681888c3162d0f33ef2d454eb75dd +Author: Bdale Garbee +Date: Fri Jan 7 00:52:50 2011 -0700 + + update changelogs for Debian build + commit 408a3e04362d626778640dd0ce7d356d3863de53 Author: Keith Packard Date: Thu Jan 6 23:38:13 2011 -0800 diff --git a/debian/changelog b/debian/changelog index cf13a14b..1d156a59 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,38 @@ +altos (0.8.1+36+gd794ef9) unstable; urgency=low + + [ Keith Packard ] + * altos: Add configuration parameter for maximum flight log size + * altos: support storage of multiple flights. + * altos: Speed up at45 and 25lc erase speeds + * altos: white space fix + * altos: report flight log offsets in hex block numbers instead of + bytes + * altos: ensure erase mark is written when erasing flights + + [ Anthony Towns ] + * altos: Optimize Morse code generation + + [ Keith Packard ] + * altos: Check requested log max size against available space + * altos: Check for full log and complain + * altosui: Add configuration of flight log size + + [ Anthony Towns ] + * altos: Remove unused accel_vel_mach and accel_vel_boost variables + * altos: Remove redundant initialization of ao_interval variables + + [ Keith Packard ] + * altosui: Split eeprom download code apart + * altos: oops -- 'e' command was only showing 7 of the 8 bytes per + line + * altosui: Add support for parsing list of flights from the 'l' + command + * altosui: Add eeprom 'manage' ui to download and delete multiple + flights + * altos: check for valid flight number in ao_log_delete + + -- Bdale Garbee Fri, 14 Jan 2011 14:30:37 -0700 + altos (0.8.1+18+g408a3e0) unstable; urgency=low [ Anthony Towns ] -- cgit v1.2.3 From b490455807d1c70c81785ed8931a07ab44e8e421 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 14 Jan 2011 14:31:19 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 589faa31..c523a997 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 97b1ca994599ad262400eb3c685799582f7f1b94 +Author: Bdale Garbee +Date: Fri Jan 14 14:30:49 2011 -0700 + + update changelogs for Debian build + commit d794ef9e0fbe4d13259db1bbd69f01717c14400b Author: Keith Packard Date: Wed Jan 12 12:41:26 2011 -0800 diff --git a/debian/changelog b/debian/changelog index 1d156a59..6bc1fc77 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.8.1+36+gd794ef9) unstable; urgency=low +altos (0.8.1+37+g97b1ca9) unstable; urgency=low [ Keith Packard ] * altos: Add configuration parameter for maximum flight log size -- cgit v1.2.3 From 2d154be89246e111a36f7c2700effbb2c97da541 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jan 2011 16:44:50 -0800 Subject: altosui: Show dialog after successful delete or when no flights Make sure the user always sees confirmation for flight log management. Signed-off-by: Keith Packard --- altosui/AltosEepromManage.java | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index b64ee525..2704f883 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -50,6 +50,20 @@ public class AltosEepromManage implements ActionListener { } } + private String showDeletedFlights() { + String result = ""; + + for (AltosEepromLog flight : flights) { + if (flight.delete) { + if (result.equals("")) + result = String.format("%d", flight.flight); + else + result = String.format("%s, %d", result, flight.flight); + } + } + return result; + } + public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); boolean success = e.getID() != 0; @@ -57,15 +71,19 @@ public class AltosEepromManage implements ActionListener { System.out.printf("Eeprom manager action %s %d\n", cmd, e.getID()); if (cmd.equals("download")) { if (success) { - System.out.printf("Download succeeded\n"); if (any_delete) delete.start(); else finish(); } } else if (cmd.equals("delete")) { - if (success) - System.out.printf("Delete succeeded\n"); + if (success) { + JOptionPane.showMessageDialog(frame, + String.format("Flights erased: %s", + showDeletedFlights()), + serial_line.device.toShortString(), + JOptionPane.INFORMATION_MESSAGE); + } finish(); } } @@ -88,6 +106,11 @@ public class AltosEepromManage implements ActionListener { flights = new AltosEepromList(serial_line, remote); if (flights.size() == 0) { + JOptionPane.showMessageDialog(frame, + String.format("No flights available on %d", + device.getSerial()), + serial_line.device.toShortString(), + JOptionPane.INFORMATION_MESSAGE); } else { AltosEepromSelect select = new AltosEepromSelect(frame, flights); -- cgit v1.2.3 From fcaee12a64d5e195b55b8f77c19dfc0c57ef5d58 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jan 2011 16:47:19 -0800 Subject: altosui: Ensure serial line is flushed after disabling remote link Flush the '~' character. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 6dce6f3d..78da5d1f 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -250,6 +250,7 @@ public class AltosSerial implements Runnable { public void stop_remote() { printf ("~"); + flush_output(); } public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { -- cgit v1.2.3 From d908c2ebd0b11a54cfd922a192249d0f0df0ddb0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jan 2011 16:47:36 -0800 Subject: altosui: Add preference for serial debugging. This dumps serial input/output to stdout. Signed-off-by: Keith Packard --- altosui/AltosConfigureUI.java | 28 +++++++++++++++++++++++++++- altosui/AltosPreferences.java | 22 ++++++++++++++++++++++ altosui/AltosSerial.java | 13 ++++++++++--- 3 files changed, 59 insertions(+), 4 deletions(-) diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 153c59fd..ab3d950e 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -47,6 +47,8 @@ public class AltosConfigureUI JLabel callsign_label; JTextField callsign_value; + JRadioButton serial_debug; + /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { AltosPreferences.set_callsign(callsign_value.getText()); @@ -166,6 +168,30 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(callsign_value, c); + /* Serial debug setting */ + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Serial Debug"), c); + + serial_debug = new JRadioButton("Enable", AltosPreferences.serial_debug()); + serial_debug.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JRadioButton item = (JRadioButton) e.getSource(); + boolean enabled = item.isSelected(); + AltosPreferences.set_serial_debug(enabled); + } + }); + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(serial_debug, c); + /* And a close button at the bottom */ close = new JButton("Close"); close.addActionListener(new ActionListener() { @@ -174,7 +200,7 @@ public class AltosConfigureUI } }); c.gridx = 0; - c.gridy = 4; + c.gridy = 5; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index c6ae6cbd..d4df4e16 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -43,6 +43,9 @@ class AltosPreferences { /* firmware directory preference name */ final static String firmwaredirPreference = "FIRMWARE"; + /* serial debug preference name */ + final static String serialDebugPreference = "SERIAL-DEBUG"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -67,6 +70,9 @@ class AltosPreferences { /* Firmware directory */ static File firmwaredir; + /* Serial debug */ + static boolean serial_debug; + public static void init(Component ui) { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -97,6 +103,9 @@ class AltosPreferences { firmwaredir = new File(firmwaredir_string); else firmwaredir = null; + + serial_debug = preferences.getBoolean(serialDebugPreference, false); + AltosSerial.set_debug(serial_debug); } static void flush_preferences() { @@ -215,4 +224,17 @@ class AltosPreferences { public static File firmwaredir() { return firmwaredir; } + + public static void set_serial_debug(boolean new_serial_debug) { + serial_debug = new_serial_debug; + AltosSerial.set_debug(serial_debug); + synchronized (preferences) { + preferences.putBoolean(serialDebugPreference, serial_debug); + flush_preferences(); + } + } + + public static boolean serial_debug() { + return serial_debug; + } } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 78da5d1f..3ad16b2b 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -47,6 +47,11 @@ public class AltosSerial implements Runnable { byte[] line_bytes; int line_count; boolean monitor_mode; + static boolean debug; + + static void set_debug(boolean new_debug) { + debug = new_debug; + } public void run () { int c; @@ -84,7 +89,8 @@ public class AltosSerial implements Runnable { q.put(new AltosLine (line)); } } else { -// System.out.printf("GOT: %s\n", line); + if (debug) + System.out.printf("\t\t\t\t\t%s\n", line); reply_queue.put(new AltosLine (line)); } line_count = 0; @@ -176,13 +182,14 @@ public class AltosSerial implements Runnable { } } - public void putc(char c) { + private void putc(char c) { if (altos != null) libaltos.altos_putchar(altos, c); } public void print(String data) { -// System.out.printf("\"%s\" ", data); + if (debug) + System.out.printf("%s", data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } -- cgit v1.2.3 From 646e1926cdf56e2cf2425413ce716e6999b64a58 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 14 Jan 2011 18:01:00 -0700 Subject: update changelogs for Debian build --- ChangeLog | 36 ++++++++++++++++++++++++++++++++++++ debian/changelog | 9 +++++++++ 2 files changed, 45 insertions(+) diff --git a/ChangeLog b/ChangeLog index c523a997..7efca650 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +commit d908c2ebd0b11a54cfd922a192249d0f0df0ddb0 +Author: Keith Packard +Date: Fri Jan 14 16:47:36 2011 -0800 + + altosui: Add preference for serial debugging. + + This dumps serial input/output to stdout. + + Signed-off-by: Keith Packard + +commit fcaee12a64d5e195b55b8f77c19dfc0c57ef5d58 +Author: Keith Packard +Date: Fri Jan 14 16:47:19 2011 -0800 + + altosui: Ensure serial line is flushed after disabling remote link + + Flush the '~' character. + + Signed-off-by: Keith Packard + +commit 2d154be89246e111a36f7c2700effbb2c97da541 +Author: Keith Packard +Date: Fri Jan 14 16:44:50 2011 -0800 + + altosui: Show dialog after successful delete or when no flights + + Make sure the user always sees confirmation for flight log management. + + Signed-off-by: Keith Packard + +commit b490455807d1c70c81785ed8931a07ab44e8e421 +Author: Bdale Garbee +Date: Fri Jan 14 14:31:19 2011 -0700 + + update changelogs for Debian build + commit 97b1ca994599ad262400eb3c685799582f7f1b94 Author: Bdale Garbee Date: Fri Jan 14 14:30:49 2011 -0700 diff --git a/debian/changelog b/debian/changelog index 6bc1fc77..0cbff558 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,12 @@ +altos (0.8.1+41+gd908c2e) unstable; urgency=low + + [ Keith Packard ] + * altosui: Show dialog after successful delete or when no flights + * altosui: Ensure serial line is flushed after disabling remote link + * altosui: Add preference for serial debugging. + + -- Bdale Garbee Fri, 14 Jan 2011 18:00:51 -0700 + altos (0.8.1+37+g97b1ca9) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From fdba0f24afd59becc499d750bbdb80aea86066ac Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 14 Jan 2011 18:01:16 -0700 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ debian/changelog | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7efca650..aa5cc6f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 646e1926cdf56e2cf2425413ce716e6999b64a58 +Author: Bdale Garbee +Date: Fri Jan 14 18:01:00 2011 -0700 + + update changelogs for Debian build + commit d908c2ebd0b11a54cfd922a192249d0f0df0ddb0 Author: Keith Packard Date: Fri Jan 14 16:47:36 2011 -0800 diff --git a/debian/changelog b/debian/changelog index 0cbff558..836b47d3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.8.1+41+gd908c2e) unstable; urgency=low +altos (0.8.1+42+g646e192) unstable; urgency=low [ Keith Packard ] * altosui: Show dialog after successful delete or when no flights -- cgit v1.2.3 From 35adb7c98fe02e84fff70c1bee22bfa019cfacc2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jan 2011 21:44:59 -0800 Subject: doc: Add telemetrum mounting template in svg and pdf forms telemetrum-outline.svg and telemetrum-outline.pdf Signed-off-by: Keith Packard --- doc/telemetrum-outline.pdf | Bin 0 -> 2047 bytes doc/telemetrum-outline.svg | 207 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 doc/telemetrum-outline.pdf create mode 100644 doc/telemetrum-outline.svg diff --git a/doc/telemetrum-outline.pdf b/doc/telemetrum-outline.pdf new file mode 100644 index 00000000..09ce5577 Binary files /dev/null and b/doc/telemetrum-outline.pdf differ diff --git a/doc/telemetrum-outline.svg b/doc/telemetrum-outline.svg new file mode 100644 index 00000000..542df64c --- /dev/null +++ b/doc/telemetrum-outline.svg @@ -0,0 +1,207 @@ + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UP + + -- cgit v1.2.3 From fef302656f21ae0ab4772f72979cbb7f071da89a Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 16 Jan 2011 20:25:19 +1300 Subject: Re-order and re-arrange eeprom download dialog Signed-off-by: Mike Beattie --- altosui/AltosEepromSelect.java | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index 104d3180..7995d32b 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -38,25 +38,30 @@ class AltosEepromItem extends JPanel implements ActionListener { System.out.printf("eeprom item action %s %d\n", e.getActionCommand(), e.getID()); if (e.getSource() == download) { log.download = download.isSelected(); - System.out.printf("download set to %b\n", log.download); + System.out.printf("download for flight %d set to %b\n", log.flight, log.download); } else if (e.getSource() == delete) { log.delete = delete.isSelected(); - System.out.printf("delete set to %b\n", log.delete); + System.out.printf("delete for flight %d set to %b\n", log.flight, log.delete); } } public AltosEepromItem(AltosEepromLog in_log) { log = in_log; - download = new JCheckBox("Download", log.download); + label = new JLabel(String.format("Flight #%02d - %04d-%02d-%02d", + log.flight, log.year, log.month, log.day)); + label.setPreferredSize(new Dimension(170, 15)); + add(label); + download = new JCheckBox("", log.download); download.addActionListener(this); + download.setPreferredSize(new Dimension(100, 15)); + download.setHorizontalAlignment(SwingConstants.CENTER); add(download); - delete = new JCheckBox("Delete", log.delete); + delete = new JCheckBox("", log.delete); delete.addActionListener(this); + delete.setPreferredSize(new Dimension(70, 15)); + delete.setHorizontalAlignment(SwingConstants.CENTER); add(delete); - label = new JLabel(String.format("Flight %d %4d-%02d-%02d", - log.flight, log.year, log.month, log.day)); - add(label); } } @@ -98,9 +103,24 @@ public class AltosEepromSelect extends JDialog implements ActionListener { labelPane.add(selectLabel); labelPane.add(Box.createHorizontalGlue()); + JLabel flightHeaderLabel = new JLabel("Flight", SwingConstants.CENTER); + flightHeaderLabel.setPreferredSize(new Dimension(170, 15)); + + JLabel downloadHeaderLabel = new JLabel("Download", SwingConstants.CENTER); + downloadHeaderLabel.setPreferredSize(new Dimension(100, 15)); + + JLabel deleteHeaderLabel = new JLabel("Delete", SwingConstants.CENTER); + deleteHeaderLabel.setPreferredSize(new Dimension(70, 15)); + + JPanel headerPane = new JPanel(); + headerPane.add(flightHeaderLabel); + headerPane.add(downloadHeaderLabel); + headerPane.add(deleteHeaderLabel); + JPanel flightPane = new JPanel(); flightPane.setLayout(new BoxLayout(flightPane, BoxLayout.Y_AXIS)); flightPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); + flightPane.add(headerPane); for (AltosEepromLog flight : flights) { flightPane.add(new AltosEepromItem(flight)); } -- cgit v1.2.3 From df1c6ab3ac079199b5a12328c9ff5cfa6ac29b36 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 17 Jan 2011 00:40:07 +1300 Subject: Convert EepromSelect dialog to use a GridBag Signed-off-by: Mike Beattie --- altosui/AltosEepromSelect.java | 118 ++++++++++++++++++++++++++++++----------- 1 file changed, 88 insertions(+), 30 deletions(-) diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index 7995d32b..f0066aac 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -28,11 +28,11 @@ import libaltosJNI.altos_device; import libaltosJNI.SWIGTYPE_p_altos_file; import libaltosJNI.SWIGTYPE_p_altos_list; -class AltosEepromItem extends JPanel implements ActionListener { +class AltosEepromItem implements ActionListener { AltosEepromLog log; + JLabel label; JCheckBox download; JCheckBox delete; - JLabel label; public void actionPerformed(ActionEvent e) { System.out.printf("eeprom item action %s %d\n", e.getActionCommand(), e.getID()); @@ -50,18 +50,12 @@ class AltosEepromItem extends JPanel implements ActionListener { label = new JLabel(String.format("Flight #%02d - %04d-%02d-%02d", log.flight, log.year, log.month, log.day)); - label.setPreferredSize(new Dimension(170, 15)); - add(label); + download = new JCheckBox("", log.download); download.addActionListener(this); - download.setPreferredSize(new Dimension(100, 15)); - download.setHorizontalAlignment(SwingConstants.CENTER); - add(download); + delete = new JCheckBox("", log.delete); delete.addActionListener(this); - delete.setPreferredSize(new Dimension(70, 15)); - delete.setHorizontalAlignment(SwingConstants.CENTER); - add(delete); } } @@ -94,6 +88,10 @@ public class AltosEepromSelect extends JDialog implements ActionListener { super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true); frame = in_frame; + /* Create the container for the dialog */ + Container contentPane = getContentPane(); + + /* First, we create a pane containing the dialog's header/title */ JLabel selectLabel = new JLabel("Select flights to download and/or delete", SwingConstants.CENTER); JPanel labelPane = new JPanel(); @@ -103,28 +101,90 @@ public class AltosEepromSelect extends JDialog implements ActionListener { labelPane.add(selectLabel); labelPane.add(Box.createHorizontalGlue()); - JLabel flightHeaderLabel = new JLabel("Flight", SwingConstants.CENTER); - flightHeaderLabel.setPreferredSize(new Dimension(170, 15)); - - JLabel downloadHeaderLabel = new JLabel("Download", SwingConstants.CENTER); - downloadHeaderLabel.setPreferredSize(new Dimension(100, 15)); - - JLabel deleteHeaderLabel = new JLabel("Delete", SwingConstants.CENTER); - deleteHeaderLabel.setPreferredSize(new Dimension(70, 15)); + /* Add the header to the container. */ + contentPane.add(labelPane, BorderLayout.PAGE_START); - JPanel headerPane = new JPanel(); - headerPane.add(flightHeaderLabel); - headerPane.add(downloadHeaderLabel); - headerPane.add(deleteHeaderLabel); - JPanel flightPane = new JPanel(); - flightPane.setLayout(new BoxLayout(flightPane, BoxLayout.Y_AXIS)); + /* Now we create the evilness that is a GridBag for the flight details */ + GridBagConstraints c; + Insets i = new Insets(4,4,4,4); + JPanel flightPane = new JPanel(); + flightPane.setLayout(new GridBagLayout()); flightPane.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); - flightPane.add(headerPane); + + /* Flight Header */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + JLabel flightHeaderLabel = new JLabel("Flight:"); + flightPane.add(flightHeaderLabel, c); + + /* Download Header */ + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + JLabel downloadHeaderLabel = new JLabel("Download:"); + flightPane.add(downloadHeaderLabel, c); + + /* Delete Header */ + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + JLabel deleteHeaderLabel = new JLabel("Delete:"); + flightPane.add(deleteHeaderLabel, c); + + /* Add the flights to the GridBag */ + AltosEepromItem item; + int itemNumber = 1; for (AltosEepromLog flight : flights) { - flightPane.add(new AltosEepromItem(flight)); + /* Create a flight object with handlers and + * appropriate UI items + */ + item = new AltosEepromItem(flight); + + /* Add a decriptive label for the flight */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = itemNumber; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + flightPane.add(item.label, c); + + /* Add a download checkbox for the flight */ + c = new GridBagConstraints(); + c.gridx = 1; c.gridy = itemNumber; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + flightPane.add(item.download, c); + + /* Add a delete checkbox for the flight */ + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = itemNumber; + c.fill = GridBagConstraints.NONE; + c.weightx = 0.5; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + flightPane.add(item.delete, c); + + itemNumber++; } + /* Add the GridBag to the container */ + contentPane.add(flightPane, BorderLayout.CENTER); + + /* Create the dialog buttons */ ok = new JButton("OK"); ok.addActionListener(this); ok.setActionCommand("ok"); @@ -141,12 +201,10 @@ public class AltosEepromSelect extends JDialog implements ActionListener { buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(ok); - Container contentPane = getContentPane(); - - contentPane.add(labelPane, BorderLayout.PAGE_START); - contentPane.add(flightPane, BorderLayout.CENTER); + /* Add the buttons to the container */ contentPane.add(buttonPane, BorderLayout.PAGE_END); + /* Pack the window! */ pack(); } } -- cgit v1.2.3 From eec9eb2e81535e62c52fbb2e57a2d33f88f92c1a Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 17 Jan 2011 07:56:53 +1300 Subject: Close serial port if Download/Delete dialog is cancelled. Signed-off-by: Mike Beattie --- altosui/AltosEepromManage.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 2704f883..c7efe478 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -146,6 +146,8 @@ public class AltosEepromManage implements ActionListener { else finish(); } + } else { + finish(); } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, -- cgit v1.2.3 From deb3c7b9206be0c9c46f75d35c8f766c26d9838f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 22:43:37 -0800 Subject: altosui: Reset eeprom download instance variables before reading flight To deal with downloading multiple flights in a single invocation, make sure all relevant instance variables are set back to start of flight download values each time a log is read. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 5d19acec..af70b15c 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -37,11 +37,13 @@ public class AltosEepromDownload implements Runnable { boolean remote; Thread eeprom_thread; AltosEepromMonitor monitor; - int flight = 0; - int year = 0, month = 0, day = 0; - boolean want_file = false; - FileWriter eeprom_file = null; - LinkedList eeprom_pending = new LinkedList(); + + int flight; + int year, month, day; + boolean want_file; + FileWriter eeprom_file; + LinkedList eeprom_pending; + AltosEepromList flights; ActionListener listener; boolean success; @@ -84,6 +86,16 @@ public class AltosEepromDownload implements Runnable { if (flights.config_data.serial == 0) throw new IOException("no serial number found"); + /* Reset per-capture variables */ + flight = 0; + year = 0; + month = 0; + day = 0; + want_file = false; + eeprom_file = null; + eeprom_pending = new LinkedList(); + + /* Set serial number in the monitor dialog window */ monitor.set_serial(flights.config_data.serial); /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ -- cgit v1.2.3 From d4add23186b3586c99579d83efdc003f79e9bf7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 14:26:18 -0800 Subject: altosui: Make serial debug more complete and accurate Display all serial input, including telemetry. Wait to display serial output until flush time, to debug missing flushing. Show when devices are opened and closed. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 3ad16b2b..e609c6b5 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -48,6 +48,7 @@ public class AltosSerial implements Runnable { int line_count; boolean monitor_mode; static boolean debug; + LinkedList pending_output = new LinkedList(); static void set_debug(boolean new_debug) { debug = new_debug; @@ -83,14 +84,14 @@ public class AltosSerial implements Runnable { for (int i = 0; i < line_count; i++) line = line + line_bytes[i]; } + if (debug) + System.out.printf("\t\t\t\t\t%s\n", line); if (line.startsWith("VERSION") || line.startsWith("CRC")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); q.put(new AltosLine (line)); } } else { - if (debug) - System.out.printf("\t\t\t\t\t%s\n", line); reply_queue.put(new AltosLine (line)); } line_count = 0; @@ -114,8 +115,12 @@ public class AltosSerial implements Runnable { } public void flush_output() { - if (altos != null) + if (altos != null) { + for (String s : pending_output) + System.out.print(s); + pending_output.clear(); libaltos.altos_flush(altos); + } } public void flush_input() { @@ -180,6 +185,8 @@ public class AltosSerial implements Runnable { synchronized (devices_opened) { devices_opened.remove(device.getPath()); } + if (debug) + System.out.printf("Closing %s\n", device.getPath()); } private void putc(char c) { @@ -189,7 +196,7 @@ public class AltosSerial implements Runnable { public void print(String data) { if (debug) - System.out.printf("%s", data); + pending_output.add(data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } @@ -209,6 +216,8 @@ public class AltosSerial implements Runnable { close(); throw new FileNotFoundException(device.toShortString()); } + if (debug) + System.out.printf("Open %s\n", device.getPath()); input_thread = new Thread(this); input_thread.start(); print("~\nE 0\n"); -- cgit v1.2.3 From fb534aae15f0f1e5d69790e159d0287b6b8a514a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 14:28:35 -0800 Subject: altosui: Use long input flush timeout when remote. 100ms isn't long enough to capture pending remote serial input, so use 300 ms in that mode. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index e609c6b5..f9f9e6e4 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -48,6 +48,7 @@ public class AltosSerial implements Runnable { int line_count; boolean monitor_mode; static boolean debug; + boolean remote; LinkedList pending_output = new LinkedList(); static void set_debug(boolean new_debug) { @@ -126,9 +127,13 @@ public class AltosSerial implements Runnable { public void flush_input() { flush_output(); boolean got_some; + + int timeout = 100; + if (remote) + timeout = 300; do { try { - Thread.sleep(100); + Thread.sleep(timeout); } catch (InterruptedException ie) { } got_some = !reply_queue.isEmpty(); @@ -259,14 +264,21 @@ public class AltosSerial implements Runnable { } public void start_remote() { + if (debug) + System.out.printf("start remote\n"); set_radio(); printf("p\nE 0\n"); flush_input(); + remote = true; } public void stop_remote() { + if (debug) + System.out.printf("stop remote\n"); + flush_input(); printf ("~"); flush_output(); + remote = false; } public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { -- cgit v1.2.3 From 987039b8f0b1d889aca9109d4c6a83f034ff64a7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 14:29:57 -0800 Subject: altosui: Remove debug message when eeprom downloads are complete. This message isn't useful now that this code appears to work. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index af70b15c..f1abd50c 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -180,7 +180,6 @@ public class AltosEepromDownload implements Runnable { CaptureLog(log); } } - System.out.printf("All flights successfully downloaded\n"); success = true; } catch (IOException ee) { show_error (serial_line.device.toShortString(), -- cgit v1.2.3 From 1bfdce6fc3367fdf03e0dc7ddd94da18723b8ba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 14:30:38 -0800 Subject: altosui: Ensure serial device is closed after eeprom download finishes As this code is all event-driven, track which events will trigger further work and block closing the device in those specific cases, ensuring that all other code paths end up closing the device. Signed-off-by: Keith Packard --- altosui/AltosEepromManage.java | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index c7efe478..d10f7954 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -44,7 +44,7 @@ public class AltosEepromManage implements ActionListener { public void finish() { if (serial_line != null) { - serial_line.flush_output(); + serial_line.flush_input(); serial_line.close(); serial_line = null; } @@ -67,14 +67,15 @@ public class AltosEepromManage implements ActionListener { public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); boolean success = e.getID() != 0; + boolean running = false; System.out.printf("Eeprom manager action %s %d\n", cmd, e.getID()); if (cmd.equals("download")) { if (success) { - if (any_delete) + if (any_delete) { delete.start(); - else - finish(); + running = true; + } } } else if (cmd.equals("delete")) { if (success) { @@ -84,12 +85,15 @@ public class AltosEepromManage implements ActionListener { serial_line.device.toShortString(), JOptionPane.INFORMATION_MESSAGE); } - finish(); } + if (!running) + finish(); } public AltosEepromManage(JFrame given_frame) { + boolean running = false; + frame = given_frame; device = AltosDeviceDialog.show(frame, AltosDevice.product_any); @@ -139,15 +143,15 @@ public class AltosEepromManage implements ActionListener { * Start flight log download */ - if (any_download) + if (any_download) { download.start(); - else if (any_delete) + running = true; + } + else if (any_delete) { delete.start(); - else - finish(); + running = true; + } } - } else { - finish(); } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, @@ -166,17 +170,16 @@ public class AltosEepromManage implements ActionListener { device.toShortString(), ee.getLocalizedMessage(), JOptionPane.ERROR_MESSAGE); - finish(); } catch (TimeoutException te) { JOptionPane.showMessageDialog(frame, String.format("Communications failed with \"%s\"", device.toShortString()), "Cannot open target device", JOptionPane.ERROR_MESSAGE); - finish(); } catch (InterruptedException ie) { - finish(); } + if (!running) + finish(); } } } -- cgit v1.2.3 From d0a841b285fb398f0be72183ec3c9d1e358419a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:02:43 -0800 Subject: altosui: Require 4 sats to light up the 'GPS locked' light. This tracks the same GPS signal requirement needed for 'GPS ready' and ensures that we have a 3d fix. Signed-off-by: Keith Packard --- altosui/AltosPad.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 66954347..e345e5da 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -152,7 +152,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class GPSLocked extends LaunchStatus { void show (AltosState state, int crc_errors) { value.setText(String.format("%4d sats", state.gps.nsat)); - lights.set(state.gps.locked); + lights.set(state.gps.locked && state.gps.nsat >= 4); } public GPSLocked (GridBagLayout layout, int y) { super (layout, y, "GPS Locked"); -- cgit v1.2.3 From b22ba359a02297e39a446cbd5ef51e63b795624a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:05:50 -0800 Subject: doc: inkscape tracks the filename inside the document telemetrum-outline.svg was renamed from telemetrum.svg and inkscape appears to care. Signed-off-by: Keith Packard --- doc/telemetrum-outline.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/telemetrum-outline.svg b/doc/telemetrum-outline.svg index 542df64c..aee63ed2 100644 --- a/doc/telemetrum-outline.svg +++ b/doc/telemetrum-outline.svg @@ -14,7 +14,7 @@ id="svg2" version="1.1" inkscape:version="0.47 r22583" - sodipodi:docname="telemetrum.svg"> + sodipodi:docname="telemetrum-outline.svg"> Date: Sat, 15 Jan 2011 16:25:10 -0800 Subject: altos: TELEMETRY PROTOCOL CHANGE. Switch to 16-bit serial numbers. What a terrible mistake! The flight computer serial numbers were recorded in only 8 bits, so serial numbers > 255 would get truncated. There's really no fix other than bumping the field to 16 bits and reflashing every TM and TD on the planet. Very unfortunate. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_monitor.c | 4 ++-- src/ao_telemetry.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index 37a39a79..5721c344 100644 --- a/src/ao.h +++ b/src/ao.h @@ -856,7 +856,7 @@ ao_gps_report_init(void); #define AO_TELEMETRY_VERSION 3 struct ao_telemetry { - uint8_t addr; + uint16_t serial; uint16_t flight; uint8_t flight_state; int16_t flight_accel; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 1e7f5102..4ba3da6d 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -41,10 +41,10 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %3d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", + printf("VERSION %d CALL %s SERIAL %d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", AO_TELEMETRY_VERSION, callsign, - recv.telemetry.addr, + recv.telemetry.serial, recv.telemetry.flight, rssi, recv.status, ao_state_names[state]); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 22ab1d67..7aad929f 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -33,7 +33,7 @@ ao_telemetry(void) while (!ao_flight_number) ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.addr = ao_serial_number; + telemetry.serial = ao_serial_number; telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; -- cgit v1.2.3 From 7a35b2d7048669a96256d4ea0086299f8a0cb1df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 22:42:38 -0800 Subject: altos: Flush log when full When the log storage is full, make sure any pending writes are flushed out so that the last bit isn't lost. Signed-off-by: Keith Packard --- src/ao_log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ao_log.c b/src/ao_log.c index 8666482b..fa072550 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -42,8 +42,8 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos) - ao_log_running = 0; + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); if (ao_log_running) { wrote = 1; ao_storage_write(ao_log_current_pos, -- cgit v1.2.3 From 8a775b8f9ecefa143050653d74dfd218b32b9bb5 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 16 Jan 2011 10:54:45 +1000 Subject: altos: Restructure skytraq NMEA parsing code to save some space Splitting this into several smaller functions appears to make SDCC generate better code. --- src/ao_gps_skytraq.c | 401 +++++++++++++++++++++++++++------------------------ 1 file changed, 212 insertions(+), 189 deletions(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 2d3d464c..a2d5f1db 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -180,6 +180,215 @@ ao_gps_parse_flag(char no_c, char yes_c) __reentrant return ret; } +static void +ao_nmea_gga() +{ + uint8_t i; + + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next_tick = ao_time(); + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + ao_gps_next.hdop = ao_gps_decimal(0xff); + if (ao_gps_next.hdop <= 50) { + ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + if (ao_gps_char == '.') + ao_gps_next.hdop = (ao_gps_next.hdop + + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + ao_gps_next.hdop = 255; + ao_gps_skip_field(); + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; + memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } +} + +static void +ao_nmea_gsv(void) +{ + char c; + uint8_t i; + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + 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; + 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 */ + 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 ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } +} + +static void +ao_nmea_rmc(void) +{ + char a, c; + uint8_t i; + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } +} void ao_gps(void) __reentrant @@ -222,197 +431,11 @@ ao_gps(void) __reentrant continue; if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { - /* Now read the data into the gps data record - * - * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 - * - * Essential fix data - * - * 025149.000 time (02:51:49.000 GMT) - * 4528.1723,N Latitude 45°28.1723' N - * 12244.2480,W Longitude 122°44.2480' W - * 1 Fix quality: - * 0 = invalid - * 1 = GPS fix (SPS) - * 2 = DGPS fix - * 3 = PPS fix - * 4 = Real Time Kinematic - * 5 = Float RTK - * 6 = estimated (dead reckoning) - * 7 = Manual input mode - * 8 = Simulation mode - * 05 Number of satellites (5) - * 2.0 Horizontal dilution - * 103.5,M Altitude, 103.5M above msl - * -19.5,M Height of geoid above WGS84 ellipsoid - * ? time in seconds since last DGPS update - * 0000 DGPS station ID - * *66 checksum - */ - - ao_gps_next_tick = ao_time(); - ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; - ao_gps_next.hour = ao_gps_decimal(2); - ao_gps_next.minute = ao_gps_decimal(2); - ao_gps_next.second = ao_gps_decimal(2); - ao_gps_skip_field(); /* skip seconds fraction */ - - ao_gps_next.latitude = ao_gps_parse_pos(2); - if (ao_gps_parse_flag('N', 'S')) - ao_gps_next.latitude = -ao_gps_next.latitude; - ao_gps_next.longitude = ao_gps_parse_pos(3); - if (ao_gps_parse_flag('E', 'W')) - ao_gps_next.longitude = -ao_gps_next.longitude; - - i = ao_gps_decimal(0xff); - if (i == 1) - ao_gps_next.flags |= AO_GPS_VALID; - - i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; - if (i > AO_GPS_NUM_SAT_MASK) - i = AO_GPS_NUM_SAT_MASK; - ao_gps_next.flags |= i; - - ao_gps_lexchar(); - ao_gps_next.hdop = ao_gps_decimal(0xff); - if (ao_gps_next.hdop <= 50) { - ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; - if (ao_gps_char == '.') - ao_gps_next.hdop = (ao_gps_next.hdop + - ((uint8_t) ao_gps_decimal(1) >> 1)); - } else - ao_gps_next.hdop = 255; - ao_gps_skip_field(); - - ao_gps_next.altitude = ao_gps_decimal(0xff); - ao_gps_skip_field(); /* skip any fractional portion */ - - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - } + ao_nmea_gga(); } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { - uint8_t done; - /* Now read the data into the GPS tracking data record - * - * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 - * - * Satellites in view data - * - * 3 Total number of GSV messages - * 1 Sequence number of current GSV message - * 12 Total sats in view (0-12) - * 05 SVID - * 54 Elevation - * 069 Azimuth - * 45 C/N0 in dB - * ... other SVIDs - * 72 checksum - */ - c = ao_gps_decimal(1); /* total messages */ - i = ao_gps_decimal(1); /* message sequence */ - if (i == 1) { - ao_gps_tracking_next.channels = 0; - } - done = (uint8_t) c == i; - ao_gps_lexchar(); - 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; - 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 */ - 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 ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } - else - ao_gps_error = 1; - if (ao_gps_error) - ao_gps_tracking_next.channels = 0; - else if (done) { - ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - } + ao_nmea_gsv(); } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { - /* Parse the RMC record to read out the current date */ - - /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 - * - * Recommended Minimum Specific GNSS Data - * - * 111636.932 UTC time 11:16:36.932 - * A Data Valid (V = receiver warning) - * 2447.0949 Latitude - * N North/south indicator - * 12100.5223 Longitude - * E East/west indicator - * 000.0 Speed over ground - * 000.0 Course over ground - * 030407 UTC date (ddmmyy format) - * A Mode indicator: - * N = data not valid - * A = autonomous mode - * D = differential mode - * E = estimated (dead reckoning) mode - * M = manual input mode - * S = simulator mode - * 61 checksum - */ - ao_gps_skip_field(); - for (i = 0; i < 8; i++) { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - a = ao_gps_decimal(2); - c = ao_gps_decimal(2); - i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_gps_next.year = i; - ao_gps_next.month = c; - ao_gps_next.day = a; - ao_gps_date_flags = AO_GPS_DATE_VALID; - } + ao_nmea_rmc(); } } } -- cgit v1.2.3 From 118fe84c9ff1cc9d1653e67a2315e22e19d60a14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 11:26:31 -0800 Subject: altos: average 512 accel/baro samples at startup instead of 1000 This lets us use a simple shift instead of a divide, saving a huge amount of code space. Signed-off-by: Keith Packard --- src/ao_flight.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 7fe85cb1..9f651ae2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -196,17 +196,17 @@ ao_flight(void) /* startup state: * - * Collect 1000 samples of acceleration and pressure + * Collect 512 samples of acceleration and pressure * data and average them to find the resting values */ - if (nsamples < 1000) { + if (nsamples < 512) { ao_raw_accel_sum += ao_raw_accel; ao_raw_pres_sum += ao_raw_pres; ++nsamples; continue; } - ao_ground_accel = (ao_raw_accel_sum / nsamples); - ao_ground_pres = (ao_raw_pres_sum / nsamples); + ao_ground_accel = ao_raw_accel_sum >> 9; + ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); -- cgit v1.2.3 From 58838c0b96a91da0bd0cd77c3ff312b589c08136 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sat, 15 Jan 2011 23:21:26 +1300 Subject: altos: Added check for an accel value above 1.5g When detecting flight or idle mode, this should indicate that accel cal values are out of whack. Signed-off-by: Mike Beattie --- src/ao_flight.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_flight.c b/src/ao_flight.c index 9f651ae2..5a9a8d80 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -221,6 +221,7 @@ ao_flight(void) if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + ao_flight_accel > ao_config.accel_plus_g - ACCEL_NOSE_UP && !ao_flight_force_idle) { /* Disable the USB controller in flight mode -- cgit v1.2.3 From add2802a8a33336180fe6856241a7f4a8200e89c Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 16 Jan 2011 00:10:30 +1300 Subject: altos: Added check for out of bounds accel Chose invalid flight mode instead of idle to give user feedback. Signed-off-by: Mike Beattie --- src/ao_flight.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 5a9a8d80..01dbb11b 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -237,9 +237,18 @@ ao_flight(void) ao_flight_state = ao_flight_pad; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } else { - ao_flight_state = ao_flight_idle; + if (ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * -> invalid mode + */ + ao_flight_state = ao_flight_invalid; + } else { + ao_flight_state = ao_flight_idle; + } - /* Turn on packet system in idle mode + /* Turn on packet system in idle or invalid mode */ ao_packet_slave_start(); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From ab31b1c737d8fd32af482e5b06699f1b832a25a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 00:56:22 -0800 Subject: altos: Add DATA_TO_XDATA to linux test harness The flight test harness needs to expose every function used by the flight code in some form, and this macro is about to become used. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 2bf7f2b2..e0cfa47a 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -154,6 +154,8 @@ struct ao_config { struct ao_config ao_config = { 250, 15937, 16467 }; +#define DATA_TO_XDATA(x) (x) + #include "ao_flight.c" void -- cgit v1.2.3 From 3566dee1cf83870396a0bb164f5549dd3faf58f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 14:40:31 -0800 Subject: altosui: Remove spurious colons from eeprom selection headers This colons make the presentation a bit confusing. Signed-off-by: Keith Packard --- altosui/AltosEepromSelect.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index f0066aac..a3069f06 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -119,7 +119,7 @@ public class AltosEepromSelect extends JDialog implements ActionListener { c.weightx = 0.5; c.anchor = GridBagConstraints.CENTER; c.insets = i; - JLabel flightHeaderLabel = new JLabel("Flight:"); + JLabel flightHeaderLabel = new JLabel("Flight"); flightPane.add(flightHeaderLabel, c); /* Download Header */ @@ -129,7 +129,7 @@ public class AltosEepromSelect extends JDialog implements ActionListener { c.weightx = 0.5; c.anchor = GridBagConstraints.CENTER; c.insets = i; - JLabel downloadHeaderLabel = new JLabel("Download:"); + JLabel downloadHeaderLabel = new JLabel("Download"); flightPane.add(downloadHeaderLabel, c); /* Delete Header */ @@ -139,7 +139,7 @@ public class AltosEepromSelect extends JDialog implements ActionListener { c.weightx = 0.5; c.anchor = GridBagConstraints.CENTER; c.insets = i; - JLabel deleteHeaderLabel = new JLabel("Delete:"); + JLabel deleteHeaderLabel = new JLabel("Delete"); flightPane.add(deleteHeaderLabel, c); /* Add the flights to the GridBag */ -- cgit v1.2.3 From afd3d3cdb8c2291c1c7cda7908392d68cd04f87f Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 17 Jan 2011 15:03:40 +1300 Subject: Rework invalid accel cal detection code Slightly reduces code space. Uncalibrated accelerometer now enters invalid state as well. Signed-off-by: Mike Beattie --- src/ao_flight.c | 63 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 01dbb11b..e99692a3 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -216,45 +216,56 @@ ao_flight(void) ao_old_vel = ao_flight_vel; ao_old_vel_tick = ao_flight_tick; - /* Go to pad state if the nose is pointing up */ + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ ao_config_get(); - if (ao_config.accel_plus_g != 0 && - ao_config.accel_minus_g != 0 && - ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && - ao_flight_accel > ao_config.accel_plus_g - ACCEL_NOSE_UP && - !ao_flight_force_idle) + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + /* Allow packet mode in invalid flight state, + * Still need to be able to fix the problem! + */ + ao_packet_slave_start(); + + } else if (ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + !ao_flight_force_idle) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; + /* Disable the USB controller in flight mode * to save power */ ao_usb_disable(); - /* Turn on telemetry system - */ + /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - ao_flight_state = ao_flight_pad; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); } else { - if (ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * -> invalid mode - */ - ao_flight_state = ao_flight_invalid; - } else { - ao_flight_state = ao_flight_idle; - } - - /* Turn on packet system in idle or invalid mode - */ + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + + /* Turn on packet system in idle mode */ ao_packet_slave_start(); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); } - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; case ao_flight_pad: -- cgit v1.2.3 From 1b8d7313504240ed04e0747e9b0f6e9a83d323e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 15:57:15 -0800 Subject: altos: Auto-calibrate linux-based flight testing code Use the provided ground acceleration average to set the two accelerometer calibration values so that the flight code will detect pad/idle mode correctly. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e0cfa47a..108d2c19 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -238,6 +238,8 @@ ao_sleep(void *wchan) switch (type) { case 'F': ao_flight_ground_accel = a; + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; ao_flight_started = 1; break; case 'S': -- cgit v1.2.3 From 69290588980bb15732a99eca5c911a3b6e9a37b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:12:02 -0800 Subject: altos: Ensure flight code gets first crack at new ADC data Instead of having everyone wait on the raw ADC ring, have the flight code wait on that and have everyone else wait for the flight code to finish looking at the data and move its pointer forwards. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_adc.c | 10 ++-------- src/ao_config.c | 6 +++--- src/ao_flight.c | 3 ++- src/ao_flight_test.c | 2 +- src/ao_ignite.c | 1 - src/ao_log.c | 4 ++-- src/ao_test.c | 2 +- 8 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/ao.h b/src/ao.h index 5721c344..abac22a3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -649,7 +649,7 @@ enum ao_flight_state { ao_flight_invalid = 9 }; -extern __xdata struct ao_adc ao_flight_data; +extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_flight_tick; extern __pdata int16_t ao_flight_accel; diff --git a/src/ao_adc.c b/src/ao_adc.c index 49d2519e..f577b458 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -27,16 +27,10 @@ ao_adc_poll(void) ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; } -void -ao_adc_sleep(void) -{ - ao_sleep(&ao_adc_ring); -} - void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); + uint8_t i = ao_adc_ring_prev(ao_flight_adc); memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } @@ -65,7 +59,7 @@ ao_adc_isr(void) __interrupt 1 /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(ao_adc_ring); + ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); } } diff --git a/src/ao_config.c b/src/ao_config.c index e97b7eb1..bbee3b44 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -209,10 +209,10 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_adc_head; + cal_adc_ring = ao_flight_adc; while (i) { - ao_sleep(&ao_adc_ring); - while (i && cal_adc_ring != ao_adc_head) { + ao_sleep(DATA_TO_XDATA(&ao_flight_adc)); + while (i && cal_adc_ring != ao_flight_adc) { accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; cal_adc_ring = ao_adc_ring_next(cal_adc_ring); i--; diff --git a/src/ao_flight.c b/src/ao_flight.c index e99692a3..9eb9a014 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -146,7 +146,8 @@ ao_flight(void) ao_raw_pres = 0; ao_flight_tick = 0; for (;;) { - ao_sleep(&ao_adc_ring); + ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { __pdata uint8_t ticks; __pdata int16_t ao_vel_change; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 108d2c19..5c619518 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -180,7 +180,7 @@ void ao_sleep(void *wchan) { ao_dump_state(); - if (wchan == &ao_adc_ring) { + if (wchan == &ao_adc_head) { char type; uint16_t tick; uint16_t a, b; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index f2b15dd2..603fcd25 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -52,7 +52,6 @@ ao_igniter_status(enum ao_igniter igniter) __xdata uint8_t request, firing, fired; __critical { - ao_adc_sleep(); ao_adc_get(&adc); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; diff --git a/src/ao_log.c b/src/ao_log.c index fa072550..099c5f6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -99,10 +99,10 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_adc_head) { + while (ao_log_adc_pos != ao_flight_adc) { log.type = AO_LOG_SENSOR; log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; diff --git a/src/ao_test.c b/src/ao_test.c index b9f7d338..14c2eb75 100644 --- a/src/ao_test.c +++ b/src/ao_test.c @@ -53,7 +53,7 @@ blink_1(void) static __xdata struct ao_adc adc; for (;;) { - ao_sleep(&ao_adc_ring); + ao_sleep(&ao_adc_head); ao_adc_get(&adc); if (adc.accel < 15900) ao_led_on(AO_LED_RED); -- cgit v1.2.3 From 2681a17500913cbaf3966f09380bb1d6b59e3863 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:18:32 -0800 Subject: altos: Sample the accelerometer reference voltage on v1.1 boards This places the 5v reference samples in an array parallel to the basic ADC values. It doesn't do anything with the values, just stores them. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_adc.c | 28 ++++++++++++++++++++++------ src/ao_pins.h | 3 +++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/ao.h b/src/ao.h index abac22a3..cef20e61 100644 --- a/src/ao.h +++ b/src/ao.h @@ -163,6 +163,11 @@ struct ao_adc { #endif #if HAS_ADC + +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif + /* * ao_adc.c */ @@ -178,6 +183,9 @@ struct ao_adc { */ extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif /* Trigger a conversion sequence (called from the timer interrupt) */ void diff --git a/src/ao_adc.c b/src/ao_adc.c index f577b458..3adf9b2e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -19,12 +19,19 @@ #include "ao_pins.h" volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +#if HAS_ACCEL_REF +volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif volatile __data uint8_t ao_adc_head; void ao_adc_poll(void) { +#if HAS_ACCEL_REF + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; +#else ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +#endif } void @@ -41,20 +48,29 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; - if (sequence == ADCCON3_ECH_TEMP) - sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); +#if HAS_ACCEL_REF + if (sequence == 2) { + a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + sequence = 0; + } else +#endif + { + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + sequence++; + } a[0] = ADCL; a[1] = ADCH; - if (sequence < 5) { + if (sequence < 6) { #if HAS_EXTERNAL_TEMP == 0 /* start next channel conversion */ /* v0.2 replaces external temp sensor with internal one */ - if (sequence == 1) + if (sequence == 2) ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; else #endif - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); diff --git a/src/ao_pins.h b/src/ao_pins.h index 9446964e..2c5b9db5 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -31,6 +31,7 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 #endif #if defined(TELEMETRUM_V_1_1) @@ -46,6 +47,7 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ @@ -81,6 +83,7 @@ #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #endif -- cgit v1.2.3 From 2887fe7affc0706dbeb2f04df9a00a9b799903ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:25:57 -0800 Subject: altos: Optimize fetching of ADC data in flight code This stores the address of the desired sample in a local variable and then fetches through that. Saves quite a few instructions. Signed-off-by: Keith Packard --- src/ao_flight.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 9eb9a014..637acd52 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -151,12 +151,14 @@ ao_flight(void) while (ao_flight_adc != ao_adc_head) { __pdata uint8_t ticks; __pdata int16_t ao_vel_change; + __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; /* Capture a sample */ - ao_raw_accel = ao_adc_ring[ao_flight_adc].accel; - ao_raw_pres = ao_adc_ring[ao_flight_adc].pres; - ao_flight_tick = ao_adc_ring[ao_flight_adc].tick; + ao_adc = &ao_adc_ring[ao_flight_adc]; + ao_flight_tick = ao_adc->tick; + ao_raw_accel = ao_adc->accel; + ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; ao_flight_accel += ao_raw_accel >> 4; -- cgit v1.2.3 From 4b71c4f4ed6cae23a7f4a2e7ae697da9ec614898 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:26:53 -0800 Subject: altos: Use 5V reference data to correct accelerometer measurements. When the 3.3V and 5V values shift relative to each other (usually due to changes in power consumption), the measured acceleration will appear to shift. This patch converts the 3.3V referenced acceleration value into a 5V referenced acceleration, eliminating this error. Signed-off-by: Keith Packard --- src/ao_flight.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/ao_flight.c b/src/ao_flight.c index 637acd52..81aecad3 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -158,6 +158,90 @@ ao_flight(void) ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; ao_raw_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_raw_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_raw_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_raw_accel 32767 + * = ------------ * ------------ + * 32737 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_raw_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_raw_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_raw_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_raw_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_raw_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; + ao_adc->accel = ao_raw_accel; +#endif ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; -- cgit v1.2.3 From cf550f9b96fa94d8db559e01df0e265bb1c7b572 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 23:23:45 -0800 Subject: doc: Remove mention of ao_wake_task This has been removed from the altos sources, so remove it from the docs too. Signed-off-by: Keith Packard --- doc/altos.xsl | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/doc/altos.xsl b/doc/altos.xsl index 295864fe..37bb58da 100644 --- a/doc/altos.xsl +++ b/doc/altos.xsl @@ -385,17 +385,6 @@ will abort the radio receive operation.
-
- ao_wake_task - - void - ao_wake_task(__xdata struct ao_task *task) - - - Force a specific task to wake up, independent of which - 'wchan' it is waiting for. - -
ao_start_scheduler -- cgit v1.2.3 From ea4cdfb87e03ecfb974f98305671265b6fb95372 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 17 Jan 2011 09:49:45 -0700 Subject: update documentation to reflect reality that modifying a board or separate pyro battery is not as simple as one trace cut on v1.0 and v1.1 boards --- doc/altusmetrum.xsl | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 7a80ba13..937be079 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -373,8 +373,8 @@ NAR #88757, TRA #12200 - Uses LiPo to fire e-matches, support for optional separate pyro - battery if needed. + Uses LiPo to fire e-matches, can be modiied to support + optional separate pyro battery if needed. @@ -449,11 +449,10 @@ NAR #88757, TRA #12200 to fire ejection charges. This works marvelously with standard low-current e-matches like the J-Tek from MJG Technologies, and with Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, you can do so by adding - a second 2mm connector to position B2 on the board and cutting the - thick pcb trace connecting the LiPo battery to the pyro circuit between - the two silk screen marks on the surface mount side of the board shown - here [insert photo] + want or need to use a separate pyro battery, the board can be factory + modified to do so. This involves cutting two traces and adding a jumper + in a densely populated part of the board on TeleMetrum v1.0 and v1.1, + along with installation of a pyro battery connector at location B2. We offer two choices of pyro and power switch connector, or you can -- cgit v1.2.3 From c411dce69be58238b8312c2fd7405cbe8b5d4a5a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 17:27:11 -0700 Subject: update changelogs for Debian build --- ChangeLog | 302 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 54 ++++++++++ 2 files changed, 356 insertions(+) diff --git a/ChangeLog b/ChangeLog index aa5cc6f8..ff2c451a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,305 @@ +commit da42f406e88ccc821cd45d5a94d5afec65ec50e9 +Merge: ea4cdfb cf550f9 +Author: Bdale Garbee +Date: Mon Jan 17 09:50:17 2011 -0700 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit ea4cdfb87e03ecfb974f98305671265b6fb95372 +Author: Bdale Garbee +Date: Mon Jan 17 09:49:45 2011 -0700 + + update documentation to reflect reality that modifying a board or separate + pyro battery is not as simple as one trace cut on v1.0 and v1.1 boards + +commit cf550f9b96fa94d8db559e01df0e265bb1c7b572 +Author: Keith Packard +Date: Sun Jan 16 23:23:45 2011 -0800 + + doc: Remove mention of ao_wake_task + + This has been removed from the altos sources, so remove it from the + docs too. + + Signed-off-by: Keith Packard + +commit 4b71c4f4ed6cae23a7f4a2e7ae697da9ec614898 +Author: Keith Packard +Date: Sat Jan 15 12:26:53 2011 -0800 + + altos: Use 5V reference data to correct accelerometer measurements. + + When the 3.3V and 5V values shift relative to each other (usually due + to changes in power consumption), the measured acceleration will + appear to shift. This patch converts the 3.3V referenced acceleration + value into a 5V referenced acceleration, eliminating this error. + + Signed-off-by: Keith Packard + +commit 2887fe7affc0706dbeb2f04df9a00a9b799903ed +Author: Keith Packard +Date: Sat Jan 15 12:25:57 2011 -0800 + + altos: Optimize fetching of ADC data in flight code + + This stores the address of the desired sample in a local variable and + then fetches through that. Saves quite a few instructions. + + Signed-off-by: Keith Packard + +commit 2681a17500913cbaf3966f09380bb1d6b59e3863 +Author: Keith Packard +Date: Sat Jan 15 12:18:32 2011 -0800 + + altos: Sample the accelerometer reference voltage on v1.1 boards + + This places the 5v reference samples in an array parallel to the basic + ADC values. It doesn't do anything with the values, just stores them. + + Signed-off-by: Keith Packard + +commit 69290588980bb15732a99eca5c911a3b6e9a37b9 +Author: Keith Packard +Date: Sat Jan 15 12:12:02 2011 -0800 + + altos: Ensure flight code gets first crack at new ADC data + + Instead of having everyone wait on the raw ADC ring, have the flight + code wait on that and have everyone else wait for the flight code to + finish looking at the data and move its pointer forwards. + + Signed-off-by: Keith Packard + +commit 1b8d7313504240ed04e0747e9b0f6e9a83d323e2 +Author: Keith Packard +Date: Sun Jan 16 15:57:15 2011 -0800 + + altos: Auto-calibrate linux-based flight testing code + + Use the provided ground acceleration average to set the two + accelerometer calibration values so that the flight code will + detect pad/idle mode correctly. + + Signed-off-by: Keith Packard + +commit afd3d3cdb8c2291c1c7cda7908392d68cd04f87f +Author: Mike Beattie +Date: Mon Jan 17 15:03:40 2011 +1300 + + Rework invalid accel cal detection code + + Slightly reduces code space. + + Uncalibrated accelerometer now enters invalid state as well. + + Signed-off-by: Mike Beattie + +commit 3566dee1cf83870396a0bb164f5549dd3faf58f5 +Author: Keith Packard +Date: Sun Jan 16 14:40:31 2011 -0800 + + altosui: Remove spurious colons from eeprom selection headers + + This colons make the presentation a bit confusing. + + Signed-off-by: Keith Packard + +commit ab31b1c737d8fd32af482e5b06699f1b832a25a1 +Author: Keith Packard +Date: Sat Jan 15 00:56:22 2011 -0800 + + altos: Add DATA_TO_XDATA to linux test harness + + The flight test harness needs to expose every function used by the + flight code in some form, and this macro is about to become used. + + Signed-off-by: Keith Packard + +commit add2802a8a33336180fe6856241a7f4a8200e89c +Author: Mike Beattie +Date: Sun Jan 16 00:10:30 2011 +1300 + + altos: Added check for out of bounds accel + + Chose invalid flight mode instead of idle to give user feedback. + + Signed-off-by: Mike Beattie + +commit 58838c0b96a91da0bd0cd77c3ff312b589c08136 +Author: Mike Beattie +Date: Sat Jan 15 23:21:26 2011 +1300 + + altos: Added check for an accel value above 1.5g + + When detecting flight or idle mode, this should indicate + that accel cal values are out of whack. + + Signed-off-by: Mike Beattie + +commit 118fe84c9ff1cc9d1653e67a2315e22e19d60a14 +Author: Keith Packard +Date: Sat Jan 15 11:26:31 2011 -0800 + + altos: average 512 accel/baro samples at startup instead of 1000 + + This lets us use a simple shift instead of a divide, saving a huge + amount of code space. + + Signed-off-by: Keith Packard + +commit 8a775b8f9ecefa143050653d74dfd218b32b9bb5 +Author: Anthony Towns +Date: Sun Jan 16 10:54:45 2011 +1000 + + altos: Restructure skytraq NMEA parsing code to save some space + + Splitting this into several smaller functions appears to make SDCC + generate better code. + +commit 7a35b2d7048669a96256d4ea0086299f8a0cb1df +Author: Keith Packard +Date: Sat Jan 15 22:42:38 2011 -0800 + + altos: Flush log when full + + When the log storage is full, make sure any pending writes are flushed + out so that the last bit isn't lost. + + Signed-off-by: Keith Packard + +commit 47ee4597e55749e8f66f61a585ea32776979bf80 +Author: Keith Packard +Date: Sat Jan 15 16:25:10 2011 -0800 + + altos: TELEMETRY PROTOCOL CHANGE. Switch to 16-bit serial numbers. + + What a terrible mistake! The flight computer serial numbers were + recorded in only 8 bits, so serial numbers > 255 would get truncated. + + There's really no fix other than bumping the field to 16 bits and + reflashing every TM and TD on the planet. Very unfortunate. + + Signed-off-by: Keith Packard + +commit b22ba359a02297e39a446cbd5ef51e63b795624a +Author: Keith Packard +Date: Sat Jan 15 12:05:50 2011 -0800 + + doc: inkscape tracks the filename inside the document + + telemetrum-outline.svg was renamed from telemetrum.svg and inkscape + appears to care. + + Signed-off-by: Keith Packard + +commit d0a841b285fb398f0be72183ec3c9d1e358419a9 +Author: Keith Packard +Date: Sat Jan 15 12:02:43 2011 -0800 + + altosui: Require 4 sats to light up the 'GPS locked' light. + + This tracks the same GPS signal requirement needed for 'GPS ready' and + ensures that we have a 3d fix. + + Signed-off-by: Keith Packard + +commit 1bfdce6fc3367fdf03e0dc7ddd94da18723b8ba3 +Author: Keith Packard +Date: Sun Jan 16 14:30:38 2011 -0800 + + altosui: Ensure serial device is closed after eeprom download finishes + + As this code is all event-driven, track which events will trigger + further work and block closing the device in those specific cases, + ensuring that all other code paths end up closing the device. + + Signed-off-by: Keith Packard + +commit 987039b8f0b1d889aca9109d4c6a83f034ff64a7 +Author: Keith Packard +Date: Sun Jan 16 14:29:57 2011 -0800 + + altosui: Remove debug message when eeprom downloads are complete. + + This message isn't useful now that this code appears to work. + + Signed-off-by: Keith Packard + +commit fb534aae15f0f1e5d69790e159d0287b6b8a514a +Author: Keith Packard +Date: Sun Jan 16 14:28:35 2011 -0800 + + altosui: Use long input flush timeout when remote. + + 100ms isn't long enough to capture pending remote serial input, so use + 300 ms in that mode. + + Signed-off-by: Keith Packard + +commit d4add23186b3586c99579d83efdc003f79e9bf7a +Author: Keith Packard +Date: Sun Jan 16 14:26:18 2011 -0800 + + altosui: Make serial debug more complete and accurate + + Display all serial input, including telemetry. + Wait to display serial output until flush time, to debug missing flushing. + Show when devices are opened and closed. + + Signed-off-by: Keith Packard + +commit deb3c7b9206be0c9c46f75d35c8f766c26d9838f +Author: Keith Packard +Date: Sat Jan 15 22:43:37 2011 -0800 + + altosui: Reset eeprom download instance variables before reading flight + + To deal with downloading multiple flights in a single invocation, make + sure all relevant instance variables are set back to start of flight + download values each time a log is read. + + Signed-off-by: Keith Packard + +commit eec9eb2e81535e62c52fbb2e57a2d33f88f92c1a +Author: Mike Beattie +Date: Mon Jan 17 07:56:53 2011 +1300 + + Close serial port if Download/Delete dialog is cancelled. + + Signed-off-by: Mike Beattie + +commit df1c6ab3ac079199b5a12328c9ff5cfa6ac29b36 +Author: Mike Beattie +Date: Mon Jan 17 00:40:07 2011 +1300 + + Convert EepromSelect dialog to use a GridBag + + Signed-off-by: Mike Beattie + +commit fef302656f21ae0ab4772f72979cbb7f071da89a +Author: Mike Beattie +Date: Sun Jan 16 20:25:19 2011 +1300 + + Re-order and re-arrange eeprom download dialog + + Signed-off-by: Mike Beattie + +commit 35adb7c98fe02e84fff70c1bee22bfa019cfacc2 +Author: Keith Packard +Date: Fri Jan 14 21:44:59 2011 -0800 + + doc: Add telemetrum mounting template in svg and pdf forms + + telemetrum-outline.svg and telemetrum-outline.pdf + + Signed-off-by: Keith Packard + +commit fdba0f24afd59becc499d750bbdb80aea86066ac +Author: Bdale Garbee +Date: Fri Jan 14 18:01:16 2011 -0700 + + update changelogs for Debian build + commit 646e1926cdf56e2cf2425413ce716e6999b64a58 Author: Bdale Garbee Date: Fri Jan 14 18:01:00 2011 -0700 diff --git a/debian/changelog b/debian/changelog index 836b47d3..0d525f42 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,57 @@ +altos (0.8.1+71+gda42f40) unstable; urgency=low + + [ Keith Packard ] + * doc: Add telemetrum mounting template in svg and pdf forms + + [ Mike Beattie ] + * Re-order and re-arrange eeprom download dialog + * Convert EepromSelect dialog to use a GridBag + * Close serial port if Download/Delete dialog is cancelled. + + [ Keith Packard ] + * altosui: Reset eeprom download instance variables before reading + flight + * altosui: Make serial debug more complete and accurate + * altosui: Use long input flush timeout when remote. + * altosui: Remove debug message when eeprom downloads are complete. + * altosui: Ensure serial device is closed after eeprom download + finishes + * altosui: Require 4 sats to light up the 'GPS locked' light. + * doc: inkscape tracks the filename inside the document + * altos: TELEMETRY PROTOCOL CHANGE. Switch to 16-bit serial numbers. + * altos: Flush log when full + + [ Anthony Towns ] + * altos: Restructure skytraq NMEA parsing code to save some space + + [ Keith Packard ] + * altos: average 512 accel/baro samples at startup instead of 1000 + + [ Mike Beattie ] + * altos: Added check for an accel value above 1.5g + * altos: Added check for out of bounds accel + + [ Keith Packard ] + * altos: Add DATA_TO_XDATA to linux test harness + * altosui: Remove spurious colons from eeprom selection headers + + [ Mike Beattie ] + * Rework invalid accel cal detection code + + [ Keith Packard ] + * altos: Auto-calibrate linux-based flight testing code + * altos: Ensure flight code gets first crack at new ADC data + * altos: Sample the accelerometer reference voltage on v1.1 boards + * altos: Optimize fetching of ADC data in flight code + * altos: Use 5V reference data to correct accelerometer measurements. + * doc: Remove mention of ao_wake_task + + [ Bdale Garbee ] + * update documentation to reflect reality that modifying a board for + separate pyro battery is not trivial + + -- Bdale Garbee Tue, 18 Jan 2011 17:26:33 -0700 + altos (0.8.1+42+g646e192) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 92d7841edcfc8a841f71f7f97cc541f8e55c4627 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Jan 2011 20:39:30 -0800 Subject: doc: Don't delete telemetrum-outline.pdf This has a drilling template for the board. Signed-off-by: Keith Packard --- doc/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index ef3ef6d1..ea030189 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -31,10 +31,10 @@ publish: $(DOC) git push) clean: - rm -f *.html *.pdf *.fo + rm -f $(HTML) $(PDF) *.fo distclean: - rm -f *.html *.pdf *.fo + rm -f $(HTML) $(PDF) *.fo indent: altusmetrum.xsl xmlindent -i 2 < altusmetrum.xsl > altusmetrum.new -- cgit v1.2.3 From 27e6dbbe95ae9b361d60576e0cbadb66792307f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Jan 2011 20:39:58 -0800 Subject: doc: Add v0.9 features from altosui to documentation. New flight download UI and new config items. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 937be079..476b48aa 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1289,9 +1289,20 @@ NAR #88757, TRA #12200 on Packet Command Mode for more information about this. - The filename for the data is computed automatically from the recorded - flight date, TeleMetrum serial number and flight number - information. + After the device has been selected, a dialog showing the + flight data saved in the device will be shown allowing you to + select which flights to download and which to delete. With + version 0.9 or newer firmware, you must erase flights in order + for the space they consume to be reused by another + flight. This prevents you from accidentally losing flight data + if you neglect to download data before flying again. Note that + if there is no more space available in the device, then no + data will be recorded for a flight. + + + The filename for each flight log is computed automatically + from the recorded flight date, TeleMetrum serial number and + flight number information.
@@ -1476,6 +1487,35 @@ NAR #88757, TRA #12200 as needed to conform to your local radio regulations.
+
+ Maximum Flight Log Size + + This sets the space (in kilobytes) allocated for each flight + log. The available space will be divided into chunks of this + size. A smaller value will allow more flights to be stored, + a larger value will record data from longer flights. + + + During ascent, TeleMetrum records barometer and + accelerometer values 100 times per second, other analog + information (voltages and temperature) 6 times per second + and GPS data once per second. During descent, the non-GPS + data is recorded 1/10th as often. Each barometer + + accelerometer record takes 8 bytes. + + + The default, 192kB, will store over 200 seconds of data at + the ascent rate, or over 2000 seconds of data at the descent + rate. That's plenty for most flights. This leaves enough + storage for five flights in a 1MB system, or 10 flights in a + 2MB system. + + + The configuration block takes the last available block of + memory, on v1.0 boards that's just 256 bytes. However, the + flash part on the v1.1 boards uses 64kB for each block. + +
Configure AltosUI @@ -1527,6 +1567,16 @@ NAR #88757, TRA #12200 your local radio regulations.
+
+ Serial Debug + + This causes all communication with a connected device to be + dumped to the console from which AltosUI was started. If + you've started it from an icon or menu entry, the output + will simply be discarded. This mode can be useful to debug + various serial communication issues. + +
Flash Image -- cgit v1.2.3 From e2e20f6ce8a9c2bca36fde5730ccd7151377ec6f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 23:18:42 -0700 Subject: add 0.9 revision entry, with caveat about telemetry format change --- doc/altusmetrum.xsl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 476b48aa..a2a9e331 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -34,6 +34,17 @@ license. + + + 0.9 + 18 January 2011 + + Updated for software version 0.9. Note that 0.9 represents a + telemetry format change, meaning both ends of a link (TeleMetrum and + TeleDongle) must be updated or communications will fail. + + + 0.8 -- cgit v1.2.3 From 26c4cc3054b1c7c9ed6ce3c2f21f6254b3245718 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 23:29:03 -0700 Subject: freshen copyright year --- debian/copyright | 4 ++-- doc/altusmetrum.xsl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/copyright b/debian/copyright index 7d9a469e..50cbcd80 100644 --- a/debian/copyright +++ b/debian/copyright @@ -10,7 +10,7 @@ Upstream Authors: Copyright: - Copyright © 2009 Keith Packard + Copyright © 2009-2011 Keith Packard License: @@ -29,7 +29,7 @@ License: The Debian packaging is: - Copyright (C) 2009 Bdale Garbee + Copyright © 2009-2011 Bdale Garbee and is also licensed under the GPL version 2. diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index a2a9e331..25f24593 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -22,7 +22,7 @@ Towns - 2010 + 2011 Bdale Garbee and Keith Packard -- cgit v1.2.3 From 5d91c250179f44ca17c26fff36718b7026aa8ee0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Jan 2011 22:34:15 -0800 Subject: fat: Add firmware for v1.1 and docs to mac/windows/linux installers We'll need to be sure to update this each time we add a product. Signed-off-by: Keith Packard --- altosui/Makefile.am | 15 +++++++++++++-- altosui/altos-windows.nsi | 10 ++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 196d7032..52b173e2 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -129,10 +129,21 @@ ICONJAR= -C $(ICONDIR) altus-metrum-16x16.jpg \ WINDOWS_ICON=$(ICONDIR)/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_TD_0_2=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx +FIRMWARE_TD=$(FIRMWARE_TD_0_2) + +FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx +FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1-$(VERSION).ihx +FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) + FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD) +ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf +ALTOS_DOC=$(top_srcdir)/doc/altos.pdf +TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf + +DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TEMPLATE_DOC) + # Distribution targets LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2 MACOSX_DIST=Altos-Mac-$(VERSION).zip diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 6f296f18..a1238095 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -80,10 +80,20 @@ Section "TeleMetrum and TeleDongle Firmware" SetOutPath $INSTDIR File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" + File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx" File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" SectionEnd +Section "Documentation" + + SetOutPath $INSTDIR + + File "../doc/altusmetrum.pdf" + File "../doc/altos.pdf" + File "../doc/telemetrum-outline.pdf" +SectionEnd + Section "Uninstaller" ; Deal with the uninstaller -- cgit v1.2.3 From 72a04d679d06aaad9c2b4297fefd585fc393ce2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Jan 2011 22:39:07 -0800 Subject: fat: Add docs to Linux package Oops. Missed this one. Signed-off-by: Keith Packard --- altosui/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 52b173e2..79394f6e 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -151,7 +151,7 @@ WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) -LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=altosui-fat MACOSX_FILES=$(FAT_FILES) libaltos.dylib -- cgit v1.2.3 From 9a5666f42d4d90a0a488fd0a85ae9914944fe0be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Jan 2011 22:46:25 -0800 Subject: doc: Build with 'make all' from top level. Build with 'make fat' This will make sure the docs are up-to-date for both regular and fat builds. Signed-off-by: Keith Packard --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 0767ccde..e1ee30a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src altosui ao-tools ao-utils +SUBDIRS=src doc altosui ao-tools ao-utils EXTRA_DIST = ChangeLog @@ -14,5 +14,6 @@ dist-hook: ChangeLog fat: cd src && $(MAKE) all + cd doc && $(MAKE) all cd altosui/libaltos && $(MAKE) all cd altosui && $(MAKE) fat -- cgit v1.2.3 From ca7b549fbf62019b01a6e6c85da50645ea9a4502 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 23:48:08 -0700 Subject: update changelogs for Debian build --- ChangeLog | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 17 ++++++++++++++ 2 files changed, 86 insertions(+) diff --git a/ChangeLog b/ChangeLog index ff2c451a..76dd775e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,72 @@ +commit 9a5666f42d4d90a0a488fd0a85ae9914944fe0be +Author: Keith Packard +Date: Tue Jan 18 22:46:25 2011 -0800 + + doc: Build with 'make all' from top level. Build with 'make fat' + + This will make sure the docs are up-to-date for both regular and + fat builds. + + Signed-off-by: Keith Packard + +commit 72a04d679d06aaad9c2b4297fefd585fc393ce2e +Author: Keith Packard +Date: Tue Jan 18 22:39:07 2011 -0800 + + fat: Add docs to Linux package + + Oops. Missed this one. + + Signed-off-by: Keith Packard + +commit 5d91c250179f44ca17c26fff36718b7026aa8ee0 +Author: Keith Packard +Date: Tue Jan 18 22:34:15 2011 -0800 + + fat: Add firmware for v1.1 and docs to mac/windows/linux installers + + We'll need to be sure to update this each time we add a product. + + Signed-off-by: Keith Packard + +commit 26c4cc3054b1c7c9ed6ce3c2f21f6254b3245718 +Author: Bdale Garbee +Date: Tue Jan 18 23:29:03 2011 -0700 + + freshen copyright year + +commit e2e20f6ce8a9c2bca36fde5730ccd7151377ec6f +Author: Bdale Garbee +Date: Tue Jan 18 23:18:42 2011 -0700 + + add 0.9 revision entry, with caveat about telemetry format change + +commit 27e6dbbe95ae9b361d60576e0cbadb66792307f3 +Author: Keith Packard +Date: Tue Jan 18 20:39:58 2011 -0800 + + doc: Add v0.9 features from altosui to documentation. + + New flight download UI and new config items. + + Signed-off-by: Keith Packard + +commit 92d7841edcfc8a841f71f7f97cc541f8e55c4627 +Author: Keith Packard +Date: Tue Jan 18 20:39:30 2011 -0800 + + doc: Don't delete telemetrum-outline.pdf + + This has a drilling template for the board. + + Signed-off-by: Keith Packard + +commit c411dce69be58238b8312c2fd7405cbe8b5d4a5a +Author: Bdale Garbee +Date: Tue Jan 18 17:27:11 2011 -0700 + + update changelogs for Debian build + commit da42f406e88ccc821cd45d5a94d5afec65ec50e9 Merge: ea4cdfb cf550f9 Author: Bdale Garbee diff --git a/debian/changelog b/debian/changelog index 0d525f42..2ee93148 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +altos (0.8.1+79+g9a5666f) unstable; urgency=low + + [ Keith Packard ] + * doc: Don't delete telemetrum-outline.pdf + * doc: Add v0.9 features from altosui to documentation. + + [ Bdale Garbee ] + * add 0.9 revision entry, with caveat about telemetry format change + * freshen copyright year + + [ Keith Packard ] + * fat: Add firmware for v1.1 and docs to mac/windows/linux installers + * fat: Add docs to Linux package + * doc: Build with 'make all' from top level. Build with 'make fat' + + -- Bdale Garbee Tue, 18 Jan 2011 23:47:52 -0700 + altos (0.8.1+71+gda42f40) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 4ae724fe1d2ca0d712321c4fdc2200ff46d77428 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 23:54:36 -0700 Subject: we need an install target to prevent parent dir make from failing --- doc/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/Makefile b/doc/Makefile index ea030189..80c84409 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -22,6 +22,8 @@ PDFSTYLE= all: $(HTML) $(PDF) +install: all + publish: $(DOC) cp $(DOC) /home/bdale/web/altusmetrum/AltOS/doc/ (cd /home/bdale/web/altusmetrum ; \ -- cgit v1.2.3 From 3c72103866f041107af49e01a5ccb6d4e6b6ac80 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Jan 2011 23:55:42 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 76dd775e..6ec2ce6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 4ae724fe1d2ca0d712321c4fdc2200ff46d77428 +Author: Bdale Garbee +Date: Tue Jan 18 23:54:36 2011 -0700 + + we need an install target to prevent parent dir make from failing + +commit ca7b549fbf62019b01a6e6c85da50645ea9a4502 +Author: Bdale Garbee +Date: Tue Jan 18 23:48:08 2011 -0700 + + update changelogs for Debian build + commit 9a5666f42d4d90a0a488fd0a85ae9914944fe0be Author: Keith Packard Date: Tue Jan 18 22:46:25 2011 -0800 diff --git a/debian/changelog b/debian/changelog index 2ee93148..4e309a16 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.8.1+81+g4ae724f) unstable; urgency=low + + * we need an install target to prevent parent dir make from failing + + -- Bdale Garbee Tue, 18 Jan 2011 23:55:36 -0700 + altos (0.8.1+79+g9a5666f) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 6244f2316267738781e31a773b377bcf8c476918 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 00:04:45 -0700 Subject: prepare to release --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ecaeab63..86cb3290 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.8.1) +AC_INIT([altos], 0.9) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 480587cf514ba21885b24c3b8fcb98d6b76ea8f4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 00:05:25 -0700 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 6 ++++++ 2 files changed, 18 insertions(+) diff --git a/ChangeLog b/ChangeLog index 6ec2ce6f..4dff7bd1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 6244f2316267738781e31a773b377bcf8c476918 +Author: Bdale Garbee +Date: Wed Jan 19 00:04:45 2011 -0700 + + prepare to release + +commit 3c72103866f041107af49e01a5ccb6d4e6b6ac80 +Author: Bdale Garbee +Date: Tue Jan 18 23:55:42 2011 -0700 + + update changelogs for Debian build + commit 4ae724fe1d2ca0d712321c4fdc2200ff46d77428 Author: Bdale Garbee Date: Tue Jan 18 23:54:36 2011 -0700 diff --git a/debian/changelog b/debian/changelog index 4e309a16..6d6a2173 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +altos (0.9) unstable; urgency=low + + * prepare to release + + -- Bdale Garbee Wed, 19 Jan 2011 00:05:17 -0700 + altos (0.8.1+81+g4ae724f) unstable; urgency=low * we need an install target to prevent parent dir make from failing -- cgit v1.2.3 From 97f4f2e0d28eec1cf19d2d25140e42f6ac277700 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Jan 2011 11:21:52 -0800 Subject: altos: Program default flight log max value for new boards New boards have no config space values at all, and so they need each value to be set. Yes, this should be fixed so that there aren't two copies of these assignments. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_config.c b/src/ao_config.c index bbee3b44..cd56b473 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -70,6 +70,7 @@ _ao_config_get(void) sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; ao_config.radio_cal = ao_radio_cal; + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { -- cgit v1.2.3 From 159fda30fe57349660c5e2d95017144ea3f5d7db Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 12:26:53 -0700 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index 4dff7bd1..870d2a99 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 97f4f2e0d28eec1cf19d2d25140e42f6ac277700 +Author: Keith Packard +Date: Wed Jan 19 11:21:52 2011 -0800 + + altos: Program default flight log max value for new boards + + New boards have no config space values at all, and so they need each + value to be set. Yes, this should be fixed so that there aren't two + copies of these assignments. + + Signed-off-by: Keith Packard + +commit 480587cf514ba21885b24c3b8fcb98d6b76ea8f4 +Author: Bdale Garbee +Date: Wed Jan 19 00:05:25 2011 -0700 + + update changelogs for Debian build + commit 6244f2316267738781e31a773b377bcf8c476918 Author: Bdale Garbee Date: Wed Jan 19 00:04:45 2011 -0700 diff --git a/debian/changelog b/debian/changelog index 6d6a2173..211cc695 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (0.9+2+g97f4f2e) unstable; urgency=low + + [ Keith Packard ] + * altos: Program default flight log max value for new boards + + -- Bdale Garbee Wed, 19 Jan 2011 12:26:48 -0700 + altos (0.9) unstable; urgency=low * prepare to release -- cgit v1.2.3 From 9541ccd9ff9e67e0862ca31706358d8308fc85d8 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 12:42:40 -0700 Subject: update turnon script to prefer TeleDongle as programmer --- ao-bringup/turnon_telemetrum | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 405247fa..e2fd7116 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -18,11 +18,11 @@ else exit 1 fi -echo "TeleMetrum v1.0 Turn-On and Calibration Program" +echo "TeleMetrum v1.1 Turn-On and Calibration Program" echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" echo echo "Expectations:" -echo "\tTeleMetrum v1.0 powered from USB" +echo "\tTeleMetrum v1.1 powered from USB" echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" echo "\t\twith coax from UHF to frequency counter" echo @@ -31,18 +31,19 @@ read SERIAL echo $RAWLOAD -$RAWLOAD -r ao_led_blink.ihx +$RAWLOAD --device TeleDongle -r ao_led_blink.ihx echo "the red LED should be blinking" sleep 5 -$RAWLOAD -r ao_radio_xmit.ihx +$RAWLOAD --device TeleDongle -r ao_radio_xmit.ihx echo -n "Generating RF carrier. Please enter measured frequency: " read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/stable/telemetrum-v1.0*.ihx $SERIAL +$AOLOAD --device TeleDongle --cal $CAL_VALUE \ + /usr/share/altos/stable/telemetrum-v1.1*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 2bb83d90aa03d825ca1b751418c91b194b72f1f9 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 12:46:02 -0700 Subject: elide changelog entries or re-release of 0.9 --- debian/changelog | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/debian/changelog b/debian/changelog index 211cc695..4e309a16 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,16 +1,3 @@ -altos (0.9+2+g97f4f2e) unstable; urgency=low - - [ Keith Packard ] - * altos: Program default flight log max value for new boards - - -- Bdale Garbee Wed, 19 Jan 2011 12:26:48 -0700 - -altos (0.9) unstable; urgency=low - - * prepare to release - - -- Bdale Garbee Wed, 19 Jan 2011 00:05:17 -0700 - altos (0.8.1+81+g4ae724f) unstable; urgency=low * we need an install target to prevent parent dir make from failing -- cgit v1.2.3 From a09501ab714c0638410d06f80903a8769d93c688 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 19 Jan 2011 12:47:25 -0700 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 12 ++++++++++++ 2 files changed, 30 insertions(+) diff --git a/ChangeLog b/ChangeLog index 870d2a99..e8d091c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 2bb83d90aa03d825ca1b751418c91b194b72f1f9 +Author: Bdale Garbee +Date: Wed Jan 19 12:46:02 2011 -0700 + + elide changelog entries or re-release of 0.9 + +commit 9541ccd9ff9e67e0862ca31706358d8308fc85d8 +Author: Bdale Garbee +Date: Wed Jan 19 12:42:40 2011 -0700 + + update turnon script to prefer TeleDongle as programmer + +commit 159fda30fe57349660c5e2d95017144ea3f5d7db +Author: Bdale Garbee +Date: Wed Jan 19 12:26:53 2011 -0700 + + update changelogs for Debian build + commit 97f4f2e0d28eec1cf19d2d25140e42f6ac277700 Author: Keith Packard Date: Wed Jan 19 11:21:52 2011 -0800 diff --git a/debian/changelog b/debian/changelog index 4e309a16..188c7e20 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +altos (0.9) unstable; urgency=low + + [ Bdale Garbee ] + * prepare to release + * update changelogs for Debian build + * update turnon script to prefer TeleDongle as programmer + + [ Keith Packard ] + * altos: Program default flight log max value for new boards + + -- Bdale Garbee Wed, 19 Jan 2011 12:46:47 -0700 + altos (0.8.1+81+g4ae724f) unstable; urgency=low * we need an install target to prevent parent dir make from failing -- cgit v1.2.3 From c3080fdafff5212f267ba7c765a2f083435be799 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Feb 2011 09:51:37 -0800 Subject: ao-load: fix usage message to note that '=' is required for options The usage message was suggesting incorrect command line syntax; long options use '=' between the option name and value, not whitespace. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 4aa91b29..5accefc8 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -102,7 +102,7 @@ static const struct option options[] = { static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] [--cal ] file.ihx serial-number\n", program); + fprintf(stderr, "usage: %s [--tty=] [--device=] [--cal=] file.ihx serial-number\n", program); exit(1); } -- cgit v1.2.3 From d3bc27fabb6159ce58b14d0f7929b0f46f67c378 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Feb 2011 09:54:01 -0800 Subject: altos/test: Add dependencies in the Makefile for ao_flight_test Yes, it would be nice to automate dependency generation here, but I can't be bothered. Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/Makefile b/src/test/Makefile index f6e9b9f5..cd9cafc8 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -11,7 +11,7 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h +ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h ao_flight.c altitude.h cc -g -o $@ $< ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h -- cgit v1.2.3 From 8b09cc1825645a57c256f38a2f9586ddecf6bda5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Feb 2011 10:02:46 -0800 Subject: altos/test: auto-configure acceleration parameters from the log file The flight test code had static accelerometer configuration values, making it impossible to use data from different boards without recompiling. As the eeprom and telem log files both contain the necessary data, parse that instead. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 5c619518..8ce94895 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -152,7 +152,7 @@ struct ao_config { #define ao_config_get() -struct ao_config ao_config = { 250, 15937, 16467 }; +struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) @@ -220,6 +220,11 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); + } else if (nword >= 6 && strcmp(words[0], "Accel")) { + ao_config.accel_plus_g = atoi(words[3]); + ao_config.accel_minus_g = atoi(words[5]); + } else if (nword >= 4 && strcmp(words[0], "Main")) { + ao_config.main_deploy = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { @@ -238,8 +243,12 @@ ao_sleep(void *wchan) switch (type) { case 'F': ao_flight_ground_accel = a; - ao_config.accel_plus_g = a; - ao_config.accel_minus_g = a + 530; + if (ao_config.accel_plus_g == 0) { + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; + } + if (ao_config.main_deploy == 0) + ao_config.main_deploy = 250; ao_flight_started = 1; break; case 'S': -- cgit v1.2.3 From fe5123fa801f5dafed8b052da607899d1ef20500 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 2 Feb 2011 19:12:57 +1000 Subject: ao_radio: generalise setup of packet size --- src/ao.h | 10 +++++----- src/ao_radio.c | 58 ++++++++-------------------------------------------------- 2 files changed, 13 insertions(+), 55 deletions(-) diff --git a/src/ao.h b/src/ao.h index cef20e61..c2d7d22b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -922,13 +922,13 @@ ao_radio_get(void); #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void -ao_radio_set_telemetry(void); +ao_radio_set_fixed_pkt(size_t size); -void -ao_radio_set_packet(void); +#define ao_radio_set_telemetry() \ + ao_radio_set_fixed_pkt(sizeof (struct ao_telemetry)) -void -ao_radio_set_rdf(void); +#define ao_radio_set_packet() \ + ao_radio_set_fixed_pkt(sizeof (struct ao_packet)) void ao_radio_send(__xdata void *data, uint8_t size) __reentrant; diff --git a/src/ao_radio.c b/src/ao_radio.c index 7b7c5161..d156f543 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -217,7 +217,7 @@ static __code uint8_t rdf_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; -static __code uint8_t telemetry_setup[] = { +static __code uint8_t fixed_pkt_setup[] = { RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), @@ -232,34 +232,8 @@ static __code uint8_t telemetry_setup[] = { RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - /* max packet length */ - RF_PKTLEN_OFF, sizeof (struct ao_telemetry), - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| - PKTCTRL1_APPEND_STATUS| - PKTCTRL1_ADR_CHK_NONE), - RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| - RF_PKTCTRL0_PKT_FORMAT_NORMAL| - RF_PKTCTRL0_CRC_EN| - RF_PKTCTRL0_LENGTH_CONFIG_FIXED), -}; - -static __code uint8_t packet_setup[] = { - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), - RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | - RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), - RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | - RF_MDMCFG1_NUM_PREAMBLE_4 | - (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - - RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* max packet length */ - RF_PKTLEN_OFF, sizeof (struct ao_packet), + /* max packet length -- now set inline */ + // RF_PKTLEN_OFF, sizeof (struct ao_telemetry), RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_APPEND_STATUS| PKTCTRL1_ADR_CHK_NONE), @@ -290,27 +264,12 @@ ao_radio_general_isr(void) __interrupt 16 } void -ao_radio_set_telemetry(void) +ao_radio_set_fixed_pkt(size_t size) { uint8_t i; - for (i = 0; i < sizeof (telemetry_setup); i += 2) - RF[telemetry_setup[i]] = telemetry_setup[i+1]; -} - -void -ao_radio_set_packet(void) -{ - uint8_t i; - for (i = 0; i < sizeof (packet_setup); i += 2) - RF[packet_setup[i]] = packet_setup[i+1]; -} - -void -ao_radio_set_rdf(void) -{ - uint8_t i; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; + for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) + RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; + RF[RF_PKTLEN_OFF] = size; } void @@ -452,8 +411,7 @@ ao_radio_rdf(int ms) ao_dma_abort(ao_radio_dma); ao_radio_idle(); } - for (i = 0; i < sizeof (telemetry_setup); i += 2) - RF[telemetry_setup[i]] = telemetry_setup[i+1]; + ao_radio_set_telemetry(); ao_radio_put(); } -- cgit v1.2.3 From aad7103dcf44e69a5a30e008836cce5542ea33e2 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 19 Feb 2011 04:17:17 +1000 Subject: src/ao_gps_skytraq: simplify parsing code Added macros to make correctly constructing skytraq commands easier. Simplified code path for NMEA processing marginally. --- src/ao_gps_skytraq.c | 146 ++++++++++++++++++++++++++++----------------------- src/ao_host.h | 1 + 2 files changed, 82 insertions(+), 65 deletions(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index a2d5f1db..4d4ca592 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -19,7 +19,7 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 2 +#define AO_GPS_LEADER 2 static const char ao_gps_header[] = "GP"; @@ -37,24 +37,32 @@ static __xdata struct ao_gps_data ao_gps_next; static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; -static const char ao_gps_config[] = { - 0xa0, 0xa1, 0x00, 0x09, /* length 9 bytes */ - 0x08, /* configure nmea */ - 1, /* gga interval */ - 1, /* gsa interval */ - 1, /* gsv interval */ - 1, /* gll interval */ - 1, /* rmc interval */ - 1, /* vtg interval */ - 1, /* zda interval */ - 0, /* attributes (0 = update to sram, 1 = update flash too) */ - 0x09, 0x0d, 0x0a, - - 0xa0, 0xa1, 0x00, 0x03, /* length: 3 bytes */ - 0x3c, /* configure navigation mode */ - 0x00, /* 0 = car, 1 = pedestrian */ - 0x00, /* 0 = update to sram, 1 = update sram + flash */ - 0x3c, 0x0d, 0x0a, +#define STQ_S 0xa0, 0xa1 +#define STQ_E 0x0d, 0x0a +#define SKYTRAQ_MSG_2(id,a,b) \ + STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E +#define SKYTRAQ_MSG_3(id,a,b,c) \ + STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E +#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ + STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E +#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ + STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ + (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E + +static const uint8_t ao_gps_config[] = { + SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + /* gga interval */ + /* gsa interval */ + /* gsv interval */ + /* gll interval */ + /* rmc interval */ + /* vtg interval */ + /* zda interval */ + /* attributes (0 = update to sram, 1 = update flash too) */ + + SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ + /* 0 = car, 1 = pedestrian */ + /* 0 = update to sram, 1 = update sram + flash */ }; static void @@ -67,13 +75,6 @@ ao_gps_lexchar(void) ao_gps_cksum ^= ao_gps_char; } -void -ao_gps_skip(void) -{ - while (ao_gps_char >= '0') - ao_gps_lexchar(); -} - void ao_gps_skip_field(void) { @@ -390,53 +391,68 @@ ao_nmea_rmc(void) } } +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), (s)+sizeof(s)) + +static void +ao_skytraq_sendbytes(const uint8_t *b, const uint8_t *e) +{ + while (b != e) { + if (*b == 0xa0) + ao_delay(AO_MS_TO_TICKS(500)); + ao_serial_putchar(*b++); + } +} + +static void +ao_gps_nmea_parse(void) +{ + uint8_t a, b, c; + + ao_gps_cksum = 0; + ao_gps_error = 0; + + for (a = 0; a < AO_GPS_LEADER; a++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[a]) + return; + } + + ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); + b = ao_gps_char; + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + + if (ao_gps_char != ',') + return; + + if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { + ao_nmea_gga(); + } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { + ao_nmea_gsv(); + } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { + ao_nmea_rmc(); + } +} + void ao_gps(void) __reentrant { - char a, c; - uint8_t i; - ao_serial_set_speed(AO_SERIAL_SPEED_9600); - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (;;) { - /* Locate the begining of the next record */ - for (;;) { - c = ao_serial_getchar(); - if (c == '$') - break; - } - ao_gps_cksum = 0; - ao_gps_error = 0; + /* give skytraq time to boot in case of cold start */ + ao_delay(AO_MS_TO_TICKS(2000)); - /* Skip anything other than GP */ - for (i = 0; i < AO_GPS_LEADER; i++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[i]) - break; - } - if (i != AO_GPS_LEADER) - continue; + ao_skytraq_sendstruct(ao_gps_config); - /* pull the record identifier characters off the link */ - ao_gps_lexchar(); - a = ao_gps_char; - ao_gps_lexchar(); - c = ao_gps_char; - ao_gps_lexchar(); - i = ao_gps_char; - ao_gps_lexchar(); - if (ao_gps_char != ',') - continue; - - if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { - ao_nmea_gga(); - } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { - ao_nmea_gsv(); - } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { - ao_nmea_rmc(); + for (;;) { + /* Locate the begining of the next record */ + if (ao_serial_getchar() == '$') { + ao_gps_nmea_parse(); } + } } diff --git a/src/ao_host.h b/src/ao_host.h index fa03a910..a96b7629 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -69,6 +69,7 @@ uint8_t ao_adc_head; #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) +#define ao_delay(x) enum ao_igniter { ao_igniter_drogue = 0, -- cgit v1.2.3 From b080e933a65d268aaaec8cfd5f617a13d5babc43 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 19 Feb 2011 05:49:15 +1000 Subject: src/ao_gps_skytraq.c: Update logging rate to 10Hz Send commands to skytraq to update baud rate to 57,600 bps, and set NMEA output rate to 10Hz. --- src/ao_gps_skytraq.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 4d4ca592..88509a3d 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -49,6 +49,13 @@ static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E +static const uint8_t ao_gps_config_serial[] = { + SKYTRAQ_MSG_3(0x05, 0, 4, 0), /* set serial port */ + /* 0 = com1 */ + /* 0 = 4800, 1 = 9600, 2 = 19200, 3 = 38400, + * 4 = 57600, 5 = 115200 */ +}; + static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ @@ -63,6 +70,10 @@ static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ /* 0 = car, 1 = pedestrian */ /* 0 = update to sram, 1 = update sram + flash */ + + SKYTRAQ_MSG_2(0x0e, 10, 0), /* config nav interval */ + /* interval */ + /* 0 = update to sram, 1 = update sram */ }; static void @@ -444,6 +455,9 @@ ao_gps(void) __reentrant /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); + ao_skytraq_sendstruct(ao_gps_config_serial); + ao_delay(AO_MS_TO_TICKS(1000)); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); ao_skytraq_sendstruct(ao_gps_config); -- cgit v1.2.3 From 0630e7d6d8cf6abf0fe07f9a6df40ee472cce1ef Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 18 Feb 2011 19:54:18 -0700 Subject: tie bringup scripts to Bdale's bench TeleDongle --- ao-bringup/turnon_teledongle | 6 +++--- ao-bringup/turnon_telemetrum | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index 5145e9b0..320cd8ff 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -31,18 +31,18 @@ read SERIAL echo $RAWLOAD -$RAWLOAD -r ao_led_blink.ihx +$RAWLOAD -D 100 -r ao_led_blink.ihx echo "LEDs should be blinking" sleep 5 -$RAWLOAD -r ao_radio_xmit.ihx +$RAWLOAD -D 100 -r ao_radio_xmit.ihx echo -n "Generating RF carrier. Please enter measured frequency: " read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --cal $CAL_VALUE /usr/share/altos/stable/teledongle-v0.2*.ihx $SERIAL +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/teledongle-v0.2*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index e2fd7116..47835c58 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -31,18 +31,18 @@ read SERIAL echo $RAWLOAD -$RAWLOAD --device TeleDongle -r ao_led_blink.ihx +$RAWLOAD --device 100 -r ao_led_blink.ihx echo "the red LED should be blinking" sleep 5 -$RAWLOAD --device TeleDongle -r ao_radio_xmit.ihx +$RAWLOAD --device 100 -r ao_radio_xmit.ihx echo -n "Generating RF carrier. Please enter measured frequency: " read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD --device TeleDongle --cal $CAL_VALUE \ +$AOLOAD --device 100 --cal $CAL_VALUE \ /usr/share/altos/stable/telemetrum-v1.1*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE -- cgit v1.2.3 From 690feb166fd2bc6b6dfc26828f1efe9f5f1c6c0d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 18 Feb 2011 23:56:01 -0700 Subject: update changelogs for Debian build --- ChangeLog | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 17 ++++++++++++++ 2 files changed, 88 insertions(+) diff --git a/ChangeLog b/ChangeLog index e8d091c0..f98de6d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,74 @@ +commit 0630e7d6d8cf6abf0fe07f9a6df40ee472cce1ef +Author: Bdale Garbee +Date: Fri Feb 18 19:54:18 2011 -0700 + + tie bringup scripts to Bdale's bench TeleDongle + +commit b080e933a65d268aaaec8cfd5f617a13d5babc43 +Author: Anthony Towns +Date: Sat Feb 19 05:49:15 2011 +1000 + + src/ao_gps_skytraq.c: Update logging rate to 10Hz + + Send commands to skytraq to update baud rate to 57,600 bps, and + set NMEA output rate to 10Hz. + +commit aad7103dcf44e69a5a30e008836cce5542ea33e2 +Author: Anthony Towns +Date: Sat Feb 19 04:17:17 2011 +1000 + + src/ao_gps_skytraq: simplify parsing code + + Added macros to make correctly constructing skytraq commands easier. + Simplified code path for NMEA processing marginally. + +commit fe5123fa801f5dafed8b052da607899d1ef20500 +Author: Anthony Towns +Date: Wed Feb 2 19:12:57 2011 +1000 + + ao_radio: generalise setup of packet size + +commit 8b09cc1825645a57c256f38a2f9586ddecf6bda5 +Author: Keith Packard +Date: Fri Feb 18 10:02:46 2011 -0800 + + altos/test: auto-configure acceleration parameters from the log file + + The flight test code had static accelerometer configuration values, + making it impossible to use data from different boards without + recompiling. As the eeprom and telem log files both contain the + necessary data, parse that instead. + + Signed-off-by: Keith Packard + +commit d3bc27fabb6159ce58b14d0f7929b0f46f67c378 +Author: Keith Packard +Date: Fri Feb 18 09:54:01 2011 -0800 + + altos/test: Add dependencies in the Makefile for ao_flight_test + + Yes, it would be nice to automate dependency generation here, but I + can't be bothered. + + Signed-off-by: Keith Packard + +commit c3080fdafff5212f267ba7c765a2f083435be799 +Author: Keith Packard +Date: Fri Feb 18 09:51:37 2011 -0800 + + ao-load: fix usage message to note that '=' is required for options + + The usage message was suggesting incorrect command line syntax; long + options use '=' between the option name and value, not whitespace. + + Signed-off-by: Keith Packard + +commit a09501ab714c0638410d06f80903a8769d93c688 +Author: Bdale Garbee +Date: Wed Jan 19 12:47:25 2011 -0700 + + update changelogs for Debian build + commit 2bb83d90aa03d825ca1b751418c91b194b72f1f9 Author: Bdale Garbee Date: Wed Jan 19 12:46:02 2011 -0700 diff --git a/debian/changelog b/debian/changelog index 188c7e20..63d75356 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,20 @@ +altos (0.9.1) unstable; urgency=low + + [ Keith Packard ] + * ao-load: fix usage message to note that '=' is required for options + * altos/test: Add dependencies in the Makefile for ao_flight_test + * altos/test: auto-configure acceleration parameters from the log file + + [ Anthony Towns ] + * ao_radio: generalise setup of packet size + * src/ao_gps_skytraq: simplify parsing code + * src/ao_gps_skytraq.c: Update logging rate to 10Hz + + [ Bdale Garbee ] + * tie bringup scripts to Bdale's bench TeleDongle + + -- Bdale Garbee Fri, 18 Feb 2011 23:55:58 -0700 + altos (0.9) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From 7ca2cf1b7e03b8453b45b45e313a33ad65da9ad5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Feb 2011 01:02:00 -0800 Subject: altosui: Mark empty eeprom records 'invalid', don't generate exception When reading empty eeprom records, mark them as 'invalid', but don't generate an exception as it's normal to read these at the end of the flight log. Signed-off-by: Keith Packard --- altosui/AltosEepromRecord.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 584a04b7..e5196c50 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -72,15 +72,24 @@ public class AltosEepromRecord { if (values[0] != (addr & 0xff)) throw new ParseException(String.format("data address out of sync at 0x%x", addr), 0); - if (checksum(values) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", addr), 0); - + int i; + for (i = 1; i < values.length; i++) + if (values[i] != 0xff) + break; cmd = values[1]; + tick_valid = true; + if (i != values.length) { + if (checksum(values) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x in line %s", addr, line), 0); + } else { + cmd = Altos.AO_LOG_INVALID; + tick_valid = false; + } + tick = values[3] + (values[4] << 8); a = values[5] + (values[6] << 8); b = values[7] + (values[8] << 8); data = null; - tick_valid = true; } public AltosEepromRecord (String line) { -- cgit v1.2.3 From 629a7637871b24fe6d1204aaa7185d84933d4639 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Feb 2011 01:04:19 -0800 Subject: altosui: Always read whole eeprom block, even at end of flight Instead of stopping early, continue reading the whole eeprom block so that the extra serial data doesn't end up confusing the next user of the serial line, which may well be reading the next flight. Signed-off-by: Keith Packard --- altosui/AltosEepromBlock.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java index f223f3fb..11438df8 100644 --- a/altosui/AltosEepromBlock.java +++ b/altosui/AltosEepromBlock.java @@ -56,7 +56,7 @@ public class AltosEepromBlock extends ArrayList { has_lon = false; has_time = false; serial_line.printf("e %x\n", block); - for (addr = 0; !done && addr < 0x100;) { + for (addr = 0; addr < 0x100;) { try { AltosEepromRecord r = new AltosEepromRecord(serial_line, block * 256 + addr); @@ -93,10 +93,15 @@ public class AltosEepromBlock extends ArrayList { lon = (double) (r.a | (r.b << 16)) / 1e7; has_lon = true; } + if (!done) + add(addr / 8, r); if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) done = true; - add(addr / 8, r); } catch (ParseException pe) { + AltosEepromRecord r = new AltosEepromRecord(Altos.AO_LOG_INVALID, + 0, 0, 0); + if (!done) + add(addr/8, r); } addr += 8; } -- cgit v1.2.3 From 249cd3b63d97581b068fff988e0cd7fcd5bf493e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Feb 2011 01:06:01 -0800 Subject: altosui: Display eeprom parsing errors to user When reading the eeprom, any parsing errors (most likely bad checksums) indicate some kind of problem with either the hardware or the flight software. Display these to the user and do not erase the flight. Signed-off-by: Keith Packard --- altosui/AltosEepromBlock.java | 3 +++ altosui/AltosEepromDownload.java | 51 +++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java index 11438df8..d59fd39e 100644 --- a/altosui/AltosEepromBlock.java +++ b/altosui/AltosEepromBlock.java @@ -44,6 +44,7 @@ public class AltosEepromBlock extends ArrayList { double lon; boolean has_time; int hour, minute, second; + ParseException parse_exception = null; public AltosEepromBlock (AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { int addr; @@ -100,6 +101,8 @@ public class AltosEepromBlock extends ArrayList { } catch (ParseException pe) { AltosEepromRecord r = new AltosEepromRecord(Altos.AO_LOG_INVALID, 0, 0, 0); + if (parse_exception == null) + parse_exception = pe; if (!done) add(addr/8, r); } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index f1abd50c..1da94a67 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -47,6 +47,7 @@ public class AltosEepromDownload implements Runnable { AltosEepromList flights; ActionListener listener; boolean success; + ParseException parse_exception; private void FlushPending() throws IOException { for (String s : flights.config_data) { @@ -128,17 +129,22 @@ public class AltosEepromDownload implements Runnable { state = eeblock.state; } + if (parse_exception == null && eeblock.parse_exception != null) + parse_exception = eeblock.parse_exception; + CheckFile(false); for (record = 0; record < eeblock.size(); record++) { AltosEepromRecord r = eeblock.get(record); - String log_line = String.format("%c %4x %4x %4x\n", - r.cmd, r.tick, r.a, r.b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); + if (r.cmd != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %4x %4x\n", + r.cmd, r.tick, r.a, r.b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + } } } CheckFile(true); @@ -148,20 +154,21 @@ public class AltosEepromDownload implements Runnable { } } - private void show_error_internal(String message, String title) { + private void show_message_internal(String message, String title, int message_type) { JOptionPane.showMessageDialog(frame, message, title, - JOptionPane.ERROR_MESSAGE); + message_type); } - private void show_error(String in_message, String in_title) { + private void show_message(String in_message, String in_title, int in_message_type) { final String message = in_message; final String title = in_title; + final int message_type = in_message_type; Runnable r = new Runnable() { public void run() { try { - show_error_internal(message, title); + show_message_internal(message, title, message_type); } catch (Exception ex) { } } @@ -174,21 +181,33 @@ public class AltosEepromDownload implements Runnable { serial_line.start_remote(); try { + boolean failed = false; for (AltosEepromLog log : flights) { + parse_exception = null; if (log.download) { monitor.reset(); CaptureLog(log); } + if (parse_exception != null) { + failed = true; + show_message(String.format("Flight %d download error\n%s\nValid log data saved", + log.flight, + parse_exception.getMessage()), + serial_line.device.toShortString(), + JOptionPane.WARNING_MESSAGE); + } } - success = true; + success = !failed; } catch (IOException ee) { - show_error (serial_line.device.toShortString(), - ee.getLocalizedMessage()); + show_message(ee.getLocalizedMessage(), + serial_line.device.toShortString(), + JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { } catch (TimeoutException te) { - show_error (String.format("Connection to \"%s\" failed", - serial_line.device.toShortString()), - "Connection Failed"); + show_message(String.format("Connection to \"%s\" failed", + serial_line.device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); } if (remote) serial_line.stop_remote(); -- cgit v1.2.3 From 2cfe205de4242398e69c9e7c613af0d2a7094686 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 00:01:01 -0800 Subject: Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" This reverts commit b080e933a65d268aaaec8cfd5f617a13d5babc43. 10Hz data isn't any better than 1Hz data; it still doesn't like going upwards rapidly. --- src/ao_gps_skytraq.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 88509a3d..4d4ca592 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -49,13 +49,6 @@ static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E -static const uint8_t ao_gps_config_serial[] = { - SKYTRAQ_MSG_3(0x05, 0, 4, 0), /* set serial port */ - /* 0 = com1 */ - /* 0 = 4800, 1 = 9600, 2 = 19200, 3 = 38400, - * 4 = 57600, 5 = 115200 */ -}; - static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ @@ -70,10 +63,6 @@ static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ /* 0 = car, 1 = pedestrian */ /* 0 = update to sram, 1 = update sram + flash */ - - SKYTRAQ_MSG_2(0x0e, 10, 0), /* config nav interval */ - /* interval */ - /* 0 = update to sram, 1 = update sram */ }; static void @@ -455,9 +444,6 @@ ao_gps(void) __reentrant /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); - ao_skytraq_sendstruct(ao_gps_config_serial); - ao_delay(AO_MS_TO_TICKS(1000)); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); ao_skytraq_sendstruct(ao_gps_config); -- cgit v1.2.3 From 8cdf4fb051c22b35c251d90bc288551f7c2898bf Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 27 Feb 2011 11:11:12 +1000 Subject: src/ao_cmd: Shave off bytes from doc strings Switch to using { func, "X args\0Desc" } to specify command, saving a char field by looking at help[0] instead, and reduce help length by doing alignment with printf instead of hardcoded spaces. --- src/ao.h | 1 - src/ao_adc.c | 4 ++-- src/ao_cmd.c | 22 ++++++++++++---------- src/ao_config.c | 4 ++-- src/ao_dbg.c | 14 +++++++------- src/ao_flight_test.c | 1 - src/ao_gps_skytraq.c | 4 ++-- src/ao_host.h | 1 - src/ao_ignite.c | 6 +++--- src/ao_log.c | 6 +++--- src/ao_monitor.c | 4 ++-- src/ao_packet_master.c | 4 ++-- src/ao_radio.c | 4 ++-- src/ao_serial.c | 4 ++-- src/ao_storage.c | 12 +++++------- 15 files changed, 44 insertions(+), 47 deletions(-) diff --git a/src/ao.h b/src/ao.h index c2d7d22b..791064e8 100644 --- a/src/ao.h +++ b/src/ao.h @@ -380,7 +380,6 @@ uint8_t ao_match_word(__code char *word); struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_adc.c b/src/ao_adc.c index 3adf9b2e..9990a1fd 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -90,8 +90,8 @@ ao_adc_dump(void) __reentrant } __code struct ao_cmds ao_adc_cmds[] = { - { 'a', ao_adc_dump, "a Display current ADC values" }, - { 0, ao_adc_dump, NULL }, + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, }; void diff --git a/src/ao_cmd.c b/src/ao_cmd.c index a54a2316..6007773c 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -237,8 +237,10 @@ help(void) puts(help_txt); for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].cmd != '\0'; cmd++) - puts(cs[cmd].help); + for (cmd = 0; cs[cmd].func; cmd++) + printf("%-45s %s\n", + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); } } @@ -282,8 +284,8 @@ ao_cmd(void) func = (void (*)(void)) NULL; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].cmd != '\0'; cmd++) - if (cs[cmd].cmd == c) { + for (cmd = 0; cs[cmd].func; cmd++) + if (cs[cmd].help[0] == c) { func = cs[cmd].func; break; } @@ -301,12 +303,12 @@ ao_cmd(void) __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { - { '?', help, "? Print this message" }, - { 'T', ao_task_info, "T Show task states" }, - { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, - { 'r', ao_reboot, "r eboot Reboot" }, - { 'v', version, "v Show version" }, - { 0, help, NULL }, + { help, "?\0Print this message" }, + { ao_task_info, "T\0Show task states" }, + { echo, "E <0 off, 1 on>\0Set command echo mode" }, + { ao_reboot, "r eboot\0Reboot" }, + { version, "v\0Show version" }, + { 0, NULL }, }; void diff --git a/src/ao_config.c b/src/ao_config.c index cd56b473..c6d36247 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -439,8 +439,8 @@ ao_config_write(void) __reentrant #endif __code struct ao_cmds ao_config_cmds[] = { - { 'c', ao_config_set, "c Set config variable (? for help, s to show)" }, - { '\0', ao_config_set, NULL }, + { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { 0, NULL }, }; void diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 0d9ec8c0..49371560 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -348,13 +348,13 @@ debug_output(void) } __code struct ao_cmds ao_dbg_cmds[7] = { - { 'D', debug_enable, "D Enable debug mode" }, - { 'G', debug_get, "G Get data from debug port" }, - { 'I', debug_input, "I Input bytes to target at " }, - { 'O', debug_output, "O Output bytes to target at " }, - { 'P', debug_put, "P ... Put data to debug port" }, - { 'R', debug_reset, "R Reset target" }, - { 0, debug_reset, 0 }, + { debug_enable, "D\0Enable debug mode" }, + { debug_get, "G \0Get data from debug port" }, + { debug_input, "I \0Input bytes to target at " }, + { debug_output, "O \0Output bytes to target at " }, + { debug_put, "P ...\0Put data to debug port" }, + { debug_reset, "R\0Reset target" }, + { 0, NULL }, }; void diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 8ce94895..0c2006d5 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -114,7 +114,6 @@ const char const * const ao_state_names[] = { }; struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 4d4ca592..d286a30a 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -471,8 +471,8 @@ gps_dump(void) __reentrant } __code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, + { gps_dump, "g\0Display current GPS values" }, + { 0, NULL }, }; void diff --git a/src/ao_host.h b/src/ao_host.h index a96b7629..65c25fe5 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -112,7 +112,6 @@ const char const * const ao_state_names[] = { }; struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 603fcd25..798ba9b4 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -154,9 +154,9 @@ ao_ignite_test(void) } __code struct ao_cmds ao_ignite_cmds[] = { - { 'i', ao_ignite_manual, "i {main|drogue} Fire igniter. is doit with D&I" }, - { 't', ao_ignite_test, "t Test igniter continuity" }, - { 0, ao_ignite_manual, NULL }, + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter continuity" }, + { 0, NULL }, }; __xdata struct ao_task ao_igniter_task; diff --git a/src/ao_log.c b/src/ao_log.c index 099c5f6f..1b10961d 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -390,9 +390,9 @@ ao_log_delete(void) __reentrant __code struct ao_cmds ao_log_cmds[] = { - { 'l', ao_log_list, "l List stored flight logs" }, - { 'd', ao_log_delete, "d Delete stored flight" }, - { 0, ao_log_delete, NULL }, + { ao_log_list, "l\0List stored flight logs" }, + { ao_log_delete, "d \0Delete stored flight" }, + { 0, NULL }, }; void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 4ba3da6d..9c4be6fb 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -96,8 +96,8 @@ set_monitor(void) } __code struct ao_cmds ao_monitor_cmds[] = { - { 'm', set_monitor, "m <0 off, 1 on> Enable/disable radio monitoring" }, - { 0, set_monitor, NULL }, + { set_monitor, "m <0 off, 1 on>\0Enable/disable radio monitoring" }, + { 0, NULL }, }; void diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5f79885c..5c4ab0dd 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -133,8 +133,8 @@ ao_packet_forward(void) __reentrant __code struct ao_cmds ao_packet_master_cmds[] = { - { 'p', ao_packet_forward, "p Remote packet link." }, - { 0, ao_packet_forward, NULL }, + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, }; void diff --git a/src/ao_radio.c b/src/ao_radio.c index d156f543..d7c00213 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -455,8 +455,8 @@ ao_radio_test(void) } __code struct ao_cmds ao_radio_cmds[] = { - { 'C', ao_radio_test, "C <1 start, 0 stop, none both> Radio carrier test" }, - { 0, ao_radio_test, NULL }, + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, }; void diff --git a/src/ao_serial.c b/src/ao_serial.c index a48734c2..dd383fca 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -93,8 +93,8 @@ monitor_serial(void) } __code struct ao_cmds ao_serial_cmds[] = { - { 'M', monitor_serial, "M Monitor serial data" }, - { 0, monitor_serial, NULL }, + { monitor_serial, "M \0Monitor serial data" }, + { 0, NULL }, }; static const struct { diff --git a/src/ao_storage.c b/src/ao_storage.c index 709259ee..9f0f75fb 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,14 +166,12 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { - { 'f', ao_storage_info, "f Show storage info" }, - { 'e', ao_storage_dump, "e Dump a block of flash data" }, -#if 0 - { 'w', ao_storage_store, "w ... Write data to flash" }, +#ifdef HAS_STORAGE_DBG + { ao_storage_store, "w ...\0Write data to flash" }, #endif - { 'z', ao_storage_zap, "z Erase flash containing " }, - { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, - { 0, ao_storage_zap, NULL }, + { ao_storage_zap, "z \0Erase flash containing " }, + { ao_storage_zapall,"Z \0Erase all logs. is doit with D&I" }, + { 0, NULL }, }; void -- cgit v1.2.3 From 6e340c87d3198647cf075ed520a82703b0d59beb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 00:26:17 -0800 Subject: altos: Oops. Lost a couple of commands when merging the doc patch I didn't merge this carefully enough and managed to lose the 'f' and 'e' commands, which are kinda useful. Signed-off-by: Keith Packard --- src/ao_storage.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_storage.c b/src/ao_storage.c index 9f0f75fb..69183514 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,6 +166,8 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { + { ao_storage_info, "f\0Show storage info" }, + { ao_storage_dump, "e \0Dump a block of flash data" }, #ifdef HAS_STORAGE_DBG { ao_storage_store, "w ...\0Write data to flash" }, #endif -- cgit v1.2.3 From 9f3d26cadf37880d2c9223f59271d295b11c4c2a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Mar 2011 14:05:13 -0700 Subject: altosui: Missed jcommon.jar in the Mac OS install image This caused graphing to fail on Mac OS X Signed-off-by: Keith Packard --- altosui/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 79394f6e..133afbe8 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -282,6 +282,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) 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 $(JFREECHART_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java + cp -p $(JCOMMON_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java cp -p $(MACOSX_EXTRA) macosx/AltOS cd macosx && zip -r ../$@ AltosUI.app AltOS -- cgit v1.2.3 From 45395c7825184efb835d5b165fa132be20c7f6fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Mar 2011 14:08:42 -0700 Subject: Bump published version number to 0.9.1 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 86cb3290..e27cf81f 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9) +AC_INIT([altos], 0.9.1) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 8f1bd11b61d9423c62162f7bbe573fc69fd75269 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Mar 2011 14:10:06 -0700 Subject: aoview: remove -s option. --- ao-tools/ao-view/aoview_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/ao-tools/ao-view/aoview_main.c b/ao-tools/ao-view/aoview_main.c index 714bee9a..f8704b89 100644 --- a/ao-tools/ao-view/aoview_main.c +++ b/ao-tools/ao-view/aoview_main.c @@ -31,7 +31,6 @@ static void destroy_event(GtkWidget *widget, gpointer data) gtk_main_quit(); } -extern int _Xdebug; char *aoview_tty = NULL; int main(int argc, char **argv) @@ -42,13 +41,12 @@ int main(int argc, char **argv) static struct option long_options[] = { { "tty", 1, 0, 'T'}, - { "sync", 0, 0, 's'}, { 0, 0, 0, 0 } }; for (;;) { int c, temp; - c = getopt_long_only(argc, argv, "sT:", long_options, &temp); + c = getopt_long_only(argc, argv, "T:", long_options, &temp); if (c == -1) break; @@ -56,9 +54,6 @@ int main(int argc, char **argv) case 'T': aoview_tty = optarg; break; - case 's': - _Xdebug = 1; - break; default: usage(); } -- cgit v1.2.3 From fdd15a254c6fab5ba2d02320ba0ceb3e6a56354c Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 26 Feb 2011 11:48:30 +1000 Subject: ao_intflash: Use internal flash for storage Makes any free pages at end of CC1111's internal flash available via the ao_storage API. --- src/ao_intflash.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/ao_intflash.c diff --git a/src/ao_intflash.c b/src/ao_intflash.c new file mode 100644 index 00000000..ad5e5aac --- /dev/null +++ b/src/ao_intflash.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2011 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "cc1111.h" + +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +#define ENDOFCODE (0x51f0 + 1500) +#define NUM_PAGES ((0x8000-ENDOFCODE)/1024) +#define SIZE (1024*NUM_PAGES) +#define LOCN (0x8000 - SIZE) + +#if NUM_PAGES < 1 +#error "Too few pages" +#endif + +#if LOCN % 1024 != 0 +#error "Pages aren't aligned properly" +#endif + +__xdata __at(LOCN) uint8_t ao_intflash[SIZE]; + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total = sizeof(ao_intflash); + +/* Block size - device is erased in these units. */ +__xdata uint32_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config = sizeof(ao_intflash); + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__xdata uint16_t ao_storage_unit = 1024; + +__xdata static uint8_t ao_intflash_dma_done; +static uint8_t ao_intflash_dma; + +/* + * The internal flash chip is arranged in 1kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint16_t addr; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + while (FCTL & FCTL_BUSY) + ; + + FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz + FADDRH = addr >> 8; + FADDRL = addr & ~0xFF00; + + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop; ; Required, see datasheet. + _endasm; + + while (FCTL & FCTL_BUSY) + ; + + return 1; +} + +/* + * Write to flash + */ + +static void +word_aligned_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint16_t addr; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + ao_dma_set_transfer(ao_intflash_dma, d, &X_FWDATA, + DMA_LEN_HIGH_VLEN_LEN | len, + DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | + DMA_CFG1_IRQMASK | DMA_CFG1_PRIORITY_HIGH); + + while (FCTL & FCTL_BUSY) + ; + + FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz + + FADDRH = addr >> 8; + FADDRL = addr & ~0xFF00; + + ao_dma_start(ao_intflash_dma); + + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + _endasm; + + __critical while (!ao_intflash_dma_done) + ao_sleep(&ao_intflash_dma_done); + + while (FCTL & (FCTL_BUSY | FCTL_SWBSY)) + ; +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant +{ + static __xdata uint8_t b[2]; + __xdata uint8_t *d = v; + uint8_t oddlen; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + if (len == 0) + return 1; + + if (pos & 1) { + b[0] = ~0; + b[1] = d[0]; + word_aligned_write(pos-1, b, 2); + pos++; + len--; + d++; + } + oddlen = len & 1; + len &= ~1; + if (len > 0) { + word_aligned_write(pos, d, len); + } + if (oddlen) { + b[0] = d[len]; + b[1] = ~0; + word_aligned_write(pos+len, b, 2); + } + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + memcpy(d, ao_intflash+pos, len); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash, starting at 0x%04x\n", LOCN); +} + +void +ao_storage_device_init(void) +{ + ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); +} -- cgit v1.2.3 From 02611efea0c485d78fad08c696c1f56e868d36b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 20:56:25 -0800 Subject: altos: Make serial, usb, beeper and accelerometer optional components Not all boards will have these, so fix places that use them to deal with that. Signed-off-by: Keith Packard --- src/Makefile.proto | 23 +++++++++-- src/ao.h | 14 ++++++- src/ao_flight.c | 114 +++++++++++++++++++++++++++++++++++++++++---------- src/ao_flight_test.c | 9 ++++ src/ao_log.c | 2 + src/ao_panic.c | 8 ++++ src/ao_pins.h | 18 ++++++++ src/ao_product.c | 4 +- src/ao_report.c | 34 ++++++++------- src/ao_telemetry.c | 6 +++ 10 files changed, 189 insertions(+), 43 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 709cbca7..30cd5798 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -42,11 +42,15 @@ ALTOS_SRC = \ # Shared AltOS drivers # ALTOS_DRIVER_SRC = \ - ao_beep.c \ ao_config.c \ ao_led.c \ ao_radio.c \ - ao_stdio.c \ + ao_stdio.c + +BEEP_DRIVER_SRC = \ + ao_beep.c + +USB_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ @@ -68,7 +72,12 @@ TELE_RECEIVER_SRC =\ # TELE_DRIVER_SRC = \ - ao_convert.c \ + ao_convert.c + +# +# Serial port driver +# +SERIAL_DRIVER_SRC = \ ao_serial.c # @@ -89,7 +98,9 @@ DBG_SRC = \ TM_DRIVER_SRC = \ ao_adc.c \ ao_gps_report.c \ - ao_ignite.c + ao_ignite.c \ + $(BEEP_DRIVER_SRC) \ + $(USB_DRIVER_SRC) # # 25LC1024 driver source @@ -142,6 +153,7 @@ TM_BASE_SRC = \ $(ALTOS_SRC) \ $(ALTOS_DRIVER_SRC) \ $(TELE_DRIVER_SRC) \ + $(SERIAL_DRIVER_SRC) \ $(TELE_COMMON_SRC) \ $(TM_DRIVER_SRC) \ $(TM_TASK_SRC) \ @@ -158,6 +170,7 @@ TI_SRC = \ $(ALTOS_DRIVER_SRC) \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TI_MAIN_SRC) \ $(DBG_SRC) @@ -172,6 +185,7 @@ TT_SRC = \ $(TELE_RECEIVER_SRC) \ $(TELE_DRIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TT_MAIN_SRC) @@ -187,6 +201,7 @@ TD_SRC = \ $(ALTOS_DRIVER_SRC) \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TD_MAIN_SRC) include Makefile.defs diff --git a/src/ao.h b/src/ao.h index 791064e8..5bbe5158 100644 --- a/src/ao.h +++ b/src/ao.h @@ -164,9 +164,13 @@ struct ao_adc { #if HAS_ADC +#if HAS_ACCEL #ifndef HAS_ACCEL_REF #error Please define HAS_ACCEL_REF #endif +#else +#define HAS_ACCEL_REF 0 +#endif /* * ao_adc.c @@ -303,7 +307,14 @@ 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; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif /* * ao_usb.c @@ -327,9 +338,11 @@ ao_usb_pollchar(void); void ao_usb_flush(void); +#if HAS_USB /* USB interrupt handler */ void ao_usb_isr(void) __interrupt 6; +#endif /* Enable the USB controller */ void @@ -1062,7 +1075,6 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -extern __code __at(0x00aa) uint8_t ao_usb_descriptors []; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_flight.c b/src/ao_flight.c index 81aecad3..843865e8 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -19,39 +19,57 @@ #include "ao.h" #endif +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_flight_tick; /* time of last data */ __pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__pdata int16_t ao_flight_accel; /* filtered acceleration */ __pdata int16_t ao_flight_pres; /* filtered pressure */ __pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_accel; /* startup acceleration */ __pdata int16_t ao_min_pres; /* minimum recorded pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ __pdata int16_t ao_main_pres; /* pressure to eject main */ +#if HAS_ACCEL +__pdata int16_t ao_flight_accel; /* filtered acceleration */ +__pdata int16_t ao_ground_accel; /* startup acceleration */ +#endif /* * track min/max data over a long interval to detect * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_cur_min_accel; -__pdata int16_t ao_interval_cur_max_accel; __pdata int16_t ao_interval_cur_min_pres; __pdata int16_t ao_interval_cur_max_pres; -__pdata int16_t ao_interval_min_accel; -__pdata int16_t ao_interval_max_accel; __pdata int16_t ao_interval_min_pres; __pdata int16_t ao_interval_max_pres; +#if HAS_ACCEL +__pdata int16_t ao_interval_cur_min_accel; +__pdata int16_t ao_interval_cur_max_accel; +__pdata int16_t ao_interval_min_accel; +__pdata int16_t ao_interval_max_accel; +#endif __data uint8_t ao_flight_adc; -__pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; -__pdata int16_t ao_accel_2g; - +__pdata int16_t ao_raw_pres; __xdata uint8_t ao_flight_force_idle; +#if HAS_ACCEL +__pdata int16_t ao_raw_accel, ao_raw_accel_prev; +__pdata int16_t ao_accel_2g; + /* Accelerometer calibration * * We're sampling the accelerometer through a resistor divider which @@ -84,6 +102,8 @@ __xdata uint8_t ao_flight_force_idle; #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) +#endif + /* * Barometer calibration * @@ -117,6 +137,7 @@ __xdata uint8_t ao_flight_force_idle; #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) +#if HAS_ACCEL /* This value is scaled in a weird way. It's a running total of accelerometer * readings minus the ground accelerometer reading. That means it measures * velocity, and quite accurately too. As it gets updated 100 times a second, @@ -126,7 +147,10 @@ __pdata int32_t ao_flight_vel; __pdata int32_t ao_min_vel; __pdata int32_t ao_old_vel; __pdata int16_t ao_old_vel_tick; -__xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum; +__xdata int32_t ao_raw_accel_sum; +#endif + +__xdata int32_t ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) @@ -141,22 +165,31 @@ ao_flight(void) __pdata static uint16_t nsamples = 0; ao_flight_adc = ao_adc_head; + ao_raw_pres = 0; +#if HAS_ACCEL ao_raw_accel_prev = 0; ao_raw_accel = 0; - ao_raw_pres = 0; +#endif ao_flight_tick = 0; for (;;) { ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { +#if HAS_ACCEL __pdata uint8_t ticks; __pdata int16_t ao_vel_change; +#endif __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; /* Capture a sample */ ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; + ao_raw_pres = ao_adc->pres; + ao_flight_pres -= ao_flight_pres >> 4; + ao_flight_pres += ao_raw_pres >> 4; + +#if HAS_ACCEL ao_raw_accel = ao_adc->accel; #if HAS_ACCEL_REF /* @@ -242,12 +275,9 @@ ao_flight(void) ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; ao_adc->accel = ao_raw_accel; #endif - ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; ao_flight_accel += ao_raw_accel >> 4; - ao_flight_pres -= ao_flight_pres >> 4; - ao_flight_pres += ao_raw_pres >> 4; /* Update velocity * * The accelerometer is mounted so that @@ -264,12 +294,14 @@ ao_flight(void) ao_flight_vel += (int32_t) ao_vel_change; else ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; +#endif ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } if (ao_flight_pres < ao_min_pres) ao_min_pres = ao_flight_pres; +#if HAS_ACCEL if (ao_flight_vel >= 0) { if (ao_flight_vel < ao_min_vel) ao_min_vel = ao_flight_vel; @@ -277,6 +309,7 @@ ao_flight(void) if (-ao_flight_vel < ao_min_vel) ao_min_vel = -ao_flight_vel; } +#endif switch (ao_flight_state) { case ao_flight_startup: @@ -287,21 +320,27 @@ ao_flight(void) * data and average them to find the resting values */ if (nsamples < 512) { +#if HAS_ACCEL ao_raw_accel_sum += ao_raw_accel; +#endif ao_raw_pres_sum += ao_raw_pres; ++nsamples; continue; } +#if HAS_ACCEL ao_ground_accel = ao_raw_accel_sum >> 9; +#endif ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); +#if HAS_ACCEL ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; ao_old_vel_tick = ao_flight_tick; +#endif /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out @@ -309,6 +348,7 @@ ao_flight(void) * - idle mode otherwise */ ao_config_get(); +#if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -323,17 +363,23 @@ ao_flight(void) */ ao_packet_slave_start(); - } else if (ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && - !ao_flight_force_idle) + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; +#if HAS_USB /* Disable the USB controller in flight mode * to save power */ ao_usb_disable(); - +#endif /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -356,6 +402,7 @@ ao_flight(void) break; case ao_flight_pad: +#if HAS_ACCEL /* Trim velocity * * Once a second, remove any velocity from @@ -366,6 +413,7 @@ ao_flight(void) ao_flight_vel -= ao_old_vel; ao_old_vel = ao_flight_vel; } +#endif /* pad to boost: * * accelerometer: > 2g AND velocity > 5m/s @@ -376,11 +424,18 @@ ao_flight(void) * the barometer, but we use both to make sure this * transition is detected */ - if ((ao_flight_accel < ao_ground_accel - ACCEL_BOOST && - ao_flight_vel > ACCEL_VEL_BOOST) || + if ( +#if HAS_ACCEL + (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && + ao_flight_vel > ACCEL_VEL_BOOST) || +#endif ao_flight_pres < ao_ground_pres - BARO_LAUNCH) { +#if HAS_ACCEL ao_flight_state = ao_flight_boost; +#else + ao_flight_state = ao_flight_coast; +#endif ao_launch_tick = ao_flight_tick; /* start logging data */ @@ -392,14 +447,17 @@ ao_flight(void) /* disable RDF beacon */ ao_rdf_set(0); +#if HAS_GPS /* Record current GPS position by waking up GPS log tasks */ ao_wakeup(&ao_gps_data); ao_wakeup(&ao_gps_tracking_data); +#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#if HAS_ACCEL case ao_flight_boost: /* boost to fast: @@ -448,6 +506,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; +#endif case ao_flight_coast: /* apogee detect: coast to drogue deploy: @@ -478,8 +537,10 @@ ao_flight(void) /* Set the 'last' limits to max range to prevent * early resting detection */ +#if HAS_ACCEL ao_interval_min_accel = 0; ao_interval_max_accel = 0x7fff; +#endif ao_interval_min_pres = 0; ao_interval_max_pres = 0x7fff; @@ -487,7 +548,9 @@ ao_flight(void) ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; +#endif /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -530,21 +593,28 @@ ao_flight(void) ao_interval_cur_min_pres = ao_flight_pres; if (ao_flight_pres > ao_interval_cur_max_pres) ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL if (ao_flight_accel < ao_interval_cur_min_accel) ao_interval_cur_min_accel = ao_flight_accel; if (ao_flight_accel > ao_interval_cur_max_accel) ao_interval_cur_max_accel = ao_flight_accel; +#endif if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { ao_interval_max_pres = ao_interval_cur_max_pres; ao_interval_min_pres = ao_interval_cur_min_pres; + ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL ao_interval_max_accel = ao_interval_cur_max_accel; ao_interval_min_accel = ao_interval_cur_min_accel; - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; +#endif + ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && + if ( +#if HAS_ACCEL + (uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && +#endif ao_flight_pres > ao_ground_pres - BARO_LAND && (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) { diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 0c2006d5..e75bc8df 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -155,6 +155,15 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#endif +#define HAS_ACCEL_REF 0 + #include "ao_flight.c" void diff --git a/src/ao_log.c b/src/ao_log.c index 1b10961d..817d3e6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -92,7 +92,9 @@ ao_log(void) log.type = AO_LOG_FLIGHT; log.tick = ao_flight_tick; +#if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; +#endif log.u.flight.flight = ao_flight_number; ao_log_data(&log); diff --git a/src/ao_panic.c b/src/ao_panic.c index e996371e..fdada201 100644 --- a/src/ao_panic.c +++ b/src/ao_panic.c @@ -17,6 +17,14 @@ #include "ao.h" +#ifndef HAS_BEEP +#error Please define HAS_BEEP +#endif + +#if !HAS_BEEP +#define ao_beep(x) +#endif + static void ao_panic_delay(uint8_t n) { diff --git a/src/ao_pins.h b/src/ao_pins.h index 2c5b9db5..59604588 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -19,6 +19,9 @@ #define _AO_PINS_H_ #if defined(TELEMETRUM_V_1_0) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 @@ -32,9 +35,13 @@ #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 #endif #if defined(TELEMETRUM_V_1_1) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 @@ -52,9 +59,12 @@ #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 #endif #if defined(TELEDONGLE_V_0_2) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 1 @@ -71,6 +81,9 @@ #endif #if defined(TELEMETRUM_V_0_1) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 @@ -86,9 +99,12 @@ #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 #endif #if defined(TELEDONGLE_V_0_1) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 0 @@ -105,6 +121,8 @@ #endif #if defined(TIDONGLE) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 1 diff --git a/src/ao_product.c b/src/ao_product.c index 82d6298f..54ba2a14 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -16,7 +16,6 @@ */ #include "ao.h" -#include "ao_usb.h" #include PRODUCT_DEFS /* Defines which mark this particular AltOS product */ @@ -27,6 +26,8 @@ const char ao_product[] = AO_iProduct_STRING; #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) +#if HAS_USB +#include "ao_usb.h" /* USB descriptors in one giant block of bytes */ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = { @@ -151,3 +152,4 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = /* Terminating zero */ 0 }; +#endif diff --git a/src/ao_report.c b/src/ao_report.c index cc8b512b..c9ee7cae 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -37,10 +37,14 @@ static const uint8_t flight_reports[] = { MORSE4(1,0,0,1), /* invalid 'X' */ }; -#if 1 -#define signal(time) ao_beep_for(AO_BEEP_MID, time) +#if HAS_BEEP +#define low(time) ao_beep_for(AO_BEEP_LOW, time) +#define mid(time) ao_beep_for(AO_BEEP_MID, time) +#define high(time) ao_beep_for(AO_BEEP_HIGH, time) #else -#define signal(time) ao_led_for(AO_LED_RED, time) +#define low(time) ao_led_for(AO_LED_RED, time) +#define mid(time) ao_led_for(AO_LED_RED|AO_LED_GREEN, time) +#define high(time) ao_led_for(AO_LED_GREEN, time) #endif #define pause(time) ao_delay(time) @@ -56,9 +60,9 @@ ao_report_beep(void) __reentrant return; while (l--) { if (r & 8) - signal(AO_MS_TO_TICKS(600)); + mid(AO_MS_TO_TICKS(600)); else - signal(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); pause(AO_MS_TO_TICKS(200)); r >>= 1; } @@ -69,12 +73,12 @@ static void ao_report_digit(uint8_t digit) __reentrant { if (!digit) { - signal(AO_MS_TO_TICKS(500)); + mid(AO_MS_TO_TICKS(500)); pause(AO_MS_TO_TICKS(200)); } else { while (digit--) { - signal(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); } } pause(AO_MS_TO_TICKS(300)); @@ -118,24 +122,24 @@ ao_report_continuity(void) __reentrant (ao_report_igniter_ready(ao_igniter_main) << 1)); if (c) { while (c--) { - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(25)); + high(AO_MS_TO_TICKS(25)); pause(AO_MS_TO_TICKS(100)); } } else { c = 10; while (c--) { - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(20)); - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); + high(AO_MS_TO_TICKS(20)); + low(AO_MS_TO_TICKS(20)); } } if (ao_log_full()) { pause(AO_MS_TO_TICKS(100)); c = 2; while (c--) { - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + low(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + high(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); } } c = 50; diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 7aad929f..dd79f3fc 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -42,16 +42,22 @@ ao_telemetry(void) while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); telemetry.flight_state = ao_flight_state; +#if HAS_ACCEL telemetry.flight_accel = ao_flight_accel; telemetry.ground_accel = ao_ground_accel; telemetry.flight_vel = ao_flight_vel; +#endif telemetry.flight_pres = ao_flight_pres; telemetry.ground_pres = ao_ground_pres; +#if HAS_ADC ao_adc_get(&telemetry.adc); +#endif +#if HAS_GPS ao_mutex_get(&ao_gps_mutex); memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); +#endif ao_radio_send(&telemetry, sizeof (telemetry)); ao_delay(ao_telemetry_interval); if (ao_rdf && -- cgit v1.2.3 From e339ffd8bd8b9e3f4758017ba355028000cb612e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:57:52 -0800 Subject: altos/test: Use ao_convert.c instead of hand-coded pres → alt func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix up ao_convert.c so that it can be used within the flight test code instead of having a (broken) copy of the code there. Signed-off-by: Keith Packard --- src/ao_convert.c | 2 +- src/ao_flight_test.c | 25 +------------------------ 2 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/ao_convert.c b/src/ao_convert.c index cec4c29f..0969f107 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef AO_CONVERT_TEST +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) #include "ao.h" #endif diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e75bc8df..70888d34 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -118,30 +118,7 @@ struct ao_cmds { const char *help; }; - -static int16_t altitude_table[2048] = { -#include "altitude.h" -}; - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t pres; - - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; -} +#include "ao_convert.c" struct ao_config { uint16_t main_deploy; -- cgit v1.2.3 From 1e56ed44e562f808addfd76bfb352f981db94094 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:59:08 -0800 Subject: altos/test: Add baro-only flight test program This builds the flight code in baro-only mode for testing. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 10 +++++++++- src/test/Makefile | 7 +++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 70888d34..a635803f 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -72,6 +72,7 @@ uint8_t ao_adc_head; #define ao_telemetry_set_interval(x) #define ao_rdf_set(rdf) #define ao_packet_slave_start() +#define ao_packet_slave_stop() enum ao_igniter { ao_igniter_drogue = 0, @@ -138,8 +139,8 @@ struct ao_config ao_config; #define HAS_GPS 1 #ifndef HAS_ACCEL #define HAS_ACCEL 1 -#endif #define HAS_ACCEL_REF 0 +#endif #include "ao_flight.c" @@ -268,12 +269,19 @@ ao_dump_state(void) { if (ao_flight_state == ao_flight_startup) return; +#if HAS_ACCEL printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", ao_state_names[ao_flight_state], (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY, (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY, ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); +#else + printf ("\t\t\t\t\t%s alt %d main %d\n", + ao_state_names[ao_flight_state], + ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), + ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); +#endif if (ao_flight_state == ao_flight_landed) exit(0); } diff --git a/src/test/Makefile b/src/test/Makefile index cd9cafc8..853713fa 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % .. -PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test CFLAGS=-I.. -I. @@ -11,9 +11,12 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h cc -g -o $@ $< +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h + cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc -g -o $@ $< -- cgit v1.2.3 From 2d41358c80f2eb8b6e98d699149bb941a6671475 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:00:52 -0800 Subject: altos: Start with packet slave running. Turn off in pad mode. Instead of turning slave mode on in idle mode, start with it running and disable it in pad mode instead. This means packet mode is available in startup mode too. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 ++++------- src/ao_packet_slave.c | 4 ++++ src/ao_pins.h | 6 ++++++ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 843865e8..8e370c4f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -358,10 +358,6 @@ ao_flight(void) * (or uncalibrated values), so we go into invalid mode */ ao_flight_state = ao_flight_invalid; - /* Allow packet mode in invalid flight state, - * Still need to be able to fix the problem! - */ - ao_packet_slave_start(); } else #endif @@ -380,6 +376,10 @@ ao_flight(void) */ ao_usb_disable(); #endif + + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -390,9 +390,6 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; - /* Turn on packet system in idle mode */ - ao_packet_slave_start(); - /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 39d04bbb..eb456dab 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -26,6 +26,9 @@ ao_packet_slave(void) while (ao_packet_enable) { if (ao_packet_recv()) { memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif ao_packet_send(); } } @@ -60,4 +63,5 @@ ao_packet_slave_init(void) ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); + ao_packet_slave_start(); } diff --git a/src/ao_pins.h b/src/ao_pins.h index 59604588..a486b9ba 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -19,6 +19,7 @@ #define _AO_PINS_H_ #if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -39,6 +40,7 @@ #endif #if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -63,6 +65,7 @@ #endif #if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 @@ -81,6 +84,7 @@ #endif #if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -103,6 +107,7 @@ #endif #if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 @@ -121,6 +126,7 @@ #endif #if defined(TIDONGLE) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 -- cgit v1.2.3 From 0e4c55d78852415e79f7318471f4d00c89703b78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:03:57 -0800 Subject: altos: Add TeleMini v1.0 This adds initial code for the telemini board, a two channel flight computer with digital telemetry and a barometric sensor. Signed-off-by: Keith Packard --- src/Makefile | 7 +++++- src/Makefile.proto | 27 ++++++++++++++++++++++ src/ao_pins.h | 19 +++++++++++++++ src/ao_telemini.c | 51 +++++++++++++++++++++++++++++++++++++++++ src/telemini-v0.1/.gitignore | 2 ++ src/telemini-v0.1/.sdcdbrc | 1 + src/telemini-v0.1/Makefile | 1 + src/telemini-v0.1/Makefile.defs | 8 +++++++ 8 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/ao_telemini.c create mode 100644 src/telemini-v0.1/.gitignore create mode 100644 src/telemini-v0.1/.sdcdbrc create mode 100644 src/telemini-v0.1/Makefile create mode 100644 src/telemini-v0.1/Makefile.defs diff --git a/src/Makefile b/src/Makefile index a6615321..42383f88 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,12 @@ CC=sdcc include Version -SUBDIRS=telemetrum-v1.1 telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=\ + telemetrum-v1.1 telemetrum-v1.0 \ + teledongle-v0.2 teledongle-v0.1 \ + telemini-v0.1 \ + telemetrum-v0.1-sky telemetrum-v0.1-sirf \ + tidongle test all: all-recursive diff --git a/src/Makefile.proto b/src/Makefile.proto index 30cd5798..625ca459 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -159,6 +159,33 @@ TM_BASE_SRC = \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) +# +# Sources for TeleMini +TMINI_DRIVER_SRC = \ + ao_adc.c \ + ao_ignite.c \ + ao_config.c \ + ao_storage.c \ + ao_intflash.c + +TMINI_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_report.c \ + ao_telemetry.c + +TMINI_MAIN_SRC = \ + ao_telemini.c + +TMINI_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TMINI_DRIVER_SRC) \ + $(TMINI_TASK_SRC) \ + $(TMINI_MAIN_SRC) + TI_MAIN_SRC = \ ao_tidongle.c diff --git a/src/ao_pins.h b/src/ao_pins.h index a486b9ba..8e07be86 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -83,6 +83,25 @@ #define SPI_CS_ON_P0 0 #endif +#if defined(TELEMINI_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 +#endif + #if defined(TELEMETRUM_V_0_1) #define HAS_FLIGHT 1 #define HAS_USB 1 diff --git a/src/ao_telemini.c b/src/ao_telemini.c new file mode 100644 index 00000000..97bc2cf4 --- /dev/null +++ b/src/ao_telemini.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +/* stub so as telemini doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/telemini-v0.1/.gitignore b/src/telemini-v0.1/.gitignore new file mode 100644 index 00000000..82868aac --- /dev/null +++ b/src/telemini-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemini-* +ao_product.h diff --git a/src/telemini-v0.1/.sdcdbrc b/src/telemini-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemini-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemini-v0.1/Makefile b/src/telemini-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemini-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs new file mode 100644 index 00000000..8a3e1ef9 --- /dev/null +++ b/src/telemini-v0.1/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telemini-v0.1-$(VERSION).ihx + +SRC = \ + $(TMINI_BASE_SRC) + +PRODUCT=TeleMini-v0.1 +PRODUCT_DEF=-DTELEMINI_V_0_1 +IDPRODUCT=0x000a -- cgit v1.2.3 From fc5d014721a7e5a7b22f07eb4ab0bb3c764473fe Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 26 Feb 2011 16:06:48 +1000 Subject: ao_intflash: Avoid overwriting code Require firmware to specify the end of its codespace in its Makefile, and use this to determine where the start of available flash is. Should give compile time errors if either there's no room left for storage, or if there's not enough room for code. --- src/Makefile.proto | 6 ++++-- src/ao_intflash.c | 2 +- src/telemini-v0.1/Makefile.defs | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 625ca459..ee3b4d6c 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -13,9 +13,11 @@ ifndef VERSION include ../Version endif -CFLAGS=--model-small --debug --opt-code-speed +CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ +CODESIZE ?= 0x8000 + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff INC = \ diff --git a/src/ao_intflash.c b/src/ao_intflash.c index ad5e5aac..450d94a3 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -24,7 +24,7 @@ #define FCTL_WRITE (1 << 1) #define FCTL_ERASE (1 << 0) -#define ENDOFCODE (0x51f0 + 1500) +#define ENDOFCODE (CODESIZE) #define NUM_PAGES ((0x8000-ENDOFCODE)/1024) #define SIZE (1024*NUM_PAGES) #define LOCN (0x8000 - SIZE) diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs index 8a3e1ef9..94ac1268 100644 --- a/src/telemini-v0.1/Makefile.defs +++ b/src/telemini-v0.1/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleMini-v0.1 PRODUCT_DEF=-DTELEMINI_V_0_1 IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From f8afc2641c779fc312a42a6358187d8716ebe61a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 23:52:11 -0800 Subject: altos: Switch LED usage for TeleMini around We're using the LEDs instead of tones, so make red mean 'low tone', green mean 'middle tone' and both mean 'high tone'. Signed-off-by: Keith Packard --- src/ao_report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_report.c b/src/ao_report.c index c9ee7cae..4646fb09 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -42,9 +42,9 @@ static const uint8_t flight_reports[] = { #define mid(time) ao_beep_for(AO_BEEP_MID, time) #define high(time) ao_beep_for(AO_BEEP_HIGH, time) #else -#define low(time) ao_led_for(AO_LED_RED, time) -#define mid(time) ao_led_for(AO_LED_RED|AO_LED_GREEN, time) -#define high(time) ao_led_for(AO_LED_GREEN, time) +#define low(time) ao_led_for(AO_LED_GREEN, time) +#define mid(time) ao_led_for(AO_LED_RED, time) +#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) #endif #define pause(time) ao_delay(time) -- cgit v1.2.3 From ddd7485f05d0cad8f5b3e1ee9b9a4d2812ea1837 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 08:03:11 -0800 Subject: altos: Switch pins around for TeleMini TeleMini has fewer sensors and uses P0 for igniters instead of P2. Signed-off-by: Keith Packard --- src/ao_adc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/ao_ignite.c | 10 ++++++++++ src/ao_pins.h | 22 ++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) diff --git a/src/ao_adc.c b/src/ao_adc.c index 9990a1fd..ce935716 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -48,6 +48,8 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; +#if IGNITE_ON_P2 + /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); @@ -71,7 +73,47 @@ ao_adc_isr(void) __interrupt 1 else #endif ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; - } else { + } +#endif + +#if IGNITE_ON_P0 + /* TeleMini readings */ + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); + switch (sequence) { + case 0: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; + break; + case 1: + /* drogue sense */ + a += 6; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; + break; + case 2: + /* main sense */ + a += 8; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } + a[0] = ADCL; + a[1] = ADCH; + if (sequence) { + /* Start next conversion */ + ADCCON3 = sequence; + } +#endif + + else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); @@ -97,6 +139,8 @@ __code struct ao_cmds ao_adc_cmds[] = { void ao_adc_init(void) { +#if IGNITE_ON_P2 + /* TeleMetrum configuration */ ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ #if HAS_EXTERNAL_TEMP @@ -105,6 +149,15 @@ ao_adc_init(void) (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ +#endif + +#if IGNITE_ON_P0 + /* TeleMini configuration */ + ADCCFG = ((1 << 0) | /* pressure */ + (1 << 1) | /* drogue sense */ + (1 << 2) | /* main sense */ + (1 << 3)); /* battery voltage */ +#endif /* enable interrupts */ ADCIF = 0; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 798ba9b4..7874ee01 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -17,11 +17,21 @@ #include "ao.h" +#if IGNITE_ON_P2 #define AO_IGNITER_DROGUE P2_3 #define AO_IGNITER_MAIN P2_4 #define AO_IGNITER_DIR P2DIR #define AO_IGNITER_DROGUE_BIT (1 << 3) #define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 diff --git a/src/ao_pins.h b/src/ao_pins.h index 8e07be86..0de39970 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -29,6 +29,8 @@ #define HAS_DBG 1 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -50,6 +52,8 @@ #define HAS_DBG 1 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -74,6 +78,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 @@ -92,6 +98,8 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -113,6 +121,8 @@ #define HAS_EEPROM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 #define AO_LED_RED 2 @@ -135,6 +145,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 @@ -154,6 +166,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 @@ -210,6 +224,14 @@ #define SPI_CS_DIR P0DIR #endif +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + #ifndef HAS_SERIAL_1 #error Please define HAS_SERIAL_1 #endif -- cgit v1.2.3 From 57d83f51377fb58018f422e42d74f29b86a821d2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 15:26:41 -0800 Subject: bringup: Add script for telemini Copied from teledongle with a few obvious changes. Signed-off-by: Keith Packard --- ao-bringup/turnon_telemini | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100755 ao-bringup/turnon_telemini diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini new file mode 100755 index 00000000..17416bf0 --- /dev/null +++ b/ao-bringup/turnon_telemini @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleMini v0.1 Turn-On and Calibration Program" +echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleMini v0.1 powered from USB" +echo "\t\twith TIdongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from SMA to frequency counter" +echo +echo -n "TeleMini serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD -D 100 -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +$RAWLOAD -D 100 -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` + +echo "Programming flash with cal value " $CAL_VALUE +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v0.1*.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From d007bccf6cb36d24a9c7c48de7d80759ac6f2e37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 15:57:58 -0800 Subject: ao-load: Make usb descriptor rewriting optional TeleMini and TeleNano don't have USB descriptors to rewrite when loading firmware, so allow them to be missing. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 72 ++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 5accefc8..1b729d39 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -29,17 +29,18 @@ struct sym { unsigned addr; char *name; + int required; } ao_symbols[] = { - { 0, "_ao_serial_number" }, + { 0, "_ao_serial_number", 1 }, #define AO_SERIAL_NUMBER (ao_symbols[0].addr) - { 0, "_ao_usb_descriptors" }, + { 0, "_ao_usb_descriptors", 0 }, #define AO_USB_DESCRIPTORS (ao_symbols[1].addr) - { 0, "_ao_radio_cal" }, + { 0, "_ao_radio_cal", 1 }, #define AO_RADIO_CAL (ao_symbols[2].addr) }; -#define NUM_SERIAL_SYMBOLS 2 #define NUM_SYMBOLS 3 +#define NUM_REQUIRED_SYMBOLS 2 static int find_symbols(FILE *map) @@ -51,7 +52,7 @@ find_symbols(FILE *map) char *colon; unsigned long a; int s; - int found = 0; + int required = 0; while (fgets(line, sizeof(line), map) != NULL) { line[sizeof(line)-1] = '\0'; @@ -70,11 +71,12 @@ find_symbols(FILE *map) for (s = 0; s < NUM_SYMBOLS; s++) if (!strcmp(ao_symbols[s].name, name)) { ao_symbols[s].addr = (unsigned) a; - ++found; + if (ao_symbols[s].required) + ++required; break; } } - return found >= NUM_SERIAL_SYMBOLS; + return required >= NUM_REQUIRED_SYMBOLS; } static int @@ -125,7 +127,6 @@ main (int argc, char **argv) char serial_int[2]; unsigned int s; int i; - unsigned usb_descriptors; int string_num; char *tty = NULL; char *device = NULL; @@ -207,35 +208,38 @@ main (int argc, char **argv) exit(1); } - usb_descriptors = AO_USB_DESCRIPTORS - image->address; - string_num = 0; - while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { - if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) { - ++string_num; - if (string_num == 4) - break; + if (AO_USB_DESCRIPTORS) { + unsigned usb_descriptors; + usb_descriptors = AO_USB_DESCRIPTORS - image->address; + string_num = 0; + while (image->data[usb_descriptors] != 0 && usb_descriptors < image->length) { + if (image->data[usb_descriptors+1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + usb_descriptors += image->data[usb_descriptors]; + } + if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) { + fprintf(stderr, "Cannot rewrite serial string at %04x\n", AO_USB_DESCRIPTORS); + exit(1); } - usb_descriptors += image->data[usb_descriptors]; - } - if (usb_descriptors >= image->length || image->data[usb_descriptors] == 0 ) { - fprintf(stderr, "Cannot rewrite serial string at %04x\n", AO_USB_DESCRIPTORS); - exit(1); - } - serial_ucs2_len = image->data[usb_descriptors] - 2; - serial_ucs2 = malloc(serial_ucs2_len); - if (!serial_ucs2) { - fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); - exit(1); - } - s = serial; - for (i = serial_ucs2_len / 2; i; i--) { - serial_ucs2[i * 2 - 1] = 0; - serial_ucs2[i * 2 - 2] = (s % 10) + '0'; - s /= 10; + serial_ucs2_len = image->data[usb_descriptors] - 2; + serial_ucs2 = malloc(serial_ucs2_len); + if (!serial_ucs2) { + fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); + exit(1); + } + s = serial; + for (i = serial_ucs2_len / 2; i; i--) { + serial_ucs2[i * 2 - 1] = 0; + serial_ucs2[i * 2 - 2] = (s % 10) + '0'; + s /= 10; + } + if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) + usage(argv[0]); } - if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) - usage(argv[0]); if (cal) { cal_int[0] = cal & 0xff; -- cgit v1.2.3 From 1d8579f973bfe1047ee91f03555e74abdc483e69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 16:31:43 -0800 Subject: altos: oops -- altitude reporting wasn't pausing between signals need to actually alternate the LED/tone with some space so you can count. Signed-off-by: Keith Packard --- src/ao_report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_report.c b/src/ao_report.c index 4646fb09..3223390f 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -78,7 +78,7 @@ ao_report_digit(uint8_t digit) __reentrant } else { while (digit--) { mid(AO_MS_TO_TICKS(200)); - mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); } } pause(AO_MS_TO_TICKS(300)); -- cgit v1.2.3 From 82707a05af0eb2d54f46b58805c95cdf4e5a3703 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Mar 2011 20:36:50 -0700 Subject: altos: Internal flash ops block when running from flash The docs say that if you are executing from flash, then the CPU will stall after a flash write or erase command is started until the operation is complete. Take advantage of that to simplify the flash code. Signed-off-by: Keith Packard --- src/ao_intflash.c | 151 ++++++++++++++++++++++++++++-------------------------- src/cc1111.h | 20 ++++++++ 2 files changed, 98 insertions(+), 73 deletions(-) diff --git a/src/ao_intflash.c b/src/ao_intflash.c index 450d94a3..88d1f7f6 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -18,38 +18,45 @@ #include "ao.h" #include "cc1111.h" -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - #define ENDOFCODE (CODESIZE) -#define NUM_PAGES ((0x8000-ENDOFCODE)/1024) -#define SIZE (1024*NUM_PAGES) -#define LOCN (0x8000 - SIZE) +#define AO_INTFLASH_BLOCK 1024 +#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) +#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) +#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) + +/* + * 21000 * 24e6 + * FWT = ------------ + * 16e9 + * + * = 31.5 + * + * Round up and use 32 + */ -#if NUM_PAGES < 1 +#define FLASH_TIMING 0x20 + +#if AO_INTFLASH_BLOCKS < 2 #error "Too few pages" #endif -#if LOCN % 1024 != 0 +#if AO_INFTLASH_LOCATION % 1024 != 0 #error "Pages aren't aligned properly" #endif -__xdata __at(LOCN) uint8_t ao_intflash[SIZE]; +__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; /* Total bytes of available storage */ __xdata uint32_t ao_storage_total = sizeof(ao_intflash); /* Block size - device is erased in these units. */ -__xdata uint32_t ao_storage_block = 1024; +__xdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config = sizeof(ao_intflash); +__xdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; /* Storage unit size - device reads and writes must be within blocks of this size. */ -__xdata uint16_t ao_storage_unit = 1024; +__xdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; __xdata static uint8_t ao_intflash_dma_done; static uint8_t ao_intflash_dma; @@ -76,21 +83,16 @@ ao_storage_erase(uint32_t pos) __reentrant addr = ((uint16_t)(ao_intflash + pos) >> 1); - while (FCTL & FCTL_BUSY) - ; - - FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz FADDRH = addr >> 8; - FADDRL = addr & ~0xFF00; - - _asm - .even - orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE - nop; ; Required, see datasheet. - _endasm; - - while (FCTL & FCTL_BUSY) - ; + FADDRL = addr; + + __critical { + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop ; Required, see datasheet. + _endasm; + } return 1; } @@ -100,45 +102,54 @@ ao_storage_erase(uint32_t pos) __reentrant */ static void -word_aligned_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant { - uint16_t addr; - - addr = ((uint16_t)(ao_intflash + pos) >> 1); - - ao_dma_set_transfer(ao_intflash_dma, d, &X_FWDATA, - DMA_LEN_HIGH_VLEN_LEN | len, - DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_FLASH, - DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | - DMA_CFG1_IRQMASK | DMA_CFG1_PRIORITY_HIGH); - - while (FCTL & FCTL_BUSY) - ; - - FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz - - FADDRH = addr >> 8; - FADDRL = addr & ~0xFF00; + pos = ((uint16_t) ao_intflash + pos) >> 1; + + ao_dma_set_transfer(ao_intflash_dma, + d, + &FWDATAXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + + FADDRH = pos >> 8; + FADDRL = pos; ao_dma_start(ao_intflash_dma); - _asm - .even - orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE - _endasm; + __critical { + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + nop + _endasm; + } +} - __critical while (!ao_intflash_dma_done) - ao_sleep(&ao_intflash_dma_done); +static void +ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant +{ + static __xdata uint8_t b[2]; - while (FCTL & (FCTL_BUSY | FCTL_SWBSY)) - ; + if (pos & 1) { + b[0] = 0xff; + b[1] = byte; + } else { + b[0] = byte; + b[1] = 0xff; + } + ao_intflash_write_aligned(pos, b, 2); } uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant { - static __xdata uint8_t b[2]; + uint16_t pos = pos32; __xdata uint8_t *d = v; uint8_t oddlen; @@ -148,23 +159,15 @@ ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant return 1; if (pos & 1) { - b[0] = ~0; - b[1] = d[0]; - word_aligned_write(pos-1, b, 2); - pos++; + ao_intflash_write_byte(pos++, *d++); len--; - d++; } oddlen = len & 1; - len &= ~1; - if (len > 0) { - word_aligned_write(pos, d, len); - } - if (oddlen) { - b[0] = d[len]; - b[1] = ~0; - word_aligned_write(pos+len, b, 2); - } + len -= oddlen; + if (len) + ao_intflash_write_aligned(pos, d, len); + if (oddlen) + ao_intflash_write_byte(pos + len, d[len]); return 1; } @@ -194,11 +197,13 @@ ao_storage_setup(void) void ao_storage_device_info(void) __reentrant { - printf ("Using internal flash, starting at 0x%04x\n", LOCN); + printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); } void ao_storage_device_init(void) { ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); + + FWT = FLASH_TIMING; } diff --git a/src/cc1111.h b/src/cc1111.h index 20ed052a..effb1a68 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -884,6 +884,26 @@ __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; sfr at 0xc2 U0BAUD; sfr at 0xfa U1BAUD; +/* Flash controller */ + +sfr at 0xAE FCTL; +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +/* Flash write data. Write two bytes here */ +sfr at 0xAF FWDATA; +__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; + +/* Flash write/erase address */ +sfr at 0xAD FADDRH; +sfr at 0xAC FADDRL; + +/* Flash timing */ +sfr at 0xAB FWT; + /* Radio */ sfr at 0xD9 RFD; -- cgit v1.2.3 From 8b546b474b7b6c5b4169b4c1ca09c6f17ebb3ae5 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 11 Mar 2011 21:41:01 +1000 Subject: ignore new flight test file --- src/test/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/.gitignore b/src/test/.gitignore index 54b00096..0a43de8a 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -1,4 +1,5 @@ ao_flight_test +ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test -- cgit v1.2.3 From c826fab31f8aea25a942b6bb8435d4b04c1bef10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Mar 2011 16:00:10 -0700 Subject: altos: Add tiny logging for TeleMini/TeleNano This splits the logging code into management of the log space within storage and separate code to actually write suitable log entries. A new log writing module, ao_log_tiny, is added which writes only altimeter data at a fairly low data rate for devices using on-chip storage. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 + src/ao.h | 102 ++++++++++++++++++++------------- src/ao_log.c | 162 ++++++----------------------------------------------- src/ao_log_big.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++ src/ao_log_tiny.c | 82 +++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 184 deletions(-) create mode 100644 src/ao_log_big.c create mode 100644 src/ao_log_tiny.c diff --git a/src/Makefile.proto b/src/Makefile.proto index ee3b4d6c..30e626ad 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -142,6 +142,7 @@ SKY_DRIVER_SRC = \ TM_TASK_SRC = \ ao_flight.c \ ao_log.c \ + ao_log_big.c \ ao_report.c \ ao_telemetry.c @@ -173,6 +174,7 @@ TMINI_DRIVER_SRC = \ TMINI_TASK_SRC = \ ao_flight.c \ ao_log.c \ + ao_log_tiny.c \ ao_report.c \ ao_telemetry.c diff --git a/src/ao.h b/src/ao.h index 5bbe5158..fd8c6034 100644 --- a/src/ao.h +++ b/src/ao.h @@ -516,6 +516,70 @@ ao_storage_device_info(void) __reentrant; * ao_log.c */ +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __xdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + /* * The data log is recorded in the eeprom as a sequence * of data packets. @@ -614,44 +678,6 @@ struct ao_log_record { uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; -/* Flush the log */ -void -ao_log_flush(void); - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -/* Logging thread main routine */ -void -ao_log(void); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - /* * ao_flight.c */ diff --git a/src/ao_log.c b/src/ao_log.c index 817d3e6f..433e9c3a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -17,43 +17,12 @@ #include "ao.h" -static __pdata uint32_t ao_log_current_pos; -static __pdata uint32_t ao_log_end_pos; -static __pdata uint32_t ao_log_start_pos; -static __xdata uint8_t ao_log_running; -static __xdata uint8_t ao_log_mutex; - -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant -{ - uint8_t sum = 0x5a; - uint8_t i; - - for (i = 0; i < sizeof (struct ao_log_record); i++) - sum += *b++; - return -sum; -} - -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_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - log, - sizeof (struct ao_log_record)); - ao_log_current_pos += sizeof (struct ao_log_record); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} +__pdata uint32_t ao_log_current_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__xdata enum flight_state ao_log_state; +__xdata uint16_t ao_flight_number; void ao_log_flush(void) @@ -61,91 +30,6 @@ ao_log_flush(void) ao_storage_flush(); } -static void ao_log_scan(void); - -__xdata struct ao_log_record log; -__xdata uint16_t ao_flight_number; - -static uint8_t -ao_log_dump_check_data(void) -{ - if (ao_log_csum((uint8_t *) &log) != 0) - return 0; - return 1; -} - -__xdata uint8_t ao_log_adc_pos; -__xdata enum flight_state ao_log_state; - -/* a hack to make sure that ao_log_records fill the eeprom block in even units */ -typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; - -void -ao_log(void) -{ - ao_storage_setup(); - - ao_log_scan(); - - while (!ao_log_running) - ao_sleep(&ao_log_running); - - log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; -#if HAS_ACCEL - log.u.flight.ground_accel = ao_ground_accel; -#endif - log.u.flight.flight = ao_flight_number; - ao_log_data(&log); - - /* Write the whole contents of the ring to the log - * when starting up. - */ - ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); - for (;;) { - /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_flight_adc) { - log.type = AO_LOG_SENSOR; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if ((ao_log_adc_pos & 0x1f) == 0) { - log.type = AO_LOG_TEMP_VOLT; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; - ao_log_data(&log); - log.type = AO_LOG_DEPLOY; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; - ao_log_data(&log); - } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } - - /* Wait for a while */ - ao_delay(AO_MS_TO_TICKS(100)); - - /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); - } -} - /* * When erasing a flight log, make sure the config block * has an up-to-date version of the current flight number @@ -205,25 +89,12 @@ ao_log_slots() return (uint8_t) (ao_storage_config / ao_config.flight_log_max); } -static uint32_t +uint32_t ao_log_pos(uint8_t slot) { return ((slot) * ao_config.flight_log_max); } -static uint16_t -ao_log_flight(uint8_t slot) -{ - if (!ao_storage_read(ao_log_pos(slot), - &log, - sizeof (struct ao_log_record))) - return 0; - - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) - return log.u.flight.flight; - return 0; -} - static uint16_t ao_log_max_flight(void) { @@ -244,7 +115,7 @@ ao_log_max_flight(void) return max_flight; } -static void +void ao_log_scan(void) __reentrant { uint8_t log_slot; @@ -364,20 +235,21 @@ ao_log_delete(void) __reentrant ao_log_current_pos = ao_log_pos(slot); ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { + uint8_t i; + static __xdata uint8_t b; + /* * Check to see if we've reached the end of * the used memory to avoid re-erasing the same * memory over and over again */ - if (ao_storage_read(ao_log_current_pos, - &log, - sizeof (struct ao_log_record))) { - for (slot = 0; slot < sizeof (struct ao_log_record); slot++) - if (((uint8_t *) &log)[slot] != 0xff) + for (i = 0; i < 16; i++) { + if (ao_storage_read(ao_log_current_pos + i, &b, 1)) + if (b != 0xff) break; - if (slot == sizeof (struct ao_log_record)) - break; } + if (i == 16) + break; ao_storage_erase(ao_log_current_pos); ao_log_current_pos += ao_storage_block; } @@ -389,8 +261,6 @@ ao_log_delete(void) __reentrant printf("No such flight: %d\n", ao_cmd_lex_i); } - - __code struct ao_cmds ao_log_cmds[] = { { ao_log_list, "l\0List stored flight logs" }, { ao_log_delete, "d \0Delete stored flight" }, diff --git a/src/ao_log_big.c b/src/ao_log_big.c new file mode 100644 index 00000000..6db4a0ff --- /dev/null +++ b/src/ao_log_big.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_record log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +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_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); + ao_log_current_pos += sizeof (struct ao_log_record); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __xdata uint8_t ao_log_adc_pos; + +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + +void +ao_log(void) +{ + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_flight_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.flight = ao_flight_number; + ao_log_data(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_flight_adc) { + log.type = AO_LOG_SENSOR; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if ((ao_log_adc_pos & 0x1f) == 0) { + log.type = AO_LOG_TEMP_VOLT; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; + log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + ao_log_data(&log); + log.type = AO_LOG_DEPLOY; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; + log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + ao_log_data(&log); + } + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_record))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c new file mode 100644 index 00000000..877c1033 --- /dev/null +++ b/src/ao_log_tiny.c @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __data uint16_t ao_log_tiny_interval; +static __data uint32_t ao_log_tiny_pos; + +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) + +void +ao_log_tiny_set_interval(uint16_t ticks) +{ + ao_log_tiny_interval = ticks; +} + +static __xdata uint16_t ao_log_tiny_data_temp; + +#define ao_log_tiny_data(d) do { \ + ao_log_tiny_data_temp = (d); \ + ao_storage_write(ao_log_tiny_pos, &ao_log_tiny_data_temp, 2); \ + ao_log_tiny_pos += 2; \ + } while (0) + +void +ao_log(void) +{ + uint16_t time; + int16_t delay; + enum ao_flight_state ao_log_tiny_state; + + ao_storage_setup(); + + ao_log_tiny_state = ao_flight_invalid; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; + while (!ao_log_running) + ao_sleep(&ao_log_running); + + time = ao_time(); + ao_log_tiny_data(ao_flight_number); + for (;;) { + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + } + ao_log_tiny_data(ao_flight_pres); // XXX change to alt + time += ao_log_tiny_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + static __xdata uint16_t flight; + + (void) slot; + ao_storage_read(0, &flight, 2); + if (flight == 0xffff) + flight = 0; + return flight; +} -- cgit v1.2.3 From 62eae8a17d870e8ac6937ba23da01a5fbc652c6c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 16:53:11 -0700 Subject: altos: Add kalman filters for baro-only boards This adds a baro-only kalman filter to track the state of the rocket, and then uses it to control flight events instead of the existing ad-hoc mechanisms. Signed-off-by: Keith Packard --- src/ao_flight.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/ao_flight_test.c | 70 +++++++++++++++++++++++++++++----- src/ao_pins.h | 4 ++ 3 files changed, 165 insertions(+), 13 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 8e370c4f..e8130baa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -31,6 +31,10 @@ #error Please define HAS_USB #endif +#ifndef USE_KALMAN +#error Please define USE_KALMAN +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ @@ -150,6 +154,62 @@ __pdata int16_t ao_old_vel_tick; __xdata int32_t ao_raw_accel_sum; #endif +#if USE_KALMAN +__pdata int16_t ao_ground_height; +__pdata int32_t ao_k_max_height; +__pdata int32_t ao_k_height; +__pdata int32_t ao_k_speed; +__pdata int32_t ao_k_accel; + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) + +#define from_fix(x) ((x) >> 16) + +#define AO_K0_100 to_fix16(0.05680323) +#define AO_K1_100 to_fix16(0.16608182) +#define AO_K2_100 to_fix16(0.24279580) + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K0_10 to_fix16(0.23772023) +#define AO_K1_10 to_fix16(0.32214149) +#define AO_K2_10 to_fix16(0.21827159) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +static void +ao_kalman_baro(void) +{ + int16_t err = ((ao_pres_to_altitude(ao_raw_pres) - ao_ground_height)) + - (int16_t) (ao_k_height >> 16); + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_10 + + (ao_k_accel >> 16) * AO_K_STEP_2_2_10); + ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_10; + + /* correct */ + ao_k_height += (int32_t) AO_K0_10 * err; + ao_k_speed += (int32_t) AO_K1_10 * err; + ao_k_accel += (int32_t) AO_K2_10 * err; + return; + } +#endif + ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_100 + + (ao_k_accel >> 16) * AO_K_STEP_2_2_100); + ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_100; + + /* correct */ + ao_k_height += (int32_t) AO_K0_100 * err; + ao_k_speed += (int32_t) AO_K1_100 * err; + ao_k_accel += (int32_t) AO_K2_100 * err; +} +#endif + __xdata int32_t ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer @@ -296,6 +356,10 @@ ao_flight(void) ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; #endif +#if USE_KALMAN + if (ao_flight_state > ao_flight_idle) + ao_kalman_baro(); +#endif ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } @@ -333,6 +397,9 @@ ao_flight(void) ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); +#if USE_KALMAN + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); +#endif ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); #if HAS_ACCEL ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; @@ -369,7 +436,6 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; - #if HAS_USB /* Disable the USB controller in flight mode * to save power @@ -421,14 +487,20 @@ ao_flight(void) * the barometer, but we use both to make sure this * transition is detected */ +#if USE_KALMAN + if ((ao_k_accel > to_fix32(20) && + ao_k_speed > to_fix32(5)) || + ao_k_height > to_fix32(20)) +#else if ( #if HAS_ACCEL (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && ao_flight_vel > ACCEL_VEL_BOOST) || #endif ao_flight_pres < ao_ground_pres - BARO_LAUNCH) +#endif { -#if HAS_ACCEL +#if HAS_ACCEL || USE_KALMAN ao_flight_state = ao_flight_boost; #else ao_flight_state = ao_flight_coast; @@ -454,7 +526,7 @@ ao_flight(void) break; } break; -#if HAS_ACCEL +#if HAS_ACCEL || USE_KALMAN case ao_flight_boost: /* boost to fast: @@ -467,8 +539,13 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ +#if USE_KALMAN + if ((ao_k_accel < to_fix32(-10) && ao_k_height > to_fix32(100)) || + (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) +#else if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) +#endif { ao_flight_state = ao_flight_fast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -492,20 +569,34 @@ ao_flight(void) * how big a pressure change the mach transition * generates would be useful here. */ +#if USE_KALMAN + if (ao_k_speed < to_fix32(200) || + ao_k_height < ao_k_max_height - to_fix32(500)) +#else if (ao_flight_vel < ACCEL_VEL_MACH || ao_flight_pres > ao_min_pres + BARO_COAST) +#endif { +#if HAS_ACCEL /* set min velocity to current velocity for * apogee detect */ ao_min_vel = abs(ao_flight_vel); +#endif ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; -#endif +#endif /* HAS_ACCEL */ case ao_flight_coast: +#if USE_KALMAN + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + */ + if (ao_k_speed < 0) +#else /* apogee detect: coast to drogue deploy: * * barometer: fall at least 10m @@ -517,6 +608,7 @@ ao_flight(void) * we'll trust to a single sensor for this test */ if (ao_flight_pres > ao_min_pres + BARO_APOGEE) +#endif { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -569,7 +661,11 @@ ao_flight(void) * at that point. Perhaps also use the drogue sense lines * to notice continutity? */ +#if USE_KALMAN + if (from_fix(ao_k_height) < ao_config.main_deploy) +#else if (ao_flight_pres >= ao_main_pres) +#endif { ao_ignite(ao_igniter_main); ao_flight_state = ao_flight_main; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index a635803f..16167644 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #define AO_HERTZ 100 @@ -62,6 +63,7 @@ enum ao_flight_state { struct ao_adc ao_adc_ring[AO_ADC_RING]; uint8_t ao_adc_head; +int ao_summary = 0; #define ao_led_on(l) #define ao_led_off(l) @@ -79,10 +81,13 @@ enum ao_igniter { ao_igniter_main = 1 }; +struct ao_adc ao_adc_static; + void ao_ignite(enum ao_igniter igniter) { - printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); + printf ("ignite %s at %7.2f\n", igniter == ao_igniter_drogue ? "drogue" : "main", + (double) ao_adc_static.tick / 100.0); } struct ao_task { @@ -99,8 +104,6 @@ struct ao_task { #define AO_FLIGHT_TEST -struct ao_adc ao_adc_static; - FILE *emulator_in; void @@ -140,20 +143,37 @@ struct ao_config ao_config; #ifndef HAS_ACCEL #define HAS_ACCEL 1 #define HAS_ACCEL_REF 0 +#define USE_KALMAN 0 +#else +#define USE_KALMAN 1 #endif #include "ao_flight.c" +#define to_double(f) ((f) / 65536.0) + void ao_insert(void) { ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); + if (ao_summary) + return; if (ao_flight_state != ao_flight_startup) { +#if USE_KALMAN + printf("time %7.2f accel %d pres %d k_height %8.2f k_speed %8.5f k_accel %8.5f\n", + (double) ao_adc_static.tick / 100, + ao_adc_static.accel, + ao_adc_static.pres, + to_double(ao_k_height), + to_double(ao_k_speed), + to_double(ao_k_accel)); +#else printf("time %g accel %d pres %d\n", (double) ao_adc_static.tick / 100, ao_adc_static.accel, ao_adc_static.pres); +#endif } } @@ -269,6 +289,8 @@ ao_dump_state(void) { if (ao_flight_state == ao_flight_startup) return; + if (ao_summary) + return; #if HAS_ACCEL printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", ao_state_names[ao_flight_state], @@ -286,14 +308,44 @@ ao_dump_state(void) exit(0); } +static const struct option options[] = { + { .name = "summary", .has_arg = 0, .val = 's' }, + { 0, 0, 0, 0}, +}; + +void run_flight_fixed(char *name, FILE *f, int summary) +{ + emulator_in = f; + ao_summary = summary; + ao_flight_init(); + ao_flight(); +} + int main (int argc, char **argv) { - emulator_in = fopen (argv[1], "r"); - if (!emulator_in) { - perror(argv[1]); - exit(1); + int summary = 0; + int c; + int i; + + while ((c = getopt_long(argc, argv, "s", options, NULL)) != -1) { + switch (c) { + case 's': + summary = 1; + break; + } } - ao_flight_init(); - ao_flight(); + + if (optind == argc) + run_flight_fixed("", stdin, summary); + else + for (i = optind; i < argc; i++) { + FILE *f = fopen(argv[i], "r"); + if (!f) { + perror(argv[i]); + continue; + } + run_flight_fixed(argv[i], f, summary); + fclose(f); + } } diff --git a/src/ao_pins.h b/src/ao_pins.h index 0de39970..353b5fd5 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -27,6 +27,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 1 + #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -50,6 +51,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 1 + #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -98,6 +100,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 0 + #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -118,6 +121,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 + #define USE_KALMAN 0 #define HAS_EEPROM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 -- cgit v1.2.3 From 32c51840c792a737019fbc9fe42f2ca073b71827 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 19:49:46 -0700 Subject: altos: Tiny logging fixes. Scan at start, stop when land or full. Initialize the flight log for tiny systems by scanning the log area to find the current flight number and log area bounds. Stop logging data when the flight is over, or when the log area is full. Signed-off-by: Keith Packard --- src/ao_log_tiny.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 877c1033..157073d4 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -18,7 +18,6 @@ #include "ao.h" static __data uint16_t ao_log_tiny_interval; -static __data uint32_t ao_log_tiny_pos; #define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) #define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) @@ -31,11 +30,16 @@ ao_log_tiny_set_interval(uint16_t ticks) static __xdata uint16_t ao_log_tiny_data_temp; -#define ao_log_tiny_data(d) do { \ - ao_log_tiny_data_temp = (d); \ - ao_storage_write(ao_log_tiny_pos, &ao_log_tiny_data_temp, 2); \ - ao_log_tiny_pos += 2; \ - } while (0) +static void ao_log_tiny_data(uint16_t d) +{ + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + ao_log_tiny_data_temp = (d); + ao_storage_write(ao_log_current_pos, &ao_log_tiny_data_temp, 2); + ao_log_current_pos += 2; + } +} void ao_log(void) @@ -46,6 +50,8 @@ ao_log(void) ao_storage_setup(); + ao_log_scan(); + ao_log_tiny_state = ao_flight_invalid; ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; while (!ao_log_running) @@ -60,12 +66,17 @@ ao_log(void) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; if (ao_log_tiny_state <= ao_flight_coast) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); } ao_log_tiny_data(ao_flight_pres); // XXX change to alt time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) ao_delay(delay); + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); } } -- cgit v1.2.3 From cbb968f5cf03625d453d84dc535758072a2c04c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:07:25 -0700 Subject: altos: Add TeleNano support This just uses the TeleMini bits, which should work fine for now. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/Makefile.proto | 31 +++++++++++++++++++++++++++++++ src/ao_adc.c | 30 ++++++++++++++++++++++++++++++ src/ao_pins.h | 22 ++++++++++++++++++++++ src/telenano-v0.1/.gitignore | 2 ++ src/telenano-v0.1/.sdcdbrc | 1 + src/telenano-v0.1/Makefile | 1 + src/telenano-v0.1/Makefile.defs | 9 +++++++++ 8 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/telenano-v0.1/.gitignore create mode 100644 src/telenano-v0.1/.sdcdbrc create mode 100644 src/telenano-v0.1/Makefile create mode 100644 src/telenano-v0.1/Makefile.defs diff --git a/src/Makefile b/src/Makefile index 42383f88..a5dec57b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ include Version SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ - telemini-v0.1 \ + telemini-v0.1 telenano-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/Makefile.proto b/src/Makefile.proto index 30e626ad..df514cfe 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -190,6 +190,37 @@ TMINI_BASE_SRC = \ $(TMINI_TASK_SRC) \ $(TMINI_MAIN_SRC) +# +# Sources for TeleNano +TNANO_DRIVER_SRC = \ + ao_adc.c \ + ao_ignite.c \ + ao_config.c \ + ao_storage.c \ + ao_intflash.c + +TNANO_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_report.c \ + ao_telemetry.c + +TNANO_MAIN_SRC = \ + ao_telemini.c + +TNANO_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TNANO_DRIVER_SRC) \ + $(TNANO_TASK_SRC) \ + $(TNANO_MAIN_SRC) + +# +# TI Dongle sources +# TI_MAIN_SRC = \ ao_tidongle.c diff --git a/src/ao_adc.c b/src/ao_adc.c index ce935716..d77e7753 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -30,7 +30,11 @@ ao_adc_poll(void) #if HAS_ACCEL_REF ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; #else +# ifdef TELENANO_V_0_1 + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; +# else ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +# endif #endif } @@ -62,6 +66,7 @@ ao_adc_isr(void) __interrupt 1 a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); sequence++; } +#define GOT_ADC a[0] = ADCL; a[1] = ADCH; if (sequence < 6) { @@ -79,6 +84,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); +#ifdef TELEMINI_V_0_1 switch (sequence) { case 0: /* pressure */ @@ -105,12 +111,36 @@ ao_adc_isr(void) __interrupt 1 sequence = 0; break; } +#define GOT_ADC +#endif +#ifdef TELENANO_V_0_1 + switch (sequence) { + case 1: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif a[0] = ADCL; a[1] = ADCH; if (sequence) { /* Start next conversion */ ADCCON3 = sequence; } +#endif +#ifndef GOT_ADC +#error No known ADC configuration set #endif else { diff --git a/src/ao_pins.h b/src/ao_pins.h index 353b5fd5..b4f177bf 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -113,6 +113,28 @@ #define HAS_ACCEL 0 #endif +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 0 + #define USE_KALMAN 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 +#endif + #if defined(TELEMETRUM_V_0_1) #define HAS_FLIGHT 1 #define HAS_USB 1 diff --git a/src/telenano-v0.1/.gitignore b/src/telenano-v0.1/.gitignore new file mode 100644 index 00000000..0412f7df --- /dev/null +++ b/src/telenano-v0.1/.gitignore @@ -0,0 +1,2 @@ +telenano-* +ao_product.h diff --git a/src/telenano-v0.1/.sdcdbrc b/src/telenano-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telenano-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telenano-v0.1/Makefile b/src/telenano-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telenano-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs new file mode 100644 index 00000000..34cf69d1 --- /dev/null +++ b/src/telenano-v0.1/Makefile.defs @@ -0,0 +1,9 @@ +PROG = telenano-v0.1-$(VERSION).ihx + +SRC = \ + $(TNANO_BASE_SRC) + +PRODUCT=TeleNano-v0.1 +PRODUCT_DEF=-DTELENANO_V_0_1 +IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From 1a8f45e7b720d01d3ff0c35ed1caaf8cbe0c3119 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 18 Mar 2011 21:12:12 -0600 Subject: fix up script to work and have reasonable texts --- ao-bringup/turnon_telemini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 17416bf0..8f694203 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -19,11 +19,11 @@ else fi echo "TeleMini v0.1 Turn-On and Calibration Program" -echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" +echo "Copyright 2011 by Bdale Garbee. Released under GPL v2" echo echo "Expectations:" -echo "\tTeleMini v0.1 powered from USB" -echo "\t\twith TIdongle (on /dev/ttyACM0) cabled to debug header" +echo "\tTeleMini v0.1 powered from LiPo" +echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" echo "\t\twith coax from SMA to frequency counter" echo echo -n "TeleMini serial number: " @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v0.1*.ihx $SERIAL +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/telemini-v0.1*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From dbe915795c66995805b5f37e6eb698cf2c143e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:26:12 -0700 Subject: altos: Fix mini/nano default log size to available flash space Also, remove accel cal code from boards without accel Signed-off-by: Keith Packard --- src/ao_config.c | 10 ++++++++-- src/ao_pins.h | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index c6d36247..771b21a1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,7 +27,11 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#if USE_INTERNAL_EEPROM +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config +#else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) +#endif #if HAS_EEPROM static void @@ -186,6 +190,7 @@ ao_config_main_deploy_set(void) __reentrant ao_config_main_deploy_show(); } +#if HAS_ACCEL void ao_config_accel_calibrate_show(void) __reentrant { @@ -252,6 +257,7 @@ ao_config_accel_calibrate_set(void) __reentrant ao_mutex_put(&ao_config_mutex); ao_config_accel_calibrate_show(); } +#endif /* HAS_ACCEL */ void ao_config_apogee_delay_show(void) __reentrant @@ -356,10 +362,10 @@ __code struct ao_config_var ao_config_vars[] = { "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, -#if HAS_ADC +#if HAS_ACCEL { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, -#endif /* HAS_ADC */ +#endif /* HAS_ACCEL */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, #if HAS_EEPROM diff --git a/src/ao_pins.h b/src/ao_pins.h index b4f177bf..c602268b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -26,6 +26,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define USE_KALMAN 0 #define DBG_ON_P1 1 @@ -50,6 +51,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define USE_KALMAN 0 #define DBG_ON_P1 1 @@ -99,6 +101,7 @@ #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define USE_KALMAN 1 #define IGNITE_ON_P2 0 @@ -121,6 +124,7 @@ #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define USE_KALMAN 1 #define IGNITE_ON_P2 0 @@ -145,6 +149,7 @@ #define HAS_DBG 0 #define USE_KALMAN 0 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 1 @@ -270,6 +275,12 @@ #error Please define HAS_EEPROM #endif +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + #ifndef HAS_DBG #error Please define HAS_DBG #endif -- cgit v1.2.3 From c985bb6a19c710409629f3c095332ba7afcf5248 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:36:59 -0700 Subject: altos/test: Add scripts to run lots of flights through the code This runs a long list of flights (there's a user-specific path pointing at the flights) and squawks if the baro and dual flight computers don't match. Signed-off-by: Keith Packard --- src/test/run-tests | 22 ++++++++++++++++ src/test/test-flights | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100755 src/test/run-tests create mode 100644 src/test/test-flights diff --git a/src/test/run-tests b/src/test/run-tests new file mode 100755 index 00000000..ec279776 --- /dev/null +++ b/src/test/run-tests @@ -0,0 +1,22 @@ +#!/bin/sh + +DIR=~/src/cc1111/flights + +while read flight; do + baro=`./ao_flight_test_baro -s $DIR/$flight | + awk '/drogue/ { printf "%s ", $4 } + /main/ { printf "%s\n", $4 }'` + full=`./ao_flight_test -s $DIR/$flight | + awk '/drogue/ { printf "%s ", $4 } + /main/ { printf "%s\n", $4 }'` + echo $flight $baro $full +done < test-flights | +awk '{ name = $1; + drogue_error = $2 - $4; + if (drogue_error < 0) drogue_error = -drogue_error; + main_error = $3 - $5; + if (main_error < 0) main_error = -main_error; + if (drogue_error > 4 || main_error > 4) + printf ("%s: baro drogue %f main %f. full drogue %f main %f\n", + name, $2, $3, $4, $5); + }' diff --git a/src/test/test-flights b/src/test/test-flights new file mode 100644 index 00000000..a9a2ecca --- /dev/null +++ b/src/test/test-flights @@ -0,0 +1,72 @@ +2009-06-03-serial-003-flight-002.eeprom +2009-06-05-serial-004-flight-008.eeprom +2009-06-06-serial-004-flight-009.eeprom +2009-06-14-serial-004-flight-010.eeprom +2009-06-20-serial-003-flight-003.eeprom +2009-07-04-serial-001-flight-006.eeprom +2009-07-18-serial-001-flight-007.eeprom +2009-08-22-serial-001-flight-001.eeprom +2009-08-22-serial-010-flight-001.eeprom +2009-09-05-serial-008-flight-002.eeprom +2009-09-05-serial-010-flight-002.eeprom +2009-09-05-serial-011-flight-001.eeprom +2009-09-11-serial-008-flight-003.eeprom +2009-09-12-serial-002-flight-002.eeprom +2009-09-12-serial-008-flight-005.eeprom +2009-09-12-serial-008-flight-007.eeprom +2009-09-19-serial-011-flight-002.eeprom +2009-10-03-serial-008-flight-009.eeprom +2009-10-03-serial-008-flight-010.eeprom +2009-10-03-serial-009-flight-001.eeprom +2009-10-03-serial-011-flight-003.eeprom +2009-10-17-serial-009-flight-002.eeprom +2009-11-14-serial-003-flight-005.eeprom +2009-11-14-serial-003-flight-006.eeprom +2009-11-21-serial-013-flight-001.eeprom +2009-11-21-serial-013-flight-002.eeprom +2010-02-13-serial-051-flight-002.eeprom +2010-02-13-serial-052-flight-002.eeprom +2010-02-28-serial-052-flight-003.eeprom +2010-02-28-serial-052-flight-004.eeprom +2010-03-06-serial-010-flight-004.eeprom +2010-03-06-serial-013-flight-003.eeprom +2010-03-06-serial-051-flight-003.eeprom +2010-03-06-serial-053-flight-004.eeprom +2010-05-08-serial-229-flight-002.eeprom +2010-05-28-serial-215-flight-002.eeprom +2010-05-28-serial-224-flight-001.eeprom +2010-05-29-serial-052-flight-005.eeprom +2010-05-30-serial-010-flight-005.eeprom +2010-05-30-serial-051-flight-004.eeprom +2010-05-30-serial-224-flight-003.eeprom +2010-05-30-serial-226-flight-001.eeprom +2010-05-31-serial-010-flight-006.eeprom +2010-05-31-serial-216-flight-001.eeprom +2010-05-31-serial-219-flight-001.eeprom +2010-05-31-serial-227-flight-003.eeprom +2010-06-05-serial-220-flight-001.eeprom +2010-06-26-serial-209-flight-003.eeprom +2010-06-26-serial-215-flight-004.eeprom +2010-06-26-serial-220-flight-002.eeprom +2010-06-26-serial-226-flight-002.eeprom +2010-06-27-serial-221-flight-002.eeprom +2010-07-17-serial-230-flight-001.eeprom +2010-07-18-serial-219-flight-002.eeprom +2010-08-07-serial-216-flight-003.eeprom +2010-08-07-serial-220-flight-003.eeprom +2010-08-12-serial-236-flight-001.eeprom +2010-08-21-serial-010-flight-007.eeprom +2010-08-21-serial-224-flight-004.eeprom +2010-08-21-serial-224-flight-005.eeprom +2010-08-21-serial-233-flight-002.eeprom +2010-09-03-serial-051-flight-005.eeprom +2010-09-03-serial-215-flight-005.eeprom +2010-09-24-serial-236-flight-006.eeprom +2010-09-25-serial-223-flight-001.eeprom +2010-10-17-serial-215-flight-006.eeprom +2010-10-23-serial-236-flight-008.eeprom +2011-01-30-serial-056-flight-001.eeprom +2011-01-30-serial-250-flight-002.eeprom +2011-02-19-serial-215-flight-007.eeprom +2011-02-19-serial-216-flight-006.eeprom +2011-02-19-serial-286-flight-001.eeprom -- cgit v1.2.3 From 7a4f6d5ad55637cde97a1e2f247f92df59bc2e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 21:01:15 -0700 Subject: altos: Write height values to log for nano/mini This is a lot more useful than the old filtered pressure data. Signed-off-by: Keith Packard --- src/ao.h | 7 +++++++ src/ao_log_tiny.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index fd8c6034..63f80678 100644 --- a/src/ao.h +++ b/src/ao.h @@ -706,6 +706,13 @@ extern __pdata int16_t ao_ground_accel; extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; +#ifdef USE_KALMAN +extern __pdata int16_t ao_ground_height; +extern __pdata int32_t ao_k_max_height; +extern __pdata int32_t ao_k_height; +extern __pdata int32_t ao_k_speed; +extern __pdata int32_t ao_k_accel; +#endif /* Flight thread */ void diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 157073d4..fad2a242 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -69,7 +69,7 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_flight_pres); // XXX change to alt + ao_log_tiny_data(ao_k_height >> 16); time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) -- cgit v1.2.3 From 1aeb759c48f475ffaaae787515e080440c8386c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 12:28:08 -0700 Subject: altos: Baro-only boards must not detect launch on accel or speed data The baro sensor generates too much noise to use small changes in computed speed or acceleration to cause a false launch detect. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/ao_flight.c b/src/ao_flight.c index e8130baa..71dd4891 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -488,9 +488,20 @@ ao_flight(void) * transition is detected */ #if USE_KALMAN +#if HAS_ACCEL + /* + * With an accelerometer, either to detect launch + */ if ((ao_k_accel > to_fix32(20) && ao_k_speed > to_fix32(5)) || ao_k_height > to_fix32(20)) +#else + /* + * Without an accelerometer, the barometer is far too + * noisy to rely on speed or acceleration data + */ + if (ao_k_height > to_fix32(20)) +#endif #else if ( #if HAS_ACCEL -- cgit v1.2.3 From e980b251e5a4d25410710a9aa89ef940e06b0d93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 18:43:52 -0700 Subject: altosui: Add software version to Configure AltosUI dialog Show this somewhere so we can figure out what is installed. Signed-off-by: Keith Packard --- altosui/AltosConfigureUI.java | 27 +++++++++++++++++---------- altosui/AltosVersion.java.in | 22 ++++++++++++++++++++++ altosui/Makefile.am | 1 + configure.ac | 1 + 4 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 altosui/AltosVersion.java.in diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index ab3d950e..9a292c91 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -87,9 +87,16 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.CENTER; pane.add(new JLabel ("Configure AltOS UI"), c); - /* Voice settings */ c.gridx = 0; c.gridy = 1; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + pane.add(new JLabel (String.format("AltOS version %s", AltosVersion.version)), c); + + /* Voice settings */ + c.gridx = 0; + c.gridy = 2; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -108,7 +115,7 @@ public class AltosConfigureUI } }); c.gridx = 1; - c.gridy = 1; + c.gridy = 2; c.gridwidth = 1; c.weightx = 1; c.fill = GridBagConstraints.NONE; @@ -116,7 +123,7 @@ public class AltosConfigureUI pane.add(enable_voice, c); c.gridx = 2; - c.gridy = 1; + c.gridy = 2; c.gridwidth = 1; c.weightx = 1; c.fill = GridBagConstraints.NONE; @@ -131,7 +138,7 @@ public class AltosConfigureUI /* Log directory settings */ c.gridx = 0; - c.gridy = 2; + c.gridy = 3; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -145,7 +152,7 @@ public class AltosConfigureUI } }); c.gridx = 1; - c.gridy = 2; + c.gridy = 3; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; @@ -153,7 +160,7 @@ public class AltosConfigureUI /* Callsign setting */ c.gridx = 0; - c.gridy = 3; + c.gridy = 4; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -162,7 +169,7 @@ public class AltosConfigureUI callsign_value = new JTextField(AltosPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); c.gridx = 1; - c.gridy = 3; + c.gridy = 4; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; @@ -170,7 +177,7 @@ public class AltosConfigureUI /* Serial debug setting */ c.gridx = 0; - c.gridy = 4; + c.gridy = 5; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -186,7 +193,7 @@ public class AltosConfigureUI }); c.gridx = 1; - c.gridy = 4; + c.gridy = 5; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -200,7 +207,7 @@ public class AltosConfigureUI } }); c.gridx = 0; - c.gridy = 5; + c.gridy = 6; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; diff --git a/altosui/AltosVersion.java.in b/altosui/AltosVersion.java.in new file mode 100644 index 00000000..b0b3c0cf --- /dev/null +++ b/altosui/AltosVersion.java.in @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosVersion { + public final static String version = "@VERSION@"; +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 133afbe8..288fca0e 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -85,6 +85,7 @@ altosui_JAVA = \ AltosGraphTime.java \ AltosGraphUI.java \ AltosDataChooser.java \ + AltosVersion.java \ AltosVoice.java JFREECHART_CLASS= \ diff --git a/configure.ac b/configure.ac index e27cf81f..83cf9987 100644 --- a/configure.ac +++ b/configure.ac @@ -134,6 +134,7 @@ PKG_CHECK_MODULES([SNDFILE], [sndfile]) AC_OUTPUT([ Makefile altosui/Makefile +altosui/AltosVersion.java altosui/libaltos/Makefile ao-tools/Makefile ao-tools/lib/Makefile -- cgit v1.2.3 From 5c28b9312d90a3a66016abc641c20bcd852d69f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:27:15 -0700 Subject: altos: Don't init packet slave on TD. Make slave start optional Oops. TeleDongle was starting the packet slave code, which kinda wrecked its ability to receive telemetry packets. This patch simply removes the packet slave code from teledongle as it cannot be used (yet), it also makes the packet slave code initialization take a parameter which controls whether to start that by default; in the future, perhaps TeleDongle will gain a command to start packet slave mode. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_packet_slave.c | 5 +++-- src/ao_teledongle.c | 1 - src/ao_telemetrum.c | 2 +- src/ao_telemini.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ao.h b/src/ao.h index 63f80678..00c395d6 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1197,6 +1197,6 @@ void ao_packet_slave_stop(void); void -ao_packet_slave_init(void); +ao_packet_slave_init(uint8_t enable); #endif /* _AO_H_ */ diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index eb456dab..e40ddfec 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -58,10 +58,11 @@ ao_packet_slave_stop(void) } void -ao_packet_slave_init(void) +ao_packet_slave_init(uint8_t enable) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); - ao_packet_slave_start(); + if (enable) + ao_packet_slave_start(); } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 505dc0cb..008b200a 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -31,7 +31,6 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_packet_slave_init(); ao_packet_master_init(); #if HAS_DBG ao_dbg_init(); diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index ed43c447..4ace415c 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -59,7 +59,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(); + ao_packet_slave_init(TRUE); ao_igniter_init(); #if HAS_DBG ao_dbg_init(); diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 97bc2cf4..dbc3b74c 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -42,9 +42,9 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); - ao_telemetry_init(); + ao_telemetry_tiny_init(); ao_radio_init(); - ao_packet_slave_init(); + ao_packet_slave_init(TRUE); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 3f0bc801fd08a613c681504f0d1f9374486a2487 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:31:20 -0700 Subject: altos: Configure packet size from send/recv parameters. Instead of setting the packet size at configuration time, use the provided packet size to the send/recv functions to configure the radio. This eliminates many configuration calls, leaving us with 'RDF' mode and 'packet' mode, the latter working for telemetry and the bi-directional link. Signed-off-by: Keith Packard --- src/ao.h | 10 ++-------- src/ao_packet_master.c | 2 -- src/ao_packet_slave.c | 4 ---- src/ao_radio.c | 29 ++++++++++++++--------------- 4 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/ao.h b/src/ao.h index 00c395d6..e076831d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -962,18 +962,12 @@ void ao_radio_general_isr(void) __interrupt 16; void -ao_radio_get(void); +ao_radio_get(uint8_t len); #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void -ao_radio_set_fixed_pkt(size_t size); - -#define ao_radio_set_telemetry() \ - ao_radio_set_fixed_pkt(sizeof (struct ao_telemetry)) - -#define ao_radio_set_packet() \ - ao_radio_set_fixed_pkt(sizeof (struct ao_packet)) +ao_radio_set_packet(void); void ao_radio_send(__xdata void *data, uint8_t size) __reentrant; diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5c4ab0dd..069bc5df 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -75,7 +75,6 @@ void ao_packet_master(void) { ao_config_get(); - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; ao_packet_master_time = ao_time(); @@ -99,7 +98,6 @@ ao_packet_master(void) ao_packet_master_sleeping = 0; } } - ao_radio_set_telemetry(); ao_exit(); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e40ddfec..9f14052a 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,7 +20,6 @@ void ao_packet_slave(void) { - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { @@ -51,9 +50,6 @@ ao_packet_slave_stop(void) ao_radio_recv_abort(); ao_delay(AO_MS_TO_TICKS(10)); } - ao_radio_get(); - ao_radio_set_telemetry(); - ao_radio_put(); } } diff --git a/src/ao_radio.c b/src/ao_radio.c index d7c00213..b5a67b99 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -264,12 +264,11 @@ ao_radio_general_isr(void) __interrupt 16 } void -ao_radio_set_fixed_pkt(size_t size) +ao_radio_set_packet(void) { uint8_t i; for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; - RF[RF_PKTLEN_OFF] = size; } void @@ -285,7 +284,7 @@ ao_radio_idle(void) } void -ao_radio_get(void) +ao_radio_get(uint8_t len) { ao_config_get(); ao_mutex_get(&ao_radio_mutex); @@ -294,13 +293,14 @@ ao_radio_get(void) RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_cal); + RF_PKTLEN = len; } void ao_radio_send(__xdata void *packet, uint8_t size) __reentrant { - ao_radio_get(); + ao_radio_get(size); ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, packet, @@ -323,7 +323,7 @@ uint8_t ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant { ao_radio_abort = 0; - ao_radio_get(); + ao_radio_get(size - 2); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, packet, @@ -375,12 +375,6 @@ ao_radio_rdf(int ms) uint8_t i; uint8_t pkt_len; - ao_radio_abort = 0; - ao_radio_get(); - ao_radio_done = 0; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; - /* * Compute the packet length as follows: * @@ -391,7 +385,12 @@ ao_radio_rdf(int ms) if (ms > (255 * 4)) ms = 255 * 4; pkt_len = ms >> 2; - RF[RF_PKTLEN_OFF] = pkt_len; + + ao_radio_abort = 0; + ao_radio_get(pkt_len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; ao_dma_set_transfer(ao_radio_dma, &ao_radio_rdf_value, @@ -411,7 +410,7 @@ ao_radio_rdf(int ms) ao_dma_abort(ao_radio_dma); ao_radio_idle(); } - ao_radio_set_telemetry(); + ao_radio_set_packet(); ao_radio_put(); } @@ -438,7 +437,7 @@ ao_radio_test(void) if ((mode & 2) && !radio_on) { ao_set_monitor(0); ao_packet_slave_stop(); - ao_radio_get(); + ao_radio_get(0xff); RFST = RFST_STX; radio_on = 1; } @@ -465,7 +464,7 @@ ao_radio_init(void) uint8_t i; for (i = 0; i < sizeof (radio_setup); i += 2) RF[radio_setup[i]] = radio_setup[i+1]; - ao_radio_set_telemetry(); + ao_radio_set_packet(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); RFIF = 0; -- cgit v1.2.3 From 5ba75e95c98d3e441a58d6f75d328d579e1997fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:41:44 -0700 Subject: altos: Make telemetry interval more consistent Instead of using a delay between telemetry packets, use a telemetry period and compute an appropriate delay each time. This requires changing the ascent telemetry from a 50ms delay to a 100ms interval, to provide a regular 10 packets-per-second rate. Before, we counted on the telemetry packet taking about 50ms to send so that we would receive about 10 per second. This also eliminates delays during descent for RDF tones -- those will get transmitted in the interval between telemetry packets without interrupting the spacing of those packets. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_telemetry.c | 48 ++++++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/src/ao.h b/src/ao.h index e076831d..075ec63a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -937,7 +937,7 @@ struct ao_telemetry_recv { /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) -#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(50) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) void diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index dd79f3fc..6556ce32 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -27,6 +27,8 @@ __xdata uint16_t ao_rdf_time; void ao_telemetry(void) { + uint16_t time; + int16_t delay; static __xdata struct ao_telemetry telemetry; ao_config_get(); @@ -37,35 +39,41 @@ ao_telemetry(void) telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; - ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); - telemetry.flight_state = ao_flight_state; + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + telemetry.flight_state = ao_flight_state; #if HAS_ACCEL - telemetry.flight_accel = ao_flight_accel; - telemetry.ground_accel = ao_ground_accel; - telemetry.flight_vel = ao_flight_vel; + telemetry.flight_accel = ao_flight_accel; + telemetry.ground_accel = ao_ground_accel; + telemetry.flight_vel = ao_flight_vel; #endif - telemetry.flight_pres = ao_flight_pres; - telemetry.ground_pres = ao_ground_pres; + telemetry.flight_pres = ao_flight_pres; + telemetry.ground_pres = ao_ground_pres; #if HAS_ADC - ao_adc_get(&telemetry.adc); + ao_adc_get(&telemetry.adc); #endif #if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); #endif - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_delay(ao_telemetry_interval); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - ao_delay(ao_telemetry_interval); + ao_radio_send(&telemetry, sizeof (telemetry)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); } } } -- cgit v1.2.3 From 8950df02382f5f0aea5bac078fdf7134b98c43ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:46:18 -0700 Subject: altos: Split out tiny telemetry from full telemetry The TeleMini and TeleNano boards do not have either GPS or accelermeters, and they also run the kalman filter which produces standard unit measurements for the flight height/speed/accel values. This makes the telemetry significantly different. ao_telemetry_tiny.c sends the required data. Note that TeleNano sends the same telemetry as telemini at this point; there are a couple of values which are not useful, but the overhead of sending them is small enough that the hassle of having three telemetry formats seemed excessive. Signed-off-by: Keith Packard --- src/Makefile.proto | 4 +-- src/ao.h | 21 ++++++++++++ src/ao_telemetry_tiny.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/ao_telemetry_tiny.c diff --git a/src/Makefile.proto b/src/Makefile.proto index df514cfe..eabd17b9 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -176,7 +176,7 @@ TMINI_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_tiny.c TMINI_MAIN_SRC = \ ao_telemini.c @@ -204,7 +204,7 @@ TNANO_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_tiny.c TNANO_MAIN_SRC = \ ao_telemini.c diff --git a/src/ao.h b/src/ao.h index 075ec63a..0ba98dbd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -925,6 +925,18 @@ struct ao_telemetry { struct ao_gps_tracking_data gps_tracking; }; +struct ao_telemetry_tiny { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t height; /* AGL in meters */ + int16_t speed; /* in m/s * 16 */ + int16_t accel; /* in m/s² * 16 */ + int16_t ground_pres; /* sensor units */ + struct ao_adc adc; /* raw ADC readings */ + char callsign[AO_MAX_CALLSIGN]; +}; + /* * ao_radio_recv tacks on rssi and status bytes */ @@ -934,6 +946,12 @@ struct ao_telemetry_recv { uint8_t status; }; +struct ao_telemetry_tiny_recv { + struct ao_telemetry_tiny telemetry_tiny; + int8_t rssi; + uint8_t status; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -949,6 +967,9 @@ ao_rdf_set(uint8_t rdf); void ao_telemetry_init(void); +void +ao_telemetry_tiny_init(void); + /* * ao_radio.c */ diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c new file mode 100644 index 00000000..83ba7fc0 --- /dev/null +++ b/src/ao_telemetry_tiny.c @@ -0,0 +1,91 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; +__xdata uint16_t ao_telemetry_tiny_interval = 0; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +void +ao_telemetry_tiny(void) +{ + uint16_t time; + int16_t delay; + static __xdata struct ao_telemetry_tiny telemetry_tiny; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + memcpy(telemetry_tiny.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + telemetry_tiny.serial = ao_serial_number; + telemetry_tiny.flight = ao_log_full() ? 0 : ao_flight_number; + for (;;) { + while (ao_telemetry_tiny_interval == 0) + ao_sleep(&ao_telemetry_tiny_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_tiny_interval) { + telemetry_tiny.flight_state = ao_flight_state; + telemetry_tiny.height = ao_k_height >> 16; + telemetry_tiny.speed = ao_k_speed >> 12; + telemetry_tiny.accel = ao_k_accel >> 12; + telemetry_tiny.ground_pres = ao_ground_pres; + ao_adc_get(&telemetry_tiny.adc); + ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_tiny_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_tiny_interval = interval; + ao_wakeup(&ao_telemetry_tiny_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_tiny_task; + +void +ao_telemetry_tiny_init() +{ + ao_add_task(&ao_telemetry_tiny_task, ao_telemetry_tiny, "telemetry_tiny"); +} -- cgit v1.2.3 From 31feb7777f73fed61193d3404f457ea1a081fe9c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:49:41 -0700 Subject: altos: Split telenano main from telemini Eventually, telenano will run different code; prepare for this by creating a telenano-specific main routine. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- src/ao_telenano.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/ao_telenano.c diff --git a/src/Makefile.proto b/src/Makefile.proto index eabd17b9..68fa4654 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,7 +207,7 @@ TNANO_TASK_SRC = \ ao_telemetry_tiny.c TNANO_MAIN_SRC = \ - ao_telemini.c + ao_telenano.c TNANO_BASE_SRC = \ $(ALTOS_SRC) \ diff --git a/src/ao_telenano.c b/src/ao_telenano.c new file mode 100644 index 00000000..dbc3b74c --- /dev/null +++ b/src/ao_telenano.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +/* stub so as telemini doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_tiny_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From ad6bb342d237988404fa32540b38c61d6ddc1f0d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:51:02 -0700 Subject: altos: The kalman code requires a constant sample rate The kalman function can't handle a variable sample rate, so keep the ADC running at full speed for the whole flight instead of slowing it down after apogee. Signed-off-by: Keith Packard --- src/ao_flight.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_flight.c b/src/ao_flight.c index 71dd4891..493913b2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -627,8 +627,10 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); +#if !USE_KALMAN /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); +#endif /* * Start recording min/max accel and pres for a while -- cgit v1.2.3 From be838db49d999426a9dd02c0166fe161722f1e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:53:08 -0700 Subject: altos: New telemetry report format (version 4). Supports tiny telemetry. This completely replaces the version 3 format with a much simpler and easier to parse scheme. It's described in detail in ao_telem.h, but the basic idea is that the whole line is split into name/value pairs, separated by whitespace. Every name is unique, and the values are either strings or integers. No extraneous formatting or units are provided. Signed-off-by: Keith Packard --- src/ao.h | 8 +- src/ao_gps_print.c | 145 +++++++++++++++------------------ src/ao_gps_sirf.c | 1 + src/ao_gps_test.c | 1 + src/ao_gps_test_skytraq.c | 1 + src/ao_monitor.c | 198 +++++++++++++++++++++++++++++++++++----------- src/ao_telem.h | 172 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 398 insertions(+), 128 deletions(-) create mode 100644 src/ao_telem.h diff --git a/src/ao.h b/src/ao.h index 0ba98dbd..527390b0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -841,6 +841,7 @@ ao_spi_init(void); #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) extern __xdata uint16_t ao_gps_tick; @@ -905,8 +906,7 @@ ao_gps_report_init(void); * ao_telemetry.c */ -#define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 3 +#define AO_MAX_CALLSIGN 8 struct ao_telemetry { uint16_t serial; @@ -1020,6 +1020,10 @@ extern const char const * const ao_state_names[]; void ao_monitor(void); +#define AO_MONITORING_OFF 0 +#define AO_MONITORING_FULL 1 +#define AO_MONITORING_TINY 2 + void ao_set_monitor(uint8_t monitoring); diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 11213174..ca071b42 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -18,86 +18,61 @@ #ifndef AO_GPS_TEST #include "ao.h" #endif - -struct ao_gps_split { - uint8_t positive; - uint8_t degrees; - uint8_t minutes; - uint16_t minutes_fraction; -}; - -static void -ao_gps_split(int32_t v, __xdata struct ao_gps_split *split) __reentrant -{ - uint32_t minutes_e7; - - split->positive = 1; - if (v < 0) { - v = -v; - split->positive = 0; - } - split->degrees = v / 10000000; - minutes_e7 = (v % 10000000) * 60; - split->minutes = minutes_e7 / 10000000; - split->minutes_fraction = (minutes_e7 % 10000000) / 1000; -} +#include "ao_telem.h" void ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant { - printf("GPS %2d sat", + char state; + + if (gps_data->flags & AO_GPS_VALID) + state = AO_TELEM_GPS_STATE_LOCKED; + else if (gps_data->flags & AO_GPS_RUNNING) + state = AO_TELEM_GPS_STATE_UNLOCKED; + else + state = AO_TELEM_GPS_STATE_ERROR; + printf(AO_TELEM_GPS_STATE " %c " + AO_TELEM_GPS_NUM_SAT " %d ", + state, (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); - if (gps_data->flags & AO_GPS_VALID) { - static __xdata struct ao_gps_split lat, lon; - int16_t climb, climb_int, climb_frac; + if (!(gps_data->flags & AO_GPS_VALID)) + return; + printf(AO_TELEM_GPS_LATITUDE " %ld " + AO_TELEM_GPS_LONGITUDE " %ld " + AO_TELEM_GPS_ALTITUDE " %d ", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); - ao_gps_split(gps_data->latitude, &lat); - ao_gps_split(gps_data->longitude, &lon); - if (gps_data->flags & AO_GPS_DATE_VALID) - printf(" 20%02d-%02d-%02d", - gps_data->year, - gps_data->month, - gps_data->day); - else - printf (" 0000-00-00"); - printf(" %2d:%02d:%02d", - gps_data->hour, - gps_data->minute, - gps_data->second); - printf(" %2d°%02d.%04d'%c %2d°%02d.%04d'%c %5dm", - lat.degrees, - lat.minutes, - lat.minutes_fraction, - lat.positive ? 'N' : 'S', - lon.degrees, - lon.minutes, - lon.minutes_fraction, - lon.positive ? 'E' : 'W', - gps_data->altitude); - climb = gps_data->climb_rate; - if (climb >= 0) { - climb_int = climb / 100; - climb_frac = climb % 100; - } else { - climb = -climb; - climb_int = -(climb / 100); - climb_frac = climb % 100; - } - printf(" %5u.%02dm/s(H) %d° %5d.%02dm/s(V)", - gps_data->ground_speed / 100, - gps_data->ground_speed % 100, - gps_data->course * 2, - climb / 100, - climb % 100); - printf(" %d.%d(hdop) %5u(herr) %5u(verr)", - gps_data->hdop / 5, - (gps_data->hdop * 2) % 10, + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(AO_TELEM_GPS_YEAR " %d " + AO_TELEM_GPS_MONTH " %d " + AO_TELEM_GPS_DAY " %d ", + gps_data->year, + gps_data->month, + gps_data->day); + + printf(AO_TELEM_GPS_HOUR " %d " + AO_TELEM_GPS_MINUTE " %d " + AO_TELEM_GPS_SECOND " %d ", + gps_data->hour, + gps_data->minute, + gps_data->second); + + printf(AO_TELEM_GPS_HDOP " %d ", + gps_data->hdop * 2); + + if (gps_data->flags & AO_GPS_COURSE_VALID) { + printf(AO_TELEM_GPS_HERROR " %d " + AO_TELEM_GPS_VERROR " %d " + AO_TELEM_GPS_VERTICAL_SPEED " %d " + AO_TELEM_GPS_HORIZONTAL_SPEED " %d " + AO_TELEM_GPS_COURSE " %d ", gps_data->h_error, - gps_data->v_error); - } else if (gps_data->flags & AO_GPS_RUNNING) { - printf(" unlocked"); - } else { - printf (" not-connected"); + gps_data->v_error, + gps_data->climb_rate, + gps_data->ground_speed, + (int) gps_data->course * 2); } } @@ -106,12 +81,11 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ { uint8_t c, n, v; __xdata struct ao_gps_sat_data *sat; - printf("SAT "); + n = gps_tracking_data->channels; - if (n == 0) { - printf("not-connected"); + if (n == 0) return; - } + sat = gps_tracking_data->sats; v = 0; for (c = 0; c < n; c++) { @@ -119,13 +93,20 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ v++; sat++; } - printf("%d ", v); + + printf (AO_TELEM_SAT_NUM " %d ", + v); + sat = gps_tracking_data->sats; + v = 0; for (c = 0; c < n; c++) { - if (sat->svid) - printf (" %3d %3d", - sat->svid, - sat->c_n_1); + if (sat->svid) { + printf (AO_TELEM_SAT_SVID "%d %d " + AO_TELEM_SAT_C_N_0 "%d %d ", + v, sat->svid, + v, sat->c_n_1); + v++; + } sat++; } } diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index a6167e6b..87b1d69c 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -405,6 +405,7 @@ ao_gps(void) __reentrant ao_gps_data.course = ao_sirf_data.course / 200; ao_gps_data.hdop = ao_sirf_data.hdop; ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + ao_gps_data.flags |= AO_GPS_COURSE_VALID; if (ao_sirf_data.h_error > 6553500) ao_gps_data.h_error = 65535; else diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index edb51304..44efb50c 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -28,6 +28,7 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) struct ao_gps_data { uint8_t year; diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 4010e09c..b94e9bd2 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -28,6 +28,7 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) struct ao_gps_data { uint8_t year; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 9c4be6fb..d6fd8305 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_telem.h" __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -23,54 +24,163 @@ __pdata uint8_t ao_monitor_led; void ao_monitor(void) { - __xdata struct ao_telemetry_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; + __xdata union { + struct ao_telemetry_recv full; + struct ao_telemetry_tiny_recv tiny; + } u; + +#define recv (u.full) +#define recv_tiny (u.tiny) + uint8_t state; int16_t rssi; for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (!ao_radio_recv(&recv, sizeof (recv))) - continue; - state = recv.telemetry.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv.rssi >> 1) - 74; - memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", - AO_TELEMETRY_VERSION, - callsign, - recv.telemetry.serial, - recv.telemetry.flight, - rssi, recv.status, - ao_state_names[state]); - printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " - "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", - recv.telemetry.adc.tick, - recv.telemetry.adc.accel, - recv.telemetry.adc.pres, - recv.telemetry.adc.temp, - recv.telemetry.adc.v_batt, - recv.telemetry.adc.sense_d, - recv.telemetry.adc.sense_m, - recv.telemetry.flight_accel, - recv.telemetry.ground_accel, - recv.telemetry.flight_vel, - recv.telemetry.flight_pres, - recv.telemetry.ground_pres, - recv.telemetry.accel_plus_g, - recv.telemetry.accel_minus_g); - ao_gps_print(&recv.telemetry.gps); - putchar(' '); - ao_gps_tracking_print(&recv.telemetry.gps_tracking); - putchar('\n'); - ao_rssi_set(rssi); + if (ao_monitoring == AO_MONITORING_FULL) { + if (!ao_radio_recv(&recv, sizeof (struct ao_telemetry_recv))) + continue; + + state = recv.telemetry.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv.rssi >> 1) - 74; + memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { + + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv.telemetry.serial, + recv.telemetry.flight, + rssi, + ao_state_names[state], + recv.telemetry.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_ACCEL " %d " + AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv.telemetry.adc.accel, + recv.telemetry.adc.pres, + recv.telemetry.adc.temp, + recv.telemetry.adc.v_batt, + recv.telemetry.adc.sense_d, + recv.telemetry.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_ACCEL_GROUND " %d " + AO_TELEM_CAL_BARO_GROUND " %d " + AO_TELEM_CAL_ACCEL_PLUS " %d " + AO_TELEM_CAL_ACCEL_MINUS " %d ", + recv.telemetry.ground_accel, + recv.telemetry.ground_pres, + recv.telemetry.accel_plus_g, + recv.telemetry.accel_minus_g); + +#if 0 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv.telemetry.height, + recv.telemetry.speed, + recv.telemetry.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv.telemetry.flight_accel, + recv.telemetry.flight_vel, + recv.telemetry.flight_pres); +#endif + ao_gps_print(&recv.telemetry.gps); + ao_gps_tracking_print(&recv.telemetry.gps_tracking); + putchar('\n'); + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } } else { - printf("CRC INVALID RSSI %3d\n", rssi); + if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) + continue; + + state = recv_tiny.telemetry_tiny.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; + memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_tiny.telemetry_tiny.serial, + recv_tiny.telemetry_tiny.flight, + rssi, + ao_state_names[state], + recv_tiny.telemetry_tiny.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_tiny.telemetry_tiny.adc.pres, + recv_tiny.telemetry_tiny.adc.temp, + recv_tiny.telemetry_tiny.adc.v_batt, + recv_tiny.telemetry_tiny.adc.sense_d, + recv_tiny.telemetry_tiny.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_BARO_GROUND " %d ", + recv_tiny.telemetry_tiny.ground_pres); + +#if 1 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d\n", + recv_tiny.telemetry_tiny.height, + recv_tiny.telemetry_tiny.speed, + recv_tiny.telemetry_tiny.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d\n", + recv_tiny.telemetry_tiny.flight_accel, + recv_tiny.telemetry_tiny.flight_vel, + recv_tiny.telemetry_tiny.flight_pres); +#endif + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } } ao_usb_flush(); ao_led_toggle(ao_monitor_led); @@ -82,21 +192,21 @@ __xdata struct ao_task ao_monitor_task; void ao_set_monitor(uint8_t monitoring) { + if (ao_monitoring) + ao_radio_recv_abort(); ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - if (!ao_monitoring) - ao_radio_recv_abort(); } static void set_monitor(void) { ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i != 0); + ao_set_monitor(ao_cmd_lex_i); } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 on>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, { 0, NULL }, }; diff --git a/src/ao_telem.h b/src/ao_telem.h new file mode 100644 index 00000000..b1624fe0 --- /dev/null +++ b/src/ao_telem.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEM_H_ +#define _AO_TELEM_H_ + +#define AO_TELEMETRY_VERSION 4 + +/* + * Telemetry version 4 and higher format: + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + +#define AO_TELEM_VERSION "VERSION" +#define AO_TELEM_CALL "c" +#define AO_TELEM_SERIAL "n" +#define AO_TELEM_FLIGHT "f" +#define AO_TELEM_RSSI "r" +#define AO_TELEM_STATE "s" +#define AO_TELEM_TICK "t" + +/* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + +#define AO_TELEM_RAW_ACCEL "r_a" +#define AO_TELEM_RAW_BARO "r_b" +#define AO_TELEM_RAW_THERMO "r_t" +#define AO_TELEM_RAW_BATT "r_v" +#define AO_TELEM_RAW_DROGUE "r_d" +#define AO_TELEM_RAW_MAIN "r_m" + +/* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + +#define AO_TELEM_CAL_ACCEL_GROUND "c_a" +#define AO_TELEM_CAL_BARO_GROUND "c_b" +#define AO_TELEM_CAL_ACCEL_PLUS "c_p" +#define AO_TELEM_CAL_ACCEL_MINUS "c_m" + +/* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + +#define AO_TELEM_KALMAN_HEIGHT "k_h" +#define AO_TELEM_KALMAN_SPEED "k_s" +#define AO_TELEM_KALMAN_ACCEL "k_a" + +/* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + +#define AO_TELEM_ADHOC_ACCEL "a_a" +#define AO_TELEM_ADHOC_SPEED "a_s" +#define AO_TELEM_ADHOC_BARO "a_b" + +/* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + +#define AO_TELEM_GPS_STATE "g_s" +#define AO_TELEM_GPS_STATE_LOCKED 'l' +#define AO_TELEM_GPS_STATE_UNLOCKED 'u' +#define AO_TELEM_GPS_STATE_ERROR 'e' +#define AO_TELEM_GPS_NUM_SAT "g_n" +#define AO_TELEM_GPS_LATITUDE "g_ns" +#define AO_TELEM_GPS_LONGITUDE "g_ew" +#define AO_TELEM_GPS_ALTITUDE "g_a" +#define AO_TELEM_GPS_YEAR "g_Y" +#define AO_TELEM_GPS_MONTH "g_M" +#define AO_TELEM_GPS_DAY "g_D" +#define AO_TELEM_GPS_HOUR "g_h" +#define AO_TELEM_GPS_MINUTE "g_m" +#define AO_TELEM_GPS_SECOND "g_s" +#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_s" +#define AO_TELEM_GPS_COURSE "g_c" +#define AO_TELEM_GPS_HDOP "g_hd" +#define AO_TELEM_GPS_VDOP "g_vd" +#define AO_TELEM_GPS_HERROR "g_he" +#define AO_TELEM_GPS_VERROR "g_ve" + +/* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + +#define AO_TELEM_SAT_NUM "s_n" +#define AO_TELEM_SAT_SVID "s_v" +#define AO_TELEM_SAT_C_N_0 "s_c" + +#endif /* _AO_TELEM_H_ */ -- cgit v1.2.3 From ca3f03ef5c09446bebf0f5734f36a0248c457b1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:55:39 -0700 Subject: altos: Add .sdcdbrc file for teledongle My sdcdb script uses this to set command line options automatically Signed-off-by: Keith Packard --- src/teledongle-v0.2/.sdcdbrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/teledongle-v0.2/.sdcdbrc diff --git a/src/teledongle-v0.2/.sdcdbrc b/src/teledongle-v0.2/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. -- cgit v1.2.3 From 20427ae4965f756aac0cedc5179a1c45b9a781f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Mar 2011 19:59:27 +0900 Subject: altos: Add nickle kalman implementation. This generates the constants needed to implement Kalman filtering in the flight firmware. Signed-off-by: Keith Packard --- src/Makefile.proto | 9 + src/kalman/kalman.5c | 493 ++++++++++++++++++++++++++++++++++++++++++++ src/kalman/kalman_filter.5c | 308 +++++++++++++++++++++++++++ src/kalman/load_csv.5c | 63 ++++++ src/kalman/matrix.5c | 157 ++++++++++++++ src/kalman/plotaccel | 18 ++ src/kalman/plotkalman | 24 +++ src/make-kalman | 18 ++ 8 files changed, 1090 insertions(+) create mode 100755 src/kalman/kalman.5c create mode 100644 src/kalman/kalman_filter.5c create mode 100644 src/kalman/load_csv.5c create mode 100644 src/kalman/matrix.5c create mode 100644 src/kalman/plotaccel create mode 100755 src/kalman/plotkalman create mode 100644 src/make-kalman diff --git a/src/Makefile.proto b/src/Makefile.proto index 68fa4654..85c0c46e 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -5,6 +5,11 @@ vpath %.c .. vpath %.h .. vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman vpath ao-make-product.5c .. CC=sdcc @@ -25,6 +30,7 @@ INC = \ ao_pins.h \ cc1111.h \ altitude.h \ + ao_kalman.h \ 25lc1024.h # @@ -307,6 +313,9 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ +../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< > $@ + ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c new file mode 100755 index 00000000..f7347184 --- /dev/null +++ b/src/kalman/kalman.5c @@ -0,0 +1,493 @@ +#!/usr/bin/env nickle + +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +autoimport ParseArgs; + +load "load_csv.5c" +import load_csv; + +load "matrix.5c" +import matrix; + +load "kalman_filter.5c" +import kalman; + +/* + * AltOS keeps speed and accel scaled + * by 4 bits to provide additional precision + */ +real height_scale = 1.0; +real accel_scale = 16.0; +real speed_scale = 16.0; + +/* + * State: + * + * x[0] = height + * x[1] = velocity + * x[2] = acceleration + */ + +/* + * Measurement + * + * z[0] = height + * z[1] = acceleration + */ + +real default_σ_m = 5; +real default_σ_h = 20; +real default_σ_a = 2; + +parameters_t param_both(real t, real σ_m, real σ_h, real σ_a) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_h == 0) + σ_h = default_σ_h; + if (σ_a == 0) + σ_a = default_σ_a; + + σ_m = imprecise(σ_m) * accel_scale; + σ_h = imprecise(σ_h) * height_scale; + σ_a = imprecise(σ_a) * accel_scale; + + t = imprecise(t); + + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, + t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[2,2]) { + { σ_h ** 2, 0 }, + { 0, σ_a ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the height and acceleration + * values. + */ + .h = (real[2,3]) { + { 1, 0, 0 }, + { 0, 0, 1 }, + }, + }; +} + +parameters_t param_baro(real t, real σ_m, real σ_h) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_h == 0) + σ_h = default_σ_h; + + σ_m = imprecise(σ_m) * accel_scale; + σ_h = imprecise(σ_h) * height_scale; + + t = imprecise(t); + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_h ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the height + * values. + */ + .h = (real[1,3]) { + { 1, 0, 0 }, + }, + }; +} + +parameters_t param_accel(real t, real σ_m, real σ_a) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_a == 0) + σ_a = default_σ_a; + + σ_m = imprecise(σ_m) * accel_scale; + σ_a = imprecise(σ_a) * accel_scale; + + t = imprecise(t); + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_a ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the acceleration + * values. + */ + .h = (real[1,3]) { + { 0, 0, 1 }, + }, + }; +} + +parameters_t param_vel(real t) { + static real σ_m = .1; + static real σ_v = imprecise(10); + + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, imprecise(t), imprecise((t**2)/2) }, + { 0, 1, imprecise(t) }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_v ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the velocity + * values. + */ + .h = (real[1,3]) { + { 0, 1, 0 }, + }, + }; +} + +real max_baro_height = 18000; + +bool just_kalman = true; +real accel_input_scale = 1; + +void run_flight(string name, file f, bool summary) { + state_t current_both = { + .x = (real[3]) { 0, 0, 0 }, + .p = (real[3,3]) { { 0 ... } ... }, + }; + state_t current_accel = current_both; + state_t current_baro = current_both; + real t; + real kalman_apogee_time = -1; + real kalman_apogee = 0; + real raw_apogee_time_first; + real raw_apogee_time_last; + real raw_apogee = 0; + real default_descent_rate = 20; + real speed = 0; + real prev_acceleration = 0; + state_t apogee_state; + parameters_fast_t fast_both; + parameters_fast_t fast_baro; + parameters_fast_t fast_accel; + real fast_delta_t = 0; + bool fast = true; + + for (;;) { + record_t record = parse_record(f, accel_input_scale); + if (record.done) + break; + if (is_uninit(&t)) + t = record.time; + real delta_t = record.time - t; + if (delta_t <= 0) + continue; + t = record.time; + if (record.height > raw_apogee) { + raw_apogee_time_first = record.time; + raw_apogee = record.height; + } + if (record.height == raw_apogee) + raw_apogee_time_last = record.time; + + real acceleration = record.acceleration; + real height = record.height; + + speed = (speed + (acceleration + prev_acceleration / 2) * delta_t); + prev_acceleration = acceleration; + + vec_t z_both = (real[2]) { record.height * height_scale, record.acceleration * accel_scale }; + vec_t z_accel = (real[1]) { record.acceleration * accel_scale }; + vec_t z_baro = (real[1]) { record.height * height_scale }; + + + if (fast) { + if (delta_t != fast_delta_t) { + fast_both = convert_to_fast(param_both(delta_t, 0, 0, 0)); + fast_accel = convert_to_fast(param_accel(delta_t, 0, 0)); + fast_baro = convert_to_fast(param_baro(delta_t, 0, 0)); + fast_delta_t = delta_t; + } + + current_both.x = predict_fast(current_both.x, fast_both); + current_accel.x = predict_fast(current_accel.x, fast_accel); + current_baro.x = predict_fast(current_baro.x, fast_baro); + + current_both.x = correct_fast(current_both.x, z_both, fast_both); + current_accel.x = correct_fast(current_accel.x, z_accel, fast_accel); + current_baro.x = correct_fast(current_baro.x, z_baro, fast_baro); + } else { + parameters_t p_both = param_both(delta_t, 0, 0, 0); + parameters_t p_accel = param_accel(delta_t, 0, 0); + parameters_t p_baro = param_baro(delta_t, 0, 0); + + state_t pred_both = predict(current_both, p_both); + state_t pred_accel = predict(current_accel, p_accel); + state_t pred_baro = predict(current_baro, p_baro); + + state_t next_both = correct(pred_both, z_both, p_both); + state_t next_accel = correct(pred_accel, z_accel, p_accel); + state_t next_baro = correct(pred_baro, z_baro, p_baro); + current_both = next_both; + current_accel = next_accel; + current_baro = next_baro; + } + + printf ("%16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f\n", + record.time, + record.height, speed, record.acceleration, + current_both.x[0] / height_scale, current_both.x[1] / speed_scale, current_both.x[2] / accel_scale, + current_accel.x[0] / height_scale, current_accel.x[1] / speed_scale, current_accel.x[2] / accel_scale, + current_baro.x[0] / height_scale, current_baro.x[1] / speed_scale, current_baro.x[2] / accel_scale); + if (kalman_apogee_time < 0) { + if (current_both.x[1] < -1 && current_accel.x[1] < -1 && current_baro.x[1] < -1) { + kalman_apogee = current_both.x[0]; + kalman_apogee_time = record.time; + break; + } + } + } + real raw_apogee_time = (raw_apogee_time_last + raw_apogee_time_first) / 2; + if (summary && !just_kalman) { + printf("%s: kalman (%8.2f m %6.2f s) raw (%8.2f m %6.2f s) error %6.2f s\n", + name, + kalman_apogee, kalman_apogee_time, + raw_apogee, raw_apogee_time, + kalman_apogee_time - raw_apogee_time); + } +} + +void main() { + bool summary = false; + int user_argind = 1; + real time_step = 0.01; + string compute = "none"; + string prefix = "AO_K"; + real σ_m = 1; + real σ_h = 4; + real σ_a = 1; + + ParseArgs::argdesc argd = { + .args = { + { .var = { .arg_flag = &summary }, + .abbr = 's', + .name = "summary", + .desc = "Print a summary of the flight" }, + { .var = { .arg_real = &max_baro_height }, + .abbr = 'm', + .name = "maxbaro", + .expr_name = "height", + .desc = "Set maximum usable barometer height" }, + { .var = { .arg_real = &accel_input_scale, }, + .abbr = 'a', + .name = "accel", + .expr_name = "", + .desc = "Set accelerometer scale factor" }, + { .var = { .arg_real = &time_step, }, + .abbr = 't', + .name = "time", + .expr_name = "", + .desc = "Set time step for convergence" }, + { .var = { .arg_string = &prefix }, + .abbr = 'p', + .name = "prefix", + .expr_name = "", + .desc = "Prefix for compute output" }, + { .var = { .arg_string = &compute }, + .abbr = 'c', + .name = "compute", + .expr_name = "{both,baro,accel}", + .desc = "Compute Kalman factor through convergence" }, + { .var = { .arg_real = &σ_m }, + .abbr = 'M', + .name = "model", + .expr_name = "", + .desc = "Model co-variance for acceleration" }, + { .var = { .arg_real = &σ_h }, + .abbr = 'H', + .name = "height", + .expr_name = "", + .desc = "Measure co-variance for height" }, + { .var = { .arg_real = &σ_a }, + .abbr = 'A', + .name = "accel", + .expr_name = "", + .desc = "Measure co-variance for acceleration" }, + }, + + .unknown = &user_argind, + }; + + ParseArgs::parseargs(&argd, &argv); + + if (compute != "none") { + parameters_t param; + + printf ("/* Kalman matrix for %s\n", compute); + printf (" * step = %f\n", time_step); + printf (" * σ_m = %f\n", σ_m); + switch (compute) { + case "both": + printf (" * σ_h = %f\n", σ_h); + printf (" * σ_a = %f\n", σ_a); + param = param_both(time_step, σ_m, σ_h, σ_a); + break; + case "accel": + printf (" * σ_a = %f\n", σ_a); + param = param_accel(time_step, σ_m, σ_a); + break; + case "baro": + printf (" * σ_h = %f\n", σ_h); + param = param_baro(time_step, σ_m, σ_h); + break; + } + printf (" */\n\n"); + mat_t k = converge(param); + int[] d = dims(k); + int time_inc = floor(1/time_step + 0.5); + if (d[1] == 2) { + for (int i = 0; i < d[0]; i++) + for (int j = 0; j < d[1]; j++) + printf ("#define %s_K%d%d_%d to_fix16(%12.10f)\n", + prefix, i, j, time_inc, k[i,j]); + } else { + for (int i = 0; i < d[0]; i++) { + printf ("#define %s_K%d_%d to_fix16(%12.10f)\n", + prefix, i, time_inc, k[i,0]); + } + } + printf ("\n"); + return; + } + string[dim(argv) - user_argind] rest = { [i] = argv[i+user_argind] }; + + # height_scale = accel_scale = speed_scale = 1; + + if (dim(rest) == 0) + run_flight("", stdin, summary); + else { + for (int i = 0; i < dim(rest); i++) { + twixt(file f = File::open(rest[i], "r"); File::close(f)) { + run_flight(rest[i], f, summary); + } + } + } +} +main(); +#kalman(stdin); +#dump(stdin); diff --git a/src/kalman/kalman_filter.5c b/src/kalman/kalman_filter.5c new file mode 100644 index 00000000..efbbf1ab --- /dev/null +++ b/src/kalman/kalman_filter.5c @@ -0,0 +1,308 @@ +load "matrix.5c" + +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +namespace kalman { + + import matrix; + + public typedef struct { + vec_t x; /* state */ + mat_t p; /* error estimate */ + mat_t k; /* kalman factor */ + } state_t; + + public typedef struct { + mat_t a; /* model */ + mat_t q; /* model error covariance */ + mat_t r; /* measurement error covariance */ + mat_t h; /* measurement from model */ + } parameters_t; + + public typedef struct { + mat_t a; /* model */ + mat_t k; /* kalman coefficient */ + mat_t h; /* measurement from model */ + } parameters_fast_t; + + vec_t measurement_from_state(vec_t x, mat_t h) { + return multiply_mat_vec(h, x); + } + + + void print_state(string name, state_t s) { + print_vec(sprintf("%s state", name), s.x); + print_mat(sprintf("%s error", name), s.p); + } + + public bool debug = false; + + public state_t predict (state_t s, parameters_t p) { + state_t n; + + if (debug) { + printf ("--------PREDICT--------\n"); + print_state("current", s); + } + + /* Predict state + * + * x': predicted state + * a: model + * x: previous state + * + * x' = a * x; + */ + + n.x = multiply_mat_vec(p.a, s.x); + + /* t0 = a * p */ + mat_t t0 = multiply (p.a, s.p); + if (debug) + print_mat("t0", t0); + + /* t1 = a * p * transpose(a) */ + + mat_t t1 = multiply (t0, transpose(p.a)); + + /* Predict error + * + * p': predicted error + * a: model + * p: previous error + * q: model error + * + * p' = a * p * transpose(a) + q + */ + + n.p = add(t1, p.q); + if (debug) + print_state("predict", n); + return n; + } + + public vec_t predict_fast(vec_t x, parameters_fast_t p) { + if (debug) { + printf ("--------FAST PREDICT--------\n"); + print_vec("current", x); + } + vec_t new = multiply_mat_vec(p.a, x); + if (debug) + print_vec("predict", new); + return new; + } + + public vec_t correct_fast(vec_t x, vec_t z, parameters_fast_t p) { + if (debug) { + printf ("--------FAST CORRECT--------\n"); + print_vec("measure", z); + print_vec("current", x); + } + vec_t model = multiply_mat_vec(p.h, x); + if (debug) + print_vec("extract model", model); + vec_t diff = vec_subtract(z, model); + if (debug) + print_vec("difference", diff); + vec_t adjust = multiply_mat_vec(p.k, diff); + if (debug) + print_vec("adjust", adjust); + + vec_t new = vec_add(x, + multiply_mat_vec(p.k, + vec_subtract(z, + multiply_mat_vec(p.h, x)))); + if (debug) + print_vec("correct", new); + return new; + } + + public state_t correct(state_t s, vec_t z, parameters_t p) { + state_t n; + + if (debug) { + printf ("--------CORRECT--------\n"); + print_vec("measure", z); + print_state("current", s); + } + + /* t0 = p * T(h) */ + + /* 3x2 = 3x3 * 3x2 */ + mat_t t0 = multiply(s.p, transpose(p.h)); + if (debug) + print_mat("t0", t0); + + /* t1 = h * p */ + + /* 2x3 = 2x3 * 3x3 */ + mat_t t1 = multiply(p.h, s.p); + if (debug) + print_mat("t1", t1); + + /* t2 = h * p * transpose(h) */ + + /* 2x2 = 2x3 * 3x2 */ + mat_t t2 = multiply(t1, transpose(p.h)); + if (debug) + print_mat("t2", t2); + + /* t3 = h * p * transpose(h) + r */ + + /* 2x2 = 2x2 + 2x2 */ + mat_t t3 = add(t2, p.r); + if (debug) + print_mat("t3", t3); + + /* t4 = inverse(h * p * transpose(h) + r) */ + + /* 2x2 = 2x2 */ + mat_t t4 = inverse(t3); + if (debug) + print_mat("t4", t4); + + /* Kalman value */ + + /* k: Kalman value + * p: error estimate + * h: state to measurement matrix + * r: measurement error covariance + * + * k = p * transpose(h) * inverse(h * p * transpose(h) + r) + * + * k = K(p) + */ + + /* 3x2 = 3x2 * 2x2 */ + mat_t k = multiply(t0, t4); + if (debug) + print_mat("k", k); + n.k = k; + + /* t5 = h * x */ + + /* 2 = 2x3 * 3 */ + vec_t t5 = multiply_mat_vec(p.h, s.x); + if (debug) + print_vec("t5", t5); + + /* t6 = z - h * x */ + + /* 2 = 2 - 2 */ + vec_t t6 = vec_subtract(z, t5); + if (debug) + print_vec("t6", t6); + + /* t7 = k * (z - h * x) */ + + /* 3 = 3x2 * 2 */ + vec_t t7 = multiply_mat_vec(k, t6); + if (debug) + print_vec("t7", t7); + + /* Correct state + * + * x: predicted state + * k: kalman value + * z: measurement + * h: state to measurement matrix + * x': corrected state + * + * x' = x + k * (z - h * x) + */ + + n.x = vec_add(s.x, t7); + if (debug) + print_vec("n->x", n.x); + + /* t8 = k * h */ + + /* 3x3 = 3x2 * 2x3 */ + mat_t t8 = multiply(k, p.h); + if (debug) + print_mat("t8", t8); + + /* t9 = 1 - k * h */ + + /* 3x3 = 3x3 - 3x3 */ + mat_t t9 = subtract(identity(dim(s.x)), t8); + if (debug) + print_mat("t9", t9); + + /* Correct error + * + * p: predicted error + * k: kalman value + * h: state to measurement matrix + * p': corrected error + * + * p' = (1 - k * h) * p + * + * p' = P(k,p) + */ + + /* 3x3 = 3x3 * 3x3 */ + n.p = multiply(t9, s.p); + if (debug) { + print_mat("n->p", n.p); +# print_state("correct", n); + } + return n; + } + + real distance(mat_t a, mat_t b) { + int[2] d = dims(a); + int i_max = d[0]; + int j_max = d[1]; + real s = 0; + + for (int i = 0; i < i_max; i++) + for (int j = 0; j < j_max; j++) + s += (a[i,j] - b[i,j]) ** 2; + return sqrt(s); + } + + public mat_t converge(parameters_t p) { + int model = dims(p.a)[0]; + int measure = dims(p.r)[0]; + int reps = 0; + state_t s = { + .x = (real[model]) { 0 ... }, + .p = (real[model,model]) { { 0 ... } ... }, + .k = (real[model,measure]) { { 0 ... } ... } + }; + + vec_t z = (real [measure]) { 0 ... }; + for (;;) { + state_t s_pre = predict(s, p); + state_t s_post = correct(s_pre, z, p); + real d = distance(s.k, s_post.k); + s = s_post; + reps++; + if (d < 1e-10 && reps > 10) + break; + } + return s.k; + } + + public parameters_fast_t convert_to_fast(parameters_t p) { + return (parameters_fast_t) { + .a = p.a, .k = converge(p), .h = p.h + }; + } +} diff --git a/src/kalman/load_csv.5c b/src/kalman/load_csv.5c new file mode 100644 index 00000000..15e83166 --- /dev/null +++ b/src/kalman/load_csv.5c @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +namespace load_csv { + string[*] parse_data(file f) { + while (!File::end(f)) { + string l = File::fgets(f); + if (l[0] == '#') + continue; + return String::parse_csv(l); + } + return (string[0]) {}; + } + + public typedef struct { + bool done; + real time; + real height; + real acceleration; + } record_t; + + public record_t parse_record(file f, real accel_scale) { + string[*] data = parse_data(f); + if (dim(data) == 0) + return (record_t) { .done = true }; + int time_off = 4; + int height_off = 11; + int accel_off = 8; + if (string_to_integer(data[0]) == 2) { + time_off = 4; + accel_off = 9; + height_off = 12; + } + return (record_t) { + .done = false, + .time = string_to_real(data[time_off]), + .height = imprecise(string_to_real(data[height_off])), + .acceleration = imprecise(string_to_real(data[accel_off]) * accel_scale) }; + } + + public void dump(file f) { + for (;;) { + record_t r = parse_record(f, 1); + if (r.done) + break; + printf ("%f %f %f\n", r.time, r.height, r.acceleration); + } + } +} diff --git a/src/kalman/matrix.5c b/src/kalman/matrix.5c new file mode 100644 index 00000000..667648f5 --- /dev/null +++ b/src/kalman/matrix.5c @@ -0,0 +1,157 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +namespace matrix { + public typedef real[*] vec_t; + public typedef real[*,*] mat_t; + + public mat_t transpose(mat_t m) { + int[2] d = dims(m); + return (real[d[1],d[0]]) { [i,j] = m[j,i] }; + } + + public void print_mat(string name, mat_t m) { + int[2] d = dims(m); + printf ("%s {\n", name); + for (int y = 0; y < d[0]; y++) { + for (int x = 0; x < d[1]; x++) + printf (" %14.8f", m[y,x]); + printf ("\n"); + } + printf ("}\n"); + } + + public void print_vec(string name, vec_t v) { + int d = dim(v); + printf ("%s {", name); + for (int x = 0; x < d; x++) + printf (" %14.8f", v[x]); + printf (" }\n"); + } + + public mat_t multiply(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[1] == db[0], "invalid matrix dimensions"); + + real dot(int rx, int ry) { + real r = 0.0; + for (int i = 0; i < da[1]; i++) + r += a[ry, i] * b[i, rx]; + return imprecise(r); + } + + mat_t r = (real[da[0], db[1]]) { [ry,rx] = dot(rx,ry) }; + return r; + } + + public mat_t multiply_mat_val(mat_t m, real value) { + int[2] d = dims(m); + for (int j = 0; j < d[1]; j++) + for (int i = 0; i < d[0]; i++) + m[i,j] *= value; + return m; + } + + public mat_t add(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[0] == db[0] && da[1] == db[1], "mismatching dim in plus"); + return (real[da[0], da[1]]) { [y,x] = a[y,x] + b[y,x] }; + } + + public mat_t subtract(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[0] == db[0] && da[1] == db[1], "mismatching dim in minus"); + return (real[da[0], da[1]]) { [y,x] = a[y,x] - b[y,x] }; + } + + public mat_t inverse(mat_t m) { + int[2] d = dims(m); + + real[1,1] inverse_1(real[1,1] m) { + return (real[1,1]) { { 1/m[0,0] } }; + } + + if (d[0] == 1 && d[1] == 1) + return inverse_1(m); + + real[2,2] inverse_2(real[2,2] m) { + real a = m[0,0], b = m[0,1]; + real c = m[1,0], d = m[1,1]; + real det = a * d - b * c; + return multiply_mat_val((real[2,2]) { + { d, -b }, { -c, a } }, 1/det); + } + + if (d[0] == 2 && d[1] == 2) + return inverse_2(m); + + real[3,3] inverse_3(real[3,3] m) { + real a = m[0,0], b = m[0,1], c = m[0, 2]; + real d = m[1,0], e = m[1,1], f = m[1, 2]; + real g = m[2,0], h = m[2,1], k = m[2, 2]; + real Z = a*(e*k-f*h) + b*(f*g - d*k) + c*(d*h-e*g); + real A = (e*k-f*h), B = (c*h-b*k), C=(b*f-c*e); + real D = (f*g-d*k), E = (a*k-c*g), F=(c*d-a*f); + real G = (d*h-e*g), H = (b*g-a*h), K=(a*e-b*d); + return multiply_mat_val((real[3,3]) { + { A, B, C }, { D, E, F }, { G, H, K }}, + 1/Z); + } + + if (d[0] == 3 && d[1] == 3) + return inverse_3(m); + assert(false, "cannot invert %v\n", d); + return m; + } + + public mat_t identity(int d) { + return (real[d,d]) { [i,j] = (i == j) ? 1 : 0 }; + } + + public vec_t vec_subtract(vec_t a, vec_t b) { + int da = dim(a); + int db = dim(b); + + assert(da == db, "mismatching dim in minus"); + return (real[da]) { [x] = a[x] - b[x] }; + } + + public vec_t vec_add(vec_t a, vec_t b) { + int da = dim(a); + int db = dim(b); + + assert(da == db, "mismatching dim in plus"); + return (real[da]) { [x] = a[x] + b[x] }; + } + + public vec_t multiply_vec_mat(vec_t v, mat_t m) { + mat_t r2 = matrix::multiply((real[dim(v),1]) { [y,x] = v[y] }, m); + return (real[dim(v)]) { [y] = r2[y,0] }; + } + + public vec_t multiply_mat_vec(mat_t m, vec_t v) { + mat_t r2 = matrix::multiply(m, (real[dim(v), 1]) { [y,x] = v[y] }); + int[2] d = dims(m); + return (real[d[0]]) { [y] = r2[y,0] }; + } +} diff --git a/src/kalman/plotaccel b/src/kalman/plotaccel new file mode 100644 index 00000000..fd540203 --- /dev/null +++ b/src/kalman/plotaccel @@ -0,0 +1,18 @@ +#!/bin/sh +for i in "$@"; do +gnuplot -p << EOF +set title "$i" +set ylabel "height (m)" +set y2label "velocity (m/s), acceleration (m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$i" using 1:3 with lines lt 1 axes x1y2 title "raw speed",\ + "$i" using 1:4 with lines lt 1 axes x1y2 title "raw accel",\ + "$i" using 1:6 with lines lt 2 axes x1y2 title "both speed",\ + "$i" using 1:7 with lines lt 2 axes x1y2 title "both accel",\ + "$i" using 1:9 with lines lt 3 axes x1y2 title "accel speed",\ + "$i" using 1:10 with lines lt 3 axes x1y2 title "accel accel" +EOF +done diff --git a/src/kalman/plotkalman b/src/kalman/plotkalman new file mode 100755 index 00000000..d2041dfb --- /dev/null +++ b/src/kalman/plotkalman @@ -0,0 +1,24 @@ +#!/bin/sh +for i in "$@"; do +gnuplot -p << EOF +set title "$i" +set ylabel "height (m)" +set y2label "velocity (m/s), acceleration (m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$i" using 1:2 with lines lt 1 axes x1y1 title "raw height",\ + "$i" using 1:3 with lines lt 1 axes x1y2 title "raw speed",\ + "$i" using 1:4 with lines lt 1 axes x1y2 title "raw accel",\ + "$i" using 1:5 with lines lt 2 axes x1y1 title "both height",\ + "$i" using 1:6 with lines lt 2 axes x1y2 title "both vel",\ + "$i" using 1:7 with lines lt 2 axes x1y2 title "both accel",\ + "$i" using 1:8 with lines lt 3 axes x1y1 title "accel height",\ + "$i" using 1:9 with lines lt 3 axes x1y2 title "accel vel",\ + "$i" using 1:10 with lines lt 3 axes x1y2 title "accel accel",\ + "$i" using 1:11 with lines lt 4 axes x1y1 title "baro height",\ + "$i" using 1:12 with lines lt 4 axes x1y2 title "baro vel",\ + "$i" using 1:13 with lines lt 4 axes x1y2 title "baro accel" +EOF +done diff --git a/src/make-kalman b/src/make-kalman new file mode 100644 index 00000000..80157c6b --- /dev/null +++ b/src/make-kalman @@ -0,0 +1,18 @@ +#!/bin/sh + +cd ../kalman + +SIGMA_ACCEL_MODEL=1 +SIGMA_BARO_MEASURE=8 +SIGMA_ACCEL_MEASURE=4 + +SIGMA="-M $SIGMA_ACCEL_MODEL -H $SIGMA_BARO_MEASURE -A $SIGMA_ACCEL_MEASURE" + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA + +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA + +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA -- cgit v1.2.3 From 7b009b2efe3af8722c358c304c2243652594e0d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 05:42:51 +0900 Subject: altos: Switch telemetrum over to kalman filter This changes the full telemetry stream to include kalman data instead of the old ad-hoc flight data. It's compatible in that the packet sizes are the same so teledongle can receive either and figure out which it has received. A few plotting and testing tools are added to make validating the new code easier. Signed-off-by: Keith Packard --- src/ao.h | 36 ++-- src/ao_flash.c | 8 +- src/ao_flight.c | 495 +++++++++++++++++++++--------------------------- src/ao_flight_test.c | 82 ++++---- src/ao_log_tiny.c | 2 +- src/ao_monitor.c | 34 ++-- src/ao_pins.h | 5 - src/ao_report.c | 2 +- src/ao_telemetry.c | 7 +- src/ao_telemetry_tiny.c | 6 +- src/test/.gitignore | 1 + src/test/Makefile | 13 +- src/test/plottest | 16 ++ src/test/run-one | 32 ++++ src/test/test-flights | 1 - 15 files changed, 367 insertions(+), 373 deletions(-) create mode 100755 src/test/plottest create mode 100755 src/test/run-one diff --git a/src/ao.h b/src/ao.h index 527390b0..b88bef1f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -34,7 +34,7 @@ /* Stack runs from above the allocated __data space to 0xfe, which avoids * writing to 0xff as that triggers the stack overflow indicator */ -#define AO_STACK_START 0x80 +#define AO_STACK_START 0x90 #define AO_STACK_END 0xfe #define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) @@ -470,7 +470,7 @@ extern __xdata uint16_t ao_storage_unit; /* Initialize above values. Can only be called once the OS is running */ void -ao_storage_setup(void); +ao_storage_setup(void) __reentrant; /* Write data. Returns 0 on failure, 1 on success */ uint8_t @@ -698,21 +698,19 @@ enum ao_flight_state { extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_flight_tick; -extern __pdata int16_t ao_flight_accel; -extern __pdata int16_t ao_flight_pres; -extern __pdata int32_t ao_flight_vel; -extern __pdata int16_t ao_ground_pres; +extern __xdata int16_t ao_ground_pres; extern __pdata int16_t ao_ground_accel; -extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; -#ifdef USE_KALMAN extern __pdata int16_t ao_ground_height; -extern __pdata int32_t ao_k_max_height; -extern __pdata int32_t ao_k_height; -extern __pdata int32_t ao_k_speed; -extern __pdata int32_t ao_k_accel; -#endif +extern __pdata int16_t ao_max_height; +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) /* Flight thread */ void @@ -912,10 +910,16 @@ struct ao_telemetry { uint16_t serial; uint16_t flight; uint8_t flight_state; - int16_t flight_accel; + int16_t accel; int16_t ground_accel; - int32_t flight_vel; - int16_t flight_pres; + union { + struct { + int16_t speed; + int16_t unused; + } k; + int32_t flight_vel; + } u; + int16_t height; int16_t ground_pres; int16_t accel_plus_g; int16_t accel_minus_g; diff --git a/src/ao_flash.c b/src/ao_flash.c index 3a264ceb..d323926f 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -93,12 +93,12 @@ static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; static __pdata uint8_t ao_flash_block_dirty; static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; -static __data uint8_t ao_flash_block_shift; -static __data uint16_t ao_flash_block_size; -static __data uint16_t ao_flash_block_mask; +static __pdata uint8_t ao_flash_block_shift; +static __pdata uint16_t ao_flash_block_size; +static __pdata uint16_t ao_flash_block_mask; void -ao_storage_setup(void) +ao_storage_setup(void) __reentrant { uint8_t status; diff --git a/src/ao_flight.c b/src/ao_flight.c index 493913b2..c65670f0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -31,22 +31,14 @@ #error Please define HAS_USB #endif -#ifndef USE_KALMAN -#error Please define USE_KALMAN -#endif - /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_flight_tick; /* time of last data */ __pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__pdata int16_t ao_flight_pres; /* filtered pressure */ -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_min_pres; /* minimum recorded pressure */ +__xdata int16_t ao_ground_pres; /* startup pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ -__pdata int16_t ao_main_pres; /* pressure to eject main */ #if HAS_ACCEL -__pdata int16_t ao_flight_accel; /* filtered acceleration */ __pdata int16_t ao_ground_accel; /* startup acceleration */ #endif @@ -55,16 +47,8 @@ __pdata int16_t ao_ground_accel; /* startup acceleration */ * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_cur_min_pres; -__pdata int16_t ao_interval_cur_max_pres; -__pdata int16_t ao_interval_min_pres; -__pdata int16_t ao_interval_max_pres; -#if HAS_ACCEL -__pdata int16_t ao_interval_cur_min_accel; -__pdata int16_t ao_interval_cur_max_accel; -__pdata int16_t ao_interval_min_accel; -__pdata int16_t ao_interval_max_accel; -#endif +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_pres; @@ -96,15 +80,8 @@ __pdata int16_t ao_accel_2g; */ #define GRAVITY 9.80665 -/* convert m/s to velocity count */ -#define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) #define ACCEL_NOSE_UP (ao_accel_2g >> 2) -#define ACCEL_BOOST ao_accel_2g -#define ACCEL_COAST (ao_accel_2g >> 3) -#define ACCEL_INT_LAND (ao_accel_2g >> 3) -#define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) -#define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) #endif @@ -127,91 +104,185 @@ __pdata int16_t ao_accel_2g; * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa */ -#define BARO_kPa 268 -#define BARO_LAUNCH (BARO_kPa / 5) /* .2kPa, or about 20m */ -#define BARO_APOGEE (BARO_kPa / 10) /* .1kPa, or about 10m */ -#define BARO_COAST (BARO_kPa * 5) /* 5kpa, or about 500m */ -#define BARO_MAIN (BARO_kPa) /* 1kPa, or about 100m */ -#define BARO_INT_LAND (BARO_kPa / 20) /* .05kPa, or about 5m */ -#define BARO_LAND (BARO_kPa * 10) /* 10kPa or about 1000m */ - /* We also have a clock, which can be used to sanity check things in * case of other failures */ #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) -#if HAS_ACCEL -/* This value is scaled in a weird way. It's a running total of accelerometer - * readings minus the ground accelerometer reading. That means it measures - * velocity, and quite accurately too. As it gets updated 100 times a second, - * it's scaled by 100 - */ -__pdata int32_t ao_flight_vel; -__pdata int32_t ao_min_vel; -__pdata int32_t ao_old_vel; -__pdata int16_t ao_old_vel_tick; -__xdata int32_t ao_raw_accel_sum; -#endif - -#if USE_KALMAN -__pdata int16_t ao_ground_height; -__pdata int32_t ao_k_max_height; -__pdata int32_t ao_k_height; -__pdata int32_t ao_k_speed; -__pdata int32_t ao_k_accel; - #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) - #define from_fix(x) ((x) >> 16) -#define AO_K0_100 to_fix16(0.05680323) -#define AO_K1_100 to_fix16(0.16608182) -#define AO_K2_100 to_fix16(0.24279580) +#include "ao_kalman.h" + +__pdata int16_t ao_ground_height; +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; #define AO_K_STEP_100 to_fix16(0.01) #define AO_K_STEP_2_2_100 to_fix16(0.00005) -#define AO_K0_10 to_fix16(0.23772023) -#define AO_K1_10 to_fix16(0.32214149) -#define AO_K2_10 to_fix16(0.21827159) - #define AO_K_STEP_10 to_fix16(0.1) #define AO_K_STEP_2_2_10 to_fix16(0.005) +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 8000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 300 + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static __pdata int16_t ao_error_h; +static __pdata int16_t ao_raw_alt; +static __pdata int16_t ao_raw_height; +static __pdata int16_t ao_error_h_sq_avg; + static void -ao_kalman_baro(void) +ao_kalman_err_height(void) { - int16_t err = ((ao_pres_to_altitude(ao_raw_pres) - ao_ground_height)) - - (int16_t) (ao_k_height >> 16); + int16_t e; + ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +} +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_10 + - (ao_k_accel >> 16) * AO_K_STEP_2_2_10); - ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_10; - - /* correct */ - ao_k_height += (int32_t) AO_K0_10 * err; - ao_k_speed += (int32_t) AO_K1_10 * err; - ao_k_accel += (int32_t) AO_K2_10 * err; + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; return; } #endif - ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_100 + - (ao_k_accel >> 16) * AO_K_STEP_2_2_100); - ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_100; - - /* correct */ - ao_k_height += (int32_t) AO_K0_100 * err; - ao_k_speed += (int32_t) AO_K1_100 * err; - ao_k_accel += (int32_t) AO_K2_100 * err; + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; } + +#if HAS_ACCEL +static __pdata int16_t ao_error_a; +static __pdata int32_t ao_accel_scale; + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_raw_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#if 0 + /* + * Check to see if things are crazy here -- + * if the computed height is far above the + * measured height, we assume that the flight + * trajectory is not vertical, and so ignore + * the accelerometer for the remainder of the + * flight. + */ + if (ao_error_h_sq_avg > 10) + { + ao_kalman_correct_baro(); + return; + } +#endif + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; + ao_k_speed += + ((int32_t) AO_BOTH_K10_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + ((int32_t) AO_BOTH_K20_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } #endif + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif /* HAS_ACCEL */ __xdata int32_t ao_raw_pres_sum; +#ifdef HAS_ACCEL +__xdata int32_t ao_raw_accel_sum; +#endif + /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ @@ -235,10 +306,6 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { -#if HAS_ACCEL - __pdata uint8_t ticks; - __pdata int16_t ao_vel_change; -#endif __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; @@ -246,9 +313,8 @@ ao_flight(void) ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; ao_raw_pres = ao_adc->pres; - ao_flight_pres -= ao_flight_pres >> 4; - ao_flight_pres += ao_raw_pres >> 4; - + ao_raw_alt = ao_pres_to_altitude(ao_raw_pres); + ao_raw_height = ao_raw_alt - ao_ground_height; #if HAS_ACCEL ao_raw_accel = ao_adc->accel; #if HAS_ACCEL_REF @@ -335,45 +401,31 @@ ao_flight(void) ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; ao_adc->accel = ao_raw_accel; #endif - - ao_flight_accel -= ao_flight_accel >> 4; - ao_flight_accel += ao_raw_accel >> 4; - /* Update velocity - * - * The accelerometer is mounted so that - * acceleration yields negative values - * while deceleration yields positive values, - * so subtract instead of add. - */ - ticks = ao_flight_tick - ao_flight_prev_tick; - ao_vel_change = ao_ground_accel - (((ao_raw_accel + 1) >> 1) + ((ao_raw_accel_prev + 1) >> 1)); - ao_raw_accel_prev = ao_raw_accel; - - /* one is a common interval */ - if (ticks == 1) - ao_flight_vel += (int32_t) ao_vel_change; - else - ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; #endif -#if USE_KALMAN - if (ao_flight_state > ao_flight_idle) - ao_kalman_baro(); -#endif - ao_flight_adc = ao_adc_ring_next(ao_flight_adc); - } - - if (ao_flight_pres < ao_min_pres) - ao_min_pres = ao_flight_pres; + if (ao_flight_state > ao_flight_idle) { + ao_kalman_predict(); #if HAS_ACCEL - if (ao_flight_vel >= 0) { - if (ao_flight_vel < ao_min_vel) - ao_min_vel = ao_flight_vel; - } else { - if (-ao_flight_vel < ao_min_vel) - ao_min_vel = -ao_flight_vel; + if (ao_flight_state <= ao_flight_coast) { +#ifndef FORCE_ACCEL + if (/*ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) &&*/ + ao_raw_alt < AO_MAX_BARO_HEIGHT) + ao_kalman_correct_both(); + else +#endif + ao_kalman_correct_accel(); + } else +#endif + if (ao_raw_alt < AO_MAX_BARO_HEIGHT || ao_flight_state >= ao_flight_drogue) + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; + } + ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } -#endif switch (ao_flight_state) { case ao_flight_startup: @@ -391,35 +443,25 @@ ao_flight(void) ++nsamples; continue; } + ao_config_get(); #if HAS_ACCEL ao_ground_accel = ao_raw_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif ao_ground_pres = ao_raw_pres_sum >> 9; - ao_min_pres = ao_ground_pres; - ao_config_get(); -#if USE_KALMAN ao_ground_height = ao_pres_to_altitude(ao_ground_pres); -#endif - ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); -#if HAS_ACCEL - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_flight_vel = 0; - ao_min_vel = 0; - ao_old_vel = ao_flight_vel; - ao_old_vel_tick = ao_flight_tick; -#endif /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out * - pad mode if we're upright, * - idle mode otherwise */ - ao_config_get(); #if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || - ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) { /* Detected an accel value outside -1.5g to 1.5g * (or uncalibrated values), so we go into invalid mode @@ -430,7 +472,7 @@ ao_flight(void) #endif if (!ao_flight_force_idle #if HAS_ACCEL - && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { @@ -465,57 +507,27 @@ ao_flight(void) break; case ao_flight_pad: -#if HAS_ACCEL - /* Trim velocity - * - * Once a second, remove any velocity from - * a second ago - */ - if ((int16_t) (ao_flight_tick - ao_old_vel_tick) >= AO_SEC_TO_TICKS(1)) { - ao_old_vel_tick = ao_flight_tick; - ao_flight_vel -= ao_old_vel; - ao_old_vel = ao_flight_vel; - } -#endif /* pad to boost: * - * accelerometer: > 2g AND velocity > 5m/s - * OR * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s * * The accelerometer should always detect motion before * the barometer, but we use both to make sure this - * transition is detected + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. */ -#if USE_KALMAN + if (ao_height > AO_M_TO_HEIGHT(20) #if HAS_ACCEL - /* - * With an accelerometer, either to detect launch - */ - if ((ao_k_accel > to_fix32(20) && - ao_k_speed > to_fix32(5)) || - ao_k_height > to_fix32(20)) -#else - /* - * Without an accelerometer, the barometer is far too - * noisy to rely on speed or acceleration data - */ - if (ao_k_height > to_fix32(20)) -#endif -#else - if ( -#if HAS_ACCEL - (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && - ao_flight_vel > ACCEL_VEL_BOOST) || -#endif - ao_flight_pres < ao_ground_pres - BARO_LAUNCH) + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) #endif + ) { -#if HAS_ACCEL || USE_KALMAN ao_flight_state = ao_flight_boost; -#else - ao_flight_state = ao_flight_coast; -#endif ao_launch_tick = ao_flight_tick; /* start logging data */ @@ -537,7 +549,6 @@ ao_flight(void) break; } break; -#if HAS_ACCEL || USE_KALMAN case ao_flight_boost: /* boost to fast: @@ -550,13 +561,8 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ -#if USE_KALMAN - if ((ao_k_accel < to_fix32(-10) && ao_k_height > to_fix32(100)) || - (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) -#else - if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) -#endif { ao_flight_state = ao_flight_fast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -564,62 +570,28 @@ ao_flight(void) } break; case ao_flight_fast: - - /* fast to coast: - * - * accelerometer: integrated velocity < 200 m/s - * OR - * barometer: fall at least 500m from max altitude - * - * This extra state is required to avoid mis-detecting - * apogee due to mach transitions. - * - * XXX this is essentially a single-detector test - * as the 500m altitude change would likely result - * in a loss of the rocket. More data on precisely - * how big a pressure change the mach transition - * generates would be useful here. + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. */ -#if USE_KALMAN - if (ao_k_speed < to_fix32(200) || - ao_k_height < ao_k_max_height - to_fix32(500)) -#else - if (ao_flight_vel < ACCEL_VEL_MACH || - ao_flight_pres > ao_min_pres + BARO_COAST) -#endif - { -#if HAS_ACCEL - /* set min velocity to current velocity for - * apogee detect - */ - ao_min_vel = abs(ao_flight_vel); -#endif + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; } break; -#endif /* HAS_ACCEL */ case ao_flight_coast: -#if USE_KALMAN /* apogee detect: coast to drogue deploy: * * speed: < 0 - */ - if (ao_k_speed < 0) -#else - /* apogee detect: coast to drogue deploy: - * - * barometer: fall at least 10m * - * It would be nice to use the accelerometer - * to detect apogee as well, but tests have - * shown that flights far from vertical would - * grossly mis-detect apogee. So, for now, - * we'll trust to a single sensor for this test + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. */ - if (ao_flight_pres > ao_min_pres + BARO_APOGEE) -#endif + if (ao_speed < 0 && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -627,32 +599,15 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); -#if !USE_KALMAN - /* slow down the ADC sample rate */ - ao_timer_set_adc_interval(10); -#endif - /* - * Start recording min/max accel and pres for a while + * Start recording min/max height * to figure out when the rocket has landed */ - /* Set the 'last' limits to max range to prevent - * early resting detection - */ -#if HAS_ACCEL - ao_interval_min_accel = 0; - ao_interval_max_accel = 0x7fff; -#endif - ao_interval_min_pres = 0; - ao_interval_max_pres = 0x7fff; /* initialize interval values */ ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; -#endif + ao_interval_min_height = ao_interval_max_height = ao_height; /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -674,11 +629,7 @@ ao_flight(void) * at that point. Perhaps also use the drogue sense lines * to notice continutity? */ -#if USE_KALMAN - if (from_fix(ao_k_height) < ao_config.main_deploy) -#else - if (ao_flight_pres >= ao_main_pres) -#endif + if (ao_height <= ao_config.main_deploy) { ao_ignite(ao_igniter_main); ao_flight_state = ao_flight_main; @@ -690,39 +641,17 @@ ao_flight(void) /* drogue/main to land: * - * accelerometer: value stable - * AND * barometer: altitude stable and within 1000m of the launch altitude */ - if (ao_flight_pres < ao_interval_cur_min_pres) - ao_interval_cur_min_pres = ao_flight_pres; - if (ao_flight_pres > ao_interval_cur_max_pres) - ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - if (ao_flight_accel < ao_interval_cur_min_accel) - ao_interval_cur_min_accel = ao_flight_accel; - if (ao_flight_accel > ao_interval_cur_max_accel) - ao_interval_cur_max_accel = ao_flight_accel; -#endif + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { - ao_interval_max_pres = ao_interval_cur_max_pres; - ao_interval_min_pres = ao_interval_cur_min_pres; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - ao_interval_max_accel = ao_interval_cur_max_accel; - ao_interval_min_accel = ao_interval_cur_min_accel; - ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; -#endif - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - - if ( -#if HAS_ACCEL - (uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && -#endif - ao_flight_pres > ao_ground_pres - BARO_LAND && - (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) + if (ao_height < AO_M_TO_HEIGHT(1000) && + ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) { ao_flight_state = ao_flight_landed; @@ -733,6 +662,8 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; } break; case ao_flight_landed: diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 16167644..e7bfbdd2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -29,6 +29,10 @@ #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + /* * One set of samples read from the A/D converter */ @@ -143,15 +147,26 @@ struct ao_config ao_config; #ifndef HAS_ACCEL #define HAS_ACCEL 1 #define HAS_ACCEL_REF 0 -#define USE_KALMAN 0 -#else -#define USE_KALMAN 1 #endif #include "ao_flight.c" #define to_double(f) ((f) / 65536.0) +#define GRAVITY 9.80665 +extern int16_t ao_ground_accel, ao_raw_accel; +extern int16_t ao_accel_2g; + +int32_t drogue_height; +int32_t main_height; + +int tick_offset; +uint16_t prev_tick; +static int ao_records_read = 0; +static int ao_eof_read = 0; +static int ao_flight_ground_accel; +static int ao_flight_started = 0; + void ao_insert(void) { @@ -159,33 +174,39 @@ ao_insert(void) ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_summary) return; - if (ao_flight_state != ao_flight_startup) { -#if USE_KALMAN - printf("time %7.2f accel %d pres %d k_height %8.2f k_speed %8.5f k_accel %8.5f\n", - (double) ao_adc_static.tick / 100, - ao_adc_static.accel, - ao_adc_static.pres, - to_double(ao_k_height), - to_double(ao_k_speed), - to_double(ao_k_accel)); -#else - printf("time %g accel %d pres %d\n", - (double) ao_adc_static.tick / 100, - ao_adc_static.accel, - ao_adc_static.pres); -#endif + if (ao_flight_state == ao_flight_startup) + return; + { + double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + (ao_config.accel_minus_g - ao_config.accel_plus_g); + + if (!tick_offset) + tick_offset = ao_adc_static.tick; + if (!drogue_height && ao_flight_state >= ao_flight_drogue) + drogue_height = ao_k_height; + if (!main_height && ao_flight_state >= ao_flight_main) + main_height = ao_k_height; + if ((prev_tick - ao_adc_static.tick) > 0) + tick_offset += 65536; + prev_tick = ao_adc_static.tick; + printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %g main %g error %d\n", + (double) (ao_adc_static.tick + tick_offset) / 100, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + drogue_height / 65536.0, + main_height / 65536.0, + ao_error_h_sq_avg); } } -static int ao_records_read = 0; -static int ao_eof_read = 0; -static int ao_flight_ground_accel; -static int ao_flight_started = 0; - void ao_sleep(void *wchan) { - ao_dump_state(); if (wchan == &ao_adc_head) { char type; uint16_t tick; @@ -291,19 +312,6 @@ ao_dump_state(void) return; if (ao_summary) return; -#if HAS_ACCEL - printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", - ao_state_names[ao_flight_state], - (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY, - (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY, - ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), - ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); -#else - printf ("\t\t\t\t\t%s alt %d main %d\n", - ao_state_names[ao_flight_state], - ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), - ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); -#endif if (ao_flight_state == ao_flight_landed) exit(0); } diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index fad2a242..f0c0662a 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -69,7 +69,7 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_k_height >> 16); + ao_log_tiny_data(ao_height); time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index d6fd8305..8f290071 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -92,23 +92,23 @@ ao_monitor(void) recv.telemetry.accel_plus_g, recv.telemetry.accel_minus_g); -#if 0 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d ", - recv.telemetry.height, - recv.telemetry.speed, - recv.telemetry.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d ", - recv.telemetry.flight_accel, - recv.telemetry.flight_vel, - recv.telemetry.flight_pres); -#endif + if (recv.telemetry.u.k.unused == 0x8000) { + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv.telemetry.height, + recv.telemetry.u.k.speed, + recv.telemetry.accel); + } else { + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv.telemetry.accel, + recv.telemetry.u.flight_vel, + recv.telemetry.height); + } ao_gps_print(&recv.telemetry.gps); ao_gps_tracking_print(&recv.telemetry.gps_tracking); putchar('\n'); diff --git a/src/ao_pins.h b/src/ao_pins.h index c602268b..a4a93aab 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,7 +28,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 - #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -53,7 +52,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 - #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -103,7 +101,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 - #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -126,7 +123,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 - #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -147,7 +143,6 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 - #define USE_KALMAN 0 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 diff --git a/src/ao_report.c b/src/ao_report.c index 3223390f..4f7fd657 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -87,7 +87,7 @@ ao_report_digit(uint8_t digit) __reentrant static void ao_report_altitude(void) { - __xdata int16_t agl = ao_pres_to_altitude(ao_min_pres) - ao_pres_to_altitude(ao_ground_pres); + __xdata int16_t agl = ao_max_height; __xdata uint8_t digits[10]; __xdata uint8_t ndigits, i; diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 6556ce32..9a86882f 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -45,12 +45,13 @@ ao_telemetry(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { telemetry.flight_state = ao_flight_state; + telemetry.height = ao_height; + telemetry.u.k.speed = ao_speed; + telemetry.accel = ao_accel; + telemetry.u.k.unused = 0x8000; #if HAS_ACCEL - telemetry.flight_accel = ao_flight_accel; telemetry.ground_accel = ao_ground_accel; - telemetry.flight_vel = ao_flight_vel; #endif - telemetry.flight_pres = ao_flight_pres; telemetry.ground_pres = ao_ground_pres; #if HAS_ADC ao_adc_get(&telemetry.adc); diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c index 83ba7fc0..6f2ddda1 100644 --- a/src/ao_telemetry_tiny.c +++ b/src/ao_telemetry_tiny.c @@ -43,9 +43,9 @@ ao_telemetry_tiny(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_tiny_interval) { telemetry_tiny.flight_state = ao_flight_state; - telemetry_tiny.height = ao_k_height >> 16; - telemetry_tiny.speed = ao_k_speed >> 12; - telemetry_tiny.accel = ao_k_accel >> 12; + telemetry_tiny.height = ao_height; + telemetry_tiny.speed = ao_speed; + telemetry_tiny.accel = ao_accel; telemetry_tiny.ground_pres = ao_ground_pres; ao_adc_get(&telemetry_tiny.adc); ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); diff --git a/src/test/.gitignore b/src/test/.gitignore index 0a43de8a..33c7ef35 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -1,5 +1,6 @@ ao_flight_test ao_flight_test_baro +ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test diff --git a/src/test/Makefile b/src/test/Makefile index 853713fa..433f749b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,7 @@ vpath % .. +vpath % ../kalman -PROGS=ao_flight_test ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test CFLAGS=-I.. -I. @@ -11,12 +12,15 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h cc -g -o $@ $< -ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c +ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h + cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc -g -o $@ $< @@ -25,3 +29,6 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc -g -o $@ $< + +../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< > $@ diff --git a/src/test/plottest b/src/test/plottest new file mode 100755 index 00000000..76af5ee7 --- /dev/null +++ b/src/test/plottest @@ -0,0 +1,16 @@ +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ +"$1" using 1:5 with lines axes x1y2 title "raw accel",\ +"$1" using 1:9 with lines axes x1y1 title "height",\ +"$1" using 1:11 with lines axes x1y2 title "speed",\ +"$1" using 1:13 with lines axes x1y2 title "accel",\ +"$1" using 1:15 with lines axes x1y1 title "drogue",\ +"$1" using 1:17 with lines axes x1y1 title "main",\ +"$1" using 1:19 with lines axes x1y1 title "error" +EOF diff --git a/src/test/run-one b/src/test/run-one new file mode 100755 index 00000000..f9d21576 --- /dev/null +++ b/src/test/run-one @@ -0,0 +1,32 @@ +#!/bin/sh + +./ao_flight_test "$1" > run-out.full +./ao_flight_test_baro "$1" > run-out.baro +./ao_flight_test_accel "$1" > run-out.accel + +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$1" +plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.full" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ +"run-out.full" using 1:9 with lines lt 2 axes x1y1 title "full height",\ +"run-out.full" using 1:11 with lines lt 2 axes x1y2 title "full speed",\ +"run-out.full" using 1:13 with lines lt 2 axes x1y2 title "full accel",\ +"run-out.full" using 1:15 with lines lt 2 axes x1y1 title "full drogue",\ +"run-out.full" using 1:17 with lines lt 2 axes x1y1 title "full main", \ +"run-out.baro" using 1:9 with lines lt 3 axes x1y1 title "baro height",\ +"run-out.baro" using 1:11 with lines lt 3 axes x1y2 title "baro speed",\ +"run-out.baro" using 1:13 with lines lt 3 axes x1y2 title "baro accel",\ +"run-out.baro" using 1:15 with lines lt 3 axes x1y1 title "baro drogue",\ +"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main",\ +"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main" +EOF diff --git a/src/test/test-flights b/src/test/test-flights index a9a2ecca..afdaba5a 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -7,7 +7,6 @@ 2009-07-18-serial-001-flight-007.eeprom 2009-08-22-serial-001-flight-001.eeprom 2009-08-22-serial-010-flight-001.eeprom -2009-09-05-serial-008-flight-002.eeprom 2009-09-05-serial-010-flight-002.eeprom 2009-09-05-serial-011-flight-001.eeprom 2009-09-11-serial-008-flight-003.eeprom -- cgit v1.2.3 From c14d6c5ace1d67bd948273ceb7eb6807b29c3806 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 08:51:23 +0900 Subject: altos: Compute a 'trust' value for the barometer Instead of making the baro use/don't-use decision binary, use a 'trust value' which slowly migrates from baro+accel to accel-only mode. This eliminates bumps in the data from a rapid shift. Signed-off-by: Keith Packard --- src/ao_flight.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index c65670f0..b86603e4 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -135,7 +135,7 @@ static __pdata int32_t ao_k_accel; /* * Above this height, the baro sensor doesn't work */ -#define AO_MAX_BARO_HEIGHT 8000 +#define AO_MAX_BARO_HEIGHT 12000 /* * Above this speed, baro measurements are unreliable @@ -168,6 +168,11 @@ static void ao_kalman_err_height(void) { int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); e = ao_error_h; @@ -177,6 +182,31 @@ ao_kalman_err_height(void) e = 127; ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; ao_error_h_sq_avg += (e * e) >> 4; + + height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; +#ifdef AO_FLIGHT_TEST + if (height_distrust > 0) + printf ("height_distrust %d\n", height_distrust); +#endif +#if HAS_ACCEL + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; +#ifdef AO_FLIGHT_TEST + if (speed_distrust > 0) + printf ("speed distrust %d\n", speed_distrust); +#endif + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust <= 0) + height_distrust = 0; + + if (height_distrust) { + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; + } } static void @@ -407,16 +437,13 @@ ao_flight(void) ao_kalman_predict(); #if HAS_ACCEL if (ao_flight_state <= ao_flight_coast) { -#ifndef FORCE_ACCEL - if (/*ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) &&*/ - ao_raw_alt < AO_MAX_BARO_HEIGHT) - ao_kalman_correct_both(); - else +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); #endif - ao_kalman_correct_accel(); } else #endif - if (ao_raw_alt < AO_MAX_BARO_HEIGHT || ao_flight_state >= ao_flight_drogue) ao_kalman_correct_baro(); ao_height = from_fix(ao_k_height); ao_speed = from_fix(ao_k_speed); -- cgit v1.2.3 From 6864e06d88a5b908cffa7c4cd2be8969ff46ce4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 16:51:04 +0900 Subject: altos/kalman: Kalman terms can be > 1, use 32-bit fixed point Because speed and acceleration are scaled by 16, it's fairly common for the kalman terms to end up larger than 1. Instead of trying to fuss with 16-bit values and shifts, just use 32-bit values. Signed-off-by: Keith Packard --- src/kalman/kalman.5c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c index f7347184..cfb7abea 100755 --- a/src/kalman/kalman.5c +++ b/src/kalman/kalman.5c @@ -460,19 +460,17 @@ void main() { mat_t k = converge(param); int[] d = dims(k); int time_inc = floor(1/time_step + 0.5); - if (d[1] == 2) { - for (int i = 0; i < d[0]; i++) - for (int j = 0; j < d[1]; j++) - printf ("#define %s_K%d%d_%d to_fix16(%12.10f)\n", - prefix, i, j, time_inc, k[i,j]); - } else { - for (int i = 0; i < d[0]; i++) { - printf ("#define %s_K%d_%d to_fix16(%12.10f)\n", - prefix, i, time_inc, k[i,0]); + for (int i = 0; i < d[0]; i++) + for (int j = 0; j < d[1]; j++) { + string name; + if (d[1] == 1) + name = sprintf("%s_K%d_%d", prefix, i, time_inc); + else + name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc); + printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]); } - } printf ("\n"); - return; + exit(0); } string[dim(argv) - user_argind] rest = { [i] = argv[i+user_argind] }; -- cgit v1.2.3 From f3053b1f3c85d4fd84b3c6cc87858f433166df34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 17:04:07 +0900 Subject: altos: Clean up some debug stuff in ao_flight.c Remove some spurious printf debugging. Remove an attempt at discovering broken accelerometer code. Signed-off-by: Keith Packard --- src/ao_flight.c | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index b86603e4..7f194e04 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -184,16 +184,8 @@ ao_kalman_err_height(void) ao_error_h_sq_avg += (e * e) >> 4; height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; -#ifdef AO_FLIGHT_TEST - if (height_distrust > 0) - printf ("height_distrust %d\n", height_distrust); -#endif #if HAS_ACCEL speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; -#ifdef AO_FLIGHT_TEST - if (speed_distrust > 0) - printf ("speed distrust %d\n", speed_distrust); -#endif if (speed_distrust <= 0) speed_distrust = 0; else if (speed_distrust > height_distrust) @@ -247,22 +239,6 @@ ao_kalman_correct_both(void) ao_kalman_err_height(); ao_kalman_err_accel(); -#if 0 - /* - * Check to see if things are crazy here -- - * if the computed height is far above the - * measured height, we assume that the flight - * trajectory is not vertical, and so ignore - * the accelerometer for the remainder of the - * flight. - */ - if (ao_error_h_sq_avg > 10) - { - ao_kalman_correct_baro(); - return; - } -#endif - #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { ao_k_height += -- cgit v1.2.3 From f30de5766c1eefb18c7d024a2cf10ce02de41071 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:29:05 +0900 Subject: altos: Add ao_flight_debug code Trace the kalman filter to make sure it's working. Signed-off-by: Keith Packard --- src/ao_flight.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 7f194e04..4c65344f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -153,6 +153,11 @@ ao_kalman_predict(void) return; } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } #endif ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; @@ -195,9 +200,21 @@ ao_kalman_err_height(void) height_distrust = 0; if (height_distrust) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif if (height_distrust > 0x100) height_distrust = 0x100; ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_raw_height - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif } } @@ -241,6 +258,15 @@ ao_kalman_correct_both(void) #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } ao_k_height += (int32_t) AO_BOTH_K00_10 * ao_error_h + (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; @@ -252,6 +278,15 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_10 * ao_error_a; return; } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } #endif ao_k_height += (int32_t) AO_BOTH_K00_100 * ao_error_h + @@ -264,23 +299,23 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_100 * ao_error_a; } +#ifdef FORCE_ACCEL static void ao_kalman_correct_accel(void) { ao_kalman_err_accel(); -#ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; return; } -#endif ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; } +#endif #endif /* HAS_ACCEL */ __xdata int32_t ao_raw_pres_sum; -- cgit v1.2.3 From a80d3836cfce3d4cfa7a71068539415c2dc421cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:50:29 +0900 Subject: altos: Missing parens and some bad arithmetic in the kalman code Fixed point computations are a pain. Signed-off-by: Keith Packard --- src/ao_flight.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 4c65344f..39325a69 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -140,7 +140,7 @@ static __pdata int32_t ao_k_accel; /* * Above this speed, baro measurements are unreliable */ -#define AO_MAX_BARO_SPEED 300 +#define AO_MAX_BARO_SPEED 200 static void ao_kalman_predict(void) @@ -185,12 +185,20 @@ ao_kalman_err_height(void) e = -e; if (e > 127) e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; ao_error_h_sq_avg += (e * e) >> 4; +#endif height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; #if HAS_ACCEL - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); if (speed_distrust <= 0) speed_distrust = 0; else if (speed_distrust > height_distrust) @@ -205,7 +213,7 @@ ao_kalman_err_height(void) #endif if (height_distrust > 0x100) height_distrust = 0x100; - ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); #ifdef AO_FLIGHT_TEST if (ao_flight_debug) { printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", @@ -269,12 +277,12 @@ ao_kalman_correct_both(void) } ao_k_height += (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; + (int32_t) AO_BOTH_K01_10 * ao_error_a; ao_k_speed += - ((int32_t) AO_BOTH_K10_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K10_10 * ao_error_h + (int32_t) AO_BOTH_K11_10 * ao_error_a; ao_k_accel += - ((int32_t) AO_BOTH_K20_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K20_10 * ao_error_h + (int32_t) AO_BOTH_K21_10 * ao_error_a; return; } @@ -602,23 +610,31 @@ ao_flight(void) if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) { +#if HAS_ACCEL ao_flight_state = ao_flight_fast; +#else + ao_flight_state = ao_flight_coast; +#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#if HAS_ACCEL case ao_flight_fast: /* * This is essentially the same as coast, * but the barometer is being ignored as * it may be unreliable. */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) && + (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30)) + { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#endif case ao_flight_coast: /* apogee detect: coast to drogue deploy: @@ -629,7 +645,11 @@ ao_flight(void) * the measured altitude reasonably closely; otherwise * we're probably transsonic. */ - if (ao_speed < 0 && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)) + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30) +#endif + ) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); -- cgit v1.2.3 From 7d7b476564a16eda81ab3406f70a21995e1b464e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:51:52 +0900 Subject: altos: Fix up flight code testing This automates flight code testing by reporting mis-detected apogee or main events. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 138 ++++++++++++++++++++++++++++++++++++-------------- src/test/run-one | 26 ++++++---- src/test/run-tests | 34 ++++++------- src/test/test-flights | 1 - 4 files changed, 131 insertions(+), 68 deletions(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e7bfbdd2..51a5965c 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -22,6 +22,7 @@ #include #include #include +#include #define AO_HERTZ 100 @@ -87,11 +88,27 @@ enum ao_igniter { struct ao_adc ao_adc_static; +int drogue_height; +double drogue_time; +int main_height; +double main_time; + +int tick_offset; + +static int32_t ao_k_height; + void ao_ignite(enum ao_igniter igniter) { - printf ("ignite %s at %7.2f\n", igniter == ao_igniter_drogue ? "drogue" : "main", - (double) ao_adc_static.tick / 100.0); + double time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (igniter == ao_igniter_drogue) { + drogue_time = time; + drogue_height = ao_k_height >> 16; + } else { + main_time = time; + main_height = ao_k_height >> 16; + } } struct ao_task { @@ -108,7 +125,12 @@ struct ao_task { #define AO_FLIGHT_TEST +int ao_flight_debug; + FILE *emulator_in; +char *emulator_app; +char *emulator_name; +double emulator_error_max = 10; void ao_dump_state(void); @@ -157,51 +179,84 @@ struct ao_config ao_config; extern int16_t ao_ground_accel, ao_raw_accel; extern int16_t ao_accel_2g; -int32_t drogue_height; -int32_t main_height; - -int tick_offset; uint16_t prev_tick; static int ao_records_read = 0; static int ao_eof_read = 0; static int ao_flight_ground_accel; static int ao_flight_started = 0; +static int ao_test_max_height; +static double ao_test_max_height_time; +static int ao_test_main_height; +static double ao_test_main_height_time; void ao_insert(void) { + double time; + ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); - if (ao_summary) - return; - if (ao_flight_state == ao_flight_startup) - return; - { + if (ao_flight_state != ao_flight_startup) { double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); if (!tick_offset) - tick_offset = ao_adc_static.tick; - if (!drogue_height && ao_flight_state >= ao_flight_drogue) - drogue_height = ao_k_height; - if (!main_height && ao_flight_state >= ao_flight_main) - main_height = ao_k_height; - if ((prev_tick - ao_adc_static.tick) > 0) + tick_offset = -ao_adc_static.tick; + if ((prev_tick - ao_adc_static.tick) > 0x400) tick_offset += 65536; prev_tick = ao_adc_static.tick; - printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %g main %g error %d\n", - (double) (ao_adc_static.tick + tick_offset) / 100, - height, - accel, - ao_state_names[ao_flight_state], - ao_k_height / 65536.0, - ao_k_speed / 65536.0 / 16.0, - ao_k_accel / 65536.0 / 16.0, - drogue_height / 65536.0, - main_height / 65536.0, - ao_error_h_sq_avg); + time = (double) (ao_adc_static.tick + tick_offset) / 100; + if (!ao_summary) { + printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", + time, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + drogue_height, + main_height, + ao_error_h_sq_avg); + } + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + } +} + +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", + drogue_height, drogue_time, main_height, main_time); + exit (1); } + exit(0); } void @@ -228,8 +283,9 @@ ao_sleep(void *wchan) if (!fgets(line, sizeof (line), emulator_in)) { if (++ao_eof_read >= 1000) { - printf ("no more data, exiting simulation\n"); - exit(0); + if (!ao_summary) + printf ("no more data, exiting simulation\n"); + ao_test_exit(); } ao_adc_static.tick += 10; ao_insert(); @@ -247,10 +303,10 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); - } else if (nword >= 6 && strcmp(words[0], "Accel")) { + } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); - } else if (nword >= 4 && strcmp(words[0], "Main")) { + } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); @@ -308,21 +364,17 @@ ao_sleep(void *wchan) void ao_dump_state(void) { - if (ao_flight_state == ao_flight_startup) - return; - if (ao_summary) - return; - if (ao_flight_state == ao_flight_landed) - exit(0); } static const struct option options[] = { { .name = "summary", .has_arg = 0, .val = 's' }, + { .name = "debug", .has_arg = 0, .val = 'd' }, { 0, 0, 0, 0}, }; void run_flight_fixed(char *name, FILE *f, int summary) { + emulator_name = name; emulator_in = f; ao_summary = summary; ao_flight_init(); @@ -336,11 +388,19 @@ main (int argc, char **argv) int c; int i; - while ((c = getopt_long(argc, argv, "s", options, NULL)) != -1) { +#if HAS_ACCEL + emulator_app="full"; +#else + emulator_app="baro"; +#endif + while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { switch (c) { case 's': summary = 1; break; + case 'd': + ao_flight_debug = 1; + break; } } diff --git a/src/test/run-one b/src/test/run-one index f9d21576..d661abec 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -1,17 +1,24 @@ #!/bin/sh -./ao_flight_test "$1" > run-out.full -./ao_flight_test_baro "$1" > run-out.baro -./ao_flight_test_accel "$1" > run-out.accel +for i in "$@"; do +./ao_flight_test "$i" > run-out.full +./ao_flight_test_baro "$i" > run-out.baro +#./ao_flight_test_accel "$i" > run-out.accel -gnuplot -persist << EOF +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ + +gnuplot << EOF set ylabel "altitude (m)" set y2label "velocity (m/s), acceleration(m/s²)" set xlabel "time (s)" set xtics border out nomirror set ytics border out nomirror set y2tics border out nomirror -set title "$1" +set title "$i" plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ "run-out.full" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ "run-out.full" using 1:9 with lines lt 2 axes x1y1 title "full height",\ @@ -23,10 +30,7 @@ plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height", "run-out.baro" using 1:11 with lines lt 3 axes x1y2 title "baro speed",\ "run-out.baro" using 1:13 with lines lt 3 axes x1y2 title "baro accel",\ "run-out.baro" using 1:15 with lines lt 3 axes x1y1 title "baro drogue",\ -"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main",\ -"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ -"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ -"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ -"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ -"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main" +"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main" +pause mouse close EOF +done \ No newline at end of file diff --git a/src/test/run-tests b/src/test/run-tests index ec279776..11b4c95c 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -2,21 +2,21 @@ DIR=~/src/cc1111/flights +bad_baro=0 +bad_full=0 while read flight; do - baro=`./ao_flight_test_baro -s $DIR/$flight | - awk '/drogue/ { printf "%s ", $4 } - /main/ { printf "%s\n", $4 }'` - full=`./ao_flight_test -s $DIR/$flight | - awk '/drogue/ { printf "%s ", $4 } - /main/ { printf "%s\n", $4 }'` - echo $flight $baro $full -done < test-flights | -awk '{ name = $1; - drogue_error = $2 - $4; - if (drogue_error < 0) drogue_error = -drogue_error; - main_error = $3 - $5; - if (main_error < 0) main_error = -main_error; - if (drogue_error > 4 || main_error > 4) - printf ("%s: baro drogue %f main %f. full drogue %f main %f\n", - name, $2, $3, $4, $5); - }' + if ./ao_flight_test_baro -s $DIR/$flight; then + : + else + ((bad_baro++)) + fi + if ./ao_flight_test -s $DIR/$flight; then + : + else + ((bad_full++)) + fi +done < test-flights +echo baro errors $bad_baro +echo full errors $bad_full +((bad = bad_baro + bad_full)) +exit $bad \ No newline at end of file diff --git a/src/test/test-flights b/src/test/test-flights index afdaba5a..0b90d9e0 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -63,7 +63,6 @@ 2010-09-24-serial-236-flight-006.eeprom 2010-09-25-serial-223-flight-001.eeprom 2010-10-17-serial-215-flight-006.eeprom -2010-10-23-serial-236-flight-008.eeprom 2011-01-30-serial-056-flight-001.eeprom 2011-01-30-serial-250-flight-002.eeprom 2011-02-19-serial-215-flight-007.eeprom -- cgit v1.2.3 From 3d2042ccc2d29e4cb8ea39c5c69d07cb7e3daeea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 16:55:08 +0900 Subject: altos: Restore sensible kalman values Now that the kalman code seems to work correctly, restore the sensor errors and model errors to match reality Signed-off-by: Keith Packard --- src/make-kalman | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/make-kalman b/src/make-kalman index 80157c6b..6fb181ec 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -2,17 +2,15 @@ cd ../kalman -SIGMA_ACCEL_MODEL=1 -SIGMA_BARO_MEASURE=8 -SIGMA_ACCEL_MEASURE=4 +SIGMA_BOTH="-M 2 -H 4 -A 4" +SIGMA_BARO="-M 2 -H 4 -A 4" +SIGMA_ACCEL="-M 2 -H 4 -A 4" -SIGMA="-M $SIGMA_ACCEL_MODEL -H $SIGMA_BARO_MEASURE -A $SIGMA_ACCEL_MEASURE" +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA -nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA -nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA - -nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA -nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO -- cgit v1.2.3 From 32364c9e0d346e0e5d517e18d4e90b8ff2fa944f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:33:38 +0900 Subject: altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. With the fixed kalman filter, transitions across mach don't cause bumps in the merged filter. And, with working kalman bits, the signal for broken baro detection is stronger and so we can allow for baro apogee detection in cases where noise occurs close to apogee. Bump the kalman filter to trust the baro less so that the model tracks across mach. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 ++--- src/make-kalman | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 39325a69..88f0544f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -626,8 +626,7 @@ ao_flight(void) * but the barometer is being ignored as * it may be unreliable. */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) && - (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30)) + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -647,7 +646,7 @@ ao_flight(void) */ if (ao_speed < 0 #if !HAS_ACCEL - && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30) + && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) #endif ) { diff --git a/src/make-kalman b/src/make-kalman index 6fb181ec..5a25e1ec 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -2,8 +2,8 @@ cd ../kalman -SIGMA_BOTH="-M 2 -H 4 -A 4" -SIGMA_BARO="-M 2 -H 4 -A 4" +SIGMA_BOTH="-M 2 -H 6 -A 2" +SIGMA_BARO="-M 2 -H 6 -A 2" SIGMA_ACCEL="-M 2 -H 4 -A 4" nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH -- cgit v1.2.3 From 43a94380032300a2e33e1faa1efe93e858e0a2cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:37:39 +0900 Subject: altos: Exit flight test at landing. Allow description in test flight list Signed-off-by: Keith Packard --- src/ao_flight_test.c | 77 +++++++++++++++++++++++++++------------------------- src/test/run-one | 3 +- src/test/run-tests | 2 +- 3 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 51a5965c..91aa0f73 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -130,7 +130,7 @@ int ao_flight_debug; FILE *emulator_in; char *emulator_app; char *emulator_name; -double emulator_error_max = 10; +double emulator_error_max = 4; void ao_dump_state(void); @@ -189,6 +189,33 @@ static double ao_test_max_height_time; static int ao_test_main_height; static double ao_test_main_height_time; +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", + drogue_height, drogue_time, main_height, main_time); + exit (1); + } + exit(0); +} + void ao_insert(void) { @@ -207,6 +234,16 @@ ao_insert(void) tick_offset += 65536; prev_tick = ao_adc_static.tick; time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + if (!ao_summary) { printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", time, @@ -219,44 +256,10 @@ ao_insert(void) drogue_height, main_height, ao_error_h_sq_avg); + if (ao_flight_state == ao_flight_landed) + ao_test_exit(); } - - if (ao_test_max_height < height) { - ao_test_max_height = height; - ao_test_max_height_time = time; - } - if (height > ao_config.main_deploy) { - ao_test_main_height_time = time; - ao_test_main_height = height; - } - } -} - -void -ao_test_exit(void) -{ - double drogue_error; - double main_error; - - if (!ao_test_main_height_time) { - ao_test_main_height_time = ao_test_max_height_time; - ao_test_main_height = ao_test_max_height; - } - drogue_error = fabs(ao_test_max_height_time - drogue_time); - main_error = fabs(ao_test_main_height_time - main_time); - if (drogue_error > emulator_error_max || main_error > emulator_error_max) { - printf ("%s %s\n", - emulator_app, emulator_name); - printf ("\tApogee error %g\n", drogue_error); - printf ("\tMain error %g\n", main_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", - ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", - drogue_height, drogue_time, main_height, main_time); - exit (1); } - exit(0); } void diff --git a/src/test/run-one b/src/test/run-one index d661abec..7d0f95ae 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -3,13 +3,14 @@ for i in "$@"; do ./ao_flight_test "$i" > run-out.full ./ao_flight_test_baro "$i" > run-out.baro -#./ao_flight_test_accel "$i" > run-out.accel +#./ao_flight_test_accel "$i" > run-out.accel #"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ #"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ #"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ #"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ #"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# gnuplot << EOF set ylabel "altitude (m)" diff --git a/src/test/run-tests b/src/test/run-tests index 11b4c95c..3e0cad3c 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -4,7 +4,7 @@ DIR=~/src/cc1111/flights bad_baro=0 bad_full=0 -while read flight; do +while read flight description; do if ./ao_flight_test_baro -s $DIR/$flight; then : else -- cgit v1.2.3 From 93040ef4d0bd90ec5ae052f22243cd56adfb300a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:40:05 +0900 Subject: Add ao_kalman.h to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 13c9b43d..0d36192c 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ src/Version src/ao_flight_test src/ao_gps_test src/ao_gps_test_skytraq +src/ao_kalman.h ao-teledongle.h ao-telemetrum.h ao-teleterra.h -- cgit v1.2.3 From 1e976a105423f2da1842f70da531c9051ba88a7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:42:31 +0900 Subject: Add description to test flights --- src/test/test-flights | 140 +++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/src/test/test-flights b/src/test/test-flights index 0b90d9e0..f6b3b992 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -1,70 +1,70 @@ -2009-06-03-serial-003-flight-002.eeprom -2009-06-05-serial-004-flight-008.eeprom -2009-06-06-serial-004-flight-009.eeprom -2009-06-14-serial-004-flight-010.eeprom -2009-06-20-serial-003-flight-003.eeprom -2009-07-04-serial-001-flight-006.eeprom -2009-07-18-serial-001-flight-007.eeprom -2009-08-22-serial-001-flight-001.eeprom -2009-08-22-serial-010-flight-001.eeprom -2009-09-05-serial-010-flight-002.eeprom -2009-09-05-serial-011-flight-001.eeprom -2009-09-11-serial-008-flight-003.eeprom -2009-09-12-serial-002-flight-002.eeprom -2009-09-12-serial-008-flight-005.eeprom -2009-09-12-serial-008-flight-007.eeprom -2009-09-19-serial-011-flight-002.eeprom -2009-10-03-serial-008-flight-009.eeprom -2009-10-03-serial-008-flight-010.eeprom -2009-10-03-serial-009-flight-001.eeprom -2009-10-03-serial-011-flight-003.eeprom -2009-10-17-serial-009-flight-002.eeprom -2009-11-14-serial-003-flight-005.eeprom -2009-11-14-serial-003-flight-006.eeprom -2009-11-21-serial-013-flight-001.eeprom -2009-11-21-serial-013-flight-002.eeprom -2010-02-13-serial-051-flight-002.eeprom -2010-02-13-serial-052-flight-002.eeprom -2010-02-28-serial-052-flight-003.eeprom -2010-02-28-serial-052-flight-004.eeprom -2010-03-06-serial-010-flight-004.eeprom -2010-03-06-serial-013-flight-003.eeprom -2010-03-06-serial-051-flight-003.eeprom -2010-03-06-serial-053-flight-004.eeprom -2010-05-08-serial-229-flight-002.eeprom -2010-05-28-serial-215-flight-002.eeprom -2010-05-28-serial-224-flight-001.eeprom -2010-05-29-serial-052-flight-005.eeprom -2010-05-30-serial-010-flight-005.eeprom -2010-05-30-serial-051-flight-004.eeprom -2010-05-30-serial-224-flight-003.eeprom -2010-05-30-serial-226-flight-001.eeprom -2010-05-31-serial-010-flight-006.eeprom -2010-05-31-serial-216-flight-001.eeprom -2010-05-31-serial-219-flight-001.eeprom -2010-05-31-serial-227-flight-003.eeprom -2010-06-05-serial-220-flight-001.eeprom -2010-06-26-serial-209-flight-003.eeprom -2010-06-26-serial-215-flight-004.eeprom -2010-06-26-serial-220-flight-002.eeprom -2010-06-26-serial-226-flight-002.eeprom -2010-06-27-serial-221-flight-002.eeprom -2010-07-17-serial-230-flight-001.eeprom -2010-07-18-serial-219-flight-002.eeprom -2010-08-07-serial-216-flight-003.eeprom -2010-08-07-serial-220-flight-003.eeprom -2010-08-12-serial-236-flight-001.eeprom -2010-08-21-serial-010-flight-007.eeprom -2010-08-21-serial-224-flight-004.eeprom -2010-08-21-serial-224-flight-005.eeprom -2010-08-21-serial-233-flight-002.eeprom -2010-09-03-serial-051-flight-005.eeprom -2010-09-03-serial-215-flight-005.eeprom -2010-09-24-serial-236-flight-006.eeprom -2010-09-25-serial-223-flight-001.eeprom -2010-10-17-serial-215-flight-006.eeprom -2011-01-30-serial-056-flight-001.eeprom -2011-01-30-serial-250-flight-002.eeprom -2011-02-19-serial-215-flight-007.eeprom -2011-02-19-serial-216-flight-006.eeprom -2011-02-19-serial-286-flight-001.eeprom +2009-06-03-serial-003-flight-002.eeprom PSAS flight on research motor.Lots of ugly bumps. +2009-06-05-serial-004-flight-008.eeprom Add June 2009 Lil Nuke flight +2009-06-06-serial-004-flight-009.eeprom Another Lil nuke flight? 700m, subsonic. +2009-06-14-serial-004-flight-010.eeprom Lil nuke flies again. 450m, subsonic. +2009-06-20-serial-003-flight-003.eeprom Transonic flight. 2100m, single deploy. +2009-07-04-serial-001-flight-006.eeprom Subsonic, 1100m, noisy descent. +2009-07-18-serial-001-flight-007.eeprom Transonic, 1900m, noisy descent. +2009-08-22-serial-001-flight-001.eeprom Transonic 2200m. noisy descent +2009-08-22-serial-010-flight-001.eeprom Subsonic, laggy baro. 400m +2009-09-05-serial-010-flight-002.eeprom Subsonic, fairly quick baro. 600m +2009-09-05-serial-011-flight-001.eeprom Subsonic, 1800m. Early Ejection confuses apogee detect. +2009-09-11-serial-008-flight-003.eeprom Subsonic, 200m, early ejection. +2009-09-12-serial-002-flight-002.eeprom Subsonic. 1200m. Very nice baro velocity +2009-09-12-serial-008-flight-005.eeprom Low flight. 220m, 100m/s. +2009-09-12-serial-008-flight-007.eeprom Model flight. +2009-09-19-serial-011-flight-002.eeprom Subsonic, but noisy baro. +2009-10-03-serial-008-flight-009.eeprom Transonic baro bump. 1600m. +2009-10-03-serial-008-flight-010.eeprom Barely transonic, but other baro bumps. +2009-10-03-serial-009-flight-001.eeprom Add Ofest ToT flight (drag race with Candy Cane). subsonic, but a bit of baro noise. +2009-10-03-serial-011-flight-003.eeprom Add Ofest G-spot flight. transonic bump, ugly looking data. +2009-10-17-serial-009-flight-002.eeprom Clean looking subsonic flight, small baro slump at max-Q +2009-11-14-serial-003-flight-005.eeprom Model flight. +2009-11-14-serial-003-flight-006.eeprom Model flight. +2009-11-21-serial-013-flight-001.eeprom ToT AMW J450ST with Jason Chamberlin strontium nitrate igniter +2009-11-21-serial-013-flight-002.eeprom ToT - CTI 1009J420CL pro38 6xl +2010-02-13-serial-051-flight-002.eeprom G-Spot at Albuquerque Rocket Society launch site in Rio Rancho, NM Cesaroni 229H255WT-14A +2010-02-13-serial-052-flight-002.eeprom Add Grappler flight at OROC February model launch +2010-02-28-serial-052-flight-003.eeprom LDDD Tillamook airport, 2010-02-28, H252 +2010-02-28-serial-052-flight-004.eeprom LDDD Tillamook airport, 2010-02-28, I161 +2010-03-06-serial-010-flight-004.eeprom Robert's Lil Nuke at Hudson Ranch on a CTI 108G57CL Pro29 +2010-03-06-serial-013-flight-003.eeprom Trick-O-Treat at Hudson Ranch on a J595BS +2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W +2010-03-06-serial-053-flight-004.eeprom Horizon Rebuilt at Hudson Ranch on a J530IM with MAWD as backup +2010-05-08-serial-229-flight-002.eeprom First customer flight on a sparky. +2010-05-28-serial-215-flight-002.eeprom Mike's L1 cert flight. Congrats! +2010-05-28-serial-224-flight-001.eeprom Bill Mott's amram +2010-05-29-serial-052-flight-005.eeprom LDDD on J335 at MHM +2010-05-30-serial-010-flight-005.eeprom Robert's Lil Nuke on a 84G88 Smoky Sam at Mile High Mayhem 2010 Version 0.1 TeleMetrum with 5010 GPS board. +2010-05-30-serial-051-flight-004.eeprom Bdale's G-Spot on a CTI 298H159 Green3 at Mile High Mayhem 2010 +2010-05-30-serial-224-flight-003.eeprom Bill Mott's L3 cert flight +2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee +2010-05-31-serial-010-flight-006.eeprom Robert's Lil Nuke with a v0.1 TeleMetrum and 5010 GPS board flying on a 159G118 Blue Streak on the last day of Mile High Mayhem 2010 +2010-05-31-serial-216-flight-001.eeprom Sharp Stick in the Sky on an "I something" EX motor from James Russell +2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. +2010-05-31-serial-227-flight-003.eeprom Mike's Rocket on J285 for successful L2 cert at MHM +2010-06-05-serial-220-flight-001.eeprom Mini-mmuchness on 159G54RL, Sunday at MHM 2010 +2010-06-26-serial-209-flight-003.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-220-flight-002.eeprom Mini Mmuchness on CTI H120CL to 1975m, OROC June 2010 +2010-06-26-serial-226-flight-002.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-27-serial-221-flight-002.eeprom PSAS LV2c on N2000 at OROC june launch +2010-07-17-serial-230-flight-001.eeprom Mike Ward's Level 1 cert flight on H225 +2010-07-18-serial-219-flight-002.eeprom MMuchness on M1230 for successful L3 cert flight +2010-08-07-serial-216-flight-003.eeprom Sharp stick on I300T at Metra's august launch. Main out at apogee. +2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. +2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 +2010-08-21-serial-010-flight-007.eeprom Robert's Lil Nuke, flying on a CTI Pro29 2-grain 110G250 Vmax. Just awesome! PFND. +2010-08-21-serial-224-flight-004.eeprom Anthony Towns' LDDD clone, successful L1 cert on a CTI Pro38 2-grain 266H125 classic. Airframe was set up for apogee-only with motor based ejection. The BP charge was larger than necessary, caused nose cone to snap back against aft airframe. Minor damage to leading edge of aft airframe, big chunk of the nose cone skin cracked away. Same problem Bdale saw on Sharp Stick's nosecone, also from Performance Rocketry, where there was apparently an air bubble below the gel coat. Determination was that damage was cosmetic and would not affect cert... confirmed by successful L2 later in the day! +2010-08-21-serial-224-flight-005.eeprom Anthony Towns' LDDD clone, successful L2 cert on a CTI Pro38 5-grain 58J357 blue streak. Perfect drogueless dual deploy! 0.8-0.9 grams aft charge and about 1.0 grams forward. Flew without ground testing charges due to time pressure before waiver closed for the day. About as close to the waiver as you'd ever want to be on a cert flight, again demonstrating that OpenRocket under-estimates apogee ... approximately 6800 ft predicted... +2010-08-21-serial-233-flight-002.eeprom Tim van Milligan's 5.5" L2 airframe, flying on a CTI Pro38 6-grain 774J410 red, TM indicated a problem with the apogee igniter continuity, noticed during countdown, turned out to be a loose wire! Perfect dual deploy flight once that was fixed. +2010-09-03-serial-051-flight-005.eeprom G-spot on an old Aerotech H125-20W single use 29mm motor. It appears the ejection at apogee actually happened much later, perhaps as much as 10 seconds late! +2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. +2010-09-24-serial-236-flight-006.eeprom LDDD on I236 in Sheridan on 2010-09-24 to 1216m +2010-09-25-serial-223-flight-001.eeprom Bdale's 10" Goblin, flying on a CTI Pro75 M1300 Imax dual thrust during Chili Blaster 2 at Hudson Ranch. First flight after rebuild to do dual deploy from one bay with ARRD and 15' surplus "+ sign" parachute. +2010-10-17-serial-215-flight-006.eeprom Horizon Rebuild on CTI J595BS at Tripoli Colorado launch site near Hartsel, CO +2011-01-30-serial-056-flight-001.eeprom Group project 5.5" Polecat Thumper airframe built in the Quay West Suites in Brisbane, Australia, during LCA 2011 by Bdale, Keith, Mike Beattie, and Anthony Towns. Flown at QRS club launch on an Aerotech J315R 54mm 2-grain motor. +2011-01-30-serial-250-flight-002.eeprom Group project 5.5" Polecat Thumper airframe built in the Quay West Suites in Brisbane, Australia, during LCA 2011 by Bdale, Keith, Mike Beattie, and Anthony Towns. Flown at QRS club launch on an Aerotech J315R 54mm 2-grain motor. +2011-02-19-serial-215-flight-007.eeprom Horizon Rebuild on a CTI Pro38 6xl J600R at Hudson Ranch 1.0 grams BP rear, 1.5 grams front Perfect drogueless dual deploy flight with no damage! +2011-02-19-serial-216-flight-006.eeprom Sharp Stick on a CTI Pro38 3-grain I345WT at Hudson Ranch Added more kevlar to the aft end, flew with 1.3 grams BP rear and 1.0 front. Perfect drogueless dual deploy flight, and no damage! +2011-02-19-serial-286-flight-001.eeprom Vertical Assault on a CTI Pro38 6xl J595BS at Hudson Ranch 1.5 grams BP rear, 1.8 grams BP front Perfect drogueless dual deploy flight, with no damage! -- cgit v1.2.3 From f3e68341f6f5daaf26dd162e4f9a06c29988986a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Mar 2011 05:27:57 +0900 Subject: altosui: Add support for telemetry version 4 New telemetry format needed to support TeleNano and TeleMini Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 21 ++- altosui/AltosCSV.java | 29 ++-- altosui/AltosDataPointReader.java | 2 + altosui/AltosDescent.java | 57 +++++++- altosui/AltosFlightUI.java | 23 +++- altosui/AltosGPS.java | 47 ++++++- altosui/AltosLanded.java | 31 ++++- altosui/AltosPad.java | 41 +++++- altosui/AltosRecord.java | 83 +++++++++-- altosui/AltosSiteMap.java | 2 - altosui/AltosState.java | 15 +- altosui/AltosTelemetry.java | 267 +++++++++++++++++++++++++++++++++--- altosui/AltosTelemetryIterable.java | 1 - altosui/AltosUI.java | 2 +- altosui/Makefile.am | 1 + src/ao_telem.h | 8 +- 16 files changed, 550 insertions(+), 80 deletions(-) diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 64bdcf30..0fbc5de2 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -87,6 +87,16 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { void reset() { value.setText(""); } + + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } public AscentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -247,6 +257,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lat extends AscentValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lat,"N", "S")); else @@ -261,6 +272,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lon extends AscentValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lon,"E", "W")); else @@ -284,8 +296,13 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + lat.hide(); + lon.hide(); + } height.show(state, crc_errors); main.show(state, crc_errors); apogee.show(state, crc_errors); diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index df98b2b4..5277c160 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -60,7 +60,7 @@ public class AltosCSV implements AltosWriter { * drogue (V) * main (V) * - * GPS data + * GPS data (if available) * connected (1/0) * locked (1/0) * nsat (used for solution) @@ -179,12 +179,14 @@ public class AltosCSV implements AltosWriter { } } - void write_header() { + void write_header(boolean gps) { out.printf("#"); write_general_header(); out.printf(","); write_flight_header(); out.printf(","); write_basic_header(); - out.printf(","); write_gps_header(); - out.printf(","); write_gps_sat_header(); + if (gps) { + out.printf(","); write_gps_header(); + out.printf(","); write_gps_sat_header(); + } out.printf ("\n"); } @@ -192,9 +194,12 @@ public class AltosCSV implements AltosWriter { 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(","); - write_gps_sat(record); + write_basic(record); + if (record.gps != null) { + out.printf(","); + write_gps(record); out.printf(","); + write_gps_sat(record); + } out.printf ("\n"); } @@ -206,7 +211,7 @@ public class AltosCSV implements AltosWriter { public void write(AltosRecord record) { if (!header_written) { - write_header(); + write_header(record.gps != null); header_written = true; } if (!seen_boost) { @@ -240,12 +245,16 @@ public class AltosCSV implements AltosWriter { write(r); } - public AltosCSV(File in_name) throws FileNotFoundException { + public AltosCSV(PrintStream in_out, File in_name) { name = in_name; - out = new PrintStream(name); + out = in_out; pad_records = new LinkedList(); } + public AltosCSV(File in_name) throws FileNotFoundException { + this(new PrintStream(in_name), in_name); + } + public AltosCSV(String in_string) throws FileNotFoundException { this(new File(in_string)); } diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index 7704310b..ee57d2ce 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -15,6 +15,8 @@ class AltosDataPointReader implements Iterable { AltosState state; AltosRecord record; + final static int MISSING = AltosRecord.MISSING; + public AltosDataPointReader(Iterable reader) { this.iter = reader.iterator(); this.state = null; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 16ccd458..594a7a09 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -37,6 +37,19 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { AltosLights lights; abstract void show(AltosState state, int crc_errors); + + void show() { + label.show(); + value.show(); + lights.show(); + } + + void hide() { + label.hide(); + value.hide(); + lights.hide(); + } + void reset() { value.setText(""); lights.set(false); @@ -90,6 +103,16 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { abstract void show(AltosState state, int crc_errors); + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void show(String format, double v) { value.setText(String.format(format, v)); } @@ -134,12 +157,27 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2.setText(""); } + void show() { + label.show(); + value1.show(); + value2.show(); + } + + void hide() { + label.hide(); + value1.hide(); + value2.hide(); + } + abstract void show(AltosState state, int crc_errors); + void show(String v1, String v2) { + show(); value1.setText(v1); value2.setText(v2); } void show(String f1, double v1, String f2, double v2) { + show(); value1.setText(String.format(f1, v1)); value2.setText(String.format(f2, v2)); } @@ -260,6 +298,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Main extends DescentStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.main_sense)); lights.set(state.main_sense > 3.2); } @@ -324,11 +363,19 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { height.show(state, crc_errors); speed.show(state, crc_errors); - bearing.show(state, crc_errors); - range.show(state, crc_errors); - elevation.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + bearing.show(state, crc_errors); + range.show(state, crc_errors); + elevation.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + bearing.hide(); + range.hide(); + elevation.hide(); + lat.hide(); + lon.hide(); + } main.show(state, crc_errors); apogee.show(state, crc_errors); } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 7fcfb8be..68e0ef87 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -29,9 +29,6 @@ import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; public class AltosFlightUI extends JFrame implements AltosFlightDisplay { - String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; - Object[][] statusData = { { "0", "pad", "-50", "0" } }; - AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; @@ -43,6 +40,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosDescent descent; AltosLanded landed; AltosSiteMap sitemap; + boolean has_map; private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; @@ -85,6 +83,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { JComponent tab = which_tab(state); + try { pad.show(state, crc_errors); ascent.show(state, crc_errors); descent.show(state, crc_errors); @@ -97,7 +96,21 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } flightStatus.show(state, crc_errors); flightInfo.show(state, crc_errors); - sitemap.show(state, crc_errors); + if (state.gps != null) { + if (!has_map) { + pane.add("Site Map", sitemap); + has_map = true; + } + sitemap.show(state, crc_errors); + } else { + if (has_map) { + pane.remove(sitemap); + has_map = false; + } + } + } catch (Exception e) { + System.out.print("Show exception" + e); + } } public void set_exit_on_close() { @@ -169,7 +182,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Table", new JScrollPane(flightInfo)); sitemap = new AltosSiteMap(); - pane.add("Site Map", sitemap); + has_map = false; /* Make the tabbed pane use the rest of the window space */ c.gridx = 0; diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java index 83821842..0dbc8364 100644 --- a/altosui/AltosGPS.java +++ b/altosui/AltosGPS.java @@ -26,10 +26,11 @@ public class AltosGPS { int c_n0; } + final static int MISSING = AltosRecord.MISSING; + int nsat; boolean locked; boolean connected; - boolean date_valid; double lat; /* degrees (+N -S) */ double lon; /* degrees (+E -W) */ int alt; /* m */ @@ -40,11 +41,11 @@ public class AltosGPS { int minute; int second; - int gps_extended; /* has extra data */ double ground_speed; /* m/s */ int course; /* degrees */ double climb_rate; /* m/s */ - double hdop; /* unitless? */ + double hdop; /* unitless */ + double vdop; /* unitless */ int h_error; /* m */ int v_error; /* m */ @@ -73,6 +74,44 @@ public class AltosGPS { hour = minute = second = 0; } + public AltosGPS(AltosTelemetryMap map) throws ParseException { + String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, + AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); + + nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); + if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { + connected = true; + locked = true; + lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); + lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); + alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); + year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); + if (year != MISSING) + year += 2000; + month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); + day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); + + hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); + minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); + second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); + + ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, + AltosRecord.MISSING, 1/100.0); + course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, + AltosRecord.MISSING); + hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); + vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); + h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); + v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); + } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { + connected = true; + locked = false; + } else { + connected = false; + locked = false; + } + } + public AltosGPS(String[] words, int i, int version) throws ParseException { AltosParse.word(words[i++], "GPS"); nsat = AltosParse.parse_int(words[i++]); @@ -184,7 +223,6 @@ public class AltosGPS { 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 */ @@ -195,7 +233,6 @@ public class AltosGPS { minute = old.minute; second = old.second; - gps_extended = old.gps_extended; /* has extra data */ ground_speed = old.ground_speed; /* m/s */ course = old.course; /* degrees */ climb_rate = old.climb_rate; /* m/s */ diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index d34efe6d..0717ffe2 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -42,10 +42,22 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { value.setText(""); } + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void show(String format, double v) { + show(); value.setText(String.format(format, v)); } + public LandedValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -86,6 +98,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lat extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lat,"N", "S")); else @@ -100,6 +113,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lon extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lon,"E", "W")); else @@ -114,6 +128,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Bearing extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.from_pad != null) show("%3.0f°", state.from_pad.bearing); else @@ -128,6 +143,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Distance extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.from_pad != null) show("%6.0f m", state.from_pad.distance); else @@ -184,10 +200,17 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - bearing.show(state, crc_errors); - distance.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + bearing.show(state, crc_errors); + distance.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + bearing.hide(); + distance.hide(); + lat.hide(); + lon.hide(); + } height.show(state, crc_errors); speed.show(state, crc_errors); accel.show(state, crc_errors); diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index e345e5da..2f59e879 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -42,6 +42,18 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { lights.set(false); } + public void show() { + label.show(); + value.show(); + lights.show(); + } + + public void hide() { + label.hide(); + value.hide(); + lights.hide(); + } + public LaunchStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -83,6 +95,16 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { JTextField value; void show(AltosState state, int crc_errors) {} + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void reset() { value.setText(""); } @@ -151,6 +173,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class GPSLocked extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4d sats", state.gps.nsat)); lights.set(state.gps.locked && state.gps.nsat >= 4); } @@ -163,6 +186,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class GPSReady extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); if (state.gps_ready) value.setText("Ready"); else @@ -189,6 +213,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLat extends LaunchValue { void show (AltosState state, int crc_errors) { + show(); value.setText(pos(state.pad_lat,"N", "S")); } public PadLat (GridBagLayout layout, int y) { @@ -200,6 +225,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLon extends LaunchValue { void show (AltosState state, int crc_errors) { + show(); value.setText(pos(state.pad_lon,"E", "W")); } public PadLon (GridBagLayout layout, int y) { @@ -235,11 +261,18 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery.show(state, crc_errors); apogee.show(state, crc_errors); main.show(state, crc_errors); - gps_locked.show(state, crc_errors); - gps_ready.show(state, crc_errors); - pad_lat.show(state, crc_errors); - pad_lon.show(state, crc_errors); pad_alt.show(state, crc_errors); + if (state.gps != null) { + gps_locked.show(state, crc_errors); + gps_ready.show(state, crc_errors); + pad_lat.show(state, crc_errors); + pad_lon.show(state, crc_errors); + } else { + gps_locked.hide(); + gps_ready.hide(); + pad_lat.hide(); + pad_lon.hide(); + } } public AltosPad() { diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 1160a273..46e96b95 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -23,6 +23,8 @@ import java.util.HashMap; import java.io.*; public class AltosRecord { + final static int MISSING = 0x7fffffff; + int version; String callsign; int serial; @@ -31,19 +33,27 @@ public class AltosRecord { int status; int state; int tick; + int accel; int pres; int temp; int batt; int drogue; int main; - int flight_accel; + int ground_accel; - int flight_vel; - int flight_pres; int ground_pres; int accel_plus_g; int accel_minus_g; + + double acceleration; + double speed; + double height; + + int flight_accel; + int flight_vel; + int flight_pres; + AltosGPS gps; double time; /* seconds since boost */ @@ -72,46 +82,82 @@ public class AltosRecord { } public double raw_pressure() { + if (pres == MISSING) + return MISSING; return barometer_to_pressure(pres); } public double filtered_pressure() { + if (flight_pres == MISSING) + return MISSING; return barometer_to_pressure(flight_pres); } public double ground_pressure() { + if (ground_pres == MISSING) + return MISSING; return barometer_to_pressure(ground_pres); } - public double filtered_altitude() { - return AltosConvert.pressure_to_altitude(filtered_pressure()); - } - public double raw_altitude() { - return AltosConvert.pressure_to_altitude(raw_pressure()); + double p = raw_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); } public double ground_altitude() { - return AltosConvert.pressure_to_altitude(ground_pressure()); + double p = ground_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_altitude() { + if (height != MISSING && ground_pres != MISSING) + return height + ground_altitude(); + + double p = filtered_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); } public double filtered_height() { - return filtered_altitude() - ground_altitude(); + if (height != MISSING) + return height; + + double f = filtered_altitude(); + double g = ground_altitude(); + if (f == MISSING || g == MISSING) + return MISSING; + return f - g; } public double raw_height() { - return raw_altitude() - ground_altitude(); + double r = raw_altitude(); + double g = ground_altitude(); + + if (r == MISSING || g == MISSING) + return MISSING; + return r - g; } public double battery_voltage() { + if (batt == MISSING) + return MISSING; return AltosConvert.cc_battery_to_voltage(batt); } public double main_voltage() { + if (main == MISSING) + return MISSING; return AltosConvert.cc_ignitor_to_voltage(main); } public double drogue_voltage() { + if (drogue == MISSING) + return MISSING; return AltosConvert.cc_ignitor_to_voltage(drogue); } @@ -131,6 +177,8 @@ public class AltosRecord { } public double temperature() { + if (temp == MISSING) + return MISSING; return thermometer_to_temperature(temp); } @@ -139,13 +187,22 @@ public class AltosRecord { return counts_per_g / 9.80665; } + public double acceleration() { + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; return (ground_accel - accel) / accel_counts_per_mss(); } public double accel_speed() { - double speed = flight_vel / (accel_counts_per_mss() * 100.0); - return speed; + if (speed != MISSING) + return speed; + if (flight_vel == MISSING) + return MISSING; + return flight_vel / (accel_counts_per_mss() * 100.0); } public String state() { diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index d6bd6d1f..f4b6b7e0 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -228,8 +228,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { int last_state = -1; public void show(final AltosState state, final int crc_errors) { // if insufficient gps data, nothing to update - if (state.gps == null) - return; if (!state.gps.locked && state.gps.nsat < 4) return; diff --git a/altosui/AltosState.java b/altosui/AltosState.java index ec499d5a..4e165f80 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -79,7 +79,8 @@ public class AltosState { data = cur; ground_altitude = data.ground_altitude(); - height = data.filtered_altitude() - ground_altitude; + height = data.filtered_height(); + System.out.printf("height %g\n", height); report_time = System.currentTimeMillis(); @@ -114,10 +115,14 @@ public class AltosState { /* compute barometric speed */ double height_change = height - prev_state.height; - if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; + if (data.speed != AltosRecord.MISSING) + baro_speed = data.speed; + else { + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } } else { npad = 0; ngps = 0; diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index bdb6466a..3eb0efa8 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -27,10 +27,40 @@ import java.util.HashMap; /* - * The telemetry data stream is a bit of a mess at present, with no consistent - * formatting. In particular, the GPS data is formatted for viewing instead of parsing. - * However, the key feature is that every telemetry line contains all of the information - * necessary to describe the current rocket state, including the calibration values + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values * for accelerometer and barometer. * * GPS unlocked: @@ -47,25 +77,201 @@ import java.util.HashMap; * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * */ public class AltosTelemetry extends AltosRecord { - public AltosTelemetry(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ - 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++]); - } + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + private void parse_v4(String[] words, int i) throws ParseException { + AltosTelemetryMap map = new AltosTelemetryMap(words, i); + + callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + serial = map.get_int(AO_TELEM_SERIAL, MISSING); + flight = map.get_int(AO_TELEM_FLIGHT, MISSING); + rssi = map.get_int(AO_TELEM_RSSI, MISSING); + state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + tick = map.get_int(AO_TELEM_TICK, 0); + + /* raw sensor values */ + accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING); + pres = map.get_int(AO_TELEM_RAW_BARO, MISSING); + temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING); + batt = map.get_int(AO_TELEM_RAW_BATT, MISSING); + drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING); + main = map.get_int(AO_TELEM_RAW_MAIN, MISSING); + + /* sensor calibration information */ + ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING); + ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING); + accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING); + accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); + + /* flight computer values */ + acceleration = map.get_int(AO_TELEM_KALMAN_ACCEL, MISSING); + if (acceleration != MISSING) + acceleration /= 16.0; + speed = map.get_int(AO_TELEM_KALMAN_SPEED, MISSING); + if (speed != MISSING) + speed /= 16.0; + height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); + + flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); + flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); + flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); + + if (map.has(AO_TELEM_GPS_STATE)) + gps = new AltosGPS(map); + else + gps = null; + } + + private void parse_legacy(String[] words, int i) throws ParseException { AltosParse.word (words[i++], "CALL"); callsign = words[i++]; @@ -140,4 +346,27 @@ public class AltosTelemetry extends AltosRecord { gps = new AltosGPS(words, i, version); } + + public AltosTelemetry(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + 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++]); + } + + if (version < 4) + parse_legacy(words, i); + else + parse_v4(words, i); + } } diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index a71ab872..14b5f27f 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -63,7 +63,6 @@ public class AltosTelemetryIterable extends AltosRecordIterable { } catch (ParseException pe) { System.out.printf("parse exception %s\n", pe.getMessage()); } catch (AltosCRCException ce) { - System.out.printf("crc error\n"); } } } catch (IOException io) { diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 90e3d7f0..4d17b0d2 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -328,7 +328,7 @@ public class AltosUI extends JFrame { if (input.equals(output)) { System.out.printf("Not processing '%s'\n", input); } else { - AltosWriter writer = open_csv(output); + AltosWriter writer = open_csv("/dev/stdout"); if (writer != null) { writer.write(iterable); writer.close(); diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 288fca0e..49f34ce3 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -65,6 +65,7 @@ altosui_JAVA = \ AltosRecord.java \ AltosRecordIterable.java \ AltosTelemetryReader.java \ + AltosTelemetryMap.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ diff --git a/src/ao_telem.h b/src/ao_telem.h index b1624fe0..1a8da291 100644 --- a/src/ao_telem.h +++ b/src/ao_telem.h @@ -108,7 +108,7 @@ * GPS values * * Name Value - * g_s GPS state (string): + * g GPS state (string): * l locked * u unlocked * e error (missing or broken) @@ -123,7 +123,7 @@ * g_m GPS minute (integer - 0-59) * g_s GPS second (integer - 0-59) * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) + * g_g GPS horizontal speed (integer, cm/sec) * g_c GPS course (integer, 0-359) * g_hd GPS hdop (integer * 10) * g_vd GPS vdop (integer * 10) @@ -131,7 +131,7 @@ * g_ve GPS v error (integer) */ -#define AO_TELEM_GPS_STATE "g_s" +#define AO_TELEM_GPS_STATE "g" #define AO_TELEM_GPS_STATE_LOCKED 'l' #define AO_TELEM_GPS_STATE_UNLOCKED 'u' #define AO_TELEM_GPS_STATE_ERROR 'e' @@ -146,7 +146,7 @@ #define AO_TELEM_GPS_MINUTE "g_m" #define AO_TELEM_GPS_SECOND "g_s" #define AO_TELEM_GPS_VERTICAL_SPEED "g_v" -#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_s" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" #define AO_TELEM_GPS_COURSE "g_c" #define AO_TELEM_GPS_HDOP "g_hd" #define AO_TELEM_GPS_VDOP "g_vd" -- cgit v1.2.3 From 7f5b5848ad6ef5c808638a29c3dc0101b56ed11e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Mar 2011 08:08:43 +0900 Subject: altosui: Add telemetry format menu and preferences Switches the TeleDongle between full and tiny telemetry packet formats, saving the last used format for each teledongle in the application preferences. Signed-off-by: Keith Packard --- altosui/Altos.java | 5 +++++ altosui/AltosFlightReader.java | 2 ++ altosui/AltosFlightUI.java | 24 ++++++++++++++++++++++++ altosui/AltosPreferences.java | 25 +++++++++++++++++++++++++ altosui/AltosSerial.java | 23 +++++++++++++++++++---- altosui/AltosState.java | 1 - altosui/AltosTelemetry.java | 8 ++------ altosui/AltosTelemetryReader.java | 5 +++++ 8 files changed, 82 insertions(+), 11 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 8ee94e04..9d5b2e02 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -63,6 +63,11 @@ public class Altos { static final int ao_flight_landed = 8; static final int ao_flight_invalid = 9; + /* Telemetry modes */ + static final int ao_telemetry_off = 0; + static final int ao_telemetry_full = 1; + static final int ao_telemetry_tiny = 2; + static HashMap string_to_state = new HashMap(); static boolean map_initialized = false; diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java index 3d59de9a..f665bda8 100644 --- a/altosui/AltosFlightReader.java +++ b/altosui/AltosFlightReader.java @@ -34,5 +34,7 @@ public class AltosFlightReader { void set_channel(int channel) { } + void set_telemetry(int telemetry) { } + void update(AltosState state) throws InterruptedException { } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 68e0ef87..286b2a4e 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -119,6 +119,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { Container bag; JComboBox channels; + JComboBox telemetries; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { AltosPreferences.init(this); @@ -149,8 +150,28 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { }); c.gridx = 0; c.gridy = 0; + c.insets = new Insets(3, 3, 3, 3); c.anchor = GridBagConstraints.WEST; bag.add (channels, c); + + // Telemetry format menu + telemetries = new JComboBox(); + telemetries.addItem("TeleMetrum"); + telemetries.addItem("TeleMini/TeleNano"); + telemetries.setSelectedIndex(AltosPreferences.telemetry(serial) - 1); + telemetries.setMaximumRowCount(2); + telemetries.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int telemetry = telemetries.getSelectedIndex(); + reader.set_telemetry(telemetry); + } + }); + c.gridx = 1; + c.gridy = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + bag.add (telemetries, c); + c.insets = new Insets(0, 0, 0, 0); } /* Flight status is always visible */ @@ -159,7 +180,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { c.gridy = 1; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; + c.gridwidth = 2; bag.add(flightStatus, c); + c.gridwidth = 1; /* The rest of the window uses a tabbed pane to * show one of the alternate data views @@ -190,6 +213,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { c.fill = GridBagConstraints.BOTH; c.weightx = 1; c.weighty = 1; + c.gridwidth = 2; bag.add(pane, c); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index d4df4e16..5f827655 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -34,6 +34,9 @@ class AltosPreferences { /* channel preference name */ final static String channelPreferenceFormat = "CHANNEL-%d"; + /* telemetry format preference name */ + final static String telemetryPreferenceFormat = "TELEMETRY-%d"; + /* voice preference name */ final static String voicePreference = "VOICE"; @@ -61,6 +64,9 @@ class AltosPreferences { /* Channel (map serial to channel) */ static Hashtable channels; + /* Telemetry (map serial to telemetry format) */ + static Hashtable telemetries; + /* Voice preference */ static boolean voice; @@ -94,6 +100,8 @@ class AltosPreferences { channels = new Hashtable(); + telemetries = new Hashtable(); + voice = preferences.getBoolean(voicePreference, true); callsign = preferences.get(callsignPreference,"N0CALL"); @@ -189,6 +197,23 @@ class AltosPreferences { return channel; } + public static void set_telemetry(int serial, int new_telemetry) { + telemetries.put(serial, new_telemetry); + synchronized (preferences) { + preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); + flush_preferences(); + } + } + + public static int telemetry(int serial) { + if (telemetries.containsKey(serial)) + return telemetries.get(serial); + int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), + Altos.ao_telemetry_full); + telemetries.put(serial, telemetry); + return telemetry; + } + public static void set_voice(boolean new_voice) { voice = new_voice; synchronized (preferences) { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index f9f9e6e4..a8ba66bd 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -47,6 +47,8 @@ public class AltosSerial implements Runnable { byte[] line_bytes; int line_count; boolean monitor_mode; + int telemetry; + int channel; static boolean debug; boolean remote; LinkedList pending_output = new LinkedList(); @@ -231,25 +233,37 @@ public class AltosSerial implements Runnable { } public void set_radio() { - set_channel(AltosPreferences.channel(device.getSerial())); + telemetry = AltosPreferences.telemetry(device.getSerial()); + channel = AltosPreferences.channel(device.getSerial()); + set_channel(channel); set_callsign(AltosPreferences.callsign()); } - public void set_channel(int channel) { + public void set_channel(int in_channel) { + channel = in_channel; if (altos != null) { if (monitor_mode) - printf("m 0\nc r %d\nm 1\n", channel); + printf("m 0\nc r %d\nm %d\n", channel, telemetry); else printf("c r %d\n", channel); flush_output(); } } + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + if (altos != null) { + if (monitor_mode) + printf("m 0\nm %d\n", telemetry); + flush_output(); + } + } + void set_monitor(boolean monitor) { monitor_mode = monitor; if (altos != null) { if (monitor) - printf("m 1\n"); + printf("m %d\n", telemetry); else printf("m 0\n"); flush_output(); @@ -285,6 +299,7 @@ public class AltosSerial implements Runnable { device = in_device; line = ""; monitor_mode = false; + telemetry = Altos.ao_telemetry_full; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); open(); diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 4e165f80..0ff2479e 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -80,7 +80,6 @@ public class AltosState { ground_altitude = data.ground_altitude(); height = data.filtered_height(); - System.out.printf("height %g\n", height); report_time = System.currentTimeMillis(); diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index 3eb0efa8..91b6d048 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -253,12 +253,8 @@ public class AltosTelemetry extends AltosRecord { accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); /* flight computer values */ - acceleration = map.get_int(AO_TELEM_KALMAN_ACCEL, MISSING); - if (acceleration != MISSING) - acceleration /= 16.0; - speed = map.get_int(AO_TELEM_KALMAN_SPEED, MISSING); - if (speed != MISSING) - speed /= 16.0; + acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, MISSING, 1/16.0); + speed = map.get_double(AO_TELEM_KALMAN_SPEED, MISSING, 1/16.0); height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 6c5a9397..980391b4 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -47,6 +47,11 @@ class AltosTelemetryReader extends AltosFlightReader { AltosPreferences.set_channel(device.getSerial(), channel); } + void set_telemetry(int telemetry) { + serial.set_telemetry(telemetry); + AltosPreferences.set_telemetry(device.getSerial(), telemetry); + } + public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException, IOException { device = in_device; -- cgit v1.2.3 From dea80af81b388cc3d7073444919f4e98b12fa730 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Mar 2011 21:29:50 -0700 Subject: altosui: Remove a bunch of debug printfs from the eeprom manager code Just noise on stdout. Signed-off-by: Keith Packard --- altosui/AltosEepromDelete.java | 3 --- altosui/AltosEepromList.java | 7 ------- altosui/AltosEepromLog.java | 7 ------- altosui/AltosEepromManage.java | 1 - altosui/AltosEepromSelect.java | 3 --- 5 files changed, 21 deletions(-) diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index c95eda15..ecd82c18 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -49,11 +49,9 @@ public class AltosEepromDelete implements Runnable { */ serial_line.flush_input(); serial_line.printf("d %d\n", log.flight); - System.out.printf("Attempt to delete flight %d\n", log.flight); for (;;) { /* It can take a while to erase the flash... */ String line = serial_line.get_reply(20000); - System.out.printf("got back line %s\n", line); if (line == null) throw new TimeoutException(); if (line.equals("Erased")) @@ -96,7 +94,6 @@ public class AltosEepromDelete implements Runnable { DeleteLog(log); } } - System.out.printf("All flights successfully deleted\n"); success = true; } catch (IOException ee) { show_error (ee.getLocalizedMessage(), diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index a932dd12..575c0bc2 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -83,7 +83,6 @@ public class AltosEepromList extends ArrayList { if (line.contains("Syntax")) continue; String[] tokens = line.split("\\s+"); - System.out.printf("got line %s (%d tokens)\n", line, tokens.length); if (tokens.length < 6) break; @@ -95,7 +94,6 @@ public class AltosEepromList extends ArrayList { start = AltosParse.parse_hex(tokens[3]); if (tokens[4].equals("end")) end = AltosParse.parse_hex(tokens[5]); - System.out.printf("parsed flight %d %x %x\n", flight, start, end); if (flight > 0 && start >= 0 && end > 0) flights.add(new AltosEepromFlight(flight, start, end)); } catch (ParseException pe) { System.out.printf("Parse error %s\n", pe.toString()); } @@ -115,7 +113,6 @@ public class AltosEepromList extends ArrayList { * firmware, this will also extract the flight number. */ for (AltosEepromFlight flight : flights) { - System.out.printf("Scanning flight %d %x %x\n", flight.flight, flight.start, flight.end); add(new AltosEepromLog(serial_line, config_data.serial, flight.start, flight.end)); } @@ -124,9 +121,5 @@ public class AltosEepromList extends ArrayList { serial_line.stop_remote(); serial_line.flush_output(); } - for (int i = 0; i < size(); i++) { - AltosEepromLog l = get(i); - System.out.printf("Found flight %d at %x - %x\n", l.flight, l.start_block, l.end_block); - } } } \ No newline at end of file diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index f284f103..10befad4 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -103,12 +103,5 @@ public class AltosEepromLog { if (has_gps && has_flight) break; } - System.out.printf("Serial %d start block %d end block %d\n", - serial, start_block, end_block); - if (has_flight) - System.out.printf("Flight %d\n", flight); - if (has_gps) - System.out.printf("%d-%d-%d %d:%02d:%02d Lat %f Lon %f\n", - year, month, day, hour, minute, second, lat, lon); } } diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index d10f7954..b12d95fa 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -69,7 +69,6 @@ public class AltosEepromManage implements ActionListener { boolean success = e.getID() != 0; boolean running = false; - System.out.printf("Eeprom manager action %s %d\n", cmd, e.getID()); if (cmd.equals("download")) { if (success) { if (any_delete) { diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index a3069f06..cb71524d 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -35,13 +35,10 @@ class AltosEepromItem implements ActionListener { JCheckBox delete; public void actionPerformed(ActionEvent e) { - System.out.printf("eeprom item action %s %d\n", e.getActionCommand(), e.getID()); if (e.getSource() == download) { log.download = download.isSelected(); - System.out.printf("download for flight %d set to %b\n", log.flight, log.download); } else if (e.getSource() == delete) { log.delete = delete.isSelected(); - System.out.printf("delete for flight %d set to %b\n", log.flight, log.delete); } } -- cgit v1.2.3 From 011615d40b3cb1d1c0ab9fa41e139e263a6a51e7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Mar 2011 21:34:31 -0700 Subject: altosui: Add support for downloading TeleMini/TeleNano flight logs Splits the eeprom downloading code into eeprom block downloading and separate eeprom data parsing so that the new data logging format can share the data downloading code. Signed-off-by: Keith Packard --- altosui/Altos.java | 1 + altosui/AltosEepromBlock.java | 7 +- altosui/AltosEepromChunk.java | 88 ++++++++++++++++++++++ altosui/AltosEepromDownload.java | 153 +++++++++++++++++++++++++++++---------- altosui/AltosEepromIterable.java | 5 +- altosui/AltosEepromLog.java | 11 ++- altosui/AltosEepromRecord.java | 45 +++++------- altosui/Makefile.am | 1 + 8 files changed, 239 insertions(+), 72 deletions(-) create mode 100644 altosui/AltosEepromChunk.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 9d5b2e02..3ef4d799 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -34,6 +34,7 @@ public class Altos { static final int AO_LOG_GPS_ALT = 'H'; static final int AO_LOG_GPS_SAT = 'V'; static final int AO_LOG_GPS_DATE = 'Y'; + static final int AO_LOG_HEIGHT = 'h'; /* Added for header fields in eeprom files */ static final int AO_LOG_CONFIG_VERSION = 1000; diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java index d59fd39e..650920d1 100644 --- a/altosui/AltosEepromBlock.java +++ b/altosui/AltosEepromBlock.java @@ -46,7 +46,7 @@ public class AltosEepromBlock extends ArrayList { int hour, minute, second; ParseException parse_exception = null; - public AltosEepromBlock (AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { + public AltosEepromBlock (AltosEepromChunk chunk) { int addr; boolean done = false; @@ -56,10 +56,9 @@ public class AltosEepromBlock extends ArrayList { has_lat = false; has_lon = false; has_time = false; - serial_line.printf("e %x\n", block); - for (addr = 0; addr < 0x100;) { + for (addr = 0; addr < chunk.chunk_size;) { try { - AltosEepromRecord r = new AltosEepromRecord(serial_line, block * 256 + addr); + AltosEepromRecord r = new AltosEepromRecord(chunk, addr); if (r.cmd == Altos.AO_LOG_FLIGHT) { flight = r.b; diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java new file mode 100644 index 00000000..8eec407d --- /dev/null +++ b/altosui/AltosEepromChunk.java @@ -0,0 +1,88 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import java.util.concurrent.*; + +public class AltosEepromChunk { + + static final int chunk_size = 256; + static final int per_line = 8; + + public int data[]; + public int address; + public ParseException parse_exception = null; + + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + int data(int offset) { + return data[offset]; + } + + int data16(int offset) { + return data[offset] | (data[offset + 1] << 8); + } + + public AltosEepromChunk(AltosSerial serial_line, int block) + throws TimeoutException, InterruptedException { + + int offset; + + data = new int[chunk_size]; + address = block * chunk_size; + serial_line.printf("e %x\n", block); + + for (offset = 0; offset < chunk_size; offset += per_line) { + try { + String line = serial_line.get_reply(5000); + + if (line == null) + throw new TimeoutException(); + + int[] values = ParseHex(line); + + if (values == null || values.length != per_line + 1) + throw new ParseException(String.format("invalid line %s", line), 0); + if (values[0] != offset) + throw new ParseException(String.format("data address out of sync at 0x%x", + address + offset), 0); + for (int i = 0; i < per_line; i++) + data[offset + i] = values[1 + i]; + } catch (ParseException pe) { + for (int i = 0; i < per_line; i++) + data[offset + i] = 0xff; + if (parse_exception == null) + parse_exception = pe; + } + } + } +} \ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 1da94a67..f96a3dc9 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -78,11 +78,105 @@ public class AltosEepromDownload implements Runnable { } } + void Log(AltosEepromRecord r) throws IOException { + if (r.cmd != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %4x %4x\n", + r.cmd, r.tick, r.a, r.b); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + } + } + + static final int log_full = 1; + static final int log_tiny = 2; + + boolean done; + int state; + + void CaptureFull(AltosEepromChunk eechunk) throws IOException { + AltosEepromBlock eeblock = new AltosEepromBlock(eechunk); + + if (eeblock.has_flight) { + flight = eeblock.flight; + monitor.set_flight(flight); + } + if (eeblock.has_date) { + year = eeblock.year; + month = eeblock.month; + day = eeblock.day; + want_file = true; + } + + if (eeblock.size() == 0 || + eeblock.has_state && eeblock.state == Altos.ao_flight_landed) + done = true; + + /* Monitor state transitions to update display */ + if (eeblock.has_state) { + if (eeblock.state > Altos.ao_flight_pad) + want_file = true; + if (eeblock.state > state) + state = eeblock.state; + } + + if (parse_exception == null && eeblock.parse_exception != null) + parse_exception = eeblock.parse_exception; + + CheckFile(false); + + for (int record = 0; record < eeblock.size(); record++) + Log(eeblock.get(record)); + } + + boolean start; + int tiny_tick; + + void CaptureTiny (AltosEepromChunk eechunk) throws IOException { + boolean some_reasonable_data = false; + + for (int i = 0; i < eechunk.data.length; i += 2) { + int v = eechunk.data16(i); + + if (i == 0 && start) { + tiny_tick = 0; + start = false; + flight = v; + Log(new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v)); + some_reasonable_data = true; + } else { + int s = v ^ 0x8000; + if (Altos.ao_flight_startup <= s && s <= Altos.ao_flight_invalid) { + Log(new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0)); + if (s == Altos.ao_flight_landed) { + done = true; + break; + } + some_reasonable_data = true; + } else { + if (v != 0xffff) + some_reasonable_data = true; + Log(new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0)); + if (state < Altos.ao_flight_drogue) + tiny_tick += 10; + else + tiny_tick += 100; + } + } + } + CheckFile(false); + if (!some_reasonable_data) + done = true; + } + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; - int state = 0; - boolean done = false; - int record; + int log_style = 0; + + state = 0; + done = false; + start = true; if (flights.config_data.serial == 0) throw new IOException("no serial number found"); @@ -104,47 +198,26 @@ public class AltosEepromDownload implements Runnable { for (block = log.start_block; !done && block < log.end_block; block++) { monitor.set_value(Altos.state_to_string[state], state, block - state_block); - AltosEepromBlock eeblock = new AltosEepromBlock(serial_line, block); + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); - if (eeblock.has_flight) { - flight = eeblock.flight; - monitor.set_flight(flight); - } - if (eeblock.has_date) { - year = eeblock.year; - month = eeblock.month; - day = eeblock.day; - want_file = true; - } + /* + * Figure out what kind of data is there + */ - if (eeblock.size() == 0 || - eeblock.has_state && eeblock.state == Altos.ao_flight_landed) - done = true; - - /* Monitor state transitions to update display */ - if (eeblock.has_state) { - if (eeblock.state > Altos.ao_flight_pad) - want_file = true; - if (eeblock.state > state) - state = eeblock.state; + if (block == log.start_block) { + if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) + log_style = log_full; + else + log_style = log_tiny; } - if (parse_exception == null && eeblock.parse_exception != null) - parse_exception = eeblock.parse_exception; - - CheckFile(false); - - for (record = 0; record < eeblock.size(); record++) { - AltosEepromRecord r = eeblock.get(record); - - if (r.cmd != Altos.AO_LOG_INVALID) { - String log_line = String.format("%c %4x %4x %4x\n", - r.cmd, r.tick, r.a, r.b); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - } + switch (log_style) { + case log_full: + CaptureFull(eechunk); + break; + case log_tiny: + CaptureTiny(eechunk); + break; } } CheckFile(true); diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index f8e6d7e5..bb7c7bef 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -124,6 +124,10 @@ public class AltosEepromIterable extends AltosRecordIterable { } eeprom.seen |= seen_sensor; break; + case Altos.AO_LOG_HEIGHT: + state.height = record.a; + eeprom.seen |= seen_sensor; + break; case Altos.AO_LOG_TEMP_VOLT: state.temp = record.a; state.batt = record.b; @@ -155,7 +159,6 @@ public class AltosEepromIterable extends AltosRecordIterable { int flags = (record.b >> 8); state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; - state.gps.date_valid = (flags & Altos.AO_GPS_DATE_VALID) != 0; state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT; break; diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index 10befad4..4c6deaa0 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -73,7 +73,16 @@ public class AltosEepromLog { in_end_block = in_start_block + 2; for (block = in_start_block; block < in_end_block; block++) { - AltosEepromBlock eeblock = new AltosEepromBlock(serial_line, block); + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); + + if (block == in_start_block) { + if (eechunk.data(0) != Altos.AO_LOG_FLIGHT) { + flight = eechunk.data16(0); + has_flight = true; + break; + } + } + AltosEepromBlock eeblock = new AltosEepromBlock(eechunk); if (eeblock.has_flight) { flight = eeblock.flight; has_flight = true; diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index e5196c50..5787af86 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -38,6 +38,8 @@ public class AltosEepromRecord { public String data; public boolean tick_valid; + static final int record_length = 8; + int[] ParseHex(String line) { String[] tokens = line.split("\\s+"); int[] array = new int[tokens.length]; @@ -51,44 +53,35 @@ public class AltosEepromRecord { return array; } - int checksum(int[] line) { + int checksum(int[] data, int start) { int csum = 0x5a; - for (int i = 1; i < line.length; i++) - csum += line[i]; + for (int i = 0; i < record_length; i++) + csum += data[i + start]; return csum & 0xff; } - public AltosEepromRecord (AltosSerial serial_line, int addr) - throws TimeoutException, ParseException, InterruptedException { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - int[] values = ParseHex(line); + public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { + + cmd = chunk.data(start); + tick_valid = true; - if (values == null || values.length < 9) { - System.out.printf("invalid line %s", line); - throw new ParseException(String.format("inalid line %s", line), 0); - } - if (values[0] != (addr & 0xff)) - throw new ParseException(String.format("data address out of sync at 0x%x", - addr), 0); int i; - for (i = 1; i < values.length; i++) - if (values[i] != 0xff) + for (i = 0; i < record_length; i++) + if (chunk.data[start + i] != 0xff) break; - cmd = values[1]; - tick_valid = true; - if (i != values.length) { - if (checksum(values) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x in line %s", addr, line), 0); + if (i != 8) { + if (checksum(chunk.data, start) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); } else { cmd = Altos.AO_LOG_INVALID; tick_valid = false; } - tick = values[3] + (values[4] << 8); - a = values[5] + (values[6] << 8); - b = values[7] + (values[8] << 8); + tick = chunk.data16(start + 2); + a = chunk.data16(start + 4); + b = chunk.data16(start + 6); + data = null; } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 49f34ce3..9a9d0d36 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -28,6 +28,7 @@ altosui_JAVA = \ AltosDevice.java \ AltosDisplayThread.java \ AltosEepromBlock.java \ + AltosEepromChunk.java \ AltosEepromDelete.java \ AltosEepromDownload.java \ AltosEepromList.java \ -- cgit v1.2.3 From b155647472ddfacb07c5ffa832e4d1f4a13ad342 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Mar 2011 22:01:18 -0700 Subject: altosui: Remove extra AltosEepromBlock layer This was interposed between the download layer and the eeprom layer to hold a eeprom block full of flight log records. The addition of the tiny log format required reworking the code to hold chunks full of eeprom data without regard to their content, so this content-specific layer didn't seem useful anymore. Signed-off-by: Keith Packard --- altosui/AltosEepromBlock.java | 111 --------------------------------------- altosui/AltosEepromDownload.java | 89 +++++++++++++++++-------------- altosui/AltosEepromLog.java | 49 +++++++---------- altosui/Makefile.am | 3 +- 4 files changed, 69 insertions(+), 183 deletions(-) delete mode 100644 altosui/AltosEepromBlock.java diff --git a/altosui/AltosEepromBlock.java b/altosui/AltosEepromBlock.java deleted file mode 100644 index 650920d1..00000000 --- a/altosui/AltosEepromBlock.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.*; -import java.lang.reflect.Array; - -import libaltosJNI.*; - -public class AltosEepromBlock extends ArrayList { - boolean has_flight; - int flight; - boolean has_state; - int state; - boolean has_date; - int year, month, day; - boolean has_lat; - double lat; - boolean has_lon; - double lon; - boolean has_time; - int hour, minute, second; - ParseException parse_exception = null; - - public AltosEepromBlock (AltosEepromChunk chunk) { - int addr; - boolean done = false; - - has_flight = false; - has_state = false; - has_date = false; - has_lat = false; - has_lon = false; - has_time = false; - for (addr = 0; addr < chunk.chunk_size;) { - try { - AltosEepromRecord r = new AltosEepromRecord(chunk, addr); - - if (r.cmd == Altos.AO_LOG_FLIGHT) { - flight = r.b; - has_flight = true; - } - - /* Monitor state transitions to update display */ - if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { - if (!has_state || r.a > state) { - state = r.a; - has_state = true; - } - } - - if (r.cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (r.a & 0xff); - month = (r.a >> 8) & 0xff; - day = (r.b & 0xff); - has_date = true; - } - if (r.cmd == Altos.AO_LOG_GPS_TIME) { - hour = (r.a & 0xff); - minute = (r.a >> 8); - second = (r.b & 0xff); - has_time = true; - } - if (r.cmd == Altos.AO_LOG_GPS_LAT) { - lat = (double) (r.a | (r.b << 16)) / 1e7; - has_lat = true; - } - if (r.cmd == Altos.AO_LOG_GPS_LON) { - lon = (double) (r.a | (r.b << 16)) / 1e7; - has_lon = true; - } - if (!done) - add(addr / 8, r); - if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) - done = true; - } catch (ParseException pe) { - AltosEepromRecord r = new AltosEepromRecord(Altos.AO_LOG_INVALID, - 0, 0, 0); - if (parse_exception == null) - parse_exception = pe; - if (!done) - add(addr/8, r); - } - addr += 8; - } - } -} \ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index f96a3dc9..a03d2b43 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -96,77 +96,88 @@ public class AltosEepromDownload implements Runnable { int state; void CaptureFull(AltosEepromChunk eechunk) throws IOException { - AltosEepromBlock eeblock = new AltosEepromBlock(eechunk); - - if (eeblock.has_flight) { - flight = eeblock.flight; - monitor.set_flight(flight); - } - if (eeblock.has_date) { - year = eeblock.year; - month = eeblock.month; - day = eeblock.day; - want_file = true; - } + boolean any_valid = false; + for (int i = 0; i < eechunk.chunk_size && !done; i += AltosEepromRecord.record_length) { + try { + AltosEepromRecord r = new AltosEepromRecord(eechunk, i); + if (r.cmd == Altos.AO_LOG_FLIGHT) { + flight = r.b; + monitor.set_flight(flight); + } - if (eeblock.size() == 0 || - eeblock.has_state && eeblock.state == Altos.ao_flight_landed) - done = true; + /* Monitor state transitions to update display */ + if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { + state = r.a; + if (state > Altos.ao_flight_pad) + want_file = true; + } - /* Monitor state transitions to update display */ - if (eeblock.has_state) { - if (eeblock.state > Altos.ao_flight_pad) - want_file = true; - if (eeblock.state > state) - state = eeblock.state; + if (r.cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + want_file = true; + } + if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) + done = true; + any_valid = true; + Log(r); + } catch (ParseException pe) { + if (parse_exception == null) + parse_exception = pe; + } } - if (parse_exception == null && eeblock.parse_exception != null) - parse_exception = eeblock.parse_exception; + if (!any_valid) + done = true; CheckFile(false); - - for (int record = 0; record < eeblock.size(); record++) - Log(eeblock.get(record)); } boolean start; int tiny_tick; void CaptureTiny (AltosEepromChunk eechunk) throws IOException { - boolean some_reasonable_data = false; + boolean any_valid = false; - for (int i = 0; i < eechunk.data.length; i += 2) { - int v = eechunk.data16(i); + for (int i = 0; i < eechunk.data.length && !done; i += 2) { + int v = eechunk.data16(i); + AltosEepromRecord r; if (i == 0 && start) { tiny_tick = 0; start = false; flight = v; - Log(new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v)); - some_reasonable_data = true; + monitor.set_flight(flight); + r = new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v); + any_valid = true; } else { int s = v ^ 0x8000; + if (Altos.ao_flight_startup <= s && s <= Altos.ao_flight_invalid) { - Log(new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0)); - if (s == Altos.ao_flight_landed) { + r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0); + if (s == Altos.ao_flight_landed) done = true; - break; - } - some_reasonable_data = true; + any_valid = true; } else { if (v != 0xffff) - some_reasonable_data = true; - Log(new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0)); + any_valid = true; + r = new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0); + + /* + * The flight software records ascent data every 100ms, and descent + * data every 1s. + */ if (state < Altos.ao_flight_drogue) tiny_tick += 10; else tiny_tick += 100; } } + Log(r); } CheckFile(false); - if (!some_reasonable_data) + if (!any_valid) done = true; } diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index 4c6deaa0..f7fb39e1 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -41,10 +41,7 @@ public class AltosEepromLog { int start_block; int end_block; - boolean has_gps; int year, month, day; - int hour, minute, second; - double lat, lon; boolean download; boolean delete; @@ -54,7 +51,7 @@ public class AltosEepromLog { throws InterruptedException, TimeoutException { int block; - boolean has_date = false, has_time = false, has_lat = false, has_lon = false; + boolean has_date = false; start_block = in_start_block; end_block = in_end_block; @@ -82,34 +79,24 @@ public class AltosEepromLog { break; } } - AltosEepromBlock eeblock = new AltosEepromBlock(eechunk); - if (eeblock.has_flight) { - flight = eeblock.flight; - has_flight = true; - } - if (eeblock.has_date) { - year = eeblock.year; - month = eeblock.month; - day = eeblock.day; - has_date = true; - } - if (eeblock.has_time) { - hour = eeblock.hour; - minute = eeblock.minute; - second = eeblock.second; - has_time = true; - } - if (eeblock.has_lat) { - lat = eeblock.lat; - has_lat = true; - } - if (eeblock.has_lon) { - lon = eeblock.lon; - has_lon = true; + for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { + try { + AltosEepromRecord r = new AltosEepromRecord(eechunk, i); + + if (r.cmd == Altos.AO_LOG_FLIGHT) { + flight = r.b; + has_flight = true; + } + if (r.cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + has_date = true; + } + } catch (ParseException pe) { + } } - if (has_date && has_time && has_lat && has_lon) - has_gps = true; - if (has_gps && has_flight) + if (has_date && has_flight) break; } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 9a9d0d36..01fe50c8 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,6 +1,6 @@ SUBDIRS=libaltos JAVAROOT=classes -AM_JAVACFLAGS=-encoding UTF-8 +AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation man_MANS=altosui.1 @@ -27,7 +27,6 @@ altosui_JAVA = \ AltosDeviceDialog.java \ AltosDevice.java \ AltosDisplayThread.java \ - AltosEepromBlock.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ AltosEepromDownload.java \ -- cgit v1.2.3 From 2c121f1ef495e8af3eb39210baa40e212b691894 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Mar 2011 22:04:09 -0700 Subject: altosui: swing hide/show methods are deprecated I don't know why, but they are, so just replace them with setVisible calls. Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 8 ++++---- altosui/AltosDescent.java | 32 ++++++++++++++++---------------- altosui/AltosLanded.java | 8 ++++---- altosui/AltosPad.java | 20 ++++++++++---------- 4 files changed, 34 insertions(+), 34 deletions(-) diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 0fbc5de2..8a4aa58b 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -89,13 +89,13 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } void show() { - label.show(); - value.show(); + label.setVisible(true); + value.setVisible(true); } void hide() { - label.hide(); - value.hide(); + label.setVisible(false); + value.setVisible(false); } public AscentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 594a7a09..addd6878 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -39,15 +39,15 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { abstract void show(AltosState state, int crc_errors); void show() { - label.show(); - value.show(); - lights.show(); + label.setVisible(true); + value.setVisible(true); + lights.setVisible(true); } void hide() { - label.hide(); - value.hide(); - lights.hide(); + label.setVisible(false); + value.setVisible(false); + lights.setVisible(false); } void reset() { @@ -104,13 +104,13 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { abstract void show(AltosState state, int crc_errors); void show() { - label.show(); - value.show(); + label.setVisible(true); + value.setVisible(true); } void hide() { - label.hide(); - value.hide(); + label.setVisible(false); + value.setVisible(false); } void show(String format, double v) { @@ -158,15 +158,15 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { } void show() { - label.show(); - value1.show(); - value2.show(); + label.setVisible(true); + value1.setVisible(true); + value2.setVisible(true); } void hide() { - label.hide(); - value1.hide(); - value2.hide(); + label.setVisible(false); + value1.setVisible(false); + value2.setVisible(false); } abstract void show(AltosState state, int crc_errors); diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 0717ffe2..63a2daf6 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -43,13 +43,13 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { } void show() { - label.show(); - value.show(); + label.setVisible(true); + value.setVisible(true); } void hide() { - label.hide(); - value.hide(); + label.setVisible(false); + value.setVisible(false); } void show(String format, double v) { diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 2f59e879..2d800e8a 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -43,15 +43,15 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { } public void show() { - label.show(); - value.show(); - lights.show(); + label.setVisible(true); + value.setVisible(true); + lights.setVisible(true); } public void hide() { - label.hide(); - value.hide(); - lights.hide(); + label.setVisible(false); + value.setVisible(false); + lights.setVisible(false); } public LaunchStatus (GridBagLayout layout, int y, String text) { @@ -96,13 +96,13 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { void show(AltosState state, int crc_errors) {} void show() { - label.show(); - value.show(); + label.setVisible(true); + value.setVisible(true); } void hide() { - label.hide(); - value.hide(); + label.setVisible(false); + value.setVisible(false); } void reset() { -- cgit v1.2.3 From 97517ee585462c2d355f23f999fb8d9ebd908ec1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2011 00:01:22 -0700 Subject: altosui: Allow TM config connection to be canceled. This leaves the config UI connection attempt running and pops up a dialog box when it takes 'too long' in the remote case so that users with Tm or Tn devices can bring up the UI, and then boot the Tm/Tn without needing to time things carefully. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 235 +++++++++++++++++++++++++++++++---------------- altosui/AltosIgnite.java | 13 +-- altosui/AltosSerial.java | 95 +++++++++++++++++-- 3 files changed, 247 insertions(+), 96 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 47de6156..854d5384 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -109,86 +109,188 @@ public class AltosConfig implements ActionListener { void start_serial() throws InterruptedException { serial_started = true; - if (remote) { - serial_line.set_radio(); - serial_line.printf("p\nE 0\n"); - serial_line.flush_input(); - } + if (remote) + serial_line.start_remote(); } void stop_serial() throws InterruptedException { if (!serial_started) return; serial_started = false; - if (remote) { - serial_line.printf("~"); - serial_line.flush_output(); + if (remote) + serial_line.stop_remote(); + } + + void update_ui() { + config_ui.set_serial(serial.get()); + config_ui.set_product(product.get()); + config_ui.set_version(version.get()); + config_ui.set_main_deploy(main_deploy.get()); + config_ui.set_apogee_delay(apogee_delay.get()); + config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_flight_log_max(flight_log_max.get()); + config_ui.set_callsign(callsign.get()); + config_ui.set_clean(); + config_ui.make_visible(); + } + + void process_line(String line) { + if (line == null) { + System.out.printf("timeout\n"); + abort(); + return; } + if (line.equals("done")) { + System.out.printf("done\n"); + if (serial_line != null) + update_ui(); + return; + } + get_int(line, "serial-number", serial); + get_int(line, "Main deploy:", main_deploy); + get_int(line, "Apogee delay:", apogee_delay); + get_int(line, "Radio channel:", radio_channel); + get_int(line, "Radio cal:", radio_calibration); + get_int(line, "Max flight log:", flight_log_max); + get_string(line, "Callsign:", callsign); + get_string(line,"software-version", version); + get_string(line,"product", product); } - void get_data() throws InterruptedException, TimeoutException { - try { - start_serial(); - serial_line.printf("c s\nv\n"); - for (;;) { - String line = serial_line.get_reply(5000); - if (line == null) - throw new TimeoutException(); - get_int(line, "serial-number", serial); - get_int(line, "Main deploy:", main_deploy); - get_int(line, "Apogee delay:", apogee_delay); - get_int(line, "Radio channel:", radio_channel); - get_int(line, "Radio cal:", radio_calibration); - get_int(line, "Max flight log:", flight_log_max); - get_string(line, "Callsign:", callsign); - get_string(line,"software-version", version); - get_string(line,"product", product); - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; + final static int serial_mode_read = 0; + final static int serial_mode_save = 1; + final static int serial_mode_reboot = 2; + + class SerialData implements Runnable { + AltosConfig config; + int serial_mode; + + void process_line(String line) { + config.process_line(line); + } + void callback(String in_line) { + final String line = in_line; + Runnable r = new Runnable() { + public void run() { + process_line(line); + } + }; + SwingUtilities.invokeLater(r); + } + + void get_data() { + try { + config.start_serial(); + config.serial_line.printf("c s\nv\n"); + for (;;) { + try { + String line = config.serial_line.get_reply(5000); + if (line == null) + stop_serial(); + callback(line); + if (line.startsWith("software-version")) + break; + } catch (Exception e) { + break; + } + } + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + callback("done"); + } + + void save_data() { + try { + start_serial(); + serial_line.printf("c m %d\n", main_deploy.get()); + serial_line.printf("c d %d\n", apogee_delay.get()); + if (!remote) { + serial_line.printf("c r %d\n", radio_channel.get()); + serial_line.printf("c f %d\n", radio_calibration.get()); + } + serial_line.printf("c c %s\n", callsign.get()); + if (flight_log_max.get() != 0) + serial_line.printf("c l %d\n", flight_log_max.get()); + serial_line.printf("c w\n"); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + void reboot() { + try { + start_serial(); + serial_line.printf("r eboot\n"); + serial_line.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial_line.close(); } - } finally { - stop_serial(); + } + + public void run () { + switch (serial_mode) { + case serial_mode_save: + save_data(); + /* fall through ... */ + case serial_mode_read: + get_data(); + break; + case serial_mode_reboot: + reboot(); + break; + } + } + + public SerialData(AltosConfig in_config, int in_serial_mode) { + config = in_config; + serial_mode = in_serial_mode; } } + void run_serial_thread(int serial_mode) { + SerialData sd = new SerialData(this, serial_mode); + Thread st = new Thread(sd); + st.start(); + } + void init_ui () throws InterruptedException, TimeoutException { config_ui = new AltosConfigUI(owner, remote); config_ui.addActionListener(this); + serial_line.set_frame(owner); set_ui(); } void abort() { + serial_line.close(); + serial_line = null; JOptionPane.showMessageDialog(owner, String.format("Connection to \"%s\" failed", device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); - try { - stop_serial(); - } catch (InterruptedException ie) { - } - serial_line.close(); - serial_line = null; + config_ui.setVisible(false); } void set_ui() throws InterruptedException, TimeoutException { if (serial_line != null) - get_data(); - config_ui.set_serial(serial.get()); - config_ui.set_product(product.get()); - config_ui.set_version(version.get()); - config_ui.set_main_deploy(main_deploy.get()); - config_ui.set_apogee_delay(apogee_delay.get()); - config_ui.set_radio_channel(radio_channel.get()); - config_ui.set_radio_calibration(radio_calibration.get()); - config_ui.set_flight_log_max(flight_log_max.get()); - config_ui.set_callsign(callsign.get()); - config_ui.set_clean(); - } - - void run_dialog() { + run_serial_thread(serial_mode_read); + else + update_ui(); } void save_data() { @@ -198,25 +300,7 @@ public class AltosConfig implements ActionListener { radio_calibration.set(config_ui.radio_calibration()); flight_log_max.set(config_ui.flight_log_max()); callsign.set(config_ui.callsign()); - try { - start_serial(); - serial_line.printf("c m %d\n", main_deploy.get()); - serial_line.printf("c d %d\n", apogee_delay.get()); - if (!remote) { - serial_line.printf("c r %d\n", radio_channel.get()); - serial_line.printf("c f %d\n", radio_calibration.get()); - } - serial_line.printf("c c %s\n", callsign.get()); - if (flight_log_max.get() != 0) - serial_line.printf("c l %d\n", flight_log_max.get()); - serial_line.printf("c w\n"); - } catch (InterruptedException ie) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - } + run_serial_thread(serial_mode_save); } public void actionPerformed(ActionEvent e) { @@ -224,17 +308,11 @@ public class AltosConfig implements ActionListener { try { if (cmd.equals("Save")) { save_data(); - set_ui(); } else if (cmd.equals("Reset")) { set_ui(); } else if (cmd.equals("Reboot")) { - if (serial_line != null) { - start_serial(); - serial_line.printf("r eboot\n"); - serial_line.flush_output(); - stop_serial(); - serial_line.close(); - } + if (serial_line != null) + run_serial_thread(serial_mode_reboot); } else if (cmd.equals("Close")) { if (serial_line != null) serial_line.close(); @@ -267,7 +345,6 @@ public class AltosConfig implements ActionListener { remote = true; try { init_ui(); - config_ui.make_visible(); } catch (InterruptedException ie) { abort(); } catch (TimeoutException te) { diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index 3cbd8a75..d3638140 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -36,11 +36,8 @@ public class AltosIgnite { private void start_serial() throws InterruptedException { serial_started = true; - if (remote) { - serial.set_radio(); - serial.printf("p\nE 0\n"); - serial.flush_input(); - } + if (remote) + serial.start_remote(); } private void stop_serial() throws InterruptedException { @@ -49,10 +46,8 @@ public class AltosIgnite { serial_started = false; if (serial == null) return; - if (remote) { - serial.printf("~"); - serial.flush_output(); - } + if (remote) + serial.stop_remote(); } class string_ref { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index a8ba66bd..88b38bb1 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -25,6 +25,11 @@ import java.lang.*; import java.io.*; import java.util.concurrent.*; import java.util.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; import libaltosJNI.*; @@ -36,7 +41,7 @@ import libaltosJNI.*; public class AltosSerial implements Runnable { - static List devices_opened = Collections.synchronizedList(new LinkedList()); + static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); AltosDevice device; SWIGTYPE_p_altos_file altos; @@ -52,6 +57,7 @@ public class AltosSerial implements Runnable { static boolean debug; boolean remote; LinkedList pending_output = new LinkedList(); + Frame frame; static void set_debug(boolean new_debug) { debug = new_debug; @@ -126,6 +132,59 @@ public class AltosSerial implements Runnable { } } + boolean abort; + JDialog timeout_dialog; + boolean timeout_started = false; + + private void stop_timeout_dialog() { + System.out.printf("stop_timeout_dialog\n"); + Runnable r = new Runnable() { + public void run() { + if (timeout_dialog != null) + timeout_dialog.setVisible(false); + } + }; + SwingUtilities.invokeLater(r); + } + + private void start_timeout_dialog_internal() { + System.out.printf("Creating timeout dialog\n"); + Object[] options = { "Cancel" }; + + JOptionPane pane = new JOptionPane(); + pane.setMessage(String.format("Connecting to %s", device.getPath())); + pane.setOptions(options); + pane.setInitialValue(null); + + timeout_dialog = pane.createDialog(frame, "Connecting..."); + + timeout_dialog.setVisible(true); + + Object o = pane.getValue(); + if (o == null) + return; + if (options[0].equals(o)) + abort = true; + } + + private boolean check_timeout() { + if (!timeout_started && frame != null) { + timeout_started = true; + System.out.printf("Starting timeout dialog\n"); + if (SwingUtilities.isEventDispatchThread()) { + start_timeout_dialog_internal(); + } else { + Runnable r = new Runnable() { + public void run() { + start_timeout_dialog_internal(); + } + }; + SwingUtilities.invokeLater(r); + } + } + return abort; + } + public void flush_input() { flush_output(); boolean got_some; @@ -156,10 +215,21 @@ public class AltosSerial implements Runnable { public String get_reply(int timeout) throws InterruptedException { flush_output(); - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line == null) - return null; - return line.line; + if (remote) { + timeout = 300; + System.out.printf("Doing remote timout\n"); + } + abort = false; + timeout_started = false; + for (;;) { + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) { + stop_timeout_dialog(); + return line.line; + } + if (!remote || check_timeout()) + return null; + } } public void add_monitor(LinkedBlockingQueue q) { @@ -289,16 +359,25 @@ public class AltosSerial implements Runnable { public void stop_remote() { if (debug) System.out.printf("stop remote\n"); - flush_input(); - printf ("~"); - flush_output(); + try { + flush_input(); + } finally { + System.out.printf("Sending tilde\n"); + printf ("~\n"); + flush_output(); + } remote = false; } + public void set_frame(Frame in_frame) { + frame = in_frame; + } + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; line = ""; monitor_mode = false; + frame = null; telemetry = Altos.ao_telemetry_full; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); -- cgit v1.2.3 From 3945d8f986d8f4bd3186a2cbaed5186e49d59839 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2011 23:15:36 -0700 Subject: altos: Variable log rate in full logging code too With the fixed ADC rate used to get better data during flight, the logging code now needs to vary the data storage rate so that descent data is recorded at 10 samples/second while ascent data is recorded at 1 sample per second. Having the logging code do this itself eliminates any interaction with the flight code. Signed-off-by: Keith Packard --- src/ao_log_big.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 6db4a0ff..8379ab5f 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -65,9 +65,16 @@ static __xdata uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 + void ao_log(void) { + uint16_t next_sensor; + uint16_t next_other; + ao_storage_setup(); ao_log_scan(); @@ -76,7 +83,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; + next_other = next_sensor = log.tick = ao_flight_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -90,36 +97,41 @@ ao_log(void) for (;;) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_flight_adc) { - log.type = AO_LOG_SENSOR; log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if ((ao_log_adc_pos & 0x1f) == 0) { + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if (ao_flight_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; ao_log_data(&log); log.type = AO_LOG_DEPLOY; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; ao_log_data(&log); + next_other = log.tick + AO_OTHER_INTERVAL; } ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } } /* Wait for a while */ -- cgit v1.2.3 From 7ce8c9081e703d1405c2595ab9bda0cfa218c6c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2011 23:38:54 -0700 Subject: altos: full logging must flush pending data before checking state Flight state must be checked only after any pending data have been written to the log as the 'current' flight state is only valid when the pending data values have been processed. This ensures that the 'boost' state is not marked until the full ring of data is written. This ensures that the data processing code can find the barometer values from before boost to get an idea of the ground pressure value. Signed-off-by: Keith Packard --- src/ao_log_big.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 8379ab5f..ab6b02f5 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -72,8 +72,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - uint16_t next_sensor; - uint16_t next_other; + uint16_t next_sensor, next_other; ao_storage_setup(); @@ -83,7 +82,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - next_other = next_sensor = log.tick = ao_flight_tick; + log.tick = ao_flight_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -94,6 +93,8 @@ ao_log(void) * when starting up. */ ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_flight_adc) { @@ -103,7 +104,7 @@ ao_log(void) log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; ao_log_data(&log); - if (ao_flight_state <= ao_flight_coast) + if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; else next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; @@ -120,18 +121,18 @@ ao_log(void) next_other = log.tick + AO_OTHER_INTERVAL; } ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); } /* Wait for a while */ -- cgit v1.2.3 From 91a75279b6d306ba9d068a28c64917d5312122e8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Mar 2011 00:12:01 -0700 Subject: altosui: Off-by-one error in telemetry format configuration UI The telemetry format menu uses 0 for full and 1 for tiny, but the telemetry configuration uses 1 for full and 2 for tiny. One direction (config to UI) was right, the other (UI to config) was wrong. Signed-off-by: Keith Packard --- altosui/AltosFlightUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 286b2a4e..66dcdad5 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -162,7 +162,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { telemetries.setMaximumRowCount(2); telemetries.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - int telemetry = telemetries.getSelectedIndex(); + int telemetry = telemetries.getSelectedIndex() + 1; reader.set_telemetry(telemetry); } }); -- cgit v1.2.3 From 067b21993e9a97fceadb355e571e5610535336a8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Mar 2011 00:13:38 -0700 Subject: altosui: Allow radio channel to be configured over the radio link TeleMini/TeleNano can't be configured via USB, so we need to allow the radio channel to be set over the radio link. This change carefully sets the new radio channel, disables the remote link and then sets the teledongle channel to the new value and brings the link back up. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 13 ++++++++++--- altosui/AltosConfigUI.java | 2 -- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 854d5384..f45e2040 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -207,13 +207,20 @@ public class AltosConfig implements ActionListener { void save_data() { try { + int channel; start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); - if (!remote) { - serial_line.printf("c r %d\n", radio_channel.get()); - serial_line.printf("c f %d\n", radio_calibration.get()); + channel = radio_channel.get(); + serial_line.printf("c r %d\n", channel); + if (remote) { + serial_line.stop_remote(); + serial_line.set_channel(channel); + AltosPreferences.set_channel(device.getSerial(), channel); + serial_line.start_remote(); } + if (!remote) + serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index e09eab25..f835ee2e 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -252,8 +252,6 @@ public class AltosConfigUI radio_channel_value = new JComboBox(radio_channel_values); radio_channel_value.setEditable(false); radio_channel_value.addItemListener(this); - if (remote) - radio_channel_value.setEnabled(false); pane.add(radio_channel_value, c); /* Radio Calibration */ -- cgit v1.2.3 From f23d0f3cbf1fb0c8eab497e266625f6410b69ba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Mar 2011 00:46:19 -0700 Subject: altosui: Tell serial device which frame to use for timeout dialogs For the timeout dialog to appear, a frame must be configured for it to appear near. This patch sends the frame from the eeprom download functions to the serial code. That path doesn't yet work as the eeprom download is still trying to talk to the serial device from the swing event thread, which prevents the cancel dialog from working. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 1 + altosui/AltosEepromManage.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index a03d2b43..fad16460 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -328,6 +328,7 @@ public class AltosEepromDownload implements Runnable { frame = given_frame; serial_line = given_serial_line; + serial_line.set_frame(frame); remote = given_remote; flights = given_flights; success = false; diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index b12d95fa..fe1db9c7 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -106,6 +106,8 @@ public class AltosEepromManage implements ActionListener { if (!device.matchProduct(AltosDevice.product_telemetrum)) remote = true; + serial_line.set_frame(frame); + flights = new AltosEepromList(serial_line, remote); if (flights.size() == 0) { -- cgit v1.2.3 From 006de838bbb096b9443863a46b8a125b1e6b5600 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Mar 2011 00:48:07 -0700 Subject: altosui: Handle serial calls from swing thread Calls from the swing thread cannot be canceled as there's no way to put up the cancel dialog. In this case, simply use the 5 second timeout and fail if no communication occurs within that amount of time. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 88b38bb1..57e13448 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -137,7 +137,6 @@ public class AltosSerial implements Runnable { boolean timeout_started = false; private void stop_timeout_dialog() { - System.out.printf("stop_timeout_dialog\n"); Runnable r = new Runnable() { public void run() { if (timeout_dialog != null) @@ -148,7 +147,6 @@ public class AltosSerial implements Runnable { } private void start_timeout_dialog_internal() { - System.out.printf("Creating timeout dialog\n"); Object[] options = { "Cancel" }; JOptionPane pane = new JOptionPane(); @@ -170,10 +168,7 @@ public class AltosSerial implements Runnable { private boolean check_timeout() { if (!timeout_started && frame != null) { timeout_started = true; - System.out.printf("Starting timeout dialog\n"); - if (SwingUtilities.isEventDispatchThread()) { - start_timeout_dialog_internal(); - } else { + if (!SwingUtilities.isEventDispatchThread()) { Runnable r = new Runnable() { public void run() { start_timeout_dialog_internal(); @@ -208,16 +203,22 @@ public class AltosSerial implements Runnable { } public String get_reply() throws InterruptedException { + if (SwingUtilities.isEventDispatchThread()) + System.out.printf("Uh-oh, reading serial device from swing thread\n"); flush_output(); AltosLine line = reply_queue.take(); return line.line; } public String get_reply(int timeout) throws InterruptedException { + boolean can_cancel = true; + if (SwingUtilities.isEventDispatchThread()) { + can_cancel = false; + System.out.printf("Uh-oh, reading serial device from swing thread\n"); + } flush_output(); - if (remote) { + if (remote && can_cancel) { timeout = 300; - System.out.printf("Doing remote timout\n"); } abort = false; timeout_started = false; @@ -227,7 +228,7 @@ public class AltosSerial implements Runnable { stop_timeout_dialog(); return line.line; } - if (!remote || check_timeout()) + if (!remote || !can_cancel || check_timeout()) return null; } } @@ -362,7 +363,6 @@ public class AltosSerial implements Runnable { try { flush_input(); } finally { - System.out.printf("Sending tilde\n"); printf ("~\n"); flush_output(); } -- cgit v1.2.3 From c754759a2d503633d527da4ebb20eb859cd506fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 17:54:44 -0700 Subject: altos: Split up flight code into separate flight/sample/kalman bits The flight code mashed together data processing, filtering and actual flight managament into one giant pile. Split things up so that we have: ao_sample.c: Sensor data processing. Reads the ring, handles calibration ao_kalman.c: Filter the data to track the accel/speed/height values ao_flight.c: Flight state management, specific to rocketry. The plan is to re-use ao_sample.c and ao_kalman.c for hardware not specifically designed for rocketry, like TeleNano. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 + src/ao.h | 131 +++++++++++++-- src/ao_adc.c | 2 +- src/ao_config.c | 6 +- src/ao_flight.c | 452 ++------------------------------------------------- src/ao_flight_test.c | 43 ++++- src/ao_kalman.c | 245 ++++++++++++++++++++++++++++ src/ao_log_big.c | 8 +- src/ao_sample.c | 206 +++++++++++++++++++++++ src/ao_stdio.c | 2 +- 10 files changed, 635 insertions(+), 466 deletions(-) create mode 100644 src/ao_kalman.c create mode 100644 src/ao_sample.c diff --git a/src/Makefile.proto b/src/Makefile.proto index 85c0c46e..8dd21a64 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -147,6 +147,8 @@ SKY_DRIVER_SRC = \ # TM_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_big.c \ ao_report.c \ @@ -179,6 +181,8 @@ TMINI_DRIVER_SRC = \ TMINI_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ @@ -207,6 +211,8 @@ TNANO_DRIVER_SRC = \ TNANO_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ diff --git a/src/ao.h b/src/ao.h index b88bef1f..42c3edda 100644 --- a/src/ao.h +++ b/src/ao.h @@ -695,22 +695,10 @@ enum ao_flight_state { ao_flight_invalid = 9 }; -extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; -extern __pdata uint16_t ao_flight_tick; -extern __xdata int16_t ao_ground_pres; -extern __pdata int16_t ao_ground_accel; + extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; -extern __pdata int16_t ao_ground_height; -extern __pdata int16_t ao_max_height; -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) /* Flight thread */ void @@ -720,6 +708,121 @@ ao_flight(void); void ao_flight_init(void); +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __xdata int16_t ao_ground_pres; /* startup pressure */ +extern __xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __xdata int16_t ao_ground_accel; /* startup acceleration */ +extern __xdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + /* * ao_report.c */ @@ -1054,7 +1157,7 @@ extern __xdata uint8_t ao_stdin_ready; void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, - void (*flush)(void)); + void (*flush)(void)) __reentrant; /* * ao_ignite.c diff --git a/src/ao_adc.c b/src/ao_adc.c index d77e7753..48568383 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_flight_adc); + uint8_t i = ao_adc_ring_prev(ao_sample_adc); memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } diff --git a/src/ao_config.c b/src/ao_config.c index 771b21a1..319febb9 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -215,10 +215,10 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_flight_adc; + cal_adc_ring = ao_sample_adc; while (i) { - ao_sleep(DATA_TO_XDATA(&ao_flight_adc)); - while (i && cal_adc_ring != ao_flight_adc) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (i && cal_adc_ring != ao_sample_adc) { accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; cal_adc_ring = ao_adc_ring_next(cal_adc_ring); i--; diff --git a/src/ao_flight.c b/src/ao_flight.c index 88f0544f..94fbf178 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -34,13 +34,7 @@ /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_flight_tick; /* time of last data */ -__pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__xdata int16_t ao_ground_pres; /* startup pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -#endif /* * track min/max data over a long interval to detect @@ -50,59 +44,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__data uint8_t ao_flight_adc; -__pdata int16_t ao_raw_pres; -__xdata uint8_t ao_flight_force_idle; - -#if HAS_ACCEL -__pdata int16_t ao_raw_accel, ao_raw_accel_prev; -__pdata int16_t ao_accel_2g; - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -#endif - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ +__xdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in * case of other failures @@ -110,228 +52,6 @@ __pdata int16_t ao_accel_2g; #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -#include "ao_kalman.h" - -__pdata int16_t ao_ground_height; -__pdata int16_t ao_height; -__pdata int16_t ao_speed; -__pdata int16_t ao_accel; -__pdata int16_t ao_max_height; - -static __pdata int32_t ao_k_height; -static __pdata int32_t ao_k_speed; -static __pdata int32_t ao_k_accel; - -#define AO_K_STEP_100 to_fix16(0.01) -#define AO_K_STEP_2_2_100 to_fix16(0.00005) - -#define AO_K_STEP_10 to_fix16(0.1) -#define AO_K_STEP_2_2_10 to_fix16(0.005) - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -static void -ao_kalman_predict(void) -{ -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + - (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; - - return; - } - if (ao_flight_debug) { - printf ("predict speed %g + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, - (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); - } -#endif - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + - (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; -} - -static __pdata int16_t ao_error_h; -static __pdata int16_t ao_raw_alt; -static __pdata int16_t ao_raw_height; -static __pdata int16_t ao_error_h_sq_avg; - -static void -ao_kalman_err_height(void) -{ - int16_t e; - int16_t height_distrust; -#if HAS_ACCEL - int16_t speed_distrust; -#endif - - ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); - - e = ao_error_h; - if (e < 0) - e = -e; - if (e > 127) - e = 127; -#if HAS_ACCEL - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; - ao_error_h_sq_avg += (e * e) >> 2; -#else - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; - ao_error_h_sq_avg += (e * e) >> 4; -#endif - - height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; -#if HAS_ACCEL - /* speed is stored * 16, but we need to ramp between 200 and 328, so - * we want to multiply by 2. The result is a shift by 3. - */ - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); - if (speed_distrust <= 0) - speed_distrust = 0; - else if (speed_distrust > height_distrust) - height_distrust = speed_distrust; -#endif - if (height_distrust <= 0) - height_distrust = 0; - - if (height_distrust) { -#ifdef AO_FLIGHT_TEST - int old_ao_error_h = ao_error_h; -#endif - if (height_distrust > 0x100) - height_distrust = 0x100; - ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); -#ifdef AO_FLIGHT_TEST - if (ao_flight_debug) { - printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_raw_height - AO_MAX_BARO_HEIGHT), - (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, - height_distrust / 256.0, - old_ao_error_h, ao_error_h); - } -#endif - } -} - -static void -ao_kalman_correct_baro(void) -{ - ao_kalman_err_height(); -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; - return; - } -#endif - ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; -} - -#if HAS_ACCEL -static __pdata int16_t ao_error_a; -static __pdata int32_t ao_accel_scale; - -static void -ao_kalman_err_accel(void) -{ - int32_t accel; - - accel = (ao_ground_accel - ao_raw_accel) * ao_accel_scale; - - /* Can't use ao_accel here as it is the pre-prediction value still */ - ao_error_a = (accel - ao_k_accel) >> 16; -} - -static void -ao_kalman_correct_both(void) -{ - ao_kalman_err_height(); - ao_kalman_err_accel(); - -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) AO_BOTH_K01_10 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_10 * ao_error_h + - (int32_t) AO_BOTH_K21_10 * ao_error_a; - return; - } - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); - } -#endif - ao_k_height += - (int32_t) AO_BOTH_K00_100 * ao_error_h + - (int32_t) AO_BOTH_K01_100 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_100 * ao_error_h + - (int32_t) AO_BOTH_K21_100 * ao_error_a; -} - -#ifdef FORCE_ACCEL -static void -ao_kalman_correct_accel(void) -{ - ao_kalman_err_accel(); - - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; - return; - } - ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; -} -#endif -#endif /* HAS_ACCEL */ - -__xdata int32_t ao_raw_pres_sum; - -#ifdef HAS_ACCEL -__xdata int32_t ao_raw_accel_sum; -#endif - /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ @@ -342,162 +62,20 @@ __xdata int32_t ao_raw_accel_sum; void ao_flight(void) { - __pdata static uint16_t nsamples = 0; - - ao_flight_adc = ao_adc_head; - ao_raw_pres = 0; -#if HAS_ACCEL - ao_raw_accel_prev = 0; - ao_raw_accel = 0; -#endif - ao_flight_tick = 0; + ao_sample_init(); + ao_flight_state = ao_flight_startup; for (;;) { - ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_flight_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - ao_flight_prev_tick = ao_flight_tick; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_flight_adc]; - ao_flight_tick = ao_adc->tick; - ao_raw_pres = ao_adc->pres; - ao_raw_alt = ao_pres_to_altitude(ao_raw_pres); - ao_raw_height = ao_raw_alt - ao_ground_height; -#if HAS_ACCEL - ao_raw_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_raw_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_raw_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_raw_accel 32767 - * = ------------ * ------------ - * 32737 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_raw_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_raw_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_raw_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_raw_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_raw_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; - ao_adc->accel = ao_raw_accel; -#endif -#endif - if (ao_flight_state > ao_flight_idle) { - ao_kalman_predict(); -#if HAS_ACCEL - if (ao_flight_state <= ao_flight_coast) { -#ifdef FORCE_ACCEL - ao_kalman_correct_accel(); -#else - ao_kalman_correct_both(); -#endif - } else -#endif - ao_kalman_correct_baro(); - ao_height = from_fix(ao_k_height); - ao_speed = from_fix(ao_k_speed); - ao_accel = from_fix(ao_k_accel); - if (ao_height > ao_max_height) - ao_max_height = ao_height; - } - ao_flight_adc = ao_adc_ring_next(ao_flight_adc); - } + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; switch (ao_flight_state) { case ao_flight_startup: - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_raw_accel_sum += ao_raw_accel; -#endif - ao_raw_pres_sum += ao_raw_pres; - ++nsamples; - continue; - } - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_raw_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_raw_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out * - pad mode if we're upright, @@ -574,7 +152,7 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_flight_tick; + ao_launch_tick = ao_sample_tick; /* start logging data */ ao_log_start(); @@ -608,7 +186,7 @@ ao_flight(void) * (15 seconds) has past. */ if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) + (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; @@ -646,7 +224,7 @@ ao_flight(void) */ if (ao_speed < 0 #if !HAS_ACCEL - && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) #endif ) { @@ -662,7 +240,7 @@ ao_flight(void) */ /* initialize interval values */ - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; ao_interval_min_height = ao_interval_max_height = ao_height; @@ -706,7 +284,7 @@ ao_flight(void) if (ao_height > ao_interval_max_height) ao_interval_max_height = ao_height; - if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { if (ao_height < AO_M_TO_HEIGHT(1000) && ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) { @@ -720,7 +298,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } ao_interval_min_height = ao_interval_max_height = ao_height; - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; case ao_flight_landed: diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 91aa0f73..f41acbca 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -53,6 +53,22 @@ struct ao_adc { #define __code #define __reentrant +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + enum ao_flight_state { ao_flight_startup = 0, ao_flight_idle = 1, @@ -66,6 +82,11 @@ enum ao_flight_state { ao_flight_invalid = 9 }; +extern enum ao_flight_state ao_flight_state; + +#define FALSE 0 +#define TRUE 1 + struct ao_adc ao_adc_ring[AO_ADC_RING]; uint8_t ao_adc_head; int ao_summary = 0; @@ -171,15 +192,25 @@ struct ao_config ao_config; #define HAS_ACCEL_REF 0 #endif -#include "ao_flight.c" - -#define to_double(f) ((f) / 65536.0) - #define GRAVITY 9.80665 -extern int16_t ao_ground_accel, ao_raw_accel; +extern int16_t ao_ground_accel, ao_flight_accel; extern int16_t ao_accel_2g; +extern uint16_t ao_sample_tick; + +extern int16_t ao_sample_height; +extern int16_t ao_sample_accel; +extern int32_t ao_accel_scale; + +int ao_sample_prev_tick; uint16_t prev_tick; + +#include "ao_kalman.c" +#include "ao_sample.c" +#include "ao_flight.c" + +#define to_double(f) ((f) / 65536.0) + static int ao_records_read = 0; static int ao_eof_read = 0; static int ao_flight_ground_accel; @@ -224,7 +255,7 @@ ao_insert(void) ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; + double height = ao_pres_to_altitude(ao_sample_pres) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); diff --git a/src/ao_kalman.c b/src/ao_kalman.c new file mode 100644 index 00000000..ee99f375 --- /dev/null +++ b/src/ao_kalman.c @@ -0,0 +1,245 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#include "ao_kalman.h" + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; + +__pdata int16_t ao_error_h; +__pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +__pdata int16_t ao_error_a; +#endif + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static void +ao_kalman_err_height(void) +{ + int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + + ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +#endif + + height_distrust = ao_sample_height - AO_MAX_BARO_HEIGHT; +#if HAS_ACCEL + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust <= 0) + height_distrust = 0; + + if (height_distrust) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_sample_height - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif + } +} + +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; + return; + } +#endif + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; +} + +#if HAS_ACCEL + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) AO_BOTH_K01_10 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_10 * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +#ifdef FORCE_ACCEL +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif +#endif /* HAS_ACCEL */ + +void +ao_kalman(void) +{ + ao_kalman_predict(); +#if HAS_ACCEL + if (ao_flight_state <= ao_flight_coast) { +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); +#endif + } else +#endif + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif +} diff --git a/src/ao_log_big.c b/src/ao_log_big.c index ab6b02f5..0c6cff85 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -82,7 +82,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; + log.tick = ao_sample_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -92,12 +92,12 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_flight_adc) { + while (ao_log_adc_pos != ao_sample_adc) { log.tick = ao_adc_ring[ao_log_adc_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; @@ -126,7 +126,7 @@ ao_log(void) if (ao_flight_state != ao_log_state) { ao_log_state = ao_flight_state; log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; + log.tick = ao_sample_tick; log.u.state.state = ao_log_state; log.u.state.reason = 0; ao_log_data(&log); diff --git a/src/ao_sample.c b/src/ao_sample.c new file mode 100644 index 00000000..ef403393 --- /dev/null +++ b/src/ao_sample.c @@ -0,0 +1,206 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +/* + * Current sensor values + */ + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata int16_t ao_sample_pres; +__pdata int16_t ao_sample_alt; +__pdata int16_t ao_sample_height; +#if HAS_ACCEL +__pdata int16_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_adc; + +/* + * Sensor calibration values + */ + +__xdata int16_t ao_ground_pres; /* startup pressure */ +__xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__xdata int16_t ao_ground_accel; /* startup acceleration */ +__xdata int16_t ao_accel_2g; /* factory accel calibration */ +__xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __xdata uint8_t ao_preflight; /* in preflight mode */ + +static __xdata uint16_t nsamples; +__xdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__xdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + ao_preflight = FALSE; + } + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); +} + +uint8_t +ao_sample(void) +{ + ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); + while (ao_sample_adc != ao_adc_head) { + __xdata struct ao_adc *ao_adc; + + /* Capture a sample */ + ao_adc = &ao_adc_ring[ao_sample_adc]; + ao_sample_tick = ao_adc->tick; + ao_sample_pres = ao_adc->pres; + ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32737 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + ao_adc->accel = ao_sample_accel; +#endif +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_adc = ao_adc_ring_next(ao_sample_adc); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_adc = ao_adc_head; + ao_preflight = TRUE; +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 78bbd3c3..6e1f5eff 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -66,7 +66,7 @@ getchar(void) __reentrant __critical void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), - void (*flush)(void)) + void (*flush)(void)) __reentrant { if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); -- cgit v1.2.3 From c6e7e812d67f91c63ba4982f7a899a72584027de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 18:18:50 -0700 Subject: altos: Create custom nano flight code No igniters, just 'pad/drogue/landed' modes (where 'drogue' == 'flying'). A constant 1Hz telemetry and RDF rate. Signed-off-by: Keith Packard --- src/Makefile.proto | 3 +- src/ao.h | 7 ++++ src/ao_flight_nano.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 12 ++++++ src/ao_report.c | 4 ++ src/ao_telenano.c | 3 +- 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/ao_flight_nano.c diff --git a/src/Makefile.proto b/src/Makefile.proto index 8dd21a64..5aad445f 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -204,13 +204,12 @@ TMINI_BASE_SRC = \ # Sources for TeleNano TNANO_DRIVER_SRC = \ ao_adc.c \ - ao_ignite.c \ ao_config.c \ ao_storage.c \ ao_intflash.c TNANO_TASK_SRC = \ - ao_flight.c \ + ao_flight_nano.c \ ao_sample.c \ ao_kalman.c \ ao_log.c \ diff --git a/src/ao.h b/src/ao.h index 42c3edda..89109fd9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -708,6 +708,13 @@ ao_flight(void); void ao_flight_init(void); +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + /* * ao_sample.c */ diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c new file mode 100644 index 00000000..64c1d8db --- /dev/null +++ b/src/ao_flight_nano.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; + +__xdata uint8_t ao_flight_force_idle; + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) + +static void +ao_flight_nano(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + + for (;;) { + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + if (ao_flight_force_idle) { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + } else { + ao_flight_state = ao_flight_pad; + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + } + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; + case ao_flight_pad: + if (ao_height> AO_M_TO_HEIGHT(20)) { + ao_flight_state = ao_flight_drogue; + ao_launch_tick = ao_sample_tick; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + /* drogue/main to land: + * + * barometer: altitude stable + */ + + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_nano_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight_nano, "flight"); +} diff --git a/src/ao_pins.h b/src/ao_pins.h index a4a93aab..30f2decc 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -40,6 +40,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEMETRUM_V_1_1) @@ -68,6 +69,7 @@ #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEDONGLE_V_0_2) @@ -89,6 +91,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 #endif #if defined(TELEMINI_V_0_1) @@ -111,6 +114,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 + #define HAS_IGNITE 1 #endif #if defined(TELENANO_V_0_1) @@ -133,6 +137,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 + #define HAS_IGNITE 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -159,6 +164,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEDONGLE_V_0_1) @@ -180,6 +186,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 #endif #if defined(TIDONGLE) @@ -200,6 +207,7 @@ #define LEDS_AVAILABLE (AO_LED_RED) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 #endif #if DBG_ON_P1 @@ -280,6 +288,10 @@ #error Please define HAS_DBG #endif +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + #ifndef PACKET_HAS_MASTER #error Please define PACKET_HAS_MASTER #endif diff --git a/src/ao_report.c b/src/ao_report.c index 4f7fd657..b9dc5bb4 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -109,6 +109,7 @@ ao_report_altitude(void) } } +#if HAS_IGNITE static uint8_t ao_report_igniter_ready(enum ao_igniter igniter) { @@ -146,6 +147,7 @@ ao_report_continuity(void) __reentrant while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); } +#endif void ao_report(void) @@ -155,10 +157,12 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); +#if HAS_IGNITE if (ao_flight_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) ao_report_continuity(); +#endif __critical { while (ao_report_state == ao_flight_state) ao_sleep(DATA_TO_XDATA(&ao_flight_state)); diff --git a/src/ao_telenano.c b/src/ao_telenano.c index dbc3b74c..47b7b3c3 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -39,13 +39,12 @@ main(void) ao_adc_init(); ao_cmd_init(); ao_storage_init(); - ao_flight_init(); + ao_flight_nano_init(); ao_log_init(); ao_report_init(); ao_telemetry_tiny_init(); ao_radio_init(); ao_packet_slave_init(TRUE); - ao_igniter_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From c71a145daefb86d2c1297abec68e54bd951e3adf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 23:35:05 -0700 Subject: altosui: Clean up packet link connecting dialog Make sure the dialog is destroyed after use (otherwise, it hangs around on the screen sometimes). Switch timeout before showing dialog to 500ms -- that brings the dialog up less often when unnecessary. Use 'timeout_started' boolean to indicate whether the I/O thread has queued the dialog for display and whether it needs to queue a call to close it down. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 57e13448..111bd771 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -137,16 +137,19 @@ public class AltosSerial implements Runnable { boolean timeout_started = false; private void stop_timeout_dialog() { - Runnable r = new Runnable() { - public void run() { - if (timeout_dialog != null) + if (timeout_started) { + timeout_started = false; + Runnable r = new Runnable() { + public void run() { timeout_dialog.setVisible(false); - } - }; - SwingUtilities.invokeLater(r); + } + }; + SwingUtilities.invokeLater(r); + } } private void start_timeout_dialog_internal() { + Object[] options = { "Cancel" }; JOptionPane pane = new JOptionPane(); @@ -163,12 +166,14 @@ public class AltosSerial implements Runnable { return; if (options[0].equals(o)) abort = true; + timeout_dialog.dispose(); + timeout_dialog = null; } private boolean check_timeout() { if (!timeout_started && frame != null) { - timeout_started = true; if (!SwingUtilities.isEventDispatchThread()) { + timeout_started = true; Runnable r = new Runnable() { public void run() { start_timeout_dialog_internal(); @@ -186,7 +191,7 @@ public class AltosSerial implements Runnable { int timeout = 100; if (remote) - timeout = 300; + timeout = 500; do { try { Thread.sleep(timeout); @@ -210,15 +215,19 @@ public class AltosSerial implements Runnable { return line.line; } + int in_reply; + public String get_reply(int timeout) throws InterruptedException { boolean can_cancel = true; + ++in_reply; + if (SwingUtilities.isEventDispatchThread()) { can_cancel = false; System.out.printf("Uh-oh, reading serial device from swing thread\n"); } flush_output(); if (remote && can_cancel) { - timeout = 300; + timeout = 500; } abort = false; timeout_started = false; @@ -226,10 +235,13 @@ public class AltosSerial implements Runnable { AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) { stop_timeout_dialog(); + --in_reply; return line.line; } - if (!remote || !can_cancel || check_timeout()) + if (!remote || !can_cancel || check_timeout()) { + --in_reply; return null; + } } } @@ -245,6 +257,9 @@ public class AltosSerial implements Runnable { } public void close() { + if (in_reply != 0) + System.out.printf("Uh-oh. Closing active serial device\n"); + if (altos != null) { libaltos.altos_close(altos); } -- cgit v1.2.3 From 573edcd7dfe10ac3251396eae88eece55d82bcb6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 23:38:02 -0700 Subject: altosui: Make flight log downloading handle 'Connecting...' dialog This required moving all of the serial communication to a separate thread and making the bulk of the download operation run after that has finished. Signed-off-by: Keith Packard --- altosui/AltosEepromManage.java | 160 +++++++++++++++++++++++++---------------- 1 file changed, 100 insertions(+), 60 deletions(-) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index fe1db9c7..5fb70a84 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -89,6 +89,103 @@ public class AltosEepromManage implements ActionListener { finish(); } + public void got_flights(AltosEepromList in_flights) { + boolean running = false;; + + flights = in_flights; + try { + if (flights.size() == 0) { + JOptionPane.showMessageDialog(frame, + String.format("No flights available on %d", + device.getSerial()), + serial_line.device.toShortString(), + JOptionPane.INFORMATION_MESSAGE); + } else { + AltosEepromSelect select = new AltosEepromSelect(frame, flights); + + if (select.run()) { + for (AltosEepromLog flight : flights) { + any_download = any_download || flight.download; + any_delete = any_delete || flight.delete; + } + if (any_download) { + download = new AltosEepromDownload(frame, + serial_line, + remote, + flights); + download.addActionListener(this); + } + + if (any_delete) { + delete = new AltosEepromDelete(frame, + serial_line, + remote, + flights); + delete.addActionListener(this); + } + + /* + * Start flight log download + */ + + if (any_download) { + download.start(); + running = true; + } + else if (any_delete) { + delete.start(); + running = true; + } + } + } + if (!running) + finish(); + } catch (Exception e) { + got_exception(e); + } + } + + public void got_exception(Exception e) { + if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(frame, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof TimeoutException) { + TimeoutException te = (TimeoutException) e; + JOptionPane.showMessageDialog(frame, + String.format("Communications failed with \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } + finish(); + } + + class EepromGetList implements Runnable { + + AltosEepromManage manage; + + public void run () { + try { + flights = new AltosEepromList(serial_line, remote); + Runnable r = new Runnable() { + public void run() { + manage.got_flights(flights); + } + }; + SwingUtilities.invokeLater(r); + } catch (Exception e) { + manage.got_exception(e); + } + } + + public EepromGetList(AltosEepromManage in_manage) { + manage = in_manage; + } + } + public AltosEepromManage(JFrame given_frame) { boolean running = false; @@ -108,52 +205,9 @@ public class AltosEepromManage implements ActionListener { serial_line.set_frame(frame); - flights = new AltosEepromList(serial_line, remote); - - if (flights.size() == 0) { - JOptionPane.showMessageDialog(frame, - String.format("No flights available on %d", - device.getSerial()), - serial_line.device.toShortString(), - JOptionPane.INFORMATION_MESSAGE); - } else { - AltosEepromSelect select = new AltosEepromSelect(frame, flights); - - if (select.run()) { - for (AltosEepromLog flight : flights) { - any_download = any_download || flight.download; - any_delete = any_delete || flight.delete; - } - if (any_download) { - download = new AltosEepromDownload(frame, - serial_line, - remote, - flights); - download.addActionListener(this); - } - - if (any_delete) { - delete = new AltosEepromDelete(frame, - serial_line, - remote, - flights); - delete.addActionListener(this); - } - - /* - * Start flight log download - */ - - if (any_download) { - download.start(); - running = true; - } - else if (any_delete) { - delete.start(); - running = true; - } - } - } + EepromGetList get_list = new EepromGetList(this); + Thread t = new Thread(get_list); + t.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, String.format("Cannot open device \"%s\"", @@ -166,21 +220,7 @@ public class AltosEepromManage implements ActionListener { device.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(frame, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } catch (TimeoutException te) { - JOptionPane.showMessageDialog(frame, - String.format("Communications failed with \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException ie) { } - if (!running) - finish(); } } } -- cgit v1.2.3 From 2f9be009ef26e3d7539f5932d267d7a8a7bcb7eb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 09:37:11 -0700 Subject: altosui: Make deployment testing handle Connecting... dialog Supporting the Connecting... dialog requires moving all serial communication to a separate thread. This was done by creating a worker thread and command queue to communicate between the UI and the serial line. Signed-off-by: Keith Packard --- altosui/AltosIgnite.java | 12 +++- altosui/AltosIgniteUI.java | 148 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 127 insertions(+), 33 deletions(-) diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index d3638140..1171d2ed 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -19,6 +19,12 @@ package altosui; import java.io.*; import java.util.concurrent.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; public class AltosIgnite { AltosDevice device; @@ -115,7 +121,7 @@ public class AltosIgnite { return status; } - public String status_string(int status) { + public static String status_string(int status) { switch (status) { case Unknown: return "Unknown"; case Ready: return "Ready"; @@ -156,6 +162,10 @@ public class AltosIgnite { serial = null; } + public void set_frame(Frame frame) { + serial.set_frame(frame); + } + public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index d542729c..000adc98 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -34,7 +34,6 @@ public class AltosIgniteUI implements ActionListener { AltosDevice device; - AltosIgnite ignite; JFrame owner; JLabel label; JRadioButton apogee; @@ -53,6 +52,70 @@ public class AltosIgniteUI int time_remaining; boolean timer_running; + LinkedBlockingQueue command_queue; + + class IgniteHandler implements Runnable { + AltosIgnite ignite; + + public void run () { + for (;;) { + Runnable r; + + try { + String command = command_queue.take(); + String reply = null; + + if (command.equals("get_status")) { + apogee_status = ignite.status(AltosIgnite.Apogee); + main_status = ignite.status(AltosIgnite.Main); + reply = "status"; + } else if (command.equals("main")) { + ignite.fire(AltosIgnite.Main); + reply = "fired"; + } else if (command.equals("apogee")) { + ignite.fire(AltosIgnite.Apogee); + reply = "fired"; + } else if (command.equals("quit")) { + ignite.close(); + break; + } else { + throw new ParseException(String.format("invalid command %s", command), 0); + } + final String f_reply = reply; + r = new Runnable() { + public void run() { + ignite_reply(f_reply); + } + }; + } catch (Exception e) { + final Exception f_e = e; + r = new Runnable() { + public void run() { + ignite_exception(f_e); + } + }; + } + SwingUtilities.invokeLater(r); + } + } + + public IgniteHandler(AltosIgnite in_ignite) { + ignite = in_ignite; + } + } + + void ignite_exception(Exception e) { + abort(); + } + + void ignite_reply(String reply) { + if (reply.equals("status")) { + set_ignite_status(); + } else if (reply.equals("fired")) { + fired(); + } + } + void set_arm_text() { if (arm.isSelected()) arm.setText(String.format("%d", time_remaining)); @@ -82,21 +145,53 @@ public class AltosIgniteUI stop_timer(); } - void get_ignite_status() throws InterruptedException, TimeoutException { - apogee_status = ignite.status(AltosIgnite.Apogee); - main_status = ignite.status(AltosIgnite.Main); + void send_command(String command) { + try { + command_queue.put(command); + } catch (Exception ex) { + abort(); + } + } + + boolean getting_status = false; + + boolean visible = false; + void set_ignite_status() { + getting_status = false; + apogee_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(apogee_status))); + main_status_label.setText(String.format("\"%s\"", AltosIgnite.status_string(main_status))); + if (!visible) { + visible = true; + setVisible(true); + } + } + + void poll_ignite_status() { + if (!getting_status) { + getting_status = true; + send_command("get_status"); + } + } + + boolean firing = false; + + void start_fire(String which) { + if (!firing) { + firing = true; + send_command(which); + } } - void set_ignite_status() throws InterruptedException, TimeoutException { - get_ignite_status(); - apogee_status_label.setText(String.format("\"%s\"", ignite.status_string(apogee_status))); - main_status_label.setText(String.format("\"%s\"", ignite.status_string(main_status))); + void fired() { + firing = false; + cancel(); } void close() { + send_command("quit"); timer.stop(); setVisible(false); - ignite.close(); + dispose(); } void abort() { @@ -116,23 +211,17 @@ public class AltosIgniteUI else set_arm_text(); } - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - } catch (TimeoutException te) { - abort(); - } + poll_ignite_status(); } void fire() { if (arm.isEnabled() && arm.isSelected() && time_remaining > 0) { - int igniter = AltosIgnite.None; + String igniter = "none"; if (apogee.isSelected() && !main.isSelected()) - igniter = AltosIgnite.Apogee; + igniter = "apogee"; else if (main.isSelected() && !apogee.isSelected()) - igniter = AltosIgnite.Main; - ignite.fire(igniter); + igniter = "main"; + send_command(igniter); cancel(); } } @@ -184,10 +273,16 @@ public class AltosIgniteUI } private boolean open() { + command_queue = new LinkedBlockingQueue(); + device = AltosDeviceDialog.show(owner, AltosDevice.product_any); if (device != null) { try { - ignite = new AltosIgnite(device); + AltosIgnite ignite = new AltosIgnite(device); + IgniteHandler handler = new IgniteHandler(ignite); + Thread t = new Thread(handler); + ignite.set_frame(owner); + t.start(); return true; } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, @@ -278,16 +373,6 @@ public class AltosIgniteUI main_status_label = new JLabel(); pane.add(main_status_label, c); - try { - set_ignite_status(); - } catch (InterruptedException ie) { - abort(); - return; - } catch (TimeoutException te) { - abort(); - return; - } - c.gridx = 0; c.gridy = 3; c.gridwidth = 1; @@ -310,7 +395,6 @@ public class AltosIgniteUI pack(); setLocationRelativeTo(owner); - setVisible(true); addWindowListener(new ConfigListener(this)); } -- cgit v1.2.3 From 8ade7d99f02df825e70d0a964b4648156101ef78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 09:38:23 -0700 Subject: altosui: Display exception messages from swing thread Flight log management exceptions were getting displayed from the log serial I/O thread instead of the swing thread. That's a bad plan. Signed-off-by: Keith Packard --- altosui/AltosEepromManage.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 5fb70a84..b46364db 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -168,17 +168,23 @@ public class AltosEepromManage implements ActionListener { AltosEepromManage manage; public void run () { + Runnable r; try { flights = new AltosEepromList(serial_line, remote); - Runnable r = new Runnable() { + r = new Runnable() { public void run() { - manage.got_flights(flights); + got_flights(flights); } }; - SwingUtilities.invokeLater(r); } catch (Exception e) { - manage.got_exception(e); + final Exception f_e = e; + r = new Runnable() { + public void run() { + got_exception(f_e); + } + }; } + SwingUtilities.invokeLater(r); } public EepromGetList(AltosEepromManage in_manage) { -- cgit v1.2.3 From 56d045040c49728a854741e99545766f3723da5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 09:39:27 -0700 Subject: altosui: Don't display 0000-00-00 for missing flight log dates With Tm/Tn not having GPS to get the current date, it's no longer unusual to have no date for a flight log, so don't show the 0000-00-00 piece in that case. Signed-off-by: Keith Packard --- altosui/AltosEepromSelect.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index cb71524d..0a6eec17 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -45,8 +45,14 @@ class AltosEepromItem implements ActionListener { public AltosEepromItem(AltosEepromLog in_log) { log = in_log; - label = new JLabel(String.format("Flight #%02d - %04d-%02d-%02d", - log.flight, log.year, log.month, log.day)); + String text; + if (log.year != 0) + text = String.format("Flight #%02d - %04d-%02d-%02d", + log.flight, log.year, log.month, log.day); + else + text = String.format("Flight #%02d", log.flight); + + label = new JLabel(text); download = new JCheckBox("", log.download); download.addActionListener(this); -- cgit v1.2.3 From 08e6bbef2c3529dfd468ef221c526fc9f3ed5b81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 10:08:46 -0700 Subject: altos: ao_sample_preflight was exiting preflight mode immediately Need to stay in pre-flight mode until we've gotten enough sensor data to calibrate things appropriately. The conversion from a unified ao_flight.c file was just broken here. Signed-off-by: Keith Packard --- src/ao_sample.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ao_sample.c b/src/ao_sample.c index ef403393..84cf1e00 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -68,16 +68,17 @@ ao_sample_preflight(void) #endif ao_sample_pres_sum += ao_sample_pres; ++nsamples; - ao_preflight = FALSE; - } - ao_config_get(); + } else { + ao_config_get(); #if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } } uint8_t -- cgit v1.2.3 From 011e37f27b3926a42c8c1a74e0f179bb48829ec7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 18:10:46 -0700 Subject: altos: Run RDF beacon after apogee instead of waiting for landing This provides tracking when GPS fails, or on TeleMini. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 94fbf178..c6cbbf7c 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -234,6 +234,9 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + /* Turn the RDF beacon back on */ + ao_rdf_set(1); + /* * Start recording min/max height * to figure out when the rocket has landed @@ -292,8 +295,6 @@ ao_flight(void) /* turn off the ADC capture */ ao_timer_set_adc_interval(0); - /* Enable RDF beacon */ - ao_rdf_set(1); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } -- cgit v1.2.3 From 87bff181a95f6bf92c2cec350d331ba6af779e80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 18:11:47 -0700 Subject: altos: Enable logging during nano flights Not having logging wasn't very useful. Signed-off-by: Keith Packard --- src/ao_flight_nano.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c index 64c1d8db..32770227 100644 --- a/src/ao_flight_nano.c +++ b/src/ao_flight_nano.c @@ -75,6 +75,10 @@ ao_flight_nano(void) if (ao_height> AO_M_TO_HEIGHT(20)) { ao_flight_state = ao_flight_drogue; ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; -- cgit v1.2.3 From a9df9fc257eb2d7038d66ac7c2539aae4474bf12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 30 Mar 2011 11:47:07 -0700 Subject: altosui: Parse and export Max flight log value New configuration field might as well get dumped to the .csv files. Signed-off-by: Keith Packard --- altosui/Altos.java | 9 +++++---- altosui/AltosEepromIterable.java | 3 +++ altosui/AltosEepromRecord.java | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 3ef4d799..1f791da5 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -44,10 +44,11 @@ public class Altos { static final int AO_LOG_CALLSIGN = 1004; static final int AO_LOG_ACCEL_CAL = 1005; static final int AO_LOG_RADIO_CAL = 1006; - static final int AO_LOG_MANUFACTURER = 1007; - static final int AO_LOG_PRODUCT = 1008; - static final int AO_LOG_SERIAL_NUMBER = 1009; - static final int AO_LOG_SOFTWARE_VERSION = 1010; + static final int AO_LOG_MAX_FLIGHT_LOG = 1007; + static final int AO_LOG_MANUFACTURER = 2000; + static final int AO_LOG_PRODUCT = 2001; + static final int AO_LOG_SERIAL_NUMBER = 2002; + static final int AO_LOG_SOFTWARE_VERSION = 9999; /* Added to flag invalid records */ static final int AO_LOG_INVALID = -1; diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index bb7c7bef..a7fd742f 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -281,6 +281,9 @@ public class AltosEepromIterable extends AltosRecordIterable { case Altos.AO_LOG_RADIO_CAL: out.printf ("# Radio cal: %d\n", record.a); break; + case Altos.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.a); + break; case Altos.AO_LOG_MANUFACTURER: out.printf ("# Manufacturer: %s\n", record.data); break; diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 5787af86..52acb435 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -131,6 +131,9 @@ public class AltosEepromRecord { } 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("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = Altos.AO_LOG_MAX_FLIGHT_LOG; + a = Integer.parseInt(tokens[3]); } else if (tokens[0].equals("manufacturer")) { cmd = Altos.AO_LOG_MANUFACTURER; data = tokens[1]; -- cgit v1.2.3 From f558cfa1df77c36a459168c1953d0945ee5a7f9f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 30 Mar 2011 11:48:03 -0700 Subject: altosui: Only plot acceleration when present in data file Eliminates a bogus axis and data line for devices which do not have an accelerometer. Signed-off-by: Keith Packard --- altosui/AltosDataPointReader.java | 10 ++++++++-- altosui/AltosEepromIterable.java | 20 ++++++++++++++++++-- altosui/AltosGraphUI.java | 33 ++++++++++++++++++++------------- altosui/AltosRecord.java | 20 +++++++++++++------- altosui/AltosRecordIterable.java | 3 +++ altosui/AltosTelemetryIterable.java | 13 +++++++++++++ 6 files changed, 75 insertions(+), 24 deletions(-) diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index ee57d2ce..4335421c 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -14,12 +14,18 @@ class AltosDataPointReader implements Iterable { Iterator iter; AltosState state; AltosRecord record; + boolean has_gps; + boolean has_accel; + boolean has_ignite; final static int MISSING = AltosRecord.MISSING; - public AltosDataPointReader(Iterable reader) { + public AltosDataPointReader(AltosRecordIterable reader) { this.iter = reader.iterator(); this.state = null; + has_accel = reader.has_accel(); + has_gps = reader.has_gps(); + has_ignite = reader.has_ignite(); } private void read_next_record() @@ -46,7 +52,7 @@ class AltosDataPointReader implements Iterable { public double acceleration() { return record.acceleration(); } public double pressure() { return record.raw_pressure(); } public double altitude() { return record.raw_altitude(); } - public double height() { return record.raw_height(); } + public double height() { return record.raw_height(); } public double accel_speed() { return record.accel_speed(); } public double baro_speed() { return state.baro_speed; } public double temperature() { return record.temperature(); } diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index a7fd742f..624e1dd3 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -57,6 +57,11 @@ class AltosOrderedRecord extends AltosEepromRecord implements Comparable> Altos.AO_GPS_NUM_SAT_SHIFT; + has_gps = true; break; case Altos.AO_LOG_GPS_LAT: int lat32 = record.a | (record.b << 16); @@ -254,6 +266,10 @@ public class AltosEepromIterable extends AltosRecordIterable { return list.iterator(); } + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + public void write_comments(PrintStream out) { Iterator iterator = records.iterator(); out.printf("# Comments\n"); diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index cd158651..e98c302b 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -96,10 +96,14 @@ public class AltosGraphUI extends JFrame public ArrayList graphs() { ArrayList graphs = new ArrayList(); - graphs.add( myAltosGraphTime("Summary") - .addElement(height) - .addElement(speed) - .addElement(acceleration) ); + graphs.add( myAltosGraphTime("Summary") + .addElement(height) + .addElement(speed) + .addElement(acceleration) ); + + graphs.add( myAltosGraphTime("Summary") + .addElement(height) + .addElement(speed)); graphs.add( myAltosGraphTime("Altitude") .addElement(height) ); @@ -107,15 +111,15 @@ public class AltosGraphUI extends JFrame graphs.add( myAltosGraphTime("Speed") .addElement(speed) ); - graphs.add( myAltosGraphTime("Acceleration") - .addElement(acceleration) ); + graphs.add( myAltosGraphTime("Acceleration") + .addElement(acceleration) ); graphs.add( myAltosGraphTime("Temperature") .addElement(temperature) ); - graphs.add( myAltosGraphTime("Continuity") - .addElement(drogue_voltage) - .addElement(main_voltage) ); + graphs.add( myAltosGraphTime("Continuity") + .addElement(drogue_voltage) + .addElement(main_voltage) ); return graphs; } @@ -154,20 +158,23 @@ public class AltosGraphUI extends JFrame public AltosGraphUI(AltosRecordIterable records) { super("Altos Graph"); - Iterable reader = new AltosDataPointReader (records); + AltosDataPointReader reader = new AltosDataPointReader (records); if (reader == null) return; - init(reader, 0); + if (reader.has_accel) + init(reader, 0); + else + init(reader, 1); } - public AltosGraphUI(Iterable data, int which) + public AltosGraphUI(AltosDataPointReader data, int which) { super("Altos Graph"); init(data, which); } - private void init(Iterable data, int which) { + private void init(AltosDataPointReader data, int which) { AltosGraph graph = createGraph(data, which); JFreeChart chart = graph.createChart(); diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 46e96b95..200fffe5 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -139,7 +139,7 @@ public class AltosRecord { double g = ground_altitude(); if (r == MISSING || g == MISSING) - return MISSING; + return height; return r - g; } @@ -246,6 +246,9 @@ public class AltosRecord { ground_pres = old.ground_pres; accel_plus_g = old.accel_plus_g; accel_minus_g = old.accel_minus_g; + acceleration = old.acceleration; + speed = old.speed; + height = old.height; gps = new AltosGPS(old.gps); } @@ -258,12 +261,12 @@ public class AltosRecord { status = 0; state = Altos.ao_flight_startup; tick = 0; - accel = 0; - pres = 0; - temp = 0; - batt = 0; - drogue = 0; - main = 0; + accel = MISSING; + pres = MISSING; + temp = MISSING; + batt = MISSING; + drogue = MISSING; + main = MISSING; flight_accel = 0; ground_accel = 0; flight_vel = 0; @@ -271,6 +274,9 @@ public class AltosRecord { ground_pres = 0; accel_plus_g = 0; accel_minus_g = 0; + acceleration = MISSING; + speed = MISSING; + height = MISSING; gps = new AltosGPS(); } } diff --git a/altosui/AltosRecordIterable.java b/altosui/AltosRecordIterable.java index a7df92d1..45843b92 100644 --- a/altosui/AltosRecordIterable.java +++ b/altosui/AltosRecordIterable.java @@ -31,4 +31,7 @@ import java.util.concurrent.LinkedBlockingQueue; public abstract class AltosRecordIterable implements Iterable { public abstract Iterator iterator(); public void write_comments(PrintStream out) { } + public boolean has_accel() { return false; } + public boolean has_gps() { return false; } + public boolean has_ignite() { return false; }; } diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index 14b5f27f..44e5ad8f 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -28,6 +28,13 @@ public class AltosTelemetryIterable extends AltosRecordIterable { return records.iterator(); } + boolean has_gps = false; + boolean has_accel = false; + boolean has_ignite = false; + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; }; + public AltosTelemetryIterable (FileInputStream input) { boolean saw_boost = false; int current_tick = 0; @@ -59,6 +66,12 @@ public class AltosTelemetryIterable extends AltosRecordIterable { saw_boost = true; boost_tick = record.tick; } + if (record.accel != AltosRecord.MISSING) + has_accel = true; + if (record.gps != null) + has_gps = true; + if (record.main != AltosRecord.MISSING) + has_ignite = true; records.add(record); } catch (ParseException pe) { System.out.printf("parse exception %s\n", pe.getMessage()); -- cgit v1.2.3 From a9dae18a664f70b668159487015e61be7f776926 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:51:15 -0700 Subject: altos: Reflect ao_flight split in ao_flight_test dependencies Need to rebuild ao_flight_test when any of the flight sources change Signed-off-by: Keith Packard --- src/test/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/Makefile b/src/test/Makefile index 433f749b..33203ffd 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -12,13 +12,13 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ $< -ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c -ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h -- cgit v1.2.3 From 8a14142e7b37031a51409f121b913fe793bf3603 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:53:12 -0700 Subject: altos: Baro useful ceiling is MSL, not AGL Use MSL instead of AGL for detecting over-range baro sensor values. Always trust baro sensor during descent; it'll get there eventually. Signed-off-by: Keith Packard --- src/ao_kalman.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/ao_kalman.c b/src/ao_kalman.c index ee99f375..fb75fba9 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -89,7 +89,9 @@ ao_kalman_err_height(void) ao_error_h_sq_avg += (e * e) >> 4; #endif - height_distrust = ao_sample_height - AO_MAX_BARO_HEIGHT; + if (ao_flight_state >= ao_flight_drogue) + return; + height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; #if HAS_ACCEL /* speed is stored * 16, but we need to ramp between 200 and 328, so * we want to multiply by 2. The result is a shift by 3. @@ -100,10 +102,7 @@ ao_kalman_err_height(void) else if (speed_distrust > height_distrust) height_distrust = speed_distrust; #endif - if (height_distrust <= 0) - height_distrust = 0; - - if (height_distrust) { + if (height_distrust > 0) { #ifdef AO_FLIGHT_TEST int old_ao_error_h = ao_error_h; #endif @@ -113,7 +112,7 @@ ao_kalman_err_height(void) #ifdef AO_FLIGHT_TEST if (ao_flight_debug) { printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_sample_height - AO_MAX_BARO_HEIGHT), + (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, height_distrust / 256.0, old_ao_error_h, ao_error_h); -- cgit v1.2.3 From c0971abc02b05d136aea257f3f40ba3b22b1d441 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:55:18 -0700 Subject: altos: Make ao_flight_test show true height but report saturated height To simulate a saturated baro sensor, clip baro data at a specified altitude. Continue to report the 'true' altitude in the output so that the resulting graphs are useful. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index f41acbca..57785442 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -41,6 +41,7 @@ struct ao_adc { uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ + int16_t pres_real; /* unclipped */ int16_t temp; /* temperature sensor */ int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ @@ -61,6 +62,8 @@ struct ao_adc { * Above this height, the baro sensor doesn't work */ #define AO_MAX_BARO_HEIGHT 12000 +#define AO_BARO_SATURATE 13000 +#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) /* * Above this speed, baro measurements are unreliable @@ -201,6 +204,8 @@ extern uint16_t ao_sample_tick; extern int16_t ao_sample_height; extern int16_t ao_sample_accel; extern int32_t ao_accel_scale; +extern int16_t ao_ground_height; +extern int16_t ao_sample_alt; int ao_sample_prev_tick; uint16_t prev_tick; @@ -255,7 +260,7 @@ ao_insert(void) ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_sample_pres) - ao_ground_height; + double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); @@ -373,6 +378,9 @@ ao_sleep(void *wchan) case 'A': ao_adc_static.tick = tick; ao_adc_static.accel = a; + ao_adc_static.pres_real = b; + if (b < AO_MIN_BARO_VALUE) + b = AO_MIN_BARO_VALUE; ao_adc_static.pres = b; ao_records_read++; ao_insert(); -- cgit v1.2.3 From 8e74cf6d1c70a7a17d01c20f6831571245392498 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:58:14 -0700 Subject: altos: Add initial TeleBT code Prototyping with a TeleMetrum v0.1 board and a serial link to a bluetooth module. Signed-off-by: Keith Packard --- src/Makefile | 1 + src/Makefile.proto | 26 ++++++++++++++++ src/ao.h | 20 +++++++++++- src/ao_btm.c | 72 +++++++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 35 +++++++++++++++++++++ src/ao_serial.c | 42 +++++++++++++++++++++++++ src/ao_stdio.c | 2 +- src/ao_telebt.c | 41 ++++++++++++++++++++++++ src/telebt-v0.0/.gitignore | 2 ++ src/telebt-v0.0/.sdcdbrc | 1 + src/telebt-v0.0/Makefile.defs | 8 +++++ 11 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/ao_btm.c create mode 100644 src/ao_telebt.c create mode 100644 src/telebt-v0.0/.gitignore create mode 100644 src/telebt-v0.0/.sdcdbrc create mode 100644 src/telebt-v0.0/Makefile.defs diff --git a/src/Makefile b/src/Makefile index a5dec57b..d83ec668 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,6 +10,7 @@ SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v0.1 telenano-v0.1 \ + telebt-v0.0 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/Makefile.proto b/src/Makefile.proto index 5aad445f..ca68edbc 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -136,12 +136,20 @@ M25_DRIVER_SRC = \ # SIRF_DRIVER_SRC = \ ao_gps_sirf.c + # # Skytraq driver source # SKY_DRIVER_SRC = \ ao_gps_skytraq.c + +# +# BTM-182 driver source +# +BTM_DRIVER_SRC = \ + ao_btm.c + # # Tasks run on TeleMetrum # @@ -229,6 +237,24 @@ TNANO_BASE_SRC = \ $(TNANO_TASK_SRC) \ $(TNANO_MAIN_SRC) +# +# Sources for TeleDongle +# + +TBT_MAIN_SRC = \ + ao_telebt.c + +TBT_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(SERIAL_DRIVER_SRC) \ + $(USB_DRIVER_SRC) \ + $(BTM_DRIVER_SRC) \ + $(DBG_SRC) \ + $(TBT_MAIN_SRC) + # # TI Dongle sources # diff --git a/src/ao.h b/src/ao.h index 89109fd9..64f33f0b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -903,6 +903,10 @@ ao_dbg_init(void); #endif #if HAS_SERIAL_1 +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + void ao_serial_rx1_isr(void) __interrupt 3; @@ -912,12 +916,21 @@ ao_serial_tx1_isr(void) __interrupt 14; char ao_serial_getchar(void) __critical; +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical; + +void +ao_serial_set_stdin(uint8_t stdin); +#endif + void ao_serial_putchar(char c) __critical; #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_57600 2 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 void ao_serial_set_speed(uint8_t speed); @@ -1332,4 +1345,9 @@ ao_packet_slave_stop(void); void ao_packet_slave_init(uint8_t enable); +/* ao_btm.c */ + +void +ao_btm_init(void); + #endif /* _AO_H_ */ diff --git a/src/ao_btm.c b/src/ao_btm.c new file mode 100644 index 00000000..224d3e81 --- /dev/null +++ b/src/ao_btm.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +uint8_t ao_btm_enable; +extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; + +void +ao_btm(void) +{ + char c; + while (ao_btm_enable) { + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + ao_usb_putchar(c); + else { + ao_usb_flush(); + ao_sleep(&ao_usart1_rx_fifo); + } + } + ao_exit(); +} + +__xdata struct ao_task ao_btm_task; + +static void +ao_btm_forward(void) +{ + char c; + ao_btm_enable = 1; + flush(); + ao_add_task(&ao_btm_task, ao_btm, "btm"); + + while ((c = ao_usb_getchar()) != '~') { + if (c == '\n') c = '\r'; + ao_serial_putchar(c); + } + ao_btm_enable = 0; + while (ao_btm_task.wchan) { + ao_wakeup(&ao_usart1_rx_fifo); + ao_delay(AO_MS_TO_TICKS(10)); + } +} + +__code struct ao_cmds ao_btm_cmds[] = { + { ao_btm_forward, "B \0BTM serial link." }, + { 0, NULL }, +}; + + +void +ao_btm_init (void) +{ + ao_serial_init(); + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_cmd_register(&ao_btm_cmds[0]); +} diff --git a/src/ao_pins.h b/src/ao_pins.h index 30f2decc..a4ebd63b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -25,6 +25,7 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 @@ -49,6 +50,7 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 @@ -77,6 +79,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -100,6 +103,7 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 @@ -123,6 +127,7 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 @@ -146,6 +151,7 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -172,6 +178,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -194,6 +201,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -210,6 +218,29 @@ #define HAS_IGNITE 0 #endif +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ @@ -270,6 +301,10 @@ #error Please define HAS_SERIAL_1 #endif +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/ao_serial.c b/src/ao_serial.c index dd383fca..b8e9d2bf 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -20,12 +20,20 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; +#if USE_SERIAL_STDIN +__pdata uint8_t ao_serial_stdin; +#endif + void ao_serial_rx1_isr(void) __interrupt 3 { if (!ao_fifo_full(ao_usart1_rx_fifo)) ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + if (ao_serial_stdin) + ao_wakeup(&ao_stdin_ready); +#endif } static __xdata uint8_t ao_serial_tx1_started; @@ -69,6 +77,29 @@ ao_serial_getchar(void) __critical return c; } +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; +#if 0 + if (!ao_serial_stdin) + return AO_READ_AGAIN; +#endif + if (ao_fifo_empty(ao_usart1_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart1_rx_fifo,c); + return c; +} + +void +ao_serial_set_stdin(uint8_t stdin) +{ + ao_serial_stdin = stdin; +} + +#endif + void ao_serial_putchar(char c) __critical { @@ -109,6 +140,10 @@ static const struct { /* .baud = */ 163, /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB }, + /* [AO_SERIAL_SPEED_19200] = */ { + /* .baud = */ 163, + /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, /* [AO_SERIAL_SPEED_57600] = */ { /* .baud = */ 59, /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB @@ -156,4 +191,11 @@ ao_serial_init(void) IEN2 |= IEN2_UTX1IE; ao_cmd_register(&ao_serial_cmds[0]); +#if 0 +#if USE_SERIAL_STDIN + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +#endif } diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 6e1f5eff..c7080ec1 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -21,7 +21,7 @@ * Basic I/O functions to support SDCC stdio package */ -#define AO_NUM_STDIOS 2 +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; static __data int8_t ao_cur_stdio; diff --git a/src/ao_telebt.c b/src/ao_telebt.c new file mode 100644 index 00000000..295f0cec --- /dev/null +++ b/src/ao_telebt.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/telebt-v0.0/.gitignore b/src/telebt-v0.0/.gitignore new file mode 100644 index 00000000..1acfbfcc --- /dev/null +++ b/src/telebt-v0.0/.gitignore @@ -0,0 +1,2 @@ +telebt-* +ao_product.h diff --git a/src/telebt-v0.0/.sdcdbrc b/src/telebt-v0.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telebt-v0.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs new file mode 100644 index 00000000..f0bb5e0c --- /dev/null +++ b/src/telebt-v0.0/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telebt-v0.0-$(VERSION).ihx + +SRC = \ + $(TBT_BASE_SRC) + +PRODUCT=TeleBT-v0.0 +PRODUCT_DEF=-DTELEBT_V_0_0 +IDPRODUCT=0x000e -- cgit v1.2.3 From ce18eaa28b1385c962c09459cbc5f20e234d9ad5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:03:25 -0700 Subject: altos: Add P2SEL_*_MASK defines to cc1111.h These are used to avoid having the code "know" which selections are 1 and which are 0 bits. Signed-off-by: Keith Packard --- src/cc1111.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cc1111.h b/src/cc1111.h index effb1a68..a72d7416 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -565,14 +565,19 @@ sfr at 0xF5 P2SEL; #define P2SEL_PRI3P1_MASK (1 << 6) #define P2SEL_PRI2P1_USART1 (0 << 5) #define P2SEL_PRI2P1_TIMER3 (1 << 5) +#define P2SEL_PRI2P1_MASK (1 << 5) #define P2SEL_PRI1P1_TIMER1 (0 << 4) #define P2SEL_PRI1P1_TIMER4 (1 << 4) +#define P2SEL_PRI1P1_MASK (1 << 4) #define P2SEL_PRI0P1_USART0 (0 << 3) #define P2SEL_PRI0P1_TIMER1 (1 << 3) +#define P2SEL_PRI0P1_MASK (1 << 3) #define P2SEL_SELP2_4_GPIO (0 << 2) #define P2SEL_SELP2_4_PERIPHERAL (1 << 2) +#define P2SEL_SELP2_4_MASK (1 << 2) #define P2SEL_SELP2_3_GPIO (0 << 1) #define P2SEL_SELP2_3_PERIPHERAL (1 << 1) +#define P2SEL_SELP2_3_MASK (1 << 1) #define P2SEL_SELP2_0_GPIO (0 << 0) #define P2SEL_SELP2_0_PERIPHERAL (1 << 0) #define P2SEL_SELP2_0_MASK (1 << 0) -- cgit v1.2.3 From 359ba0d9fc2c5947e6adc98bebcd061069c61e79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:04:58 -0700 Subject: altos: expose set of available stdio values This lets external code manipulate which connection to communicate over. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_stdio.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 64f33f0b..2d2bbf82 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1169,6 +1169,9 @@ struct ao_stdio { void (*flush)(void); }; +extern __data int8_t ao_cur_stdio; +extern __data int8_t ao_num_stdios; + void flush(void); diff --git a/src/ao_stdio.c b/src/ao_stdio.c index c7080ec1..3dd457f7 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -24,8 +24,8 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; -static __data int8_t ao_cur_stdio; -static __data int8_t ao_num_stdios; +__data int8_t ao_cur_stdio; +__data int8_t ao_num_stdios; void putchar(char c) -- cgit v1.2.3 From 01952da35a57ae4da062facb26b3c6d7de29190f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:07:23 -0700 Subject: altos: Provide for a pre-filter on commands This allows for external code to see each command line before it is processed and potentially skip it. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_cmd.c | 5 +++++ 2 files changed, 13 insertions(+) diff --git a/src/ao.h b/src/ao.h index 2d2bbf82..77f3259e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -403,6 +403,14 @@ ao_cmd_register(__code struct ao_cmds *cmds); void ao_cmd_init(void); +#if HAS_CMD_FILTER +/* + * Provided by an external module to filter raw command lines + */ +uint8_t +ao_cmd_filter(void); +#endif + /* * ao_dma.c */ diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 6007773c..50d5b96f 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -275,6 +275,11 @@ ao_cmd(void) lex_echo = 1; for (;;) { readline(); +#if HAS_CMD_FILTER + if (ao_cmd_filter()) + continue; + cmd_i = 0; +#endif ao_cmd_lex(); ao_cmd_white(); c = ao_cmd_lex_c; -- cgit v1.2.3 From 39bde78edc863d9d2ef50a59b8f28ab6274892b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:08:37 -0700 Subject: altos: Allow any stdio to be used with packet forwarding There's no reason to restrict packet forwarding to work only from USB. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 069bc5df..e721ffba 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -26,7 +26,7 @@ ao_packet_getchar(void) __critical break; if (ao_packet_master_sleeping) ao_wakeup(&ao_packet_master_sleeping); - ao_usb_flush(); + flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -39,7 +39,7 @@ ao_packet_echo(void) __reentrant while (ao_packet_enable) { c = ao_packet_getchar(); if (c != AO_READ_AGAIN) - ao_usb_putchar(c); + putchar(c); } ao_exit(); } @@ -112,7 +112,7 @@ ao_packet_forward(void) __reentrant ao_set_monitor(0); ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = ao_usb_getchar()) != '~') { + while ((c = getchar()) != '~') { if (c == '\r') c = '\n'; ao_packet_putchar(c); } -- cgit v1.2.3 From 4f243a282f9aeb7433ccb2942850d380a091e603 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:10:37 -0700 Subject: altos: Remove serial monitor command This takes up space and isn't that useful these days Signed-off-by: Keith Packard --- src/ao_serial.c | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/ao_serial.c b/src/ao_serial.c index b8e9d2bf..d6395810 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -58,8 +58,6 @@ ao_serial_tx1_isr(void) __interrupt 14 ao_wakeup(&ao_usart1_tx_fifo); } -static __pdata serial_echo; - char ao_serial_getchar(void) __critical { @@ -67,13 +65,6 @@ ao_serial_getchar(void) __critical while (ao_fifo_empty(ao_usart1_rx_fifo)) ao_sleep(&ao_usart1_rx_fifo); ao_fifo_remove(ao_usart1_rx_fifo, c); - if (serial_echo) { - printf("%02x ", ((int) c) & 0xff); - if (c >= ' ') - putchar(c); - putchar('\n'); - flush(); - } return c; } @@ -116,18 +107,6 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static void -monitor_serial(void) -{ - ao_cmd_hex(); - serial_echo = ao_cmd_lex_i != 0; -} - -__code struct ao_cmds ao_serial_cmds[] = { - { monitor_serial, "M \0Monitor serial data" }, - { 0, NULL }, -}; - static const struct { uint8_t baud; uint8_t gcr; @@ -189,8 +168,6 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; - - ao_cmd_register(&ao_serial_cmds[0]); #if 0 #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, -- cgit v1.2.3 From 9f8a96a8516e13878b329dbf1da855ed9a3219c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:11:44 -0700 Subject: altos: Make ao_serial_drain public Allow external code to discard serial input Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_serial.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index 77f3259e..b92e623f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -935,6 +935,9 @@ ao_serial_set_stdin(uint8_t stdin); void ao_serial_putchar(char c) __critical; +void +ao_serial_drain(void) __critical; + #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_9600 1 #define AO_SERIAL_SPEED_19200 2 diff --git a/src/ao_serial.c b/src/ao_serial.c index d6395810..e9373e23 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -100,7 +100,7 @@ ao_serial_putchar(char c) __critical ao_serial_tx1_start(); } -static void +void ao_serial_drain(void) __critical { while (!ao_fifo_empty(ao_usart1_tx_fifo)) -- cgit v1.2.3 From 92386f2e8419c4df125692cc998eb72ec49bf991 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:12:56 -0700 Subject: altos: Clean up usage of serial port for stdio Code wanting to use this must invoke ao_add_stdio; that way the link can be configured before command processing starts. Signed-off-by: Keith Packard --- src/ao_serial.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/ao_serial.c b/src/ao_serial.c index e9373e23..dc68f862 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -20,10 +20,6 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; -#if USE_SERIAL_STDIN -__pdata uint8_t ao_serial_stdin; -#endif - void ao_serial_rx1_isr(void) __interrupt 3 { @@ -31,8 +27,7 @@ ao_serial_rx1_isr(void) __interrupt 3 ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN - if (ao_serial_stdin) - ao_wakeup(&ao_stdin_ready); + ao_wakeup(&ao_stdin_ready); #endif } @@ -73,22 +68,11 @@ char ao_serial_pollchar(void) __critical { char c; -#if 0 - if (!ao_serial_stdin) - return AO_READ_AGAIN; -#endif if (ao_fifo_empty(ao_usart1_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_usart1_rx_fifo,c); return c; } - -void -ao_serial_set_stdin(uint8_t stdin) -{ - ao_serial_stdin = stdin; -} - #endif void @@ -168,11 +152,4 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; -#if 0 -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); -#endif -#endif } -- cgit v1.2.3 From 4e2c18249e16c98cf5f7dccdf8d3b84bc473863a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 16:48:12 -0700 Subject: altos: Clean up serial initialization Flush serial input buffers when switching speeds. Ensure pin configuration is correct. Signed-off-by: Keith Packard --- src/ao_serial.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ao_serial.c b/src/ao_serial.c index dc68f862..9c0b798d 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -119,6 +119,7 @@ ao_serial_set_speed(uint8_t speed) ao_serial_drain(); if (speed > AO_SERIAL_SPEED_57600) return; + U1UCR |= UxUCR_FLUSH; U1BAUD = ao_serial_speeds[speed].baud; U1GCR = ao_serial_speeds[speed].gcr; } @@ -129,7 +130,8 @@ ao_serial_init(void) /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; - /* ee has already set the P2SEL bits */ + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | + (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); /* Make the USART pins be controlled by the USART */ P1SEL |= (1 << 6) | (1 << 7); @@ -143,7 +145,7 @@ ao_serial_init(void) /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | UxUCR_FLOW_DISABLE | - UxUCR_D9_ODD_PARITY | + UxUCR_D9_EVEN_PARITY | UxUCR_BIT9_8_BITS | UxUCR_PARITY_DISABLE | UxUCR_SPB_1_STOP_BIT | -- cgit v1.2.3 From a5d60fdb9c969c1516feb76a16001c9688112c4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 17:25:07 -0700 Subject: altos: Make cmd echo per-connection instead of global Allow different connections to use different echo values, permitting the packet link to turn off echo while the USB link still has it on. Signed-off-by: Keith Packard --- src/ao.h | 5 +++++ src/ao_cmd.c | 17 ++++++++--------- src/ao_stdio.c | 25 ++++++++++++++++--------- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/ao.h b/src/ao.h index b92e623f..9b375894 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1178,8 +1178,10 @@ struct ao_stdio { char (*pollchar)(void); void (*putchar)(char c) __reentrant; void (*flush)(void); + uint8_t echo; }; +extern __xdata struct ao_stdio ao_stdios[]; extern __data int8_t ao_cur_stdio; extern __data int8_t ao_num_stdios; @@ -1188,6 +1190,9 @@ flush(void); extern __xdata uint8_t ao_stdin_ready; +uint8_t +ao_echo(void); + void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 50d5b96f..c738a3e0 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -21,7 +21,6 @@ __xdata uint16_t ao_cmd_lex_i; __xdata uint32_t ao_cmd_lex_u32; __xdata char ao_cmd_lex_c; __xdata enum ao_cmd_status ao_cmd_status; -static __xdata uint8_t lex_echo; #define CMD_LEN 32 @@ -41,7 +40,7 @@ static void readline(void) { __xdata char c; - if (lex_echo) + if (ao_echo()) put_string("> "); cmd_len = 0; for (;;) { @@ -50,7 +49,7 @@ readline(void) /* backspace/delete */ if (c == '\010' || c == '\177') { if (cmd_len != 0) { - if (lex_echo) + if (ao_echo()) put_string("\010 \010"); --cmd_len; } @@ -60,7 +59,7 @@ readline(void) /* ^U */ if (c == '\025') { while (cmd_len != 0) { - if (lex_echo) + if (ao_echo()) put_string("\010 \010"); --cmd_len; } @@ -72,18 +71,18 @@ readline(void) c = '\n'; if (c == '\n') { - if (lex_echo) + if (ao_echo()) putchar('\n'); break; } if (cmd_len >= CMD_LEN - 2) { - if (lex_echo) + if (ao_echo()) putchar('\007'); continue; } cmd_line[cmd_len++] = c; - if (lex_echo) + if (ao_echo()) putchar(c); } cmd_line[cmd_len++] = '\n'; @@ -198,7 +197,8 @@ static void echo(void) { ao_cmd_hex(); - lex_echo = ao_cmd_lex_i != 0; + if (ao_cmd_status == ao_cmd_success) + ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; } static void @@ -272,7 +272,6 @@ ao_cmd(void) __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); - lex_echo = 1; for (;;) { readline(); #if HAS_CMD_FILTER diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 3dd457f7..ec3b6607 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -23,7 +23,7 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) -static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; +__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; __data int8_t ao_cur_stdio; __data int8_t ao_num_stdios; @@ -31,15 +31,15 @@ void putchar(char c) { if (c == '\n') - (*stdios[ao_cur_stdio].putchar)('\r'); - (*stdios[ao_cur_stdio].putchar)(c); + (*ao_stdios[ao_cur_stdio].putchar)('\r'); + (*ao_stdios[ao_cur_stdio].putchar)(c); } void flush(void) { - if (stdios[ao_cur_stdio].flush) - stdios[ao_cur_stdio].flush(); + if (ao_stdios[ao_cur_stdio].flush) + ao_stdios[ao_cur_stdio].flush(); } __xdata uint8_t ao_stdin_ready; @@ -51,7 +51,7 @@ getchar(void) __reentrant __critical int8_t stdio = ao_cur_stdio; for (;;) { - c = stdios[stdio].pollchar(); + c = ao_stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) break; if (++stdio == ao_num_stdios) @@ -63,6 +63,12 @@ getchar(void) __reentrant __critical return c; } +uint8_t +ao_echo(void) +{ + return ao_stdios[ao_cur_stdio].echo; +} + void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), @@ -70,8 +76,9 @@ ao_add_stdio(char (*pollchar)(void), { if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); - stdios[ao_num_stdios].pollchar = pollchar; - stdios[ao_num_stdios].putchar = putchar; - stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios].putchar = putchar; + ao_stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].echo = 1; ao_num_stdios++; } -- cgit v1.2.3 From 8db5c52f1c76a05020e4e0afbe4ea27485ad9f82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 17:26:08 -0700 Subject: altos: Clean up BT serial communcations Disable echo on both ends in command mode to eliminate looping error values. Switch to 57600 baud to improve performance. Signed-off-by: Keith Packard --- src/ao_btm.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/ao_pins.h | 1 + 2 files changed, 214 insertions(+), 18 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 224d3e81..c7024ed3 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,56 +17,251 @@ #include "ao.h" -uint8_t ao_btm_enable; +uint8_t ao_btm_running; +uint8_t ao_btm_stdio; +__xdata uint8_t ao_btm_connected; +uint8_t ao_btm_chat; + +__xdata char ao_btm_buffer[1024]; +int ao_btm_ptr; + +#define AO_BTM_MAX_REPLY 16 +__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; + extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; +/* + * Read a line of data from the serial port, truncating + * it after a few characters. + */ + +uint8_t +ao_btm_get_line(void) +{ + uint8_t ao_btm_reply_len = 0; + char c; + + for (;;) { + + while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; + if (c == '\r' || c == '\n') + goto done; + } + for (c = 0; c < 10; c++) { + ao_delay(AO_MS_TO_TICKS(10)); + if (!ao_fifo_empty(ao_usart1_rx_fifo)) + break; + } + if (c == 10) + goto done; + } +done: + for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) + ao_btm_reply[c++] = '\0'; + return ao_btm_reply_len; +} + +/* + * Drain the serial port completely + */ void -ao_btm(void) +ao_btm_drain() +{ + while (ao_btm_get_line()) + ; +} + +void +ao_btm_echo(uint8_t echo) +{ + ao_stdios[ao_btm_stdio].echo = echo; +} + +/* + * A command line pre-processor to detect connect/disconnect messages + * and update the internal state + */ + +uint8_t +ao_cmd_filter(void) +{ + ao_cmd_lex(); + while (ao_cmd_lex_c != '\n') { + if (ao_match_word("CONNECT")) { + ao_btm_connected = 1; + ao_btm_echo(1); + ao_wakeup(&ao_btm_connected); + return 1; + } + if (ao_match_word("DISCONNECT")) { + ao_btm_connected = 0; + ao_btm_echo(0); + ao_wakeup(&ao_btm_connected); + return 1; + } + if (ao_match_word("ERROR")) + return 1; + if (ao_match_word("OK")) + return 1; + ao_cmd_lex(); + } + ao_cmd_status = 0; + return !ao_btm_connected; +} + +/* + * A wrapper for ao_serial_pollchar that + * doesn't return any characters while we're + * initializing the bluetooth device + */ +char +ao_btm_pollchar(void) { char c; - while (ao_btm_enable) { - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) - ao_usb_putchar(c); - else { - ao_usb_flush(); - ao_sleep(&ao_usart1_rx_fifo); + if (!ao_btm_running) + return AO_READ_AGAIN; + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; + return c; +} + +/* + * Wait for the bluetooth device to return + * status from the previously executed command + */ +uint8_t +ao_btm_wait_reply(void) +{ + for (;;) { + ao_btm_get_line(); + if (!strcmp(ao_btm_reply, "OK")) + return 1; + if (!strcmp(ao_btm_reply, "ERROR")) + return -1; + if (ao_btm_reply[0] == '\0') + return 0; + } +} + +void +ao_btm_cmd(__code char *cmd) +{ + ao_cur_stdio = ao_btm_stdio; + printf(cmd); + ao_btm_wait_reply(); +} + +/* + * A thread to initialize the bluetooth device and + * hang around to blink the LED when connected + */ +void +ao_btm(void) +{ + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_add_stdio(ao_btm_pollchar, + ao_serial_putchar, + NULL); + ao_btm_stdio = ao_num_stdios - 1; + ao_cur_stdio = ao_btm_stdio; + ao_btm_echo(0); + ao_btm_drain(); + ao_delay(AO_SEC_TO_TICKS(1)); + printf("+++"); + ao_btm_drain(); + ao_delay(AO_SEC_TO_TICKS(1)); + printf("\r"); + ao_btm_drain(); + ao_btm_cmd("ATQ0\r"); + ao_btm_cmd("ATE0\r"); + ao_btm_cmd("ATH\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + ao_btm_cmd("ATC0\r"); + ao_btm_cmd("ATL4\r"); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_btm_drain(); + printf("ATN=TeleBT-%d\r", ao_serial_number); + ao_btm_wait_reply(); + ao_btm_running = 1; + for (;;) { + while (!ao_btm_connected && !ao_btm_chat) + ao_sleep(&ao_btm_connected); + if (ao_btm_chat) { + ao_btm_running = 0; + while (ao_btm_chat) { + char c; + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + ao_usb_putchar(c); + else { + ao_usb_flush(); + ao_sleep(&ao_usart1_rx_fifo); + } + } + ao_btm_running = 1; + } + while (ao_btm_connected) { + ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); + ao_delay(AO_SEC_TO_TICKS(3)); } } - ao_exit(); } -__xdata struct ao_task ao_btm_task; +__xdata struct ao_task ao_btm_task; +/* + * Connect directly to the bluetooth device, mostly + * useful for testing + */ static void ao_btm_forward(void) { char c; - ao_btm_enable = 1; - flush(); - ao_add_task(&ao_btm_task, ao_btm, "btm"); + ao_btm_chat = 1; + ao_wakeup(&ao_btm_connected); + ao_usb_flush(); while ((c = ao_usb_getchar()) != '~') { if (c == '\n') c = '\r'; ao_serial_putchar(c); } - ao_btm_enable = 0; - while (ao_btm_task.wchan) { + ao_btm_chat = 0; + while (!ao_btm_running) { ao_wakeup(&ao_usart1_rx_fifo); ao_delay(AO_MS_TO_TICKS(10)); } } +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ + int i; + + for (i = 0; i < ao_btm_ptr; i++) + putchar(ao_btm_buffer[i]); + putchar('\n'); +} + __code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_forward, "B \0BTM serial link." }, + { ao_btm_forward, "B\0BTM serial link." }, + { ao_btm_dump, "d\0Dump btm buffer." }, { 0, NULL }, }; - void ao_btm_init (void) { ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_add_task(&ao_btm_task, ao_btm, "bt"); ao_cmd_register(&ao_btm_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index a4ebd63b..ed42df8b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -224,6 +224,7 @@ #define HAS_BEEP 0 #define HAS_SERIAL_1 1 #define USE_SERIAL_STDIN 1 + #define HAS_CMD_FILTER 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 -- cgit v1.2.3 From 835ab3a8c2741a09b27de58c37439a193c9919ce Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 19:35:00 -0700 Subject: altosui: Add missing AltosTelemetryMap.java file Signed-off-by: Keith Packard --- altosui/.gitignore | 2 ++ altosui/AltosTelemetryMap.java | 63 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 altosui/AltosTelemetryMap.java diff --git a/altosui/.gitignore b/altosui/.gitignore index 89be1d53..6d65611f 100644 --- a/altosui/.gitignore +++ b/altosui/.gitignore @@ -4,10 +4,12 @@ macosx/ fat/ Manifest.txt Manifest-fat.txt +AltosVersion.java libaltosJNI classes altosui altosui-test +altosui-jdb classaltosui.stamp Altos-Linux-*.tar.bz2 Altos-Mac-*.zip diff --git a/altosui/AltosTelemetryMap.java b/altosui/AltosTelemetryMap.java new file mode 100644 index 00000000..d906100f --- /dev/null +++ b/altosui/AltosTelemetryMap.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryMap extends HashMap { + public boolean has(String key) { + return containsKey(key); + } + + public String get_string(String key) throws ParseException { + if (!has(key)) + throw new ParseException ("missing " + key, 0); + return (String) get(key); + } + + public String get_string(String key, String def) { + if (has(key)) + return get(key); + else + return def; + } + + public int get_int(String key) throws ParseException { + return AltosParse.parse_int(get_string(key)); + } + + public int get_int(String key, int def) throws ParseException { + if (has(key)) + return get_int(key); + else + return def; + } + + public double get_double(String key, double def, double scale) throws ParseException { + if (has(key)) + return get_int(key) * scale; + else + return def; + } + + public AltosTelemetryMap(String[] words, int start) { + for (int i = start; i < words.length - 1; i += 2) + put(words[i], words[i+1]); + } +} -- cgit v1.2.3 From 1a54a58d72147888f783a3caf364479efff4ed9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 7 Apr 2011 22:00:38 -0700 Subject: altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. PIo(6) appears to be an active-low indication of the Bluetooth connection status. Hook this up using an interrupt to track the link state instead of using in-band status messages. Signed-off-by: Keith Packard --- src/ao.h | 5 ++ src/ao_btm.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/ao_pins.h | 1 + src/ao_usb.c | 4 + src/cc1111.h | 8 ++ 5 files changed, 203 insertions(+), 44 deletions(-) diff --git a/src/ao.h b/src/ao.h index 9b375894..dad1f3df 100644 --- a/src/ao.h +++ b/src/ao.h @@ -107,6 +107,7 @@ ao_start_scheduler(void); #define AO_PANIC_REBOOT 8 /* Reboot failed */ #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ +#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ /* Stop the operating system, beeping and blinking the reason */ void @@ -1366,6 +1367,10 @@ ao_packet_slave_init(uint8_t enable); /* ao_btm.c */ +/* Shared by USB, so the USB code calls this function */ +void +ao_btm_isr(void); + void ao_btm_init(void); diff --git a/src/ao_btm.c b/src/ao_btm.c index c7024ed3..71907f86 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -18,12 +18,47 @@ #include "ao.h" uint8_t ao_btm_running; -uint8_t ao_btm_stdio; +int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; uint8_t ao_btm_chat; __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; +char ao_btm_dir; + +uint8_t ao_btm_send_chars = 0; + +void +ao_btm_putchar(char c); + +static void +ao_btm_add_char(char c) +{ + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ + if (dir != ao_btm_dir) { + ao_btm_add_char(dir); + ao_btm_dir = dir; + } + ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ + ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ + ao_btm_log_char(c, '<'); +} #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -44,10 +79,9 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; if (c == '\r' || c == '\n') goto done; } @@ -89,20 +123,14 @@ ao_btm_echo(uint8_t echo) uint8_t ao_cmd_filter(void) { + if (ao_cur_stdio != ao_btm_stdio) + return 0; ao_cmd_lex(); while (ao_cmd_lex_c != '\n') { - if (ao_match_word("CONNECT")) { - ao_btm_connected = 1; - ao_btm_echo(1); - ao_wakeup(&ao_btm_connected); + if (ao_match_word("CONNECT")) return 1; - } - if (ao_match_word("DISCONNECT")) { - ao_btm_connected = 0; - ao_btm_echo(0); - ao_wakeup(&ao_btm_connected); + if (ao_match_word("DISCONNECT")) return 1; - } if (ao_match_word("ERROR")) return 1; if (ao_match_word("OK")) @@ -126,11 +154,25 @@ ao_btm_pollchar(void) return AO_READ_AGAIN; c = ao_serial_pollchar(); if (c != AO_READ_AGAIN) - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; + ao_btm_log_in_char(c); return c; } +void +ao_btm_putchar(char c) +{ + if (!ao_btm_send_chars) { + ao_btm_log_out_char(c); + ao_serial_putchar(c); + } +} + +void +ao_btm_stdio_putchar(char c) { + if (ao_btm_connected) + ao_btm_putchar(c); +} + /* * Wait for the bluetooth device to return * status from the previously executed command @@ -140,9 +182,9 @@ ao_btm_wait_reply(void) { for (;;) { ao_btm_get_line(); - if (!strcmp(ao_btm_reply, "OK")) + if (!strncmp(ao_btm_reply, "OK", 2)) return 1; - if (!strcmp(ao_btm_reply, "ERROR")) + if (!strncmp(ao_btm_reply, "ERROR", 5)) return -1; if (ao_btm_reply[0] == '\0') return 0; @@ -150,13 +192,50 @@ ao_btm_wait_reply(void) } void +ao_btm_string(__code char *cmd) +{ + char c; + + while (c = *cmd++) + ao_btm_putchar(c); +} + +uint8_t ao_btm_cmd(__code char *cmd) { - ao_cur_stdio = ao_btm_stdio; - printf(cmd); - ao_btm_wait_reply(); + ao_btm_drain(); + ao_btm_string(cmd); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_set_name(void) +{ + char sn[7]; + char *s = sn + 7; + char c; + int n; + ao_btm_string("ATN=TeleBT-"); + *--s = '\0'; + n = ao_serial_number; + do { + *--s = '0' + n % 10; + } while (n /= 10); + while ((c = *s++)) + ao_btm_putchar(c); + return ao_btm_wait_reply(); } +uint8_t +ao_btm_try_speed(uint8_t speed) +{ + ao_serial_set_speed(speed); + ao_btm_drain(); + (void) ao_btm_cmd("\rATE0\rATQ0\r"); + if (ao_btm_cmd("AT\r") == 1) + return 1; + return 0; +} /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -164,30 +243,36 @@ ao_btm_cmd(__code char *cmd) void ao_btm(void) { - ao_serial_set_speed(AO_SERIAL_SPEED_19200); ao_add_stdio(ao_btm_pollchar, - ao_serial_putchar, + ao_btm_stdio_putchar, NULL); ao_btm_stdio = ao_num_stdios - 1; - ao_cur_stdio = ao_btm_stdio; ao_btm_echo(0); - ao_btm_drain(); - ao_delay(AO_SEC_TO_TICKS(1)); - printf("+++"); - ao_btm_drain(); - ao_delay(AO_SEC_TO_TICKS(1)); - printf("\r"); - ao_btm_drain(); - ao_btm_cmd("ATQ0\r"); + + /* + * The first time we connect, the BTM-180 comes up at 19200 baud. + * After that, it will remember and come up at 57600 baud. So, see + * if it is already running at 57600 baud, and if that doesn't work + * then tell it to switch to 57600 from 19200 baud. + */ + while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) + ao_btm_cmd("ATL4\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + } + + /* Disable echo */ ao_btm_cmd("ATE0\r"); - ao_btm_cmd("ATH\r"); - ao_delay(AO_SEC_TO_TICKS(1)); - ao_btm_cmd("ATC0\r"); - ao_btm_cmd("ATL4\r"); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - ao_btm_drain(); - printf("ATN=TeleBT-%d\r", ao_serial_number); - ao_btm_wait_reply(); + + /* Enable flow control */ + ao_btm_cmd("ATC1\r"); + + /* Set the reported name to something we can find on the host */ + ao_btm_set_name(); + + /* Turn off status reporting */ + ao_btm_cmd("ATQ1\r"); + ao_btm_running = 1; for (;;) { while (!ao_btm_connected && !ao_btm_chat) @@ -197,9 +282,10 @@ ao_btm(void) while (ao_btm_chat) { char c; c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) + if (c != AO_READ_AGAIN) { + ao_btm_log_in_char(c); ao_usb_putchar(c); - else { + } else { ao_usb_flush(); ao_sleep(&ao_usart1_rx_fifo); } @@ -229,7 +315,7 @@ ao_btm_forward(void) ao_usb_flush(); while ((c = ao_usb_getchar()) != '~') { if (c == '\n') c = '\r'; - ao_serial_putchar(c); + ao_btm_putchar(c); } ao_btm_chat = 0; while (!ao_btm_running) { @@ -245,15 +331,56 @@ static void ao_btm_dump(void) { int i; + char c; - for (i = 0; i < ao_btm_ptr; i++) - putchar(ao_btm_buffer[i]); + for (i = 0; i < ao_btm_ptr; i++) { + c = ao_btm_buffer[i]; + if (c < ' ' && c != '\n') + printf("\\%03o", ((int) c) & 0xff); + else + putchar(ao_btm_buffer[i]); + } putchar('\n'); } +static void +ao_btm_speed(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_u32 == 57600) + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + else if (ao_cmd_lex_u32 == 19200) + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + else + ao_cmd_status = ao_cmd_syntax_error; +} + +void +ao_btm_check_link() __critical +{ + if (P2_1) { + ao_btm_connected = 0; + PICTL |= PICTL_P2ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~PICTL_P2ICON; + } +} + +void +ao_btm_isr(void) +{ + if (P2IFG & (1 << 1)) { + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); + } + P2IFG = 0; +} + __code struct ao_cmds ao_btm_cmds[] = { { ao_btm_forward, "B\0BTM serial link." }, { ao_btm_dump, "d\0Dump btm buffer." }, + { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, { 0, NULL }, }; @@ -262,6 +389,20 @@ ao_btm_init (void) { ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); + + /* + * Configure link status line + */ + + /* Set P2_1 to input, pull-down */ + P2DIR &= ~(1 << 1); + P2INP |= P2INP_MDP2_1_TRISTATE; + + /* Enable P2 interrupts */ + IEN2 |= IEN2_P2IE; + ao_btm_check_link(); + PICTL |= PICTL_P2IEN; + ao_add_task(&ao_btm_task, ao_btm, "bt"); ao_cmd_register(&ao_btm_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index ed42df8b..1344dcaa 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -228,6 +228,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_BTM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 diff --git a/src/ao_usb.c b/src/ao_usb.c index b4e3f1fe..ece6756a 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -46,6 +46,7 @@ void ao_usb_isr(void) __interrupt 6 { USBIF = 0; + IRCON2 &= ~IRCON2_USBIF; ao_usb_iif |= USBIIF; if (ao_usb_iif & 1) ao_wakeup(&ao_usb_task); @@ -57,6 +58,9 @@ ao_usb_isr(void) __interrupt 6 if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); +#if HAS_BTM + ao_btm_isr(); +#endif } struct ao_usb_setup { diff --git a/src/cc1111.h b/src/cc1111.h index a72d7416..a07490e5 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -662,6 +662,14 @@ sfr at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) +sfr at 0x8C PICTL; +#define PICTL_P2IEN (1 << 5) +#define PICTL_P0IENH (1 << 4) +#define PICTL_P0IENL (1 << 3) +#define PICTL_P2ICON (1 << 2) +#define PICTL_P1ICON (1 << 1) +#define PICTL_P0ICON (1 << 0) + /* GPIO pins */ sfr at 0x80 P0; -- cgit v1.2.3 From bf1c7df5301a1727e871a8447f835fe75bdce3fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Apr 2011 10:12:50 -0700 Subject: altosui: Add TeleBT USB device support TeleBT can work just like a TeleDongle over USB. Signed-off-by: Keith Packard --- altosui/AltosDevice.java | 14 +++++++++++--- altosui/libaltos/libaltos.h | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index f0fda57b..b7aa38f6 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -81,15 +81,21 @@ public class AltosDevice extends altos_device { return 0x000d; } + static int usb_product_telebt() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEBT; + return 0x000e; + } + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); public final static int product_altusmetrum = usb_product_altusmetrum(); public final static int product_telemetrum = usb_product_telemetrum(); public final static int product_teledongle = usb_product_teledongle(); public final static int product_teleterra = usb_product_teleterra(); + public final static int product_telebt = usb_product_telebt(); public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; @@ -98,7 +104,7 @@ public class AltosDevice extends altos_device { if (name == null) name = "Altus Metrum"; return String.format("%-20.20s %4d %s", - getName(), getSerial(), getPath()); + name, getSerial(), getPath()); } public String toShortString() { @@ -129,7 +135,9 @@ public class AltosDevice extends altos_device { return true; if (want_product == product_basestation) - return matchProduct(product_teledongle) || matchProduct(product_teleterra); + return matchProduct(product_teledongle) || + matchProduct(product_teleterra) || + matchProduct(product_telebt); int have_product = getProduct(); diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 6e94899e..0e5691cb 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -40,6 +40,7 @@ #define USB_PRODUCT_TELEMETRUM 0x000b #define USB_PRODUCT_TELEDONGLE 0x000c #define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_TELEBT 0x000e #define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a #define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 -- cgit v1.2.3 From 8dd455204cf8712fa8c142b0c0517cec1bf5fd0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Apr 2011 10:13:55 -0700 Subject: altosui: Add low-level Bluetooth APIs Adds the JNI functions to query and connect to arbitrary bluetooth devices. Adds Java wrappers to construct a list of proximate bluetooth devices. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 142 ++++++++++ altosui/AltosEepromDownload.java | 1 + altosui/Makefile.am | 1 + altosui/libaltos/Makefile.am | 2 +- altosui/libaltos/cjnitest.c | 26 ++ altosui/libaltos/libaltos.c | 574 ++++++++++++++++++++++++--------------- altosui/libaltos/libaltos.h | 21 ++ 7 files changed, 543 insertions(+), 224 deletions(-) create mode 100644 altosui/AltosBTDevice.java diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java new file mode 100644 index 00000000..8eb18bb9 --- /dev/null +++ b/altosui/AltosBTDevice.java @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.util.*; +import libaltosJNI.*; + +public class AltosBTDevice extends altos_bt_device { + + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + loaded_library = false; + } + initialized = true; + } + return loaded_library; + } + + static String bt_product_telebt() { + if (load_library()) + return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT; + return "TeleBT"; + } + + public final static String bt_product_telebt = bt_product_telebt(); + public final static String bt_product_any = "Any"; + public final static String bt_product_basestation = "Basestation"; + + public String getProduct() { + String name = getName(); + if (name == null) + return "Altus Metrum"; + int dash = name.lastIndexOf("-"); + if (dash < 0) + return name; + return name.substring(0,dash); + } + + public int getSerial() { + String name = getName(); + if (name == null) + return 0; + int dash = name.lastIndexOf("-"); + if (dash < 0 || dash >= name.length()) + return 0; + String sn = name.substring(dash + 1, name.length()); + try { + return Integer.parseInt(sn); + } catch (NumberFormatException ne) { + return 0; + } + } + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + getProduct(), getSerial(), getAddr()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + getProduct(), getSerial(), getAddr()); + + } + + public boolean isAltusMetrum() { + if (getName().startsWith(bt_product_telebt)) + return true; + return false; + } + + public boolean matchProduct(String want_product) { + + if (!isAltusMetrum()) + return false; + + if (want_product.equals(bt_product_any)) + return true; + + if (want_product.equals(bt_product_basestation)) + return matchProduct(bt_product_telebt); + + if (want_product.equals(getProduct())) + return true; + + return false; + } + + static AltosBTDevice[] list(String product) { + if (!load_library()) + return null; + + SWIGTYPE_p_altos_bt_list list = libaltos.altos_bt_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + SWIGTYPE_p_altos_file file; + + for (;;) { + AltosBTDevice device = new AltosBTDevice(); + if (libaltos.altos_bt_list_next(list, device) == 0) + break; + if (device.matchProduct(product)) + device_list.add(device); + } + libaltos.altos_bt_list_finish(list); + } + + AltosBTDevice[] devices = new AltosBTDevice[device_list.size()]; + for (int i = 0; i < device_list.size(); i++) + devices[i] = device_list.get(i); + return devices; + } +} \ No newline at end of file diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index fad16460..5c704968 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -158,6 +158,7 @@ public class AltosEepromDownload implements Runnable { r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0); if (s == Altos.ao_flight_landed) done = true; + state = s; any_valid = true; } else { if (v != 0xffff) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 01fe50c8..5b11d1b0 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -26,6 +26,7 @@ altosui_JAVA = \ AltosDescent.java \ AltosDeviceDialog.java \ AltosDevice.java \ + AltosBTDevice.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am index 388d2104..3f5f3ee2 100644 --- a/altosui/libaltos/Makefile.am +++ b/altosui/libaltos/Makefile.am @@ -16,7 +16,7 @@ noinst_PROGRAMS=cjnitest cjnitest_LDADD=libaltos.la -LIBS= +LIBS=-lbluetooth HFILES=libaltos.h diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index c6d6e069..79561643 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -14,6 +14,8 @@ main () { struct altos_device device; struct altos_list *list; + struct altos_bt_device bt_device; + struct altos_bt_list *bt_list; altos_init(); list = altos_list_start(); @@ -39,5 +41,29 @@ main () altos_close(file); } altos_list_finish(list); + bt_list = altos_bt_list_start(); + while (altos_bt_list_next(bt_list, &bt_device)) { + printf ("%s %s\n", bt_device.name, bt_device.addr); + if (strncmp(bt_device.name, "TeleBT", 6) == 0) { + struct altos_file *file; + + int c; + file = altos_bt_open(&bt_device); + if (!file) { + printf("altos_bt_open failed\n"); + continue; + } + altos_puts(file,"v\nc s\n"); + altos_flush(file); + while ((c = altos_getchar(file, 100)) >= 0) { + putchar(c); + } + if (c != LIBALTOS_TIMEOUT) + printf("getchar returns %d\n", c); + altos_close(file); + } + } + altos_bt_list_finish(bt_list); altos_fini(); + return 0; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 465f0ac8..13635a0d 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -56,6 +56,230 @@ altos_strndup (const char *s, size_t n) #define altos_strndup strndup #endif +#ifdef POSIX_TTY + +#include +#include +#include +#include +#include + +#define USB_BUF_SIZE 64 + +struct altos_file { + int fd; +#ifdef USE_POLL + int pipe[2]; +#else + int out_fd; +#endif + unsigned char out_data[USB_BUF_SIZE]; + int out_used; + unsigned char in_data[USB_BUF_SIZE]; + int in_used; + int in_read; +}; + +PUBLIC struct altos_file * +altos_open(struct altos_device *device) +{ + struct altos_file *file = calloc (sizeof (struct altos_file), 1); + int ret; + struct termios term; + + if (!file) + return NULL; + + file->fd = open(device->path, O_RDWR | O_NOCTTY); + if (file->fd < 0) { + perror(device->path); + 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; +} + +PUBLIC void +altos_close(struct altos_file *file) +{ + if (file->fd != -1) { + int fd = file->fd; + file->fd = -1; +#ifdef USE_POLL + write(file->pipe[1], "\r", 1); +#else + close(file->out_fd); + file->out_fd = -1; +#endif + close(fd); + } +} + +PUBLIC void +altos_free(struct altos_file *file) +{ + altos_close(file); + free(file); +} + +PUBLIC int +altos_flush(struct altos_file *file) +{ + if (file->out_used && 0) { + printf ("flush \""); + fwrite(file->out_data, 1, file->out_used, stdout); + printf ("\"\n"); + } + while (file->out_used) { + int ret; + + if (file->fd < 0) + return -EBADF; +#ifdef USE_POLL + ret = write (file->fd, file->out_data, file->out_used); +#else + ret = write (file->out_fd, file->out_data, file->out_used); +#endif + if (ret < 0) + return -errno; + if (ret) { + memmove(file->out_data, file->out_data + ret, + file->out_used - ret); + file->out_used -= ret; + } + } + return 0; +} + +PUBLIC int +altos_putchar(struct altos_file *file, char c) +{ + int ret; + + if (file->out_used == USB_BUF_SIZE) { + ret = altos_flush(file); + if (ret) { + return ret; + } + } + file->out_data[file->out_used++] = c; + ret = 0; + if (file->out_used == USB_BUF_SIZE) + ret = altos_flush(file); + return 0; +} + +#ifdef USE_POLL +#include +#endif + +static int +altos_fill(struct altos_file *file, int timeout) +{ + int ret; +#ifdef USE_POLL + struct pollfd fd[2]; +#endif + + if (timeout == 0) + timeout = -1; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; +#ifdef USE_POLL + fd[0].fd = file->fd; + fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; + fd[1].fd = file->pipe[0]; + fd[1].events = POLLIN; + ret = poll(fd, 2, timeout); + if (ret < 0) { + 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 + } + } + if (file->in_used && 0) { + printf ("fill \""); + fwrite(file->in_data, 1, file->in_used, stdout); + printf ("\"\n"); + } + return 0; +} + +PUBLIC int +altos_getchar(struct altos_file *file, int timeout) +{ + int ret; + while (file->in_read == file->in_used) { + if (file->fd < 0) + return LIBALTOS_ERROR; + ret = altos_fill(file, timeout); + if (ret) + return ret; + } + return file->in_data[file->in_read++]; +} + +#endif /* POSIX_TTY */ + /* * Scan for Altus Metrum devices by looking through /sys */ @@ -68,6 +292,10 @@ altos_strndup (const char *s, size_t n) #include #include #include +#include +#include +#include +#include static char * cc_fullname (char *dir, char *file) @@ -354,6 +582,129 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } +struct altos_bt_list { + inquiry_info *ii; + int sock; + int dev_id; + int rsp; + int num_rsp; +}; + +#define INQUIRY_MAX_RSP 255 +#define INQUIRY_LEN 8 + +struct altos_bt_list * +altos_bt_list_start(void) +{ + struct altos_bt_list *bt_list; + + bt_list = calloc(1, sizeof (struct altos_bt_list)); + if (!bt_list) + goto no_bt_list; + + bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info)); + if (!bt_list->ii) + goto no_ii; + bt_list->dev_id = hci_get_route(NULL); + if (bt_list->dev_id < 0) + goto no_dev_id; + + bt_list->sock = hci_open_dev(bt_list->dev_id); + if (bt_list->sock < 0) + goto no_sock; + + bt_list->num_rsp = hci_inquiry(bt_list->dev_id, + INQUIRY_LEN, + INQUIRY_MAX_RSP, + NULL, + &bt_list->ii, + IREQ_CACHE_FLUSH); + if (bt_list->num_rsp < 0) + goto no_rsp; + + bt_list->rsp = 0; + return bt_list; + +no_rsp: + close(bt_list->sock); +no_sock: +no_dev_id: + free(bt_list->ii); +no_ii: + free(bt_list); +no_bt_list: + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + inquiry_info *ii; + + if (bt_list->rsp >= bt_list->num_rsp) + return 0; + + ii = &bt_list->ii[bt_list->rsp]; + ba2str(&ii->bdaddr, device->addr); + memset(&device->name, '\0', sizeof (device->name)); + if (hci_read_remote_name(bt_list->sock, &ii->bdaddr, + sizeof (device->name), + device->name, 0) < 0) { + strcpy(device->name, "[unknown]"); + } + bt_list->rsp++; + return 1; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ + close(bt_list->sock); + free(bt_list->ii); + free(bt_list); +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + struct sockaddr_rc addr = { 0 }; + int s, status; + struct altos_file *file; + + file = calloc(1, sizeof (struct altos_file)); + if (!file) + goto no_file; + file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); + if (file->fd < 0) + goto no_sock; + + addr.rc_family = AF_BLUETOOTH; + addr.rc_channel = 1; + str2ba(device->addr, &addr.rc_bdaddr); + + status = connect(file->fd, + (struct sockaddr *)&addr, + sizeof(addr)); + if (status < 0) { + perror("connect"); + goto no_link; + } + +#ifdef USE_POLL + pipe(file->pipe); +#else + file->out_fd = dup(file->fd); +#endif + return file; +no_link: + close(s); +no_sock: + free(file); +no_file: + return NULL; +} + #endif #ifdef DARWIN @@ -468,229 +819,6 @@ altos_list_finish(struct altos_list *list) #endif -#ifdef POSIX_TTY - -#include -#include -#include -#include -#include - -#define USB_BUF_SIZE 64 - -struct altos_file { - int fd; -#ifdef USE_POLL - int pipe[2]; -#else - int out_fd; -#endif - unsigned char out_data[USB_BUF_SIZE]; - int out_used; - unsigned char in_data[USB_BUF_SIZE]; - int in_used; - int in_read; -}; - -PUBLIC struct altos_file * -altos_open(struct altos_device *device) -{ - struct altos_file *file = calloc (sizeof (struct altos_file), 1); - int ret; - struct termios term; - - if (!file) - return NULL; - - file->fd = open(device->path, O_RDWR | O_NOCTTY); - if (file->fd < 0) { - perror(device->path); - 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; -} - -PUBLIC void -altos_close(struct altos_file *file) -{ - if (file->fd != -1) { - int fd = file->fd; - file->fd = -1; -#ifdef USE_POLL - write(file->pipe[1], "\r", 1); -#else - close(file->out_fd); - file->out_fd = -1; -#endif - close(fd); - } -} - -PUBLIC void -altos_free(struct altos_file *file) -{ - altos_close(file); - free(file); -} - -PUBLIC int -altos_flush(struct altos_file *file) -{ - if (file->out_used && 0) { - printf ("flush \""); - fwrite(file->out_data, 1, file->out_used, stdout); - printf ("\"\n"); - } - while (file->out_used) { - int ret; - - if (file->fd < 0) - return -EBADF; -#ifdef USE_POLL - ret = write (file->fd, file->out_data, file->out_used); -#else - ret = write (file->out_fd, file->out_data, file->out_used); -#endif - if (ret < 0) - return -errno; - if (ret) { - memmove(file->out_data, file->out_data + ret, - file->out_used - ret); - file->out_used -= ret; - } - } - return 0; -} - -PUBLIC int -altos_putchar(struct altos_file *file, char c) -{ - int ret; - - if (file->out_used == USB_BUF_SIZE) { - ret = altos_flush(file); - if (ret) { - return ret; - } - } - file->out_data[file->out_used++] = c; - ret = 0; - if (file->out_used == USB_BUF_SIZE) - ret = altos_flush(file); - return 0; -} - -#ifdef USE_POLL -#include -#endif - -static int -altos_fill(struct altos_file *file, int timeout) -{ - int ret; -#ifdef USE_POLL - struct pollfd fd[2]; -#endif - - if (timeout == 0) - timeout = -1; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; -#ifdef USE_POLL - fd[0].fd = file->fd; - fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL; - fd[1].fd = file->pipe[0]; - fd[1].events = POLLIN; - ret = poll(fd, 2, timeout); - if (ret < 0) { - 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 - } - } - if (file->in_used && 0) { - printf ("fill \""); - fwrite(file->in_data, 1, file->in_used, stdout); - printf ("\"\n"); - } - return 0; -} - -PUBLIC int -altos_getchar(struct altos_file *file, int timeout) -{ - int ret; - while (file->in_read == file->in_used) { - if (file->fd < 0) - return LIBALTOS_ERROR; - ret = altos_fill(file, timeout); - if (ret) - return ret; - } - return file->in_data[file->in_read++]; -} - -#endif /* POSIX_TTY */ #ifdef WINDOWS diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 0e5691cb..9c3f9655 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -58,6 +58,15 @@ struct altos_device { //%mutable; }; +#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" + +struct altos_bt_device { + //%immutable; + char name[256]; + char addr[20]; + //%mutable; +}; + #define LIBALTOS_SUCCESS 0 #define LIBALTOS_ERROR -1 #define LIBALTOS_TIMEOUT -2 @@ -100,4 +109,16 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); +PUBLIC struct altos_bt_list * +altos_bt_list_start(void); + +PUBLIC int +altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); + +PUBLIC void +altos_bt_list_finish(struct altos_bt_list *list); + +PUBLIC struct altos_file * +altos_bt_open(struct altos_bt_device *device); + #endif /* _LIBALTOS_H_ */ -- cgit v1.2.3 From 7f49d694e776819e03b2c708e1c4ee23ba311430 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Apr 2011 22:53:12 -0700 Subject: altos/altosui: Log averaged baro sensor data in Tm/Tn Instead of logging the best height guess from the kalman filter, log barometer data. The logged data consists of the average value betwen log points to reduce noise. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosDataPoint.java | 1 + altosui/AltosDataPointReader.java | 1 + altosui/AltosEepromDownload.java | 3 ++- altosui/AltosEepromIterable.java | 9 +++++++-- altosui/AltosGraphUI.java | 2 +- src/ao_log_tiny.c | 35 +++++++++++++++++++++++++---------- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 1f791da5..54aced32 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -34,7 +34,7 @@ public class Altos { static final int AO_LOG_GPS_ALT = 'H'; static final int AO_LOG_GPS_SAT = 'V'; static final int AO_LOG_GPS_DATE = 'Y'; - static final int AO_LOG_HEIGHT = 'h'; + static final int AO_LOG_PRESSURE = 'P'; /* Added for header fields in eeprom files */ static final int AO_LOG_CONFIG_VERSION = 1000; diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java index 66313e03..5e077320 100644 --- a/altosui/AltosDataPoint.java +++ b/altosui/AltosDataPoint.java @@ -25,5 +25,6 @@ interface AltosDataPoint { double battery_voltage(); double drogue_voltage(); double main_voltage(); + boolean has_accel(); } diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index 4335421c..fa48013f 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -59,6 +59,7 @@ class AltosDataPointReader implements Iterable { public double battery_voltage() { return record.battery_voltage(); } public double drogue_voltage() { return record.drogue_voltage(); } public double main_voltage() { return record.main_voltage(); } + public boolean has_accel() { return has_accel; } }; } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index fad16460..a42f401c 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -162,7 +162,8 @@ public class AltosEepromDownload implements Runnable { } else { if (v != 0xffff) any_valid = true; - r = new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0); + + r = new AltosEepromRecord(Altos.AO_LOG_PRESSURE, tiny_tick, 0, v); /* * The flight software records ascent data every 100ms, and descent diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index 624e1dd3..16349b88 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -134,8 +134,13 @@ public class AltosEepromIterable extends AltosRecordIterable { eeprom.seen |= seen_sensor; has_accel = true; break; - case Altos.AO_LOG_HEIGHT: - state.height = (short) record.a; + case Altos.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } eeprom.seen |= seen_sensor; break; case Altos.AO_LOG_TEMP_VOLT: diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index e98c302b..4b994b47 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -35,7 +35,7 @@ public class AltosGraphUI extends JFrame AltosGraphTime.Element speed = new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { public void gotTimeData(double time, AltosDataPoint d) { - if (d.state() < Altos.ao_flight_drogue) { + if (d.state() < Altos.ao_flight_drogue && d.has_accel()) { series.add(time, d.accel_speed()); } else { series.add(time, d.baro_speed()); diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index f0c0662a..6c2468fc 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -44,9 +44,12 @@ static void ao_log_tiny_data(uint16_t d) void ao_log(void) { - uint16_t time; - int16_t delay; + uint16_t last_time; + uint16_t now; enum ao_flight_state ao_log_tiny_state; + int32_t sum; + int16_t count; + uint8_t ao_log_adc; ao_storage_setup(); @@ -57,9 +60,19 @@ ao_log(void) while (!ao_log_running) ao_sleep(&ao_log_running); - time = ao_time(); ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + sum = 0; + count = 0; + ao_log_adc = ao_sample_adc; + last_time = ao_time(); for (;;) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (ao_log_adc != ao_sample_adc) { + sum += ao_adc_ring[ao_log_adc].pres; + count++; + ao_log_adc = ao_adc_ring_next(ao_log_adc); + } if (ao_flight_state != ao_log_tiny_state) { ao_log_tiny_data(ao_flight_state | 0x8000); ao_log_tiny_state = ao_flight_state; @@ -69,14 +82,16 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_height); - time += ao_log_tiny_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); + if (!ao_log_running) + ao_exit(); + now = ao_time(); + if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { + ao_log_tiny_data(sum / count); + sum = 0; + count = 0; + last_time = now; + } } } -- cgit v1.2.3 From a0fb471ce10642fc4a4bd40e4a81f8d6fe7a7c21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Apr 2011 20:27:38 -0700 Subject: altosui: oops - lost state changes when downloading eeprom data. This would cause the reader to just keep reading past the end of the flight. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index a42f401c..3dd5b12f 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -155,8 +155,9 @@ public class AltosEepromDownload implements Runnable { int s = v ^ 0x8000; if (Altos.ao_flight_startup <= s && s <= Altos.ao_flight_invalid) { - r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, s, 0); - if (s == Altos.ao_flight_landed) + state = s; + r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, state, 0); + if (state == Altos.ao_flight_landed) done = true; any_valid = true; } else { -- cgit v1.2.3 From c269e263a6accd815ed5d08c0f5a6c3d5b9d3853 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Apr 2011 09:38:48 -0700 Subject: altos: Write a few pre-launch samples for Tm/Tn devices Record pre-launch samples in a small ring and flush that to flash when launch is detected. This provides a complete record of the flight, rather than simply starting after launch detect. Signed-off-by: Keith Packard --- src/ao_log_tiny.c | 91 +++++++++++++++++++++++++++++++++++++++++++------------ src/ao_pins.h | 1 + 2 files changed, 72 insertions(+), 20 deletions(-) diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 6c2468fc..d26e0080 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -19,8 +19,14 @@ static __data uint16_t ao_log_tiny_interval; -#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) #define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) +#if USE_FAST_ASCENT_LOG +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_PAD_RING 8 +#else +#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT +#define AO_PAD_RING 2 +#endif void ao_log_tiny_set_interval(uint16_t ticks) @@ -28,19 +34,47 @@ ao_log_tiny_set_interval(uint16_t ticks) ao_log_tiny_interval = ticks; } -static __xdata uint16_t ao_log_tiny_data_temp; static void ao_log_tiny_data(uint16_t d) { if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) ao_log_stop(); if (ao_log_running) { - ao_log_tiny_data_temp = (d); - ao_storage_write(ao_log_current_pos, &ao_log_tiny_data_temp, 2); + ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); ao_log_current_pos += 2; } } +static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; +static __pdata uint8_t ao_log_pad_ring_pos; + +#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) + +static void ao_log_tiny_queue(uint16_t d) +{ + ao_log_pad_ring[ao_log_pad_ring_pos] = d; + ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); +} + +static void ao_log_tiny_start(void) +{ + uint8_t p; + uint16_t d; + + ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + p = ao_log_pad_ring_pos; + do { + d = ao_log_pad_ring[p]; + /* + * ignore unwritten slots + */ + if (d) + ao_log_tiny_data(d); + p = ao_pad_ring_next(p); + } while (p != ao_log_pad_ring_pos); +} + void ao_log(void) { @@ -50,44 +84,61 @@ ao_log(void) int32_t sum; int16_t count; uint8_t ao_log_adc; + uint8_t ao_log_started = 0; ao_storage_setup(); ao_log_scan(); ao_log_tiny_state = ao_flight_invalid; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; - while (!ao_log_running) - ao_sleep(&ao_log_running); - - ao_log_tiny_data(ao_flight_number); - ao_log_tiny_data(ao_ground_pres); + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; sum = 0; count = 0; ao_log_adc = ao_sample_adc; last_time = ao_time(); for (;;) { + + /* + * Add in pending sample data + */ ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); while (ao_log_adc != ao_sample_adc) { sum += ao_adc_ring[ao_log_adc].pres; count++; ao_log_adc = ao_adc_ring_next(ao_log_adc); } - if (ao_flight_state != ao_log_tiny_state) { - ao_log_tiny_data(ao_flight_state | 0x8000); - ao_log_tiny_state = ao_flight_state; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; - if (ao_log_tiny_state <= ao_flight_coast) - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; - if (ao_log_tiny_state == ao_flight_landed) - ao_log_stop(); + if (ao_log_running) { + if (!ao_log_started) { + ao_log_tiny_start(); + ao_log_started = 1; + } + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; +#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; +#endif + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); + } } + /* Stop logging when told to */ - if (!ao_log_running) + if (!ao_log_running && ao_log_started) ao_exit(); + + /* + * Write out the sample when finished + */ now = ao_time(); if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { - ao_log_tiny_data(sum / count); + count = sum / count; + if (ao_log_started) + ao_log_tiny_data(count); + else + ao_log_tiny_queue(count); sum = 0; count = 0; last_time = now; diff --git a/src/ao_pins.h b/src/ao_pins.h index 30f2decc..2161c5d2 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -108,6 +108,7 @@ #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 #define AO_LED_GREEN 1 #define AO_LED_RED 2 -- cgit v1.2.3 From 5b3f18b38d80aa041b971204bf7a94278bd9584a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 8 Apr 2011 19:46:15 -0700 Subject: altosui: Add primitive bluetooth device manager UI. This isn't useful, but does inquire for available bluetooth devices and show them in a list. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 26 ----- altosui/AltosBTDeviceIterator.java | 68 ++++++++++++++ altosui/AltosBTManage.java | 188 +++++++++++++++++++++++++++++++++++++ altosui/AltosConfigureUI.java | 17 +++- altosui/AltosUI.java | 4 + altosui/Makefile.am | 2 + 6 files changed, 278 insertions(+), 27 deletions(-) create mode 100644 altosui/AltosBTDeviceIterator.java create mode 100644 altosui/AltosBTManage.java diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 8eb18bb9..233037de 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -113,30 +113,4 @@ public class AltosBTDevice extends altos_bt_device { return false; } - - static AltosBTDevice[] list(String product) { - if (!load_library()) - return null; - - SWIGTYPE_p_altos_bt_list list = libaltos.altos_bt_list_start(); - - ArrayList device_list = new ArrayList(); - if (list != null) { - SWIGTYPE_p_altos_file file; - - for (;;) { - AltosBTDevice device = new AltosBTDevice(); - if (libaltos.altos_bt_list_next(list, device) == 0) - break; - if (device.matchProduct(product)) - device_list.add(device); - } - libaltos.altos_bt_list_finish(list); - } - - AltosBTDevice[] devices = new AltosBTDevice[device_list.size()]; - for (int i = 0; i < device_list.size(); i++) - devices[i] = device_list.get(i); - return devices; - } } \ No newline at end of file diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java new file mode 100644 index 00000000..935bf822 --- /dev/null +++ b/altosui/AltosBTDeviceIterator.java @@ -0,0 +1,68 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.util.*; +import libaltosJNI.*; + +public class AltosBTDeviceIterator implements Iterator { + String product; + AltosBTDevice current; + boolean done; + SWIGTYPE_p_altos_bt_list list; + + public boolean hasNext() { + System.out.printf ("BT has next?\n"); + if (list == null) + return false; + if (current != null) + return true; + if (done) + return false; + current = new AltosBTDevice(); + while (libaltos.altos_bt_list_next(list, current) != 0) { + System.out.printf("Got BT device %s\n", current.toString()); +// if (current.matchProduct(product)) + return true; + } + current = null; + done = true; + return false; + } + + public AltosBTDevice next() { + if (hasNext()) { + AltosBTDevice next = current; + current = null; + return next; + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public AltosBTDeviceIterator(String in_product) { + product = in_product; + done = false; + current = null; + list = libaltos.altos_bt_list_start(); + System.out.printf("Iteration of BT list started\n"); + } +} diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java new file mode 100644 index 00000000..8e9e0f73 --- /dev/null +++ b/altosui/AltosBTManage.java @@ -0,0 +1,188 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosBTManage extends JDialog implements ActionListener { + String product; + LinkedBlockingQueue found_devices; + JFrame frame; + + class DeviceList extends JList implements Iterable { + LinkedList devices; + DefaultListModel list_model; + + public void add (AltosBTDevice device) { + devices.add(device); + list_model.addElement(device); + } + + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + + public Iterator iterator() { + return devices.iterator(); + } + + public DeviceList() { + devices = new LinkedList(); + list_model = new DefaultListModel(); + setModel(list_model); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setLayoutOrientation(JList.HORIZONTAL_WRAP); + setVisibleRowCount(-1); + } + } + + DeviceList visible_devices; + + DeviceList selected_devices; + + public void actionPerformed(ActionEvent e) { + } + + public void got_visible_device() { + while (!found_devices.isEmpty()) { + AltosBTDevice device = found_devices.remove(); + visible_devices.add(device); + } + } + + class BTGetVisibleDevices implements Runnable { + public void run () { + + try { + AltosBTDeviceIterator i = new AltosBTDeviceIterator(product); + AltosBTDevice device; + + while ((device = i.next()) != null) { + Runnable r; + + found_devices.add(device); + r = new Runnable() { + public void run() { + got_visible_device(); + } + }; + SwingUtilities.invokeLater(r); + } + } catch (Exception e) { + System.out.printf("uh-oh, exception %s\n", e.toString()); + } + } + } + + public AltosBTManage(String product, JFrame in_frame) { + frame = in_frame; + BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); + Thread t = new Thread(get_visible_devices); + t.start(); + + found_devices = new LinkedBlockingQueue(); + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(this); + + final JButton selectButton = new JButton("Select"); + selectButton.setActionCommand("select"); + selectButton.addActionListener(this); + getRootPane().setDefaultButton(selectButton); + + selected_devices = new DeviceList(); + JScrollPane selected_list_scroller = new JScrollPane(selected_devices); + selected_list_scroller.setPreferredSize(new Dimension(400, 80)); + selected_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + + visible_devices = new DeviceList(); + JScrollPane visible_list_scroller = new JScrollPane(visible_devices); + visible_list_scroller.setPreferredSize(new Dimension(400, 80)); + visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(selected_devices); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(selected_list_scroller); + listPane.add(visible_list_scroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + //Lay out the buttons from left to right. + JPanel buttonPane = new JPanel(); + buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); + buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); + buttonPane.add(Box.createHorizontalGlue()); + buttonPane.add(cancelButton); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(selectButton); + + //Put everything together, using the content pane's BorderLayout. + Container contentPane = getContentPane(); + contentPane.add(listPane, BorderLayout.CENTER); + contentPane.add(buttonPane, BorderLayout.PAGE_END); + + //Initialize values. +// list.setSelectedValue(initial, true); + pack(); + setLocationRelativeTo(frame); + setVisible(true); + } +} diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 9a292c91..a2755a06 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -49,6 +49,8 @@ public class AltosConfigureUI JRadioButton serial_debug; + JButton manage_bluetooth; + /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { AltosPreferences.set_callsign(callsign_value.getText()); @@ -199,6 +201,19 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(serial_debug, c); + manage_bluetooth = new JButton("Manage Bluetooth"); + manage_bluetooth.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + new AltosBTManage(AltosBTDevice.bt_product_any, owner); + } + }); + c.gridx = 1; + c.gridy = 6; + c.gridwidth = 3; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(manage_bluetooth, c); + /* And a close button at the bottom */ close = new JButton("Close"); close.addActionListener(new ActionListener() { @@ -207,7 +222,7 @@ public class AltosConfigureUI } }); c.gridx = 0; - c.gridy = 6; + c.gridy = 7; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 4d17b0d2..73ddf979 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -198,6 +198,10 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { + AltosBTManage bt_manage; + + bt_manage = new AltosBTManage(AltosBTDevice.bt_product_any, this); + bt_manage.list(); AltosDevice device = AltosDeviceDialog.show(AltosUI.this, AltosDevice.product_basestation); diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 5b11d1b0..37a40eaa 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -27,6 +27,8 @@ altosui_JAVA = \ AltosDeviceDialog.java \ AltosDevice.java \ AltosBTDevice.java \ + AltosBTDeviceIterator.java \ + AltosBTManage.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ -- cgit v1.2.3 From 9cdef76c1275b343099d0d01af82d7eadd36a410 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Apr 2011 10:12:29 -0700 Subject: altosui: Create abstract AltosDevice class This will wrap either USB or BT devices. The USB device constants have been moved to Altos.java Signed-off-by: Keith Packard --- altosui/Altos.java | 79 ++++++++++++++++ altosui/AltosConfig.java | 4 +- altosui/AltosDevice.java | 166 ++------------------------------- altosui/AltosDeviceDialog.java | 2 +- altosui/AltosEepromManage.java | 4 +- altosui/AltosFlashUI.java | 2 +- altosui/AltosIgnite.java | 2 +- altosui/AltosIgniteUI.java | 2 +- altosui/AltosSerial.java | 2 +- altosui/AltosSerialInUseException.java | 6 +- altosui/AltosUI.java | 6 +- altosui/AltosUSBDevice.java | 103 ++++++++++++++++++++ altosui/Makefile.am | 1 + 13 files changed, 206 insertions(+), 173 deletions(-) create mode 100644 altosui/AltosUSBDevice.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 1f791da5..5df004c5 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -21,6 +21,8 @@ import java.awt.*; import java.util.*; import java.text.*; +import libaltosJNI.*; + public class Altos { /* EEProm command letters */ static final int AO_LOG_FLIGHT = 'F'; @@ -222,4 +224,81 @@ public class Altos { input = input.substring(0,dot); return input.concat(extension); } + + static public boolean initialized = false; + static public boolean loaded_library = false; + + public static boolean load_library() { + if (!initialized) { + try { + System.loadLibrary("altos"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e) { + loaded_library = false; + } + initialized = true; + } + return loaded_library; + } + + static int usb_vendor_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_VENDOR_ALTUSMETRUM; + return 0x000a; + } + + static int usb_product_altusmetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + return 0x000a; + } + + static int usb_product_altusmetrum_min() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; + return 0x000a; + } + + static int usb_product_altusmetrum_max() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; + return 0x000d; + } + + static int usb_product_telemetrum() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEMETRUM; + return 0x000b; + } + + static int usb_product_teledongle() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEDONGLE; + return 0x000c; + } + + static int usb_product_teleterra() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELETERRA; + return 0x000d; + } + + static int usb_product_telebt() { + if (load_library()) + return libaltosConstants.USB_PRODUCT_TELEBT; + return 0x000e; + } + + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); + public final static int product_altusmetrum = usb_product_altusmetrum(); + public final static int product_telemetrum = usb_product_telemetrum(); + public final static int product_teledongle = usb_product_teledongle(); + public final static int product_teleterra = usb_product_teleterra(); + public final static int product_telebt = usb_product_telebt(); + public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); + public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); + + public final static int product_any = 0x10000; + public final static int product_basestation = 0x10000 + 1; } diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index f45e2040..c5de83f2 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -344,11 +344,11 @@ public class AltosConfig implements ActionListener { version = new string_ref("unknown"); product = new string_ref("unknown"); - device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + device = AltosDeviceDialog.show(owner, Altos.product_any); if (device != null) { try { serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) + if (!device.matchProduct(Altos.product_telemetrum)) remote = true; try { init_ui(); diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index b7aa38f6..3357c550 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -1,5 +1,5 @@ /* - * Copyright © 2010 Keith Packard + * Copyright © 2011 Keith Packard * * 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 @@ -20,159 +20,11 @@ import java.lang.*; import java.util.*; import libaltosJNI.*; -public class AltosDevice extends altos_device { - - static public boolean initialized = false; - static public boolean loaded_library = false; - - public static boolean load_library() { - if (!initialized) { - try { - System.loadLibrary("altos"); - libaltos.altos_init(); - loaded_library = true; - } catch (UnsatisfiedLinkError e) { - loaded_library = false; - } - initialized = true; - } - return loaded_library; - } - - static int usb_vendor_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_VENDOR_ALTUSMETRUM; - return 0x000a; - } - - static int usb_product_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; - return 0x000a; - } - - static int usb_product_altusmetrum_min() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; - return 0x000a; - } - - static int usb_product_altusmetrum_max() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; - return 0x000d; - } - - static int usb_product_telemetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEMETRUM; - return 0x000b; - } - - static int usb_product_teledongle() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEDONGLE; - return 0x000c; - } - - static int usb_product_teleterra() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELETERRA; - return 0x000d; - } - - static int usb_product_telebt() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEBT; - return 0x000e; - } - - public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); - public final static int product_altusmetrum = usb_product_altusmetrum(); - public final static int product_telemetrum = usb_product_telemetrum(); - public final static int product_teledongle = usb_product_teledongle(); - public final static int product_teleterra = usb_product_teleterra(); - public final static int product_telebt = usb_product_telebt(); - public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); - public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - - public final static int product_any = 0x10000; - public final static int product_basestation = 0x10000 + 1; - - public String toString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%-20.20s %4d %s", - name, getSerial(), getPath()); - } - - public String toShortString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; - return String.format("%s %d %s", - name, getSerial(), getPath()); - - } - - public boolean isAltusMetrum() { - if (getVendor() != vendor_altusmetrum) - return false; - if (getProduct() < product_altusmetrum_min) - return false; - if (getProduct() > product_altusmetrum_max) - return false; - return true; - } - - public boolean matchProduct(int want_product) { - - if (!isAltusMetrum()) - return false; - - if (want_product == product_any) - return true; - - if (want_product == product_basestation) - return matchProduct(product_teledongle) || - matchProduct(product_teleterra) || - matchProduct(product_telebt); - - int have_product = getProduct(); - - if (have_product == product_altusmetrum) /* old devices match any request */ - return true; - - if (want_product == have_product) - return true; - - return false; - } - - static AltosDevice[] list(int product) { - if (!load_library()) - return null; - - SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - - ArrayList device_list = new ArrayList(); - if (list != null) { - SWIGTYPE_p_altos_file file; - - for (;;) { - AltosDevice device = new AltosDevice(); - if (libaltos.altos_list_next(list, device) == 0) - break; - if (device.matchProduct(product)) - device_list.add(device); - } - libaltos.altos_list_finish(list); - } - - AltosDevice[] devices = new AltosDevice[device_list.size()]; - for (int i = 0; i < device_list.size(); i++) - devices[i] = device_list.get(i); - return devices; - } -} \ No newline at end of file +public interface AltosDevice { + public abstract String toString(); + public abstract String toShortString(); + public abstract int getSerial(); + public abstract String getPath(); + public abstract boolean matchProduct(int product); + public SWIGTYPE_p_altos_file open(); +} diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index 2966ad1e..154bf20b 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -37,7 +37,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosDevice[] devices; - devices = AltosDevice.list(product); + devices = AltosUSBDevice.list(product); if (devices != null && devices.length > 0) { value = null; diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index b46364db..cd2b74fe 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -197,7 +197,7 @@ public class AltosEepromManage implements ActionListener { boolean running = false; frame = given_frame; - device = AltosDeviceDialog.show(frame, AltosDevice.product_any); + device = AltosDeviceDialog.show(frame, Altos.product_any); remote = false; any_download = false; @@ -206,7 +206,7 @@ public class AltosEepromManage implements ActionListener { if (device != null) { try { serial_line = new AltosSerial(device); - if (!device.matchProduct(AltosDevice.product_telemetrum)) + if (!device.matchProduct(Altos.product_telemetrum)) remote = true; serial_line.set_frame(frame); diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 0302ccd3..ad7aeac8 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -151,7 +151,7 @@ public class AltosFlashUI build_dialog(); - debug_dongle = AltosDeviceDialog.show(frame, AltosDevice.product_any); + debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any); if (debug_dongle == null) return; diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index 1171d2ed..7a06c63d 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -172,7 +172,7 @@ public class AltosIgnite { serial = new AltosSerial(device); remote = false; - if (!device.matchProduct(AltosDevice.product_telemetrum)) + if (!device.matchProduct(Altos.product_telemetrum)) remote = true; } } \ No newline at end of file diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 000adc98..ad5b7cfb 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -275,7 +275,7 @@ public class AltosIgniteUI private boolean open() { command_queue = new LinkedBlockingQueue(); - device = AltosDeviceDialog.show(owner, AltosDevice.product_any); + device = AltosDeviceDialog.show(owner, Altos.product_any); if (device != null) { try { AltosIgnite ignite = new AltosIgnite(device); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 111bd771..6c80b66f 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -304,7 +304,7 @@ public class AltosSerial implements Runnable { throw new AltosSerialInUseException(device); devices_opened.add(device.getPath()); } - altos = libaltos.altos_open(device); + altos = device.open(); if (altos == null) { close(); throw new FileNotFoundException(device.toShortString()); diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java index 4b108c7c..7380f331 100644 --- a/altosui/AltosSerialInUseException.java +++ b/altosui/AltosSerialInUseException.java @@ -17,12 +17,10 @@ package altosui; -import libaltosJNI.*; - public class AltosSerialInUseException extends Exception { - public altos_device device; + public AltosDevice device; - public AltosSerialInUseException (altos_device in_device) { + public AltosSerialInUseException (AltosDevice in_device) { device = in_device; } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 73ddf979..0fc6583c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -34,7 +34,7 @@ public class AltosUI extends JFrame { public AltosVoice voice = new AltosVoice(); public static boolean load_library(Frame frame) { - if (!AltosDevice.load_library()) { + if (!Altos.load_library()) { JOptionPane.showMessageDialog(frame, String.format("No AltOS library in \"%s\"", System.getProperty("java.library.path","")), @@ -203,7 +203,7 @@ public class AltosUI extends JFrame { bt_manage = new AltosBTManage(AltosBTDevice.bt_product_any, this); bt_manage.list(); AltosDevice device = AltosDeviceDialog.show(AltosUI.this, - AltosDevice.product_basestation); + Altos.product_basestation); if (device != null) telemetry_window(device); @@ -401,7 +401,7 @@ public class AltosUI extends JFrame { AltosUI altosui = new AltosUI(); altosui.setVisible(true); - AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation); + AltosDevice[] devices = AltosUSBDevice.list(Altos.product_basestation); for (int i = 0; i < devices.length; i++) altosui.telemetry_window(devices[i]); } diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java new file mode 100644 index 00000000..03ddf5a8 --- /dev/null +++ b/altosui/AltosUSBDevice.java @@ -0,0 +1,103 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.util.*; +import libaltosJNI.*; + +public class AltosUSBDevice extends altos_device implements AltosDevice { + + public String toString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%-20.20s %4d %s", + name, getSerial(), getPath()); + } + + public String toShortString() { + String name = getName(); + if (name == null) + name = "Altus Metrum"; + return String.format("%s %d %s", + name, getSerial(), getPath()); + + } + + public SWIGTYPE_p_altos_file open() { + return libaltos.altos_open(this); + } + + public boolean isAltusMetrum() { + if (getVendor() != Altos.vendor_altusmetrum) + return false; + if (getProduct() < Altos.product_altusmetrum_min) + return false; + if (getProduct() > Altos.product_altusmetrum_max) + return false; + return true; + } + + public boolean matchProduct(int want_product) { + + if (!isAltusMetrum()) + return false; + + if (want_product == Altos.product_any) + return true; + + if (want_product == Altos.product_basestation) + return matchProduct(Altos.product_teledongle) || + matchProduct(Altos.product_teleterra) || + matchProduct(Altos.product_telebt); + + int have_product = getProduct(); + + if (have_product == Altos.product_altusmetrum) /* old devices match any request */ + return true; + + if (want_product == have_product) + return true; + + return false; + } + + static AltosUSBDevice[] list(int product) { + if (!Altos.load_library()) + return null; + + SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); + + ArrayList device_list = new ArrayList(); + if (list != null) { + for (;;) { + AltosUSBDevice device = new AltosUSBDevice(); + if (libaltos.altos_list_next(list, device) == 0) + break; + if (device.matchProduct(product)) + device_list.add(device); + } + libaltos.altos_list_finish(list); + } + + AltosUSBDevice[] devices = new AltosUSBDevice[device_list.size()]; + for (int i = 0; i < device_list.size(); i++) + devices[i] = device_list.get(i); + return devices; + } +} \ No newline at end of file diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 37a40eaa..f2de4a3a 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -26,6 +26,7 @@ altosui_JAVA = \ AltosDescent.java \ AltosDeviceDialog.java \ AltosDevice.java \ + AltosUSBDevice.java \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ -- cgit v1.2.3 From 84163eee7847a09fe78f8762b28f857d76bf5755 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Apr 2011 10:22:30 -0700 Subject: altosui: Make AltosBTDevice implement AltosDevice interface This will allow the use of either USB or BT devices through the AltosDevice interface. Signed-off-by: Keith Packard --- altosui/Altos.java | 8 ++++++ altosui/AltosBTDevice.java | 59 ++++++++++++++++++--------------------------- altosui/AltosUSBDevice.java | 2 +- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 5df004c5..d221077e 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -301,4 +301,12 @@ public class Altos { public final static int product_any = 0x10000; public final static int product_basestation = 0x10000 + 1; + + static String bt_product_telebt() { + if (load_library()) + return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT; + return "TeleBT"; + } + + public final static String bt_product_telebt = bt_product_telebt(); } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 233037de..5e946415 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -20,36 +20,9 @@ import java.lang.*; import java.util.*; import libaltosJNI.*; -public class AltosBTDevice extends altos_bt_device { - - static public boolean initialized = false; - static public boolean loaded_library = false; - - public static boolean load_library() { - if (!initialized) { - try { - System.loadLibrary("altos"); - libaltos.altos_init(); - loaded_library = true; - } catch (UnsatisfiedLinkError e) { - loaded_library = false; - } - initialized = true; - } - return loaded_library; - } - - static String bt_product_telebt() { - if (load_library()) - return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT; - return "TeleBT"; - } - - public final static String bt_product_telebt = bt_product_telebt(); - public final static String bt_product_any = "Any"; - public final static String bt_product_basestation = "Basestation"; +public class AltosBTDevice extends altos_bt_device implements AltosDevice { - public String getProduct() { + public String getProductName() { String name = getName(); if (name == null) return "Altus Metrum"; @@ -59,6 +32,16 @@ public class AltosBTDevice extends altos_bt_device { return name.substring(0,dash); } + public int getProduct() { + if (Altos.bt_product_telebt.equals(getProductName())) + return Altos.product_telebt; + return 0; + } + + public String getPath() { + return getAddr(); + } + public int getSerial() { String name = getName(); if (name == null) @@ -91,24 +74,28 @@ public class AltosBTDevice extends altos_bt_device { } - public boolean isAltusMetrum() { - if (getName().startsWith(bt_product_telebt)) + public SWIGTYPE_p_altos_file open() { + return libaltos.altos_bt_open(this); + } + + private boolean isAltusMetrum() { + if (getName().startsWith(Altos.bt_product_telebt)) return true; return false; } - public boolean matchProduct(String want_product) { + public boolean matchProduct(int want_product) { if (!isAltusMetrum()) return false; - if (want_product.equals(bt_product_any)) + if (want_product == Altos.product_any) return true; - if (want_product.equals(bt_product_basestation)) - return matchProduct(bt_product_telebt); + if (want_product == Altos.product_basestation) + return matchProduct(Altos.product_telebt); - if (want_product.equals(getProduct())) + if (want_product == getProduct()) return true; return false; diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index 03ddf5a8..deed0056 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -43,7 +43,7 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return libaltos.altos_open(this); } - public boolean isAltusMetrum() { + private boolean isAltusMetrum() { if (getVendor() != Altos.vendor_altusmetrum) return false; if (getProduct() < Altos.product_altusmetrum_min) -- cgit v1.2.3 From f249e5926f5fd9f86c41e7f0a414193533d4d8b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 18 Apr 2011 18:16:38 -0500 Subject: altosui: Make bluetooth dialog modal This allows it to be displayed correctly while the device dialog box (also modal) is up. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 2 +- altosui/AltosBTDeviceIterator.java | 4 +- altosui/AltosBTManage.java | 21 ++++++--- altosui/AltosDeviceDialog.java | 91 ++++++++++++++++++++------------------ altosui/AltosUI.java | 4 -- 5 files changed, 65 insertions(+), 57 deletions(-) diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 5e946415..ff2be49a 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -62,7 +62,7 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { if (name == null) name = "Altus Metrum"; return String.format("%-20.20s %4d %s", - getProduct(), getSerial(), getAddr()); + getProductName(), getSerial(), getAddr()); } public String toShortString() { diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java index 935bf822..63ce3674 100644 --- a/altosui/AltosBTDeviceIterator.java +++ b/altosui/AltosBTDeviceIterator.java @@ -21,7 +21,7 @@ import java.util.*; import libaltosJNI.*; public class AltosBTDeviceIterator implements Iterator { - String product; + int product; AltosBTDevice current; boolean done; SWIGTYPE_p_altos_bt_list list; @@ -58,7 +58,7 @@ public class AltosBTDeviceIterator implements Iterator { throw new UnsupportedOperationException(); } - public AltosBTDeviceIterator(String in_product) { + public AltosBTDeviceIterator(int in_product) { product = in_product; done = false; current = null; diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 8e9e0f73..66e1210e 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -31,9 +31,8 @@ import java.util.concurrent.*; import libaltosJNI.*; public class AltosBTManage extends JDialog implements ActionListener { - String product; LinkedBlockingQueue found_devices; - JFrame frame; + Frame frame; class DeviceList extends JList implements Iterable { LinkedList devices; @@ -104,7 +103,7 @@ public class AltosBTManage extends JDialog implements ActionListener { public void run () { try { - AltosBTDeviceIterator i = new AltosBTDeviceIterator(product); + AltosBTDeviceIterator i = new AltosBTDeviceIterator(Altos.product_any); AltosBTDevice device; while ((device = i.next()) != null) { @@ -124,9 +123,21 @@ public class AltosBTManage extends JDialog implements ActionListener { } } - public AltosBTManage(String product, JFrame in_frame) { + public static void show(Component frameComp) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosBTManage dialog; + + dialog = new AltosBTManage(frame); + dialog.setVisible(true); + } + + public AltosBTManage(Frame in_frame) { + super(in_frame, "Manage Bluetooth Devices", true); + frame = in_frame; + BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); + Thread t = new Thread(get_visible_devices); t.start(); @@ -182,7 +193,5 @@ public class AltosBTManage extends JDialog implements ActionListener { //Initialize values. // list.setSelectedValue(initial, true); pack(); - setLocationRelativeTo(frame); - setVisible(true); } } diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index 154bf20b..fa20f867 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -22,59 +22,55 @@ import java.util.*; import javax.swing.*; import java.awt.*; import java.awt.event.*; -import libaltosJNI.libaltos; -import libaltosJNI.altos_device; -import libaltosJNI.SWIGTYPE_p_altos_file; -import libaltosJNI.SWIGTYPE_p_altos_list; +import libaltosJNI.*; public class AltosDeviceDialog extends JDialog implements ActionListener { - private static AltosDeviceDialog dialog; - private static AltosDevice value = null; - private JList list; - public static AltosDevice show (Component frameComp, int product) { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosDevice[] devices; devices = AltosUSBDevice.list(product); + AltosDeviceDialog dialog; - if (devices != null && devices.length > 0) { - value = null; - dialog = new AltosDeviceDialog(frame, frameComp, - devices, - devices[0]); - - dialog.setVisible(true); - return value; - } else { - /* check for missing altos JNI library, which - * will put up its own error dialog - */ - if (AltosUI.load_library(frame)) { - JOptionPane.showMessageDialog(frame, - "No AltOS devices available", - "No AltOS devices", - JOptionPane.ERROR_MESSAGE); - } - return null; - } + dialog = new AltosDeviceDialog(frame, frameComp, + devices); + dialog.setVisible(true); + return dialog.getValue(); + } + + private AltosDevice value; + private JList list; + private JButton cancel_button; + private JButton select_button; + private JButton manage_bluetooth_button; + private Frame frame; + + private AltosDevice getValue() { + return value; } - private AltosDeviceDialog (Frame frame, Component location, - AltosDevice[] devices, - AltosDevice initial) { - super(frame, "Device Selection", true); + private AltosDeviceDialog (Frame in_frame, Component location, + AltosDevice[] devices) { + super(in_frame, "Device Selection", true); + frame = in_frame; value = null; - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(this); + cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + + manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); - final JButton selectButton = new JButton("Select"); - selectButton.setActionCommand("select"); - selectButton.addActionListener(this); - getRootPane().setDefaultButton(selectButton); + select_button = new JButton("Select"); + select_button.setActionCommand("select"); + select_button.addActionListener(this); + if (devices.length == 0) + select_button.setEnabled(false); + getRootPane().setDefaultButton(select_button); list = new JList(devices) { //Subclass JList to workaround bug 4832765, which can cause the @@ -112,7 +108,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { - selectButton.doClick(); //emulate button click + select_button.doClick(); //emulate button click } } }); @@ -139,9 +135,11 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancelButton); + buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(selectButton); + buttonPane.add(manage_bluetooth_button); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + buttonPane.add(select_button); //Put everything together, using the content pane's BorderLayout. Container contentPane = getContentPane(); @@ -149,7 +147,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { contentPane.add(buttonPane, BorderLayout.PAGE_END); //Initialize values. - list.setSelectedValue(initial, true); + if (devices != null && devices.length > 0) + list.setSelectedValue(devices[0], true); pack(); setLocationRelativeTo(location); } @@ -157,8 +156,12 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { //Handle clicks on the Set and Cancel buttons. public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) - AltosDeviceDialog.value = (AltosDevice)(list.getSelectedValue()); - AltosDeviceDialog.dialog.setVisible(false); + value = (AltosDevice)(list.getSelectedValue()); + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame); + return; + } + setVisible(false); } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 0fc6583c..4b808c41 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -198,10 +198,6 @@ public class AltosUI extends JFrame { } private void ConnectToDevice() { - AltosBTManage bt_manage; - - bt_manage = new AltosBTManage(AltosBTDevice.bt_product_any, this); - bt_manage.list(); AltosDevice device = AltosDeviceDialog.show(AltosUI.this, Altos.product_basestation); -- cgit v1.2.3 From 17f38e045fcd8ca0224095c0b2b7b098df77a8d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 08:43:40 -0700 Subject: altosui: Use persistent list of bluetooth devices for device dialogs Store a list of known bluetooth devices as preferences. Always include those in device dialogs with an option to go browse for more devices in both the device dialog and the Configure AltosUI dialog. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 + altosui/AltosBTDevice.java | 24 ++- altosui/AltosBTDeviceIterator.java | 7 +- altosui/AltosBTKnown.java | 97 +++++++++++++ altosui/AltosBTManage.java | 291 ++++++++++++++++++++++++++++--------- altosui/AltosConfigureUI.java | 2 +- altosui/AltosDeviceDialog.java | 53 ++++--- altosui/AltosFlightUI.java | 2 +- altosui/AltosPreferences.java | 25 +++- altosui/AltosSiteMap.java | 2 - altosui/AltosUI.java | 8 +- altosui/AltosUSBDevice.java | 9 +- altosui/Makefile.am | 1 + altosui/libaltos/cjnitest.c | 2 +- altosui/libaltos/libaltos.c | 16 +- altosui/libaltos/libaltos.h | 5 +- 16 files changed, 423 insertions(+), 123 deletions(-) create mode 100644 altosui/AltosBTKnown.java diff --git a/altosui/Altos.java b/altosui/Altos.java index d221077e..a087f73a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -309,4 +309,6 @@ public class Altos { } public final static String bt_product_telebt = bt_product_telebt(); + + public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index ff2be49a..c2721b26 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -86,8 +86,9 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { public boolean matchProduct(int want_product) { - if (!isAltusMetrum()) - return false; + System.out.printf("matchProduct %s %d\n", toString(), want_product); +// if (!isAltusMetrum()) +// return false; if (want_product == Altos.product_any) return true; @@ -100,4 +101,23 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { return false; } + + public boolean equals(Object o) { + if (!(o instanceof AltosBTDevice)) + return false; + AltosBTDevice other = (AltosBTDevice) o; + System.out.printf("AltosBTDevice equals %s == %s\n", toString(), other.toString()); + return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); + } + + public int hashCode() { + return getName().hashCode() ^ getAddr().hashCode(); + } + + public AltosBTDevice(String name, String addr) { + libaltos.altos_bt_fill_in(name, addr,this); + } + + public AltosBTDevice() { + } } \ No newline at end of file diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java index 63ce3674..7c360705 100644 --- a/altosui/AltosBTDeviceIterator.java +++ b/altosui/AltosBTDeviceIterator.java @@ -21,7 +21,6 @@ import java.util.*; import libaltosJNI.*; public class AltosBTDeviceIterator implements Iterator { - int product; AltosBTDevice current; boolean done; SWIGTYPE_p_altos_bt_list list; @@ -58,11 +57,9 @@ public class AltosBTDeviceIterator implements Iterator { throw new UnsupportedOperationException(); } - public AltosBTDeviceIterator(int in_product) { - product = in_product; + public AltosBTDeviceIterator(int inquiry_time) { done = false; current = null; - list = libaltos.altos_bt_list_start(); - System.out.printf("Iteration of BT list started\n"); + list = libaltos.altos_bt_list_start(inquiry_time); } } diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java new file mode 100644 index 00000000..95830637 --- /dev/null +++ b/altosui/AltosBTKnown.java @@ -0,0 +1,97 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.util.*; +import libaltosJNI.*; +import java.util.prefs.*; + +public class AltosBTKnown implements Iterable { + LinkedList devices = new LinkedList(); + Preferences bt_pref = AltosPreferences.bt_devices(); + + private String get_address(String name) { + return bt_pref.get(name, ""); + } + + private void set_address(String name, String addr) { + bt_pref.put(name, addr); + System.out.printf("saving known %s %s\n", name, addr); + } + + private void remove(String name) { + bt_pref.remove(name); + } + + private void load() { + try { + String[] names = bt_pref.keys(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + String addr = get_address(name); + System.out.printf("Known device %s %s\n", name, addr); + devices.add(new AltosBTDevice(name, addr)); + } + } catch (BackingStoreException be) { + } catch (IllegalStateException ie) { + } + } + + public Iterator iterator() { + return devices.iterator(); + } + + private void flush() { + AltosPreferences.flush_preferences(); + } + + public void set(Iterable new_devices) { + for (AltosBTDevice old : devices) { + boolean found = false; + for (AltosBTDevice new_device : new_devices) { + if (new_device.equals(old)) { + found = true; + break; + } + } + if (!found) + remove(old.getName()); + } + devices = new LinkedList(); + for (AltosBTDevice new_device : new_devices) { + devices.add(new_device); + set_address(new_device.getName(), new_device.getAddr()); + } + flush(); + } + + public List list(int product) { + LinkedList list = new LinkedList(); + for (AltosBTDevice device : devices) { + if (device.matchProduct(product)) + list.add(device); + } + return list; + } + + public AltosBTKnown() { + devices = new LinkedList(); + bt_pref = AltosPreferences.bt_devices(); + load(); + } +} \ No newline at end of file diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 66e1210e..98a8b757 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -22,6 +22,8 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; +import javax.swing.event.*; +import javax.swing.plaf.basic.*; import java.io.*; import java.util.*; import java.text.*; @@ -30,17 +32,32 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosBTManage extends JDialog implements ActionListener { +public class AltosBTManage extends JDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; Frame frame; + LinkedList listeners; + AltosBTKnown bt_known; class DeviceList extends JList implements Iterable { LinkedList devices; DefaultListModel list_model; public void add (AltosBTDevice device) { - devices.add(device); - list_model.addElement(device); + if (!devices.contains(device)) { + devices.add(device); + list_model.addElement(device); + } + } + + public void remove (AltosBTDevice device) { + if (devices.contains(device)) { + devices.remove(device); + list_model.removeElement(device); + } + } + + public boolean contains(AltosBTDevice device) { + return devices.contains(device); } //Subclass JList to workaround bug 4832765, which can cause the @@ -75,6 +92,14 @@ public class AltosBTManage extends JDialog implements ActionListener { return devices.iterator(); } + public java.util.List selected_list() { + java.util.LinkedList l = new java.util.LinkedList(); + Object[] a = getSelectedValues(); + for (int i = 0; i < a.length; i++) + l.add((AltosBTDevice)a[i]); + return l; + } + public DeviceList() { devices = new LinkedList(); list_model = new DefaultListModel(); @@ -87,111 +112,233 @@ public class AltosBTManage extends JDialog implements ActionListener { DeviceList visible_devices; - DeviceList selected_devices; + DeviceList known_devices; + Thread bt_thread; + + public Iterator iterator() { + return known_devices.iterator(); + } + + public void commit() { + bt_known.set(this); + } + + public void add_known() { + for (AltosBTDevice device : visible_devices.selected_list()) { + System.out.printf("Add known %s\n", device.toString()); + known_devices.add(device); + visible_devices.remove(device); + } + } + + public void remove_known() { + for (AltosBTDevice device : known_devices.selected_list()) { + System.out.printf("Remove known %s\n", device.toString()); + known_devices.remove(device); + visible_devices.add(device); + } + } + + public void addActionListener(ActionListener l) { + listeners.add(l); + } + + private void forwardAction(ActionEvent e) { + for (ActionListener l : listeners) + l.actionPerformed(e); + } public void actionPerformed(ActionEvent e) { + String command = e.getActionCommand(); + System.out.printf("manage command %s\n", command); + if ("ok".equals(command)) { + bt_thread.interrupt(); + commit(); + setVisible(false); + forwardAction(e); + } else if ("cancel".equals(command)) { + bt_thread.interrupt(); + setVisible(false); + forwardAction(e); + } else if ("select".equals(command)) { + add_known(); + } else if ("deselect".equals(command)) { + remove_known(); + } } public void got_visible_device() { while (!found_devices.isEmpty()) { AltosBTDevice device = found_devices.remove(); - visible_devices.add(device); + if (!known_devices.contains(device)) + visible_devices.add(device); } } class BTGetVisibleDevices implements Runnable { public void run () { - - try { - AltosBTDeviceIterator i = new AltosBTDeviceIterator(Altos.product_any); - AltosBTDevice device; - - while ((device = i.next()) != null) { - Runnable r; - - found_devices.add(device); - r = new Runnable() { - public void run() { - got_visible_device(); - } - }; - SwingUtilities.invokeLater(r); + for (;;) + for (int time = 1; time <= 8; time <<= 1) { + AltosBTDeviceIterator i = new AltosBTDeviceIterator(time); + AltosBTDevice device; + + if (Thread.interrupted()) + return; + try { + while ((device = i.next()) != null) { + Runnable r; + + if (Thread.interrupted()) + return; + found_devices.add(device); + r = new Runnable() { + public void run() { + got_visible_device(); + } + }; + SwingUtilities.invokeLater(r); + } + } catch (Exception e) { + System.out.printf("uh-oh, exception %s\n", e.toString()); + } } - } catch (Exception e) { - System.out.printf("uh-oh, exception %s\n", e.toString()); - } } } - public static void show(Component frameComp) { + public static void show(Component frameComp, AltosBTKnown known) { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosBTManage dialog; - dialog = new AltosBTManage(frame); + dialog = new AltosBTManage(frame, known); dialog.setVisible(true); } - public AltosBTManage(Frame in_frame) { + public AltosBTManage(Frame in_frame, AltosBTKnown in_known) { super(in_frame, "Manage Bluetooth Devices", true); frame = in_frame; - + bt_known = in_known; BTGetVisibleDevices get_visible_devices = new BTGetVisibleDevices(); + bt_thread = new Thread(get_visible_devices); + bt_thread.start(); - Thread t = new Thread(get_visible_devices); - t.start(); + listeners = new LinkedList(); found_devices = new LinkedBlockingQueue(); - JButton cancelButton = new JButton("Cancel"); - cancelButton.addActionListener(this); - - final JButton selectButton = new JButton("Select"); - selectButton.setActionCommand("select"); - selectButton.addActionListener(this); - getRootPane().setDefaultButton(selectButton); - - selected_devices = new DeviceList(); - JScrollPane selected_list_scroller = new JScrollPane(selected_devices); - selected_list_scroller.setPreferredSize(new Dimension(400, 80)); - selected_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(4,4,4,4); + + /* + * Known devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + pane.add(new JLabel("Known Devices"), c); + + known_devices = new DeviceList(); + for (AltosBTDevice device : bt_known) + known_devices.add(device); + + JScrollPane known_list_scroller = new JScrollPane(known_devices); + known_list_scroller.setPreferredSize(new Dimension(400, 80)); + known_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 2; + pane.add(known_list_scroller, c); + + /* + * Visible devices label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + pane.add(new JLabel("Visible Devices"), c); visible_devices = new DeviceList(); JScrollPane visible_list_scroller = new JScrollPane(visible_devices); visible_list_scroller.setPreferredSize(new Dimension(400, 80)); visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 2; + c.gridy = 1; + c.gridheight = 2; + c.gridwidth = 1; + pane.add(visible_list_scroller, c); + + /* + * Arrows between the two lists + */ + BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST); + select_arrow.setActionCommand("select"); + select_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.SOUTH; + c.gridx = 1; + c.gridy = 1; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(select_arrow, c); + + BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST); + deselect_arrow.setActionCommand("deselect"); + deselect_arrow.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.NORTH; + c.gridx = 1; + c.gridy = 2; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(deselect_arrow, c); + + JButton cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(cancel_button, c); + + JButton ok_button = new JButton("OK"); + ok_button.setActionCommand("ok"); + ok_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 2; + c.gridy = 3; + c.gridheight = 1; + c.gridwidth = 1; + pane.add(ok_button, c); + + getRootPane().setDefaultButton(ok_button); - //Create a container so that we can add a title around - //the scroll pane. Can't add a title directly to the - //scroll pane because its background would be white. - //Lay out the label and scroll pane from top to bottom. - JPanel listPane = new JPanel(); - listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); - - JLabel label = new JLabel("Select Device"); - label.setLabelFor(selected_devices); - listPane.add(label); - listPane.add(Box.createRigidArea(new Dimension(0,5))); - listPane.add(selected_list_scroller); - listPane.add(visible_list_scroller); - listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - - //Lay out the buttons from left to right. - JPanel buttonPane = new JPanel(); - buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); - buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); - buttonPane.add(Box.createHorizontalGlue()); - buttonPane.add(cancelButton); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(selectButton); - - //Put everything together, using the content pane's BorderLayout. - Container contentPane = getContentPane(); - contentPane.add(listPane, BorderLayout.CENTER); - contentPane.add(buttonPane, BorderLayout.PAGE_END); - - //Initialize values. -// list.setSelectedValue(initial, true); pack(); + setLocationRelativeTo(frame); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + bt_thread.interrupt(); + setVisible(false); + } + }); } } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index a2755a06..0f5e4a3b 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -204,7 +204,7 @@ public class AltosConfigureUI manage_bluetooth = new JButton("Manage Bluetooth"); manage_bluetooth.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - new AltosBTManage(AltosBTDevice.bt_product_any, owner); + AltosBTManage.show(owner, Altos.bt_known); } }); c.gridx = 1; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index fa20f867..e17504e2 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -26,37 +26,46 @@ import libaltosJNI.*; public class AltosDeviceDialog extends JDialog implements ActionListener { - public static AltosDevice show (Component frameComp, int product) { - - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDevice[] devices; - devices = AltosUSBDevice.list(product); - AltosDeviceDialog dialog; - - dialog = new AltosDeviceDialog(frame, frameComp, - devices); - dialog.setVisible(true); - return dialog.getValue(); - } - private AltosDevice value; private JList list; private JButton cancel_button; private JButton select_button; private JButton manage_bluetooth_button; private Frame frame; + private int product; private AltosDevice getValue() { return value; } - private AltosDeviceDialog (Frame in_frame, Component location, - AltosDevice[] devices) { + private AltosDevice[] devices() { + java.util.List usb_devices = AltosUSBDevice.list(product); + java.util.List bt_devices = Altos.bt_known.list(product); + AltosDevice[] devices = new AltosDevice[usb_devices.size() + bt_devices.size()]; + + for (int i = 0; i < usb_devices.size(); i++) + devices[i] = usb_devices.get(i); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); + return devices; + } + + private void update_devices() { + AltosDevice[] devices = devices(); + list.setListData(devices); + select_button.setEnabled(devices.length > 0); + } + + private AltosDeviceDialog (Frame in_frame, Component location, int in_product) { super(in_frame, "Device Selection", true); + product = in_product; frame = in_frame; value = null; + AltosDevice[] devices = devices(); + cancel_button = new JButton("Cancel"); cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); @@ -147,7 +156,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { contentPane.add(buttonPane, BorderLayout.PAGE_END); //Initialize values. - if (devices != null && devices.length > 0) + if (devices != null && devices.length != 0) list.setSelectedValue(devices[0], true); pack(); setLocationRelativeTo(location); @@ -158,10 +167,20 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame); + AltosBTManage.show(frame, Altos.bt_known); + update_devices(); return; } setVisible(false); } + public static AltosDevice show (Component frameComp, int product) { + + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDeviceDialog dialog; + + dialog = new AltosDeviceDialog(frame, frameComp, product); + dialog.setVisible(true); + return dialog.getValue(); + } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 66dcdad5..eb6c6d9d 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -122,7 +122,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { JComboBox telemetries; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { - AltosPreferences.init(this); + AltosPreferences.set_component(this); voice = in_voice; reader = in_reader; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 5f827655..b1192be1 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -79,11 +79,9 @@ class AltosPreferences { /* Serial debug */ static boolean serial_debug; - public static void init(Component ui) { + public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - component = ui; - /* Initialize logdir from preferences */ String logdir_string = preferences.get(logdirPreference, null); if (logdir_string != null) @@ -116,14 +114,23 @@ class AltosPreferences { AltosSerial.set_debug(serial_debug); } + static { init(); } + + static void set_component(Component in_component) { + component = in_component; + } + static void flush_preferences() { try { preferences.flush(); } catch (BackingStoreException ee) { - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); + if (component != null) + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + else + System.err.printf("Cannot save preferences\n"); } } @@ -262,4 +269,8 @@ class AltosPreferences { public static boolean serial_debug() { return serial_debug; } + + public static Preferences bt_devices() { + return preferences.node("bt_devices"); + } } diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index f4b6b7e0..7575c10e 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -164,8 +164,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } public static void prefetchMaps(double lat, double lng, int w, int h) { - AltosPreferences.init(null); - AltosSiteMap asm = new AltosSiteMap(true); asm.centre = asm.getBaseLocation(lat, lng); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 4b808c41..7955c1c2 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -99,7 +99,7 @@ public class AltosUI extends JFrame { if (imgURL != null) setIconImage(new ImageIcon(imgURL).getImage()); - AltosPreferences.init(this); + AltosPreferences.set_component(this); pane = getContentPane(); gridbag = new GridBagLayout(); @@ -397,9 +397,9 @@ public class AltosUI extends JFrame { AltosUI altosui = new AltosUI(); altosui.setVisible(true); - AltosDevice[] devices = AltosUSBDevice.list(Altos.product_basestation); - for (int i = 0; i < devices.length; i++) - altosui.telemetry_window(devices[i]); + java.util.List devices = AltosUSBDevice.list(Altos.product_basestation); + for (AltosDevice device : devices) + altosui.telemetry_window(device); } } } diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index deed0056..dc746a64 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -77,13 +77,13 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { return false; } - static AltosUSBDevice[] list(int product) { + static java.util.List list(int product) { if (!Altos.load_library()) return null; SWIGTYPE_p_altos_list list = libaltos.altos_list_start(); - ArrayList device_list = new ArrayList(); + ArrayList device_list = new ArrayList(); if (list != null) { for (;;) { AltosUSBDevice device = new AltosUSBDevice(); @@ -95,9 +95,6 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { libaltos.altos_list_finish(list); } - AltosUSBDevice[] devices = new AltosUSBDevice[device_list.size()]; - for (int i = 0; i < device_list.size(); i++) - devices[i] = device_list.get(i); - return devices; + return device_list; } } \ No newline at end of file diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f2de4a3a..f4d84ad2 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -30,6 +30,7 @@ altosui_JAVA = \ AltosBTDevice.java \ AltosBTDeviceIterator.java \ AltosBTManage.java \ + AltosBTKnown.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index 79561643..88e40d73 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -41,7 +41,7 @@ main () altos_close(file); } altos_list_finish(list); - bt_list = altos_bt_list_start(); + bt_list = altos_bt_list_start(8); while (altos_bt_list_next(bt_list, &bt_device)) { printf ("%s %s\n", bt_device.name, bt_device.addr); if (strncmp(bt_device.name, "TeleBT", 6) == 0) { diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 13635a0d..2c47f3e5 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -591,10 +591,9 @@ struct altos_bt_list { }; #define INQUIRY_MAX_RSP 255 -#define INQUIRY_LEN 8 struct altos_bt_list * -altos_bt_list_start(void) +altos_bt_list_start(int inquiry_time) { struct altos_bt_list *bt_list; @@ -614,7 +613,7 @@ altos_bt_list_start(void) goto no_sock; bt_list->num_rsp = hci_inquiry(bt_list->dev_id, - INQUIRY_LEN, + inquiry_time, INQUIRY_MAX_RSP, NULL, &bt_list->ii, @@ -665,6 +664,15 @@ altos_bt_list_finish(struct altos_bt_list *bt_list) free(bt_list); } +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ + strncpy(device->name, name, sizeof (device->name)); + device->name[sizeof(device->name)-1] = '\0'; + strncpy(device->addr, addr, sizeof (device->addr)); + device->addr[sizeof(device->addr)-1] = '\0'; +} + struct altos_file * altos_bt_open(struct altos_bt_device *device) { @@ -768,7 +776,7 @@ get_number(io_object_t object, CFStringRef entry, int *result) } struct altos_list * -altos_list_start(void) +altos_list_start(int time) { struct altos_list *list = calloc (sizeof (struct altos_list), 1); CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 9c3f9655..f710919c 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -110,7 +110,7 @@ PUBLIC int altos_getchar(struct altos_file *file, int timeout); PUBLIC struct altos_bt_list * -altos_bt_list_start(void); +altos_bt_list_start(int inquiry_time); PUBLIC int altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); @@ -118,6 +118,9 @@ altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device); PUBLIC void altos_bt_list_finish(struct altos_bt_list *list); +PUBLIC void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device); + PUBLIC struct altos_file * altos_bt_open(struct altos_bt_device *device); -- cgit v1.2.3 From 8de9d3cbfcd1db7b554fb761296a8de09aafc8c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 10:25:47 -0700 Subject: altos: Add delays to bt startup sequence The BT device takes a few seconds after power-up before it is ready to receive commands. Signed-off-by: Keith Packard --- src/ao_btm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ao_btm.c b/src/ao_btm.c index 71907f86..4f56c382 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -249,6 +249,8 @@ ao_btm(void) ao_btm_stdio = ao_num_stdios - 1; ao_btm_echo(0); + ao_delay(AO_SEC_TO_TICKS(3)); + /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see @@ -256,6 +258,7 @@ ao_btm(void) * then tell it to switch to 57600 from 19200 baud. */ while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + ao_delay(AO_SEC_TO_TICKS(1)); if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) ao_btm_cmd("ATL4\r"); ao_delay(AO_SEC_TO_TICKS(1)); -- cgit v1.2.3 From 6b5957d5f6f8181da7be98c9bce49a0ec0b4a713 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 10:41:28 -0700 Subject: altosui: Wait two seconds after bluetooth connect XXX "something" isn't quite ready to communicate right after the device is connected, so we stick a delay in. There should be a better fix. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 2c47f3e5..c5bcf900 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -698,6 +698,7 @@ altos_bt_open(struct altos_bt_device *device) perror("connect"); goto no_link; } + sleep(2); #ifdef USE_POLL pipe(file->pipe); -- cgit v1.2.3 From e3d501940718428135e04995dff7fef691c08a20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:20:19 -0700 Subject: altos: Solidify BT connections Use delays while sending commands to BT module. Don't use BT for stdio until the module is initialized. Add \r to name setting command Don't require 'connected' signal for command input. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_btm.c | 41 ++++++++++++++++++++--------------------- src/ao_stdio.c | 4 ++-- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/ao.h b/src/ao.h index dad1f3df..226f9a22 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1194,7 +1194,7 @@ extern __xdata uint8_t ao_stdin_ready; uint8_t ao_echo(void); -void +int8_t ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, void (*flush)(void)) __reentrant; diff --git a/src/ao_btm.c b/src/ao_btm.c index 4f56c382..784a566f 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -26,8 +26,6 @@ __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; char ao_btm_dir; -uint8_t ao_btm_send_chars = 0; - void ao_btm_putchar(char c); @@ -109,6 +107,9 @@ ao_btm_drain() ; } +/* + * Set the stdio echo for the bluetooth link + */ void ao_btm_echo(uint8_t echo) { @@ -138,7 +139,7 @@ ao_cmd_filter(void) ao_cmd_lex(); } ao_cmd_status = 0; - return !ao_btm_connected; + return 0; } /* @@ -161,16 +162,10 @@ ao_btm_pollchar(void) void ao_btm_putchar(char c) { - if (!ao_btm_send_chars) { - ao_btm_log_out_char(c); - ao_serial_putchar(c); - } -} - -void -ao_btm_stdio_putchar(char c) { - if (ao_btm_connected) - ao_btm_putchar(c); + ao_btm_log_out_char(c); + ao_serial_putchar(c); + if (!ao_btm_running) + ao_delay(1); } /* @@ -211,12 +206,13 @@ ao_btm_cmd(__code char *cmd) uint8_t ao_btm_set_name(void) { - char sn[7]; - char *s = sn + 7; + char sn[8]; + char *s = sn + 8; char c; int n; ao_btm_string("ATN=TeleBT-"); *--s = '\0'; + *--s = '\r'; n = ao_serial_number; do { *--s = '0' + n % 10; @@ -236,6 +232,7 @@ ao_btm_try_speed(uint8_t speed) return 1; return 0; } + /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -243,12 +240,9 @@ ao_btm_try_speed(uint8_t speed) void ao_btm(void) { - ao_add_stdio(ao_btm_pollchar, - ao_btm_stdio_putchar, - NULL); - ao_btm_stdio = ao_num_stdios - 1; - ao_btm_echo(0); - + /* + * Wait for the bluetooth device to boot + */ ao_delay(AO_SEC_TO_TICKS(3)); /* @@ -276,6 +270,11 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); + ao_btm_stdio = ao_add_stdio(ao_btm_pollchar, + ao_btm_putchar, + NULL); + ao_btm_echo(0); + ao_btm_running = 1; for (;;) { while (!ao_btm_connected && !ao_btm_chat) diff --git a/src/ao_stdio.c b/src/ao_stdio.c index ec3b6607..6b890832 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -69,7 +69,7 @@ ao_echo(void) return ao_stdios[ao_cur_stdio].echo; } -void +int8_t ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant @@ -80,5 +80,5 @@ ao_add_stdio(char (*pollchar)(void), ao_stdios[ao_num_stdios].putchar = putchar; ao_stdios[ao_num_stdios].flush = flush; ao_stdios[ao_num_stdios].echo = 1; - ao_num_stdios++; + return ao_num_stdios++; } -- cgit v1.2.3 From ce7cf0c5ddc5405f6f474f4e20752fc0b02f3ecb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:27:40 -0700 Subject: altos: Simplify BT communications Eliminate stdio I/O wrappers Signed-off-by: Keith Packard --- src/ao_btm.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 784a566f..6ba5eb1a 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -143,29 +143,16 @@ ao_cmd_filter(void) } /* - * A wrapper for ao_serial_pollchar that - * doesn't return any characters while we're - * initializing the bluetooth device + * Delay between command charaters; the BT module + * can't keep up with 57600 baud */ -char -ao_btm_pollchar(void) -{ - char c; - if (!ao_btm_running) - return AO_READ_AGAIN; - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) - ao_btm_log_in_char(c); - return c; -} void ao_btm_putchar(char c) { ao_btm_log_out_char(c); ao_serial_putchar(c); - if (!ao_btm_running) - ao_delay(1); + ao_delay(1); } /* @@ -270,8 +257,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_btm_pollchar, - ao_btm_putchar, + ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, NULL); ao_btm_echo(0); -- cgit v1.2.3 From 0195ff442c1da5d363dfda3f88f41865d0c6b469 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:31:10 -0700 Subject: altos: Remove bt debug command This will permit some additional cleanups. Signed-off-by: Keith Packard --- src/ao_btm.c | 42 +----------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 6ba5eb1a..aa7a7101 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -20,7 +20,6 @@ uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -uint8_t ao_btm_chat; __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; @@ -264,23 +263,8 @@ ao_btm(void) ao_btm_running = 1; for (;;) { - while (!ao_btm_connected && !ao_btm_chat) + while (!ao_btm_connected) ao_sleep(&ao_btm_connected); - if (ao_btm_chat) { - ao_btm_running = 0; - while (ao_btm_chat) { - char c; - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) { - ao_btm_log_in_char(c); - ao_usb_putchar(c); - } else { - ao_usb_flush(); - ao_sleep(&ao_usart1_rx_fifo); - } - } - ao_btm_running = 1; - } while (ao_btm_connected) { ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); ao_delay(AO_SEC_TO_TICKS(3)); @@ -290,29 +274,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -/* - * Connect directly to the bluetooth device, mostly - * useful for testing - */ -static void -ao_btm_forward(void) -{ - char c; - - ao_btm_chat = 1; - ao_wakeup(&ao_btm_connected); - ao_usb_flush(); - while ((c = ao_usb_getchar()) != '~') { - if (c == '\n') c = '\r'; - ao_btm_putchar(c); - } - ao_btm_chat = 0; - while (!ao_btm_running) { - ao_wakeup(&ao_usart1_rx_fifo); - ao_delay(AO_MS_TO_TICKS(10)); - } -} - /* * Dump everything received from the bluetooth device during startup */ @@ -367,7 +328,6 @@ ao_btm_isr(void) } __code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_forward, "B\0BTM serial link." }, { ao_btm_dump, "d\0Dump btm buffer." }, { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, { 0, NULL }, -- cgit v1.2.3 From 7f5c9986dfa2d130b6c8c14308638cce49391a6e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:42:30 -0700 Subject: altos: remove BT logging code This was used to debug the serial line startup. Signed-off-by: Keith Packard --- src/ao_btm.c | 73 ------------------------------------------------------------ 1 file changed, 73 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index aa7a7101..491e4be3 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -21,42 +21,9 @@ uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -__xdata char ao_btm_buffer[1024]; -int ao_btm_ptr; -char ao_btm_dir; - void ao_btm_putchar(char c); -static void -ao_btm_add_char(char c) -{ - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; -} - -static void -ao_btm_log_char(char c, char dir) -{ - if (dir != ao_btm_dir) { - ao_btm_add_char(dir); - ao_btm_dir = dir; - } - ao_btm_add_char(c); -} - -static void -ao_btm_log_out_char(char c) -{ - ao_btm_log_char(c, '>'); -} - -static void -ao_btm_log_in_char(char c) -{ - ao_btm_log_char(c, '<'); -} - #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -76,7 +43,6 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { - ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; if (c == '\r' || c == '\n') @@ -149,7 +115,6 @@ ao_cmd_filter(void) void ao_btm_putchar(char c) { - ao_btm_log_out_char(c); ao_serial_putchar(c); ao_delay(1); } @@ -274,37 +239,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -/* - * Dump everything received from the bluetooth device during startup - */ -static void -ao_btm_dump(void) -{ - int i; - char c; - - for (i = 0; i < ao_btm_ptr; i++) { - c = ao_btm_buffer[i]; - if (c < ' ' && c != '\n') - printf("\\%03o", ((int) c) & 0xff); - else - putchar(ao_btm_buffer[i]); - } - putchar('\n'); -} - -static void -ao_btm_speed(void) -{ - ao_cmd_decimal(); - if (ao_cmd_lex_u32 == 57600) - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - else if (ao_cmd_lex_u32 == 19200) - ao_serial_set_speed(AO_SERIAL_SPEED_19200); - else - ao_cmd_status = ao_cmd_syntax_error; -} - void ao_btm_check_link() __critical { @@ -327,12 +261,6 @@ ao_btm_isr(void) P2IFG = 0; } -__code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_dump, "d\0Dump btm buffer." }, - { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, - { 0, NULL }, -}; - void ao_btm_init (void) { @@ -353,5 +281,4 @@ ao_btm_init (void) PICTL |= PICTL_P2IEN; ao_add_task(&ao_btm_task, ao_btm, "bt"); - ao_cmd_register(&ao_btm_cmds[0]); } -- cgit v1.2.3 From 2ebdb888f6792de70b3132950a988d49752d264e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 14:01:19 -0700 Subject: altosui: Eliminate ao_cmd_filter hook Disabling status messages means we don't need to filter them out of the input stream. Signed-off-by: Keith Packard --- src/ao_btm.c | 31 ------------------------------- src/ao_cmd.c | 5 ----- src/ao_pins.h | 1 - 3 files changed, 37 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 491e4be3..db0ff6b0 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,13 +17,9 @@ #include "ao.h" -uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -void -ao_btm_putchar(char c); - #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -81,32 +77,6 @@ ao_btm_echo(uint8_t echo) ao_stdios[ao_btm_stdio].echo = echo; } -/* - * A command line pre-processor to detect connect/disconnect messages - * and update the internal state - */ - -uint8_t -ao_cmd_filter(void) -{ - if (ao_cur_stdio != ao_btm_stdio) - return 0; - ao_cmd_lex(); - while (ao_cmd_lex_c != '\n') { - if (ao_match_word("CONNECT")) - return 1; - if (ao_match_word("DISCONNECT")) - return 1; - if (ao_match_word("ERROR")) - return 1; - if (ao_match_word("OK")) - return 1; - ao_cmd_lex(); - } - ao_cmd_status = 0; - return 0; -} - /* * Delay between command charaters; the BT module * can't keep up with 57600 baud @@ -226,7 +196,6 @@ ao_btm(void) NULL); ao_btm_echo(0); - ao_btm_running = 1; for (;;) { while (!ao_btm_connected) ao_sleep(&ao_btm_connected); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index c738a3e0..23346c3d 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -274,11 +274,6 @@ ao_cmd(void) for (;;) { readline(); -#if HAS_CMD_FILTER - if (ao_cmd_filter()) - continue; - cmd_i = 0; -#endif ao_cmd_lex(); ao_cmd_white(); c = ao_cmd_lex_c; diff --git a/src/ao_pins.h b/src/ao_pins.h index 1344dcaa..9ee5bdb4 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -224,7 +224,6 @@ #define HAS_BEEP 0 #define HAS_SERIAL_1 1 #define USE_SERIAL_STDIN 1 - #define HAS_CMD_FILTER 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 -- cgit v1.2.3 From d41edb3384b6336f3482e61b0c9f9400a8b4f519 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 15:29:39 -0700 Subject: altosui: Make flight data download work through TeleBT This required flushing input before reading data blocks and adjusting some delays. Signed-off-by: Keith Packard --- altosui/AltosEepromChunk.java | 1 + altosui/AltosEepromList.java | 2 +- altosui/AltosEepromLog.java | 7 ++++--- altosui/libaltos/libaltos.c | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index 8eec407d..1e42077f 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -59,6 +59,7 @@ public class AltosEepromChunk { data = new int[chunk_size]; address = block * chunk_size; + serial_line.flush_input(); serial_line.printf("e %x\n", block); for (offset = 0; offset < chunk_size; offset += per_line) { diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index 575c0bc2..185fec91 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -114,7 +114,7 @@ public class AltosEepromList extends ArrayList { */ for (AltosEepromFlight flight : flights) { add(new AltosEepromLog(serial_line, config_data.serial, - flight.start, flight.end)); + flight.flight, flight.start, flight.end)); } } finally { if (remote) diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index f7fb39e1..0cf420d9 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -47,7 +47,8 @@ public class AltosEepromLog { boolean delete; public AltosEepromLog(AltosSerial serial_line, int in_serial, - int in_start_block, int in_end_block) + int in_flight, int in_start_block, + int in_end_block) throws InterruptedException, TimeoutException { int block; @@ -73,8 +74,8 @@ public class AltosEepromLog { AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); if (block == in_start_block) { - if (eechunk.data(0) != Altos.AO_LOG_FLIGHT) { - flight = eechunk.data16(0); + if (eechunk.data16(0) == in_flight) { + flight = in_flight; has_flight = true; break; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index c5bcf900..5e507cdf 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -698,7 +698,7 @@ altos_bt_open(struct altos_bt_device *device) perror("connect"); goto no_link; } - sleep(2); + sleep(1); #ifdef USE_POLL pipe(file->pipe); -- cgit v1.2.3 From 214cd69c0e4a1617ed5cde8fc2f46a4cee6ecced Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Apr 2011 22:50:58 -0700 Subject: altos: add telebt-v0.0 Makefile Git doesn't like to add these. Signed-off-by: Keith Packard --- src/telebt-v0.0/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/telebt-v0.0/Makefile diff --git a/src/telebt-v0.0/Makefile b/src/telebt-v0.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telebt-v0.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto -- cgit v1.2.3 From 2e7b7b80432bb251ac39efa1fa05d32b5f250e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2011 21:17:07 -0700 Subject: altosui: Separate out flash debug code to separate thread This avoids blocking the Swing thread while waiting for the serial device. Signed-off-by: Keith Packard --- altosui/AltosFlash.java | 15 ++-- altosui/AltosFlashUI.java | 159 ++++++++++++++++++++++++++++++++---------- altosui/AltosRomconfigUI.java | 10 +++ altosui/AltosUI.java | 2 +- 4 files changed, 139 insertions(+), 47 deletions(-) diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java index 802adc8c..e91e9806 100644 --- a/altosui/AltosFlash.java +++ b/altosui/AltosFlash.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosFlash implements Runnable { +public class AltosFlash { File file; FileInputStream input; AltosHexfile image; @@ -252,9 +252,7 @@ public class AltosFlash implements Runnable { throw new IOException("Failed to execute program on target"); } - Thread thread; - - public void run() { + public void flash() { try { if (!check_rom_config()) throw new IOException("Invalid rom config settings"); @@ -333,15 +331,14 @@ public class AltosFlash implements Runnable { } } - public void flash() { - thread = new Thread(this); - thread.start(); + public void close() { + if (debug != null) + debug.close(); } synchronized public void abort() { aborted = true; - if (debug != null) - debug.close(); + close(); } public void addActionListener(ActionListener l) { diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index ad7aeac8..3874b500 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; public class AltosFlashUI extends JDialog @@ -41,14 +41,24 @@ public class AltosFlashUI JProgressBar pbar; JButton cancel; - File file; - Thread thread; JFrame frame; + + // Hex file with rom image + File file; + + // Debug connection AltosDevice debug_dongle; + + // Desired Rom configuration + AltosRomconfig rom_config; + + // Flash controller AltosFlash flash; public void actionPerformed(ActionEvent e) { if (e.getSource() == cancel) { + if (flash != null) + flash.abort(); setVisible(false); dispose(); } else { @@ -111,7 +121,7 @@ public class AltosFlashUI c.gridx = 1; c.gridy = 1; c.anchor = GridBagConstraints.LINE_START; c.insets = ir; - file_value = new JLabel(""); + file_value = new JLabel(file.toString()); pane.add(file_value, c); pbar = new JProgressBar(); @@ -144,18 +154,11 @@ public class AltosFlashUI setLocationRelativeTo(frame); } - public AltosFlashUI(JFrame in_frame) { - super(in_frame, "Program Altusmetrum Device", false); - - frame = in_frame; - - build_dialog(); - - debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any); - - if (debug_dongle == null) - return; + void set_serial(int serial_number) { + serial_value.setText(String.format("%d", serial_number)); + } + boolean select_source_file() { JFileChooser hexfile_chooser = new JFileChooser(); File firmwaredir = AltosPreferences.firmwaredir(); @@ -167,46 +170,128 @@ public class AltosFlashUI int returnVal = hexfile_chooser.showOpenDialog(frame); if (returnVal != JFileChooser.APPROVE_OPTION) - return; - + return false; file = hexfile_chooser.getSelectedFile(); + if (file == null) + return false; + AltosPreferences.set_firmwaredir(file.getParentFile()); + return true; + } - if (file != null) - AltosPreferences.set_firmwaredir(file.getParentFile()); + boolean select_debug_dongle() { + debug_dongle = AltosDeviceDialog.show(frame, Altos.product_any); - try { - flash = new AltosFlash(file, debug_dongle); - flash.addActionListener(this); - AltosRomconfigUI romconfig_ui = new AltosRomconfigUI (frame); + if (debug_dongle == null) + return false; + return true; + } - romconfig_ui.set(flash.romconfig()); - AltosRomconfig romconfig = romconfig_ui.showDialog(); + boolean update_rom_config_info(AltosRomconfig existing_config) { + AltosRomconfig new_config; + new_config = AltosRomconfigUI.show(frame, existing_config); + if (new_config == null) + return false; + rom_config = new_config; + set_serial(rom_config.serial_number); + setVisible(true); + return true; + } - 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(); - } - } catch (FileNotFoundException ee) { + void exception (Exception e) { + if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(frame, "Cannot open image", file.toString(), JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { + } else if (e instanceof AltosSerialInUseException) { JOptionPane.showMessageDialog(frame, String.format("Device \"%s\" already in use", debug_dongle.toShortString()), "Device in use", JOptionPane.ERROR_MESSAGE); - } catch (IOException e) { + } else if (e instanceof IOException) { JOptionPane.showMessageDialog(frame, e.getMessage(), file.toString(), JOptionPane.ERROR_MESSAGE); - } catch (InterruptedException ie) { } } + + class flash_task implements Runnable { + AltosFlashUI ui; + Thread t; + AltosFlash flash; + + public void run () { + try { + flash = new AltosFlash(ui.file, ui.debug_dongle); + flash.addActionListener(ui); + + final AltosRomconfig current_config = flash.romconfig(); + + final Semaphore await_rom_config = new Semaphore(0); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.flash = flash; + ui.update_rom_config_info(current_config); + System.out.printf("Done updating rom config info\n"); + await_rom_config.release(); + } + }); + System.out.printf("Waiting for rom configuration updates\n"); + await_rom_config.acquire(); + System.out.printf("Got rom config update\n"); + + if (ui.rom_config != null) { + System.out.printf("rom_config not null\n"); + flash.set_romconfig(ui.rom_config); + flash.flash(); + } + } catch (Exception ee) { + final Exception e = ee; + System.out.printf("exception %s\n", e.toString()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.exception(e); + } + }); + } + if (flash != null) + flash.close(); + } + + public flash_task(AltosFlashUI in_ui) { + ui = in_ui; + t = new Thread(this); + t.start(); + } + } + + flash_task flasher; + + /* + * Execute the steps for flashing + * a device. Note that this returns immediately; + * this dialog is not modal + */ + void showDialog() { + if (!select_debug_dongle()) + return; + if (!select_source_file()) + return; + build_dialog(); + flash_task f = new flash_task(this); + } + + static void show(JFrame frame) { + AltosFlashUI ui = new AltosFlashUI(frame); + + ui.showDialog(); + } + + public AltosFlashUI(JFrame in_frame) { + super(in_frame, "Program Altusmetrum Device", false); + + frame = in_frame; + } } \ No newline at end of file diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index e1dc974e..7e21735c 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -126,6 +126,11 @@ public class AltosRomconfigUI setLocationRelativeTo(owner); } + public AltosRomconfigUI(JFrame frame, AltosRomconfig config) { + this(frame); + set(config); + } + boolean selected; /* Listen for events from our buttons */ @@ -183,4 +188,9 @@ public class AltosRomconfigUI return romconfig(); return null; } + + public static AltosRomconfig show(JFrame frame, AltosRomconfig config) { + AltosRomconfigUI ui = new AltosRomconfigUI(frame, config); + return ui.showDialog(); + } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 7955c1c2..7bb4ba12 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -219,7 +219,7 @@ public class AltosUI extends JFrame { } void FlashImage() { - new AltosFlashUI(AltosUI.this); + AltosFlashUI.show(AltosUI.this); } void FireIgniter() { -- cgit v1.2.3 From aa5caf6310f074109472e6f55d8bd9751fb75c4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2011 21:26:21 -0700 Subject: altosui: Fix TeleBT name in flight monitor title Was getting the product number, not the product name. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index c2721b26..7a876c25 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -58,19 +58,13 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { } public String toString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; return String.format("%-20.20s %4d %s", getProductName(), getSerial(), getAddr()); } public String toShortString() { - String name = getName(); - if (name == null) - name = "Altus Metrum"; return String.format("%s %d %s", - getProduct(), getSerial(), getAddr()); + getProductName(), getSerial(), getAddr()); } -- cgit v1.2.3 From 109344d54d3fa4f79342fd1ea2a3f4085475e30c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2011 22:28:40 -0700 Subject: altosui: Display reader name (usually the device) when an I/O error occurs Access the reader name directly from the reader object instead of a local variable (which wasn't getting set anyways). Signed-off-by: Keith Packard --- altosui/AltosDisplayThread.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index 84abfae9..ce8d9159 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -33,7 +33,6 @@ public class AltosDisplayThread extends Thread { Frame parent; IdleThread idle_thread; AltosVoice voice; - String name; AltosFlightReader reader; int crc_errors; AltosFlightDisplay display; @@ -57,19 +56,18 @@ public class AltosDisplayThread extends Thread { SwingUtilities.invokeLater(r); } - void reading_error_internal(String name) { + void reading_error_internal() { JOptionPane.showMessageDialog(parent, - String.format("Error reading from \"%s\"", name), + String.format("Error reading from \"%s\"", reader.name), "Telemetry Read Error", JOptionPane.ERROR_MESSAGE); } - void reading_error_safely(String in_name) { - final String name = in_name; + void reading_error_safely() { Runnable r = new Runnable() { public void run() { try { - reading_error_internal(name); + reading_error_internal(); } catch (Exception ex) { } } @@ -258,7 +256,7 @@ public class AltosDisplayThread extends Thread { } catch (InterruptedException ee) { interrupted = true; } catch (IOException ie) { - reading_error_safely(name); + reading_error_safely(); } finally { if (!interrupted) idle_thread.report(true); -- cgit v1.2.3 From e3bf13a38d24e95b16df1e2f01952d10f24cda10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2011 22:55:08 -0700 Subject: altosui: Move AltosIgniteUI device open out of Swing thread Eliminate more blocking code from the Swing thread. Signed-off-by: Keith Packard --- altosui/AltosIgniteUI.java | 93 +++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index ad5b7cfb..42120b92 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -56,8 +56,27 @@ public class AltosIgniteUI class IgniteHandler implements Runnable { AltosIgnite ignite; + JFrame owner; + + void send_exception(Exception e) { + final Exception f_e = e; + Runnable r = new Runnable() { + public void run() { + ignite_exception(f_e); + } + }; + SwingUtilities.invokeLater(r); + } public void run () { + try { + ignite = new AltosIgnite(device); + } catch (Exception e) { + send_exception(e); + return; + } + ignite.set_frame(owner); + for (;;) { Runnable r; @@ -87,25 +106,45 @@ public class AltosIgniteUI ignite_reply(f_reply); } }; + SwingUtilities.invokeLater(r); } catch (Exception e) { - final Exception f_e = e; - r = new Runnable() { - public void run() { - ignite_exception(f_e); - } - }; + send_exception(e); } - SwingUtilities.invokeLater(r); } } - public IgniteHandler(AltosIgnite in_ignite) { - ignite = in_ignite; + public IgniteHandler(JFrame in_owner) { + owner = in_owner; } } void ignite_exception(Exception e) { - abort(); + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); } void ignite_reply(String reply) { @@ -149,7 +188,7 @@ public class AltosIgniteUI try { command_queue.put(command); } catch (Exception ex) { - abort(); + ignite_exception(ex); } } @@ -194,15 +233,6 @@ public class AltosIgniteUI dispose(); } - void abort() { - close(); - JOptionPane.showMessageDialog(owner, - String.format("Connection to \"%s\" failed", - device.toShortString()), - "Connection Failed", - JOptionPane.ERROR_MESSAGE); - } - void tick_timer() { if (timer_running) { --time_remaining; @@ -277,31 +307,10 @@ public class AltosIgniteUI device = AltosDeviceDialog.show(owner, Altos.product_any); if (device != null) { - try { - AltosIgnite ignite = new AltosIgnite(device); - IgniteHandler handler = new IgniteHandler(ignite); + IgniteHandler handler = new IgniteHandler(owner); Thread t = new Thread(handler); - ignite.set_frame(owner); t.start(); return true; - } catch (FileNotFoundException ee) { - JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), - "Cannot open target device", - JOptionPane.ERROR_MESSAGE); - } catch (AltosSerialInUseException si) { - JOptionPane.showMessageDialog(owner, - String.format("Device \"%s\" already in use", - device.toShortString()), - "Device in use", - JOptionPane.ERROR_MESSAGE); - } catch (IOException ee) { - JOptionPane.showMessageDialog(owner, - device.toShortString(), - ee.getLocalizedMessage(), - JOptionPane.ERROR_MESSAGE); - } } return false; } -- cgit v1.2.3 From 72a03baa73698fc1213a74320e6253c2380dd8fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Apr 2011 23:00:42 -0700 Subject: altosui: Fix BT manage dialog so that the device lists resize This makes the device scrolling lists fill any extra space when the window is resized. Signed-off-by: Keith Packard --- altosui/AltosBTManage.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 98a8b757..10fdab3b 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -241,6 +241,8 @@ public class AltosBTManage extends JDialog implements ActionListener, Iterable Date: Fri, 6 May 2011 15:44:56 -0700 Subject: altos: Add preliminary telebt v0.1 defines This should make the telebt v0.1 binary that works on the real hardware. Signed-off-by: Keith Packard --- src/Makefile.proto | 8 +++++++- src/ao_log_telem.c | 30 ++++++++++++++++++++++++++++++ src/ao_pins.h | 28 ++++++++++++++++++++++++++++ src/ao_telebt.c | 4 ++++ src/telebt-v0.1/.gitignore | 2 ++ src/telebt-v0.1/.sdcdbrc | 1 + src/telebt-v0.1/Makefile | 1 + src/telebt-v0.1/Makefile.defs | 8 ++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/ao_log_telem.c create mode 100644 src/telebt-v0.1/.gitignore create mode 100644 src/telebt-v0.1/.sdcdbrc create mode 100644 src/telebt-v0.1/Makefile create mode 100644 src/telebt-v0.1/Makefile.defs diff --git a/src/Makefile.proto b/src/Makefile.proto index ca68edbc..04b708b2 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -238,7 +238,7 @@ TNANO_BASE_SRC = \ $(TNANO_MAIN_SRC) # -# Sources for TeleDongle +# Sources for TeleBluetooth # TBT_MAIN_SRC = \ @@ -255,6 +255,12 @@ TBT_BASE_SRC = \ $(DBG_SRC) \ $(TBT_MAIN_SRC) +TBT_V_0_1_SRC = \ + $(TBT_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(M25_DRIVER_SRC) \ + ao_log_telem.c + # # TI Dongle sources # diff --git a/src/ao_log_telem.c b/src/ao_log_telem.c new file mode 100644 index 00000000..1b472efe --- /dev/null +++ b/src/ao_log_telem.c @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +ao_log_write_erase(uint8_t pos) +{ + (void) pos; +} + +uint8_t +ao_log_present(void) +{ + return 0; +} diff --git a/src/ao_pins.h b/src/ao_pins.h index 324d7827..bc9bdcb9 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -243,6 +243,34 @@ #define HAS_IGNITE 0 #endif +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 295f0cec..34d4432d 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -27,6 +27,10 @@ main(void) ao_led_on(AO_LED_RED); ao_timer_init(); ao_cmd_init(); +#if HAS_EEPROM + ao_spi_init(); + ao_storage_init(); +#endif ao_usb_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); diff --git a/src/telebt-v0.1/.gitignore b/src/telebt-v0.1/.gitignore new file mode 100644 index 00000000..1acfbfcc --- /dev/null +++ b/src/telebt-v0.1/.gitignore @@ -0,0 +1,2 @@ +telebt-* +ao_product.h diff --git a/src/telebt-v0.1/.sdcdbrc b/src/telebt-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telebt-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telebt-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs new file mode 100644 index 00000000..50657c83 --- /dev/null +++ b/src/telebt-v0.1/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telebt-v0.1-$(VERSION).ihx + +SRC = \ + $(TBT_V_0_1_SRC) + +PRODUCT=TeleBT-v0.1 +PRODUCT_DEF=-DTELEBT_V_0_1 +IDPRODUCT=0x000e -- cgit v1.2.3 From c360e5c04e30421e9ea2f7006b7d35aef35f1edd Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 6 May 2011 17:57:17 -0600 Subject: first cut at a telebt turn on script --- ao-bringup/turnon_telebt | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 4 ++-- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100755 ao-bringup/turnon_telebt diff --git a/ao-bringup/turnon_telebt b/ao-bringup/turnon_telebt new file mode 100755 index 00000000..3b8bd3e4 --- /dev/null +++ b/ao-bringup/turnon_telebt @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleBT v0.1 Turn-On and Calibration Program" +echo "Copyright 2011 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleBT v0.1 powered from USB" +echo "\t\twith TeleDonle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from SMA to frequency counter" +echo +echo -n "TeleBT serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD -D 100 -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +$RAWLOAD -D 100 -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` + +echo "Programming flash with cal value " $CAL_VALUE +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/telebt-v0.1*.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/debian/changelog b/debian/changelog index 63d75356..fe01210d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.9.1) unstable; urgency=low +altos (0.9.1.telemini.1) unstable; urgency=low [ Keith Packard ] * ao-load: fix usage message to note that '=' is required for options @@ -13,7 +13,7 @@ altos (0.9.1) unstable; urgency=low [ Bdale Garbee ] * tie bringup scripts to Bdale's bench TeleDongle - -- Bdale Garbee Fri, 18 Feb 2011 23:55:58 -0700 + -- Bdale Garbee Fri, 01 Apr 2011 20:02:12 -0600 altos (0.9) unstable; urgency=low -- cgit v1.2.3 From d9cc27641fe1778c098b065bf110be7823e6c9f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 16:57:38 -0700 Subject: altos: Add telebt-v0.1 to Makefile Doesn't get built without it. Signed-off-by: Keith Packard --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index d83ec668..3eec3980 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,7 +10,7 @@ SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v0.1 telenano-v0.1 \ - telebt-v0.0 \ + telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test -- cgit v1.2.3 From 19bfa3882a2d95fcade256c2d63ad24f794281e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 20:33:58 -0700 Subject: altos: Use USART configuration 1 with flow control for TBT It's just wired that way. Signed-off-by: Keith Packard --- src/ao_pins.h | 3 +++ src/ao_serial.c | 18 ++++++++++++++++++ src/cc1111.h | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/src/ao_pins.h b/src/ao_pins.h index bc9bdcb9..4c31f755 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -248,6 +248,9 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 #define USE_SERIAL_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 diff --git a/src/ao_serial.c b/src/ao_serial.c index 9c0b798d..2e7dad7b 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -127,6 +127,18 @@ ao_serial_set_speed(uint8_t speed) void ao_serial_init(void) { +#if HAS_SERIAL_1_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_1_HW_FLOW + P0SEL |= (1 << 3) | (1 << 2); +#endif +#else /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; @@ -135,6 +147,8 @@ ao_serial_init(void) /* Make the USART pins be controlled by the USART */ P1SEL |= (1 << 6) | (1 << 7); + P1SEL |= (1 << 5) | (1 << 4); +#endif /* UART mode with receiver enabled */ U1CSR = (UxCSR_MODE_UART | UxCSR_RE); @@ -144,7 +158,11 @@ ao_serial_init(void) /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_1_HW_FLOW + UxUCR_FLOW_ENABLE | +#else UxUCR_FLOW_DISABLE | +#endif UxUCR_D9_EVEN_PARITY | UxUCR_BIT9_8_BITS | UxUCR_PARITY_DISABLE | diff --git a/src/cc1111.h b/src/cc1111.h index a07490e5..5b018cb5 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -589,6 +589,12 @@ sfr at 0xFD P0DIR; sfr at 0xFE P1DIR; sfr at 0xFF P2DIR; +#define P2DIR_PRIP0_USART0_USART1 (0 << 6) +#define P2DIR_PRIP0_USART1_USART0 (1 << 6) +#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) +#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) +#define P2DIR_PRIP0_MASK (3 << 6) + sfr at 0x8F P0INP; /* Select between tri-state and pull up/down -- cgit v1.2.3 From 3336d0f726afd1d43cf62280940e5fb91dab2e91 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 21:13:19 -0700 Subject: altos: Fix BT link status pin for real TBT hardware The prototype used P2_1, while the real hardware uses P1_7. Lots of defines to make this work... Signed-off-by: Keith Packard --- src/ao_btm.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- src/ao_pins.h | 8 ++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index db0ff6b0..355c3ca4 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -208,26 +208,44 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + void ao_btm_check_link() __critical { - if (P2_1) { + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { ao_btm_connected = 0; - PICTL |= PICTL_P2ICON; + PICTL |= BT_PICTL_ICON; } else { ao_btm_connected = 1; - PICTL &= ~PICTL_P2ICON; + PICTL &= ~BT_PICTL_ICON; } } void ao_btm_isr(void) { - if (P2IFG & (1 << 1)) { + if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); ao_wakeup(&ao_btm_connected); } - P2IFG = 0; + BT_PIFG = 0; } void @@ -240,14 +258,26 @@ ao_btm_init (void) * Configure link status line */ - /* Set P2_1 to input, pull-down */ - P2DIR &= ~(1 << 1); - P2INP |= P2INP_MDP2_1_TRISTATE; + /* Set pin to input */ + BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); + + /* Set pin to tri-state */ + BT_PINP |= (1 << BT_LINK_PIN_INDEX); - /* Enable P2 interrupts */ - IEN2 |= IEN2_P2IE; + /* Enable interrupts */ + IEN2 |= BT_IEN2_PIE; + + /* Check current pin state */ ao_btm_check_link(); + +#if BT_LINK_ON_P2 + /* Eable the pin interrupt */ PICTL |= PICTL_P2IEN; +#endif +#if BT_LINK_ON_P1 + /* Enable pin interrupt */ + P1IEN |= (1 << BT_LINK_PIN_INDEX); +#endif ao_add_task(&ao_btm_task, ao_btm, "bt"); } diff --git a/src/ao_pins.h b/src/ao_pins.h index 4c31f755..21b99027 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -241,6 +241,10 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 #endif #if defined(TELEBT_V_0_1) @@ -272,6 +276,10 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 #endif #if DBG_ON_P1 -- cgit v1.2.3 From 6d858b64ee0e8c227c149d2af6d2d634536964f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:12:31 -0700 Subject: altos: pull TBT v0.1 ser_reset line low This line resets the BT module if held low for three seconds. Signed-off-by: Keith Packard --- src/ao_btm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/ao_btm.c b/src/ao_btm.c index 355c3ca4..241b3f6a 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -254,6 +254,15 @@ ao_btm_init (void) ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); +#if BT_LINK_ON_P1 + /* + * Configure ser reset line + */ + + P1_6 = 0; + P1DIR |= (1 << 6); +#endif + /* * Configure link status line */ -- cgit v1.2.3 From 22e3ac0eb014b8255029763ae8180ad3527ba306 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:42:32 -0700 Subject: altos: Add beeper to TBT v0.1 It's available, let's use it. Signed-off-by: Keith Packard --- src/Makefile.proto | 1 + src/ao_btm.c | 4 ++++ src/ao_pins.h | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 04b708b2..c86de823 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -259,6 +259,7 @@ TBT_V_0_1_SRC = \ $(TBT_BASE_SRC) \ $(SPI_DRIVER_SRC) \ $(M25_DRIVER_SRC) \ + $(BEEP_DRIVER_SRC) \ ao_log_telem.c # diff --git a/src/ao_btm.c b/src/ao_btm.c index 241b3f6a..4b3c5209 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -166,6 +166,10 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); +#if HAS_BEEP + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +#endif + /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see diff --git a/src/ao_pins.h b/src/ao_pins.h index 21b99027..4a03ca50 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -250,7 +250,7 @@ #if defined(TELEBT_V_0_1) #define HAS_FLIGHT 0 #define HAS_USB 1 - #define HAS_BEEP 0 + #define HAS_BEEP 1 #define HAS_SERIAL_1 1 #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 -- cgit v1.2.3 From 514348055630edec12224c4b0964240b929759a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:42:58 -0700 Subject: altos: Debugging TBT issues -- check pin configuration after boot Make sure the serial pins are configured as peripherals Make sure the ser_reset and bt_link pins are going the right direction. Signed-off-by: Keith Packard --- src/ao_btm.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 4b3c5209..490b2667 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,6 +17,21 @@ #include "ao.h" +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -166,6 +181,15 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); +#if BT_LINK_ON_P1 + if ((P1DIR & (1 << 6)) == 0) + ao_panic(AO_PANIC_BT); + if ((P1DIR & (1 << 7)) != 0) + ao_panic(AO_PANIC_BT); + if ((P0SEL & ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) != + ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) + ao_panic(AO_PANIC_BT); +#endif #if HAS_BEEP ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); #endif @@ -212,21 +236,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - void ao_btm_check_link() __critical { -- cgit v1.2.3 From 23f441b95e55fbee709382b05d325bc021285766 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:49:54 -0700 Subject: altos: Initialize beeper for telebt Needed to get sounds to come out Signed-off-by: Keith Packard --- src/ao_telebt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 34d4432d..8e77c4d9 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -26,6 +26,9 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_timer_init(); +#if HAS_BEEP + ao_beep_init(); +#endif ao_cmd_init(); #if HAS_EEPROM ao_spi_init(); -- cgit v1.2.3 From 8be559baa979c15e78f8dba7879b383dbe3936d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:59:15 -0700 Subject: altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line Otherwise, we're heading off into the weeds... Signed-off-by: Keith Packard --- src/ao.h | 12 ++++++++++-- src/ao_btm.c | 3 +++ src/ao_usb.c | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index 226f9a22..600c488a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1367,9 +1367,17 @@ ao_packet_slave_init(uint8_t enable); /* ao_btm.c */ -/* Shared by USB, so the USB code calls this function */ +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + void -ao_btm_isr(void); +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; + void ao_btm_init(void); diff --git a/src/ao_btm.c b/src/ao_btm.c index 490b2667..172004e9 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -253,6 +253,9 @@ ao_btm_check_link() __critical void ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif { if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); diff --git a/src/ao_usb.c b/src/ao_usb.c index ece6756a..dd752152 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -59,8 +59,10 @@ ao_usb_isr(void) __interrupt 6 if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); #if HAS_BTM +#if BT_LINK_ON_P2 ao_btm_isr(); #endif +#endif } struct ao_usb_setup { -- cgit v1.2.3 From 66bdf0e066bc0bb7a326a6c2a9c88b69e5c1be66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 23:12:47 -0700 Subject: altos: clear CPU port 1 interrupt flag when handled Signed-off-by: Keith Packard --- src/ao_btm.c | 3 +++ src/ao_usb.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index 172004e9..a9306c10 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -257,6 +257,9 @@ ao_btm_isr(void) __interrupt 15 #endif { +#if BT_LINK_ON_P1 + P1IF = 0; +#endif if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); ao_wakeup(&ao_btm_connected); diff --git a/src/ao_usb.c b/src/ao_usb.c index dd752152..e4b7938d 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -46,7 +46,6 @@ void ao_usb_isr(void) __interrupt 6 { USBIF = 0; - IRCON2 &= ~IRCON2_USBIF; ao_usb_iif |= USBIIF; if (ao_usb_iif & 1) ao_wakeup(&ao_usb_task); -- cgit v1.2.3 From 479bdffa35d0b8d4e48868c8d20f3cb1549521ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 23:55:23 -0700 Subject: Revert "altos: Debugging TBT issues -- check pin configuration after boot" This reverts commit 514348055630edec12224c4b0964240b929759a3. Looks like this was never a problem. --- src/ao_btm.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/src/ao_btm.c b/src/ao_btm.c index a9306c10..44155ec1 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,21 +17,6 @@ #include "ao.h" -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -181,15 +166,6 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); -#if BT_LINK_ON_P1 - if ((P1DIR & (1 << 6)) == 0) - ao_panic(AO_PANIC_BT); - if ((P1DIR & (1 << 7)) != 0) - ao_panic(AO_PANIC_BT); - if ((P0SEL & ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) != - ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) - ao_panic(AO_PANIC_BT); -#endif #if HAS_BEEP ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); #endif @@ -236,6 +212,21 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + void ao_btm_check_link() __critical { -- cgit v1.2.3 From 4d27e281f81aee88adff3d84085356ec310e4b92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 May 2011 21:38:02 -0600 Subject: Switch version to 0.9.4 For Mayhem, so we can tell what version each board is running Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 83cf9987..32ef7d74 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.1) +AC_INIT([altos], 0.9.4) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From dc0b49dcbaa2d0a69e002c151337b6e9fd3060d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 2 Jun 2011 23:16:30 -0700 Subject: altosui: Handle old TeleDongle receiving kalman telemetry packets The telemetry packets now send the kalman height/speed/accel values instead of the ad-hoc values. If received by an old TeleDongle box, the speed value will be of the form 0x8000abcd, which will be printed as a 32-bit value by TeleDongle. We only want the abcd part, which is the speed * 16. Detect this automatically and compute the correct values for all three. Signed-off-by: Keith Packard --- altosui/AltosTelemetry.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index 91b6d048..7d68b5b5 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -326,6 +326,16 @@ public class AltosTelemetry extends AltosRecord { AltosParse.word(words[i++], "fp:"); flight_pres = AltosParse.parse_int(words[i++]); + /* Old TeleDongle code with kalman-reporting TeleMetrum code */ + if ((flight_vel & 0xffff0000) == 0x80000000) { + speed = ((short) flight_vel) / 16.0; + acceleration = flight_accel / 16.0; + height = flight_pres; + flight_vel = MISSING; + flight_pres = MISSING; + flight_accel = MISSING; + } + AltosParse.word(words[i++], "gp:"); ground_pres = AltosParse.parse_int(words[i++]); -- cgit v1.2.3 From 0e67b6890dd3a06665239f8dfd2e69266d055e46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Jun 2011 12:26:45 -0700 Subject: altos: Rename telemetry to telemetry_orig This makes room to create a new multi-packet telemetry format without changing anything yet. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- src/ao.h | 13 +++--- src/ao_monitor.c | 66 ++++++++++++++++-------------- src/ao_radio.c | 3 -- src/ao_telemetrum.c | 2 +- src/ao_telemetry.c | 105 ------------------------------------------------ src/ao_telemetry_orig.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 149 insertions(+), 147 deletions(-) delete mode 100644 src/ao_telemetry.c create mode 100644 src/ao_telemetry_orig.c diff --git a/src/Makefile.proto b/src/Makefile.proto index c86de823..bc7b3a7f 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -160,7 +160,7 @@ TM_TASK_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_orig.c TM_MAIN_SRC = \ ao_telemetrum.c diff --git a/src/ao.h b/src/ao.h index 600c488a..b6a987e3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1079,10 +1079,11 @@ struct ao_telemetry_tiny { /* * ao_radio_recv tacks on rssi and status bytes */ -struct ao_telemetry_recv { - struct ao_telemetry telemetry; - int8_t rssi; - uint8_t status; + +struct ao_telemetry_orig_recv { + struct ao_telemetry_orig telemetry_orig; + int8_t rssi; + uint8_t status; }; struct ao_telemetry_tiny_recv { @@ -1104,7 +1105,7 @@ void ao_rdf_set(uint8_t rdf); void -ao_telemetry_init(void); +ao_telemetry_orig_init(void); void ao_telemetry_tiny_init(void); @@ -1160,7 +1161,7 @@ void ao_monitor(void); #define AO_MONITORING_OFF 0 -#define AO_MONITORING_FULL 1 +#define AO_MONITORING_ORIG 1 #define AO_MONITORING_TINY 2 void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 8f290071..248857de 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,11 +26,12 @@ ao_monitor(void) { __xdata char callsign[AO_MAX_CALLSIGN+1]; __xdata union { - struct ao_telemetry_recv full; + struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; } u; -#define recv (u.full) +#define recv_raw (u.raw) +#define recv_orig (u.orig) #define recv_tiny (u.tiny) uint8_t state; @@ -39,18 +40,19 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (ao_monitoring == AO_MONITORING_FULL) { - if (!ao_radio_recv(&recv, sizeof (struct ao_telemetry_recv))) + switch (ao_monitoring) { + case AO_MONITORING_ORIG: + if (!ao_radio_recv(&recv_orig, sizeof (struct ao_telemetry_orig_recv))) continue; - state = recv.telemetry.flight_state; + state = recv_orig.telemetry_orig.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv.rssi >> 1) - 74; - memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); + rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; - if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { + if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { /* General header fields */ printf(AO_TELEM_VERSION " %d " @@ -62,11 +64,11 @@ ao_monitor(void) AO_TELEM_TICK " %d ", AO_TELEMETRY_VERSION, callsign, - recv.telemetry.serial, - recv.telemetry.flight, + recv_orig.telemetry_orig.serial, + recv_orig.telemetry_orig.flight, rssi, ao_state_names[state], - recv.telemetry.adc.tick); + recv_orig.telemetry_orig.adc.tick); /* Raw sensor values */ printf(AO_TELEM_RAW_ACCEL " %d " @@ -75,48 +77,49 @@ ao_monitor(void) AO_TELEM_RAW_BATT " %d " AO_TELEM_RAW_DROGUE " %d " AO_TELEM_RAW_MAIN " %d ", - recv.telemetry.adc.accel, - recv.telemetry.adc.pres, - recv.telemetry.adc.temp, - recv.telemetry.adc.v_batt, - recv.telemetry.adc.sense_d, - recv.telemetry.adc.sense_m); + recv_orig.telemetry_orig.adc.accel, + recv_orig.telemetry_orig.adc.pres, + recv_orig.telemetry_orig.adc.temp, + recv_orig.telemetry_orig.adc.v_batt, + recv_orig.telemetry_orig.adc.sense_d, + recv_orig.telemetry_orig.adc.sense_m); /* Sensor calibration values */ printf(AO_TELEM_CAL_ACCEL_GROUND " %d " AO_TELEM_CAL_BARO_GROUND " %d " AO_TELEM_CAL_ACCEL_PLUS " %d " AO_TELEM_CAL_ACCEL_MINUS " %d ", - recv.telemetry.ground_accel, - recv.telemetry.ground_pres, - recv.telemetry.accel_plus_g, - recv.telemetry.accel_minus_g); + recv_orig.telemetry_orig.ground_accel, + recv_orig.telemetry_orig.ground_pres, + recv_orig.telemetry_orig.accel_plus_g, + recv_orig.telemetry_orig.accel_minus_g); - if (recv.telemetry.u.k.unused == 0x8000) { + if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { /* Kalman state values */ printf(AO_TELEM_KALMAN_HEIGHT " %d " AO_TELEM_KALMAN_SPEED " %d " AO_TELEM_KALMAN_ACCEL " %d ", - recv.telemetry.height, - recv.telemetry.u.k.speed, - recv.telemetry.accel); + recv_orig.telemetry_orig.height, + recv_orig.telemetry_orig.u.k.speed, + recv_orig.telemetry_orig.accel); } else { /* Ad-hoc flight values */ printf(AO_TELEM_ADHOC_ACCEL " %d " AO_TELEM_ADHOC_SPEED " %ld " AO_TELEM_ADHOC_BARO " %d ", - recv.telemetry.accel, - recv.telemetry.u.flight_vel, - recv.telemetry.height); + recv_orig.telemetry_orig.accel, + recv_orig.telemetry_orig.u.flight_vel, + recv_orig.telemetry_orig.height); } - ao_gps_print(&recv.telemetry.gps); - ao_gps_tracking_print(&recv.telemetry.gps_tracking); + ao_gps_print(&recv_orig.telemetry_orig.gps); + ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); ao_rssi_set(rssi); } else { printf("CRC INVALID RSSI %3d\n", rssi); } - } else { + break; + case AO_MONITORING_TINY: if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) continue; @@ -181,6 +184,7 @@ ao_monitor(void) } else { printf("CRC INVALID RSSI %3d\n", rssi); } + break; } ao_usb_flush(); ao_led_toggle(ao_monitor_led); diff --git a/src/ao_radio.c b/src/ao_radio.c index b5a67b99..01974ba1 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -161,8 +161,6 @@ static __code uint8_t radio_setup[] = { RF_SYNC0_OFF, 0x91, /* max packet length */ - RF_PKTLEN_OFF, sizeof (struct ao_telemetry), - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_APPEND_STATUS| PKTCTRL1_ADR_CHK_NONE), @@ -233,7 +231,6 @@ static __code uint8_t fixed_pkt_setup[] = { (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), /* max packet length -- now set inline */ - // RF_PKTLEN_OFF, sizeof (struct ao_telemetry), RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_APPEND_STATUS| PKTCTRL1_ADR_CHK_NONE), diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 4ace415c..bede5868 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_serial_init(); ao_gps_init(); ao_gps_report_init(); - ao_telemetry_init(); + ao_telemetry_orig_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c deleted file mode 100644 index 9a86882f..00000000 --- a/src/ao_telemetry.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata uint16_t ao_telemetry_interval = 0; -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry telemetry; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.serial = ao_serial_number; - telemetry.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.accel_plus_g = ao_config.accel_plus_g; - telemetry.accel_minus_g = ao_config.accel_minus_g; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - telemetry.flight_state = ao_flight_state; - telemetry.height = ao_height; - telemetry.u.k.speed = ao_speed; - telemetry.accel = ao_accel; - telemetry.u.k.unused = 0x8000; -#if HAS_ACCEL - telemetry.ground_accel = ao_ground_accel; -#endif - telemetry.ground_pres = ao_ground_pres; -#if HAS_ADC - ao_adc_get(&telemetry.adc); -#endif -#if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); -#endif - ao_radio_send(&telemetry, sizeof (telemetry)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - ao_wakeup(&ao_telemetry_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_task; - -void -ao_telemetry_init() -{ - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); -} diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c new file mode 100644 index 00000000..9a86882f --- /dev/null +++ b/src/ao_telemetry_orig.c @@ -0,0 +1,105 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + static __xdata struct ao_telemetry telemetry; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + telemetry.serial = ao_serial_number; + telemetry.flight = ao_log_full() ? 0 : ao_flight_number; + telemetry.accel_plus_g = ao_config.accel_plus_g; + telemetry.accel_minus_g = ao_config.accel_minus_g; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&ao_telemetry_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + telemetry.flight_state = ao_flight_state; + telemetry.height = ao_height; + telemetry.u.k.speed = ao_speed; + telemetry.accel = ao_accel; + telemetry.u.k.unused = 0x8000; +#if HAS_ACCEL + telemetry.ground_accel = ao_ground_accel; +#endif + telemetry.ground_pres = ao_ground_pres; +#if HAS_ADC + ao_adc_get(&telemetry.adc); +#endif +#if HAS_GPS + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); +#endif + ao_radio_send(&telemetry, sizeof (telemetry)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + ao_wakeup(&ao_telemetry_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} -- cgit v1.2.3 From 489a68ba8e3bc360e2e8fc887e4c4b840b5a0dd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Jun 2011 12:27:34 -0700 Subject: altos: Add arbitrary telemetry packet monitoring This adds the ability to monitor arbitrary telemetry packets (up to 128 bytes), moving the telemetry data parsing up to the host. Signed-off-by: Keith Packard --- src/ao.h | 9 +++++++-- src/ao_monitor.c | 10 ++++++++++ src/ao_telemetry_orig.c | 10 +++++----- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/ao.h b/src/ao.h index b6a987e3..f5753703 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1036,12 +1036,13 @@ void ao_gps_report_init(void); /* - * ao_telemetry.c + * ao_telemetry_orig.c */ #define AO_MAX_CALLSIGN 8 +#define AO_MAX_TELEMETRY 128 -struct ao_telemetry { +struct ao_telemetry_orig { uint16_t serial; uint16_t flight; uint8_t flight_state; @@ -1080,6 +1081,10 @@ struct ao_telemetry_tiny { * ao_radio_recv tacks on rssi and status bytes */ +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + struct ao_telemetry_orig_recv { struct ao_telemetry_orig telemetry_orig; int8_t rssi; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 248857de..ac1929db 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,6 +26,7 @@ ao_monitor(void) { __xdata char callsign[AO_MAX_CALLSIGN+1]; __xdata union { + struct ao_telemetry_raw_recv raw; struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; } u; @@ -185,6 +186,15 @@ ao_monitor(void) printf("CRC INVALID RSSI %3d\n", rssi); } break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + if (!ao_radio_recv(&recv_raw, ao_monitoring)) + continue; + for (state = 0; state < ao_monitoring + 1; state++) + printf("%02x ", recv_raw.packet[state]); + printf("%02x\n", recv_raw.packet[state]); + break; } ao_usb_flush(); ao_led_toggle(ao_monitor_led); diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c index 9a86882f..4b3a344a 100644 --- a/src/ao_telemetry_orig.c +++ b/src/ao_telemetry_orig.c @@ -25,11 +25,11 @@ __xdata uint16_t ao_rdf_time; #define AO_RDF_LENGTH_MS 500 void -ao_telemetry(void) +ao_telemetry_orig(void) { uint16_t time; int16_t delay; - static __xdata struct ao_telemetry telemetry; + static __xdata struct ao_telemetry_orig telemetry; ao_config_get(); while (!ao_flight_number) @@ -96,10 +96,10 @@ ao_rdf_set(uint8_t rdf) ao_rdf_time = ao_time(); } -__xdata struct ao_task ao_telemetry_task; +__xdata struct ao_task ao_telemetry_orig_task; void -ao_telemetry_init() +ao_telemetry_orig_init() { - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); + ao_add_task(&ao_telemetry_orig_task, ao_telemetry_orig, "telemetry_orig"); } -- cgit v1.2.3 From 5e111fdf1f23203baeeb490ae1b69402ebd513b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Jun 2011 08:31:12 -0700 Subject: altos: Add checksum to TELEM output lines Verify the received telemetry lines to protect against OS data loss Signed-off-by: Keith Packard --- src/ao_monitor.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index ac1929db..1d083c59 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -36,6 +36,7 @@ ao_monitor(void) #define recv_tiny (u.tiny) uint8_t state; + uint8_t sum, byte; int16_t rssi; for (;;) { @@ -191,9 +192,14 @@ ao_monitor(void) ao_monitoring = AO_MAX_TELEMETRY; if (!ao_radio_recv(&recv_raw, ao_monitoring)) continue; - for (state = 0; state < ao_monitoring + 1; state++) - printf("%02x ", recv_raw.packet[state]); - printf("%02x\n", recv_raw.packet[state]); + printf ("TELEM %02x", ao_monitoring+2); + sum = 0x5a; + for (state = 0; state < ao_monitoring + 2; state++) { + byte = recv_raw.packet[state]; + sum += byte; + printf("%02x", byte); + } + printf("%02x\n", sum); break; } ao_usb_flush(); -- cgit v1.2.3 From 336224a08327cadc95f6e5b564a4ddc64aaad8f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Jun 2011 08:31:51 -0700 Subject: altos: Start adding new telemetry frame definitions These use the initial 24 bytes per frame plan, which will probably get changed to 32 bytes per frame. Signed-off-by: Keith Packard --- src/ao.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/ao.h b/src/ao.h index f5753703..4895f016 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1042,6 +1042,95 @@ ao_gps_report_init(void); #define AO_MAX_CALLSIGN 8 #define AO_MAX_TELEMETRY 128 +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[19]; /* 5 */ + /* 24 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + /* 24 */ +}; + +#define AO_TELEMETRY_CONSTANT 0x10 + +struct ao_telemetry_constant { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + int16_t ground_accel; /* 8 average ground accelerometer (TM only) */ + int16_t ground_pres; /* 10 average ground barometer */ + int16_t accel_plus_g; /* 12 +1g accelerometer calibration value (TM only) */ + int16_t accel_minus_g; /* 14 -1g accelermeter calibration value (TM only) */ + char callsign[AO_MAX_CALLSIGN]; /* 16 identity */ + /* 24 */ +}; + +#define AO_TELEMETRY_LOCATION 0x11 + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t hdop; /* 22 (m * 5) */ + uint8_t unused; /* 23 */ + /* 24 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x12 + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + uint8_t sats_0_1[3]; /* 6 reported sats 0 and 1 */ + uint8_t sats_2_3[3]; + uint8_t sats_4_5[3]; + uint8_t sats_6_7[3]; + uint8_t sats_8_9[3]; + uint8_t sats_10_11[3]; + /* 24 */ +}; + +#define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) +#define AO_SAT_0_C_N_1(s) ((((s)[0] & 0xc0) >> 2) | ((s)[1] & 0x0f)) +#define AO_SAT_1_SSID(s) ((((s)[1] & 0xf0) >> 2) | ((s)[2] & 0x03)) +#define AO_SAT_1_C_N_1(s) (((s)[2] & 0xfc) >> 2) + struct ao_telemetry_orig { uint16_t serial; uint16_t flight; -- cgit v1.2.3 From cb239b7161feea8646425b1f5788c3c82ae24321 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2011 01:01:08 -0700 Subject: altos: ao_radio_recv needs byte count *including* rssi and status That's two more than the actual packet length. Signed-off-by: Keith Packard --- src/ao_monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 1d083c59..e5e9159f 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -190,9 +190,9 @@ ao_monitor(void) default: if (ao_monitoring > AO_MAX_TELEMETRY) ao_monitoring = AO_MAX_TELEMETRY; - if (!ao_radio_recv(&recv_raw, ao_monitoring)) + if (!ao_radio_recv(&recv_raw, ao_monitoring + 2)) continue; - printf ("TELEM %02x", ao_monitoring+2); + printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { byte = recv_raw.packet[state]; -- cgit v1.2.3 From 7fd9b8f720add559b262e81d61ededc9df16ca94 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2011 01:03:00 -0700 Subject: altosui: Support raw telemetry from TeleDongle Use raw telemetry frames when TeleDongle supports them, this involves parsing the hex dump of the packet instead of having teledongle take the packet apart. Only the legacy format is working at this point; the altos bits for the new split telemetry frames is not written yet. Signed-off-by: Keith Packard --- altosui/Altos.java | 68 +++- altosui/AltosEepromIterable.java | 1 + altosui/AltosFile.java | 2 +- altosui/AltosFlightUI.java | 10 +- altosui/AltosGPS.java | 16 +- altosui/AltosGPSSat.java | 32 ++ altosui/AltosLog.java | 8 +- altosui/AltosPreferences.java | 2 +- altosui/AltosRecord.java | 11 + altosui/AltosSerial.java | 21 +- altosui/AltosTelemetry.java | 153 +-------- altosui/AltosTelemetryIterable.java | 4 +- altosui/AltosTelemetryReader.java | 6 +- altosui/AltosTelemetryRecord.java | 23 ++ altosui/AltosTelemetryRecordGeneral.java | 44 +++ altosui/AltosTelemetryRecordLegacy.java | 512 +++++++++++++++++++++++++++++++ altosui/AltosTelemetryRecordRaw.java | 135 ++++++++ altosui/AltosTelemetryRecordSensor.java | 64 ++++ altosui/Makefile.am | 6 + configure.ac | 2 +- 20 files changed, 948 insertions(+), 172 deletions(-) create mode 100644 altosui/AltosGPSSat.java create mode 100644 altosui/AltosTelemetryRecord.java create mode 100644 altosui/AltosTelemetryRecordGeneral.java create mode 100644 altosui/AltosTelemetryRecordLegacy.java create mode 100644 altosui/AltosTelemetryRecordRaw.java create mode 100644 altosui/AltosTelemetryRecordSensor.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 6a2d9b9b..25d97bcf 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -20,6 +20,7 @@ package altosui; import java.awt.*; import java.util.*; import java.text.*; +import java.nio.charset.Charset; import libaltosJNI.*; @@ -69,8 +70,11 @@ public class Altos { /* Telemetry modes */ static final int ao_telemetry_off = 0; - static final int ao_telemetry_full = 1; - static final int ao_telemetry_tiny = 2; + static final int ao_telemetry_legacy = 1; + static final int ao_telemetry_split = 2; + + static final int ao_telemetry_split_len = 32; + static final int ao_telemetry_legacy_len = 95; static HashMap string_to_state = new HashMap(); @@ -201,6 +205,66 @@ public class Altos { return -1; } + static int int8(int[] bytes, int i) { + return (int) (byte) bytes[i]; + } + + static int uint8(int[] bytes, int i) { + return bytes[i]; + } + + static int int16(int[] bytes, int i) { + return (int) (short) (bytes[i] + (bytes[i+1] << 8)); + } + + static int uint16(int[] bytes, int i) { + return bytes[i] + (bytes[i+1] << 8); + } + + static int uint32(int[] bytes, int i) { + return bytes[i] + + (bytes[i+1] << 8) + + (bytes[i+2] << 16) + + (bytes[i+3] << 24); + } + + static final Charset unicode_set = Charset.forName("UTF-8"); + + static String string(int[] bytes, int s, int l) { + byte[] b = new byte[bytes.length]; + for (int i = 0; i < l; i++) + b[i] = (byte) bytes[s+i]; + return new String(b, unicode_set); + } + + static int hexbyte(String s, int i) { + int c0, c1; + + if (s.length() < i + 2) + throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); + c0 = s.charAt(i); + if (!Altos.ishex(c0)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c0)); + c1 = s.charAt(i+1); + if (!Altos.ishex(c1)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c1)); + return Altos.fromhex(c0) * 16 + Altos.fromhex(c1); + } + + static int[] hexbytes(String s) { + int n; + int[] r; + int i; + + if ((s.length() & 1) != 0) + throw new NumberFormatException(String.format("invalid line \"%s\"", s)); + n = s.length() / 2; + r = new int[n]; + for (i = 0; i < n; i++) + r[i] = Altos.hexbyte(s, i * 2); + return r; + } + static int fromdec(String s) throws NumberFormatException { int c, v = 0; int sign = 1; diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index 16349b88..812e5fc6 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -230,6 +230,7 @@ public class AltosEepromIterable extends AltosRecordIterable { case Altos.AO_LOG_SOFTWARE_VERSION: break; } + state.seen |= eeprom.seen; } LinkedList make_list() { diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java index 06360572..2e33b271 100644 --- a/altosui/AltosFile.java +++ b/altosui/AltosFile.java @@ -38,7 +38,7 @@ class AltosFile extends File { extension); } - public AltosFile(AltosTelemetry telem) { + public AltosFile(AltosRecord telem) { this(telem.serial, telem.flight, "telem"); } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index eb6c6d9d..5f1fc678 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -156,9 +156,13 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { // Telemetry format menu telemetries = new JComboBox(); - telemetries.addItem("TeleMetrum"); - telemetries.addItem("TeleMini/TeleNano"); - telemetries.setSelectedIndex(AltosPreferences.telemetry(serial) - 1); + telemetries.addItem("Legacy TeleMetrum"); + telemetries.addItem("Split Telemetry"); + int telemetry = 1; + telemetry = AltosPreferences.telemetry(serial); + if (telemetry > Altos.ao_telemetry_split) + telemetry = Altos.ao_telemetry_split; + telemetries.setSelectedIndex(telemetry - 1); telemetries.setMaximumRowCount(2); telemetries.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java index 0dbc8364..b5df7c9a 100644 --- a/altosui/AltosGPS.java +++ b/altosui/AltosGPS.java @@ -21,10 +21,6 @@ import java.lang.*; import java.text.*; public class AltosGPS { - public class AltosGPSSat { - int svid; - int c_n0; - } final static int MISSING = AltosRecord.MISSING; @@ -158,9 +154,9 @@ public class AltosGPS { else tracking_channels = AltosParse.parse_int(words[i]); i++; - cc_gps_sat = new AltosGPS.AltosGPSSat[tracking_channels]; + cc_gps_sat = new AltosGPSSat[tracking_channels]; for (int chan = 0; chan < tracking_channels; chan++) { - cc_gps_sat[chan] = new AltosGPS.AltosGPSSat(); + cc_gps_sat[chan] = new AltosGPSSat(); cc_gps_sat[chan].svid = AltosParse.parse_int(words[i++]); /* Older versions included SiRF status bits */ if (version < 2) @@ -168,7 +164,7 @@ public class AltosGPS { cc_gps_sat[chan].c_n0 = AltosParse.parse_int(words[i++]); } } else - cc_gps_sat = new AltosGPS.AltosGPSSat[0]; + cc_gps_sat = new AltosGPSSat[0]; } public void set_latitude(int in_lat) { @@ -201,14 +197,14 @@ public class AltosGPS { public void add_sat(int svid, int c_n0) { if (cc_gps_sat == null) { - cc_gps_sat = new AltosGPS.AltosGPSSat[1]; + cc_gps_sat = new AltosGPSSat[1]; } else { - AltosGPSSat[] new_gps_sat = new AltosGPS.AltosGPSSat[cc_gps_sat.length + 1]; + AltosGPSSat[] new_gps_sat = new AltosGPSSat[cc_gps_sat.length + 1]; for (int i = 0; i < cc_gps_sat.length; i++) new_gps_sat[i] = cc_gps_sat[i]; cc_gps_sat = new_gps_sat; } - AltosGPS.AltosGPSSat sat = new AltosGPS.AltosGPSSat(); + AltosGPSSat sat = new AltosGPSSat(); sat.svid = svid; sat.c_n0 = c_n0; cc_gps_sat[cc_gps_sat.length - 1] = sat; diff --git a/altosui/AltosGPSSat.java b/altosui/AltosGPSSat.java new file mode 100644 index 00000000..fb125651 --- /dev/null +++ b/altosui/AltosGPSSat.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosGPSSat { + int svid; + int c_n0; + + public AltosGPSSat(int s, int c) { + svid = s; + c_n0= c; + } + + public AltosGPSSat() { + } +} + diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java index dd147d21..64275f32 100644 --- a/altosui/AltosLog.java +++ b/altosui/AltosLog.java @@ -54,9 +54,10 @@ class AltosLog implements Runnable { } } - boolean open (AltosTelemetry telem) throws IOException { + boolean open (AltosRecord telem) throws IOException { AltosFile a = new AltosFile(telem); + System.out.printf("open %s\n", a.toString()); log_file = new FileWriter(a, true); if (log_file != null) { while (!pending_queue.isEmpty()) { @@ -74,18 +75,21 @@ class AltosLog implements Runnable { public void run () { try { + AltosRecord previous = null; for (;;) { AltosLine line = input_queue.take(); if (line.line == null) continue; try { - AltosTelemetry telem = new AltosTelemetry(line.line); + AltosRecord telem = AltosTelemetry.parse(line.line, previous); if (telem.serial != serial || telem.flight != flight || log_file == null) { close_log_file(); serial = telem.serial; flight = telem.flight; + System.out.printf("Opening telem %d %d\n", serial, flight); open(telem); } + previous = telem; } catch (ParseException pe) { } catch (AltosCRCException ce) { } diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index b1192be1..5029aff6 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -216,7 +216,7 @@ class AltosPreferences { if (telemetries.containsKey(serial)) return telemetries.get(serial); int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - Altos.ao_telemetry_full); + Altos.ao_telemetry_split); telemetries.put(serial, telemetry); return telemetry; } diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 200fffe5..8976edf0 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -25,6 +25,15 @@ import java.io.*; public class AltosRecord { final static int MISSING = 0x7fffffff; + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + int seen; + int version; String callsign; int serial; @@ -226,6 +235,7 @@ public class AltosRecord { public AltosRecord(AltosRecord old) { version = old.version; + seen = old.seen; callsign = old.callsign; serial = old.serial; flight = old.flight; @@ -254,6 +264,7 @@ public class AltosRecord { public AltosRecord() { version = 0; + seen = 0; callsign = "N0CALL"; serial = 0; flight = 0; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 6c80b66f..3666cb41 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -95,7 +95,7 @@ public class AltosSerial implements Runnable { } if (debug) System.out.printf("\t\t\t\t\t%s\n", line); - if (line.startsWith("VERSION") || line.startsWith("CRC")) { + if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { for (int e = 0; e < monitors.size(); e++) { LinkedBlockingQueue q = monitors.get(e); q.put(new AltosLine (line)); @@ -325,11 +325,22 @@ public class AltosSerial implements Runnable { set_callsign(AltosPreferences.callsign()); } + private int telemetry_len() { + switch (telemetry) { + case 1: + default: + return Altos.ao_telemetry_legacy_len; + case 2: + return Altos.ao_telemetry_split_len; + } + } + public void set_channel(int in_channel) { channel = in_channel; if (altos != null) { if (monitor_mode) - printf("m 0\nc r %d\nm %d\n", channel, telemetry); + printf("m 0\nc r %d\nm %x\n", + channel, telemetry_len()); else printf("c r %d\n", channel); flush_output(); @@ -340,7 +351,7 @@ public class AltosSerial implements Runnable { telemetry = in_telemetry; if (altos != null) { if (monitor_mode) - printf("m 0\nm %d\n", telemetry); + printf("m 0\nm %x\n", telemetry_len()); flush_output(); } } @@ -349,7 +360,7 @@ public class AltosSerial implements Runnable { monitor_mode = monitor; if (altos != null) { if (monitor) - printf("m %d\n", telemetry); + printf("m %x\n", telemetry_len()); else printf("m 0\n"); flush_output(); @@ -393,7 +404,7 @@ public class AltosSerial implements Runnable { line = ""; monitor_mode = false; frame = null; - telemetry = Altos.ao_telemetry_full; + telemetry = Altos.ao_telemetry_split; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); open(); diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index 7d68b5b5..a05269f4 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -27,6 +27,10 @@ import java.util.HashMap; /* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * * Version 4 is a replacement with consistent syntax. Each telemetry line * contains a sequence of space-separated names and values, the values are * either integers or strings. The names are all unique. All values are @@ -81,6 +85,7 @@ import java.util.HashMap; */ public class AltosTelemetry extends AltosRecord { + /* * General header fields * @@ -228,151 +233,9 @@ public class AltosTelemetry extends AltosRecord { final static String AO_TELEM_SAT_SVID = "s_v"; final static String AO_TELEM_SAT_C_N_0 = "s_c"; - private void parse_v4(String[] words, int i) throws ParseException { - AltosTelemetryMap map = new AltosTelemetryMap(words, i); - - callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); - serial = map.get_int(AO_TELEM_SERIAL, MISSING); - flight = map.get_int(AO_TELEM_FLIGHT, MISSING); - rssi = map.get_int(AO_TELEM_RSSI, MISSING); - state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); - tick = map.get_int(AO_TELEM_TICK, 0); - - /* raw sensor values */ - accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING); - pres = map.get_int(AO_TELEM_RAW_BARO, MISSING); - temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING); - batt = map.get_int(AO_TELEM_RAW_BATT, MISSING); - drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING); - main = map.get_int(AO_TELEM_RAW_MAIN, MISSING); - - /* sensor calibration information */ - ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING); - ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING); - accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING); - accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); - - /* flight computer values */ - acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, MISSING, 1/16.0); - speed = map.get_double(AO_TELEM_KALMAN_SPEED, MISSING, 1/16.0); - height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); - - flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); - flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); - flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); - - if (map.has(AO_TELEM_GPS_STATE)) - gps = new AltosGPS(map); - else - gps = null; - } - - private void parse_legacy(String[] words, int i) throws ParseException { - - AltosParse.word (words[i++], "CALL"); - callsign = words[i++]; - - AltosParse.word (words[i++], "SERIAL"); - serial = 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++], "STATE"); - state = Altos.state(words[i++]); - - tick = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a:"); - accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "p:"); - pres = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "t:"); - temp = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "v:"); - batt = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "d:"); - drogue = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "m:"); - main = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fa:"); - flight_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "ga:"); - ground_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fv:"); - flight_vel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fp:"); - flight_pres = AltosParse.parse_int(words[i++]); - - /* Old TeleDongle code with kalman-reporting TeleMetrum code */ - if ((flight_vel & 0xffff0000) == 0x80000000) { - speed = ((short) flight_vel) / 16.0; - acceleration = flight_accel / 16.0; - height = flight_pres; - flight_vel = MISSING; - flight_pres = MISSING; - flight_accel = MISSING; - } - - AltosParse.word(words[i++], "gp:"); - ground_pres = 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++]); - } else { - accel_plus_g = ground_accel; - accel_minus_g = ground_accel + 530; - } - - gps = new AltosGPS(words, i, version); - } - - public AltosTelemetry(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; - - 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++]); - } + static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { + AltosTelemetryRecord r = AltosTelemetryRecordGeneral.parse(line); - if (version < 4) - parse_legacy(words, i); - else - parse_v4(words, i); + return r.update_state(previous); } } diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index 44e5ad8f..90a08485 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -40,6 +40,7 @@ public class AltosTelemetryIterable extends AltosRecordIterable { int current_tick = 0; int boost_tick = 0; + AltosRecord previous = null; records = new LinkedList (); try { @@ -49,9 +50,10 @@ public class AltosTelemetryIterable extends AltosRecordIterable { break; } try { - AltosTelemetry record = new AltosTelemetry(line); + AltosRecord record = AltosTelemetry.parse(line, previous); if (record == null) break; + previous = record; if (records.isEmpty()) { current_tick = record.tick; } else { diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 980391b4..18f17841 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -26,6 +26,7 @@ class AltosTelemetryReader extends AltosFlightReader { AltosDevice device; AltosSerial serial; AltosLog log; + AltosRecord previous; LinkedBlockingQueue telem; @@ -33,7 +34,9 @@ class AltosTelemetryReader extends AltosFlightReader { AltosLine l = telem.take(); if (l.line == null) throw new IOException("IO error"); - return new AltosTelemetry(l.line); + AltosRecord next = AltosTelemetry.parse(l.line, previous); + previous = next; + return next; } void close(boolean interrupted) { @@ -58,6 +61,7 @@ class AltosTelemetryReader extends AltosFlightReader { serial = new AltosSerial(device); log = new AltosLog(serial); name = device.toShortString(); + previous = null; telem = new LinkedBlockingQueue(); serial.set_radio(); diff --git a/altosui/AltosTelemetryRecord.java b/altosui/AltosTelemetryRecord.java new file mode 100644 index 00000000..cfac309a --- /dev/null +++ b/altosui/AltosTelemetryRecord.java @@ -0,0 +1,23 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 interface AltosTelemetryRecord { + + public AltosRecord update_state(AltosRecord previous); +} diff --git a/altosui/AltosTelemetryRecordGeneral.java b/altosui/AltosTelemetryRecordGeneral.java new file mode 100644 index 00000000..55f6c495 --- /dev/null +++ b/altosui/AltosTelemetryRecordGeneral.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordGeneral { + + static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + System.out.printf("First word \"%s\"\n", word[i]); + if (word[i].equals("TELEM")) + r = AltosTelemetryRecordRaw.parse(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } +} diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java new file mode 100644 index 00000000..e3751ee7 --- /dev/null +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -0,0 +1,512 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * + */ + +public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTelemetryRecord { + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + private void parse_v4(String[] words, int i) throws ParseException { + AltosTelemetryMap map = new AltosTelemetryMap(words, i); + + callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + serial = map.get_int(AO_TELEM_SERIAL, MISSING); + flight = map.get_int(AO_TELEM_FLIGHT, MISSING); + rssi = map.get_int(AO_TELEM_RSSI, MISSING); + state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + tick = map.get_int(AO_TELEM_TICK, 0); + + /* raw sensor values */ + accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING); + pres = map.get_int(AO_TELEM_RAW_BARO, MISSING); + temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING); + batt = map.get_int(AO_TELEM_RAW_BATT, MISSING); + drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING); + main = map.get_int(AO_TELEM_RAW_MAIN, MISSING); + + /* sensor calibration information */ + ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING); + ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING); + accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING); + accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); + + /* flight computer values */ + acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, MISSING, 1/16.0); + speed = map.get_double(AO_TELEM_KALMAN_SPEED, MISSING, 1/16.0); + height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); + + flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); + flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); + flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); + + if (map.has(AO_TELEM_GPS_STATE)) + gps = new AltosGPS(map); + else + gps = null; + } + + private void parse_legacy(String[] words, int i) throws ParseException { + + AltosParse.word (words[i++], "CALL"); + callsign = words[i++]; + + AltosParse.word (words[i++], "SERIAL"); + serial = 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++], "STATE"); + state = Altos.state(words[i++]); + + tick = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a:"); + accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "p:"); + pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "t:"); + temp = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "v:"); + batt = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "d:"); + drogue = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "m:"); + main = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fa:"); + flight_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "ga:"); + ground_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fv:"); + flight_vel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fp:"); + flight_pres = AltosParse.parse_int(words[i++]); + + /* Old TeleDongle code with kalman-reporting TeleMetrum code */ + if ((flight_vel & 0xffff0000) == 0x80000000) { + speed = ((short) flight_vel) / 16.0; + acceleration = flight_accel / 16.0; + height = flight_pres; + flight_vel = MISSING; + flight_pres = MISSING; + flight_accel = MISSING; + } + + AltosParse.word(words[i++], "gp:"); + ground_pres = 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++]); + } else { + accel_plus_g = ground_accel; + accel_minus_g = ground_accel + 530; + } + + gps = new AltosGPS(words, i, version); + } + + public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + 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++]); + } + + if (version < 4) + parse_legacy(words, i); + else + parse_v4(words, i); + } + + /* + * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that + */ + + int[] bytes; + + private int int8(int i) { + return Altos.int8(bytes, i + 1); + } + private int uint8(int i) { + return Altos.uint8(bytes, i + 1); + } + private int int16(int i) { + return Altos.int16(bytes, i + 1); + } + private int uint16(int i) { + return Altos.uint16(bytes, i + 1); + } + private int uint32(int i) { + return Altos.uint32(bytes, i + 1); + } + private String string(int i, int l) { + return Altos.string(bytes, i + 1, l); + } + + static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); + static final int AO_GPS_NUM_SAT_SHIFT = (0); + + static final int AO_GPS_VALID = (1 << 4); + static final int AO_GPS_RUNNING = (1 << 5); + static final int AO_GPS_DATE_VALID = (1 << 6); + static final int AO_GPS_COURSE_VALID = (1 << 7); + + static class theLock extends Object { + } + static public theLock lockObject = new theLock(); + public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { + bytes = in_bytes; + synchronized(lockObject) { + for (int i = 0; i < in_bytes.length - 2; i++) { + if ((i % 10) == 0) + System.out.printf("%3d:", i); + System.out.printf(" %02x", uint8(i)); + if ((i % 10) == 9 || i == in_bytes.length - 3) + System.out.printf("\n"); + } + } + version = 4; + callsign = string(62, 8); + serial = uint16(0); + flight = uint16(2); + rssi = in_rssi; + status = in_status; + state = uint8(4); + tick = uint16(21); + accel = int16(23); + pres = int16(25); + temp = int16(27); + batt = int16(29); + drogue = int16(31); + main = int16(33); + + ground_accel = int16(7); + ground_pres = int16(15); + accel_plus_g = int16(17); + accel_minus_g = int16(19); + + if (uint16(11) == 0x8000) { + acceleration = int16(5); + speed = int16(9); + height = int16(13); + flight_accel = MISSING; + flight_vel = MISSING; + flight_pres = MISSING; + } else { + flight_accel = int16(5); + flight_vel = uint32(9); + flight_pres = int16(13); + acceleration = MISSING; + speed = MISSING; + height = MISSING; + } + + gps = null; + + int gps_flags = uint8(41); + + if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { + gps = new AltosGPS(); + + gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); + gps.locked = (gps_flags & AO_GPS_VALID) != 0; + gps.connected = true; + gps.lat = uint32(42) / 1.0e7; + gps.lon = uint32(46) / 1.0e7; + gps.alt = int16(50); + gps.ground_speed = uint16(52) / 100.0; + gps.course = uint8(54) * 2; + gps.hdop = uint8(55) / 5.0; + gps.h_error = uint16(58); + gps.v_error = uint16(60); + + int n_tracking_reported = uint8(70); + if (n_tracking_reported > 12) + n_tracking_reported = 12; + int n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + if (uint8(71 + i*2) != 0) + n_tracking_actual++; + } + if (n_tracking_actual > 0) { + gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; + + n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + int svid = uint8(71 + i*2); + int c_n0 = uint8(72 + i*2); + if (svid != 0) + gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); + } + } + } + + time = 0.0; + } + + public AltosRecord update_state(AltosRecord previous) { + return this; + } +} diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java new file mode 100644 index 00000000..35796a22 --- /dev/null +++ b/altosui/AltosTelemetryRecordRaw.java @@ -0,0 +1,135 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { + int[] bytes; + int serial; + int tick; + int type; + + final static int packet_type_TM_sensor = 0x01; + final static int packet_type_Tm_sensor = 0x02; + final static int packet_type_Tn_sensor = 0x03; + final static int packet_type_config = 0x04; + final static int packet_type_GPS_location = 0x05; + final static int packet_type_GPS_satellites = 0x06; + + final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); + final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); + final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; + + static boolean cksum(int[] bytes) { + int sum = 0x5a; + for (int i = 1; i < bytes.length - 1; i++) + sum += bytes[i]; + sum &= 0xff; + System.out.printf("%d bytes sum 0x%x last byte 0x%x\n", + bytes.length, sum, bytes[bytes.length - 1]); + return sum == bytes[bytes.length - 1]; + } + + public static AltosTelemetryRecord parse (String hex) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + int[] bytes; + try { + bytes = Altos.hexbytes(hex); + } catch (NumberFormatException ne) { + throw new ParseException(ne.getMessage(), 0); + } + + /* one for length, one for checksum */ + if (bytes[0] != bytes.length - 2) + throw new ParseException(String.format("invalid length %d != %d\n", + bytes[0], + bytes.length - 2), 0); + if (!cksum(bytes)) + throw new ParseException(String.format("invalid line \"%s\"", hex), 0); + + int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; + int status = Altos.uint8(bytes, bytes.length - 2); + + System.out.printf ("rssi 0x%x = %d status 0x%x\n", + Altos.uint8(bytes, bytes.length - 3), + rssi, status); + + if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) + throw new AltosCRCException(rssi); + + /* length, data ..., rssi, status, checksum -- 4 bytes extra */ + switch (bytes.length) { + case Altos.ao_telemetry_split_len + 4: + int type = Altos.uint8(bytes, 4 + 1); + switch (type) { + case packet_type_TM_sensor: + case packet_type_Tm_sensor: + case packet_type_Tn_sensor: + r = new AltosTelemetryRecordSensor(bytes); + break; + default: + r = new AltosTelemetryRecordRaw(bytes); + break; + } + case Altos.ao_telemetry_legacy_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + default: + throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); + } + return r; + } + + public int int8(int off) { + return Altos.int8(bytes, off + 1); + } + + public int uint8(int off) { + return Altos.uint8(bytes, off + 1); + } + + public int int16(int off) { + return Altos.int16(bytes, off + 1); + } + + public int uint16(int off) { + return Altos.uint16(bytes, off + 1); + } + + public int uint32(int off) { + return Altos.uint32(bytes, off + 1); + } + + public AltosTelemetryRecordRaw(int[] in_bytes) { + bytes = in_bytes; + serial = uint16(0); + tick = uint16(2); + type = uint8(4); + } + + public AltosRecord update_state(AltosRecord previous) { + if (previous != null) + return new AltosRecord(previous); + else + return new AltosRecord(); + } +} diff --git a/altosui/AltosTelemetryRecordSensor.java b/altosui/AltosTelemetryRecordSensor.java new file mode 100644 index 00000000..5ae9f891 --- /dev/null +++ b/altosui/AltosTelemetryRecordSensor.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { + int state; + int accel; + int pres; + int temp; + int v_batt; + int sense_d; + int sense_m; + + int acceleration; + int speed; + int height; + + int ground_accel; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + + public AltosTelemetryRecordSensor(int[] in_bytes) { + super(in_bytes); + state = uint8(5); + + accel = int16(6); + pres = int16(8); + temp = int16(10); + v_batt = int16(12); + sense_d = int16(14); + sense_m = int16(16); + + acceleration = int16(18); + speed = int16(20); + height = int16(22); + + ground_accel = int16(24); + ground_pres = int16(26); + accel_plus_g = int16(28); + accel_minus_g = int16(30); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + return next; + } +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f4d84ad2..6a4d9d17 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -51,6 +51,7 @@ altosui_JAVA = \ AltosFlightStatus.java \ AltosFlightUI.java \ AltosGPS.java \ + AltosGPSSat.java \ AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ @@ -70,6 +71,11 @@ altosui_JAVA = \ AltosRecord.java \ AltosRecordIterable.java \ AltosTelemetryReader.java \ + AltosTelemetryRecord.java \ + AltosTelemetryRecordGeneral.java \ + AltosTelemetryRecordRaw.java \ + AltosTelemetryRecordSensor.java \ + AltosTelemetryRecordLegacy.java \ AltosTelemetryMap.java \ AltosReplayReader.java \ AltosRomconfig.java \ diff --git a/configure.ac b/configure.ac index 32ef7d74..07d30717 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4) +AC_INIT([altos], 0.9.4.99) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 06e82bd2c2a5eea153a053e542df9bc3537e9a01 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jul 2011 01:50:33 -0700 Subject: doc: Add telemetry format description Document the telemetry packet contents. Signed-off-by: Keith Packard --- doc/Makefile | 10 +- doc/telemetry.xsl | 572 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 578 insertions(+), 4 deletions(-) create mode 100644 doc/telemetry.xsl diff --git a/doc/Makefile b/doc/Makefile index 80c84409..b431f4ca 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,8 +2,8 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -HTML=altusmetrum.html altos.html -PDF=altusmetrum.pdf altos.pdf +HTML=altusmetrum.html altos.html telemetry.html +PDF=altusmetrum.pdf altos.pdf telemetry.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl @@ -11,11 +11,13 @@ PDFSTYLE= .SUFFIXES: .xsl .html .fo .pdf +XSLTFLAGS=--stringparam section.autolabel 1 + .xsl.html: - xsltproc -o $@ $(HTMLSTYLE) $*.xsl + xsltproc $(XSLTFLAGS) -o $@ $(HTMLSTYLE) $*.xsl .xsl.fo: - xsltproc -o $@ $(FOSTYLE) $*.xsl + xsltproc $(XSLTFLAGS) -o $@ $(FOSTYLE) $*.xsl .fo.pdf: fop -fo $*.fo -pdf $@ diff --git a/doc/telemetry.xsl b/doc/telemetry.xsl new file mode 100644 index 00000000..8f0c3ff0 --- /dev/null +++ b/doc/telemetry.xsl @@ -0,0 +1,572 @@ + + + +
+ + AltOS Telemetry + Packet Definitions + + Keith + Packard + + + 2011 + Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.1 + 01 July 2011 + Initial content + + + +
+ History and Motivation + + The original AltoOS telemetry mechanism encoded everything + available piece of information on the TeleMetrum hardware into a + single unified packet. Initially, the packets contained very + little data—some raw sensor readings along with the current GPS + coordinates when a GPS receiver was connected. Over time, the + amount of data grew to include sensor calibration data, GPS + satellite information and a host of internal state information + designed to help diagnose flight failures in case of a loss of + the on-board flight data. + + + Because every packet contained all of the data, packets were + huge—95 bytes long. Much of the information was also specific to + the TeleMetrum hardware. With the introduction of the TeleMini + flight computer, most of the data contained in the telemetry + packets was unavailable. Initially, a shorter, but still + comprehensive packet was implemented. This required that the + ground station be pre-configured as to which kind of packet to + expect. + + + The development of several companion boards also made the + shortcomings evident—each companion board would want to include + telemetry data in the radio link; with the original design, the + packet would have to hold the new data as well, requiring + additional TeleMetrum and ground station changes. + +
+
+ Packet Format Design + + AltOS telemetry data is split into multiple different packets, + all the same size, but each includs an identifier so that the + ground station can distinguish among different types. A single + flight board will transmit multiple packet types, each type on a + different schedule. The ground software need look for only a + single packet size, and then decode the information within the + packet and merge data from multiple packets to construct the + full flight computer state. + + + Each AltOS packet is 32 bytes long. This size was chosen based + on the known telemetry data requirements. The power of two size + allows them to be stored easily in flash memory without having + them split across blocks or leaving gaps at the end. + + + All packet types start with a five byte header which encodes the + device serial number, device clock value and the packet + type. The remaining 27 bytes encode type-specific data. + +
+
+ Packet Formats + This section first defines the packet header common to all packets + and then the per-packet data layout. +
+ Packet Header + + Telemetry Packet Header + + + + + + + + Offset + Data Type + Name + Description + + + + + 0 + uint16_t + serial + Device serial Number + + + 2 + uint16_t + tick + Device time in 100ths of a second + + + 4 + uint8_t + type + Packet type + + + 5 + + + +
+ + Each packet starts with these five bytes which serve to identify + which device has transmitted the packet, when it was transmitted + and what the rest of the packet contains. + +
+
+ Sensor Data + + + + + + + Type + Description + + + + + 0x01 + TeleMetrum Sensor Data + + + 0x02 + TeleMini Sensor Data + + + 0x03 + TeleNano Sensor Data + + + + + + TeleMetrum, TeleMini and TeleNano share this same packet + format for sensor data. Each uses a distinct packet type so + that the receiver knows which data values are valid and which + are undefined. + + + Sensor Packet Contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 5uint8_tstateFlight state + + + 6int16_taccelaccelerometer (TM only) + + + 8int16_tprespressure sensor + + + 10int16_ttemptemperature sensor + + + 12int16_tv_battbattery voltage + + + 14int16_tsense_ddrogue continuity sense (TM/Tm) + + + 16int16_tsense_mmain continuity sense (TM/Tm) + + + 18int16_taccelm/s² * 16 + + + 20int16_tspeedm/s * 16 + + + 22int16_theightm + + + 24int16_tground_accelTM + + + 26int16_tground_presAverage barometer reading on ground + + + 28int16_taccel_plus_gTM + + + 30int16_taccel_minus_gTM + + + 32 + + + +
+
+
+ Configuration Data + + + + + + + Type + Description + + + + + 0x04 + Configuration Data + + + + + + Sensor Packet Contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 5uint8_ttypeDevice type + + + 6uint16_tflightFlight number + + + 8uint8_tconfig_majorConfig major version + + + 9uint8_tconfig_minorConfig minor version + + + 10uint16_tmain_deployMain deploy alt in meters + + + 12uint32_tflight_log_maxMaximum flight log size (B) + + + 16charcallsign[8]Radio operator identifier + + + 24charversion[8]Software version identifier + + + 32 + + + +
+
+
+ GPS Location + + + + + + + Type + Description + + + + + 0x05 + GPS Location + + + + + + GPS Location Packet Contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 5uint8_tflagsGPS Flags (see below) + + + 6int16_taltitudem + + + 8int32_tlatitudedegrees * 107 + + + 12int32_tlongitudedegrees * 107 + + + 16uint8_tyear + + + 17uint8_tmonth + + + 18uint8_tday + + + 19uint8_thour + + + 20uint8_tminute + + + 21uint8_tsecond + + + 22uint8_tpdop* 5 + + + 23uint8_thdop* 5 + + + 24uint8_tvdop* 5 + + + 25uint8_tmodeN, A, D, E, M, S + + + 26uint16_tground_speedcm/s + + + 28uint8_tcourse/ 2 + + + 29uint8_tunused[2] + + + 32 + + + +
+
+
+ GPS Satellite Data + + + + + + + Type + Description + + + + + 0x06 + GPS Satellite Data + + + + + + GPS Satellite Data Contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 5uint8_tchannels + + + 6uint8_tsat_0_id + + + 7uint8_tsat_0_c_n_1 + + + 8uint8_tsat_1_id + + + 9uint8_tsat_1_c_n_1 + + + 10uint8_tsat_2_id + + + 11uint8_tsat_2_c_n_1 + + + 12uint8_tsat_3_id + + + 13uint8_tsat_3_c_n_1 + + + 14uint8_tsat_4_id + + + 15uint8_tsat_4_c_n_1 + + + 16uint8_tsat_5_id + + + 17uint8_tsat_5_c_n_1 + + + 18uint8_tsat_6_id + + + 19uint8_tsat_6_c_n_1 + + + 20uint8_tsat_7_id + + + 21uint8_tsat_7_c_n_1 + + + 22uint8_tsat_8_id + + + 23uint8_tsat_8_c_n_1 + + + 24uint8_tsat_9_id + + + 25uint8_tsat_9_c_n_1 + + + 26uint8_tsat_10_id + + + 27uint8_tsat_10_c_n_1 + + + 28uint8_tsat_11_id + + + 29uint8_tsat_11_c_n_1 + + + 30uin8_tunused30 + + + 31uin8_tunused31 + + + 32 + + + +
+
+
+
+ + \ No newline at end of file -- cgit v1.2.3 From 98df3ba984acf3b47a09949bbea0f3264f711f5b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 14:17:55 -0700 Subject: doc: Complete initial telemetry description Finish describing the contents and modulation scheme for telemetry data. Signed-off-by: Keith Packard --- doc/telemetry.xsl | 420 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 289 insertions(+), 131 deletions(-) diff --git a/doc/telemetry.xsl b/doc/telemetry.xsl index 8f0c3ff0..d2b17126 100644 --- a/doc/telemetry.xsl +++ b/doc/telemetry.xsl @@ -31,37 +31,6 @@
-
- History and Motivation - - The original AltoOS telemetry mechanism encoded everything - available piece of information on the TeleMetrum hardware into a - single unified packet. Initially, the packets contained very - little data—some raw sensor readings along with the current GPS - coordinates when a GPS receiver was connected. Over time, the - amount of data grew to include sensor calibration data, GPS - satellite information and a host of internal state information - designed to help diagnose flight failures in case of a loss of - the on-board flight data. - - - Because every packet contained all of the data, packets were - huge—95 bytes long. Much of the information was also specific to - the TeleMetrum hardware. With the introduction of the TeleMini - flight computer, most of the data contained in the telemetry - packets was unavailable. Initially, a shorter, but still - comprehensive packet was implemented. This required that the - ground station be pre-configured as to which kind of packet to - expect. - - - The development of several companion boards also made the - shortcomings evident—each companion board would want to include - telemetry data in the radio link; with the original design, the - packet would have to hold the new data as well, requiring - additional TeleMetrum and ground station changes. - -
Packet Format Design @@ -95,7 +64,7 @@ Telemetry Packet Header - + @@ -172,10 +141,15 @@ that the receiver knows which data values are valid and which are undefined. + + Sensor Data packets are transmitted once per second on the + ground, 10 times per second during ascent and once per second + during descent and landing +
Sensor Packet Contents - + @@ -257,10 +231,18 @@ + + This provides a description of the software installed on the + flight computer as well as any user-specified configuration data. + + + Configuration data packets are transmitted once per second + during all phases of the flight +
Sensor Packet Contents - + @@ -324,10 +306,19 @@ + + This packet provides all of the information available from the + Venus SkyTraq GPS receiver—position, time, speed and precision + estimates. + + + GPS Location packets are transmitted once per second during + all phases of the flight +
GPS Location Packet Contents - + @@ -341,7 +332,8 @@ - 5uint8_tflagsGPS Flags (see below) + 5uint8_tflags + See GPS Flags table below 6int16_taltitudem @@ -380,7 +372,8 @@ 24uint8_tvdop* 5 - 25uint8_tmodeN, A, D, E, M, S + 25uint8_tmode + See GPS Mode table below 26uint16_tground_speedcm/s @@ -389,7 +382,7 @@ 28uint8_tcourse/ 2 - 29uint8_tunused[2] + 29uint8_tunused[3] 32 @@ -397,6 +390,116 @@
+ + Packed into a one byte field are status flags and the count of + satellites used to compute the position fix. Note that this + number may be lower than the number of satellites being + tracked; the receiver will not use information from satellites + with weak signals or which are close enough to the horizon to + have significantly degraded position accuracy. + + + GPS Flags + + + + + + + Bits + Name + Description + + + + + 0-3 + nsats + Number of satellites in solution + + + 4 + valid + GPS solution is valid + + + 5 + running + GPS receiver is operational + + + 6 + date_valid + Reported date is valid + + + 7 + course_valid + ground speed, course and climb rates are valid + + + +
+ + Here are all of the valid GPS operational modes. Altus Metrum + products will only ever report 'N' (not valid), 'A' + (Autonomous) modes or 'E' (Estimated). The remaining modes + are either testing modes or require additional data. + + + GPS Mode + + + + + + + Mode + Name + Decsription + + + + + N + Not Valid + All data are invalid + + + A + Autonomous mode + Data are derived from satellite data + + + D + Differential Mode + + Data are augmented with differential data from a + known ground station. The SkyTraq unit in TeleMetrum + does not support this mode + + + + E + Estimated + + Data are estimated using dead reckoning from the + last known data + + + + M + Manual + Data were entered manually + + + S + Simulated + GPS receiver testing mode + + + +
GPS Satellite Data @@ -418,6 +521,15 @@ + + This packet provides space vehicle identifiers and signal + quality information in the form of a C/N1 number for up to 12 + satellites. The order of the svids is not specified. + + + GPS Satellite data are transmitted once per second during all + phases of the flight. + GPS Satellite Data Contents @@ -436,137 +548,183 @@ 5uint8_tchannels + Number of reported satellite information - 6uint8_tsat_0_id + 6sat_info_tsats[12] + See Per-Satellite data table below - 7uint8_tsat_0_c_n_1 + 30uint8_tunused[2] - 8uint8_tsat_1_id - - - 9uint8_tsat_1_c_n_1 - - - 10uint8_tsat_2_id - - - 11uint8_tsat_2_c_n_1 - - - 12uint8_tsat_3_id - - - 13uint8_tsat_3_c_n_1 - - - 14uint8_tsat_4_id - - - 15uint8_tsat_4_c_n_1 - - - 16uint8_tsat_5_id - - - 17uint8_tsat_5_c_n_1 - - - 18uint8_tsat_6_id + 32 + + +
+ + GPS Per-Satellite data (sat_info_t) + + + + + + - 19uint8_tsat_6_c_n_1 + Offset + Data Type + Name + Description + + - 20uint8_tsat_7_id + 0uint8_tsvid + Space Vehicle Identifier - 21uint8_tsat_7_c_n_1 + 1uint8_tc_n_1 + C/N1 signal quality indicator - 22uint8_tsat_8_id + 2 + + +
+
+
+
+ Data Transmission + + Altus Metrum devices use the Texas Instruments CC1111 + microcontroller which includes an integrated sub-GHz digital + transceiver. This transceiver is used to both transmit and + receive the telemetry packets. This section discusses what + modulation scheme is used and how this device is configured. + +
+ Modulation Scheme + + Texas Instruments provides a tool for computing modulation + parameters given a desired modulation format and basic bit + rate. For AltOS, the basic bit rate was specified as 38 kBaud, + resulting in the following signal parmeters: + + + + + + + - 23uint8_tsat_8_c_n_1 + Parameter + Value + Description + + - 24uint8_tsat_9_id + Modulation + GFSK + Gaussian Frequency Shift Keying - 25uint8_tsat_9_c_n_1 + Deviation + 20.507812 kHz + Frequency modulation - 26uint8_tsat_10_id + Data rate + 38.360596 kBaud + Raw bit rate - 27uint8_tsat_10_c_n_1 + RX Filter Bandwidth + 93.75 kHz + Receiver Band pass filter bandwidth - 28uint8_tsat_11_id + IF Frequency + 140.62 kHz + Receiver intermediate frequency + + +
+
+
+ + The cc1111 provides forward error correction in hardware, + which AltOS uses to improve reception of weak signals. The + overall effect of this is to halve the available bandwidth for + data from 38 kBaud to 19 kBaud. + + Error Correction + + + + + + - 29uint8_tsat_11_c_n_1 + Parameter + Value + Description + + - 30uin8_tunused30 + Error Correction + Convolutional coding FEC + 1/2 code, constraint length m=4 - 31uin8_tunused31 + Interleaving + 4 x 4 + Reduce effect of noise burst - 32 + Data Whitening + XOR with 9-bit PNR + Rotate right with bit 8 = bit 0 xor bit 5, initial + value 111111111
+
+ History and Motivation + + The original AltoOS telemetry mechanism encoded everything + available piece of information on the TeleMetrum hardware into a + single unified packet. Initially, the packets contained very + little data—some raw sensor readings along with the current GPS + coordinates when a GPS receiver was connected. Over time, the + amount of data grew to include sensor calibration data, GPS + satellite information and a host of internal state information + designed to help diagnose flight failures in case of a loss of + the on-board flight data. + + + Because every packet contained all of the data, packets were + huge—95 bytes long. Much of the information was also specific to + the TeleMetrum hardware. With the introduction of the TeleMini + flight computer, most of the data contained in the telemetry + packets was unavailable. Initially, a shorter, but still + comprehensive packet was implemented. This required that the + ground station be pre-configured as to which kind of packet to + expect. + + + The development of several companion boards also made the + shortcomings evident—each companion board would want to include + telemetry data in the radio link; with the original design, the + packet would have to hold the new data as well, requiring + additional TeleMetrum and ground station changes. + +
- - \ No newline at end of file -- cgit v1.2.3 From a08173197d5533ecb395102ed34e751135660d06 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:01:59 -0700 Subject: doc: Fix a few minor telemetry doc mistakes Multiple 'accel' entries in the Sensor packet. Swap ground_accel and ground_pres to group accel cal data Signed-off-by: Keith Packard --- doc/telemetry.xsl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/telemetry.xsl b/doc/telemetry.xsl index d2b17126..a0b9f6e7 100644 --- a/doc/telemetry.xsl +++ b/doc/telemetry.xsl @@ -184,7 +184,7 @@ 16int16_tsense_mmain continuity sense (TM/Tm) - 18int16_taccelm/s² * 16 + 18int16_taccelerationm/s² * 16 20int16_tspeedm/s * 16 @@ -193,10 +193,10 @@ 22int16_theightm - 24int16_tground_accelTM + 24int16_tground_presAverage barometer reading on ground - 26int16_tground_presAverage barometer reading on ground + 26int16_tground_accelTM 28int16_taccel_plus_gTM -- cgit v1.2.3 From c763a3f9cf2bf055e9705ce5ff4bc172f445037d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:02:52 -0700 Subject: Version strings must be < 8 bytes long The new telemetry packets include the version string, so make sure its less than 8 characters long Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 07d30717..187af4fb 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.99) +AC_INIT([altos], 0.9.4.1) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From d3c26e534d8df34cfbf29b70cd1b2692493ce150 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:03:51 -0700 Subject: altos: teledongle does not need ao_packet_slave.c TeleDongle doesn't provide slave interfaces, so remove ao_packet_slave from the TD build Signed-off-by: Keith Packard --- src/Makefile.proto | 10 ++++++---- src/ao_radio.c | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index bc7b3a7f..5322df17 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -62,9 +62,7 @@ USB_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_packet.c \ - ao_packet_slave.c \ - ao_state.c + ao_packet.c # # Receiver code @@ -73,6 +71,7 @@ TELE_RECEIVER_SRC =\ ao_monitor.c \ ao_gps_print.c \ ao_packet_master.c \ + ao_state.c \ ao_rssi.c # @@ -107,6 +106,7 @@ TM_DRIVER_SRC = \ ao_adc.c \ ao_gps_report.c \ ao_ignite.c \ + ao_packet_slave.c \ $(BEEP_DRIVER_SRC) \ $(USB_DRIVER_SRC) @@ -160,7 +160,7 @@ TM_TASK_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry_orig.c + ao_telemetry.c TM_MAIN_SRC = \ ao_telemetrum.c @@ -185,6 +185,7 @@ TMINI_DRIVER_SRC = \ ao_ignite.c \ ao_config.c \ ao_storage.c \ + ao_packet_slave.c \ ao_intflash.c TMINI_TASK_SRC = \ @@ -214,6 +215,7 @@ TNANO_DRIVER_SRC = \ ao_adc.c \ ao_config.c \ ao_storage.c \ + ao_packet_slave.c \ ao_intflash.c TNANO_TASK_SRC = \ diff --git a/src/ao_radio.c b/src/ao_radio.c index 01974ba1..4c382bb9 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -433,7 +433,9 @@ ao_radio_test(void) mode++; if ((mode & 2) && !radio_on) { ao_set_monitor(0); +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_radio_get(0xff); RFST = RFST_STX; radio_on = 1; -- cgit v1.2.3 From 06b6f78e22be38a26bfe11ed4d4b659d5b13f00c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:04:49 -0700 Subject: altos: Shrink const space in ao_config Eliminate separate 'cmd' and 'help' struct entries. Use \0 trick in cmd strings to eliminate whitespace. Edit help text. Signed-off-by: Keith Packard --- src/ao_config.c | 66 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index 319febb9..c7fc7dd2 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -208,7 +208,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant int32_t accel_total; uint8_t cal_adc_ring; - printf("Orient %s and press a key...", orientation); + printf("Orient antenna %s and press a key...", orientation); flush(); (void) getchar(); puts("\r\n"); flush(); @@ -235,8 +235,8 @@ ao_config_accel_calibrate_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; if (ao_cmd_lex_i == 0) { - up = ao_config_accel_calibrate_auto("antenna up"); - down = ao_config_accel_calibrate_auto("antenna down"); + up = ao_config_accel_calibrate_auto("up"); + down = ao_config_accel_calibrate_auto("down"); } else { up = ao_cmd_lex_i; ao_cmd_decimal(); @@ -245,7 +245,7 @@ ao_config_accel_calibrate_set(void) __reentrant down = ao_cmd_lex_i; } if (up >= down) { - printf("Invalid accel calibration: antenna up (%d) should be less than antenna down (%d)\n", + printf("Invalid accel: up (%d) down (%d)\n", up, down); return; } @@ -336,10 +336,9 @@ ao_config_log_set(void) __reentrant #endif /* HAS_EEPROM */ struct ao_config_var { - char cmd; + const char *str; void (*set)(void) __reentrant; void (*show)(void) __reentrant; - const char *help; }; static void @@ -353,35 +352,34 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_ADC - { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, - "m Set height above launch for main deploy (in meters)" }, - { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, - "d Set apogee igniter delay (in seconds)" }, + { "m \0Main deploy (in meters)", + ao_config_main_deploy_set, ao_config_main_deploy_show, }, + { "d \0Apogee delay (in seconds)", + ao_config_apogee_delay_set, ao_config_apogee_delay_show }, #endif /* HAS_ADC */ - { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, - "r Set radio channel (freq = 434.550 + channel * .1)" }, - { 'c', ao_config_callsign_set, ao_config_callsign_show, - "c Set callsign broadcast in each packet (8 char max)" }, + { "r \0Radio channel (freq = 434.550 + chan * .1)", + ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "c \0Callsign (8 char max)", + ao_config_callsign_set, ao_config_callsign_show }, #if HAS_ACCEL - { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, - "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { "a <+g> <-g>\0Accel calib (0 for auto)", + ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, #endif /* HAS_ACCEL */ - { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, - "f Set radio calibration value (cal = rf/(xtal/2^16))" }, + { "f \0Radio calib (cal = rf/(xtal/2^16))", + ao_config_radio_cal_set, ao_config_radio_cal_show }, #if HAS_EEPROM - { 'l', ao_config_log_set, ao_config_log_show, - "l Set flight log size in kB" }, + { "l \0Flight log size in kB", + ao_config_log_set, ao_config_log_show }, #endif - { 's', ao_config_show, ao_config_show, - "s Show current config values" }, + { "s\0Show", + ao_config_show, ao_config_show }, #if HAS_EEPROM - { 'w', ao_config_write, ao_config_write, - "w Write current values to eeprom" }, + { "w\0Write to eeprom", + ao_config_write, ao_config_write }, #endif - { '?', ao_config_help, ao_config_help, - "? Show available config variables" }, - { 0, ao_config_help, ao_config_help, - NULL }, + { "?\0Help", + ao_config_help, ao_config_help }, + { 0, 0, 0 } }; void @@ -395,8 +393,8 @@ ao_config_set(void) c = ao_cmd_lex_c; ao_cmd_lex(); func = 0; - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) - if (ao_config_vars[cmd].cmd == c) { + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].str[0] == c) { func = ao_config_vars[cmd].set; break; } @@ -410,8 +408,10 @@ static void ao_config_help(void) __reentrant { uint8_t cmd; - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) - puts (ao_config_vars[cmd].help); + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + printf("%-20s %s\n", + ao_config_vars[cmd].str, + ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); } static void @@ -420,7 +420,7 @@ ao_config_show(void) __reentrant uint8_t cmd; printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) (*ao_config_vars[cmd].show)(); } -- cgit v1.2.3 From 9e5e4c1ad82d621ceb7286f72c87eeaf5976f9bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:06:48 -0700 Subject: altos: Add sat info to GPS report command Plan to use this to report current flight computer state in idle mode. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index d286a30a..6099ca96 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -312,9 +312,8 @@ ao_nmea_gsv(void) ao_gps_skip_field(); /* azimuth */ 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_tracking_next.sats[i].c_n_1 = c) != 0) + ao_gps_tracking_next.channels = i + 1; } } if (ao_gps_char == '*') { @@ -461,17 +460,24 @@ __xdata struct ao_task ao_gps_task; static void gps_dump(void) __reentrant { + uint8_t i; ao_mutex_get(&ao_gps_mutex); printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); printf ("Lat/Lon: %ld %ld\n", 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); + printf ("Sats: %d", ao_gps_tracking_data.channels); + for (i = 0; i < ao_gps_tracking_data.channels; i++) + printf (" %d %d", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\ndone\n"); ao_mutex_put(&ao_gps_mutex); } __code struct ao_cmds ao_gps_cmds[] = { - { gps_dump, "g\0Display current GPS values" }, + { gps_dump, "g\0Display GPS" }, { 0, NULL }, }; -- cgit v1.2.3 From b51e5466f7a125db873edd1fa9bd3881d7e98aad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:08:19 -0700 Subject: altos: Shrink help text Reduce const space taken by command help text. Signed-off-by: Keith Packard --- src/ao_adc.c | 2 +- src/ao_cmd.c | 12 +++++------- src/ao_dbg.c | 12 ++++++------ src/ao_ignite.c | 2 +- src/ao_log.c | 4 ++-- src/ao_storage.c | 8 ++++---- 6 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/ao_adc.c b/src/ao_adc.c index 48568383..cbeb6a24 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -162,7 +162,7 @@ ao_adc_dump(void) __reentrant } __code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Display current ADC values" }, + { ao_adc_dump, "a\0Current ADC" }, { 0, NULL }, }; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 23346c3d..3f020dc3 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -221,8 +221,6 @@ version(void) printf("software-version %s\n", ao_version); } -static const char help_txt[] = "All numbers are in hex"; - #define NUM_CMDS 11 static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); @@ -234,7 +232,7 @@ help(void) __xdata uint8_t cmds; __xdata uint8_t cmd; __code struct ao_cmds * __xdata cs; - puts(help_txt); + for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; for (cmd = 0; cs[cmd].func; cmd++) @@ -302,11 +300,11 @@ ao_cmd(void) __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { - { help, "?\0Print this message" }, - { ao_task_info, "T\0Show task states" }, - { echo, "E <0 off, 1 on>\0Set command echo mode" }, + { help, "?\0Help" }, + { ao_task_info, "T\0Show tasks" }, + { echo, "E <0 off, 1 on>\0Set echo mode" }, { ao_reboot, "r eboot\0Reboot" }, - { version, "v\0Show version" }, + { version, "v\0Version" }, { 0, NULL }, }; diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 49371560..14a123a2 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -348,12 +348,12 @@ debug_output(void) } __code struct ao_cmds ao_dbg_cmds[7] = { - { debug_enable, "D\0Enable debug mode" }, - { debug_get, "G \0Get data from debug port" }, - { debug_input, "I \0Input bytes to target at " }, - { debug_output, "O \0Output bytes to target at " }, - { debug_put, "P ...\0Put data to debug port" }, - { debug_reset, "R\0Reset target" }, + { debug_enable, "D\0Enable debug" }, + { debug_get, "G \0Get data" }, + { debug_input, "I \0Input at " }, + { debug_output, "O \0Output at " }, + { debug_put, "P ...\0Put data" }, + { debug_reset, "R\0Reset" }, { 0, NULL }, }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 7874ee01..8ef83da8 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -165,7 +165,7 @@ ao_ignite_test(void) __code struct ao_cmds ao_ignite_cmds[] = { { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter continuity" }, + { ao_ignite_test, "t\0Test igniter" }, { 0, NULL }, }; diff --git a/src/ao_log.c b/src/ao_log.c index 433e9c3a..71900490 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -262,8 +262,8 @@ ao_log_delete(void) __reentrant } __code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List stored flight logs" }, - { ao_log_delete, "d \0Delete stored flight" }, + { ao_log_list, "l\0List flight logs" }, + { ao_log_delete, "d \0Delete flight" }, { 0, NULL }, }; diff --git a/src/ao_storage.c b/src/ao_storage.c index 69183514..6ffca0e5 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,13 +166,13 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { - { ao_storage_info, "f\0Show storage info" }, - { ao_storage_dump, "e \0Dump a block of flash data" }, + { ao_storage_info, "f\0Show storage" }, + { ao_storage_dump, "e \0Dump flash" }, #ifdef HAS_STORAGE_DBG { ao_storage_store, "w ...\0Write data to flash" }, #endif - { ao_storage_zap, "z \0Erase flash containing " }, - { ao_storage_zapall,"Z \0Erase all logs. is doit with D&I" }, + { ao_storage_zap, "z \0Erase " }, + { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, { 0, NULL }, }; -- cgit v1.2.3 From 359681f23e2f71bc8f4975a4a76ae28c08ecab2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:09:03 -0700 Subject: altos: Add split telemetry code This sends every packet every time, which isn't correct, but should be useful for testing. Signed-off-by: Keith Packard --- src/ao.h | 98 +++++++++++++++++++++++------------ src/ao_product.c | 2 +- src/ao_telemetrum.c | 2 +- src/ao_telemetry.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+), 34 deletions(-) create mode 100644 src/ao_telemetry.c diff --git a/src/ao.h b/src/ao.h index 4895f016..4d31f4f5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1040,14 +1040,15 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 #define AO_MAX_TELEMETRY 128 struct ao_telemetry_generic { uint16_t serial; /* 0 */ uint16_t tick; /* 2 */ uint8_t type; /* 4 */ - uint8_t payload[19]; /* 5 */ - /* 24 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ }; #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 @@ -1070,31 +1071,46 @@ struct ao_telemetry_sensor { int16_t acceleration; /* 18 m/s² * 16 */ int16_t speed; /* 20 m/s * 16 */ int16_t height; /* 22 m */ - /* 24 */ -}; -#define AO_TELEMETRY_CONSTANT 0x10 + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; -struct ao_telemetry_constant { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - int16_t ground_accel; /* 8 average ground accelerometer (TM only) */ - int16_t ground_pres; /* 10 average ground barometer */ - int16_t accel_plus_g; /* 12 +1g accelerometer calibration value (TM only) */ - int16_t accel_minus_g; /* 14 -1g accelermeter calibration value (TM only) */ - char callsign[AO_MAX_CALLSIGN]; /* 16 identity */ - /* 24 */ +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t main_deploy; /* 10 Main deploy alt in meters */ + uint32_t flight_log_max; /* 12 Maximum flight log size in bytes */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ }; -#define AO_TELEMETRY_LOCATION 0x11 +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' struct ao_telemetry_location { uint16_t serial; /* 0 */ uint16_t tick; /* 2 */ uint8_t type; /* 4 */ + uint8_t flags; /* 5 Number of sats and other flags */ int16_t altitude; /* 6 GPS reported altitude (m) */ int32_t latitude; /* 8 latitude (degrees * 10â·) */ @@ -1105,25 +1121,40 @@ struct ao_telemetry_location { uint8_t hour; /* 19 (0-23) */ uint8_t minute; /* 20 (0-59) */ uint8_t second; /* 21 (0-59) */ - uint8_t hdop; /* 22 (m * 5) */ - uint8_t unused; /* 23 */ - /* 24 */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + uint8_t course; /* 28 degrees / 2 */ + uint8_t unused[3]; /* 29 */ + /* 32 */ }; #define AO_TELEMETRY_SATELLITE 0x12 +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - uint8_t sats_0_1[3]; /* 6 reported sats 0 and 1 */ - uint8_t sats_2_3[3]; - uint8_t sats_4_5[3]; - uint8_t sats_6_7[3]; - uint8_t sats_8_9[3]; - uint8_t sats_10_11[3]; - /* 24 */ + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; }; #define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) @@ -1198,6 +1229,9 @@ ao_telemetry_set_interval(uint16_t interval); void ao_rdf_set(uint8_t rdf); +void +ao_telemetry_init(void); + void ao_telemetry_orig_init(void); diff --git a/src/ao_product.c b/src/ao_product.c index 54ba2a14..bb42e92c 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -20,7 +20,7 @@ /* Defines which mark this particular AltOS product */ -const char ao_version[] = AO_iVersion_STRING; +const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING; const char ao_manufacturer[] = AO_iManufacturer_STRING; const char ao_product[] = AO_iProduct_STRING; diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index bede5868..4ace415c 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_serial_init(); ao_gps_init(); ao_gps_report_init(); - ao_telemetry_orig_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c new file mode 100644 index 00000000..024ac6f8 --- /dev/null +++ b/src/ao_telemetry.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM +#endif + +#if defined(TELEMINI_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI +#endif + +#if defined(TELENANO_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO +#endif + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + static __xdata union ao_telemetry_all telemetry; + uint8_t sample; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + + telemetry.generic.serial = ao_serial_number; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&ao_telemetry_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + + /* Send sensor packet */ + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; + + ao_radio_send(&telemetry, sizeof (telemetry)); + + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + ao_wakeup(&ao_telemetry_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} -- cgit v1.2.3 From ef3ce687d73c1274ce5368432f4d449b063ce5c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 23:39:21 -0700 Subject: altos: Complete new telemetry switchover This involved rewriting the GPS code to use the telemetry structures directly so that a memcpy could be used to transfer the data to the telemetry packets, saving a bunch of code space, along with fixing up the gps testing programs to deal with the structure changes. In addition, the teledongle code needed to have the monitoring code split into separate radio receiver and USB writer threads as the packets are now back-to-back, and hence come too fast to wait for the USB data to be sent to the host after each one. Signed-off-by: Keith Packard --- src/ao.h | 162 ++++++++++++++++++++++--------------------- src/ao_gps_print.c | 6 +- src/ao_gps_report.c | 12 ++-- src/ao_gps_sirf.c | 6 +- src/ao_gps_skytraq.c | 10 +-- src/ao_gps_test.c | 12 ++-- src/ao_gps_test_skytraq.c | 13 ++-- src/ao_monitor.c | 81 +++++++++++++++------- src/ao_telemetry.c | 170 +++++++++++++++++++++++++++++++++------------- 9 files changed, 292 insertions(+), 180 deletions(-) diff --git a/src/ao.h b/src/ao.h index 4d31f4f5..08f45275 100644 --- a/src/ao.h +++ b/src/ao.h @@ -965,80 +965,8 @@ void ao_spi_init(void); /* - * ao_gps.c + * ao_telemetry.c */ - -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -extern __xdata uint16_t ao_gps_tick; - -struct ao_gps_data { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10â· */ - int32_t longitude; /* degrees * 10â· */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -struct ao_gps_sat_data { - uint8_t svid; - 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[AO_MAX_GPS_TRACKING]; -}; - -extern __xdata uint8_t ao_gps_mutex; -extern __xdata struct ao_gps_data ao_gps_data; -extern __xdata struct ao_gps_tracking_data ao_gps_tracking_data; - -void -ao_gps(void); - -void -ao_gps_print(__xdata struct ao_gps_data *gps_data); - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data); - -void -ao_gps_init(void); - -/* - * ao_gps_report.c - */ - -void -ao_gps_report(void); - -void -ao_gps_report_init(void); - -/* - * ao_telemetry_orig.c - */ - #define AO_MAX_CALLSIGN 8 #define AO_MAX_VERSION 8 #define AO_MAX_TELEMETRY 128 @@ -1126,12 +1054,13 @@ struct ao_telemetry_location { uint8_t vdop; /* 24 (m * 5) */ uint8_t mode; /* 25 */ uint16_t ground_speed; /* 26 cm/s */ - uint8_t course; /* 28 degrees / 2 */ - uint8_t unused[3]; /* 29 */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ /* 32 */ }; -#define AO_TELEMETRY_SATELLITE 0x12 +#define AO_TELEMETRY_SATELLITE 0x06 struct ao_telemetry_satellite_info { uint8_t svid; @@ -1157,10 +1086,79 @@ union ao_telemetry_all { struct ao_telemetry_satellite satellite; }; -#define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) -#define AO_SAT_0_C_N_1(s) ((((s)[0] & 0xc0) >> 2) | ((s)[1] & 0x0f)) -#define AO_SAT_1_SSID(s) ((((s)[1] & 0xf0) >> 2) | ((s)[2] & 0x03)) -#define AO_SAT_1_C_N_1(s) (((s)[2] & 0xfc) >> 2) +/* + * ao_gps.c + */ + +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +extern __xdata uint16_t ao_gps_tick; +extern __xdata uint8_t ao_gps_mutex; +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10â· */ + int32_t longitude; /* degrees * 10â· */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +void +ao_gps(void); + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data); + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); + +void +ao_gps_init(void); + +/* + * ao_gps_report.c + */ + +void +ao_gps_report(void); + +void +ao_gps_report_init(void); + +/* + * ao_telemetry_orig.c + */ struct ao_telemetry_orig { uint16_t serial; @@ -1180,9 +1178,9 @@ struct ao_telemetry_orig { int16_t accel_plus_g; int16_t accel_minus_g; struct ao_adc adc; - struct ao_gps_data gps; + struct ao_gps_orig gps; char callsign[AO_MAX_CALLSIGN]; - struct ao_gps_tracking_data gps_tracking; + struct ao_gps_tracking_orig gps_tracking; }; struct ao_telemetry_tiny { diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index ca071b42..fcdedd30 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -21,7 +21,7 @@ #include "ao_telem.h" void -ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant +ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant { char state; @@ -77,10 +77,10 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant } void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __reentrant +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant { uint8_t c, n, v; - __xdata struct ao_gps_sat_data *sat; + __xdata struct ao_gps_sat_orig *sat; n = gps_tracking_data->channels; if (n == 0) diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index 7abc93f5..e57f8744 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -20,14 +20,14 @@ void ao_gps_report(void) { - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_gps_data gps_data; + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_location gps_data; uint8_t date_reported = 0; for (;;) { ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); if (!(gps_data.flags & AO_GPS_VALID)) @@ -64,15 +64,15 @@ ao_gps_report(void) void ao_gps_tracking_report(void) { - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_gps_tracking_data gps_tracking_data; + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; uint8_t c, n; for (;;) { ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 87b1d69c..5827c687 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -21,8 +21,8 @@ __xdata uint8_t ao_gps_mutex; __xdata uint16_t ao_gps_tick; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; @@ -406,6 +406,7 @@ ao_gps(void) __reentrant ao_gps_data.hdop = ao_sirf_data.hdop; ao_gps_data.climb_rate = ao_sirf_data.climb_rate; ao_gps_data.flags |= AO_GPS_COURSE_VALID; +#if 0 if (ao_sirf_data.h_error > 6553500) ao_gps_data.h_error = 65535; else @@ -414,6 +415,7 @@ ao_gps(void) __reentrant ao_gps_data.v_error = 65535; else ao_gps_data.v_error = ao_sirf_data.v_error / 100; +#endif ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); break; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 6099ca96..84743ff5 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -29,13 +29,13 @@ static __xdata uint8_t ao_gps_cksum; static __xdata uint8_t ao_gps_error; __xdata uint16_t ao_gps_tick; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; static __xdata uint16_t ao_gps_next_tick; -static __xdata struct ao_gps_data ao_gps_next; +static __xdata struct ao_telemetry_location ao_gps_next; static __xdata uint8_t ao_gps_date_flags; -static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; +static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 #define STQ_E 0x0d, 0x0a @@ -265,7 +265,7 @@ ao_nmea_gga() if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 44efb50c..93d7a9ab 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -30,7 +30,7 @@ #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -struct ao_gps_data { +struct ao_gps_orig { uint8_t year; uint8_t month; uint8_t day; @@ -58,18 +58,22 @@ struct ao_gps_data { #define SIRF_SAT_ACQUISITION_FAILED (1 << 6) #define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) -struct ao_gps_sat_data { +struct ao_gps_sat_orig { uint8_t svid; uint8_t c_n_1; }; #define AO_MAX_GPS_TRACKING 12 -struct ao_gps_tracking_data { +struct ao_gps_tracking_orig { uint8_t channels; - struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; }; +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + void ao_mutex_get(uint8_t *mutex) { diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index b94e9bd2..a78fae0f 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -30,7 +30,7 @@ #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -struct ao_gps_data { +struct ao_gps_orig { uint8_t year; uint8_t month; uint8_t day; @@ -58,19 +58,22 @@ struct ao_gps_data { #define SIRF_SAT_ACQUISITION_FAILED (1 << 6) #define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) -struct ao_gps_sat_data { +struct ao_gps_sat_orig { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; #define AO_MAX_GPS_TRACKING 12 -struct ao_gps_tracking_data { +struct ao_gps_tracking_orig { uint8_t channels; - struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; }; +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + void ao_mutex_get(uint8_t *mutex) { diff --git a/src/ao_monitor.c b/src/ao_monitor.c index e5e9159f..8f1b9e12 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -21,32 +21,71 @@ __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; -void -ao_monitor(void) -{ - __xdata char callsign[AO_MAX_CALLSIGN+1]; - __xdata union { +#define AO_MONITOR_RING 8 + +__xdata union ao_monitor { struct ao_telemetry_raw_recv raw; struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; - } u; +} ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) -#define recv_raw (u.raw) -#define recv_orig (u.orig) -#define recv_tiny (u.tiny) +__data uint8_t ao_monitor_head; +void +ao_monitor_get(void) +{ + uint8_t size; + + for (;;) { + switch (ao_monitoring) { + case 0: + ao_sleep(&ao_monitoring); + continue; + case AO_MONITORING_ORIG: + size = sizeof (struct ao_telemetry_orig_recv); + break; + case AO_MONITORING_TINY: + size = sizeof (struct ao_telemetry_tiny_recv); + break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + size = ao_monitoring; + break; + } + if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) + continue; + ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_put(void) +{ + __xdata char callsign[AO_MAX_CALLSIGN+1]; + + uint8_t ao_monitor_tail; uint8_t state; uint8_t sum, byte; int16_t rssi; + __xdata union ao_monitor *m; + +#define recv_raw ((m->raw)) +#define recv_orig ((m->orig)) +#define recv_tiny ((m->tiny)) + ao_monitor_tail = ao_monitor_head; for (;;) { - __critical while (!ao_monitoring) - ao_sleep(&ao_monitoring); + while (ao_monitor_tail == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + m = &ao_monitor_ring[ao_monitor_tail]; + ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { case AO_MONITORING_ORIG: - if (!ao_radio_recv(&recv_orig, sizeof (struct ao_telemetry_orig_recv))) - continue; - state = recv_orig.telemetry_orig.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ @@ -122,9 +161,6 @@ ao_monitor(void) } break; case AO_MONITORING_TINY: - if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) - continue; - state = recv_tiny.telemetry_tiny.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ @@ -188,10 +224,6 @@ ao_monitor(void) } break; default: - if (ao_monitoring > AO_MAX_TELEMETRY) - ao_monitoring = AO_MAX_TELEMETRY; - if (!ao_radio_recv(&recv_raw, ao_monitoring + 2)) - continue; printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { @@ -203,11 +235,11 @@ ao_monitor(void) break; } ao_usb_flush(); - ao_led_toggle(ao_monitor_led); } } -__xdata struct ao_task ao_monitor_task; +__xdata struct ao_task ao_monitor_get_task; +__xdata struct ao_task ao_monitor_put_task; void ao_set_monitor(uint8_t monitoring) @@ -236,5 +268,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_monitor_led = monitor_led; ao_monitoring = monitoring; ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_task, ao_monitor, "monitor"); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); + ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); } diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 024ac6f8..94ea0b22 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,7 +18,13 @@ #include "ao.h" #include "ao_product.h" -__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint16_t ao_telemetry_interval; +__xdata int8_t ao_telemetry_config_max; +__xdata int8_t ao_telemetry_config_cur; +#if HAS_GPS +__xdata int8_t ao_telemetry_loc_cur; +__xdata int8_t ao_telemetry_sat_cur; +#endif __xdata uint8_t ao_rdf = 0; __xdata uint16_t ao_rdf_time; @@ -37,13 +43,110 @@ __xdata uint16_t ao_rdf_time; #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO #endif +static __xdata union ao_telemetry_all telemetry; + +/* Send sensor packet */ +static void +ao_send_sensor(void) +{ + uint8_t sample; + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static void +ao_send_configuration(void) +{ + if (--ao_telemetry_config_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_config_cur = ao_telemetry_config_max; + } +} + +#if HAS_GPS +static void +ao_send_location(void) +{ + if (--ao_telemetry_loc_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_LOCATION; + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.location.flags, + &ao_gps_data.flags, + 26); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_loc_cur = ao_telemetry_config_max; + } +} + +static void +ao_send_satellite(void) +{ + if (--ao_telemetry_sat_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_SATELLITE; + ao_mutex_get(&ao_gps_mutex); + telemetry.satellite.channels = ao_gps_tracking_data.channels; + memcpy(&telemetry.satellite.sats, + &ao_gps_tracking_data.sats, + AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_sat_cur = ao_telemetry_config_max; + } +} +#endif + void ao_telemetry(void) { uint16_t time; int16_t delay; - static __xdata union ao_telemetry_all telemetry; - uint8_t sample; ao_config_get(); while (!ao_flight_number) @@ -56,54 +159,13 @@ ao_telemetry(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { - /* Send sensor packet */ - sample = ao_sample_adc; - - telemetry.generic.tick = ao_adc_ring[sample].tick; - telemetry.generic.type = AO_TELEMETRY_SENSOR; - telemetry.sensor.state = ao_flight_state; -#if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; -#else - telemetry.sensor.accel = 0; -#endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; -#if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; -#else - telemetry.sensor.sense_d = 0; - telemetry.sensor.sense_m = 0; + ao_send_sensor(); + ao_send_configuration(); +#if HAS_GPS + ao_send_location(); + ao_send_satellite(); #endif - - telemetry.sensor.acceleration = ao_accel; - telemetry.sensor.speed = ao_speed; - telemetry.sensor.height = ao_height; - - telemetry.sensor.ground_pres = ao_ground_pres; - telemetry.sensor.ground_accel = ao_ground_accel; - telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; - telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; - - ao_radio_send(&telemetry, sizeof (telemetry)); - - telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; - telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_flight_number; - telemetry.configuration.config_major = AO_CONFIG_MAJOR; - telemetry.configuration.config_minor = AO_CONFIG_MINOR; - telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max; - memcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); - if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { @@ -124,6 +186,16 @@ void ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; + ao_telemetry_config_cur = 0; +#if HAS_GPS + ao_telemetry_loc_cur = 0; + if (ao_telemetry_config_max - 1 > ao_telemetry_loc_cur) + ao_telemetry_loc_cur++; + ao_telemetry_sat_cur = ao_telemetry_loc_cur; + if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) + ao_telemetry_sat_cur++; +#endif ao_wakeup(&ao_telemetry_interval); } -- cgit v1.2.3 From 4132ac5896114e5f3d8fb3f219422e8933078cf4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 21:41:44 -0700 Subject: altosui: Parse remaining standard telemetry packets Signed-off-by: Keith Packard --- altosui/Altos.java | 15 ++++- altosui/AltosLog.java | 4 +- altosui/AltosRecord.java | 7 ++ altosui/AltosTelemetryRecordConfiguration.java | 64 ++++++++++++++++++ altosui/AltosTelemetryRecordGeneral.java | 1 - altosui/AltosTelemetryRecordLocation.java | 92 ++++++++++++++++++++++++++ altosui/AltosTelemetryRecordRaw.java | 36 ++++++---- altosui/AltosTelemetryRecordSatellite.java | 52 +++++++++++++++ altosui/AltosTelemetryRecordSensor.java | 47 ++++++++++++- altosui/Makefile.am | 3 + 10 files changed, 302 insertions(+), 19 deletions(-) create mode 100644 altosui/AltosTelemetryRecordConfiguration.java create mode 100644 altosui/AltosTelemetryRecordLocation.java create mode 100644 altosui/AltosTelemetryRecordSatellite.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 25d97bcf..37a4f67b 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -231,10 +231,21 @@ public class Altos { static final Charset unicode_set = Charset.forName("UTF-8"); static String string(int[] bytes, int s, int l) { - byte[] b = new byte[bytes.length]; + if (s + l > bytes.length) { + if (s > bytes.length) { + s = bytes.length; + l = 0; + } else { + l = bytes.length - s; + } + } + + byte[] b = new byte[l]; + for (int i = 0; i < l; i++) b[i] = (byte) bytes[s+i]; - return new String(b, unicode_set); + String n = new String(b, unicode_set); + return n; } static int hexbyte(String s, int i) { diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java index 64275f32..855ee2b4 100644 --- a/altosui/AltosLog.java +++ b/altosui/AltosLog.java @@ -82,7 +82,9 @@ class AltosLog implements Runnable { continue; try { AltosRecord telem = AltosTelemetry.parse(line.line, previous); - if (telem.serial != serial || telem.flight != flight || log_file == null) { + if (telem.serial != 0 && telem.flight != 0 && + (telem.serial != serial || telem.flight != flight || log_file == null)) + { close_log_file(); serial = telem.serial; flight = telem.flight; diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 8976edf0..144b1c3c 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -67,6 +67,13 @@ public class AltosRecord { double time; /* seconds since boost */ + int device_type; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String firmware_version; /* * Values for our MP3H6115A pressure sensor * diff --git a/altosui/AltosTelemetryRecordConfiguration.java b/altosui/AltosTelemetryRecordConfiguration.java new file mode 100644 index 00000000..98dc6ab9 --- /dev/null +++ b/altosui/AltosTelemetryRecordConfiguration.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { + int device_type; + int flight; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String callsign; + String version; + + public AltosTelemetryRecordConfiguration(int[] in_bytes) { + super(in_bytes); + + device_type = uint8(5); + flight = uint16(6); + config_major = uint8(8); + config_minor = uint8(9); + apogee_delay = uint16(10); + main_deploy = uint16(12); + flight_log_max = uint16(14); + callsign = string(16, 8); + version = string(24, 8); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.device_type = device_type; + next.flight = flight; + next.config_major = config_major; + next.config_minor = config_minor; + next.apogee_delay = apogee_delay; + next.main_deploy = main_deploy; + next.flight_log_max = flight_log_max; + + next.callsign = callsign; + next.firmware_version = version; + + next.seen |= AltosRecord.seen_deploy; + + return next; + } +} diff --git a/altosui/AltosTelemetryRecordGeneral.java b/altosui/AltosTelemetryRecordGeneral.java index 55f6c495..722baba3 100644 --- a/altosui/AltosTelemetryRecordGeneral.java +++ b/altosui/AltosTelemetryRecordGeneral.java @@ -34,7 +34,6 @@ public class AltosTelemetryRecordGeneral { throw new AltosCRCException(AltosParse.parse_int(word[i++])); } - System.out.printf("First word \"%s\"\n", word[i]); if (word[i].equals("TELEM")) r = AltosTelemetryRecordRaw.parse(word[i+1]); else diff --git a/altosui/AltosTelemetryRecordLocation.java b/altosui/AltosTelemetryRecordLocation.java new file mode 100644 index 00000000..76bd106e --- /dev/null +++ b/altosui/AltosTelemetryRecordLocation.java @@ -0,0 +1,92 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { + int flags; + int altitude; + int latitude; + int longitude; + int year; + int month; + int day; + int hour; + int minute; + int second; + int pdop; + int hdop; + int vdop; + int mode; + int ground_speed; + int climb_rate; + int course; + + public AltosTelemetryRecordLocation(int[] in_bytes) { + super(in_bytes); + + flags = uint8(5); + altitude = int16(6); + latitude = uint32(8); + longitude = uint32(12); + year = uint8(16); + month = uint8(17); + day = uint8(18); + hour = uint8(19); + minute = uint8(20); + second = uint8(21); + pdop = uint8(22); + hdop = uint8(23); + vdop = uint8(24); + mode = uint8(25); + ground_speed = uint16(26); + climb_rate = int16(28); + course = uint8(30); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.nsat = flags & 0xf; + next.gps.locked = (flags & (1 << 4)) != 0; + next.gps.connected = (flags & (1 << 5)) != 0; + + if (next.gps.locked) { + next.gps.lat = latitude * 1.0e-7; + next.gps.lon = longitude * 1.0e-7; + next.gps.alt = altitude; + next.gps.year = 2000 + year; + next.gps.month = month; + next.gps.day = day; + next.gps.hour = hour; + next.gps.minute = minute; + next.gps.second = second; + next.gps.ground_speed = ground_speed * 1.0e-2; + next.gps.course = course * 2; + next.gps.climb_rate = climb_rate * 1.0e-2; + next.gps.hdop = hdop; + next.gps.vdop = vdop; + next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; + } + + return next; + } +} diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index 35796a22..e6c4cfc8 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -30,9 +30,9 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { final static int packet_type_TM_sensor = 0x01; final static int packet_type_Tm_sensor = 0x02; final static int packet_type_Tn_sensor = 0x03; - final static int packet_type_config = 0x04; - final static int packet_type_GPS_location = 0x05; - final static int packet_type_GPS_satellites = 0x06; + final static int packet_type_configuration = 0x04; + final static int packet_type_location = 0x05; + final static int packet_type_satellite = 0x06; final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); @@ -43,8 +43,6 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { for (int i = 1; i < bytes.length - 1; i++) sum += bytes[i]; sum &= 0xff; - System.out.printf("%d bytes sum 0x%x last byte 0x%x\n", - bytes.length, sum, bytes[bytes.length - 1]); return sum == bytes[bytes.length - 1]; } @@ -69,10 +67,6 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; int status = Altos.uint8(bytes, bytes.length - 2); - System.out.printf ("rssi 0x%x = %d status 0x%x\n", - Altos.uint8(bytes, bytes.length - 3), - rssi, status); - if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) throw new AltosCRCException(rssi); @@ -84,12 +78,22 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { case packet_type_TM_sensor: case packet_type_Tm_sensor: case packet_type_Tn_sensor: - r = new AltosTelemetryRecordSensor(bytes); + r = new AltosTelemetryRecordSensor(bytes, rssi); + break; + case packet_type_configuration: + r = new AltosTelemetryRecordConfiguration(bytes); + break; + case packet_type_location: + r = new AltosTelemetryRecordLocation(bytes); + break; + case packet_type_satellite: + r = new AltosTelemetryRecordSatellite(bytes); break; default: r = new AltosTelemetryRecordRaw(bytes); break; } + break; case Altos.ao_telemetry_legacy_len + 4: r = new AltosTelemetryRecordLegacy(bytes, rssi, status); break; @@ -119,6 +123,10 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { return Altos.uint32(bytes, off + 1); } + public String string(int off, int l) { + return Altos.string(bytes, off + 1, l); + } + public AltosTelemetryRecordRaw(int[] in_bytes) { bytes = in_bytes; serial = uint16(0); @@ -127,9 +135,13 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { } public AltosRecord update_state(AltosRecord previous) { + AltosRecord next; if (previous != null) - return new AltosRecord(previous); + next = new AltosRecord(previous); else - return new AltosRecord(); + next = new AltosRecord(); + next.serial = serial; + next.tick = tick; + return next; } } diff --git a/altosui/AltosTelemetryRecordSatellite.java b/altosui/AltosTelemetryRecordSatellite.java new file mode 100644 index 00000000..2dd782ad --- /dev/null +++ b/altosui/AltosTelemetryRecordSatellite.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { + int channels; + AltosGPSSat[] sats; + + public AltosTelemetryRecordSatellite(int[] in_bytes) { + super(in_bytes); + + channels = uint8(5); + if (channels > 12) + channels = 12; + if (channels == 0) + sats = null; + else { + sats = new AltosGPSSat[channels]; + for (int i = 0; i < channels; i++) { + int svid = uint8(6 + i * 2 + 0); + int c_n_1 = uint8(6 + i * 2 + 1); + sats[i] = new AltosGPSSat(svid, c_n_1); + } + } + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.cc_gps_sat = sats; + + return next; + } +} diff --git a/altosui/AltosTelemetryRecordSensor.java b/altosui/AltosTelemetryRecordSensor.java index 5ae9f891..3998437b 100644 --- a/altosui/AltosTelemetryRecordSensor.java +++ b/altosui/AltosTelemetryRecordSensor.java @@ -36,7 +36,9 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { int accel_plus_g; int accel_minus_g; - public AltosTelemetryRecordSensor(int[] in_bytes) { + int rssi; + + public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { super(in_bytes); state = uint8(5); @@ -51,14 +53,53 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { speed = int16(20); height = int16(22); - ground_accel = int16(24); - ground_pres = int16(26); + ground_pres = int16(24); + ground_accel = int16(26); accel_plus_g = int16(28); accel_minus_g = int16(30); + + rssi = in_rssi; } public AltosRecord update_state(AltosRecord previous) { AltosRecord next = super.update_state(previous); + + next.state = state; + if (type == packet_type_TM_sensor) + next.accel = accel; + else + next.accel = AltosRecord.MISSING; + next.pres = pres; + next.temp = temp; + next.batt = v_batt; + if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { + next.drogue = sense_d; + next.main = sense_m; + } else { + next.drogue = AltosRecord.MISSING; + next.main = AltosRecord.MISSING; + } + + next.acceleration = acceleration / 16.0; + next.speed = speed / 16.0; + next.height = height; + + next.ground_pres = ground_pres; + if (type == packet_type_TM_sensor) { + next.ground_accel = ground_accel; + next.accel_plus_g = accel_plus_g; + next.accel_minus_g = accel_minus_g; + } else { + next.ground_accel = AltosRecord.MISSING; + next.accel_plus_g = AltosRecord.MISSING; + next.accel_minus_g = AltosRecord.MISSING; + } + + next.rssi = rssi; + + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + System.out.printf("Sensor record update - rssi %d\n", rssi); return next; } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 6a4d9d17..6e64acab 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -75,6 +75,9 @@ altosui_JAVA = \ AltosTelemetryRecordGeneral.java \ AltosTelemetryRecordRaw.java \ AltosTelemetryRecordSensor.java \ + AltosTelemetryRecordConfiguration.java \ + AltosTelemetryRecordLocation.java \ + AltosTelemetryRecordSatellite.java \ AltosTelemetryRecordLegacy.java \ AltosTelemetryMap.java \ AltosReplayReader.java \ -- cgit v1.2.3 From 938949e39aac834a1c0912f8f307f74fe41418cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 21:42:22 -0700 Subject: doc: Chang Config and Location packets Config packets get apogee delay, and have flight_log_max shrunk to two bytes. Location packets get climb_rate added. Signed-off-by: Keith Packard --- doc/telemetry.xsl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/telemetry.xsl b/doc/telemetry.xsl index a0b9f6e7..73a9f900 100644 --- a/doc/telemetry.xsl +++ b/doc/telemetry.xsl @@ -268,10 +268,15 @@ 9uint8_tconfig_minorConfig minor version - 10uint16_tmain_deployMain deploy alt in meters + 10uint16_tapogee_delay + Apogee deploy delay in seconds - 12uint32_tflight_log_maxMaximum flight log size (B) + 12uint16_tmain_deployMain deploy alt in meters + + + 14uint16_tflight_log_max + Maximum flight log size (kB) 16charcallsign[8]Radio operator identifier @@ -379,10 +384,13 @@ 26uint16_tground_speedcm/s - 28uint8_tcourse/ 2 + 28int16_tclimb_ratecm/s + + + 30uint8_tcourse/ 2 - 29uint8_tunused[3] + 31uint8_tunused[1] 32 -- cgit v1.2.3 From edf6252450e06fd42fa6dde3acd127baa8fa6d36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 21:44:53 -0700 Subject: altos: Adapt to changes in telemetry Configuration packet Apogee delay added. flight_log_max changed to two bytes (in kB now). Signed-off-by: Keith Packard --- src/ao.h | 5 +++-- src/ao_telemetry.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ao.h b/src/ao.h index 08f45275..9a986479 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1018,8 +1018,9 @@ struct ao_telemetry_configuration { uint16_t flight; /* 6 flight number */ uint8_t config_major; /* 8 Config major version */ uint8_t config_minor; /* 9 Config minor version */ - uint16_t main_deploy; /* 10 Main deploy alt in meters */ - uint32_t flight_log_max; /* 12 Maximum flight log size in bytes */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ char version[AO_MAX_VERSION]; /* 24 Software version */ /* 32 */ diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 94ea0b22..f45d2ab4 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -94,8 +94,9 @@ ao_send_configuration(void) telemetry.configuration.flight = ao_flight_number; telemetry.configuration.config_major = AO_CONFIG_MAJOR; telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.apogee_delay = ao_config.apogee_delay; telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max; + telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; memcpy (telemetry.configuration.callsign, ao_config.callsign, AO_MAX_CALLSIGN); -- cgit v1.2.3 From 6ac34f9c8efd464194137ac4ce8228bf9d7d83be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:35:02 -0700 Subject: doc: Add section about TeleDongle USB line format Describe the format of the TELEM lines sent over USB from TeleDongle to the host. Signed-off-by: Keith Packard --- doc/telemetry.xsl | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/doc/telemetry.xsl b/doc/telemetry.xsl index 73a9f900..fa66bff9 100644 --- a/doc/telemetry.xsl +++ b/doc/telemetry.xsl @@ -704,6 +704,74 @@ +
+ TeleDongle packet format + + TeleDongle does not do any interpretation of the packet data, + instead it is configured to receive packets of a specified + length (32 bytes in this case). For each received packet, + TeleDongle produces a single line of text. This line starts with + the string "TELEM " and is followed by a list of hexadecimal + encoded bytes. + + TELEM 224f01080b05765e00701f1a1bbeb8d7b60b070605140c000600000000000000003fa988 + + The hexadecimal encoded string of bytes contains a length byte, + the packet data, two bytes added by the cc1111 radio receiver + hardware and finally a checksum so that the host software can + validate that the line was transmitted without any errors. + + + + + + + + + + Offset + Name + Example + Description + + + + + 0 + length + 22 + Total length of data bytes in the line. Note that + this includes the added RSSI and status bytes + + + 1 ·· length-3 + packet + 4f ·· 00 + Bytes of actual packet data + + + length-2 + rssi + 3f + Received signal strength. dBm = rssi / 2 - 74 + + + length-1 + lqi + a9 + Link Quality Indicator and CRC status. Bit 7 + is set when the CRC is correct + + + length + checksum + 88 + (0x5a + sum(bytes 1 ·· length-1)) % 256 + + + +
+
History and Motivation -- cgit v1.2.3 From 72575dcb9cfbb5c1ccdb3510b9962a6f60ca3fa3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:35:50 -0700 Subject: altosui: Elide nul bytes at end of telemetry string values All telemetry fields are fixed length, so any embedded strings are padded with nul bytes. Signed-off-by: Keith Packard --- altosui/Altos.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 37a4f67b..36490844 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -240,9 +240,15 @@ public class Altos { } } + int i; + for (i = l - 1; i >= 0; i--) + if (bytes[s+i] != 0) + break; + + l = i + 1; byte[] b = new byte[l]; - for (int i = 0; i < l; i++) + for (i = 0; i < l; i++) b[i] = (byte) bytes[s+i]; String n = new String(b, unicode_set); return n; -- cgit v1.2.3 From c1f859170b37864b816eb561318dbfb1cafaeed6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:37:00 -0700 Subject: altosui: Elide missing values from graphs Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 4b994b47..942688d2 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -28,18 +28,23 @@ public class AltosGraphUI extends JFrame AltosGraphTime.Element height = new AltosGraphTime.TimeSeries("Height (m)", "Height (AGL)", red) { public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.height()); + double height = d.height(); + if (height != AltosRecord.MISSING) + series.add(time, d.height()); } }; AltosGraphTime.Element speed = new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { public void gotTimeData(double time, AltosDataPoint d) { + double speed; if (d.state() < Altos.ao_flight_drogue && d.has_accel()) { - series.add(time, d.accel_speed()); + speed = d.accel_speed(); } else { - series.add(time, d.baro_speed()); + speed = d.baro_speed(); } + if (speed != AltosRecord.MISSING) + series.add(time, speed); } }; @@ -48,7 +53,9 @@ public class AltosGraphUI extends JFrame "Axial Acceleration", blue) { public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.acceleration()); + double acceleration = d.acceleration(); + if (acceleration != AltosRecord.MISSING) + series.add(time, acceleration); } }; @@ -57,7 +64,9 @@ public class AltosGraphUI extends JFrame "Board temperature", red) { public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.temperature()); + double temp = d.temperature(); + if (temp != AltosRecord.MISSING) + series.add(time, d.temperature()); } }; @@ -65,7 +74,9 @@ public class AltosGraphUI extends JFrame new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) { public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.drogue_voltage()); + double v = d.drogue_voltage(); + if (v != AltosRecord.MISSING) + series.add(time, v); } }; @@ -73,7 +84,9 @@ public class AltosGraphUI extends JFrame new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) { public void gotTimeData(double time, AltosDataPoint d) { - series.add(time, d.main_voltage()); + double v = d.main_voltage(); + if (v != AltosRecord.MISSING) + series.add(time, v); } }; -- cgit v1.2.3 From d0335f83c54df0b23c28d04d34c212a1bdffadd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:37:51 -0700 Subject: altosui: Add main/drogue voltages to default graph Until we get a UI for changing the graph elements, lets add a few more potentially useful values. Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 942688d2..03aae652 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -112,7 +112,9 @@ public class AltosGraphUI extends JFrame graphs.add( myAltosGraphTime("Summary") .addElement(height) .addElement(speed) - .addElement(acceleration) ); + .addElement(acceleration) + .addElement(drogue_voltage) + .addElement(main_voltage) ); graphs.add( myAltosGraphTime("Summary") .addElement(height) -- cgit v1.2.3 From 7cfd43663cde5ebdf04e4face076d79ff6329ac3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:38:28 -0700 Subject: altosui: Remove debug printf. Signed-off-by: Keith Packard --- altosui/AltosTelemetryRecordSensor.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosTelemetryRecordSensor.java b/altosui/AltosTelemetryRecordSensor.java index 3998437b..96fee81f 100644 --- a/altosui/AltosTelemetryRecordSensor.java +++ b/altosui/AltosTelemetryRecordSensor.java @@ -99,7 +99,6 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; - System.out.printf("Sensor record update - rssi %d\n", rssi); return next; } } -- cgit v1.2.3 From 481577a29380afe6750ef7c4e928daff837cbc49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 23:38:42 -0700 Subject: altosui: Compress telemetry records marked with the same time Split telemetry transmits multiple packets with the same timestamp. Merge those into a single record when read from a file. Signed-off-by: Keith Packard --- altosui/AltosTelemetryIterable.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index 90a08485..1a31b365 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -53,7 +53,6 @@ public class AltosTelemetryIterable extends AltosRecordIterable { AltosRecord record = AltosTelemetry.parse(line, previous); if (record == null) break; - previous = record; if (records.isEmpty()) { current_tick = record.tick; } else { @@ -74,7 +73,9 @@ public class AltosTelemetryIterable extends AltosRecordIterable { has_gps = true; if (record.main != AltosRecord.MISSING) has_ignite = true; - records.add(record); + if (previous != null && previous.tick != record.tick) + records.add(previous); + previous = record; } catch (ParseException pe) { System.out.printf("parse exception %s\n", pe.getMessage()); } catch (AltosCRCException ce) { @@ -84,6 +85,9 @@ public class AltosTelemetryIterable extends AltosRecordIterable { System.out.printf("io exception\n"); } + if (previous != null) + records.add(previous); + /* adjust all tick counts to be relative to boost time */ for (AltosRecord r : this) r.time = (r.tick - boost_tick) / 100.0; -- cgit v1.2.3 From 41c230cac359b4459ca93196d08704b7d35447c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 12:38:11 -0700 Subject: altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd No functional changes, just reduces code size. Signed-off-by: Keith Packard --- src/ao_cmd.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 3f020dc3..60f10716 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -110,9 +110,8 @@ putnibble(uint8_t v) void ao_cmd_put16(uint16_t v) { - int8_t i; - for (i = 3; i >= 0; i--) - putnibble((v >> (i << 2)) & 0xf); + ao_cmd_put8(v >> 8); + ao_cmd_put8(v); } void @@ -133,18 +132,20 @@ void ao_cmd_hex(void) { __xdata uint8_t r = ao_cmd_lex_error; + uint8_t n; ao_cmd_lex_i = 0; ao_cmd_white(); for(;;) { if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - '0'); + n = (ao_cmd_lex_c - '0'); else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'a' + 10); + n = (ao_cmd_lex_c - 'a' + 10); else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'A' + 10); + n = (ao_cmd_lex_c - 'A' + 10); else break; + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; r = ao_cmd_success; ao_cmd_lex(); } @@ -265,8 +266,8 @@ ao_cmd_register(__code struct ao_cmds *cmds) void ao_cmd(void) { - __xdata char c; - __xdata uint8_t cmd, cmds; + char c; + uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); -- cgit v1.2.3 From 480b48837db31987b947e4d32248965d4a16be03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 13:21:25 -0700 Subject: altos: Shrink ao_config_callsign_set Replacing a hand-coded memset with a function call, using static space instead of stack space for an array. Signed-off-by: Keith Packard --- src/ao_config.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index c7fc7dd2..2434bc6c 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -116,8 +116,9 @@ void ao_config_callsign_set(void) __reentrant { uint8_t c; - char callsign[AO_MAX_CALLSIGN + 1]; + static __xdata char callsign[AO_MAX_CALLSIGN + 1]; + memset(callsign, '\0', sizeof callsign); ao_cmd_white(); c = 0; while (ao_cmd_lex_c != '\n') { @@ -131,8 +132,6 @@ ao_config_callsign_set(void) __reentrant return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - while (c < AO_MAX_CALLSIGN + 1) - callsign[c++] = '\0'; memcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); ao_config_dirty = 1; -- cgit v1.2.3 From 64860be02b3efa6f784a259249cfa6d14545fbd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 13:49:05 -0700 Subject: altos: Shrink ao_add_task by rolling up a memset loop This has a dramatic effect. By pulling the 'stack' variable into registers it reduces the size of this function from 550 to 231 bytes. Signed-off-by: Keith Packard --- src/ao_task.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/ao_task.c b/src/ao_task.c index 35f34b49..7e34ed61 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -48,26 +48,31 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam */ stack = task->stack; - *stack++ = ((uint16_t) start); - *stack++ = ((uint16_t) start) >> 8; + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ /* and the stuff saved by ao_switch */ - *stack++ = 0; /* acc */ - *stack++ = 0x80; /* IE */ - *stack++ = 0; /* DPL */ - *stack++ = 0; /* DPH */ - *stack++ = 0; /* B */ - *stack++ = 0; /* R2 */ - *stack++ = 0; /* R3 */ - *stack++ = 0; /* R4 */ - *stack++ = 0; /* R5 */ - *stack++ = 0; /* R6 */ - *stack++ = 0; /* R7 */ - *stack++ = 0; /* R0 */ - *stack++ = 0; /* R1 */ - *stack++ = 0; /* PSW */ - *stack++ = 0; /* BP */ - task->stack_count = stack - task->stack; + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; task->wchan = NULL; } -- cgit v1.2.3 From 92047ff86c79c2b18ef565a4560b06fe00d6f159 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:31:53 -0700 Subject: altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_gps_sirf.c | 2 +- src/ao_gps_skytraq.c | 31 ++++++++++++++++--------------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/ao.h b/src/ao.h index 9a986479..40466123 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1099,7 +1099,7 @@ union ao_telemetry_all { #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -extern __xdata uint16_t ao_gps_tick; +extern __pdata uint16_t ao_gps_tick; extern __xdata uint8_t ao_gps_mutex; extern __xdata struct ao_telemetry_location ao_gps_data; extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 5827c687..f2abbf84 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -20,7 +20,7 @@ #endif __xdata uint8_t ao_gps_mutex; -__xdata uint16_t ao_gps_tick; +__pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 84743ff5..e7d1d2ef 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -21,20 +21,20 @@ #define AO_GPS_LEADER 2 -static const char ao_gps_header[] = "GP"; +static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; -static __xdata char ao_gps_char; -static __xdata uint8_t ao_gps_cksum; -static __xdata uint8_t ao_gps_error; +static __pdata char ao_gps_char; +static __pdata uint8_t ao_gps_cksum; +static __pdata uint8_t ao_gps_error; -__xdata uint16_t ao_gps_tick; +__pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; -static __xdata uint16_t ao_gps_next_tick; +static __pdata uint16_t ao_gps_next_tick; static __xdata struct ao_telemetry_location ao_gps_next; -static __xdata uint8_t ao_gps_date_flags; +static __pdata uint8_t ao_gps_date_flags; static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 @@ -49,7 +49,7 @@ static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E -static const uint8_t ao_gps_config[] = { +static __code uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ /* gsa interval */ @@ -89,13 +89,13 @@ ao_gps_skip_sep(void) ao_gps_lexchar(); } -__xdata static uint8_t ao_gps_num_width; +__pdata static uint8_t ao_gps_num_width; static int16_t ao_gps_decimal(uint8_t max_width) { int16_t v; - __xdata uint8_t neg = 0; + __pdata uint8_t neg = 0; ao_gps_skip_sep(); if (ao_gps_char == '-') { @@ -390,15 +390,16 @@ ao_nmea_rmc(void) } } -#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), (s)+sizeof(s)) +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) static void -ao_skytraq_sendbytes(const uint8_t *b, const uint8_t *e) +ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) { - while (b != e) { - if (*b == 0xa0) + while (l--) { + uint8_t c = *b++; + if (c == 0xa0) ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(*b++); + ao_serial_putchar(c); } } -- cgit v1.2.3 From 62267144d189967fcd0724b6dfbdbab3cb6fb414 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:33:52 -0700 Subject: altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_ignite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 8ef83da8..e1b91bea 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -58,8 +58,8 @@ enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter) { __xdata struct ao_adc adc; - __xdata int16_t value; - __xdata uint8_t request, firing, fired; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; __critical { ao_adc_get(&adc); @@ -143,7 +143,7 @@ ao_ignite_manual(void) } } -static __code char *igniter_status_names[] = { +static __code char * __code igniter_status_names[] = { "unknown", "ready", "active", "open" }; -- cgit v1.2.3 From 5203ddaac692bfd82a01368da9fb66c25e9e14c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:36:45 -0700 Subject: altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_log.c | 2 +- src/ao_log_big.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index 40466123..c9a6970e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -535,7 +535,7 @@ extern __pdata uint32_t ao_log_current_pos; extern __pdata uint32_t ao_log_end_pos; extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; -extern __xdata enum flight_state ao_log_state; +extern __pdata enum flight_state ao_log_state; /* required functions from the underlying log system */ diff --git a/src/ao_log.c b/src/ao_log.c index 71900490..80d7243d 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -21,7 +21,7 @@ __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; __pdata uint32_t ao_log_start_pos; __xdata uint8_t ao_log_running; -__xdata enum flight_state ao_log_state; +__pdata enum flight_state ao_log_state; __xdata uint16_t ao_flight_number; void diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 0c6cff85..74d94c4b 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -60,7 +60,7 @@ ao_log_dump_check_data(void) return 1; } -static __xdata uint8_t ao_log_adc_pos; +static __data uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; @@ -72,7 +72,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - uint16_t next_sensor, next_other; + __pdata uint16_t next_sensor, next_other; ao_storage_setup(); -- cgit v1.2.3 From 002f167fc2709aaf1a4984aaa0a3519a97749d5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:37:15 -0700 Subject: altos: Switch ao_report.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_report.c b/src/ao_report.c index b9dc5bb4..3cf558e1 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -48,7 +48,7 @@ static const uint8_t flight_reports[] = { #endif #define pause(time) ao_delay(time) -static __xdata enum ao_flight_state ao_report_state; +static __pdata enum ao_flight_state ao_report_state; static void ao_report_beep(void) __reentrant @@ -87,9 +87,9 @@ ao_report_digit(uint8_t digit) __reentrant static void ao_report_altitude(void) { - __xdata int16_t agl = ao_max_height; + __pdata int16_t agl = ao_max_height; __xdata uint8_t digits[10]; - __xdata uint8_t ndigits, i; + __pdata uint8_t ndigits, i; if (agl < 0) agl = 0; -- cgit v1.2.3 From 803bf106caf5d6b5ac12eb00a941647c7325edd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:37:34 -0700 Subject: altos: Switch ao_rssi.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_rssi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ao_rssi.c b/src/ao_rssi.c index 6912b9a2..e3964d2d 100644 --- a/src/ao_rssi.c +++ b/src/ao_rssi.c @@ -18,8 +18,8 @@ #include "ao.h" static __xdata volatile uint16_t ao_rssi_time; -static __xdata volatile uint16_t ao_rssi_delay; -static __xdata uint8_t ao_rssi_led; +static __pdata volatile uint16_t ao_rssi_delay; +static __pdata uint8_t ao_rssi_led; void ao_rssi(void) -- cgit v1.2.3 From 86b41d4c2b8a9fa4507cdb75302e0cedebb103cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:38:29 -0700 Subject: altos: Switch ao_sample.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 10 +++++----- src/ao_sample.c | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ao.h b/src/ao.h index c9a6970e..1919a259 100644 --- a/src/ao.h +++ b/src/ao.h @@ -803,13 +803,13 @@ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ #endif -extern __xdata int16_t ao_ground_pres; /* startup pressure */ -extern __xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -extern __xdata int16_t ao_ground_accel; /* startup acceleration */ -extern __xdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif void ao_sample_init(void); diff --git a/src/ao_sample.c b/src/ao_sample.c index 84cf1e00..ac156646 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -37,21 +37,21 @@ __data uint8_t ao_sample_adc; * Sensor calibration values */ -__xdata int16_t ao_ground_pres; /* startup pressure */ -__xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +__pdata int16_t ao_ground_pres; /* startup pressure */ +__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -__xdata int16_t ao_ground_accel; /* startup acceleration */ -__xdata int16_t ao_accel_2g; /* factory accel calibration */ -__xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +__pdata int16_t ao_ground_accel; /* startup acceleration */ +__pdata int16_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif -static __xdata uint8_t ao_preflight; /* in preflight mode */ +static __pdata uint8_t ao_preflight; /* in preflight mode */ -static __xdata uint16_t nsamples; -__xdata int32_t ao_sample_pres_sum; +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; #if HAS_ACCEL -__xdata int32_t ao_sample_accel_sum; +__pdata int32_t ao_sample_accel_sum; #endif static void -- cgit v1.2.3 From 9ba0da9247ea424a7a147aa85daae0d5e6316b81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:38:46 -0700 Subject: altos: Switch ao_serial.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_serial.c b/src/ao_serial.c index 2e7dad7b..82370c64 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -91,7 +91,7 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static const struct { +static __code struct { uint8_t baud; uint8_t gcr; } ao_serial_speeds[] = { -- cgit v1.2.3 From f2f8ade6994aa3a69fd08f19c4403ceb8cea295d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:39:44 -0700 Subject: altos: Switch ao_stdio.c __data to __pdata Signed-off-by: Keith Packard --- src/ao.h | 4 ++-- src/ao_stdio.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index 1919a259..dade99bf 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1311,8 +1311,8 @@ struct ao_stdio { }; extern __xdata struct ao_stdio ao_stdios[]; -extern __data int8_t ao_cur_stdio; -extern __data int8_t ao_num_stdios; +extern __pdata int8_t ao_cur_stdio; +extern __pdata int8_t ao_num_stdios; void flush(void); diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 6b890832..c0138a30 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -24,8 +24,8 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; -__data int8_t ao_cur_stdio; -__data int8_t ao_num_stdios; +__pdata int8_t ao_cur_stdio; +__pdata int8_t ao_num_stdios; void putchar(char c) -- cgit v1.2.3 From 359baab005c274a0841268c615c23b3ffef813cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:41:06 -0700 Subject: altos: Switch ao_telemetry.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_telemetry.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index f45d2ab4..dcd0ff62 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,15 +18,15 @@ #include "ao.h" #include "ao_product.h" -__xdata uint16_t ao_telemetry_interval; -__xdata int8_t ao_telemetry_config_max; -__xdata int8_t ao_telemetry_config_cur; +static __pdata uint16_t ao_telemetry_interval; +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; #if HAS_GPS -__xdata int8_t ao_telemetry_loc_cur; -__xdata int8_t ao_telemetry_sat_cur; +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; #endif -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; +static __pdata uint8_t ao_rdf = 0; +static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 @@ -156,7 +156,7 @@ ao_telemetry(void) telemetry.generic.serial = ao_serial_number; for (;;) { while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); + ao_sleep(&telemetry); time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { @@ -197,7 +197,7 @@ ao_telemetry_set_interval(uint16_t interval) if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) ao_telemetry_sat_cur++; #endif - ao_wakeup(&ao_telemetry_interval); + ao_wakeup(&telemetry); } void -- cgit v1.2.3 From 355db71f4511adff8abcb2caded61c12fe8b7ee9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:41:32 -0700 Subject: altos: Switch ao_usb.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_usb.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/ao_usb.c b/src/ao_usb.c index e4b7938d..08cb7390 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -21,10 +21,10 @@ struct ao_task __xdata ao_usb_task; static __xdata uint16_t ao_usb_in_bytes; -static __xdata uint16_t ao_usb_in_bytes_last; +static __pdata uint16_t ao_usb_in_bytes_last; static __xdata uint16_t ao_usb_out_bytes; -static __xdata uint8_t ao_usb_iif; -static __xdata uint8_t ao_usb_running; +static __pdata uint8_t ao_usb_iif; +static __pdata uint8_t ao_usb_running; static void ao_usb_set_interrupts(void) @@ -72,20 +72,20 @@ struct ao_usb_setup { uint16_t length; } __xdata ao_usb_setup; -__xdata uint8_t ao_usb_ep0_state; -uint8_t * __xdata ao_usb_ep0_in_data; -__xdata uint8_t ao_usb_ep0_in_len; -__xdata uint8_t ao_usb_ep0_in_buf[2]; -__xdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__xdata ao_usb_ep0_out_data; -__xdata uint8_t ao_usb_configuration; +__pdata uint8_t ao_usb_ep0_state; +uint8_t * __pdata ao_usb_ep0_in_data; +__pdata uint8_t ao_usb_ep0_in_len; +__pdata uint8_t ao_usb_ep0_in_buf[2]; +__pdata uint8_t ao_usb_ep0_out_len; +__xdata uint8_t *__pdata ao_usb_ep0_out_data; +__pdata uint8_t ao_usb_configuration; /* Send an IN data packet */ static void ao_usb_ep0_flush(void) { - __xdata uint8_t this_len; - __xdata uint8_t cs0; + __pdata uint8_t this_len; + __pdata uint8_t cs0; /* If the IN packet hasn't been picked up, just return */ USBINDEX = 0; @@ -115,9 +115,9 @@ __xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; static void ao_usb_get_descriptor(uint16_t value) { - const uint8_t *__xdata descriptor; - __xdata uint8_t type = value >> 8; - __xdata uint8_t index = value; + __code uint8_t *__pdata descriptor; + __pdata uint8_t type = value >> 8; + __pdata uint8_t index = value; descriptor = ao_usb_descriptors; while (descriptor[0] != 0) { @@ -138,7 +138,7 @@ ao_usb_get_descriptor(uint16_t value) static void ao_usb_ep0_fill(void) { - __xdata uint8_t len; + __pdata uint8_t len; USBINDEX = 0; len = USBCNT0; @@ -282,7 +282,7 @@ ao_usb_ep0_setup(void) static void ao_usb_ep0(void) { - __xdata uint8_t cs0; + __pdata uint8_t cs0; ao_usb_ep0_state = AO_USB_EP0_IDLE; for (;;) { -- cgit v1.2.3 From 2ec986f08ce8d4635f4435bb0042b405d93edc40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:45:04 -0700 Subject: altos: Switch const for __code in struct ao_cmds This saves quite a bit of code space when accessing these values. Signed-off-by: Keith Packard --- src/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index dade99bf..bb384611 100644 --- a/src/ao.h +++ b/src/ao.h @@ -395,7 +395,7 @@ ao_match_word(__code char *word); struct ao_cmds { void (*func)(void); - const char *help; + __code char *help; }; void -- cgit v1.2.3 From 6893752900385ee51cc4cf75e1b672202de7578a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:26:09 -0700 Subject: altos: switch ao_cmd __xdata to __pdata Saves code space Signed-off-by: Keith Packard --- src/ao.h | 8 ++++---- src/ao_cmd.c | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ao.h b/src/ao.h index bb384611..8836a286 100644 --- a/src/ao.h +++ b/src/ao.h @@ -367,10 +367,10 @@ enum ao_cmd_status { ao_cmd_syntax_error = 2, }; -extern __xdata uint16_t ao_cmd_lex_i; -extern __xdata uint32_t ao_cmd_lex_u32; -extern __xdata char ao_cmd_lex_c; -extern __xdata enum ao_cmd_status ao_cmd_status; +extern __pdata uint16_t ao_cmd_lex_i; +extern __pdata uint32_t ao_cmd_lex_u32; +extern __pdata char ao_cmd_lex_c; +extern __pdata enum ao_cmd_status ao_cmd_status; void ao_cmd_lex(void); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 60f10716..6d3ae38d 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -17,21 +17,21 @@ #include "ao.h" -__xdata uint16_t ao_cmd_lex_i; -__xdata uint32_t ao_cmd_lex_u32; -__xdata char ao_cmd_lex_c; -__xdata enum ao_cmd_status ao_cmd_status; +__pdata uint16_t ao_cmd_lex_i; +__pdata uint32_t ao_cmd_lex_u32; +__pdata char ao_cmd_lex_c; +__pdata enum ao_cmd_status ao_cmd_status; #define CMD_LEN 32 static __xdata char cmd_line[CMD_LEN]; -static __xdata uint8_t cmd_len; -static __xdata uint8_t cmd_i; +static __pdata uint8_t cmd_len; +static __pdata uint8_t cmd_i; static void -put_string(char *s) +put_string(__code char *s) { - __xdata char c; + char c; while (c = *s++) putchar(c); } @@ -39,7 +39,7 @@ put_string(char *s) static void readline(void) { - __xdata char c; + __pdata char c; if (ao_echo()) put_string("> "); cmd_len = 0; @@ -131,7 +131,7 @@ ao_cmd_white(void) void ao_cmd_hex(void) { - __xdata uint8_t r = ao_cmd_lex_error; + __pdata uint8_t r = ao_cmd_lex_error; uint8_t n; ao_cmd_lex_i = 0; @@ -156,7 +156,7 @@ ao_cmd_hex(void) void ao_cmd_decimal(void) { - __xdata uint8_t r = ao_cmd_lex_error; + __pdata uint8_t r = ao_cmd_lex_error; ao_cmd_lex_u32 = 0; ao_cmd_white(); @@ -225,14 +225,14 @@ version(void) #define NUM_CMDS 11 static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); -static __xdata uint8_t ao_ncmds; +static __pdata uint8_t ao_ncmds; static void help(void) { - __xdata uint8_t cmds; - __xdata uint8_t cmd; - __code struct ao_cmds * __xdata cs; + register uint8_t cmds; + register uint8_t cmd; + register __code struct ao_cmds * cs; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; -- cgit v1.2.3 From 6903b6464db7eb803de8bf9b897c45431f7a1d63 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:27:32 -0700 Subject: altos: Switch ao_config.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index 2434bc6c..813164ea 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -18,8 +18,8 @@ #include "ao.h" __xdata struct ao_config ao_config; -__xdata uint8_t ao_config_loaded; -__xdata uint8_t ao_config_dirty; +__pdata uint8_t ao_config_loaded; +__pdata uint8_t ao_config_dirty; __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 @@ -335,7 +335,7 @@ ao_config_log_set(void) __reentrant #endif /* HAS_EEPROM */ struct ao_config_var { - const char *str; + __code char *str; void (*set)(void) __reentrant; void (*show)(void) __reentrant; }; -- cgit v1.2.3 From 3742b36a528f114c3b1873caa4f39581145b76da Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:28:01 -0700 Subject: altos: Switch ao_dbg.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_dbg.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 14a123a2..d4c9567f 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -31,7 +31,7 @@ ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant void ao_dbg_send_byte(uint8_t byte) { - __xdata uint8_t b, d; + __pdata uint8_t b, d; DBG_PORT |= DBG_DATA; DBG_PORT_DIR |= DBG_DATA; @@ -49,7 +49,7 @@ ao_dbg_send_byte(uint8_t byte) uint8_t ao_dbg_recv_byte(void) { - __xdata uint8_t byte, b; + __pdata uint8_t byte, b; byte = 0; for (b = 0; b < 8; b++) { @@ -89,12 +89,12 @@ ao_dbg_recv_byte(void) #define SFR_DPL1 0x84 #define SFR_DPH1 0x85 -__xdata uint8_t save_acc; -__xdata uint8_t save_psw; -__xdata uint8_t save_dpl0; -__xdata uint8_t save_dph0; -__xdata uint8_t save_dpl1; -__xdata uint8_t save_dph1; +__pdata uint8_t save_acc; +__pdata uint8_t save_psw; +__pdata uint8_t save_dpl0; +__pdata uint8_t save_dph0; +__pdata uint8_t save_dpl1; +__pdata uint8_t save_dph1; static uint8_t ao_dbg_inst1(uint8_t a) __reentrant @@ -260,9 +260,9 @@ debug_put(void) static void debug_get(void) { - __xdata uint16_t count; - __xdata uint16_t i; - __xdata uint8_t byte; + __pdata uint16_t count; + __pdata uint16_t i; + __pdata uint8_t byte; ao_cmd_hex(); if (ao_cmd_status != ao_cmd_success) return; @@ -284,7 +284,7 @@ debug_get(void) static uint8_t getnibble(void) { - __xdata char c; + __pdata char c; c = getchar(); if ('0' <= c && c <= '9') @@ -300,10 +300,10 @@ getnibble(void) static void debug_input(void) { - __xdata uint16_t count; - __xdata uint16_t addr; - __xdata uint8_t b; - __xdata uint8_t i; + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; + __pdata uint8_t i; ao_cmd_hex(); count = ao_cmd_lex_i; @@ -326,9 +326,9 @@ debug_input(void) static void debug_output(void) { - __xdata uint16_t count; - __xdata uint16_t addr; - __xdata uint8_t b; + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; ao_cmd_hex(); count = ao_cmd_lex_i; -- cgit v1.2.3 From 038d7b25ba833da4be458409670d3f95e8aaf17b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:51:52 -0700 Subject: altos: Switch ao_flight and ao_flight_nano __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_flight.c | 5 +---- src/ao_flight_nano.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/ao.h b/src/ao.h index 8836a286..ac5615bb 100644 --- a/src/ao.h +++ b/src/ao.h @@ -707,7 +707,7 @@ enum ao_flight_state { extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_launch_time; -extern __xdata uint8_t ao_flight_force_idle; +extern __pdata uint8_t ao_flight_force_idle; /* Flight thread */ void diff --git a/src/ao_flight.c b/src/ao_flight.c index c6cbbf7c..f1b60d69 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -44,7 +44,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__xdata uint8_t ao_flight_force_idle; +__pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in * case of other failures @@ -170,7 +170,6 @@ ao_flight(void) #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; case ao_flight_boost: @@ -194,7 +193,6 @@ ao_flight(void) ao_flight_state = ao_flight_coast; #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; #if HAS_ACCEL @@ -208,7 +206,6 @@ ao_flight(void) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; #endif diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c index 32770227..2e332b12 100644 --- a/src/ao_flight_nano.c +++ b/src/ao_flight_nano.c @@ -30,7 +30,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__xdata uint8_t ao_flight_force_idle; +__pdata uint8_t ao_flight_force_idle; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) -- cgit v1.2.3 From b65140a0139075adeddaccf0f4d5c7a75fac4757 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:52:25 -0700 Subject: altos: Switch flash drivers __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 8 ++++---- src/ao_ee.c | 8 ++++---- src/ao_flash.c | 8 ++++---- src/ao_intflash.c | 8 ++++---- src/ao_m25.c | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/ao.h b/src/ao.h index ac5615bb..e52a2198 100644 --- a/src/ao.h +++ b/src/ao.h @@ -464,16 +464,16 @@ ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; */ /* Total bytes of available storage */ -extern __xdata uint32_t ao_storage_total; +extern __pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -extern __xdata uint32_t ao_storage_block; +extern __pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __xdata uint32_t ao_storage_config; +extern __pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __xdata uint16_t ao_storage_unit; +extern __pdata uint16_t ao_storage_unit; #define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) diff --git a/src/ao_ee.c b/src/ao_ee.c index e3b41103..83863af5 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -23,16 +23,16 @@ #define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; /* * Using SPI on USART 0, with P1_2 as the chip select diff --git a/src/ao_flash.c b/src/ao_flash.c index d323926f..00e96398 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -19,16 +19,16 @@ #include "at45db161d.h" /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 diff --git a/src/ao_intflash.c b/src/ao_intflash.c index 88d1f7f6..d76d954e 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -47,16 +47,16 @@ __xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total = sizeof(ao_intflash); +__pdata uint32_t ao_storage_total = sizeof(ao_intflash); /* Block size - device is erased in these units. */ -__xdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; +__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; +__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; /* Storage unit size - device reads and writes must be within blocks of this size. */ -__xdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; +__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; __xdata static uint8_t ao_intflash_dma_done; static uint8_t ao_intflash_dma; diff --git a/src/ao_m25.c b/src/ao_m25.c index afd5df76..208c69ba 100644 --- a/src/ao_m25.c +++ b/src/ao_m25.c @@ -18,16 +18,16 @@ #include "ao.h" /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; /* * Each flash chip is arranged in 64kB sectors; the -- cgit v1.2.3 From 0154d13756bcb09f009981ee5e4bd27fd04b8788 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:19:22 -0700 Subject: altos: Switch Tm and Tn to common telemetry code Signed-off-by: Keith Packard --- src/Makefile.proto | 4 ++-- src/ao_telemetry.c | 6 ++++++ src/ao_telemini.c | 2 +- src/ao_telenano.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Makefile.proto b/src/Makefile.proto index 5322df17..309fd75d 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -195,7 +195,7 @@ TMINI_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry_tiny.c + ao_telemetry.c TMINI_MAIN_SRC = \ ao_telemini.c @@ -225,7 +225,7 @@ TNANO_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry_tiny.c + ao_telemetry.c TNANO_MAIN_SRC = \ ao_telenano.c diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index dcd0ff62..603a6791 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -77,9 +77,15 @@ ao_send_sensor(void) telemetry.sensor.height = ao_height; telemetry.sensor.ground_pres = ao_ground_pres; +#if HAS_ACCEL telemetry.sensor.ground_accel = ao_ground_accel; telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; +#else + telemetry.sensor.ground_accel = 0; + telemetry.sensor.accel_plus_g = 0; + telemetry.sensor.accel_minus_g = 0; +#endif ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/ao_telemini.c b/src/ao_telemini.c index dbc3b74c..19d03692 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -42,7 +42,7 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); - ao_telemetry_tiny_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telenano.c b/src/ao_telenano.c index 47b7b3c3..40822b6e 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -42,7 +42,7 @@ main(void) ao_flight_nano_init(); ao_log_init(); ao_report_init(); - ao_telemetry_tiny_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_config_init(); -- cgit v1.2.3 From 5ca6400fd8a360b64d8f96f50d5595a7fd17762d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:18:54 -0700 Subject: altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c All products use the common ao_telemetry.c code now Signed-off-by: Keith Packard --- src/ao_telemetry_orig.c | 105 ------------------------------------------------ src/ao_telemetry_tiny.c | 91 ----------------------------------------- 2 files changed, 196 deletions(-) delete mode 100644 src/ao_telemetry_orig.c delete mode 100644 src/ao_telemetry_tiny.c diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c deleted file mode 100644 index 4b3a344a..00000000 --- a/src/ao_telemetry_orig.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata uint16_t ao_telemetry_interval = 0; -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry_orig(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry_orig telemetry; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.serial = ao_serial_number; - telemetry.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.accel_plus_g = ao_config.accel_plus_g; - telemetry.accel_minus_g = ao_config.accel_minus_g; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - telemetry.flight_state = ao_flight_state; - telemetry.height = ao_height; - telemetry.u.k.speed = ao_speed; - telemetry.accel = ao_accel; - telemetry.u.k.unused = 0x8000; -#if HAS_ACCEL - telemetry.ground_accel = ao_ground_accel; -#endif - telemetry.ground_pres = ao_ground_pres; -#if HAS_ADC - ao_adc_get(&telemetry.adc); -#endif -#if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); -#endif - ao_radio_send(&telemetry, sizeof (telemetry)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - ao_wakeup(&ao_telemetry_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_orig_task; - -void -ao_telemetry_orig_init() -{ - ao_add_task(&ao_telemetry_orig_task, ao_telemetry_orig, "telemetry_orig"); -} diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c deleted file mode 100644 index 6f2ddda1..00000000 --- a/src/ao_telemetry_tiny.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; -__xdata uint16_t ao_telemetry_tiny_interval = 0; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry_tiny(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry_tiny telemetry_tiny; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry_tiny.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry_tiny.serial = ao_serial_number; - telemetry_tiny.flight = ao_log_full() ? 0 : ao_flight_number; - for (;;) { - while (ao_telemetry_tiny_interval == 0) - ao_sleep(&ao_telemetry_tiny_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_tiny_interval) { - telemetry_tiny.flight_state = ao_flight_state; - telemetry_tiny.height = ao_height; - telemetry_tiny.speed = ao_speed; - telemetry_tiny.accel = ao_accel; - telemetry_tiny.ground_pres = ao_ground_pres; - ao_adc_get(&telemetry_tiny.adc); - ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_tiny_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_tiny_interval = interval; - ao_wakeup(&ao_telemetry_tiny_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_tiny_task; - -void -ao_telemetry_tiny_init() -{ - ao_add_task(&ao_telemetry_tiny_task, ao_telemetry_tiny, "telemetry_tiny"); -} -- cgit v1.2.3 From 81cf2e833bedbc1ace8fd310e9e94bfb7673d428 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:43:17 -0700 Subject: altos: Ensure low-rate telem packets interleave with sensor telem packets To avoid over-committing the radio link, we want to send only one low rate packet after each sensor packet. However, the initializations for this were incorrect, causing the configuration and location packets to be sent at the same time. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 603a6791..172b6f17 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -194,13 +194,13 @@ ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; - ao_telemetry_config_cur = 0; + ao_telemetry_config_cur = 1; #if HAS_GPS - ao_telemetry_loc_cur = 0; - if (ao_telemetry_config_max - 1 > ao_telemetry_loc_cur) + ao_telemetry_loc_cur = 1; + if (ao_telemetry_config_max > ao_telemetry_loc_cur) ao_telemetry_loc_cur++; ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) + if (ao_telemetry_config_max > ao_telemetry_sat_cur) ao_telemetry_sat_cur++; #endif ao_wakeup(&telemetry); -- cgit v1.2.3 From 504ab7ab355652d5d01094c927089029596a0753 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 17:49:01 -0700 Subject: altos: product defines are always in ao_product.h When all products were built in a single directory, each one had a separate version of ao_product.h. Now that they all reside in sub-directories, each directory has its own ao_product.h This change is needed so that other modules in the system can use the product defines; otherwise, ao_product.h was not built at the right time. Signed-off-by: Keith Packard --- configure.ac | 2 +- src/Makefile.proto | 3 +-- src/ao_product.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 187af4fb..78f5adbb 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.1) +AC_INIT([altos], 0.9.4.2) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/Makefile.proto b/src/Makefile.proto index 309fd75d..d4a8c4ea 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -359,8 +359,7 @@ all: ../$(PROG) 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 - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +$(REL): ao_product.h distclean: clean diff --git a/src/ao_product.c b/src/ao_product.c index bb42e92c..fb59580b 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -16,7 +16,7 @@ */ #include "ao.h" -#include PRODUCT_DEFS +#include "ao_product.h" /* Defines which mark this particular AltOS product */ -- cgit v1.2.3 From 80ca066a825646f833ca609190c76c5252118d9a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 21:36:38 -0700 Subject: altosui: Build device constants into .java code This eliminates a depedency on updates to the system helper library, which means we don't have to provide a new library on all platforms just to support a new USB id. Signed-off-by: Keith Packard --- altosui/Altos.java | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 36490844..96263797 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -324,50 +324,42 @@ public class Altos { } static int usb_vendor_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_VENDOR_ALTUSMETRUM; - return 0x000a; + load_library(); + return 0xfffe; } static int usb_product_altusmetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM; + load_library(); return 0x000a; } static int usb_product_altusmetrum_min() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MIN; + load_library(); return 0x000a; } static int usb_product_altusmetrum_max() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_ALTUSMETRUM_MAX; - return 0x000d; + load_library(); + return 0x0013; } static int usb_product_telemetrum() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEMETRUM; + load_library(); return 0x000b; } static int usb_product_teledongle() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEDONGLE; + load_library(); return 0x000c; } static int usb_product_teleterra() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELETERRA; + load_library(); return 0x000d; } static int usb_product_telebt() { - if (load_library()) - return libaltosConstants.USB_PRODUCT_TELEBT; + load_library(); return 0x000e; } @@ -384,8 +376,7 @@ public class Altos { public final static int product_basestation = 0x10000 + 1; static String bt_product_telebt() { - if (load_library()) - return libaltosConstants.BLUETOOTH_PRODUCT_TELEBT; + load_library(); return "TeleBT"; } -- cgit v1.2.3 From 8f80f5705d64469bcfb00ff11aee68364edb271b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 21:38:57 -0700 Subject: altosui: Don't show missing igniter and gps values The new telemetry stuff leaves state.gps always set (but empty), which seems fine, we just need to look at state.gps.connected to see if there's a GPS receiver on board. For TeleNano, we also want to hide the igniter status fields as they won't have any data present. Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 41 +++++++++++++++++++++++++++++++++-------- altosui/AltosDescent.java | 17 ++++++++++++----- altosui/AltosFlightUI.java | 4 ++-- altosui/AltosInfoTable.java | 8 +++++--- altosui/AltosLanded.java | 6 +++--- altosui/AltosPad.java | 14 +++++++++++--- 6 files changed, 66 insertions(+), 24 deletions(-) diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 8a4aa58b..d607b0c5 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -36,6 +36,18 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { JTextField value; AltosLights lights; + void show() { + value.setVisible(true); + lights.setVisible(true); + label.setVisible(true); + } + + void hide() { + value.setVisible(false); + lights.setVisible(false); + label.setVisible(false); + } + void show(AltosState state, int crc_errors) {} void reset() { value.setText(""); @@ -136,14 +148,19 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { void reset() { value.setText(""); max_value.setText(""); - max = 0; + max = AltosRecord.MISSING; } void show(String format, double v) { - value.setText(String.format(format, v)); - if (v > max) { - max_value.setText(String.format(format, v)); - max = v; + if (v == AltosRecord.MISSING) { + value.setText("Missing"); + max_value.setText("Missing"); + } else { + value.setText(String.format(format, v)); + if (v > max || max == AltosRecord.MISSING) { + max_value.setText(String.format(format, v)); + max = v; + } } } public AscentValueHold (GridBagLayout layout, int y, String text) { @@ -233,6 +250,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Apogee extends AscentStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.drogue_sense)); lights.set(state.drogue_sense > 3.2); } @@ -245,6 +263,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Main extends AscentStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.main_sense)); lights.set(state.main_sense > 3.2); } @@ -296,7 +315,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - if (state.gps != null) { + if (state.gps != null && state.gps.connected) { lat.show(state, crc_errors); lon.show(state, crc_errors); } else { @@ -304,8 +323,14 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lon.hide(); } height.show(state, crc_errors); - main.show(state, crc_errors); - apogee.show(state, crc_errors); + if (state.main_sense != AltosRecord.MISSING) + main.show(state, crc_errors); + else + main.hide(); + if (state.drogue_sense != AltosRecord.MISSING) + apogee.show(state, crc_errors); + else + apogee.hide(); speed.show(state, crc_errors); accel.show(state, crc_errors); } diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index addd6878..2a9e7eef 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -258,7 +258,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Lat extends DescentValue { void show (AltosState state, int crc_errors) { - if (state.gps != null) + if (state.gps != null && state.gps.connected) show(pos(state.gps.lat,"N", "S")); else show("???"); @@ -272,7 +272,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Lon extends DescentValue { void show (AltosState state, int crc_errors) { - if (state.gps != null) + if (state.gps != null && state.gps.connected) show(pos(state.gps.lon,"W", "E")); else show("???"); @@ -286,6 +286,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Apogee extends DescentStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.drogue_sense)); lights.set(state.drogue_sense > 3.2); } @@ -363,7 +364,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { height.show(state, crc_errors); speed.show(state, crc_errors); - if (state.gps != null) { + if (state.gps != null && state.gps.connected) { bearing.show(state, crc_errors); range.show(state, crc_errors); elevation.show(state, crc_errors); @@ -376,8 +377,14 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { lat.hide(); lon.hide(); } - main.show(state, crc_errors); - apogee.show(state, crc_errors); + if (state.main_sense != AltosRecord.MISSING) + main.show(state, crc_errors); + else + main.hide(); + if (state.drogue_sense != AltosRecord.MISSING) + apogee.show(state, crc_errors); + else + apogee.hide(); } public AltosDescent() { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 5f1fc678..9536c4bb 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -156,8 +156,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { // Telemetry format menu telemetries = new JComboBox(); - telemetries.addItem("Legacy TeleMetrum"); - telemetries.addItem("Split Telemetry"); + telemetries.addItem("Original TeleMetrum Telemetry"); + telemetries.addItem("Standard AltOS Telemetry"); int telemetry = 1; telemetry = AltosPreferences.telemetry(serial); if (telemetry > Altos.ao_telemetry_split) diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 723f8301..8ebeaba1 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -107,10 +107,12 @@ public class AltosInfoTable extends JTable { info_add_row(0, "Max Speed", "%8.1f m/s", state.max_speed); info_add_row(0, "Temperature", "%9.2f °C", state.temperature); info_add_row(0, "Battery", "%9.2f V", state.battery); - info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); - info_add_row(0, "Main", "%9.2f V", state.main_sense); + if (state.drogue_sense != AltosRecord.MISSING) + info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); + if (state.main_sense != AltosRecord.MISSING) + info_add_row(0, "Main", "%9.2f V", state.main_sense); info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); - if (state.gps == null) { + if (state.gps == null || !state.gps.connected) { info_add_row(1, "GPS", "not available"); } else { if (state.gps_ready) diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 63a2daf6..d5c8e434 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -99,7 +99,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lat extends LandedValue { void show (AltosState state, int crc_errors) { show(); - if (state.gps != null) + if (state.gps != null && state.gps.connected) value.setText(pos(state.gps.lat,"N", "S")); else value.setText("???"); @@ -114,7 +114,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lon extends LandedValue { void show (AltosState state, int crc_errors) { show(); - if (state.gps != null) + if (state.gps != null && state.gps.connected) value.setText(pos(state.gps.lon,"E", "W")); else value.setText("???"); @@ -200,7 +200,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - if (state.gps != null) { + if (state.gps != null && state.gps.connected) { bearing.show(state, crc_errors); distance.show(state, crc_errors); lat.show(state, crc_errors); diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 2d800e8a..d08925be 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -149,6 +149,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class Apogee extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.drogue_sense)); lights.set(state.drogue_sense > 3.2); } @@ -161,6 +162,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class Main extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.main_sense)); lights.set(state.main_sense > 3.2); } @@ -259,10 +261,16 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { battery.show(state, crc_errors); - apogee.show(state, crc_errors); - main.show(state, crc_errors); + if (state.drogue_sense == AltosRecord.MISSING) + apogee.hide(); + else + apogee.show(state, crc_errors); + if (state.main_sense == AltosRecord.MISSING) + main.hide(); + else + main.show(state, crc_errors); pad_alt.show(state, crc_errors); - if (state.gps != null) { + if (state.gps != null && state.gps.connected) { gps_locked.show(state, crc_errors); gps_ready.show(state, crc_errors); pad_lat.show(state, crc_errors); -- cgit v1.2.3 From 0d0cf6f9a1b14a1b66aee3845964cd33d1f035c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 13:09:57 -0700 Subject: altos: new versions of sdcc require __ prefixes for custom keywords Fortunately, 2.9.1 appears to accept either, so we can switch now and prepare for sdcc 3.0.0. Signed-off-by: Keith Packard --- src/ao_task.c | 2 +- src/cc1111.h | 148 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/ao_task.c b/src/ao_task.c index 7e34ed61..f5850fa4 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -78,7 +78,7 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam /* Task switching function. This must not use any stack variables */ void -ao_yield(void) _naked +ao_yield(void) __naked { /* Save current context */ diff --git a/src/cc1111.h b/src/cc1111.h index 5b018cb5..e52aa79f 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,7 +40,7 @@ #include #include -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 */ @@ -60,7 +60,7 @@ sbit __at 0xAF EA; /* Enable All */ #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 */ @@ -70,7 +70,7 @@ sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #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 */ @@ -82,7 +82,7 @@ sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ #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) @@ -126,14 +126,14 @@ sfr __at 0xC6 CLKCON; /* Clock Control */ #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 */ @@ -150,7 +150,7 @@ sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically clea /* * 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. */ @@ -161,7 +161,7 @@ sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ /* * 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) @@ -169,7 +169,7 @@ sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ /* * 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 */ @@ -190,7 +190,7 @@ sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ /* * 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) */ @@ -225,8 +225,8 @@ sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ * 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) @@ -286,13 +286,13 @@ sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ */ /* 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) @@ -312,10 +312,10 @@ sfr __at 0xEB T4CTL; /* 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) @@ -328,16 +328,16 @@ sfr __at 0xEE T4CCTL1; #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) @@ -442,12 +442,12 @@ __xdata __at (0xde17) volatile uint8_t USBCNTH; __xdata __at (0xde20) volatile uint8_t USBFIFO[12]; /* ADC Data register, low and high */ -sfr at 0xBA ADCL; -sfr at 0xBB ADCH; +__sfr at 0xBA ADCL; +__sfr at 0xBB ADCH; __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; /* ADC Control Register 1 */ -sfr at 0xB4 ADCCON1; +__sfr at 0xB4 ADCCON1; # define ADCCON1_EOC (1 << 7) /* conversion complete */ # define ADCCON1_ST (1 << 6) /* start conversion */ @@ -463,7 +463,7 @@ sfr at 0xB4 ADCCON1; # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ /* ADC Control Register 2 */ -sfr at 0xB5 ADCCON2; +__sfr at 0xB5 ADCCON2; # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ @@ -498,7 +498,7 @@ sfr at 0xB5 ADCCON2; /* ADC Control Register 3 */ -sfr at 0xB6 ADCCON3; +__sfr at 0xB6 ADCCON3; # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ @@ -533,13 +533,13 @@ sfr at 0xB6 ADCCON3; * ADC configuration register, this selects which * GPIO pins are to be used as ADC inputs */ -sfr at 0xF2 ADCCFG; +__sfr at 0xF2 ADCCFG; /* * Watchdog timer */ -sfr at 0xc9 WDCTL; +__sfr at 0xc9 WDCTL; #define WDCTL_CLEAR_FIRST (0xa << 4) #define WDCTL_CLEAR_SECOND (0x5 << 4) @@ -556,9 +556,9 @@ sfr at 0xc9 WDCTL; * Pin selectors, these set which pins are * using their peripheral function */ -sfr at 0xF3 P0SEL; -sfr at 0xF4 P1SEL; -sfr at 0xF5 P2SEL; +__sfr at 0xF3 P0SEL; +__sfr at 0xF4 P1SEL; +__sfr at 0xF5 P2SEL; #define P2SEL_PRI3P1_USART0 (0 << 6) #define P2SEL_PRI3P1_USART1 (1 << 6) @@ -585,9 +585,9 @@ sfr at 0xF5 P2SEL; /* * For pins used as GPIOs, these set which are used as outputs */ -sfr at 0xFD P0DIR; -sfr at 0xFE P1DIR; -sfr at 0xFF P2DIR; +__sfr at 0xFD P0DIR; +__sfr at 0xFE P1DIR; +__sfr at 0xFF P2DIR; #define P2DIR_PRIP0_USART0_USART1 (0 << 6) #define P2DIR_PRIP0_USART1_USART0 (1 << 6) @@ -595,7 +595,7 @@ sfr at 0xFF P2DIR; #define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) #define P2DIR_PRIP0_MASK (3 << 6) -sfr at 0x8F P0INP; +__sfr at 0x8F P0INP; /* Select between tri-state and pull up/down * for pins P0_0 - P0_7. @@ -617,7 +617,7 @@ sfr at 0x8F P0INP; #define P0INP_MDP0_0_PULL (0 << 0) #define P0INP_MDP0_0_TRISTATE (1 << 0) -sfr at 0xF6 P1INP; +__sfr at 0xF6 P1INP; /* Select between tri-state and pull up/down * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are @@ -636,7 +636,7 @@ sfr at 0xF6 P1INP; #define P1INP_MDP1_2_PULL (0 << 2) #define P1INP_MDP1_2_TRISTATE (1 << 2) -sfr at 0xF7 P2INP; +__sfr at 0xF7 P2INP; /* P2INP has three extra bits which are used to choose * between pull-up and pull-down when they are not tri-stated */ @@ -662,13 +662,13 @@ sfr at 0xF7 P2INP; #define P2INP_MDP2_0_TRISTATE (1 << 0) /* GPIO interrupt status flags */ -sfr at 0x89 P0IFG; -sfr at 0x8A P1IFG; -sfr at 0x8B P2IFG; +__sfr at 0x89 P0IFG; +__sfr at 0x8A P1IFG; +__sfr at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) -sfr at 0x8C PICTL; +__sfr at 0x8C PICTL; #define PICTL_P2IEN (1 << 5) #define PICTL_P0IENH (1 << 4) #define PICTL_P0IENL (1 << 3) @@ -677,7 +677,7 @@ sfr at 0x8C PICTL; #define PICTL_P0ICON (1 << 0) /* GPIO pins */ -sfr at 0x80 P0; +__sfr at 0x80 P0; sbit at 0x80 P0_0; sbit at 0x81 P0_1; @@ -688,7 +688,7 @@ sbit at 0x85 P0_5; sbit at 0x86 P0_6; sbit at 0x87 P0_7; -sfr at 0x90 P1; +__sfr at 0x90 P1; sbit at 0x90 P1_0; sbit at 0x91 P1_1; @@ -699,7 +699,7 @@ sbit at 0x95 P1_5; sbit at 0x96 P1_6; sbit at 0x97 P1_7; -sfr at 0xa0 P2; +__sfr at 0xa0 P2; sbit at 0xa0 P2_0; sbit at 0xa1 P2_1; @@ -794,7 +794,7 @@ struct cc_dma_channel { * DMAARM - DMA Channel Arm */ -sfr at 0xD6 DMAARM; +__sfr at 0xD6 DMAARM; # define DMAARM_ABORT (1 << 7) # define DMAARM_DMAARM4 (1 << 4) @@ -807,7 +807,7 @@ sfr at 0xD6 DMAARM; * DMAREQ - DMA Channel Start Request and Status */ -sfr at 0xD7 DMAREQ; +__sfr at 0xD7 DMAREQ; # define DMAREQ_DMAREQ4 (1 << 4) # define DMAREQ_DMAREQ3 (1 << 3) @@ -819,21 +819,21 @@ sfr at 0xD7 DMAREQ; * DMA configuration 0 address */ -sfr at 0xD5 DMA0CFGH; -sfr at 0xD4 DMA0CFGL; +__sfr at 0xD5 DMA0CFGH; +__sfr at 0xD4 DMA0CFGL; /* * DMA configuration 1-4 address */ -sfr at 0xD3 DMA1CFGH; -sfr at 0xD2 DMA1CFGL; +__sfr at 0xD3 DMA1CFGH; +__sfr at 0xD2 DMA1CFGL; /* * DMAIRQ - DMA Interrupt Flag */ -sfr at 0xD1 DMAIRQ; +__sfr at 0xD1 DMAIRQ; # define DMAIRQ_DMAIF4 (1 << 4) # define DMAIRQ_DMAIF3 (1 << 3) @@ -846,8 +846,8 @@ sfr at 0xD1 DMAIRQ; */ /* USART config/status registers */ -sfr at 0x86 U0CSR; -sfr at 0xF8 U1CSR; +__sfr at 0x86 U0CSR; +__sfr at 0xF8 U1CSR; # define UxCSR_MODE_UART (1 << 7) # define UxCSR_MODE_SPI (0 << 7) @@ -861,8 +861,8 @@ sfr at 0xF8 U1CSR; # define UxCSR_ACTIVE (1 << 0) /* UART configuration registers */ -sfr at 0xc4 U0UCR; -sfr at 0xfb U1UCR; +__sfr at 0xc4 U0UCR; +__sfr at 0xfb U1UCR; # define UxUCR_FLUSH (1 << 7) # define UxUCR_FLOW_DISABLE (0 << 6) @@ -881,8 +881,8 @@ sfr at 0xfb U1UCR; # define UxUCR_START_HIGH (1 << 0) /* USART General configuration registers (mostly SPI) */ -sfr at 0xc5 U0GCR; -sfr at 0xfc U1GCR; +__sfr at 0xc5 U0GCR; +__sfr at 0xfc U1GCR; # define UxGCR_CPOL_NEGATIVE (0 << 7) # define UxGCR_CPOL_POSITIVE (1 << 7) @@ -894,18 +894,18 @@ sfr at 0xfc U1GCR; # define UxGCR_BAUD_E_SHIFT 0 /* USART data registers */ -sfr at 0xc1 U0DBUF; +__sfr at 0xc1 U0DBUF; __xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -sfr at 0xf9 U1DBUF; +__sfr at 0xf9 U1DBUF; __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; /* USART baud rate registers, M value */ -sfr at 0xc2 U0BAUD; -sfr at 0xfa U1BAUD; +__sfr at 0xc2 U0BAUD; +__sfr at 0xfa U1BAUD; /* Flash controller */ -sfr at 0xAE FCTL; +__sfr at 0xAE FCTL; #define FCTL_BUSY (1 << 7) #define FCTL_SWBSY (1 << 6) #define FCTL_CONTRD_ENABLE (1 << 4) @@ -913,22 +913,22 @@ sfr at 0xAE FCTL; #define FCTL_ERASE (1 << 0) /* Flash write data. Write two bytes here */ -sfr at 0xAF FWDATA; +__sfr at 0xAF FWDATA; __xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; /* Flash write/erase address */ -sfr at 0xAD FADDRH; -sfr at 0xAC FADDRL; +__sfr at 0xAD FADDRH; +__sfr at 0xAC FADDRL; /* Flash timing */ -sfr at 0xAB FWT; +__sfr at 0xAB FWT; /* Radio */ -sfr at 0xD9 RFD; +__sfr at 0xD9 RFD; __xdata at (0xDFD9) volatile uint8_t RFDXADDR; -sfr at 0xE9 RFIF; +__sfr at 0xE9 RFIF; #define RFIF_IM_TXUNF (1 << 7) #define RFIF_IM_RXOVF (1 << 6) #define RFIF_IM_TIMEOUT (1 << 5) @@ -938,7 +938,7 @@ sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) -sfr at 0x91 RFIM; +__sfr at 0x91 RFIM; #define RFIM_IM_TXUNF (1 << 7) #define RFIM_IM_RXOVF (1 << 6) #define RFIM_IM_TIMEOUT (1 << 5) @@ -948,7 +948,7 @@ sfr at 0x91 RFIM; #define RFIM_IM_CCA (1 << 1) #define RFIM_IM_SFD (1 << 0) -sfr at 0xE1 RFST; +__sfr at 0xE1 RFST; #define RFST_SFSTXON 0x00 #define RFST_SCAL 0x01 -- cgit v1.2.3 From 7bb11b716ccb6c80701bc3f34ecf9bef97cbbfc9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jul 2011 18:53:41 -0700 Subject: Set version to 0.9.4.3 for Bdale 2011-7-16 flights Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 78f5adbb..cee1b833 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.2) +AC_INIT([altos], 0.9.4.3) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 8c20030ea4eb8e068e1ba88e01d07dfbc27bd7db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 18:41:15 -0700 Subject: altosui: Start adding support for scanning radio for available devices This is untested. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 365 +++++++++++++++++++++++++++++++++++++++++++++++ altosui/AltosUI.java | 12 ++ altosui/Makefile.am | 1 + 3 files changed, 378 insertions(+) create mode 100644 altosui/AltosScanUI.java diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java new file mode 100644 index 00000000..e55f317c --- /dev/null +++ b/altosui/AltosScanUI.java @@ -0,0 +1,365 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 java.util.concurrent.*; + +class AltosScanResult { + String callsign; + int serial; + int flight; + int channel; + int telemetry; + boolean interrupted = false; + + public String toString() { + return String.format("%-9.9s %4d %4d %2d %2d", + callsign, serial, flight, channel, telemetry); + } + + public String toShortString() { + return String.format("%s %d %d %d %d", + callsign, serial, flight, channel, telemetry); + } + + public AltosScanResult(String in_callsign, int in_serial, + int in_flight, int in_channel, int in_telemetry) { + callsign = in_callsign; + serial = in_serial; + flight = in_flight; + channel = in_channel; + telemetry = in_telemetry; + } + + public boolean equals(AltosScanResult other) { + return (callsign.equals(other.callsign) && + serial == other.serial && + flight == other.flight && + channel == other.channel && + telemetry == other.telemetry); + } +} + +class AltosScanResults extends LinkedList implements ListModel { + + LinkedList listeners = new LinkedList(); + + public boolean add(AltosScanResult r) { + for (AltosScanResult old : this) + if (old.equals(r)) + return true; + + super.add(r); + ListDataEvent de = new ListDataEvent(this, + ListDataEvent.INTERVAL_ADDED, + this.size() - 2, this.size() - 1); + for (ListDataListener l : listeners) + l.contentsChanged(de); + return true; + } + + public void addListDataListener(ListDataListener l) { + listeners.add(l); + } + + public void removeListDataListener(ListDataListener l) { + listeners.remove(l); + } + + public AltosScanResult getElementAt(int i) { + return this.get(i); + } + + public int getSize() { + return this.size(); + } +} + +public class AltosScanUI + extends JDialog + implements ActionListener +{ + JFrame owner; + AltosDevice device; + AltosTelemetryReader reader; + private JList list; + private JLabel channel_label; + private JLabel monitor_label; + private JButton ok_button; + javax.swing.Timer timer; + AltosScanResults results = new AltosScanResults(); + + static final int[] monitors = { Altos.ao_telemetry_split_len, + Altos.ao_telemetry_legacy_len }; + int monitor; + int channel; + + final static int timeout = 5 * 1000; + TelemetryHandler handler; + Thread thread; + + void scan_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); + } + + class TelemetryHandler implements Runnable { + + public void run() { + + boolean interrupted = false; + + try { + for (;;) { + try { + AltosRecord record = reader.read(); + if (record == null) + break; + if ((record.seen & AltosRecord.seen_flight) != 0) { + AltosScanResult result = new AltosScanResult(record.callsign, + record.serial, + record.flight, + channel, + monitor); + results.add(result); + } + } catch (ParseException pp) { + System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); + } catch (AltosCRCException ce) { + } + } + } catch (InterruptedException ee) { + interrupted = true; + } catch (IOException ie) { + } finally { + reader.close(interrupted); + } + } + } + + void set_channel() { + reader.serial.set_channel(channel); + } + + void set_monitor() { + reader.serial.set_telemetry(monitors[monitor]); + } + + void next() { + ++channel; + if (channel == 10) { + channel = 0; + ++monitor; + if (monitor == monitors.length) + monitor = 0; + set_monitor(); + } + set_channel(); + } + + + void close() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + if (timer != null) + timer.stop(); + setVisible(false); + dispose(); + } + + void tick_timer() { + next(); + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) { + close(); + } + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosScanUI ui; + + public ConfigListener(AltosScanUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + device = AltosDeviceDialog.show(owner, Altos.product_any); + if (device != null) { + try { + reader = new AltosTelemetryReader(device); + set_channel(); + set_monitor(); + handler = new TelemetryHandler(); + thread = new Thread(handler); + thread.start(); + return true; + } catch (Exception e) { + scan_exception(e); + } + } + return false; + } + + public AltosScanUI(JFrame in_owner) { + + owner = in_owner; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + timer = new javax.swing.Timer(timeout, this); + timer.setActionCommand("tick"); + timer.restart(); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + c.anchor = GridBagConstraints.CENTER; + + list = new JList(results) { + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + }; + + list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + list.setLayoutOrientation(JList.HORIZONTAL_WRAP); + list.setVisibleRowCount(-1); + +// list.addMouseListener(new MouseAdapter() { +// public void mouseClicked(MouseEvent e) { +// if (e.getClickCount() == 2) { +// select_button.doClick(); //emulate button click +// } +// } +// }); + JScrollPane listScroller = new JScrollPane(list); + listScroller.setPreferredSize(new Dimension(400, 80)); + listScroller.setAlignmentX(LEFT_ALIGNMENT); + + //Create a container so that we can add a title around + //the scroll pane. Can't add a title directly to the + //scroll pane because its background would be white. + //Lay out the label and scroll pane from top to bottom. + JPanel listPane = new JPanel(); + listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS)); + + JLabel label = new JLabel("Select Device"); + label.setLabelFor(list); + listPane.add(label); + listPane.add(Box.createRigidArea(new Dimension(0,5))); + listPane.add(listScroller); + listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + pane.add(listPane, c); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + } +} \ No newline at end of file diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 7bb4ba12..6a24d8a9 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -172,6 +172,14 @@ public class AltosUI extends JFrame { } }); + + b = addButton(0, 2, "Scan Channels"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + ScanChannels(); + } + }); + setTitle("AltOS"); pane.doLayout(); @@ -226,6 +234,10 @@ public class AltosUI extends JFrame { new AltosIgniteUI(AltosUI.this); } + void ScanChannels() { + new AltosScanUI(AltosUI.this); + } + /* * Replay a flight from telemetry data */ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 6e64acab..0a3ed0b1 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -83,6 +83,7 @@ altosui_JAVA = \ AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ + AltosScanUI.java \ AltosSerial.java \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ -- cgit v1.2.3 From f32a55ac9a3ebbde2b41782f22491e72258fe05a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 19:00:12 -0700 Subject: altosui: Pop up monitor window from scan dialog Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 120 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 23 deletions(-) diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index e55f317c..01b01720 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,6 +35,7 @@ class AltosScanResult { int flight; int channel; int telemetry; + boolean interrupted = false; public String toString() { @@ -104,12 +105,14 @@ public class AltosScanUI extends JDialog implements ActionListener { - JFrame owner; + AltosUI owner; AltosDevice device; AltosTelemetryReader reader; private JList list; private JLabel channel_label; private JLabel monitor_label; + private JButton fake_button; + private JButton cancel_button; private JButton ok_button; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); @@ -228,8 +231,26 @@ public class AltosScanUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("close")) { + if (cmd.equals("fake")) { + results.add(new AltosScanResult("N0CALL", 300, 1, 0, 1)); + } + + if (cmd.equals("cancel")) { + close(); + } + + if (cmd.equals("ok")) { close(); + AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); + System.out.printf("Selected channel %d telemetry %d\n", + r.channel, r.telemetry); + if (device != null) { + if (reader != null) { + reader.set_telemetry(r.telemetry); + reader.set_channel(r.channel); + owner.telemetry_window(device); + } + } } } @@ -266,12 +287,12 @@ public class AltosScanUI return false; } - public AltosScanUI(JFrame in_owner) { + public AltosScanUI(AltosUI in_owner) { owner = in_owner; - if (!open()) - return; +// if (!open()) +// return; Container pane = getContentPane(); GridBagConstraints c = new GridBagConstraints(); @@ -285,17 +306,6 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 3; - c.anchor = GridBagConstraints.CENTER; - list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning @@ -330,13 +340,13 @@ public class AltosScanUI list.setLayoutOrientation(JList.HORIZONTAL_WRAP); list.setVisibleRowCount(-1); -// list.addMouseListener(new MouseAdapter() { -// public void mouseClicked(MouseEvent e) { -// if (e.getClickCount() == 2) { -// select_button.doClick(); //emulate button click -// } -// } -// }); + list.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + ok_button.doClick(); //emulate button click + } + } + }); JScrollPane listScroller = new JScrollPane(list); listScroller.setPreferredSize(new Dimension(400, 80)); listScroller.setAlignmentX(LEFT_ALIGNMENT); @@ -355,11 +365,75 @@ public class AltosScanUI listPane.add(listScroller); listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 3; + c.anchor = GridBagConstraints.CENTER; + pane.add(listPane, c); + fake_button = new JButton("fake"); + fake_button.addActionListener(this); + fake_button.setActionCommand("fake"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(fake_button, c); + + cancel_button = new JButton("Cancel"); + cancel_button.addActionListener(this); + cancel_button.setActionCommand("cancel"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(cancel_button, c); + + ok_button = new JButton("OK"); + ok_button.addActionListener(this); + ok_button.setActionCommand("ok"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 2; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(ok_button, c); + pack(); setLocationRelativeTo(owner); addWindowListener(new ConfigListener(this)); + + setVisible(true); } } \ No newline at end of file -- cgit v1.2.3 From d4375bc737655546c2d40f49acdfc2e60ebfea5a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:19:14 -0700 Subject: altosui: Remove debugging printf from AltosLog Signed-off-by: Keith Packard --- altosui/AltosLog.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java index 855ee2b4..6157a656 100644 --- a/altosui/AltosLog.java +++ b/altosui/AltosLog.java @@ -88,7 +88,6 @@ class AltosLog implements Runnable { close_log_file(); serial = telem.serial; flight = telem.flight; - System.out.printf("Opening telem %d %d\n", serial, flight); open(telem); } previous = telem; -- cgit v1.2.3 From ebcba28b3c09925869b617880d2919e5d0e059f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:19:41 -0700 Subject: altosui: Configuration telemetry record includes flight number Mark the reported altos record as including flight information. Signed-off-by: Keith Packard --- altosui/AltosTelemetryRecordConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosTelemetryRecordConfiguration.java b/altosui/AltosTelemetryRecordConfiguration.java index 98dc6ab9..b029d120 100644 --- a/altosui/AltosTelemetryRecordConfiguration.java +++ b/altosui/AltosTelemetryRecordConfiguration.java @@ -57,7 +57,7 @@ public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { next.callsign = callsign; next.firmware_version = version; - next.seen |= AltosRecord.seen_deploy; + next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight; return next; } -- cgit v1.2.3 From 7ef786276b5d5c7d17c3fe4f36aa41db61a9742f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:23:08 -0700 Subject: altosui: Finish radio scanning UI Scans all channels and telemetry formats, presenting visible devices in a list. Entries from the list may be selected, in which case a monitor window pops up with the appropriate configuration. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 183 ++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 80 deletions(-) diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 01b01720..d94ac3ae 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,12 +35,13 @@ class AltosScanResult { int flight; int channel; int telemetry; + static final String[] short_monitor_names = { "Standard", "Original" }; boolean interrupted = false; public String toString() { - return String.format("%-9.9s %4d %4d %2d %2d", - callsign, serial, flight, channel, telemetry); + return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d telemetry %s)", + callsign, serial, flight, channel, short_monitor_names[telemetry]); } public String toShortString() { @@ -109,20 +110,18 @@ public class AltosScanUI AltosDevice device; AltosTelemetryReader reader; private JList list; - private JLabel channel_label; - private JLabel monitor_label; - private JButton fake_button; + private JLabel scanning_label; private JButton cancel_button; - private JButton ok_button; + private JButton monitor_button; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); - static final int[] monitors = { Altos.ao_telemetry_split_len, - Altos.ao_telemetry_legacy_len }; + static final String[] monitor_names = { "Standard AltOS Telemetry", "Original TeleMetrum Telemetry" }; + static final int[] monitors = { 2, 1 }; int monitor; int channel; - final static int timeout = 5 * 1000; + final static int timeout = 1200; TelemetryHandler handler; Thread thread; @@ -166,17 +165,21 @@ public class AltosScanUI try { AltosRecord record = reader.read(); if (record == null) - break; + continue; if ((record.seen & AltosRecord.seen_flight) != 0) { - AltosScanResult result = new AltosScanResult(record.callsign, + final AltosScanResult result = new AltosScanResult(record.callsign, record.serial, record.flight, channel, monitor); - results.add(result); + Runnable r = new Runnable() { + public void run() { + results.add(result); + } + }; + SwingUtilities.invokeLater(r); } } catch (ParseException pp) { - System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); } catch (AltosCRCException ce) { } } @@ -189,24 +192,29 @@ public class AltosScanUI } } - void set_channel() { - reader.serial.set_channel(channel); - } - - void set_monitor() { - reader.serial.set_telemetry(monitors[monitor]); + void set_label() { + scanning_label.setText(String.format("Scanning: channel %d %s", + channel, + monitor_names[monitor])); } void next() { + reader.serial.set_monitor(false); + try { + Thread.sleep(100); + } catch (InterruptedException ie){ + } ++channel; - if (channel == 10) { + if (channel > 9) { channel = 0; ++monitor; if (monitor == monitors.length) monitor = 0; - set_monitor(); + reader.serial.set_telemetry(monitors[monitor]); } - set_channel(); + reader.serial.set_channel(channel); + set_label(); + reader.serial.set_monitor(true); } @@ -231,24 +239,22 @@ public class AltosScanUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("fake")) { - results.add(new AltosScanResult("N0CALL", 300, 1, 0, 1)); - } - - if (cmd.equals("cancel")) { + if (cmd.equals("cancel")) close(); - } - if (cmd.equals("ok")) { + if (cmd.equals("tick")) + tick_timer(); + + if (cmd.equals("monitor")) { close(); AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); - System.out.printf("Selected channel %d telemetry %d\n", - r.channel, r.telemetry); - if (device != null) { - if (reader != null) { - reader.set_telemetry(r.telemetry); - reader.set_channel(r.channel); - owner.telemetry_window(device); + if (r != null) { + if (device != null) { + if (reader != null) { + reader.set_telemetry(monitors[r.telemetry]); + reader.set_channel(r.channel); + owner.telemetry_window(device); + } } } } @@ -270,20 +276,37 @@ public class AltosScanUI } private boolean open() { - device = AltosDeviceDialog.show(owner, Altos.product_any); - if (device != null) { - try { - reader = new AltosTelemetryReader(device); - set_channel(); - set_monitor(); - handler = new TelemetryHandler(); - thread = new Thread(handler); - thread.start(); - return true; - } catch (Exception e) { - scan_exception(e); - } + device = AltosDeviceDialog.show(owner, Altos.product_basestation); + if (device == null) + return false; + try { + reader = new AltosTelemetryReader(device); + reader.serial.set_channel(channel); + reader.serial.set_telemetry(monitors[monitor]); + handler = new TelemetryHandler(); + thread = new Thread(handler); + thread.start(); + return true; + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Unkonwn I/O error", + JOptionPane.ERROR_MESSAGE); } + if (reader != null) + reader.close(false); return false; } @@ -291,8 +314,8 @@ public class AltosScanUI owner = in_owner; -// if (!open()) -// return; + if (!open()) + return; Container pane = getContentPane(); GridBagConstraints c = new GridBagConstraints(); @@ -306,6 +329,23 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); + scanning_label = new JLabel("Scanning:"); + + set_label(); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + + pane.add(scanning_label, c); + list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning @@ -343,7 +383,7 @@ public class AltosScanUI list.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { - ok_button.doClick(); //emulate button click + monitor_button.doClick(); //emulate button click } } }); @@ -365,24 +405,7 @@ public class AltosScanUI listPane.add(listScroller); listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - c.weightx = 1; - c.weighty = 1; - - c.gridx = 0; - c.gridy = 0; - c.gridwidth = 3; - c.anchor = GridBagConstraints.CENTER; - - pane.add(listPane, c); - - fake_button = new JButton("fake"); - fake_button.addActionListener(this); - fake_button.setActionCommand("fake"); - - c.fill = GridBagConstraints.NONE; + c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = i; c.weightx = 1; @@ -390,10 +413,10 @@ public class AltosScanUI c.gridx = 0; c.gridy = 1; - c.gridwidth = 1; + c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; - pane.add(fake_button, c); + pane.add(listPane, c); cancel_button = new JButton("Cancel"); cancel_button.addActionListener(this); @@ -405,16 +428,16 @@ public class AltosScanUI c.weightx = 1; c.weighty = 1; - c.gridx = 1; - c.gridy = 1; + c.gridx = 0; + c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; pane.add(cancel_button, c); - ok_button = new JButton("OK"); - ok_button.addActionListener(this); - ok_button.setActionCommand("ok"); + monitor_button = new JButton("Monitor"); + monitor_button.addActionListener(this); + monitor_button.setActionCommand("monitor"); c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -422,12 +445,12 @@ public class AltosScanUI c.weightx = 1; c.weighty = 1; - c.gridx = 2; - c.gridy = 1; + c.gridx = 1; + c.gridy = 2; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; - pane.add(ok_button, c); + pane.add(monitor_button, c); pack(); setLocationRelativeTo(owner); -- cgit v1.2.3 From 941b90a4905e34936d24a25ca90ac04eb6f5a792 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 17:38:00 -0700 Subject: altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry Move telemetry constants to Altos class, adding functions to compute names and lengths. Generalize users of these values to use all of the known values. Add support for v0.8 TeleMetrum telemetry Signed-off-by: Keith Packard --- altosui/Altos.java | 34 +++++++++++++++++++++++++++++---- altosui/AltosFlightUI.java | 14 +++++++------- altosui/AltosPreferences.java | 2 +- altosui/AltosScanUI.java | 28 +++++++++++++-------------- altosui/AltosSerial.java | 10 ++-------- altosui/AltosTelemetryRecordLegacy.java | 20 ++++++++++++------- altosui/AltosTelemetryRecordRaw.java | 7 +++++-- 7 files changed, 72 insertions(+), 43 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 96263797..8d5916ad 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -70,11 +70,23 @@ public class Altos { /* Telemetry modes */ static final int ao_telemetry_off = 0; - static final int ao_telemetry_legacy = 1; - static final int ao_telemetry_split = 2; + static final int ao_telemetry_min = 1; + static final int ao_telemetry_standard = 1; + static final int ao_telemetry_0_9 = 2; + static final int ao_telemetry_0_8 = 3; + static final int ao_telemetry_max = 3; + + static final String[] ao_telemetry_name = { + "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" + }; + + static final int ao_telemetry_standard_len = 32; + static final int ao_telemetry_0_9_len = 95; + static final int ao_telemetry_0_8_len = 94; - static final int ao_telemetry_split_len = 32; - static final int ao_telemetry_legacy_len = 95; + static final int[] ao_telemetry_len = { + 0, 32, 95, 94 + }; static HashMap string_to_state = new HashMap(); @@ -103,6 +115,20 @@ public class Altos { map_initialized = true; } + static int telemetry_len(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_len[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + static String telemetry_name(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_name[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + static String[] state_to_string = { "startup", "idle", diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 9536c4bb..04bfc90d 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -156,14 +156,14 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { // Telemetry format menu telemetries = new JComboBox(); - telemetries.addItem("Original TeleMetrum Telemetry"); - telemetries.addItem("Standard AltOS Telemetry"); - int telemetry = 1; - telemetry = AltosPreferences.telemetry(serial); - if (telemetry > Altos.ao_telemetry_split) - telemetry = Altos.ao_telemetry_split; + for (int i = 1; i <= Altos.ao_telemetry_max; i++) + telemetries.addItem(Altos.telemetry_name(i)); + int telemetry = AltosPreferences.telemetry(serial); + if (telemetry <= Altos.ao_telemetry_off || + telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_standard; telemetries.setSelectedIndex(telemetry - 1); - telemetries.setMaximumRowCount(2); + telemetries.setMaximumRowCount(Altos.ao_telemetry_max); telemetries.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int telemetry = telemetries.getSelectedIndex() + 1; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 5029aff6..c8dee743 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -216,7 +216,7 @@ class AltosPreferences { if (telemetries.containsKey(serial)) return telemetries.get(serial); int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - Altos.ao_telemetry_split); + Altos.ao_telemetry_standard); telemetries.put(serial, telemetry); return telemetry; } diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index d94ac3ae..54be4f52 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -35,13 +35,12 @@ class AltosScanResult { int flight; int channel; int telemetry; - static final String[] short_monitor_names = { "Standard", "Original" }; boolean interrupted = false; public String toString() { - return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d telemetry %s)", - callsign, serial, flight, channel, short_monitor_names[telemetry]); + return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d %s)", + callsign, serial, flight, channel, Altos.telemetry_name(telemetry)); } public String toShortString() { @@ -116,9 +115,7 @@ public class AltosScanUI javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); - static final String[] monitor_names = { "Standard AltOS Telemetry", "Original TeleMetrum Telemetry" }; - static final int[] monitors = { 2, 1 }; - int monitor; + int telemetry; int channel; final static int timeout = 1200; @@ -171,7 +168,7 @@ public class AltosScanUI record.serial, record.flight, channel, - monitor); + telemetry); Runnable r = new Runnable() { public void run() { results.add(result); @@ -195,7 +192,7 @@ public class AltosScanUI void set_label() { scanning_label.setText(String.format("Scanning: channel %d %s", channel, - monitor_names[monitor])); + Altos.telemetry_name(telemetry))); } void next() { @@ -207,10 +204,10 @@ public class AltosScanUI ++channel; if (channel > 9) { channel = 0; - ++monitor; - if (monitor == monitors.length) - monitor = 0; - reader.serial.set_telemetry(monitors[monitor]); + ++telemetry; + if (telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_min; + reader.serial.set_telemetry(telemetry); } reader.serial.set_channel(channel); set_label(); @@ -251,7 +248,7 @@ public class AltosScanUI if (r != null) { if (device != null) { if (reader != null) { - reader.set_telemetry(monitors[r.telemetry]); + reader.set_telemetry(r.telemetry); reader.set_channel(r.channel); owner.telemetry_window(device); } @@ -282,7 +279,7 @@ public class AltosScanUI try { reader = new AltosTelemetryReader(device); reader.serial.set_channel(channel); - reader.serial.set_telemetry(monitors[monitor]); + reader.serial.set_telemetry(telemetry); handler = new TelemetryHandler(); thread = new Thread(handler); thread.start(); @@ -329,6 +326,9 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); + channel = 0; + telemetry = Altos.ao_telemetry_min; + scanning_label = new JLabel("Scanning:"); set_label(); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 3666cb41..2e8ce870 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -326,13 +326,7 @@ public class AltosSerial implements Runnable { } private int telemetry_len() { - switch (telemetry) { - case 1: - default: - return Altos.ao_telemetry_legacy_len; - case 2: - return Altos.ao_telemetry_split_len; - } + return Altos.telemetry_len(telemetry); } public void set_channel(int in_channel) { @@ -404,7 +398,7 @@ public class AltosSerial implements Runnable { line = ""; monitor_mode = false; frame = null; - telemetry = Altos.ao_telemetry_split; + telemetry = Altos.ao_telemetry_standard; monitors = new LinkedList> (); reply_queue = new LinkedBlockingQueue (); open(); diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java index e3751ee7..756f3ec9 100644 --- a/altosui/AltosTelemetryRecordLegacy.java +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -385,24 +385,25 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele */ int[] bytes; + int adjust; private int int8(int i) { - return Altos.int8(bytes, i + 1); + return Altos.int8(bytes, i + 1 + adjust); } private int uint8(int i) { - return Altos.uint8(bytes, i + 1); + return Altos.uint8(bytes, i + 1 + adjust); } private int int16(int i) { - return Altos.int16(bytes, i + 1); + return Altos.int16(bytes, i + 1 + adjust); } private int uint16(int i) { - return Altos.uint16(bytes, i + 1); + return Altos.uint16(bytes, i + 1 + adjust); } private int uint32(int i) { - return Altos.uint32(bytes, i + 1); + return Altos.uint32(bytes, i + 1 + adjust); } private String string(int i, int l) { - return Altos.string(bytes, i + 1, l); + return Altos.string(bytes, i + 1 + adjust, l); } static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); @@ -428,8 +429,13 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele } } version = 4; - callsign = string(62, 8); + adjust = 0; serial = uint16(0); + + if (bytes.length == Altos.ao_telemetry_0_8_len + 4) + adjust = -1; + + callsign = string(62, 8); flight = uint16(2); rssi = in_rssi; status = in_status; diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index e6c4cfc8..4b34f017 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -72,7 +72,7 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { /* length, data ..., rssi, status, checksum -- 4 bytes extra */ switch (bytes.length) { - case Altos.ao_telemetry_split_len + 4: + case Altos.ao_telemetry_standard_len + 4: int type = Altos.uint8(bytes, 4 + 1); switch (type) { case packet_type_TM_sensor: @@ -94,7 +94,10 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { break; } break; - case Altos.ao_telemetry_legacy_len + 4: + case Altos.ao_telemetry_0_9_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + case Altos.ao_telemetry_0_8_len + 4: r = new AltosTelemetryRecordLegacy(bytes, rssi, status); break; default: -- cgit v1.2.3 From e905042879147dd86241bf2dcc7437e5a6eb7578 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 20:43:57 -0700 Subject: altosui: Initialize channel and telemetry before use in ScanUI Otherwise we try to use telemetry format 0, which means 'no telemetry'. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 54be4f52..bc1638ed 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -311,6 +311,9 @@ public class AltosScanUI owner = in_owner; + channel = 0; + telemetry = Altos.ao_telemetry_min; + if (!open()) return; @@ -326,9 +329,6 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); - channel = 0; - telemetry = Altos.ao_telemetry_min; - scanning_label = new JLabel("Scanning:"); set_label(); -- cgit v1.2.3 From cbd14ba103ee5e3c5eec18e3a4ff13c320b98634 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 20:44:51 -0700 Subject: altosui: Set 'seen' bits in legacy telemetry packet reader Otherwise, the 'scan' code won't show detected flight computers. Signed-off-by: Keith Packard --- altosui/AltosTelemetryRecordLegacy.java | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java index 756f3ec9..f59027ab 100644 --- a/altosui/AltosTelemetryRecordLegacy.java +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -414,27 +414,19 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele static final int AO_GPS_DATE_VALID = (1 << 6); static final int AO_GPS_COURSE_VALID = (1 << 7); - static class theLock extends Object { - } - static public theLock lockObject = new theLock(); public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { bytes = in_bytes; - synchronized(lockObject) { - for (int i = 0; i < in_bytes.length - 2; i++) { - if ((i % 10) == 0) - System.out.printf("%3d:", i); - System.out.printf(" %02x", uint8(i)); - if ((i % 10) == 9 || i == in_bytes.length - 3) - System.out.printf("\n"); - } - } version = 4; adjust = 0; - serial = uint16(0); - if (bytes.length == Altos.ao_telemetry_0_8_len + 4) + if (bytes.length == Altos.ao_telemetry_0_8_len + 4) { + serial = uint8(0); adjust = -1; - + } else + serial = uint16(0); + + seen = seen_flight | seen_sensor | seen_temp_volt | seen_deploy; + callsign = string(62, 8); flight = uint16(2); rssi = in_rssi; @@ -476,6 +468,7 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { gps = new AltosGPS(); + seen |= seen_gps_time | seen_gps_lat | seen_gps_lon; gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); gps.locked = (gps_flags & AO_GPS_VALID) != 0; gps.connected = true; -- cgit v1.2.3 From 225073fd822f9861a83d65386c29fda9b37bf273 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 16:37:40 -0700 Subject: altosui: Add map preloading GUI Provide a way to manually enter latitude and longitude, preview the map area while downloading a 9x9 grid of map tiles to be used when monitoring flights without network access. Signed-off-by: Keith Packard --- altosui/AltosSiteMap.java | 59 +++++--- altosui/AltosSiteMapPreload.java | 285 +++++++++++++++++++++++++++++++++++++++ altosui/AltosUI.java | 11 ++ altosui/Makefile.am | 1 + 4 files changed, 340 insertions(+), 16 deletions(-) create mode 100644 altosui/AltosSiteMapPreload.java diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index 7575c10e..73068138 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -150,10 +150,13 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { //System.out.printf("Loading/fetching map %s\n", pngfile); Thread thread = new Thread() { public void run() { - ImageIcon res; - res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); + final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); if (res != null) { - tile.loadMap(res); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + tile.loadMap(res); + } + }); } else { System.out.printf("# Failed to fetch file %s\n", pngfile); System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); @@ -163,6 +166,24 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { thread.start(); } + File pngfile; + String pngurl; + + public int prefetchMap(int x, int y) { + LatLng map_latlng = latlng( + -centre.x + x*px_size + px_size/2, + -centre.y + y*px_size + px_size/2); + pngfile = MapFile(map_latlng.lat, map_latlng.lng); + pngurl = MapURL(map_latlng.lat, map_latlng.lng); + if (pngfile.exists()) { + return 1; + } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { + return 0; + } else { + return -1; + } + } + public static void prefetchMaps(double lat, double lng, int w, int h) { AltosSiteMap asm = new AltosSiteMap(true); asm.centre = asm.getBaseLocation(lat, lng); @@ -172,18 +193,18 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { int dx = -w/2, dy = -h/2; for (int y = dy; y < h+dy; y++) { for (int x = dx; x < w+dx; x++) { - LatLng map_latlng = asm.latlng( - -asm.centre.x + x*px_size + px_size/2, - -asm.centre.y + y*px_size + px_size/2); - File pngfile = asm.MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = asm.MapURL(map_latlng.lat, map_latlng.lng); - if (pngfile.exists()) { - System.out.printf("Already have %s\n", pngfile); - } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { - System.out.printf("Fetched map %s\n", pngfile); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); + int r = asm.prefetchMap(x, y); + switch (r) { + case 1: + System.out.printf("Already have %s\n", asm.pngfile); + break; + case 0: + System.out.printf("Fetched map %s\n", asm.pngfile); + break; + case -1: + System.out.printf("# Failed to fetch file %s\n", asm.pngfile); + System.out.printf(" wget -O '%s' ''\n", asm.pngfile, asm.pngurl); + break; } } } @@ -224,6 +245,12 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { boolean initialised = false; Point2D.Double last_pt = null; int last_state = -1; + + public void show(double lat, double lon) { + initMaps(lat, lon); + initialised = true; + scrollRocketToVisible(pt(lat, lon)); + } public void show(final AltosState state, final int crc_errors) { // if insufficient gps data, nothing to update if (!state.gps.locked && state.gps.nsat < 4) @@ -382,6 +409,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } setViewportView(comp); - setPreferredSize(new Dimension(500,200)); + setPreferredSize(new Dimension(500,500)); } } diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java new file mode 100644 index 00000000..2d9468b9 --- /dev/null +++ b/altosui/AltosSiteMapPreload.java @@ -0,0 +1,285 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.image.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.MouseInputAdapter; +import javax.imageio.ImageIO; +import javax.swing.table.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.lang.Math; +import java.awt.geom.Point2D; +import java.awt.geom.Line2D; + +class AltosMapPos extends Box { + JLabel label; + JComboBox hemi; + JTextField deg; + JLabel deg_label; + JTextField min; + JLabel min_label; + + public void set_value(double new_value) { + double d, m; + int h; + + h = 0; + if (new_value < 0) { + h = 1; + new_value = -new_value; + } + d = Math.floor(new_value); + deg.setText(String.format("%3.0f", d)); + m = (new_value - d) * 60.0; + min.setText(String.format("%7.4f", m)); + hemi.setSelectedIndex(h); + } + + public double get_value() throws NumberFormatException { + int h = hemi.getSelectedIndex(); + double d = Double.parseDouble(deg.getText()); + double m = Double.parseDouble(min.getText()); + double v = d + m/60.0; + if (h == 1) + v = -v; + return v; + } + + public AltosMapPos(String label_value, + String[] hemi_names, + double default_value) { + super(BoxLayout.X_AXIS); + label = new JLabel(label_value); + hemi = new JComboBox(hemi_names); + hemi.setEditable(false); + deg = new JTextField("000"); + deg_label = new JLabel("degrees"); + min = new JTextField("00.0000"); + min_label = new JLabel("minutes"); + set_value(default_value); + add(label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(hemi); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg); + add(Box.createRigidArea(new Dimension(5, 0))); + add(deg_label); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min); + add(Box.createRigidArea(new Dimension(5, 0))); + add(min_label); + } +} + +public class AltosSiteMapPreload extends JDialog implements ActionListener { + AltosUI owner; + AltosSiteMap map; + + AltosMapPos lat; + AltosMapPos lon; + + JProgressBar pbar; + + final static int width = 9; + final static int height = 9; + final static int tiles = width * height; + + JToggleButton load_button; + boolean loading; + JButton close_button; + + static final String[] lat_hemi_names = { "N", "S" }; + static final String[] lon_hemi_names = { "E", "W" }; + + class updatePbar implements Runnable { + int n; + String s; + + public updatePbar(int in_n, String in_s) { + n = in_n; + s = in_s; + } + + public void run() { + pbar.setValue(n); + pbar.setString(s); + if (n == width * height) { + load_button.setSelected(false); + loading = false; + } + } + } + + class bgLoad extends Thread { + + AltosSiteMap map; + + public bgLoad(AltosSiteMap in_map) { + map = in_map; + } + + public void run() { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + map.prefetchMap(y - height/2, x - width/2); + SwingUtilities.invokeLater(new updatePbar(y * height + x + 1, + map.pngfile.toString())); + } + } + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("close")) + setVisible(false); + + if (cmd.equals("load")) { + if (!loading) { + loading = true; + final double latitude = lat.get_value(); + final double longitude = lon.get_value(); + map.show(latitude,longitude); + bgLoad thread = new bgLoad(map); + thread.start(); + } + } + } + + public AltosSiteMapPreload(AltosUI in_owner) { + owner = in_owner; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + pane.setLayout(new GridBagLayout()); + + map = new AltosSiteMap(); + + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + + pane.add(map, c); + + pbar = new JProgressBar(); + pbar.setMinimum(0); + pbar.setMaximum(width * height); + pbar.setValue(0); + pbar.setString(""); + pbar.setStringPainted(true); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 2; + + pane.add(pbar, c); + + lat = new AltosMapPos("Latitude:", + lat_hemi_names, + 37.167833333); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lat, c); + + lon = new AltosMapPos("Longitude:", + lon_hemi_names, + -97.73975); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(lon, c); + + load_button = new JToggleButton("Load Map"); + load_button.addActionListener(this); + load_button.setActionCommand("load"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(load_button, c); + + close_button = new JButton("Close"); + close_button.addActionListener(this); + close_button.setActionCommand("close"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + + pane.add(close_button, c); + + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } +} \ No newline at end of file diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 6a24d8a9..d8c8d61c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -180,6 +180,13 @@ public class AltosUI extends JFrame { } }); + b = addButton(1, 2, "Load Maps"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + LoadMaps(); + } + }); + setTitle("AltOS"); pane.doLayout(); @@ -238,6 +245,10 @@ public class AltosUI extends JFrame { new AltosScanUI(AltosUI.this); } + void LoadMaps() { + new AltosSiteMapPreload(AltosUI.this); + } + /* * Replay a flight from telemetry data */ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 0a3ed0b1..18862d98 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -88,6 +88,7 @@ altosui_JAVA = \ AltosSerialInUseException.java \ AltosSerialMonitor.java \ AltosSiteMap.java \ + AltosSiteMapPreload.java \ AltosSiteMapCache.java \ AltosSiteMapTile.java \ AltosState.java \ -- cgit v1.2.3 From 0929ee32f753255cbe1474988cb41a5a86d29a0e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 17:37:20 -0700 Subject: altosui: Try to avoid resize weirdness with map preloading grid bag + box does some strange stuff, this appears to avoid the worst of the interactions. Signed-off-by: Keith Packard --- altosui/AltosSiteMapPreload.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 2d9468b9..f939e9d6 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -217,7 +217,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = i; - c.weightx = 1; + c.weightx = 0; c.weighty = 0; c.gridx = 0; @@ -234,7 +234,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = i; - c.weightx = 1; + c.weightx = 0; c.weighty = 0; c.gridx = 1; -- cgit v1.2.3 From 00e6981c2e0a668864fcf391932855cd8942140c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 21:05:06 -0700 Subject: altosui: Flush telemetry lines before starting to watch for scan results This prevents pending telemetry lines from being incorrectly attributed to the wrong channel/telemetry. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 5 +++++ altosui/AltosTelemetryReader.java | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index bc1638ed..96cab73b 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -280,6 +280,11 @@ public class AltosScanUI reader = new AltosTelemetryReader(device); reader.serial.set_channel(channel); reader.serial.set_telemetry(telemetry); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + } + reader.flush(); handler = new TelemetryHandler(); thread = new Thread(handler); thread.start(); diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 18f17841..23524b2c 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -39,6 +39,10 @@ class AltosTelemetryReader extends AltosFlightReader { return next; } + void flush() { + telem.clear(); + } + void close(boolean interrupted) { serial.remove_monitor(telem); log.close(); -- cgit v1.2.3 From 0a4d934f6e2914bfe2d965630543f029a1576c11 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 22:34:44 -0700 Subject: altosui: Display full map preload area in view. This involved fixing the map view to support arbitrary sizes, and then exposing a synchronous tile loading API so that the progress bar could be used to show tile loading progress. Signed-off-by: Keith Packard --- altosui/AltosSiteMap.java | 99 +++++++++++++++++++++++----------------- altosui/AltosSiteMapCache.java | 6 +++ altosui/AltosSiteMapPreload.java | 91 +++++++++++++++++++++++++----------- altosui/AltosSiteMapTile.java | 8 +++- 4 files changed, 136 insertions(+), 68 deletions(-) diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index 73068138..188902e9 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -97,6 +97,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { int zoom; double scale_x, scale_y; + int radius; /* half width/height of tiles to load */ + private Point2D.Double pt(double lat, double lng) { return pt(new LatLng(lat, lng), scale_x, scale_y); } @@ -144,37 +146,31 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // nothing } - private void bgLoadMap(final AltosSiteMapTile tile, - final File pngfile, final String pngurl) + private void loadMap(final AltosSiteMapTile tile, + File pngfile, String pngurl) { - //System.out.printf("Loading/fetching map %s\n", pngfile); - Thread thread = new Thread() { - public void run() { - final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); - if (res != null) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - tile.loadMap(res); - } - }); - } else { - System.out.printf("# Failed to fetch file %s\n", pngfile); - System.out.printf(" wget -O '%s' ''\n", pngfile, pngurl); - } - } - }; - thread.start(); + final ImageIcon res = AltosSiteMapCache.fetchAndLoadMap(pngfile, pngurl); + if (res != null) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + tile.loadMap(res); + } + }); + } else { + System.out.printf("# Failed to fetch file %s\n", pngfile); + System.out.printf(" wget -O '%s' '%s'\n", pngfile, pngurl); + } } - File pngfile; - String pngurl; + File pngfile; + String pngurl; public int prefetchMap(int x, int y) { LatLng map_latlng = latlng( -centre.x + x*px_size + px_size/2, -centre.y + y*px_size + px_size/2); - pngfile = MapFile(map_latlng.lat, map_latlng.lng); - pngurl = MapURL(map_latlng.lat, map_latlng.lng); + pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); + pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); if (pngfile.exists()) { return 1; } else if (AltosSiteMapCache.fetchMap(pngfile, pngurl)) { @@ -210,25 +206,41 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } } - private void initMap(AltosSiteMapTile tile, Point offset) { + public String initMap(Point offset) { + AltosSiteMapTile tile = mapTiles.get(offset); Point2D.Double coord = tileCoordOffset(offset); LatLng map_latlng = latlng(px_size/2-coord.x, px_size/2-coord.y); - File pngfile = MapFile(map_latlng.lat, map_latlng.lng); - String pngurl = MapURL(map_latlng.lat, map_latlng.lng); - bgLoadMap(tile, pngfile, pngurl); + File pngfile = MapFile(map_latlng.lat, map_latlng.lng, zoom); + String pngurl = MapURL(map_latlng.lat, map_latlng.lng, zoom); + loadMap(tile, pngfile, pngurl); + return pngfile.toString(); } - private void initMaps(double lat, double lng) { - centre = getBaseLocation(lat, lng); - + public void setBaseLocation(double lat, double lng) { for (Point k : mapTiles.keySet()) { - initMap(mapTiles.get(k), k); + AltosSiteMapTile tile = mapTiles.get(k); + tile.clearMap(); } + + centre = getBaseLocation(lat, lng); + scrollRocketToVisible(pt(lat,lng)); } - private File MapFile(double lat, double lng) { + private void initMaps(double lat, double lng) { + setBaseLocation(lat, lng); + + Thread thread = new Thread() { + public void run() { + for (Point k : mapTiles.keySet()) + initMap(k); + } + }; + thread.start(); + } + + private static File MapFile(double lat, double lng, int zoom) { char chlat = lat < 0 ? 'S' : 'N'; char chlng = lng < 0 ? 'W' : 'E'; if (lat < 0) lat = -lat; @@ -238,7 +250,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { chlat, lat, chlng, lng, zoom)); } - private String MapURL(double lat, double lng) { + private static String MapURL(double lat, double lng, int zoom) { return String.format("http://maps.google.com/maps/api/staticmap?center=%.6f,%.6f&zoom=%d&size=%dx%d&sensor=false&maptype=hybrid&format=png32", lat, lng, zoom, px_size, px_size); } @@ -248,7 +260,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { public void show(double lat, double lon) { initMaps(lat, lon); - initialised = true; scrollRocketToVisible(pt(lat, lon)); } public void show(final AltosState state, final int crc_errors) { @@ -295,7 +306,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { AltosSiteMapTile tile = createTile(offset); tile.show(state, crc_errors, lref, ref); - initMap(tile, offset); + initMap(offset); finishTileLater(tile, offset); } @@ -325,13 +336,13 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { } private void ensureTilesAround(Point base_offset) { - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { Point offset = new Point(base_offset.x + x, base_offset.y + y); if (mapTiles.containsKey(offset)) continue; AltosSiteMapTile tile = createTile(offset); - initMap(tile, offset); + initMap(offset); finishTileLater(tile, offset); } } @@ -396,13 +407,15 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { JComponent comp = new JComponent() { }; private GridBagLayout layout = new GridBagLayout(); - public AltosSiteMap() { + public AltosSiteMap(int in_radius) { + radius = in_radius; + GrabNDrag scroller = new GrabNDrag(comp); comp.setLayout(layout); - for (int x = -1; x <= 1; x++) { - for (int y = -1; y <= 1; y++) { + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { Point offset = new Point(x, y); AltosSiteMapTile t = createTile(offset); addTileAt(t, offset); @@ -411,4 +424,8 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { setViewportView(comp); setPreferredSize(new Dimension(500,500)); } + + public AltosSiteMap() { + this(1); + } } diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java index 2e62cc45..cfad52a9 100644 --- a/altosui/AltosSiteMapCache.java +++ b/altosui/AltosSiteMapCache.java @@ -37,6 +37,7 @@ public class AltosSiteMapCache extends JLabel { try { u = new URL(url); } catch (java.net.MalformedURLException e) { + System.out.printf("Malformed URL '%s'\n", url); return false; } @@ -57,9 +58,12 @@ public class AltosSiteMapCache extends JLabel { in.close(); if (offset != contentLength) { + System.out.printf("Bad length %d != %d\n", + offset, contentLength); return false; } } catch (IOException e) { + System.out.printf("IO exception reading URL\n"); return false; } @@ -69,11 +73,13 @@ public class AltosSiteMapCache extends JLabel { out.flush(); out.close(); } catch (FileNotFoundException e) { + System.out.printf("Can't create file\n"); return false; } catch (IOException e) { if (file.exists()) { file.delete(); } + System.out.printf("IO exception writing file\n"); return false; } return true; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index f939e9d6..25133435 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -33,6 +33,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; class AltosMapPos extends Box { + AltosUI owner; JLabel label; JComboBox hemi; JTextField deg; @@ -58,25 +59,51 @@ class AltosMapPos extends Box { public double get_value() throws NumberFormatException { int h = hemi.getSelectedIndex(); - double d = Double.parseDouble(deg.getText()); - double m = Double.parseDouble(min.getText()); - double v = d + m/60.0; + String d_t = deg.getText(); + String m_t = min.getText(); + double d, m, v; + try { + d = Double.parseDouble(d_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid degrees \"%s\"", + d_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + try { + if (m_t.equals("")) + m = 0; + else + m = Double.parseDouble(m_t); + } catch (NumberFormatException ne) { + JOptionPane.showMessageDialog(owner, + String.format("Invalid minutes \"%s\"", + m_t), + "Invalid number", + JOptionPane.ERROR_MESSAGE); + throw ne; + } + v = d + m/60.0; if (h == 1) v = -v; return v; } - public AltosMapPos(String label_value, + public AltosMapPos(AltosUI in_owner, + String label_value, String[] hemi_names, double default_value) { super(BoxLayout.X_AXIS); + owner = in_owner; label = new JLabel(label_value); hemi = new JComboBox(hemi_names); hemi.setEditable(false); deg = new JTextField("000"); - deg_label = new JLabel("degrees"); + deg_label = new JLabel("°"); min = new JTextField("00.0000"); - min_label = new JLabel("minutes"); + min_label = new JLabel("'"); set_value(default_value); add(label); add(Box.createRigidArea(new Dimension(5, 0))); @@ -101,9 +128,9 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { JProgressBar pbar; - final static int width = 9; - final static int height = 9; - final static int tiles = width * height; + final static int radius = 4; + final static int width = (radius * 2 + 1); + final static int height = (radius * 2 + 1); JToggleButton load_button; boolean loading; @@ -116,15 +143,21 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { int n; String s; - public updatePbar(int in_n, String in_s) { - n = in_n; + public updatePbar(int x, int y, String in_s) { + n = (x + radius) + (y + radius) * width + 1; + System.out.printf("update pbar %d\n", n); s = in_s; } public void run() { pbar.setValue(n); pbar.setString(s); - if (n == width * height) { + if (n < width * height) { + pbar.setValue(n); + pbar.setString(s); + } else { + pbar.setValue(0); + pbar.setString(""); load_button.setSelected(false); loading = false; } @@ -140,11 +173,11 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { } public void run() { - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - map.prefetchMap(y - height/2, x - width/2); - SwingUtilities.invokeLater(new updatePbar(y * height + x + 1, - map.pngfile.toString())); + for (int y = -map.radius; y <= map.radius; y++) { + for (int x = -map.radius; x <= map.radius; x++) { + String pngfile; + pngfile = map.initMap(new Point(x,y)); + SwingUtilities.invokeLater(new updatePbar(x, y, pngfile)); } } } @@ -158,12 +191,16 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { if (cmd.equals("load")) { if (!loading) { - loading = true; - final double latitude = lat.get_value(); - final double longitude = lon.get_value(); - map.show(latitude,longitude); - bgLoad thread = new bgLoad(map); - thread.start(); + try { + final double latitude = lat.get_value(); + final double longitude = lon.get_value(); + map.setBaseLocation(latitude,longitude); + loading = true; + bgLoad thread = new bgLoad(map); + thread.start(); + } catch (NumberFormatException ne) { + load_button.setSelected(false); + } } } } @@ -177,7 +214,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { pane.setLayout(new GridBagLayout()); - map = new AltosSiteMap(); + map = new AltosSiteMap(4); c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; @@ -211,7 +248,8 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { pane.add(pbar, c); - lat = new AltosMapPos("Latitude:", + lat = new AltosMapPos(owner, + "Latitude:", lat_hemi_names, 37.167833333); c.fill = GridBagConstraints.NONE; @@ -227,7 +265,8 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { pane.add(lat, c); - lon = new AltosMapPos("Longitude:", + lon = new AltosMapPos(owner, + "Longitude:", lon_hemi_names, -97.73975); diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java index 8301f42b..66da7c54 100644 --- a/altosui/AltosSiteMapTile.java +++ b/altosui/AltosSiteMapTile.java @@ -35,11 +35,16 @@ public class AltosSiteMapTile extends JLayeredPane { JLabel mapLabel; JLabel draw; Graphics2D g2d; + int px_size; public void loadMap(ImageIcon icn) { mapLabel.setIcon(icn); } + public void clearMap() { + fillLabel(mapLabel, Color.GRAY, px_size); + } + static Color stateColors[] = { Color.WHITE, // startup Color.WHITE, // idle @@ -90,7 +95,8 @@ public class AltosSiteMapTile extends JLayeredPane { return g; } - public AltosSiteMapTile(int px_size) { + public AltosSiteMapTile(int in_px_size) { + px_size = in_px_size; setPreferredSize(new Dimension(px_size, px_size)); mapLabel = new JLabel(); -- cgit v1.2.3 From 1681c57cbbfc5214dbc2a519e54ce9f29ffe3921 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 22:43:34 -0700 Subject: altosui: Remove a bunch of sitemap debugging printfs Seems to work, let's get less chatty Signed-off-by: Keith Packard --- altosui/AltosSiteMapCache.java | 6 ------ altosui/AltosSiteMapPreload.java | 1 - 2 files changed, 7 deletions(-) diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java index cfad52a9..2e62cc45 100644 --- a/altosui/AltosSiteMapCache.java +++ b/altosui/AltosSiteMapCache.java @@ -37,7 +37,6 @@ public class AltosSiteMapCache extends JLabel { try { u = new URL(url); } catch (java.net.MalformedURLException e) { - System.out.printf("Malformed URL '%s'\n", url); return false; } @@ -58,12 +57,9 @@ public class AltosSiteMapCache extends JLabel { in.close(); if (offset != contentLength) { - System.out.printf("Bad length %d != %d\n", - offset, contentLength); return false; } } catch (IOException e) { - System.out.printf("IO exception reading URL\n"); return false; } @@ -73,13 +69,11 @@ public class AltosSiteMapCache extends JLabel { out.flush(); out.close(); } catch (FileNotFoundException e) { - System.out.printf("Can't create file\n"); return false; } catch (IOException e) { if (file.exists()) { file.delete(); } - System.out.printf("IO exception writing file\n"); return false; } return true; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 25133435..c97f081c 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -145,7 +145,6 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { public updatePbar(int x, int y, String in_s) { n = (x + radius) + (y + radius) * width + 1; - System.out.printf("update pbar %d\n", n); s = in_s; } -- cgit v1.2.3 From a482d904a3f391c3a24df3660acb3f3696aa6766 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 16 Jul 2011 23:08:49 -0700 Subject: altosui: Make sure degree and minute values are visible (map preload) Set min size to preferred size so that the value remains visible instead of snapping to 0 pixels wide. Signed-off-by: Keith Packard --- altosui/AltosSiteMapPreload.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index c97f081c..876c14ac 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -105,6 +105,8 @@ class AltosMapPos extends Box { min = new JTextField("00.0000"); min_label = new JLabel("'"); set_value(default_value); + deg.setMinimumSize(deg.getPreferredSize()); + min.setMinimumSize(min.getPreferredSize()); add(label); add(Box.createRigidArea(new Dimension(5, 0))); add(hemi); -- cgit v1.2.3 From 1332ed55192f22525f31574f60fae4c6579e6f7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 08:13:15 -0700 Subject: Set version to 0.9.4.4 Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cee1b833..b7af55e4 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.3) +AC_INIT([altos], 0.9.4.4) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 51796e2f1ebce3ee8dc1ac90648381410c1379ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 May 2011 11:32:29 -0700 Subject: altos, altosui: Add igniter mode (dual, apogee, main) This provides for redundant charges for either apogee or main. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 7 ++++++ altosui/AltosConfigData.java | 2 ++ altosui/AltosConfigUI.java | 54 ++++++++++++++++++++++++++++++++++++++++---- src/ao.h | 7 +++++- src/ao_config.c | 31 +++++++++++++++++++++++++ src/ao_ignite.c | 50 ++++++++++++++++++++++++++++++++-------- 6 files changed, 136 insertions(+), 15 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index c5de83f2..e3c30d4d 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -70,6 +70,7 @@ public class AltosConfig implements ActionListener { int_ref radio_channel; int_ref radio_calibration; int_ref flight_log_max; + int_ref ignite_mode; string_ref version; string_ref product; string_ref callsign; @@ -130,6 +131,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_channel(radio_channel.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_flight_log_max(flight_log_max.get()); + config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); config_ui.make_visible(); @@ -153,6 +155,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Radio channel:", radio_channel); get_int(line, "Radio cal:", radio_calibration); get_int(line, "Max flight log:", flight_log_max); + get_int(line, "Ignite mode:", ignite_mode); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -224,6 +227,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); + if (ignite_mode.get() >= 0) + serial_line.printf("c i %d\n", ignite_mode.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { } finally { @@ -306,6 +311,7 @@ public class AltosConfig implements ActionListener { radio_channel.set(config_ui.radio_channel()); radio_calibration.set(config_ui.radio_calibration()); flight_log_max.set(config_ui.flight_log_max()); + ignite_mode.set(config_ui.ignite_mode()); callsign.set(config_ui.callsign()); run_serial_thread(serial_mode_save); } @@ -340,6 +346,7 @@ public class AltosConfig implements ActionListener { radio_channel = new int_ref(0); radio_calibration = new int_ref(1186611); flight_log_max = new int_ref(0); + ignite_mode = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 8c32ed86..3f0e9af3 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -51,6 +51,7 @@ public class AltosConfigData implements Iterable { int accel_cal_plus, accel_cal_minus; int radio_calibration; int flight_log_max; + int ignite_mode; static String get_string(String line, String label) throws ParseException { @@ -96,6 +97,7 @@ public class AltosConfigData implements Iterable { try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} try { version = get_string(line,"software-version"); } catch (Exception e) {} try { product = get_string(line,"product"); } catch (Exception e) {} diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index f835ee2e..6f635b9d 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -46,6 +46,7 @@ public class AltosConfigUI JLabel radio_channel_label; JLabel radio_calibration_label; JLabel flight_log_max_label; + JLabel ignite_mode_label; JLabel callsign_label; public boolean dirty; @@ -59,6 +60,7 @@ public class AltosConfigUI JComboBox radio_channel_value; JTextField radio_calibration_value; JComboBox flight_log_max_value; + JComboBox ignite_mode_value; JTextField callsign_value; JButton save; @@ -83,6 +85,12 @@ public class AltosConfigUI "704", "768", "832", "896", "960", }; + static String[] ignite_mode_values = { + "Dual Deploy", + "Redundant Apogee", + "Redundant Main", + }; + static String[] radio_channel_values = new String[10]; { for (int i = 0; i <= 9; i++) @@ -326,9 +334,33 @@ public class AltosConfigUI flight_log_max_value.addItemListener(this); pane.add(flight_log_max_value, c); - /* Buttons */ + /* Ignite mode */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 9; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + ignite_mode_label = new JLabel("Igniter Firing Mode:"); + pane.add(ignite_mode_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 9; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + ignite_mode_value = new JComboBox(ignite_mode_values); + ignite_mode_value.setEditable(false); + ignite_mode_value.addItemListener(this); + pane.add(ignite_mode_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -339,7 +371,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 9; + c.gridx = 2; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -350,7 +382,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 9; + c.gridx = 4; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -361,7 +393,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 9; + c.gridx = 6; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -499,6 +531,20 @@ public class AltosConfigUI return Integer.parseInt(flight_log_max_value.getSelectedItem().toString()); } + public void set_ignite_mode(int new_ignite_mode) { + if (new_ignite_mode < 0) { + ignite_mode_value.setEnabled(false); + new_ignite_mode = 0; + } else { + ignite_mode_value.setEnabled(true); + } + ignite_mode_value.setSelectedItem(Integer.toString(new_ignite_mode)); + } + + public int ignite_mode() { + return ignite_mode_value.getSelectedIndex(); + } + public void set_clean() { dirty = false; } diff --git a/src/ao.h b/src/ao.h index e52a2198..d3e588b6 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1357,7 +1357,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 4 +#define AO_CONFIG_MINOR 5 struct ao_config { uint8_t major; @@ -1370,8 +1370,13 @@ struct ao_config { int16_t accel_minus_g; /* minor version 2 */ uint32_t radio_cal; /* minor version 3 */ uint32_t flight_log_max; /* minor version 4 */ + uint8_t ignite_mode; /* minor version 5 */ }; +#define AO_IGNITE_MODE_DUAL 0 +#define AO_IGNITE_MODE_APOGEE 1 +#define AO_IGNITE_MODE_MAIN 2 + extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 diff --git a/src/ao_config.c b/src/ao_config.c index 813164ea..48349886 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL #if USE_INTERNAL_EEPROM #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else @@ -75,6 +76,7 @@ _ao_config_get(void) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; ao_config.radio_cal = ao_radio_cal; ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -92,6 +94,9 @@ _ao_config_get(void) /* Fixups for minor version 4 */ if (ao_config.minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + /* Fixupes for minor version 5 */ + if (ao_config.minor < 5) + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -334,6 +339,28 @@ ao_config_log_set(void) __reentrant } #endif /* HAS_EEPROM */ +#if HAS_IGNITE +void +ao_config_ignite_mode_show(void) __reentrant +{ + printf("Ignite mode: %d\n", ao_config.ignite_mode); +} + +void +ao_config_ignite_mode_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.ignite_mode = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -369,6 +396,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_EEPROM { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, +#endif +#if HAS_IGNITE + { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", + ao_config_ignite_mode_set, ao_config_ignite_mode_show }, #endif { "s\0Show", ao_config_show, ao_config_show }, diff --git a/src/ao_ignite.c b/src/ao_ignite.c index e1b91bea..512ec622 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -51,7 +51,7 @@ void ao_ignite(enum ao_igniter igniter) __critical { ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition[0]); + ao_wakeup(&ao_ignition); } enum ao_igniter_status @@ -91,16 +91,46 @@ void ao_igniter_fire(enum ao_igniter igniter) __critical { ao_ignition[igniter].firing = 1; - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + break; + case ao_igniter_main: + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } break; } ao_ignition[igniter].firing = 0; -- cgit v1.2.3 From 81cac174c80ee42d9e94c6500da7c4c760c3ce67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 11:25:47 -0700 Subject: altosui: Download list of site locations for map preloading The current URL for this is: http://gag.com/~keithp/launch-sites.txt The format is: :: lat and lon are both in signed decimal degrees. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 1 + altosui/AltosSiteMapPreload.java | 169 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 159 insertions(+), 11 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 2e8ce870..8f8f99d7 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -25,6 +25,7 @@ import java.lang.*; import java.io.*; import java.util.concurrent.*; import java.util.*; +import java.text.*; import java.awt.*; import java.awt.event.*; import javax.swing.*; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 876c14ac..972765ae 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -31,6 +31,8 @@ import java.util.prefs.*; import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; +import java.net.URL; +import java.net.URLConnection; class AltosMapPos extends Box { AltosUI owner; @@ -100,13 +102,14 @@ class AltosMapPos extends Box { label = new JLabel(label_value); hemi = new JComboBox(hemi_names); hemi.setEditable(false); - deg = new JTextField("000"); + deg = new JTextField(5); + deg.setMinimumSize(deg.getPreferredSize()); + deg.setHorizontalAlignment(JTextField.RIGHT); deg_label = new JLabel("°"); - min = new JTextField("00.0000"); + min = new JTextField(9); + min.setMinimumSize(min.getPreferredSize()); min_label = new JLabel("'"); set_value(default_value); - deg.setMinimumSize(deg.getPreferredSize()); - min.setMinimumSize(min.getPreferredSize()); add(label); add(Box.createRigidArea(new Dimension(5, 0))); add(hemi); @@ -121,19 +124,111 @@ class AltosMapPos extends Box { } } -public class AltosSiteMapPreload extends JDialog implements ActionListener { +class AltosSite { + String name; + double latitude; + double longitude; + + public String toString() { + return name; + } + + public AltosSite(String in_name, double in_latitude, double in_longitude) { + name = in_name; + latitude = in_latitude; + longitude = in_longitude; + } + + public AltosSite(String line) throws ParseException { + String[] elements = line.split(":"); + + if (elements.length < 3) + throw new ParseException(String.format("Invalid site line %s", line), 0); + + name = elements[0]; + + try { + latitude = Double.parseDouble(elements[1]); + longitude = Double.parseDouble(elements[2]); + } catch (NumberFormatException ne) { + throw new ParseException(String.format("Invalid site line %s", line), 0); + } + } +} + +class AltosSites extends Thread { + AltosSiteMapPreload preload; + URL url; + LinkedList sites; + + void notify_complete() { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + preload.set_sites(); + } + }); + } + + void add(AltosSite site) { + sites.add(site); + } + + void add(String line) { + try { + add(new AltosSite(line)); + } catch (ParseException pe) { + } + } + + public void run() { + try { + URLConnection uc = url.openConnection(); + int length = uc.getContentLength(); + + InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), Altos.unicode_set); + BufferedReader in = new BufferedReader(in_stream); + + for (;;) { + String line = in.readLine(); + if (line == null) + break; + add(line); + } + } catch (IOException e) { + } finally { + notify_complete(); + } + } + + public AltosSites(AltosSiteMapPreload in_preload) { + sites = new LinkedList(); + preload = in_preload; + try { + url = new URL("http://gag.com/~keithp/launch-sites.txt"); + } catch (java.net.MalformedURLException e) { + notify_complete(); + } + start(); + } +} + +public class AltosSiteMapPreload extends JDialog implements ActionListener, ItemListener { AltosUI owner; AltosSiteMap map; AltosMapPos lat; AltosMapPos lon; - JProgressBar pbar; - final static int radius = 4; final static int width = (radius * 2 + 1); final static int height = (radius * 2 + 1); + JProgressBar pbar; + + AltosSites sites; + JLabel site_list_label; + JComboBox site_list; + JToggleButton load_button; boolean loading; JButton close_button; @@ -184,6 +279,27 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { } } + public void set_sites() { + int i = 1; + for (AltosSite site : sites.sites) { + site_list.insertItemAt(site, i); + i++; + } + } + + public void itemStateChanged(ItemEvent e) { + int state = e.getStateChange(); + + if (state == ItemEvent.SELECTED) { + Object o = e.getItem(); + if (o instanceof AltosSite) { + AltosSite site = (AltosSite) o; + lat.set_value(site.latitude); + lon.set_value(site.longitude); + } + } + } + public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); @@ -249,6 +365,37 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { pane.add(pbar, c); + site_list_label = new JLabel ("Known Launch Sites:"); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list_label, c); + + site_list = new JComboBox(new String[] { "Site List" }); + site_list.addItemListener(this); + + sites = new AltosSites(this); + + c.fill = GridBagConstraints.HORIZONTAL; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 0; + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + + pane.add(site_list, c); + lat = new AltosMapPos(owner, "Latitude:", lat_hemi_names, @@ -260,7 +407,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.weighty = 0; c.gridx = 0; - c.gridy = 2; + c.gridy = 3; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; @@ -278,7 +425,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.weighty = 0; c.gridx = 1; - c.gridy = 2; + c.gridy = 3; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; @@ -295,7 +442,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.weighty = 0; c.gridx = 0; - c.gridy = 3; + c.gridy = 4; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; @@ -312,7 +459,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener { c.weighty = 0; c.gridx = 1; - c.gridy = 3; + c.gridy = 4; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; -- cgit v1.2.3 From fef42e0d9e0a20bdbd32e052749fc63575515e1c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 11:29:13 -0700 Subject: altosui: Add launch-sites.txt Contains a few of our favorites. Signed-off-by: Keith Packard --- altosui/launch-sites.txt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 altosui/launch-sites.txt diff --git a/altosui/launch-sites.txt b/altosui/launch-sites.txt new file mode 100644 index 00000000..05619d57 --- /dev/null +++ b/altosui/launch-sites.txt @@ -0,0 +1,7 @@ +KLOUDBusters Rocket Pasture:37.167833333:-97.73975 +NCR Pawnee:40.8875500:-104.6484750 +OPROC Discovery Bay:47.97808,-122.896383 +OROC Brothers:43.79949786336483:-120.6485810681392 +OROC Sheridan:45.044176:-123.314323 +Tripoli Colorado Hartsel:39.009247:-105.702338 +WAC Sportsman Club:47.815327777777778:-119.427186111111111 -- cgit v1.2.3 From 1f3f3d575572eff33a2bc7a53d4691e59a428450 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 15:09:55 -0700 Subject: altosui: Add a bunch more site locations BALLS, Rio Rancho, METRA, QRS Cedar Grove and Hudson Ranch Signed-off-by: Keith Packard --- altosui/Makefile.am | 3 +++ altosui/launch-sites.txt | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 18862d98..e3075d41 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -307,3 +307,6 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) $(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi -rm -f $@ makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi + +publish: + scp launch-sites.txt gag.com:public_html \ No newline at end of file diff --git a/altosui/launch-sites.txt b/altosui/launch-sites.txt index 05619d57..baa0dfe9 100644 --- a/altosui/launch-sites.txt +++ b/altosui/launch-sites.txt @@ -1,7 +1,12 @@ +AHPRA BALLS:40.808333333333333:-119.15 +ARS Rio Rancho:35.33475:-106.75361 KLOUDBusters Rocket Pasture:37.167833333:-97.73975 +METRA Pine Island:41.31939:-74.47077 NCR Pawnee:40.8875500:-104.6484750 OPROC Discovery Bay:47.97808,-122.896383 OROC Brothers:43.79949786336483:-120.6485810681392 OROC Sheridan:45.044176:-123.314323 +QRS Cedar Grove:-27.8512283:152.9624000 +SCORE Hudson Ranch:38.155602777777778:-104.809119444444444 Tripoli Colorado Hartsel:39.009247:-105.702338 WAC Sportsman Club:47.815327777777778:-119.427186111111111 -- cgit v1.2.3 From ddef3e4ec1b3ff86b164f83807c34c2a78f73eb8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 15:45:07 -0700 Subject: altosui: Mark preload site location with red circles (like launch) Just to show where on the map the official launch location is. Signed-off-by: Keith Packard --- altosui/AltosSiteMap.java | 10 ++++++++++ altosui/AltosSiteMapPreload.java | 1 + altosui/AltosSiteMapTile.java | 11 +++++++++++ 3 files changed, 22 insertions(+) diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index 188902e9..b3fb3c54 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -320,6 +320,16 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { last_state = state.state; } + public void draw_circle(double lat, double lon) { + final Point2D.Double pt = pt(lat, lon); + + for (Point offset : mapTiles.keySet()) { + AltosSiteMapTile tile = mapTiles.get(offset); + Point2D.Double ref = translatePoint(pt, tileCoordOffset(offset)); + tile.draw_circle(ref); + } + } + private AltosSiteMapTile createTile(Point offset) { AltosSiteMapTile tile = new AltosSiteMapTile(px_size); mapTiles.put(offset, tile); diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 972765ae..5d437e17 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -312,6 +312,7 @@ public class AltosSiteMapPreload extends JDialog implements ActionListener, Item final double latitude = lat.get_value(); final double longitude = lon.get_value(); map.setBaseLocation(latitude,longitude); + map.draw_circle(latitude,longitude); loading = true; bgLoad thread = new bgLoad(map); thread.start(); diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java index 66da7c54..9e62bb47 100644 --- a/altosui/AltosSiteMapTile.java +++ b/altosui/AltosSiteMapTile.java @@ -43,6 +43,10 @@ public class AltosSiteMapTile extends JLayeredPane { public void clearMap() { fillLabel(mapLabel, Color.GRAY, px_size); + g2d = fillLabel(draw, new Color(127,127,127,0), px_size); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setStroke(new BasicStroke(6, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); } static Color stateColors[] = { @@ -85,6 +89,13 @@ public class AltosSiteMapTile extends JLayeredPane { repaint(); } + public void draw_circle(Point2D.Double pt) { + g2d.setColor(Color.RED); + g2d.drawOval((int)pt.x-5, (int)pt.y-5, 10, 10); + g2d.drawOval((int)pt.x-20, (int)pt.y-20, 40, 40); + g2d.drawOval((int)pt.x-35, (int)pt.y-35, 70, 70); + } + public static Graphics2D fillLabel(JLabel l, Color c, int px_size) { BufferedImage img = new BufferedImage(px_size, px_size, BufferedImage.TYPE_INT_ARGB); -- cgit v1.2.3 From 6796d9e253a808824ba32cdb008da8bf302780fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 15:53:13 -0700 Subject: Fix NCR Pawnee location Signed-off-by: Keith Packard --- altosui/launch-sites.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/launch-sites.txt b/altosui/launch-sites.txt index baa0dfe9..bd5d1795 100644 --- a/altosui/launch-sites.txt +++ b/altosui/launch-sites.txt @@ -2,7 +2,7 @@ AHPRA BALLS:40.808333333333333:-119.15 ARS Rio Rancho:35.33475:-106.75361 KLOUDBusters Rocket Pasture:37.167833333:-97.73975 METRA Pine Island:41.31939:-74.47077 -NCR Pawnee:40.8875500:-104.6484750 +NCR Pawnee:40.885955:-104.63793 OPROC Discovery Bay:47.97808,-122.896383 OROC Brothers:43.79949786336483:-120.6485810681392 OROC Sheridan:45.044176:-123.314323 -- cgit v1.2.3 From 7f6cce5749724dbb836aaa27bbeedf977106f6f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 16:43:41 -0700 Subject: Add HARA Bragg Farms site Signed-off-by: Keith Packard --- altosui/launch-sites.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/launch-sites.txt b/altosui/launch-sites.txt index bd5d1795..de7955e0 100644 --- a/altosui/launch-sites.txt +++ b/altosui/launch-sites.txt @@ -1,5 +1,6 @@ AHPRA BALLS:40.808333333333333:-119.15 ARS Rio Rancho:35.33475:-106.75361 +HARA Bragg Farms:34.895875:-86.616211 KLOUDBusters Rocket Pasture:37.167833333:-97.73975 METRA Pine Island:41.31939:-74.47077 NCR Pawnee:40.885955:-104.63793 -- cgit v1.2.3 From 6795d353be91df96a571cebc237e6a54a065a380 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 16:44:10 -0700 Subject: altosui: Change continutity colors to yellow/magenta Makes them stand apart from the accel/speed lines Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 03aae652..a27aa37f 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -23,6 +23,9 @@ public class AltosGraphUI extends JFrame static final private Color green = new Color(31,194,31); static final private Color blue = new Color(31,31,194); static final private Color black = new Color(31,31,31); + static final private Color yellow = new Color(194,194,31); + static final private Color cyan = new Color(31,194,194); + static final private Color magenta = new Color(194,31,194); static private class OverallGraphs { AltosGraphTime.Element height = @@ -71,7 +74,7 @@ public class AltosGraphUI extends JFrame }; AltosGraphTime.Element drogue_voltage = - new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", blue) + new AltosGraphTime.TimeSeries("Voltage (V)", "Drogue Continuity", yellow) { public void gotTimeData(double time, AltosDataPoint d) { double v = d.drogue_voltage(); @@ -81,7 +84,7 @@ public class AltosGraphUI extends JFrame }; AltosGraphTime.Element main_voltage = - new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", green) + new AltosGraphTime.TimeSeries("Voltage (V)", "Main Continuity", magenta) { public void gotTimeData(double time, AltosDataPoint d) { double v = d.main_voltage(); -- cgit v1.2.3 From 146a0ab223e8d9b376125d1e59f597f6d7851a9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 18:49:55 -0700 Subject: altos: Add ability to read new TELEM files to ao_flight_test Not that telem files are currently very useful as the kalman filter gets completly confused by the variable steps caused by missing data, but... Signed-off-by: Keith Packard --- src/ao_flight_test.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_kalman.c | 37 +++++++++ src/make-kalman | 3 + 3 files changed, 249 insertions(+) diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 57785442..72ad1450 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -298,6 +298,139 @@ ao_insert(void) } } +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; +}; + +uint16_t +uint16(uint8_t *bytes, int off) +{ + off++; + return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); +} + +int16_t +int16(uint8_t *bytes, int off) +{ + return (int16_t) uint16(bytes, off); +} + void ao_sleep(void *wchan) { @@ -306,6 +439,8 @@ ao_sleep(void *wchan) uint16_t tick; uint16_t a, b; int ret; + uint8_t bytes[1024]; + union ao_telemetry_all telem; char line[1024]; char *saveptr; char *l; @@ -342,6 +477,8 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); + if (type == 'P') + type = 'A'; } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); @@ -358,6 +495,78 @@ ao_sleep(void *wchan) a = atoi(words[12]); b = atoi(words[14]); } + } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { + char *hex = words[1]; + char elt[3]; + int i, len; + uint8_t sum; + + len = strlen(hex); + if (len > sizeof (bytes) * 2) { + len = sizeof (bytes)*2; + hex[len] = '\0'; + } + for (i = 0; i < len; i += 2) { + elt[0] = hex[i]; + elt[1] = hex[i+1]; + elt[2] = '\0'; + bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); + } + len = i/2; + if (bytes[0] != len - 2) { + printf ("bad length %d != %d\n", bytes[0], len - 2); + continue; + } + sum = 0x5a; + for (i = 1; i < len-1; i++) + sum += bytes[i]; + if (sum != bytes[len-1]) { + printf ("bad checksum\n"); + continue; + } + if ((bytes[len-2] & 0x80) == 0) { + continue; + } + if (len == 36) { + memcpy(&telem, bytes + 1, 32); + tick = telem.generic.tick; + switch (telem.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (!ao_flight_started) { + ao_flight_ground_accel = telem.sensor.ground_accel; + ao_config.accel_plus_g = telem.sensor.accel_plus_g; + ao_config.accel_minus_g = telem.sensor.accel_minus_g; + ao_flight_started = 1; + } + type = 'A'; + a = telem.sensor.accel; + b = telem.sensor.pres; + break; + } + } else if (len == 99) { + ao_flight_started = 1; + tick = uint16(bytes, 21); + ao_flight_ground_accel = int16(bytes, 7); + ao_config.accel_plus_g = int16(bytes, 17); + ao_config.accel_minus_g = int16(bytes, 19); + type = 'A'; + a = int16(bytes, 23); + b = int16(bytes, 25); + } else if (len == 98) { + ao_flight_started = 1; + tick = uint16(bytes, 20); + ao_flight_ground_accel = int16(bytes, 6); + ao_config.accel_plus_g = int16(bytes, 16); + ao_config.accel_minus_g = int16(bytes, 18); + type = 'A'; + a = int16(bytes, 22); + b = int16(bytes, 24); + } else { + printf("unknown len %d\n", len); + continue; + } } if (type != 'F' && !ao_flight_started) continue; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index fb75fba9..4e6cbb06 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -31,6 +31,9 @@ static __pdata int32_t ao_k_accel; #define AO_K_STEP_10 to_fix16(0.1) #define AO_K_STEP_2_2_10 to_fix16(0.005) +#define AO_K_STEP_1 to_fix16(1) +#define AO_K_STEP_2_2_1 to_fix16(0.5) + __pdata int16_t ao_height; __pdata int16_t ao_speed; __pdata int16_t ao_accel; @@ -47,6 +50,13 @@ static void ao_kalman_predict(void) { #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + + (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; + + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; @@ -126,6 +136,12 @@ ao_kalman_correct_baro(void) { ao_kalman_err_height(); #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; @@ -158,6 +174,27 @@ ao_kalman_correct_both(void) ao_kalman_err_accel(); #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_1 * ao_error_h + + (int32_t) AO_BOTH_K01_1 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_1 * ao_error_h + + (int32_t) AO_BOTH_K21_1 * ao_error_a; + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { if (ao_flight_debug) { printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", diff --git a/src/make-kalman b/src/make-kalman index 5a25e1ec..9ac35134 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -8,9 +8,12 @@ SIGMA_ACCEL="-M 2 -H 4 -A 4" nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO -- cgit v1.2.3 From e19a117b99e8374ca0e8e35948e23bc672ad1a32 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:33:38 -0700 Subject: altos: Average height values for landing detection Instead of using the direct output of the kalman filter and hoping that is quiet enough to detect landing, filter that with a long exponential decay filter and then check to make sure that doesn't change more than 2m in 5 seconds as a trigger for landing detection. Tested with existing telemetrum flight logs and it correctly detects landing in all cases. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_flight.c | 15 +++++++------- src/ao_flight_test.c | 58 ++++++++++++++++++++++++++++++++++++++++++++-------- src/ao_kalman.c | 14 +++++++++++++ 4 files changed, 72 insertions(+), 16 deletions(-) diff --git a/src/ao.h b/src/ao.h index d3e588b6..9cde9cba 100644 --- a/src/ao.h +++ b/src/ao.h @@ -829,6 +829,7 @@ extern __pdata int16_t ao_height; /* meters */ extern __pdata int16_t ao_speed; /* m/s * 16 */ extern __pdata int16_t ao_accel; /* m/s² * 16 */ extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ extern __pdata int16_t ao_error_h; extern __pdata int16_t ao_error_h_sq_avg; diff --git a/src/ao_flight.c b/src/ao_flight.c index f1b60d69..a8760ff0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -43,7 +43,6 @@ __pdata uint16_t ao_launch_tick; /* time of launch detect */ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; - __pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in @@ -242,7 +241,7 @@ ao_flight(void) /* initialize interval values */ ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_min_height = ao_interval_max_height = ao_avg_height; /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -279,14 +278,14 @@ ao_flight(void) * barometer: altitude stable and within 1000m of the launch altitude */ - if (ao_height < ao_interval_min_height) - ao_interval_min_height = ao_height; - if (ao_height > ao_interval_max_height) - ao_interval_max_height = ao_height; + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { if (ao_height < AO_M_TO_HEIGHT(1000) && - ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) { ao_flight_state = ao_flight_landed; @@ -295,7 +294,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } - ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_min_height = ao_interval_max_height = ao_avg_height; ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 72ad1450..e55d5ade 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -155,6 +155,7 @@ FILE *emulator_in; char *emulator_app; char *emulator_name; double emulator_error_max = 4; +double emulator_height_error_max = 20; /* noise in the baro sensor */ void ao_dump_state(void); @@ -224,12 +225,20 @@ static int ao_test_max_height; static double ao_test_max_height_time; static int ao_test_main_height; static double ao_test_main_height_time; +static double ao_test_landed_time; +static double ao_test_landed_height; +static double ao_test_landed_time; +static int landed_set; +static double landed_time; +static double landed_height; void ao_test_exit(void) { double drogue_error; double main_error; + double landed_error; + double landed_time_error; if (!ao_test_main_height_time) { ao_test_main_height_time = ao_test_max_height_time; @@ -237,16 +246,23 @@ ao_test_exit(void) } drogue_error = fabs(ao_test_max_height_time - drogue_time); main_error = fabs(ao_test_main_height_time - main_time); - if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + landed_error = fabs(ao_test_landed_height - landed_height); + landed_time_error = ao_test_landed_time - landed_time; + if (drogue_error > emulator_error_max || main_error > emulator_error_max || + landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { printf ("%s %s\n", emulator_app, emulator_name); printf ("\tApogee error %g\n", drogue_error); printf ("\tMain error %g\n", main_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + printf ("\tLanded height error %g\n", landed_error); + printf ("\tLanded time error %g\n", landed_time_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", - drogue_height, drogue_time, main_height, main_time); + ao_test_main_height, ao_test_main_height_time, + ao_test_landed_height, ao_test_landed_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + drogue_height, drogue_time, main_height, main_time, + landed_height, landed_time); exit (1); } exit(0); @@ -274,14 +290,27 @@ ao_insert(void) if (ao_test_max_height < height) { ao_test_max_height = height; ao_test_max_height_time = time; + ao_test_landed_height = height; + ao_test_landed_time = time; } if (height > ao_config.main_deploy) { ao_test_main_height_time = time; ao_test_main_height = height; } + if (ao_test_landed_height > height) { + ao_test_landed_height = height; + ao_test_landed_time = time; + } + + if (ao_flight_state == ao_flight_landed && !landed_set) { + landed_set = 1; + landed_time = time; + landed_height = height; + } + if (!ao_summary) { - printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", + printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", time, height, accel, @@ -289,11 +318,13 @@ ao_insert(void) ao_k_height / 65536.0, ao_k_speed / 65536.0 / 16.0, ao_k_accel / 65536.0 / 16.0, + ao_avg_height, drogue_height, main_height, ao_error_h_sq_avg); - if (ao_flight_state == ao_flight_landed) - ao_test_exit(); + +// if (ao_flight_state == ao_flight_landed) +// ao_test_exit(); } } } @@ -495,6 +526,17 @@ ao_sleep(void *wchan) a = atoi(words[12]); b = atoi(words[14]); } + } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { + tick = strtol(words[1], NULL, 16); + a = 16384 - 328; + b = strtol(words[2], NULL, 10); + type = 'A'; + if (!ao_flight_started) { + ao_flight_ground_accel = 16384 - 328; + ao_config.accel_plus_g = 16384 - 328; + ao_config.accel_minus_g = 16384 + 328; + ao_flight_started = 1; + } } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { char *hex = words[1]; char elt[3]; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index 4e6cbb06..ab97fc34 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -38,6 +38,8 @@ __pdata int16_t ao_height; __pdata int16_t ao_speed; __pdata int16_t ao_accel; __pdata int16_t ao_max_height; +static __pdata int32_t ao_avg_height_scaled; +__pdata int16_t ao_avg_height; __pdata int16_t ao_error_h; __pdata int16_t ao_error_h_sq_avg; @@ -275,6 +277,18 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_avg_height = ao_height; + } else if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height = (ao_avg_height_scaled + 3) >> 2; + } else +#endif + { + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height = (ao_avg_height_scaled + 15) >> 5; + } #ifdef AO_FLIGHT_TEST ao_sample_prev_tick = ao_sample_tick; #endif -- cgit v1.2.3 From 6c55bf35b11ae3ddae152795072d69e98184bac1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 01:49:35 -0700 Subject: altos: Reduce height averaging filter time constant Using the longer time constant could lead to false landing detection just after apogee, which is definitely not a good idea. Signed-off-by: Keith Packard --- src/ao_kalman.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/ao_kalman.c b/src/ao_kalman.c index ab97fc34..203d727a 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -277,18 +277,15 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; #ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_avg_height = ao_height; - } else if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; - ao_avg_height = (ao_avg_height_scaled + 3) >> 2; - } else + if (ao_sample_tick - ao_sample_prev_tick > 50) + ao_avg_height = (ao_avg_height_scaled + 1) >> 1; + else if (ao_sample_tick - ao_sample_prev_tick > 5) + ao_avg_height = (ao_avg_height_scaled + 7) >> 4; + else #endif - { - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; - ao_avg_height = (ao_avg_height_scaled + 15) >> 5; - } + ao_avg_height = (ao_avg_height_scaled + 63) >> 7; #ifdef AO_FLIGHT_TEST ao_sample_prev_tick = ao_sample_tick; #endif -- cgit v1.2.3 From 82e04a0e3a3296288a524ec582785a36fd644331 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 02:09:23 -0700 Subject: altos: Require sequencing through 'main' state before landing The old version of the code would permit the flight to go straight from 'drogue' to 'landed' without passing through 'main' at all. This meant that a false landing detection would leave the main charge unfired, potentially causing the airframe to land on drogue alone. Requiring that the flight sequence pass through main ensures that the main charge will get fired at the right time, although if the airframe lands higher than that altitude, it will not go to 'landed' mode ever. Signed-off-by: Keith Packard --- src/ao_flight.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index a8760ff0..af3d6bfa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -233,16 +233,6 @@ ao_flight(void) /* Turn the RDF beacon back on */ ao_rdf_set(1); - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - /* and enter drogue state */ ao_flight_state = ao_flight_drogue; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -266,16 +256,28 @@ ao_flight(void) if (ao_height <= ao_config.main_deploy) { ao_ignite(ao_igniter_main); + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_flight_state = ao_flight_main; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } + break; /* fall through... */ case ao_flight_main: - /* drogue/main to land: + /* main to land: * - * barometer: altitude stable and within 1000m of the launch altitude + * barometer: altitude stable */ if (ao_avg_height < ao_interval_min_height) @@ -284,8 +286,7 @@ ao_flight(void) ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_height < AO_M_TO_HEIGHT(1000) && - ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) { ao_flight_state = ao_flight_landed; -- cgit v1.2.3 From 95201e7fe4a6a7ec42321e8dbad3aea3bbf4c840 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 17:40:02 -0700 Subject: altosui: Standard text field in flight UI needs more width (now 20) Latitude and longitude take more than 16 characters. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 8d5916ad..1acce949 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -98,7 +98,7 @@ public class Altos { static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); static final Font status_font = new Font("SansSerif", Font.BOLD, 24); - static final int text_width = 16; + static final int text_width = 20; static void initialize_map() { -- cgit v1.2.3 From 37c41c962ea4631e62307a57d2ce6572b87fd743 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 17:41:02 -0700 Subject: altosui: Parse accel cal from 'c s' command These fields weren't used before, so the code to parse them hadn't been written. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 3f0e9af3..6b80171a 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -95,6 +95,15 @@ public class AltosConfigData implements Iterable { try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { + if (line.startsWith("Accel cal")) { + String[] bits = line.split("\\s+"); + if (bits.length >= 6) { + accel_cal_plus = Integer.parseInt(bits[3]); + accel_cal_minus = Integer.parseInt(bits[5]); + } + } + } catch (Exception e) {} try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} -- cgit v1.2.3 From 3cc2eed6cdafe788a8617ab45c6664077e76411e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 18:01:52 -0700 Subject: altosui: Simple timeouts don't work with query data To get the query to come back, it's best to abort and retry the command, other wise the command may have been lost to the previous connection. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 2 +- altosui/AltosSerial.java | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 6b80171a..1d50ade9 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -85,7 +85,7 @@ public class AltosConfigData implements Iterable { serial_line.printf("c s\nv\n"); lines = new LinkedList(); for (;;) { - String line = serial_line.get_reply(5000); + String line = serial_line.get_reply_no_dialog(5000); if (line == null) throw new TimeoutException(); if (line.contains("Syntax error")) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 8f8f99d7..cb82a574 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -233,12 +233,14 @@ public class AltosSerial implements Runnable { abort = false; timeout_started = false; for (;;) { + System.out.printf("timeout %d\n", timeout); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) { stop_timeout_dialog(); --in_reply; return line.line; } + System.out.printf("no line remote %b can_cancel %b\n", remote, can_cancel); if (!remote || !can_cancel || check_timeout()) { --in_reply; return null; @@ -246,6 +248,14 @@ public class AltosSerial implements Runnable { } } + public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { + flush_output(); + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) + return line.line; + return null; + } + public void add_monitor(LinkedBlockingQueue q) { set_monitor(true); monitors.add(q); -- cgit v1.2.3 From 11a2bb8e28df7ed87542f2ee726f877971f5d52a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 17:41:53 -0700 Subject: altosui: Add idle monitor dialog This monitors a telemetrum device in idle mode, either directly or through a teledongle, allowing the GPS status and batteries to be monitored without resorting to placing the device in pad mode. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 388 ++++++++++++++++++++++++++++++++++++++++ altosui/AltosState.java | 2 +- altosui/AltosUI.java | 14 ++ altosui/Makefile.am | 1 + 4 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 altosui/AltosIdleMonitorUI.java diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java new file mode 100644 index 00000000..a4262cae --- /dev/null +++ b/altosui/AltosIdleMonitorUI.java @@ -0,0 +1,388 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +class AltosADC { + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + + public AltosADC(AltosSerial serial) throws InterruptedException, TimeoutException { + serial.printf("a\n"); + for (;;) { + String line = serial.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("accel:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("pres:")) { + pres = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("temp:")) { + temp = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("drogue:")) { + drogue = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + } + break; + } + } +} + +class AltosGPSQuery extends AltosGPS { + public AltosGPSQuery (AltosSerial serial) throws TimeoutException, InterruptedException { + serial.printf("g\n"); + for (;;) { + String line = serial.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] bits = line.split("\\s+"); + if (bits.length == 0) + continue; + if (line.startsWith("Date:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split(":"); + if (d.length < 3) + continue; + year = Integer.parseInt(d[0]) + 2000; + month = Integer.parseInt(d[1]); + day = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Time:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split("/"); + if (d.length < 3) + continue; + hour = Integer.parseInt(d[0]); + minute = Integer.parseInt(d[1]); + second = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Lat/Lon:")) { + if (bits.length < 3) + continue; + lat = Integer.parseInt(bits[1]) * 1.0e-7; + lon = Integer.parseInt(bits[2]) * 1.0e-7; + continue; + } + if (line.startsWith("Alt:")) { + if (bits.length < 2) + continue; + alt = Integer.parseInt(bits[1]); + continue; + } + if (line.startsWith("Flags:")) { + if (bits.length < 2) + continue; + int status = Integer.decode(bits[1]); + connected = (status & Altos.AO_GPS_RUNNING) != 0; + locked = (status & Altos.AO_GPS_VALID) != 0; + continue; + } + if (line.startsWith("Sats:")) { + if (bits.length < 2) + continue; + nsat = Integer.parseInt(bits[1]); + cc_gps_sat = new AltosGPSSat[nsat]; + for (int i = 0; i < nsat; i++) { + int svid = Integer.parseInt(bits[2+i*2]); + int cc_n0 = Integer.parseInt(bits[3+i*2]); + cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0); + } + } + if (line.startsWith("done")) + break; + if (line.startsWith("Syntax error")) + break; + } + } +} + +class AltosIdleMonitor extends Thread { + AltosDevice device; + AltosSerial serial; + AltosIdleMonitorUI ui; + AltosState state; + boolean remote; + int channel; + AltosState previous_state; + AltosConfigData config_data; + AltosADC adc; + AltosGPS gps; + + void update_state() throws InterruptedException, TimeoutException { + AltosRecord record = new AltosRecord(); + + try { + if (remote) { + set_channel(channel); + serial.start_remote(); + } else + serial.flush_input(); + config_data = new AltosConfigData(serial); + adc = new AltosADC(serial); + gps = new AltosGPSQuery(serial); + } finally { + if (remote) + serial.stop_remote(); + } + + record.version = 0; + record.callsign = config_data.callsign; + record.serial = config_data.serial; + record.flight = 0; + record.rssi = 0; + record.status = 0; + record.state = Altos.ao_flight_idle; + + record.tick = adc.tick; + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; + record.acceleration = 0; + record.speed = 0; + record.height = 0; + record.gps = gps; + state = new AltosState (record, state); + } + + void set_channel(int in_channel) { + channel = in_channel; + } + + public void post_state() { + Runnable r = new Runnable() { + public void run() { + ui.update(state); + } + }; + SwingUtilities.invokeLater(r); + } + + public void run() { + try { + for (;;) { + try { + update_state(); + post_state(); + } catch (TimeoutException te) { + } + Thread.sleep(1000); + } + } catch (InterruptedException ie) { + serial.close(); + } + } + + public AltosIdleMonitor(AltosIdleMonitorUI in_ui, AltosDevice in_device, boolean in_remote) + throws FileNotFoundException, AltosSerialInUseException { + device = in_device; + ui = in_ui; + serial = new AltosSerial(device); + remote = in_remote; + state = null; + } +} + +public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { + AltosDevice device; + JTabbedPane pane; + AltosPad pad; + AltosInfoTable flightInfo; + AltosFlightStatus flightStatus; + AltosIdleMonitor thread; + int serial; + boolean remote; + + void stop_display() { + if (thread != null && thread.isAlive()) { + thread.interrupt(); + try { + thread.join(); + } catch (InterruptedException ie) {} + } + thread = null; + } + + void disconnect() { + stop_display(); + } + + public void reset() { + pad.reset(); + flightInfo.clear(); + } + + public void show(AltosState state, int crc_errors) { + try { + pad.show(state, crc_errors); + flightStatus.show(state, crc_errors); + flightInfo.show(state, crc_errors); + } catch (Exception e) { + System.out.print("Show exception" + e); + } + } + + public void update(AltosState state) { + show (state, 0); + } + + Container bag; + JComboBox channels; + + public AltosIdleMonitorUI(JFrame in_owner) throws FileNotFoundException, AltosSerialInUseException { + + device = AltosDeviceDialog.show(in_owner, Altos.product_any); + remote = false; + if (!device.matchProduct(Altos.product_telemetrum)) + remote = true; + + serial = device.getSerial(); + bag = getContentPane(); + bag.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + + java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg"); + if (imgURL != null) + setIconImage(new ImageIcon(imgURL).getImage()); + + setTitle(String.format("AltOS %s", device.toShortString())); + + /* Stick channel selector at top of table for telemetry monitoring */ + if (remote && serial >= 0) { + // Channel menu + channels = new AltosChannelMenu(AltosPreferences.channel(serial)); + channels.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int channel = channels.getSelectedIndex(); + thread.set_channel(channel); + } + }); + c.gridx = 0; + c.gridy = 0; + c.insets = new Insets(3, 3, 3, 3); + c.anchor = GridBagConstraints.WEST; + bag.add (channels, c); + } + + + /* Flight status is always visible */ + flightStatus = new AltosFlightStatus(); + c.gridx = 0; + c.gridy = 1; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.gridwidth = 2; + bag.add(flightStatus, c); + c.gridwidth = 1; + + /* The rest of the window uses a tabbed pane to + * show one of the alternate data views + */ + pane = new JTabbedPane(); + + pad = new AltosPad(); + pane.add("Launch Pad", pad); + + flightInfo = new AltosInfoTable(); + pane.add("Table", new JScrollPane(flightInfo)); + + /* Make the tabbed pane use the rest of the window space */ + c.gridx = 0; + c.gridy = 2; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + c.weighty = 1; + c.gridwidth = 2; + bag.add(pane, c); + + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + disconnect(); + setVisible(false); + dispose(); + } + }); + + pack(); + setVisible(true); + + thread = new AltosIdleMonitor(this, device, remote); + + thread.start(); + } +} diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 0ff2479e..d374aed8 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -130,7 +130,7 @@ public class AltosState { time_change = 0; } - if (state == Altos.ao_flight_pad) { + if (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle) { /* Track consecutive 'good' gps reports, waiting for 10 of them */ if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index d8c8d61c..9b724fd7 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -187,6 +187,13 @@ public class AltosUI extends JFrame { } }); + b = addButton(2, 2, "Monitor Idle"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + IdleMonitor(); + } + }); + setTitle("AltOS"); pane.doLayout(); @@ -300,6 +307,13 @@ public class AltosUI extends JFrame { new AltosConfigureUI(AltosUI.this, voice); } + private void IdleMonitor() { + try { + new AltosIdleMonitorUI(this); + } catch (Exception e) { + } + } + static AltosRecordIterable open_logfile(String filename) { File file = new File (filename); try { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e3075d41..008bd097 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -55,6 +55,7 @@ altosui_JAVA = \ AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ + AltosIdleMonitorUI.java \ AltosIgnite.java \ AltosIgniteUI.java \ AltosInfoTable.java \ -- cgit v1.2.3 From 6492218fc316f8cf6214a577807a8dd0a80a9b6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 19:07:56 -0700 Subject: altos/altosui: Add pad orientation configure option Allow TeleMetrum to be operated with the antenna pointing downwards on the pad. This provides some additional flexibility when designing an ebay. The accelerometer calibration levels are flipped around to match, so no re-calibration should be required. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 9 ++++++-- altosui/AltosConfigUI.java | 56 +++++++++++++++++++++++++++++++++++++++++----- altosui/AltosSerial.java | 1 - src/ao.h | 6 ++++- src/ao_config.c | 39 +++++++++++++++++++++++++++++++- src/ao_flight_test.c | 4 ++++ src/ao_sample.c | 2 ++ 7 files changed, 107 insertions(+), 10 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index e3c30d4d..04d75528 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -71,6 +71,7 @@ public class AltosConfig implements ActionListener { int_ref radio_calibration; int_ref flight_log_max; int_ref ignite_mode; + int_ref pad_orientation; string_ref version; string_ref product; string_ref callsign; @@ -132,6 +133,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); + config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); config_ui.make_visible(); @@ -139,12 +141,10 @@ public class AltosConfig implements ActionListener { void process_line(String line) { if (line == null) { - System.out.printf("timeout\n"); abort(); return; } if (line.equals("done")) { - System.out.printf("done\n"); if (serial_line != null) update_ui(); return; @@ -156,6 +156,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Radio cal:", radio_calibration); get_int(line, "Max flight log:", flight_log_max); get_int(line, "Ignite mode:", ignite_mode); + get_int(line, "Pad orientation:", pad_orientation); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -229,6 +230,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c l %d\n", flight_log_max.get()); if (ignite_mode.get() >= 0) serial_line.printf("c i %d\n", ignite_mode.get()); + if (pad_orientation.get() >= 0) + serial_line.printf("c o %d\n", pad_orientation.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { } finally { @@ -312,6 +315,7 @@ public class AltosConfig implements ActionListener { radio_calibration.set(config_ui.radio_calibration()); flight_log_max.set(config_ui.flight_log_max()); ignite_mode.set(config_ui.ignite_mode()); + pad_orientation.set(config_ui.pad_orientation()); callsign.set(config_ui.callsign()); run_serial_thread(serial_mode_save); } @@ -347,6 +351,7 @@ public class AltosConfig implements ActionListener { radio_calibration = new int_ref(1186611); flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); + pad_orientation = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 6f635b9d..1a48c1d3 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -47,6 +47,7 @@ public class AltosConfigUI JLabel radio_calibration_label; JLabel flight_log_max_label; JLabel ignite_mode_label; + JLabel pad_orientation_label; JLabel callsign_label; public boolean dirty; @@ -61,6 +62,7 @@ public class AltosConfigUI JTextField radio_calibration_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; + JComboBox pad_orientation_value; JTextField callsign_value; JButton save; @@ -91,6 +93,11 @@ public class AltosConfigUI "Redundant Main", }; + static String[] pad_orientation_values = { + "Antenna Up", + "Antenna Down", + }; + static String[] radio_channel_values = new String[10]; { for (int i = 0; i <= 9; i++) @@ -358,9 +365,33 @@ public class AltosConfigUI ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); - /* Buttons */ + /* Pad orientation */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 10; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + pad_orientation_label = new JLabel("Pad Orientation:"); + pane.add(pad_orientation_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 10; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + pad_orientation_value = new JComboBox(pad_orientation_values); + pad_orientation_value.setEditable(false); + pad_orientation_value.addItemListener(this); + pane.add(pad_orientation_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -371,7 +402,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 10; + c.gridx = 2; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -382,7 +413,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 10; + c.gridx = 4; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -393,7 +424,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 10; + c.gridx = 6; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -538,13 +569,28 @@ public class AltosConfigUI } else { ignite_mode_value.setEnabled(true); } - ignite_mode_value.setSelectedItem(Integer.toString(new_ignite_mode)); + ignite_mode_value.setSelectedIndex(new_ignite_mode); } public int ignite_mode() { return ignite_mode_value.getSelectedIndex(); } + + public void set_pad_orientation(int new_pad_orientation) { + if (new_pad_orientation < 0) { + pad_orientation_value.setEnabled(false); + new_pad_orientation = 0; + } else { + pad_orientation_value.setEnabled(true); + } + pad_orientation_value.setSelectedIndex(new_pad_orientation); + } + + public int pad_orientation() { + return pad_orientation_value.getSelectedIndex(); + } + public void set_clean() { dirty = false; } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index cb82a574..f45aa18b 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -233,7 +233,6 @@ public class AltosSerial implements Runnable { abort = false; timeout_started = false; for (;;) { - System.out.printf("timeout %d\n", timeout); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) { stop_timeout_dialog(); diff --git a/src/ao.h b/src/ao.h index 9cde9cba..b315af7a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1358,7 +1358,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 5 +#define AO_CONFIG_MINOR 6 struct ao_config { uint8_t major; @@ -1372,12 +1372,16 @@ struct ao_config { uint32_t radio_cal; /* minor version 3 */ uint32_t flight_log_max; /* minor version 4 */ uint8_t ignite_mode; /* minor version 5 */ + uint8_t pad_orientation; /* minor version 6 */ }; #define AO_IGNITE_MODE_DUAL 0 #define AO_IGNITE_MODE_APOGEE 1 #define AO_IGNITE_MODE_MAIN 2 +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 diff --git a/src/ao_config.c b/src/ao_config.c index 48349886..215dda92 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -28,6 +28,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL +#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP #if USE_INTERNAL_EEPROM #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else @@ -77,6 +78,7 @@ _ao_config_get(void) ao_config.radio_cal = ao_radio_cal; ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -97,6 +99,8 @@ _ao_config_get(void) /* Fixupes for minor version 5 */ if (ao_config.minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + if (ao_config.minor < 6) + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -357,7 +361,36 @@ ao_config_ignite_mode_set(void) __reentrant ao_config.ignite_mode = ao_cmd_lex_i; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + ao_config_ignite_mode_show(); +} +#endif + +#if HAS_IGNITE +void +ao_config_pad_orientation_show(void) __reentrant +{ + printf("Pad orientation: %d\n", ao_config.pad_orientation); +} + +void +ao_config_pad_orientation_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_cmd_lex_i &= 1; + if (ao_config.pad_orientation != ao_cmd_lex_i) { + uint16_t t; + t = ao_config.accel_plus_g; + ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; + ao_config.accel_minus_g = 0x7fff - t; + } + ao_config.pad_orientation = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_pad_orientation_show(); } #endif @@ -400,6 +433,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_IGNITE { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", ao_config_ignite_mode_set, ao_config_ignite_mode_show }, +#endif +#if HAS_ACCEL + { "o <0 antenna up, 1 antenna down>\0Set pad orientation", + ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif { "s\0Show", ao_config_show, ao_config_show }, diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e55d5ade..56733c89 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -179,8 +179,12 @@ struct ao_config { uint16_t main_deploy; int16_t accel_plus_g; int16_t accel_minus_g; + uint8_t pad_orientation; }; +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + #define ao_config_get() struct ao_config ao_config; diff --git a/src/ao_sample.c b/src/ao_sample.c index ac156646..88ba58c5 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -179,6 +179,8 @@ ao_sample(void) * just dropped a bit of noise off the low end. */ ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = 0x7fff - ao_sample_accel; ao_adc->accel = ao_sample_accel; #endif #endif -- cgit v1.2.3 From 6d5e5b0be237d5448aa9d15decd6127cf41ca7b2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:30:42 -0600 Subject: update version for a Bdale build for use turning on TeleMini v1.0 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b7af55e4..72289226 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.4) +AC_INIT([altos], 0.9.4.5) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 7c94945690a6ff5cbf872026fd6411a30089c7b1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:33:09 -0600 Subject: simplify version in last changelog entry so git-dch is less confused --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index fe01210d..b4425070 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -altos (0.9.1.telemini.1) unstable; urgency=low +altos (0.9.1) unstable; urgency=low [ Keith Packard ] * ao-load: fix usage message to note that '=' is required for options -- cgit v1.2.3 From 6f9f75cbfccf975204ab847ca0e9cf86188716c6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:35:47 -0600 Subject: update changelogs for Debian build --- ChangeLog | 2431 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 255 ++++++ 2 files changed, 2686 insertions(+) diff --git a/ChangeLog b/ChangeLog index f98de6d6..cb28f93b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,2434 @@ +commit 7c94945690a6ff5cbf872026fd6411a30089c7b1 +Author: Bdale Garbee +Date: Mon Aug 8 07:33:09 2011 -0600 + + simplify version in last changelog entry so git-dch is less confused + +commit 6d5e5b0be237d5448aa9d15decd6127cf41ca7b2 +Author: Bdale Garbee +Date: Mon Aug 8 07:30:42 2011 -0600 + + update version for a Bdale build for use turning on TeleMini v1.0 + +commit 6492218fc316f8cf6214a577807a8dd0a80a9b6a +Author: Keith Packard +Date: Tue Aug 2 19:07:56 2011 -0700 + + altos/altosui: Add pad orientation configure option + + Allow TeleMetrum to be operated with the antenna pointing downwards on + the pad. This provides some additional flexibility when designing an + ebay. + + The accelerometer calibration levels are flipped around to match, so + no re-calibration should be required. + + Signed-off-by: Keith Packard + +commit 11a2bb8e28df7ed87542f2ee726f877971f5d52a +Author: Keith Packard +Date: Tue Aug 2 17:41:53 2011 -0700 + + altosui: Add idle monitor dialog + + This monitors a telemetrum device in idle mode, either directly or through a + teledongle, allowing the GPS status and batteries to be monitored + without resorting to placing the device in pad mode. + + Signed-off-by: Keith Packard + +commit 3cc2eed6cdafe788a8617ab45c6664077e76411e +Author: Keith Packard +Date: Tue Aug 2 18:01:52 2011 -0700 + + altosui: Simple timeouts don't work with query data + + To get the query to come back, it's best to abort and retry the + command, other wise the command may have been lost to the previous + connection. + + Signed-off-by: Keith Packard + +commit 37c41c962ea4631e62307a57d2ce6572b87fd743 +Author: Keith Packard +Date: Tue Aug 2 17:41:02 2011 -0700 + + altosui: Parse accel cal from 'c s' command + + These fields weren't used before, so the code to parse them hadn't + been written. + + Signed-off-by: Keith Packard + +commit 95201e7fe4a6a7ec42321e8dbad3aea3bbf4c840 +Author: Keith Packard +Date: Tue Aug 2 17:40:02 2011 -0700 + + altosui: Standard text field in flight UI needs more width (now 20) + + Latitude and longitude take more than 16 characters. + + Signed-off-by: Keith Packard + +commit 82e04a0e3a3296288a524ec582785a36fd644331 +Author: Keith Packard +Date: Tue Aug 2 02:09:23 2011 -0700 + + altos: Require sequencing through 'main' state before landing + + The old version of the code would permit the flight to go straight + from 'drogue' to 'landed' without passing through 'main' at all. This + meant that a false landing detection would leave the main charge + unfired, potentially causing the airframe to land on drogue alone. + + Requiring that the flight sequence pass through main ensures that the + main charge will get fired at the right time, although if the airframe + lands higher than that altitude, it will not go to 'landed' mode ever. + + Signed-off-by: Keith Packard + +commit 6c55bf35b11ae3ddae152795072d69e98184bac1 +Author: Keith Packard +Date: Tue Aug 2 01:49:35 2011 -0700 + + altos: Reduce height averaging filter time constant + + Using the longer time constant could lead to false landing detection + just after apogee, which is definitely not a good idea. + + Signed-off-by: Keith Packard + +commit e19a117b99e8374ca0e8e35948e23bc672ad1a32 +Author: Keith Packard +Date: Mon Aug 1 22:33:38 2011 -0700 + + altos: Average height values for landing detection + + Instead of using the direct output of the kalman filter and hoping + that is quiet enough to detect landing, filter that with a long + exponential decay filter and then check to make sure that doesn't + change more than 2m in 5 seconds as a trigger for landing detection. + + Tested with existing telemetrum flight logs and it correctly detects + landing in all cases. + + Signed-off-by: Keith Packard + +commit 146a0ab223e8d9b376125d1e59f597f6d7851a9b +Author: Keith Packard +Date: Sun Jul 17 18:49:55 2011 -0700 + + altos: Add ability to read new TELEM files to ao_flight_test + + Not that telem files are currently very useful as the kalman filter + gets completly confused by the variable steps caused by missing data, but... + + Signed-off-by: Keith Packard + +commit 6795d353be91df96a571cebc237e6a54a065a380 +Author: Keith Packard +Date: Sun Jul 17 16:44:10 2011 -0700 + + altosui: Change continutity colors to yellow/magenta + + Makes them stand apart from the accel/speed lines + + Signed-off-by: Keith Packard + +commit 7f6cce5749724dbb836aaa27bbeedf977106f6f3 +Author: Keith Packard +Date: Sun Jul 17 16:43:41 2011 -0700 + + Add HARA Bragg Farms site + + Signed-off-by: Keith Packard + +commit 6796d9e253a808824ba32cdb008da8bf302780fc +Author: Keith Packard +Date: Sun Jul 17 15:53:13 2011 -0700 + + Fix NCR Pawnee location + + Signed-off-by: Keith Packard + +commit ddef3e4ec1b3ff86b164f83807c34c2a78f73eb8 +Author: Keith Packard +Date: Sun Jul 17 15:45:07 2011 -0700 + + altosui: Mark preload site location with red circles (like launch) + + Just to show where on the map the official launch location is. + + Signed-off-by: Keith Packard + +commit 1f3f3d575572eff33a2bc7a53d4691e59a428450 +Author: Keith Packard +Date: Sun Jul 17 15:09:55 2011 -0700 + + altosui: Add a bunch more site locations + + BALLS, Rio Rancho, METRA, QRS Cedar Grove and Hudson Ranch + + Signed-off-by: Keith Packard + +commit fef42e0d9e0a20bdbd32e052749fc63575515e1c +Author: Keith Packard +Date: Sun Jul 17 11:29:13 2011 -0700 + + altosui: Add launch-sites.txt + + Contains a few of our favorites. + + Signed-off-by: Keith Packard + +commit 81cac174c80ee42d9e94c6500da7c4c760c3ce67 +Author: Keith Packard +Date: Sun Jul 17 11:25:47 2011 -0700 + + altosui: Download list of site locations for map preloading + + The current URL for this is: + http://gag.com/~keithp/launch-sites.txt + + The format is: + :: + + lat and lon are both in signed decimal degrees. + + Signed-off-by: Keith Packard + +commit f7cd8317bf78ece334e1ceb0263b875ca43bbbd2 +Merge: 51796e2 a482d90 +Author: Keith Packard +Date: Sun Jul 17 08:17:44 2011 -0700 + + Merge branch 'preload-maps' + +commit 51796e2f1ebce3ee8dc1ac90648381410c1379ee +Author: Keith Packard +Date: Mon May 23 11:32:29 2011 -0700 + + altos, altosui: Add igniter mode (dual, apogee, main) + + This provides for redundant charges for either apogee or main. + + Signed-off-by: Keith Packard + +commit 1332ed55192f22525f31574f60fae4c6579e6f7f +Author: Keith Packard +Date: Sun Jul 17 08:13:15 2011 -0700 + + Set version to 0.9.4.4 + + Signed-off-by: Keith Packard + +commit a482d904a3f391c3a24df3660acb3f3696aa6766 +Author: Anthony Towns +Date: Sat Jul 16 23:08:49 2011 -0700 + + altosui: Make sure degree and minute values are visible (map preload) + + Set min size to preferred size so that the value remains visible + instead of snapping to 0 pixels wide. + + Signed-off-by: Keith Packard + +commit 1681c57cbbfc5214dbc2a519e54ce9f29ffe3921 +Author: Keith Packard +Date: Sat Jul 16 22:43:34 2011 -0700 + + altosui: Remove a bunch of sitemap debugging printfs + + Seems to work, let's get less chatty + + Signed-off-by: Keith Packard + +commit 0a4d934f6e2914bfe2d965630543f029a1576c11 +Author: Keith Packard +Date: Sat Jul 16 22:34:44 2011 -0700 + + altosui: Display full map preload area in view. + + This involved fixing the map view to support arbitrary sizes, and then + exposing a synchronous tile loading API so that the progress bar could + be used to show tile loading progress. + + Signed-off-by: Keith Packard + +commit abb8510b97ce9cbbff0275cc31f74780fe1ce138 +Merge: 0929ee3 00e6981 +Author: Keith Packard +Date: Sat Jul 16 21:06:37 2011 -0700 + + Merge branch 'scan-telemetry' into preload-maps + +commit 00e6981c2e0a668864fcf391932855cd8942140c +Author: Keith Packard +Date: Sat Jul 16 21:05:06 2011 -0700 + + altosui: Flush telemetry lines before starting to watch for scan results + + This prevents pending telemetry lines from being incorrectly + attributed to the wrong channel/telemetry. + + Signed-off-by: Keith Packard + +commit 0929ee32f753255cbe1474988cb41a5a86d29a0e +Author: Keith Packard +Date: Sat Jul 16 17:37:20 2011 -0700 + + altosui: Try to avoid resize weirdness with map preloading + + grid bag + box does some strange stuff, this appears to avoid the + worst of the interactions. + + Signed-off-by: Keith Packard + +commit 225073fd822f9861a83d65386c29fda9b37bf273 +Author: Keith Packard +Date: Sat Jul 16 16:37:40 2011 -0700 + + altosui: Add map preloading GUI + + Provide a way to manually enter latitude and longitude, preview the + map area while downloading a 9x9 grid of map tiles to be used when + monitoring flights without network access. + + Signed-off-by: Keith Packard + +commit cbd14ba103ee5e3c5eec18e3a4ff13c320b98634 +Author: Keith Packard +Date: Sat Jul 16 20:44:51 2011 -0700 + + altosui: Set 'seen' bits in legacy telemetry packet reader + + Otherwise, the 'scan' code won't show detected flight computers. + + Signed-off-by: Keith Packard + +commit e905042879147dd86241bf2dcc7437e5a6eb7578 +Author: Keith Packard +Date: Sat Jul 16 20:43:57 2011 -0700 + + altosui: Initialize channel and telemetry before use in ScanUI + + Otherwise we try to use telemetry format 0, which means 'no telemetry'. + + Signed-off-by: Keith Packard + +commit 941b90a4905e34936d24a25ca90ac04eb6f5a792 +Author: Keith Packard +Date: Sat Jul 16 17:38:00 2011 -0700 + + altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry + + Move telemetry constants to Altos class, adding functions to compute + names and lengths. Generalize users of these values to use all of the + known values. + + Add support for v0.8 TeleMetrum telemetry + + Signed-off-by: Keith Packard + +commit 7ef786276b5d5c7d17c3fe4f36aa41db61a9742f +Author: Keith Packard +Date: Sat Jul 16 14:23:08 2011 -0700 + + altosui: Finish radio scanning UI + + Scans all channels and telemetry formats, presenting visible devices + in a list. Entries from the list may be selected, in which case a + monitor window pops up with the appropriate configuration. + + Signed-off-by: Keith Packard + +commit ebcba28b3c09925869b617880d2919e5d0e059f0 +Author: Keith Packard +Date: Sat Jul 16 14:19:41 2011 -0700 + + altosui: Configuration telemetry record includes flight number + + Mark the reported altos record as including flight information. + + Signed-off-by: Keith Packard + +commit d4375bc737655546c2d40f49acdfc2e60ebfea5a +Author: Keith Packard +Date: Sat Jul 16 14:19:14 2011 -0700 + + altosui: Remove debugging printf from AltosLog + + Signed-off-by: Keith Packard + +commit f32a55ac9a3ebbde2b41782f22491e72258fe05a +Author: Keith Packard +Date: Sat Jul 9 19:00:12 2011 -0700 + + altosui: Pop up monitor window from scan dialog + + Signed-off-by: Keith Packard + +commit 8c20030ea4eb8e068e1ba88e01d07dfbc27bd7db +Author: Keith Packard +Date: Sat Jul 9 18:41:15 2011 -0700 + + altosui: Start adding support for scanning radio for available devices + + This is untested. + + Signed-off-by: Keith Packard + +commit 7bb11b716ccb6c80701bc3f34ecf9bef97cbbfc9 +Author: Keith Packard +Date: Fri Jul 15 18:53:41 2011 -0700 + + Set version to 0.9.4.3 for Bdale 2011-7-16 flights + + Signed-off-by: Keith Packard + +commit 0d0cf6f9a1b14a1b66aee3845964cd33d1f035c2 +Author: Keith Packard +Date: Sat Jul 9 13:09:57 2011 -0700 + + altos: new versions of sdcc require __ prefixes for custom keywords + + Fortunately, 2.9.1 appears to accept either, so we can switch now and + prepare for sdcc 3.0.0. + + Signed-off-by: Keith Packard + +commit 8f80f5705d64469bcfb00ff11aee68364edb271b +Author: Keith Packard +Date: Wed Jul 6 21:38:57 2011 -0700 + + altosui: Don't show missing igniter and gps values + + The new telemetry stuff leaves state.gps always set (but empty), which + seems fine, we just need to look at state.gps.connected to see if + there's a GPS receiver on board. + + For TeleNano, we also want to hide the igniter status fields as they + won't have any data present. + + Signed-off-by: Keith Packard + +commit 80ca066a825646f833ca609190c76c5252118d9a +Author: Keith Packard +Date: Wed Jul 6 21:36:38 2011 -0700 + + altosui: Build device constants into .java code + + This eliminates a depedency on updates to the system helper library, + which means we don't have to provide a new library on all platforms + just to support a new USB id. + + Signed-off-by: Keith Packard + +commit 504ab7ab355652d5d01094c927089029596a0753 +Author: Keith Packard +Date: Wed Jul 6 17:49:01 2011 -0700 + + altos: product defines are always in ao_product.h + + When all products were built in a single directory, each one had a + separate version of ao_product.h. Now that they all reside in + sub-directories, each directory has its own ao_product.h + + This change is needed so that other modules in the system can use the + product defines; otherwise, ao_product.h was not built at the right time. + + Signed-off-by: Keith Packard + +commit 81cf2e833bedbc1ace8fd310e9e94bfb7673d428 +Author: Keith Packard +Date: Wed Jul 6 16:43:17 2011 -0700 + + altos: Ensure low-rate telem packets interleave with sensor telem packets + + To avoid over-committing the radio link, we want to send only + one low rate packet after each sensor packet. However, the + initializations for this were incorrect, causing the configuration and + location packets to be sent at the same time. + + Signed-off-by: Keith Packard + +commit 5ca6400fd8a360b64d8f96f50d5595a7fd17762d +Author: Keith Packard +Date: Wed Jul 6 16:18:54 2011 -0700 + + altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c + + All products use the common ao_telemetry.c code now + + Signed-off-by: Keith Packard + +commit 0154d13756bcb09f009981ee5e4bd27fd04b8788 +Author: Keith Packard +Date: Wed Jul 6 16:19:22 2011 -0700 + + altos: Switch Tm and Tn to common telemetry code + + Signed-off-by: Keith Packard + +commit b65140a0139075adeddaccf0f4d5c7a75fac4757 +Author: Keith Packard +Date: Wed Jul 6 15:52:25 2011 -0700 + + altos: Switch flash drivers __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 038d7b25ba833da4be458409670d3f95e8aaf17b +Author: Keith Packard +Date: Wed Jul 6 15:51:52 2011 -0700 + + altos: Switch ao_flight and ao_flight_nano __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 3742b36a528f114c3b1873caa4f39581145b76da +Author: Keith Packard +Date: Wed Jul 6 15:28:01 2011 -0700 + + altos: Switch ao_dbg.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 6903b6464db7eb803de8bf9b897c45431f7a1d63 +Author: Keith Packard +Date: Wed Jul 6 15:27:32 2011 -0700 + + altos: Switch ao_config.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 6893752900385ee51cc4cf75e1b672202de7578a +Author: Keith Packard +Date: Wed Jul 6 15:26:09 2011 -0700 + + altos: switch ao_cmd __xdata to __pdata + + Saves code space + + Signed-off-by: Keith Packard + +commit 2ec986f08ce8d4635f4435bb0042b405d93edc40 +Author: Keith Packard +Date: Wed Jul 6 15:45:04 2011 -0700 + + altos: Switch const for __code in struct ao_cmds + + This saves quite a bit of code space when accessing these values. + + Signed-off-by: Keith Packard + +commit 355db71f4511adff8abcb2caded61c12fe8b7ee9 +Author: Keith Packard +Date: Wed Jul 6 15:41:32 2011 -0700 + + altos: Switch ao_usb.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 359baab005c274a0841268c615c23b3ffef813cf +Author: Keith Packard +Date: Wed Jul 6 15:41:06 2011 -0700 + + altos: Switch ao_telemetry.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit f2f8ade6994aa3a69fd08f19c4403ceb8cea295d +Author: Keith Packard +Date: Wed Jul 6 15:39:44 2011 -0700 + + altos: Switch ao_stdio.c __data to __pdata + + Signed-off-by: Keith Packard + +commit 9ba0da9247ea424a7a147aa85daae0d5e6316b81 +Author: Keith Packard +Date: Wed Jul 6 15:38:46 2011 -0700 + + altos: Switch ao_serial.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 86b41d4c2b8a9fa4507cdb75302e0cedebb103cb +Author: Keith Packard +Date: Wed Jul 6 15:38:29 2011 -0700 + + altos: Switch ao_sample.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 803bf106caf5d6b5ac12eb00a941647c7325edd1 +Author: Keith Packard +Date: Wed Jul 6 15:37:34 2011 -0700 + + altos: Switch ao_rssi.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 002f167fc2709aaf1a4984aaa0a3519a97749d5f +Author: Keith Packard +Date: Wed Jul 6 15:37:15 2011 -0700 + + altos: Switch ao_report.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 5203ddaac692bfd82a01368da9fb66c25e9e14c1 +Author: Keith Packard +Date: Wed Jul 6 15:36:45 2011 -0700 + + altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 62267144d189967fcd0724b6dfbdbab3cb6fb414 +Author: Keith Packard +Date: Wed Jul 6 15:33:52 2011 -0700 + + altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 92047ff86c79c2b18ef565a4560b06fe00d6f159 +Author: Keith Packard +Date: Wed Jul 6 15:31:53 2011 -0700 + + altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata + + Signed-off-by: Keith Packard + +commit 64860be02b3efa6f784a259249cfa6d14545fbd3 +Author: Keith Packard +Date: Wed Jul 6 13:49:05 2011 -0700 + + altos: Shrink ao_add_task by rolling up a memset loop + + This has a dramatic effect. By pulling the 'stack' variable into + registers it reduces the size of this function from 550 to 231 bytes. + + Signed-off-by: Keith Packard + +commit 480b48837db31987b947e4d32248965d4a16be03 +Author: Keith Packard +Date: Wed Jul 6 13:21:25 2011 -0700 + + altos: Shrink ao_config_callsign_set + + Replacing a hand-coded memset with a function call, using static space + instead of stack space for an array. + + Signed-off-by: Keith Packard + +commit 41c230cac359b4459ca93196d08704b7d35447c7 +Author: Keith Packard +Date: Wed Jul 6 12:38:11 2011 -0700 + + altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd + + No functional changes, just reduces code size. + + Signed-off-by: Keith Packard + +commit 481577a29380afe6750ef7c4e928daff837cbc49 +Author: Keith Packard +Date: Tue Jul 5 23:38:42 2011 -0700 + + altosui: Compress telemetry records marked with the same time + + Split telemetry transmits multiple packets with the same + timestamp. Merge those into a single record when read from a file. + + Signed-off-by: Keith Packard + +commit 7cfd43663cde5ebdf04e4face076d79ff6329ac3 +Author: Keith Packard +Date: Tue Jul 5 23:38:28 2011 -0700 + + altosui: Remove debug printf. + + Signed-off-by: Keith Packard + +commit d0335f83c54df0b23c28d04d34c212a1bdffadd0 +Author: Keith Packard +Date: Tue Jul 5 23:37:51 2011 -0700 + + altosui: Add main/drogue voltages to default graph + + Until we get a UI for changing the graph elements, lets add a few more + potentially useful values. + + Signed-off-by: Keith Packard + +commit c1f859170b37864b816eb561318dbfb1cafaeed6 +Author: Keith Packard +Date: Tue Jul 5 23:37:00 2011 -0700 + + altosui: Elide missing values from graphs + + Signed-off-by: Keith Packard + +commit 72575dcb9cfbb5c1ccdb3510b9962a6f60ca3fa3 +Author: Keith Packard +Date: Tue Jul 5 23:35:50 2011 -0700 + + altosui: Elide nul bytes at end of telemetry string values + + All telemetry fields are fixed length, so any embedded strings are + padded with nul bytes. + + Signed-off-by: Keith Packard + +commit 6ac34f9c8efd464194137ac4ce8228bf9d7d83be +Author: Keith Packard +Date: Tue Jul 5 23:35:02 2011 -0700 + + doc: Add section about TeleDongle USB line format + + Describe the format of the TELEM lines sent over USB from TeleDongle + to the host. + + Signed-off-by: Keith Packard + +commit edf6252450e06fd42fa6dde3acd127baa8fa6d36 +Author: Keith Packard +Date: Tue Jul 5 21:44:53 2011 -0700 + + altos: Adapt to changes in telemetry Configuration packet + + Apogee delay added. flight_log_max changed to two bytes (in kB now). + + Signed-off-by: Keith Packard + +commit 938949e39aac834a1c0912f8f307f74fe41418cc +Author: Keith Packard +Date: Tue Jul 5 21:42:22 2011 -0700 + + doc: Chang Config and Location packets + + Config packets get apogee delay, and have flight_log_max shrunk to two + bytes. + + Location packets get climb_rate added. + + Signed-off-by: Keith Packard + +commit 4132ac5896114e5f3d8fb3f219422e8933078cf4 +Author: Keith Packard +Date: Tue Jul 5 21:41:44 2011 -0700 + + altosui: Parse remaining standard telemetry packets + + Signed-off-by: Keith Packard + +commit ef3ce687d73c1274ce5368432f4d449b063ce5c0 +Author: Keith Packard +Date: Mon Jul 4 23:39:21 2011 -0700 + + altos: Complete new telemetry switchover + + This involved rewriting the GPS code to use the telemetry structures + directly so that a memcpy could be used to transfer the data to the + telemetry packets, saving a bunch of code space, along with fixing up + the gps testing programs to deal with the structure changes. + + In addition, the teledongle code needed to have the monitoring code + split into separate radio receiver and USB writer threads as the + packets are now back-to-back, and hence come too fast to wait for the + USB data to be sent to the host after each one. + + Signed-off-by: Keith Packard + +commit 359681f23e2f71bc8f4975a4a76ae28c08ecab2e +Author: Keith Packard +Date: Mon Jul 4 18:09:03 2011 -0700 + + altos: Add split telemetry code + + This sends every packet every time, which isn't correct, but should be + useful for testing. + + Signed-off-by: Keith Packard + +commit b51e5466f7a125db873edd1fa9bd3881d7e98aad +Author: Keith Packard +Date: Mon Jul 4 18:08:19 2011 -0700 + + altos: Shrink help text + + Reduce const space taken by command help text. + + Signed-off-by: Keith Packard + +commit 9e5e4c1ad82d621ceb7286f72c87eeaf5976f9bf +Author: Keith Packard +Date: Mon Jul 4 18:06:48 2011 -0700 + + altos: Add sat info to GPS report command + + Plan to use this to report current flight computer state in idle mode. + + Signed-off-by: Keith Packard + +commit 06b6f78e22be38a26bfe11ed4d4b659d5b13f00c +Author: Keith Packard +Date: Mon Jul 4 18:04:49 2011 -0700 + + altos: Shrink const space in ao_config + + Eliminate separate 'cmd' and 'help' struct entries. + Use \0 trick in cmd strings to eliminate whitespace. + Edit help text. + + Signed-off-by: Keith Packard + +commit d3c26e534d8df34cfbf29b70cd1b2692493ce150 +Author: Keith Packard +Date: Mon Jul 4 18:03:51 2011 -0700 + + altos: teledongle does not need ao_packet_slave.c + + TeleDongle doesn't provide slave interfaces, so remove ao_packet_slave + from the TD build + + Signed-off-by: Keith Packard + +commit c763a3f9cf2bf055e9705ce5ff4bc172f445037d +Author: Keith Packard +Date: Mon Jul 4 18:02:52 2011 -0700 + + Version strings must be < 8 bytes long + + The new telemetry packets include the version string, so make sure its + less than 8 characters long + + Signed-off-by: Keith Packard + +commit a08173197d5533ecb395102ed34e751135660d06 +Author: Keith Packard +Date: Mon Jul 4 18:01:59 2011 -0700 + + doc: Fix a few minor telemetry doc mistakes + + Multiple 'accel' entries in the Sensor packet. + Swap ground_accel and ground_pres to group accel cal data + + Signed-off-by: Keith Packard + +commit 98df3ba984acf3b47a09949bbea0f3264f711f5b +Author: Keith Packard +Date: Mon Jul 4 14:17:55 2011 -0700 + + doc: Complete initial telemetry description + + Finish describing the contents and modulation scheme for telemetry + data. + + Signed-off-by: Keith Packard + +commit 06e82bd2c2a5eea153a053e542df9bc3537e9a01 +Author: Keith Packard +Date: Sat Jul 2 01:50:33 2011 -0700 + + doc: Add telemetry format description + + Document the telemetry packet contents. + + Signed-off-by: Keith Packard + +commit 7fd9b8f720add559b262e81d61ededc9df16ca94 +Author: Keith Packard +Date: Tue Jun 28 01:03:00 2011 -0700 + + altosui: Support raw telemetry from TeleDongle + + Use raw telemetry frames when TeleDongle supports them, this involves + parsing the hex dump of the packet instead of having teledongle take + the packet apart. Only the legacy format is working at this point; the + altos bits for the new split telemetry frames is not written yet. + + Signed-off-by: Keith Packard + +commit cb239b7161feea8646425b1f5788c3c82ae24321 +Author: Keith Packard +Date: Tue Jun 28 01:01:08 2011 -0700 + + altos: ao_radio_recv needs byte count *including* rssi and status + + That's two more than the actual packet length. + + Signed-off-by: Keith Packard + +commit 336224a08327cadc95f6e5b564a4ddc64aaad8f8 +Author: Keith Packard +Date: Fri Jun 24 08:31:51 2011 -0700 + + altos: Start adding new telemetry frame definitions + + These use the initial 24 bytes per frame plan, which will probably get + changed to 32 bytes per frame. + + Signed-off-by: Keith Packard + +commit 5e111fdf1f23203baeeb490ae1b69402ebd513b8 +Author: Keith Packard +Date: Fri Jun 24 08:31:12 2011 -0700 + + altos: Add checksum to TELEM output lines + + Verify the received telemetry lines to protect against OS data loss + + Signed-off-by: Keith Packard + +commit 489a68ba8e3bc360e2e8fc887e4c4b840b5a0dd3 +Author: Keith Packard +Date: Wed Jun 22 12:27:34 2011 -0700 + + altos: Add arbitrary telemetry packet monitoring + + This adds the ability to monitor arbitrary telemetry packets (up to + 128 bytes), moving the telemetry data parsing up to the host. + + Signed-off-by: Keith Packard + +commit 0e67b6890dd3a06665239f8dfd2e69266d055e46 +Author: Keith Packard +Date: Wed Jun 22 12:26:45 2011 -0700 + + altos: Rename telemetry to telemetry_orig + + This makes room to create a new multi-packet telemetry format without + changing anything yet. + + Signed-off-by: Keith Packard + +commit dc0b49dcbaa2d0a69e002c151337b6e9fd3060d9 +Author: Keith Packard +Date: Thu Jun 2 23:16:30 2011 -0700 + + altosui: Handle old TeleDongle receiving kalman telemetry packets + + The telemetry packets now send the kalman height/speed/accel values + instead of the ad-hoc values. If received by an old TeleDongle box, + the speed value will be of the form 0x8000abcd, which will be printed + as a 32-bit value by TeleDongle. We only want the abcd part, which is + the speed * 16. Detect this automatically and compute the correct + values for all three. + + Signed-off-by: Keith Packard + +commit 4d27e281f81aee88adff3d84085356ec310e4b92 +Author: Keith Packard +Date: Wed May 25 21:38:02 2011 -0600 + + Switch version to 0.9.4 + + For Mayhem, so we can tell what version each board is running + + Signed-off-by: Keith Packard + +commit 479bdffa35d0b8d4e48868c8d20f3cb1549521ab +Author: Keith Packard +Date: Fri May 6 23:55:23 2011 -0700 + + Revert "altos: Debugging TBT issues -- check pin configuration after boot" + + This reverts commit 514348055630edec12224c4b0964240b929759a3. + + Looks like this was never a problem. + +commit 66bdf0e066bc0bb7a326a6c2a9c88b69e5c1be66 +Author: Keith Packard +Date: Fri May 6 23:12:47 2011 -0700 + + altos: clear CPU port 1 interrupt flag when handled + + Signed-off-by: Keith Packard + +commit 8be559baa979c15e78f8dba7879b383dbe3936d3 +Author: Keith Packard +Date: Fri May 6 22:59:15 2011 -0700 + + altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line + + Otherwise, we're heading off into the weeds... + + Signed-off-by: Keith Packard + +commit 23f441b95e55fbee709382b05d325bc021285766 +Author: Keith Packard +Date: Fri May 6 22:49:54 2011 -0700 + + altos: Initialize beeper for telebt + + Needed to get sounds to come out + + Signed-off-by: Keith Packard + +commit 514348055630edec12224c4b0964240b929759a3 +Author: Keith Packard +Date: Fri May 6 22:42:58 2011 -0700 + + altos: Debugging TBT issues -- check pin configuration after boot + + Make sure the serial pins are configured as peripherals + Make sure the ser_reset and bt_link pins are going the right direction. + + Signed-off-by: Keith Packard + +commit 22e3ac0eb014b8255029763ae8180ad3527ba306 +Author: Keith Packard +Date: Fri May 6 22:42:32 2011 -0700 + + altos: Add beeper to TBT v0.1 + + It's available, let's use it. + + Signed-off-by: Keith Packard + +commit 6d858b64ee0e8c227c149d2af6d2d634536964f4 +Author: Keith Packard +Date: Fri May 6 22:12:31 2011 -0700 + + altos: pull TBT v0.1 ser_reset line low + + This line resets the BT module if held low for three seconds. + + Signed-off-by: Keith Packard + +commit 3336d0f726afd1d43cf62280940e5fb91dab2e91 +Author: Keith Packard +Date: Fri May 6 21:13:19 2011 -0700 + + altos: Fix BT link status pin for real TBT hardware + + The prototype used P2_1, while the real hardware uses P1_7. Lots of + defines to make this work... + + Signed-off-by: Keith Packard + +commit 19bfa3882a2d95fcade256c2d63ad24f794281e5 +Author: Keith Packard +Date: Fri May 6 20:33:58 2011 -0700 + + altos: Use USART configuration 1 with flow control for TBT + + It's just wired that way. + + Signed-off-by: Keith Packard + +commit d9cc27641fe1778c098b065bf110be7823e6c9f4 +Author: Keith Packard +Date: Fri May 6 16:57:38 2011 -0700 + + altos: Add telebt-v0.1 to Makefile + + Doesn't get built without it. + + Signed-off-by: Keith Packard + +commit c360e5c04e30421e9ea2f7006b7d35aef35f1edd +Author: Bdale Garbee +Date: Fri May 6 17:57:17 2011 -0600 + + first cut at a telebt turn on script + +commit c1760cebd47d0f03808f3204c0fcb1183f754e50 +Author: Keith Packard +Date: Fri May 6 15:44:56 2011 -0700 + + altos: Add preliminary telebt v0.1 defines + + This should make the telebt v0.1 binary that works on the real hardware. + + Signed-off-by: Keith Packard + +commit 72a03baa73698fc1213a74320e6253c2380dd8fa +Author: Keith Packard +Date: Mon Apr 25 23:00:42 2011 -0700 + + altosui: Fix BT manage dialog so that the device lists resize + + This makes the device scrolling lists fill any extra space when the + window is resized. + + Signed-off-by: Keith Packard + +commit e3bf13a38d24e95b16df1e2f01952d10f24cda10 +Author: Keith Packard +Date: Mon Apr 25 22:55:08 2011 -0700 + + altosui: Move AltosIgniteUI device open out of Swing thread + + Eliminate more blocking code from the Swing thread. + + Signed-off-by: Keith Packard + +commit 109344d54d3fa4f79342fd1ea2a3f4085475e30c +Author: Keith Packard +Date: Mon Apr 25 22:28:40 2011 -0700 + + altosui: Display reader name (usually the device) when an I/O error occurs + + Access the reader name directly from the reader object instead of a + local variable (which wasn't getting set anyways). + + Signed-off-by: Keith Packard + +commit aa5caf6310f074109472e6f55d8bd9751fb75c4c +Author: Keith Packard +Date: Mon Apr 25 21:26:21 2011 -0700 + + altosui: Fix TeleBT name in flight monitor title + + Was getting the product number, not the product name. + + Signed-off-by: Keith Packard + +commit 2e7b7b80432bb251ac39efa1fa05d32b5f250e14 +Author: Keith Packard +Date: Mon Apr 25 21:17:07 2011 -0700 + + altosui: Separate out flash debug code to separate thread + + This avoids blocking the Swing thread while waiting for the serial + device. + + Signed-off-by: Keith Packard + +commit 214cd69c0e4a1617ed5cde8fc2f46a4cee6ecced +Author: Keith Packard +Date: Sat Apr 23 22:50:58 2011 -0700 + + altos: add telebt-v0.0 Makefile + + Git doesn't like to add these. + + Signed-off-by: Keith Packard + +commit d41edb3384b6336f3482e61b0c9f9400a8b4f519 +Author: Keith Packard +Date: Tue Apr 19 15:29:39 2011 -0700 + + altosui: Make flight data download work through TeleBT + + This required flushing input before reading data blocks and adjusting + some delays. + + Signed-off-by: Keith Packard + +commit 44fb71ca3e5bccd5f601fc5a2d5da7292050b1d6 +Merge: 2ebdb88 c269e26 +Author: Keith Packard +Date: Tue Apr 19 14:06:39 2011 -0700 + + Merge branch 'telemini' into telebt + +commit 2ebdb888f6792de70b3132950a988d49752d264e +Author: Keith Packard +Date: Tue Apr 19 14:01:19 2011 -0700 + + altosui: Eliminate ao_cmd_filter hook + + Disabling status messages means we don't need to filter them out of + the input stream. + + Signed-off-by: Keith Packard + +commit 7f5c9986dfa2d130b6c8c14308638cce49391a6e +Author: Keith Packard +Date: Tue Apr 19 13:42:30 2011 -0700 + + altos: remove BT logging code + + This was used to debug the serial line startup. + + Signed-off-by: Keith Packard + +commit 0195ff442c1da5d363dfda3f88f41865d0c6b469 +Author: Keith Packard +Date: Tue Apr 19 13:31:10 2011 -0700 + + altos: Remove bt debug command + + This will permit some additional cleanups. + + Signed-off-by: Keith Packard + +commit ce7cf0c5ddc5405f6f474f4e20752fc0b02f3ecb +Author: Keith Packard +Date: Tue Apr 19 13:27:40 2011 -0700 + + altos: Simplify BT communications + + Eliminate stdio I/O wrappers + + Signed-off-by: Keith Packard + +commit e3d501940718428135e04995dff7fef691c08a20 +Author: Keith Packard +Date: Tue Apr 19 13:20:19 2011 -0700 + + altos: Solidify BT connections + + Use delays while sending commands to BT module. + Don't use BT for stdio until the module is initialized. + Add \r to name setting command + Don't require 'connected' signal for command input. + + Signed-off-by: Keith Packard + +commit 6b5957d5f6f8181da7be98c9bce49a0ec0b4a713 +Author: Keith Packard +Date: Tue Apr 19 10:41:28 2011 -0700 + + altosui: Wait two seconds after bluetooth connect XXX + + "something" isn't quite ready to communicate right after the device is + connected, so we stick a delay in. There should be a better fix. + + Signed-off-by: Keith Packard + +commit 8de9d3cbfcd1db7b554fb761296a8de09aafc8c3 +Author: Keith Packard +Date: Tue Apr 19 10:25:47 2011 -0700 + + altos: Add delays to bt startup sequence + + The BT device takes a few seconds after power-up before it is ready to + receive commands. + + Signed-off-by: Keith Packard + +commit 17f38e045fcd8ca0224095c0b2b7b098df77a8d8 +Author: Keith Packard +Date: Tue Apr 19 08:43:40 2011 -0700 + + altosui: Use persistent list of bluetooth devices for device dialogs + + Store a list of known bluetooth devices as preferences. Always include + those in device dialogs with an option to go browse for more devices + in both the device dialog and the Configure AltosUI dialog. + + Signed-off-by: Keith Packard + +commit f249e5926f5fd9f86c41e7f0a414193533d4d8b0 +Author: Keith Packard +Date: Mon Apr 18 18:16:38 2011 -0500 + + altosui: Make bluetooth dialog modal + + This allows it to be displayed correctly while the device dialog box + (also modal) is up. + + Signed-off-by: Keith Packard + +commit 84163eee7847a09fe78f8762b28f857d76bf5755 +Author: Keith Packard +Date: Thu Apr 14 10:22:30 2011 -0700 + + altosui: Make AltosBTDevice implement AltosDevice interface + + This will allow the use of either USB or BT devices through the + AltosDevice interface. + + Signed-off-by: Keith Packard + +commit 9cdef76c1275b343099d0d01af82d7eadd36a410 +Author: Keith Packard +Date: Thu Apr 14 10:12:29 2011 -0700 + + altosui: Create abstract AltosDevice class + + This will wrap either USB or BT devices. The USB device constants have + been moved to Altos.java + + Signed-off-by: Keith Packard + +commit 5b3f18b38d80aa041b971204bf7a94278bd9584a +Author: Keith Packard +Date: Fri Apr 8 19:46:15 2011 -0700 + + altosui: Add primitive bluetooth device manager UI. + + This isn't useful, but does inquire for available bluetooth devices + and show them in a list. + + Signed-off-by: Keith Packard + +commit c269e263a6accd815ed5d08c0f5a6c3d5b9d3853 +Author: Keith Packard +Date: Thu Apr 14 09:38:48 2011 -0700 + + altos: Write a few pre-launch samples for Tm/Tn devices + + Record pre-launch samples in a small ring and flush that to flash when + launch is detected. This provides a complete record of the flight, + rather than simply starting after launch detect. + + Signed-off-by: Keith Packard + +commit a0fb471ce10642fc4a4bd40e4a81f8d6fe7a7c21 +Author: Keith Packard +Date: Wed Apr 13 20:27:38 2011 -0700 + + altosui: oops - lost state changes when downloading eeprom data. + + This would cause the reader to just keep reading past the end of the + flight. + + Signed-off-by: Keith Packard + +commit 7f49d694e776819e03b2c708e1c4ee23ba311430 +Author: Keith Packard +Date: Sat Apr 9 22:53:12 2011 -0700 + + altos/altosui: Log averaged baro sensor data in Tm/Tn + + Instead of logging the best height guess from the kalman filter, log + barometer data. The logged data consists of the average value betwen + log points to reduce noise. + + Signed-off-by: Keith Packard + +commit 8dd455204cf8712fa8c142b0c0517cec1bf5fd0f +Author: Keith Packard +Date: Fri Apr 8 10:13:55 2011 -0700 + + altosui: Add low-level Bluetooth APIs + + Adds the JNI functions to query and connect to arbitrary + bluetooth devices. + + Adds Java wrappers to construct a list of proximate bluetooth devices. + + Signed-off-by: Keith Packard + +commit bf1c7df5301a1727e871a8447f835fe75bdce3fc +Author: Keith Packard +Date: Fri Apr 8 10:12:50 2011 -0700 + + altosui: Add TeleBT USB device support + + TeleBT can work just like a TeleDongle over USB. + + Signed-off-by: Keith Packard + +commit 1a54a58d72147888f783a3caf364479efff4ed9b +Author: Keith Packard +Date: Thu Apr 7 22:00:38 2011 -0700 + + altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. + + PIo(6) appears to be an active-low indication of the Bluetooth + connection status. Hook this up using an interrupt to track the + link state instead of using in-band status messages. + + Signed-off-by: Keith Packard + +commit f28efe271f9670473249574f6bcf6e160fe58c7b +Merge: 8db5c52 835ab3a +Author: Keith Packard +Date: Fri Apr 1 19:35:22 2011 -0700 + + Merge branch 'telemini' into telebt + +commit 835ab3a8c2741a09b27de58c37439a193c9919ce +Author: Keith Packard +Date: Fri Apr 1 19:35:00 2011 -0700 + + altosui: Add missing AltosTelemetryMap.java file + + Signed-off-by: Keith Packard + +commit 8db5c52f1c76a05020e4e0afbe4ea27485ad9f82 +Author: Keith Packard +Date: Fri Apr 1 17:26:08 2011 -0700 + + altos: Clean up BT serial communcations + + Disable echo on both ends in command mode to eliminate looping error + values. + + Switch to 57600 baud to improve performance. + + Signed-off-by: Keith Packard + +commit a5d60fdb9c969c1516feb76a16001c9688112c4c +Author: Keith Packard +Date: Fri Apr 1 17:25:07 2011 -0700 + + altos: Make cmd echo per-connection instead of global + + Allow different connections to use different echo values, permitting + the packet link to turn off echo while the USB link still has it on. + + Signed-off-by: Keith Packard + +commit 4e2c18249e16c98cf5f7dccdf8d3b84bc473863a +Author: Keith Packard +Date: Fri Apr 1 16:48:12 2011 -0700 + + altos: Clean up serial initialization + + Flush serial input buffers when switching speeds. + Ensure pin configuration is correct. + + Signed-off-by: Keith Packard + +commit 92386f2e8419c4df125692cc998eb72ec49bf991 +Author: Keith Packard +Date: Fri Apr 1 14:12:56 2011 -0700 + + altos: Clean up usage of serial port for stdio + + Code wanting to use this must invoke ao_add_stdio; that way + the link can be configured before command processing starts. + + Signed-off-by: Keith Packard + +commit 9f8a96a8516e13878b329dbf1da855ed9a3219c4 +Author: Keith Packard +Date: Fri Apr 1 14:11:44 2011 -0700 + + altos: Make ao_serial_drain public + + Allow external code to discard serial input + + Signed-off-by: Keith Packard + +commit 4f243a282f9aeb7433ccb2942850d380a091e603 +Author: Keith Packard +Date: Fri Apr 1 14:10:37 2011 -0700 + + altos: Remove serial monitor command + + This takes up space and isn't that useful these days + + Signed-off-by: Keith Packard + +commit 39bde78edc863d9d2ef50a59b8f28ab6274892b4 +Author: Keith Packard +Date: Fri Apr 1 14:08:37 2011 -0700 + + altos: Allow any stdio to be used with packet forwarding + + There's no reason to restrict packet forwarding to work only from + USB. + + Signed-off-by: Keith Packard + +commit 01952da35a57ae4da062facb26b3c6d7de29190f +Author: Keith Packard +Date: Fri Apr 1 14:07:23 2011 -0700 + + altos: Provide for a pre-filter on commands + + This allows for external code to see each command line before it is + processed and potentially skip it. + + Signed-off-by: Keith Packard + +commit 359ba0d9fc2c5947e6adc98bebcd061069c61e79 +Author: Keith Packard +Date: Fri Apr 1 14:04:58 2011 -0700 + + altos: expose set of available stdio values + + This lets external code manipulate which connection to communicate + over. + + Signed-off-by: Keith Packard + +commit ce18eaa28b1385c962c09459cbc5f20e234d9ad5 +Author: Keith Packard +Date: Fri Apr 1 14:03:25 2011 -0700 + + altos: Add P2SEL_*_MASK defines to cc1111.h + + These are used to avoid having the code "know" which selections are 1 + and which are 0 bits. + + Signed-off-by: Keith Packard + +commit 8e74cf6d1c70a7a17d01c20f6831571245392498 +Author: Keith Packard +Date: Thu Mar 31 20:58:14 2011 -0700 + + altos: Add initial TeleBT code + + Prototyping with a TeleMetrum v0.1 board and a serial link to a + bluetooth module. + + Signed-off-by: Keith Packard + +commit c0971abc02b05d136aea257f3f40ba3b22b1d441 +Author: Keith Packard +Date: Thu Mar 31 20:55:18 2011 -0700 + + altos: Make ao_flight_test show true height but report saturated height + + To simulate a saturated baro sensor, clip baro data at a specified + altitude. Continue to report the 'true' altitude in the output so that + the resulting graphs are useful. + + Signed-off-by: Keith Packard + +commit 8a14142e7b37031a51409f121b913fe793bf3603 +Author: Keith Packard +Date: Thu Mar 31 20:53:12 2011 -0700 + + altos: Baro useful ceiling is MSL, not AGL + + Use MSL instead of AGL for detecting over-range baro sensor values. + Always trust baro sensor during descent; it'll get there eventually. + + Signed-off-by: Keith Packard + +commit a9dae18a664f70b668159487015e61be7f776926 +Author: Keith Packard +Date: Thu Mar 31 20:51:15 2011 -0700 + + altos: Reflect ao_flight split in ao_flight_test dependencies + + Need to rebuild ao_flight_test when any of the flight sources change + + Signed-off-by: Keith Packard + +commit f558cfa1df77c36a459168c1953d0945ee5a7f9f +Author: Keith Packard +Date: Wed Mar 30 11:48:03 2011 -0700 + + altosui: Only plot acceleration when present in data file + + Eliminates a bogus axis and data line for devices which do not have an + accelerometer. + + Signed-off-by: Keith Packard + +commit a9df9fc257eb2d7038d66ac7c2539aae4474bf12 +Author: Keith Packard +Date: Wed Mar 30 11:47:07 2011 -0700 + + altosui: Parse and export Max flight log value + + New configuration field might as well get dumped to the .csv files. + + Signed-off-by: Keith Packard + +commit 87bff181a95f6bf92c2cec350d331ba6af779e80 +Author: Keith Packard +Date: Tue Mar 29 18:11:47 2011 -0700 + + altos: Enable logging during nano flights + + Not having logging wasn't very useful. + + Signed-off-by: Keith Packard + +commit 011e37f27b3926a42c8c1a74e0f179bb48829ec7 +Author: Keith Packard +Date: Tue Mar 29 18:10:46 2011 -0700 + + altos: Run RDF beacon after apogee instead of waiting for landing + + This provides tracking when GPS fails, or on TeleMini. + + Signed-off-by: Keith Packard + +commit 08e6bbef2c3529dfd468ef221c526fc9f3ed5b81 +Author: Keith Packard +Date: Tue Mar 29 10:08:46 2011 -0700 + + altos: ao_sample_preflight was exiting preflight mode immediately + + Need to stay in pre-flight mode until we've gotten enough sensor data + to calibrate things appropriately. The conversion from a unified + ao_flight.c file was just broken here. + + Signed-off-by: Keith Packard + +commit 56d045040c49728a854741e99545766f3723da5e +Author: Keith Packard +Date: Tue Mar 29 09:39:27 2011 -0700 + + altosui: Don't display 0000-00-00 for missing flight log dates + + With Tm/Tn not having GPS to get the current date, it's no longer + unusual to have no date for a flight log, so don't show the 0000-00-00 + piece in that case. + + Signed-off-by: Keith Packard + +commit 8ade7d99f02df825e70d0a964b4648156101ef78 +Author: Keith Packard +Date: Tue Mar 29 09:38:23 2011 -0700 + + altosui: Display exception messages from swing thread + + Flight log management exceptions were getting displayed from the log + serial I/O thread instead of the swing thread. That's a bad plan. + + Signed-off-by: Keith Packard + +commit 2f9be009ef26e3d7539f5932d267d7a8a7bcb7eb +Author: Keith Packard +Date: Tue Mar 29 09:37:11 2011 -0700 + + altosui: Make deployment testing handle Connecting... dialog + + Supporting the Connecting... dialog requires moving all serial + communication to a separate thread. This was done by creating a worker + thread and command queue to communicate between the UI and the serial line. + + Signed-off-by: Keith Packard + +commit 573edcd7dfe10ac3251396eae88eece55d82bcb6 +Author: Keith Packard +Date: Mon Mar 28 23:38:02 2011 -0700 + + altosui: Make flight log downloading handle 'Connecting...' dialog + + This required moving all of the serial communication to a separate + thread and making the bulk of the download operation run after that + has finished. + + Signed-off-by: Keith Packard + +commit c71a145daefb86d2c1297abec68e54bd951e3adf +Author: Keith Packard +Date: Mon Mar 28 23:35:05 2011 -0700 + + altosui: Clean up packet link connecting dialog + + Make sure the dialog is destroyed after use (otherwise, it hangs + around on the screen sometimes). + + Switch timeout before showing dialog to 500ms -- that brings the + dialog up less often when unnecessary. + + Use 'timeout_started' boolean to indicate whether the I/O thread has + queued the dialog for display and whether it needs to queue a call to + close it down. + + Signed-off-by: Keith Packard + +commit c6e7e812d67f91c63ba4982f7a899a72584027de +Author: Keith Packard +Date: Mon Mar 28 18:18:50 2011 -0700 + + altos: Create custom nano flight code + + No igniters, just 'pad/drogue/landed' modes (where 'drogue' == + 'flying'). A constant 1Hz telemetry and RDF rate. + + Signed-off-by: Keith Packard + +commit c754759a2d503633d527da4ebb20eb859cd506fd +Author: Keith Packard +Date: Mon Mar 28 17:54:44 2011 -0700 + + altos: Split up flight code into separate flight/sample/kalman bits + + The flight code mashed together data processing, filtering and actual + flight managament into one giant pile. Split things up so that we + have: + + ao_sample.c: Sensor data processing. Reads the ring, handles calibration + ao_kalman.c: Filter the data to track the accel/speed/height values + ao_flight.c: Flight state management, specific to rocketry. + + The plan is to re-use ao_sample.c and ao_kalman.c for hardware not + specifically designed for rocketry, like TeleNano. + + Signed-off-by: Keith Packard + +commit 006de838bbb096b9443863a46b8a125b1e6b5600 +Author: Keith Packard +Date: Sun Mar 27 00:48:07 2011 -0700 + + altosui: Handle serial calls from swing thread + + Calls from the swing thread cannot be canceled as there's no way to + put up the cancel dialog. In this case, simply use the 5 second + timeout and fail if no communication occurs within that amount of time. + + Signed-off-by: Keith Packard + +commit f23d0f3cbf1fb0c8eab497e266625f6410b69ba3 +Author: Keith Packard +Date: Sun Mar 27 00:46:19 2011 -0700 + + altosui: Tell serial device which frame to use for timeout dialogs + + For the timeout dialog to appear, a frame must be configured for it to + appear near. This patch sends the frame from the eeprom download + functions to the serial code. That path doesn't yet work as the eeprom + download is still trying to talk to the serial device from the swing + event thread, which prevents the cancel dialog from working. + + Signed-off-by: Keith Packard + +commit 067b21993e9a97fceadb355e571e5610535336a8 +Author: Keith Packard +Date: Sun Mar 27 00:13:38 2011 -0700 + + altosui: Allow radio channel to be configured over the radio link + + TeleMini/TeleNano can't be configured via USB, so we need to allow + the radio channel to be set over the radio link. + + This change carefully sets the new radio channel, disables the remote + link and then sets the teledongle channel to the new value and brings + the link back up. + + Signed-off-by: Keith Packard + +commit 91a75279b6d306ba9d068a28c64917d5312122e8 +Author: Keith Packard +Date: Sun Mar 27 00:12:01 2011 -0700 + + altosui: Off-by-one error in telemetry format configuration UI + + The telemetry format menu uses 0 for full and 1 for tiny, but the + telemetry configuration uses 1 for full and 2 for tiny. One direction + (config to UI) was right, the other (UI to config) was wrong. + + Signed-off-by: Keith Packard + +commit 7ce8c9081e703d1405c2595ab9bda0cfa218c6c4 +Author: Keith Packard +Date: Sat Mar 26 23:38:54 2011 -0700 + + altos: full logging must flush pending data before checking state + + Flight state must be checked only after any pending data have been + written to the log as the 'current' flight state is only valid when + the pending data values have been processed. This ensures that the + 'boost' state is not marked until the full ring of data is + written. This ensures that the data processing code can find the + barometer values from before boost to get an idea of the ground + pressure value. + + Signed-off-by: Keith Packard + +commit 3945d8f986d8f4bd3186a2cbaed5186e49d59839 +Author: Keith Packard +Date: Sat Mar 26 23:15:36 2011 -0700 + + altos: Variable log rate in full logging code too + + With the fixed ADC rate used to get better data during flight, the + logging code now needs to vary the data storage rate so that descent + data is recorded at 10 samples/second while ascent data is recorded at + 1 sample per second. Having the logging code do this itself eliminates + any interaction with the flight code. + + Signed-off-by: Keith Packard + +commit 97517ee585462c2d355f23f999fb8d9ebd908ec1 +Author: Keith Packard +Date: Sat Mar 26 00:01:22 2011 -0700 + + altosui: Allow TM config connection to be canceled. + + This leaves the config UI connection attempt running and pops up a + dialog box when it takes 'too long' in the remote case so that users + with Tm or Tn devices can bring up the UI, and then boot the Tm/Tn + without needing to time things carefully. + + Signed-off-by: Keith Packard + +commit 2c121f1ef495e8af3eb39210baa40e212b691894 +Author: Keith Packard +Date: Fri Mar 25 22:04:09 2011 -0700 + + altosui: swing hide/show methods are deprecated + + I don't know why, but they are, so just replace them with + setVisible calls. + + Signed-off-by: Keith Packard + +commit b155647472ddfacb07c5ffa832e4d1f4a13ad342 +Author: Keith Packard +Date: Fri Mar 25 22:01:18 2011 -0700 + + altosui: Remove extra AltosEepromBlock layer + + This was interposed between the download layer and the eeprom layer to + hold a eeprom block full of flight log records. The addition of the tiny + log format required reworking the code to hold chunks full of eeprom + data without regard to their content, so this content-specific layer + didn't seem useful anymore. + + Signed-off-by: Keith Packard + +commit 011615d40b3cb1d1c0ab9fa41e139e263a6a51e7 +Author: Keith Packard +Date: Fri Mar 25 21:34:31 2011 -0700 + + altosui: Add support for downloading TeleMini/TeleNano flight logs + + Splits the eeprom downloading code into eeprom block downloading and + separate eeprom data parsing so that the new data logging format can + share the data downloading code. + + Signed-off-by: Keith Packard + +commit dea80af81b388cc3d7073444919f4e98b12fa730 +Author: Keith Packard +Date: Fri Mar 25 21:29:50 2011 -0700 + + altosui: Remove a bunch of debug printfs from the eeprom manager code + + Just noise on stdout. + + Signed-off-by: Keith Packard + +commit 7f5b5848ad6ef5c808638a29c3dc0101b56ed11e +Author: Keith Packard +Date: Thu Mar 24 08:08:43 2011 +0900 + + altosui: Add telemetry format menu and preferences + + Switches the TeleDongle between full and tiny telemetry packet + formats, saving the last used format for each teledongle in the + application preferences. + + Signed-off-by: Keith Packard + +commit f3e68341f6f5daaf26dd162e4f9a06c29988986a +Author: Keith Packard +Date: Thu Mar 24 05:27:57 2011 +0900 + + altosui: Add support for telemetry version 4 + + New telemetry format needed to support TeleNano and TeleMini + + Signed-off-by: Keith Packard + +commit 1e976a105423f2da1842f70da531c9051ba88a7f +Author: Keith Packard +Date: Wed Mar 23 10:42:31 2011 +0900 + + Add description to test flights + +commit 93040ef4d0bd90ec5ae052f22243cd56adfb300a +Author: Keith Packard +Date: Wed Mar 23 10:40:05 2011 +0900 + + Add ao_kalman.h to .gitignore + +commit 43a94380032300a2e33e1faa1efe93e858e0a2cf +Author: Keith Packard +Date: Wed Mar 23 10:37:39 2011 +0900 + + altos: Exit flight test at landing. Allow description in test flight list + + Signed-off-by: Keith Packard + +commit 32364c9e0d346e0e5d517e18d4e90b8ff2fa944f +Author: Keith Packard +Date: Wed Mar 23 10:33:38 2011 +0900 + + altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. + + With the fixed kalman filter, transitions across mach don't cause + bumps in the merged filter. + + And, with working kalman bits, the signal for broken baro detection is + stronger and so we can allow for baro apogee detection in cases where + noise occurs close to apogee. + + Bump the kalman filter to trust the baro less so that the model tracks + across mach. + + Signed-off-by: Keith Packard + +commit 3d2042ccc2d29e4cb8ea39c5c69d07cb7e3daeea +Author: Keith Packard +Date: Tue Mar 22 16:55:08 2011 +0900 + + altos: Restore sensible kalman values + + Now that the kalman code seems to work correctly, restore the sensor + errors and model errors to match reality + + Signed-off-by: Keith Packard + +commit 7d7b476564a16eda81ab3406f70a21995e1b464e +Author: Keith Packard +Date: Tue Mar 22 21:51:52 2011 +0900 + + altos: Fix up flight code testing + + This automates flight code testing by reporting mis-detected apogee or + main events. + + Signed-off-by: Keith Packard + +commit a80d3836cfce3d4cfa7a71068539415c2dc421cd +Author: Keith Packard +Date: Tue Mar 22 21:50:29 2011 +0900 + + altos: Missing parens and some bad arithmetic in the kalman code + + Fixed point computations are a pain. + + Signed-off-by: Keith Packard + +commit f30de5766c1eefb18c7d024a2cf10ce02de41071 +Author: Keith Packard +Date: Tue Mar 22 21:29:05 2011 +0900 + + altos: Add ao_flight_debug code + + Trace the kalman filter to make sure it's working. + + Signed-off-by: Keith Packard + +commit f3053b1f3c85d4fd84b3c6cc87858f433166df34 +Author: Keith Packard +Date: Tue Mar 22 17:04:07 2011 +0900 + + altos: Clean up some debug stuff in ao_flight.c + + Remove some spurious printf debugging. + Remove an attempt at discovering broken accelerometer code. + + Signed-off-by: Keith Packard + +commit 6864e06d88a5b908cffa7c4cd2be8969ff46ce4d +Author: Keith Packard +Date: Tue Mar 22 16:51:04 2011 +0900 + + altos/kalman: Kalman terms can be > 1, use 32-bit fixed point + + Because speed and acceleration are scaled by 16, it's fairly common + for the kalman terms to end up larger than 1. Instead of trying to + fuss with 16-bit values and shifts, just use 32-bit values. + + Signed-off-by: Keith Packard + +commit c14d6c5ace1d67bd948273ceb7eb6807b29c3806 +Author: Keith Packard +Date: Tue Mar 22 08:51:23 2011 +0900 + + altos: Compute a 'trust' value for the barometer + + Instead of making the baro use/don't-use decision binary, use a 'trust + value' which slowly migrates from baro+accel to accel-only mode. This + eliminates bumps in the data from a rapid shift. + + Signed-off-by: Keith Packard + +commit 7b009b2efe3af8722c358c304c2243652594e0d5 +Author: Keith Packard +Date: Tue Mar 22 05:42:51 2011 +0900 + + altos: Switch telemetrum over to kalman filter + + This changes the full telemetry stream to include kalman data instead + of the old ad-hoc flight data. It's compatible in that the packet + sizes are the same so teledongle can receive either and figure out + which it has received. + + A few plotting and testing tools are added to make validating the new + code easier. + + Signed-off-by: Keith Packard + +commit 20427ae4965f756aac0cedc5179a1c45b9a781f2 +Author: Keith Packard +Date: Mon Mar 21 19:59:27 2011 +0900 + + altos: Add nickle kalman implementation. + + This generates the constants needed to implement Kalman filtering in + the flight firmware. + + Signed-off-by: Keith Packard + +commit ca3f03ef5c09446bebf0f5734f36a0248c457b1d +Author: Keith Packard +Date: Sat Mar 19 23:55:39 2011 -0700 + + altos: Add .sdcdbrc file for teledongle + + My sdcdb script uses this to set command line options automatically + + Signed-off-by: Keith Packard + +commit be838db49d999426a9dd02c0166fe161722f1e61 +Author: Keith Packard +Date: Sat Mar 19 23:53:08 2011 -0700 + + altos: New telemetry report format (version 4). Supports tiny telemetry. + + This completely replaces the version 3 format with a much simpler and + easier to parse scheme. It's described in detail in ao_telem.h, but + the basic idea is that the whole line is split into name/value pairs, + separated by whitespace. Every name is unique, and the values are + either strings or integers. No extraneous formatting or units are + provided. + + Signed-off-by: Keith Packard + +commit ad6bb342d237988404fa32540b38c61d6ddc1f0d +Author: Keith Packard +Date: Sat Mar 19 23:51:02 2011 -0700 + + altos: The kalman code requires a constant sample rate + + The kalman function can't handle a variable sample rate, so keep the + ADC running at full speed for the whole flight instead of slowing it + down after apogee. + + Signed-off-by: Keith Packard + +commit 31feb7777f73fed61193d3404f457ea1a081fe9c +Author: Keith Packard +Date: Sat Mar 19 23:49:41 2011 -0700 + + altos: Split telenano main from telemini + + Eventually, telenano will run different code; prepare for this by + creating a telenano-specific main routine. + + Signed-off-by: Keith Packard + +commit 8950df02382f5f0aea5bac078fdf7134b98c43ed +Author: Keith Packard +Date: Sat Mar 19 23:46:18 2011 -0700 + + altos: Split out tiny telemetry from full telemetry + + The TeleMini and TeleNano boards do not have either GPS or + accelermeters, and they also run the kalman filter which produces + standard unit measurements for the flight height/speed/accel + values. This makes the telemetry significantly + different. ao_telemetry_tiny.c sends the required data. + + Note that TeleNano sends the same telemetry as telemini at this point; + there are a couple of values which are not useful, but the overhead of + sending them is small enough that the hassle of having three telemetry + formats seemed excessive. + + Signed-off-by: Keith Packard + +commit 5ba75e95c98d3e441a58d6f75d328d579e1997fe +Author: Keith Packard +Date: Sat Mar 19 23:41:44 2011 -0700 + + altos: Make telemetry interval more consistent + + Instead of using a delay between telemetry packets, use a telemetry + period and compute an appropriate delay each time. This requires + changing the ascent telemetry from a 50ms delay to a 100ms interval, + to provide a regular 10 packets-per-second rate. Before, we counted on + the telemetry packet taking about 50ms to send so that we would + receive about 10 per second. + + This also eliminates delays during descent for RDF tones -- those will + get transmitted in the interval between telemetry packets without + interrupting the spacing of those packets. + + Signed-off-by: Keith Packard + +commit 3f0bc801fd08a613c681504f0d1f9374486a2487 +Author: Keith Packard +Date: Sat Mar 19 23:31:20 2011 -0700 + + altos: Configure packet size from send/recv parameters. + + Instead of setting the packet size at configuration time, use the + provided packet size to the send/recv functions to configure the + radio. This eliminates many configuration calls, leaving us with 'RDF' + mode and 'packet' mode, the latter working for telemetry and the + bi-directional link. + + Signed-off-by: Keith Packard + +commit 5c28b9312d90a3a66016abc641c20bcd852d69f8 +Author: Keith Packard +Date: Sat Mar 19 23:27:15 2011 -0700 + + altos: Don't init packet slave on TD. Make slave start optional + + Oops. TeleDongle was starting the packet slave code, which kinda + wrecked its ability to receive telemetry packets. This patch simply + removes the packet slave code from teledongle as it cannot be used + (yet), it also makes the packet slave code initialization take a + parameter which controls whether to start that by default; in the + future, perhaps TeleDongle will gain a command to start packet slave mode. + + Signed-off-by: Keith Packard + +commit e980b251e5a4d25410710a9aa89ef940e06b0d93 +Author: Keith Packard +Date: Sat Mar 19 18:43:52 2011 -0700 + + altosui: Add software version to Configure AltosUI dialog + + Show this somewhere so we can figure out what is installed. + + Signed-off-by: Keith Packard + +commit 1aeb759c48f475ffaaae787515e080440c8386c3 +Author: Keith Packard +Date: Sat Mar 19 12:28:08 2011 -0700 + + altos: Baro-only boards must not detect launch on accel or speed data + + The baro sensor generates too much noise to use small changes in + computed speed or acceleration to cause a false launch detect. + + Signed-off-by: Keith Packard + +commit 7a4f6d5ad55637cde97a1e2f247f92df59bc2e14 +Author: Keith Packard +Date: Fri Mar 18 21:01:15 2011 -0700 + + altos: Write height values to log for nano/mini + + This is a lot more useful than the old filtered pressure data. + + Signed-off-by: Keith Packard + +commit c985bb6a19c710409629f3c095332ba7afcf5248 +Author: Keith Packard +Date: Fri Mar 18 20:36:59 2011 -0700 + + altos/test: Add scripts to run lots of flights through the code + + This runs a long list of flights (there's a user-specific path + pointing at the flights) and squawks if the baro and dual flight + computers don't match. + + Signed-off-by: Keith Packard + +commit dbe915795c66995805b5f37e6eb698cf2c143e61 +Author: Keith Packard +Date: Fri Mar 18 20:26:12 2011 -0700 + + altos: Fix mini/nano default log size to available flash space + + Also, remove accel cal code from boards without accel + + Signed-off-by: Keith Packard + +commit 5db94e1e230bade966a997aa83165405a9ec9d83 +Merge: 1a8f45e cbb968f +Author: Bdale Garbee +Date: Fri Mar 18 21:12:39 2011 -0600 + + Merge branch 'telemini' of ssh://git.gag.com/scm/git/fw/altos into telemini + +commit 1a8f45e7b720d01d3ff0c35ed1caaf8cbe0c3119 +Author: Bdale Garbee +Date: Fri Mar 18 21:12:12 2011 -0600 + + fix up script to work and have reasonable texts + +commit cbb968f5cf03625d453d84dc535758072a2c04c7 +Author: Keith Packard +Date: Fri Mar 18 20:07:25 2011 -0700 + + altos: Add TeleNano support + + This just uses the TeleMini bits, which should work fine for now. + + Signed-off-by: Keith Packard + +commit 32c51840c792a737019fbc9fe42f2ca073b71827 +Author: Keith Packard +Date: Fri Mar 18 19:49:46 2011 -0700 + + altos: Tiny logging fixes. Scan at start, stop when land or full. + + Initialize the flight log for tiny systems by scanning the log area to + find the current flight number and log area bounds. + + Stop logging data when the flight is over, or when the log area is + full. + + Signed-off-by: Keith Packard + +commit 62eae8a17d870e8ac6937ba23da01a5fbc652c6c +Author: Keith Packard +Date: Fri Mar 18 16:53:11 2011 -0700 + + altos: Add kalman filters for baro-only boards + + This adds a baro-only kalman filter to track the state of the rocket, + and then uses it to control flight events instead of the existing + ad-hoc mechanisms. + + Signed-off-by: Keith Packard + +commit c826fab31f8aea25a942b6bb8435d4b04c1bef10 +Author: Keith Packard +Date: Thu Mar 17 16:00:10 2011 -0700 + + altos: Add tiny logging for TeleMini/TeleNano + + This splits the logging code into management of the log space within + storage and separate code to actually write suitable log entries. A + new log writing module, ao_log_tiny, is added which writes only + altimeter data at a fairly low data rate for devices using on-chip + storage. + + Signed-off-by: Keith Packard + +commit 8b546b474b7b6c5b4169b4c1ca09c6f17ebb3ae5 +Author: Anthony Towns +Date: Fri Mar 11 21:41:01 2011 +1000 + + ignore new flight test file + +commit 82707a05af0eb2d54f46b58805c95cdf4e5a3703 +Author: Keith Packard +Date: Wed Mar 16 20:36:50 2011 -0700 + + altos: Internal flash ops block when running from flash + + The docs say that if you are executing from flash, then the CPU will + stall after a flash write or erase command is started until the + operation is complete. Take advantage of that to simplify the flash + code. + + Signed-off-by: Keith Packard + +commit 1d8579f973bfe1047ee91f03555e74abdc483e69 +Author: Keith Packard +Date: Mon Mar 7 16:31:43 2011 -0800 + + altos: oops -- altitude reporting wasn't pausing between signals + + need to actually alternate the LED/tone with some space so you can + count. + + Signed-off-by: Keith Packard + +commit d007bccf6cb36d24a9c7c48de7d80759ac6f2e37 +Author: Keith Packard +Date: Mon Mar 7 15:57:58 2011 -0800 + + ao-load: Make usb descriptor rewriting optional + + TeleMini and TeleNano don't have USB descriptors to rewrite when + loading firmware, so allow them to be missing. + + Signed-off-by: Keith Packard + +commit 57d83f51377fb58018f422e42d74f29b86a821d2 +Author: Keith Packard +Date: Mon Mar 7 15:26:41 2011 -0800 + + bringup: Add script for telemini + + Copied from teledongle with a few obvious changes. + + Signed-off-by: Keith Packard + +commit ddd7485f05d0cad8f5b3e1ee9b9a4d2812ea1837 +Author: Keith Packard +Date: Mon Mar 7 08:03:11 2011 -0800 + + altos: Switch pins around for TeleMini + + TeleMini has fewer sensors and uses P0 for igniters instead of P2. + + Signed-off-by: Keith Packard + +commit f8afc2641c779fc312a42a6358187d8716ebe61a +Author: Keith Packard +Date: Sun Mar 6 23:52:11 2011 -0800 + + altos: Switch LED usage for TeleMini around + + We're using the LEDs instead of tones, so make red mean 'low tone', + green mean 'middle tone' and both mean 'high tone'. + + Signed-off-by: Keith Packard + +commit fc5d014721a7e5a7b22f07eb4ab0bb3c764473fe +Author: Anthony Towns +Date: Sat Feb 26 16:06:48 2011 +1000 + + ao_intflash: Avoid overwriting code + + Require firmware to specify the end of its codespace in its Makefile, + and use this to determine where the start of available flash is. Should + give compile time errors if either there's no room left for storage, or + if there's not enough room for code. + +commit 0e4c55d78852415e79f7318471f4d00c89703b78 +Author: Keith Packard +Date: Sun Mar 6 21:03:57 2011 -0800 + + altos: Add TeleMini v1.0 + + This adds initial code for the telemini board, a two channel + flight computer with digital telemetry and a barometric sensor. + + Signed-off-by: Keith Packard + +commit 2d41358c80f2eb8b6e98d699149bb941a6671475 +Author: Keith Packard +Date: Sun Mar 6 21:00:52 2011 -0800 + + altos: Start with packet slave running. Turn off in pad mode. + + Instead of turning slave mode on in idle mode, start with it running + and disable it in pad mode instead. This means packet mode is + available in startup mode too. + + Signed-off-by: Keith Packard + +commit 1e56ed44e562f808addfd76bfb352f981db94094 +Author: Keith Packard +Date: Sun Mar 6 21:59:08 2011 -0800 + + altos/test: Add baro-only flight test program + + This builds the flight code in baro-only mode for testing. + + Signed-off-by: Keith Packard + +commit e339ffd8bd8b9e3f4758017ba355028000cb612e +Author: Keith Packard +Date: Sun Mar 6 21:57:52 2011 -0800 + + altos/test: Use ao_convert.c instead of hand-coded pres → alt func + + Fix up ao_convert.c so that it can be used within the flight test code + instead of having a (broken) copy of the code there. + + Signed-off-by: Keith Packard + +commit 02611efea0c485d78fad08c696c1f56e868d36b8 +Author: Keith Packard +Date: Sun Mar 6 20:56:25 2011 -0800 + + altos: Make serial, usb, beeper and accelerometer optional components + + Not all boards will have these, so fix places that use them to deal + with that. + + Signed-off-by: Keith Packard + +commit fdd15a254c6fab5ba2d02320ba0ceb3e6a56354c +Author: Anthony Towns +Date: Sat Feb 26 11:48:30 2011 +1000 + + ao_intflash: Use internal flash for storage + + Makes any free pages at end of CC1111's internal flash available via + the ao_storage API. + +commit 8f1bd11b61d9423c62162f7bbe573fc69fd75269 +Author: Keith Packard +Date: Wed Mar 16 14:10:06 2011 -0700 + + aoview: remove -s option. + +commit 45395c7825184efb835d5b165fa132be20c7f6fe +Author: Keith Packard +Date: Wed Mar 16 14:08:42 2011 -0700 + + Bump published version number to 0.9.1 + +commit 9f3d26cadf37880d2c9223f59271d295b11c4c2a +Author: Keith Packard +Date: Wed Mar 16 14:05:13 2011 -0700 + + altosui: Missed jcommon.jar in the Mac OS install image + + This caused graphing to fail on Mac OS X + + Signed-off-by: Keith Packard + +commit 6e340c87d3198647cf075ed520a82703b0d59beb +Author: Keith Packard +Date: Mon Mar 7 00:26:17 2011 -0800 + + altos: Oops. Lost a couple of commands when merging the doc patch + + I didn't merge this carefully enough and managed to lose the 'f' + and 'e' commands, which are kinda useful. + + Signed-off-by: Keith Packard + +commit 8cdf4fb051c22b35c251d90bc288551f7c2898bf +Author: Anthony Towns +Date: Sun Feb 27 11:11:12 2011 +1000 + + src/ao_cmd: Shave off bytes from doc strings + + Switch to using { func, "X args\0Desc" } to specify command, saving + a char field by looking at help[0] instead, and reduce help length by + doing alignment with printf instead of hardcoded spaces. + +commit 2cfe205de4242398e69c9e7c613af0d2a7094686 +Author: Keith Packard +Date: Mon Mar 7 00:01:01 2011 -0800 + + Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" + + This reverts commit b080e933a65d268aaaec8cfd5f617a13d5babc43. + + 10Hz data isn't any better than 1Hz data; it still doesn't like going + upwards rapidly. + +commit 249cd3b63d97581b068fff988e0cd7fcd5bf493e +Author: Keith Packard +Date: Sat Feb 19 01:06:01 2011 -0800 + + altosui: Display eeprom parsing errors to user + + When reading the eeprom, any parsing errors (most likely bad + checksums) indicate some kind of problem with either the hardware or + the flight software. Display these to the user and do not erase the + flight. + + Signed-off-by: Keith Packard + +commit 629a7637871b24fe6d1204aaa7185d84933d4639 +Author: Keith Packard +Date: Sat Feb 19 01:04:19 2011 -0800 + + altosui: Always read whole eeprom block, even at end of flight + + Instead of stopping early, continue reading the whole eeprom block so + that the extra serial data doesn't end up confusing the next user of + the serial line, which may well be reading the next flight. + + Signed-off-by: Keith Packard + +commit 7ca2cf1b7e03b8453b45b45e313a33ad65da9ad5 +Author: Keith Packard +Date: Sat Feb 19 01:02:00 2011 -0800 + + altosui: Mark empty eeprom records 'invalid', don't generate exception + + When reading empty eeprom records, mark them as 'invalid', but don't + generate an exception as it's normal to read these at the end of the + flight log. + + Signed-off-by: Keith Packard + +commit 690feb166fd2bc6b6dfc26828f1efe9f5f1c6c0d +Author: Bdale Garbee +Date: Fri Feb 18 23:56:01 2011 -0700 + + update changelogs for Debian build + commit 0630e7d6d8cf6abf0fe07f9a6df40ee472cce1ef Author: Bdale Garbee Date: Fri Feb 18 19:54:18 2011 -0700 diff --git a/debian/changelog b/debian/changelog index b4425070..0de954b3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,258 @@ +altos (0.9.4.5) unstable; urgency=low + + [ Keith Packard ] + * altosui: Mark empty eeprom records 'invalid', don't generate exception + * altosui: Always read whole eeprom block, even at end of flight + * altosui: Display eeprom parsing errors to user + * Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" + + [ Anthony Towns ] + * src/ao_cmd: Shave off bytes from doc strings + + [ Keith Packard ] + * altos: Oops. Lost a couple of commands when merging the doc patch + * altosui: Missed jcommon.jar in the Mac OS install image + * Bump published version number to 0.9.1 + * aoview: remove -s option. + + [ Anthony Towns ] + * ao_intflash: Use internal flash for storage + + [ Keith Packard ] + * altos: Make serial, usb, beeper and accelerometer optional components + * altos/test: Use ao_convert.c instead of hand-coded pres → alt func + * altos/test: Add baro-only flight test program + * altos: Start with packet slave running. Turn off in pad mode. + * altos: Add TeleMini v1.0 + + [ Anthony Towns ] + * ao_intflash: Avoid overwriting code + + [ Keith Packard ] + * altos: Switch LED usage for TeleMini around + * altos: Switch pins around for TeleMini + * bringup: Add script for telemini + * ao-load: Make usb descriptor rewriting optional + * altos: oops -- altitude reporting wasn't pausing between signals + * altos: Internal flash ops block when running from flash + + [ Anthony Towns ] + * ignore new flight test file + + [ Keith Packard ] + * altos: Add tiny logging for TeleMini/TeleNano + * altos: Add kalman filters for baro-only boards + * altos: Tiny logging fixes. Scan at start, stop when land or full. + * altos: Add TeleNano support + + [ Bdale Garbee ] + * fix up script to work and have reasonable texts + + [ Keith Packard ] + * altos: Fix mini/nano default log size to available flash space + * altos/test: Add scripts to run lots of flights through the code + * altos: Write height values to log for nano/mini + * altos: Baro-only boards must not detect launch on accel or speed data + * altosui: Add software version to Configure AltosUI dialog + * altos: Don't init packet slave on TD. Make slave start optional + * altos: Configure packet size from send/recv parameters. + * altos: Make telemetry interval more consistent + * altos: Split out tiny telemetry from full telemetry + * altos: Split telenano main from telemini + * altos: The kalman code requires a constant sample rate + * altos: New telemetry report format (version 4). Supports tiny telemetry. + * altos: Add .sdcdbrc file for teledongle + * altos: Add nickle kalman implementation. + * altos: Switch telemetrum over to kalman filter + * altos: Compute a 'trust' value for the barometer + * altos/kalman: Kalman terms can be > 1, use 32-bit fixed point + * altos: Clean up some debug stuff in ao_flight.c + * altos: Add ao_flight_debug code + * altos: Missing parens and some bad arithmetic in the kalman code + * altos: Fix up flight code testing + * altos: Restore sensible kalman values + * altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. + * altos: Exit flight test at landing. Allow description in test flight list + * Add ao_kalman.h to .gitignore + * Add description to test flights + * altosui: Add support for telemetry version 4 + * altosui: Add telemetry format menu and preferences + * altosui: Remove a bunch of debug printfs from the eeprom manager code + * altosui: Add support for downloading TeleMini/TeleNano flight logs + * altosui: Remove extra AltosEepromBlock layer + * altosui: swing hide/show methods are deprecated + * altosui: Allow TM config connection to be canceled. + * altos: Variable log rate in full logging code too + * altos: full logging must flush pending data before checking state + * altosui: Off-by-one error in telemetry format configuration UI + * altosui: Allow radio channel to be configured over the radio link + * altosui: Tell serial device which frame to use for timeout dialogs + * altosui: Handle serial calls from swing thread + * altos: Split up flight code into separate flight/sample/kalman bits + * altos: Create custom nano flight code + * altosui: Clean up packet link connecting dialog + * altosui: Make flight log downloading handle 'Connecting...' dialog + * altosui: Make deployment testing handle Connecting... dialog + * altosui: Display exception messages from swing thread + * altosui: Don't display 0000-00-00 for missing flight log dates + * altos: ao_sample_preflight was exiting preflight mode immediately + * altos: Run RDF beacon after apogee instead of waiting for landing + * altos: Enable logging during nano flights + * altosui: Parse and export Max flight log value + * altosui: Only plot acceleration when present in data file + * altos: Reflect ao_flight split in ao_flight_test dependencies + * altos: Baro useful ceiling is MSL, not AGL + * altos: Make ao_flight_test show true height but report saturated height + * altos: Add initial TeleBT code + * altos: Add P2SEL_*_MASK defines to cc1111.h + * altos: expose set of available stdio values + * altos: Provide for a pre-filter on commands + * altos: Allow any stdio to be used with packet forwarding + * altos: Remove serial monitor command + * altos: Make ao_serial_drain public + * altos: Clean up usage of serial port for stdio + * altos: Clean up serial initialization + * altos: Make cmd echo per-connection instead of global + * altos: Clean up BT serial communcations + * altosui: Add missing AltosTelemetryMap.java file + * altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. + * altosui: Add TeleBT USB device support + * altosui: Add low-level Bluetooth APIs + * altos/altosui: Log averaged baro sensor data in Tm/Tn + * altosui: oops - lost state changes when downloading eeprom data. + * altos: Write a few pre-launch samples for Tm/Tn devices + * altosui: Add primitive bluetooth device manager UI. + * altosui: Create abstract AltosDevice class + * altosui: Make AltosBTDevice implement AltosDevice interface + * altosui: Make bluetooth dialog modal + * altosui: Use persistent list of bluetooth devices for device dialogs + * altos: Add delays to bt startup sequence + * altosui: Wait two seconds after bluetooth connect XXX + * altos: Solidify BT connections + * altos: Simplify BT communications + * altos: Remove bt debug command + * altos: remove BT logging code + * altosui: Eliminate ao_cmd_filter hook + * altosui: Make flight data download work through TeleBT + * altos: add telebt-v0.0 Makefile + * altosui: Separate out flash debug code to separate thread + * altosui: Fix TeleBT name in flight monitor title + * altosui: Display reader name (usually the device) when an I/O error occurs + * altosui: Move AltosIgniteUI device open out of Swing thread + * altosui: Fix BT manage dialog so that the device lists resize + * altos: Add preliminary telebt v0.1 defines + + [ Bdale Garbee ] + * first cut at a telebt turn on script + + [ Keith Packard ] + * altos: Add telebt-v0.1 to Makefile + * altos: Use USART configuration 1 with flow control for TBT + * altos: Fix BT link status pin for real TBT hardware + * altos: pull TBT v0.1 ser_reset line low + * altos: Add beeper to TBT v0.1 + * altos: Debugging TBT issues -- check pin configuration after boot + * altos: Initialize beeper for telebt + * altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line + * altos: clear CPU port 1 interrupt flag when handled + * Revert "altos: Debugging TBT issues -- check pin configuration after boot" + * Switch version to 0.9.4 + * altosui: Handle old TeleDongle receiving kalman telemetry packets + * altos: Rename telemetry to telemetry_orig + * altos: Add arbitrary telemetry packet monitoring + * altos: Add checksum to TELEM output lines + * altos: Start adding new telemetry frame definitions + * altos: ao_radio_recv needs byte count *including* rssi and status + * altosui: Support raw telemetry from TeleDongle + * doc: Add telemetry format description + * doc: Complete initial telemetry description + * doc: Fix a few minor telemetry doc mistakes + * Version strings must be < 8 bytes long + * altos: teledongle does not need ao_packet_slave.c + * altos: Shrink const space in ao_config + * altos: Add sat info to GPS report command + * altos: Shrink help text + * altos: Add split telemetry code + * altos: Complete new telemetry switchover + * altosui: Parse remaining standard telemetry packets + * doc: Chang Config and Location packets + * altos: Adapt to changes in telemetry Configuration packet + * doc: Add section about TeleDongle USB line format + * altosui: Elide nul bytes at end of telemetry string values + * altosui: Elide missing values from graphs + * altosui: Add main/drogue voltages to default graph + * altosui: Remove debug printf. + * altosui: Compress telemetry records marked with the same time + * altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd + * altos: Shrink ao_config_callsign_set + * altos: Shrink ao_add_task by rolling up a memset loop + * altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata + * altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata + * altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata + * altos: Switch ao_report.c __xdata to __pdata + * altos: Switch ao_rssi.c __xdata to __pdata + * altos: Switch ao_sample.c __xdata to __pdata + * altos: Switch ao_serial.c __xdata to __pdata + * altos: Switch ao_stdio.c __data to __pdata + * altos: Switch ao_telemetry.c __xdata to __pdata + * altos: Switch ao_usb.c __xdata to __pdata + * altos: Switch const for __code in struct ao_cmds + * altos: switch ao_cmd __xdata to __pdata + * altos: Switch ao_config.c __xdata to __pdata + * altos: Switch ao_dbg.c __xdata to __pdata + * altos: Switch ao_flight and ao_flight_nano __xdata to __pdata + * altos: Switch flash drivers __xdata to __pdata + * altos: Switch Tm and Tn to common telemetry code + * altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c + * altos: Ensure low-rate telem packets interleave with sensor telem packets + * altos: product defines are always in ao_product.h + * altosui: Build device constants into .java code + * altosui: Don't show missing igniter and gps values + * altos: new versions of sdcc require __ prefixes for custom keywords + * Set version to 0.9.4.3 for Bdale 2011-7-16 flights + * altosui: Start adding support for scanning radio for available devices + * altosui: Pop up monitor window from scan dialog + * altosui: Remove debugging printf from AltosLog + * altosui: Configuration telemetry record includes flight number + * altosui: Finish radio scanning UI + * altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry + * altosui: Initialize channel and telemetry before use in ScanUI + * altosui: Set 'seen' bits in legacy telemetry packet reader + * altosui: Add map preloading GUI + * altosui: Try to avoid resize weirdness with map preloading + * altosui: Flush telemetry lines before starting to watch for scan results + * altosui: Display full map preload area in view. + * altosui: Remove a bunch of sitemap debugging printfs + + [ Anthony Towns ] + * altosui: Make sure degree and minute values are visible (map preload) + + [ Keith Packard ] + * Set version to 0.9.4.4 + * altos, altosui: Add igniter mode (dual, apogee, main) + * altosui: Download list of site locations for map preloading + * altosui: Add launch-sites.txt + * altosui: Add a bunch more site locations + * altosui: Mark preload site location with red circles (like launch) + * Fix NCR Pawnee location + * Add HARA Bragg Farms site + * altosui: Change continutity colors to yellow/magenta + * altos: Add ability to read new TELEM files to ao_flight_test + * altos: Average height values for landing detection + * altos: Reduce height averaging filter time constant + * altos: Require sequencing through 'main' state before landing + * altosui: Standard text field in flight UI needs more width (now 20) + * altosui: Parse accel cal from 'c s' command + * altosui: Simple timeouts don't work with query data + * altosui: Add idle monitor dialog + * altos/altosui: Add pad orientation configure option + + [ Bdale Garbee ] + * update version for a Bdale build for use turning on TeleMini v1.0 + * simplify version in last changelog entry so git-dch is less confused + + -- Bdale Garbee Mon, 08 Aug 2011 07:35:18 -0600 + altos (0.9.1) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From ebaad64525119c0fdacf382adc2c99e5df5be23f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:37:23 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index cb28f93b..3321d552 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 6f9f75cbfccf975204ab847ca0e9cf86188716c6 +Author: Bdale Garbee +Date: Mon Aug 8 07:35:47 2011 -0600 + + update changelogs for Debian build + commit 7c94945690a6ff5cbf872026fd6411a30089c7b1 Author: Bdale Garbee Date: Mon Aug 8 07:33:09 2011 -0600 -- cgit v1.2.3 From 3cad81b0ebb52352c66643a2587e94a2b693a2d2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:38:48 -0600 Subject: stop doing automatic tag push during builds --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 83f3a53f..1ea1f68d 100755 --- a/debian/rules +++ b/debian/rules @@ -13,7 +13,7 @@ prebuild: git commit -n ChangeLog debian/changelog \ -m "update changelogs for Debian build" git tag debian/$(DEB_VERSION) - git push --tags origin master +# git push --tags origin master configure: configure-stamp configure-stamp: -- cgit v1.2.3 From f26c7172a1b2b5344fae6ede562f2da7a56b80e3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 07:54:14 -0600 Subject: build depend on bluetooth dev package --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 9f3fc532..61ba6cfe 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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, libtool, libjfreechart-java +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, libtool, libjfreechart-java, libbluetooth-dev Standards-Version: 3.9.1 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 5082b4998b8a9787e0e2f4d96d912e434aa9b81a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 09:31:18 -0600 Subject: clean up all existing lintian warnings --- debian/control | 2 +- debian/rules | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 61ba6cfe..fc70c8e0 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard 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, libtool, libjfreechart-java, libbluetooth-dev -Standards-Version: 3.9.1 +Standards-Version: 3.9.2 Homepage: http://altusmetrum.org/AltOS Package: altos diff --git a/debian/rules b/debian/rules index 1ea1f68d..1353321d 100755 --- a/debian/rules +++ b/debian/rules @@ -21,7 +21,9 @@ configure-stamp: ./autogen.sh --prefix=/usr touch configure-stamp -build: build-stamp +build: build-arch build-indep +build-arch: build-stamp +build-indep: build-stamp build-stamp: configure-stamp dh_testdir @@ -43,6 +45,7 @@ install: build dh_installdirs $(MAKE) DESTDIR=$(CURDIR)/debian/altos install + sed -i "/dependency_libs/ s/'.*'/''/" `find debian/altos/usr/lib/altos/ -name '*.la'` binary-indep: install -- cgit v1.2.3 From 4a507898d6de631bb2e8ed4aa3e0933d97222323 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 09:34:59 -0600 Subject: rewind changelog for re-build of 0.9.4.5 --- debian/changelog | 255 ------------------------------------------------------- 1 file changed, 255 deletions(-) diff --git a/debian/changelog b/debian/changelog index 0de954b3..b4425070 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,258 +1,3 @@ -altos (0.9.4.5) unstable; urgency=low - - [ Keith Packard ] - * altosui: Mark empty eeprom records 'invalid', don't generate exception - * altosui: Always read whole eeprom block, even at end of flight - * altosui: Display eeprom parsing errors to user - * Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" - - [ Anthony Towns ] - * src/ao_cmd: Shave off bytes from doc strings - - [ Keith Packard ] - * altos: Oops. Lost a couple of commands when merging the doc patch - * altosui: Missed jcommon.jar in the Mac OS install image - * Bump published version number to 0.9.1 - * aoview: remove -s option. - - [ Anthony Towns ] - * ao_intflash: Use internal flash for storage - - [ Keith Packard ] - * altos: Make serial, usb, beeper and accelerometer optional components - * altos/test: Use ao_convert.c instead of hand-coded pres → alt func - * altos/test: Add baro-only flight test program - * altos: Start with packet slave running. Turn off in pad mode. - * altos: Add TeleMini v1.0 - - [ Anthony Towns ] - * ao_intflash: Avoid overwriting code - - [ Keith Packard ] - * altos: Switch LED usage for TeleMini around - * altos: Switch pins around for TeleMini - * bringup: Add script for telemini - * ao-load: Make usb descriptor rewriting optional - * altos: oops -- altitude reporting wasn't pausing between signals - * altos: Internal flash ops block when running from flash - - [ Anthony Towns ] - * ignore new flight test file - - [ Keith Packard ] - * altos: Add tiny logging for TeleMini/TeleNano - * altos: Add kalman filters for baro-only boards - * altos: Tiny logging fixes. Scan at start, stop when land or full. - * altos: Add TeleNano support - - [ Bdale Garbee ] - * fix up script to work and have reasonable texts - - [ Keith Packard ] - * altos: Fix mini/nano default log size to available flash space - * altos/test: Add scripts to run lots of flights through the code - * altos: Write height values to log for nano/mini - * altos: Baro-only boards must not detect launch on accel or speed data - * altosui: Add software version to Configure AltosUI dialog - * altos: Don't init packet slave on TD. Make slave start optional - * altos: Configure packet size from send/recv parameters. - * altos: Make telemetry interval more consistent - * altos: Split out tiny telemetry from full telemetry - * altos: Split telenano main from telemini - * altos: The kalman code requires a constant sample rate - * altos: New telemetry report format (version 4). Supports tiny telemetry. - * altos: Add .sdcdbrc file for teledongle - * altos: Add nickle kalman implementation. - * altos: Switch telemetrum over to kalman filter - * altos: Compute a 'trust' value for the barometer - * altos/kalman: Kalman terms can be > 1, use 32-bit fixed point - * altos: Clean up some debug stuff in ao_flight.c - * altos: Add ao_flight_debug code - * altos: Missing parens and some bad arithmetic in the kalman code - * altos: Fix up flight code testing - * altos: Restore sensible kalman values - * altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. - * altos: Exit flight test at landing. Allow description in test flight list - * Add ao_kalman.h to .gitignore - * Add description to test flights - * altosui: Add support for telemetry version 4 - * altosui: Add telemetry format menu and preferences - * altosui: Remove a bunch of debug printfs from the eeprom manager code - * altosui: Add support for downloading TeleMini/TeleNano flight logs - * altosui: Remove extra AltosEepromBlock layer - * altosui: swing hide/show methods are deprecated - * altosui: Allow TM config connection to be canceled. - * altos: Variable log rate in full logging code too - * altos: full logging must flush pending data before checking state - * altosui: Off-by-one error in telemetry format configuration UI - * altosui: Allow radio channel to be configured over the radio link - * altosui: Tell serial device which frame to use for timeout dialogs - * altosui: Handle serial calls from swing thread - * altos: Split up flight code into separate flight/sample/kalman bits - * altos: Create custom nano flight code - * altosui: Clean up packet link connecting dialog - * altosui: Make flight log downloading handle 'Connecting...' dialog - * altosui: Make deployment testing handle Connecting... dialog - * altosui: Display exception messages from swing thread - * altosui: Don't display 0000-00-00 for missing flight log dates - * altos: ao_sample_preflight was exiting preflight mode immediately - * altos: Run RDF beacon after apogee instead of waiting for landing - * altos: Enable logging during nano flights - * altosui: Parse and export Max flight log value - * altosui: Only plot acceleration when present in data file - * altos: Reflect ao_flight split in ao_flight_test dependencies - * altos: Baro useful ceiling is MSL, not AGL - * altos: Make ao_flight_test show true height but report saturated height - * altos: Add initial TeleBT code - * altos: Add P2SEL_*_MASK defines to cc1111.h - * altos: expose set of available stdio values - * altos: Provide for a pre-filter on commands - * altos: Allow any stdio to be used with packet forwarding - * altos: Remove serial monitor command - * altos: Make ao_serial_drain public - * altos: Clean up usage of serial port for stdio - * altos: Clean up serial initialization - * altos: Make cmd echo per-connection instead of global - * altos: Clean up BT serial communcations - * altosui: Add missing AltosTelemetryMap.java file - * altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. - * altosui: Add TeleBT USB device support - * altosui: Add low-level Bluetooth APIs - * altos/altosui: Log averaged baro sensor data in Tm/Tn - * altosui: oops - lost state changes when downloading eeprom data. - * altos: Write a few pre-launch samples for Tm/Tn devices - * altosui: Add primitive bluetooth device manager UI. - * altosui: Create abstract AltosDevice class - * altosui: Make AltosBTDevice implement AltosDevice interface - * altosui: Make bluetooth dialog modal - * altosui: Use persistent list of bluetooth devices for device dialogs - * altos: Add delays to bt startup sequence - * altosui: Wait two seconds after bluetooth connect XXX - * altos: Solidify BT connections - * altos: Simplify BT communications - * altos: Remove bt debug command - * altos: remove BT logging code - * altosui: Eliminate ao_cmd_filter hook - * altosui: Make flight data download work through TeleBT - * altos: add telebt-v0.0 Makefile - * altosui: Separate out flash debug code to separate thread - * altosui: Fix TeleBT name in flight monitor title - * altosui: Display reader name (usually the device) when an I/O error occurs - * altosui: Move AltosIgniteUI device open out of Swing thread - * altosui: Fix BT manage dialog so that the device lists resize - * altos: Add preliminary telebt v0.1 defines - - [ Bdale Garbee ] - * first cut at a telebt turn on script - - [ Keith Packard ] - * altos: Add telebt-v0.1 to Makefile - * altos: Use USART configuration 1 with flow control for TBT - * altos: Fix BT link status pin for real TBT hardware - * altos: pull TBT v0.1 ser_reset line low - * altos: Add beeper to TBT v0.1 - * altos: Debugging TBT issues -- check pin configuration after boot - * altos: Initialize beeper for telebt - * altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line - * altos: clear CPU port 1 interrupt flag when handled - * Revert "altos: Debugging TBT issues -- check pin configuration after boot" - * Switch version to 0.9.4 - * altosui: Handle old TeleDongle receiving kalman telemetry packets - * altos: Rename telemetry to telemetry_orig - * altos: Add arbitrary telemetry packet monitoring - * altos: Add checksum to TELEM output lines - * altos: Start adding new telemetry frame definitions - * altos: ao_radio_recv needs byte count *including* rssi and status - * altosui: Support raw telemetry from TeleDongle - * doc: Add telemetry format description - * doc: Complete initial telemetry description - * doc: Fix a few minor telemetry doc mistakes - * Version strings must be < 8 bytes long - * altos: teledongle does not need ao_packet_slave.c - * altos: Shrink const space in ao_config - * altos: Add sat info to GPS report command - * altos: Shrink help text - * altos: Add split telemetry code - * altos: Complete new telemetry switchover - * altosui: Parse remaining standard telemetry packets - * doc: Chang Config and Location packets - * altos: Adapt to changes in telemetry Configuration packet - * doc: Add section about TeleDongle USB line format - * altosui: Elide nul bytes at end of telemetry string values - * altosui: Elide missing values from graphs - * altosui: Add main/drogue voltages to default graph - * altosui: Remove debug printf. - * altosui: Compress telemetry records marked with the same time - * altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd - * altos: Shrink ao_config_callsign_set - * altos: Shrink ao_add_task by rolling up a memset loop - * altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata - * altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata - * altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata - * altos: Switch ao_report.c __xdata to __pdata - * altos: Switch ao_rssi.c __xdata to __pdata - * altos: Switch ao_sample.c __xdata to __pdata - * altos: Switch ao_serial.c __xdata to __pdata - * altos: Switch ao_stdio.c __data to __pdata - * altos: Switch ao_telemetry.c __xdata to __pdata - * altos: Switch ao_usb.c __xdata to __pdata - * altos: Switch const for __code in struct ao_cmds - * altos: switch ao_cmd __xdata to __pdata - * altos: Switch ao_config.c __xdata to __pdata - * altos: Switch ao_dbg.c __xdata to __pdata - * altos: Switch ao_flight and ao_flight_nano __xdata to __pdata - * altos: Switch flash drivers __xdata to __pdata - * altos: Switch Tm and Tn to common telemetry code - * altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c - * altos: Ensure low-rate telem packets interleave with sensor telem packets - * altos: product defines are always in ao_product.h - * altosui: Build device constants into .java code - * altosui: Don't show missing igniter and gps values - * altos: new versions of sdcc require __ prefixes for custom keywords - * Set version to 0.9.4.3 for Bdale 2011-7-16 flights - * altosui: Start adding support for scanning radio for available devices - * altosui: Pop up monitor window from scan dialog - * altosui: Remove debugging printf from AltosLog - * altosui: Configuration telemetry record includes flight number - * altosui: Finish radio scanning UI - * altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry - * altosui: Initialize channel and telemetry before use in ScanUI - * altosui: Set 'seen' bits in legacy telemetry packet reader - * altosui: Add map preloading GUI - * altosui: Try to avoid resize weirdness with map preloading - * altosui: Flush telemetry lines before starting to watch for scan results - * altosui: Display full map preload area in view. - * altosui: Remove a bunch of sitemap debugging printfs - - [ Anthony Towns ] - * altosui: Make sure degree and minute values are visible (map preload) - - [ Keith Packard ] - * Set version to 0.9.4.4 - * altos, altosui: Add igniter mode (dual, apogee, main) - * altosui: Download list of site locations for map preloading - * altosui: Add launch-sites.txt - * altosui: Add a bunch more site locations - * altosui: Mark preload site location with red circles (like launch) - * Fix NCR Pawnee location - * Add HARA Bragg Farms site - * altosui: Change continutity colors to yellow/magenta - * altos: Add ability to read new TELEM files to ao_flight_test - * altos: Average height values for landing detection - * altos: Reduce height averaging filter time constant - * altos: Require sequencing through 'main' state before landing - * altosui: Standard text field in flight UI needs more width (now 20) - * altosui: Parse accel cal from 'c s' command - * altosui: Simple timeouts don't work with query data - * altosui: Add idle monitor dialog - * altos/altosui: Add pad orientation configure option - - [ Bdale Garbee ] - * update version for a Bdale build for use turning on TeleMini v1.0 - * simplify version in last changelog entry so git-dch is less confused - - -- Bdale Garbee Mon, 08 Aug 2011 07:35:18 -0600 - altos (0.9.1) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From a67c16958df8e60b131b01e00fd5bca590af0e7d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Mon, 8 Aug 2011 09:38:53 -0600 Subject: update changelogs for Debian build --- ChangeLog | 30 +++++++ debian/changelog | 261 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 291 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3321d552..bd8253c9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +commit 4a507898d6de631bb2e8ed4aa3e0933d97222323 +Author: Bdale Garbee +Date: Mon Aug 8 09:34:59 2011 -0600 + + rewind changelog for re-build of 0.9.4.5 + +commit 5082b4998b8a9787e0e2f4d96d912e434aa9b81a +Author: Bdale Garbee +Date: Mon Aug 8 09:31:18 2011 -0600 + + clean up all existing lintian warnings + +commit f26c7172a1b2b5344fae6ede562f2da7a56b80e3 +Author: Bdale Garbee +Date: Mon Aug 8 07:54:14 2011 -0600 + + build depend on bluetooth dev package + +commit 3cad81b0ebb52352c66643a2587e94a2b693a2d2 +Author: Bdale Garbee +Date: Mon Aug 8 07:38:48 2011 -0600 + + stop doing automatic tag push during builds + +commit ebaad64525119c0fdacf382adc2c99e5df5be23f +Author: Bdale Garbee +Date: Mon Aug 8 07:37:23 2011 -0600 + + update changelogs for Debian build + commit 6f9f75cbfccf975204ab847ca0e9cf86188716c6 Author: Bdale Garbee Date: Mon Aug 8 07:35:47 2011 -0600 diff --git a/debian/changelog b/debian/changelog index b4425070..858a65b3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,264 @@ +altos (0.9.4.5) unstable; urgency=low + + [ Keith Packard ] + * altosui: Mark empty eeprom records 'invalid', don't generate exception + * altosui: Always read whole eeprom block, even at end of flight + * altosui: Display eeprom parsing errors to user + * Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" + + [ Anthony Towns ] + * src/ao_cmd: Shave off bytes from doc strings + + [ Keith Packard ] + * altos: Oops. Lost a couple of commands when merging the doc patch + * altosui: Missed jcommon.jar in the Mac OS install image + * Bump published version number to 0.9.1 + * aoview: remove -s option. + + [ Anthony Towns ] + * ao_intflash: Use internal flash for storage + + [ Keith Packard ] + * altos: Make serial, usb, beeper and accelerometer optional components + * altos/test: Use ao_convert.c instead of hand-coded pres → alt func + * altos/test: Add baro-only flight test program + * altos: Start with packet slave running. Turn off in pad mode. + * altos: Add TeleMini v1.0 + + [ Anthony Towns ] + * ao_intflash: Avoid overwriting code + + [ Keith Packard ] + * altos: Switch LED usage for TeleMini around + * altos: Switch pins around for TeleMini + * bringup: Add script for telemini + * ao-load: Make usb descriptor rewriting optional + * altos: oops -- altitude reporting wasn't pausing between signals + * altos: Internal flash ops block when running from flash + + [ Anthony Towns ] + * ignore new flight test file + + [ Keith Packard ] + * altos: Add tiny logging for TeleMini/TeleNano + * altos: Add kalman filters for baro-only boards + * altos: Tiny logging fixes. Scan at start, stop when land or full. + * altos: Add TeleNano support + + [ Bdale Garbee ] + * fix up script to work and have reasonable texts + + [ Keith Packard ] + * altos: Fix mini/nano default log size to available flash space + * altos/test: Add scripts to run lots of flights through the code + * altos: Write height values to log for nano/mini + * altos: Baro-only boards must not detect launch on accel or speed data + * altosui: Add software version to Configure AltosUI dialog + * altos: Don't init packet slave on TD. Make slave start optional + * altos: Configure packet size from send/recv parameters. + * altos: Make telemetry interval more consistent + * altos: Split out tiny telemetry from full telemetry + * altos: Split telenano main from telemini + * altos: The kalman code requires a constant sample rate + * altos: New telemetry report format (version 4). Supports tiny telemetry. + * altos: Add .sdcdbrc file for teledongle + * altos: Add nickle kalman implementation. + * altos: Switch telemetrum over to kalman filter + * altos: Compute a 'trust' value for the barometer + * altos/kalman: Kalman terms can be > 1, use 32-bit fixed point + * altos: Clean up some debug stuff in ao_flight.c + * altos: Add ao_flight_debug code + * altos: Missing parens and some bad arithmetic in the kalman code + * altos: Fix up flight code testing + * altos: Restore sensible kalman values + * altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. + * altos: Exit flight test at landing. Allow description in test flight list + * Add ao_kalman.h to .gitignore + * Add description to test flights + * altosui: Add support for telemetry version 4 + * altosui: Add telemetry format menu and preferences + * altosui: Remove a bunch of debug printfs from the eeprom manager code + * altosui: Add support for downloading TeleMini/TeleNano flight logs + * altosui: Remove extra AltosEepromBlock layer + * altosui: swing hide/show methods are deprecated + * altosui: Allow TM config connection to be canceled. + * altos: Variable log rate in full logging code too + * altos: full logging must flush pending data before checking state + * altosui: Off-by-one error in telemetry format configuration UI + * altosui: Allow radio channel to be configured over the radio link + * altosui: Tell serial device which frame to use for timeout dialogs + * altosui: Handle serial calls from swing thread + * altos: Split up flight code into separate flight/sample/kalman bits + * altos: Create custom nano flight code + * altosui: Clean up packet link connecting dialog + * altosui: Make flight log downloading handle 'Connecting...' dialog + * altosui: Make deployment testing handle Connecting... dialog + * altosui: Display exception messages from swing thread + * altosui: Don't display 0000-00-00 for missing flight log dates + * altos: ao_sample_preflight was exiting preflight mode immediately + * altos: Run RDF beacon after apogee instead of waiting for landing + * altos: Enable logging during nano flights + * altosui: Parse and export Max flight log value + * altosui: Only plot acceleration when present in data file + * altos: Reflect ao_flight split in ao_flight_test dependencies + * altos: Baro useful ceiling is MSL, not AGL + * altos: Make ao_flight_test show true height but report saturated height + * altos: Add initial TeleBT code + * altos: Add P2SEL_*_MASK defines to cc1111.h + * altos: expose set of available stdio values + * altos: Provide for a pre-filter on commands + * altos: Allow any stdio to be used with packet forwarding + * altos: Remove serial monitor command + * altos: Make ao_serial_drain public + * altos: Clean up usage of serial port for stdio + * altos: Clean up serial initialization + * altos: Make cmd echo per-connection instead of global + * altos: Clean up BT serial communcations + * altosui: Add missing AltosTelemetryMap.java file + * altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. + * altosui: Add TeleBT USB device support + * altosui: Add low-level Bluetooth APIs + * altos/altosui: Log averaged baro sensor data in Tm/Tn + * altosui: oops - lost state changes when downloading eeprom data. + * altos: Write a few pre-launch samples for Tm/Tn devices + * altosui: Add primitive bluetooth device manager UI. + * altosui: Create abstract AltosDevice class + * altosui: Make AltosBTDevice implement AltosDevice interface + * altosui: Make bluetooth dialog modal + * altosui: Use persistent list of bluetooth devices for device dialogs + * altos: Add delays to bt startup sequence + * altosui: Wait two seconds after bluetooth connect XXX + * altos: Solidify BT connections + * altos: Simplify BT communications + * altos: Remove bt debug command + * altos: remove BT logging code + * altosui: Eliminate ao_cmd_filter hook + * altosui: Make flight data download work through TeleBT + * altos: add telebt-v0.0 Makefile + * altosui: Separate out flash debug code to separate thread + * altosui: Fix TeleBT name in flight monitor title + * altosui: Display reader name (usually the device) when an I/O error occurs + * altosui: Move AltosIgniteUI device open out of Swing thread + * altosui: Fix BT manage dialog so that the device lists resize + * altos: Add preliminary telebt v0.1 defines + + [ Bdale Garbee ] + * first cut at a telebt turn on script + + [ Keith Packard ] + * altos: Add telebt-v0.1 to Makefile + * altos: Use USART configuration 1 with flow control for TBT + * altos: Fix BT link status pin for real TBT hardware + * altos: pull TBT v0.1 ser_reset line low + * altos: Add beeper to TBT v0.1 + * altos: Debugging TBT issues -- check pin configuration after boot + * altos: Initialize beeper for telebt + * altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line + * altos: clear CPU port 1 interrupt flag when handled + * Revert "altos: Debugging TBT issues -- check pin configuration after boot" + * Switch version to 0.9.4 + * altosui: Handle old TeleDongle receiving kalman telemetry packets + * altos: Rename telemetry to telemetry_orig + * altos: Add arbitrary telemetry packet monitoring + * altos: Add checksum to TELEM output lines + * altos: Start adding new telemetry frame definitions + * altos: ao_radio_recv needs byte count *including* rssi and status + * altosui: Support raw telemetry from TeleDongle + * doc: Add telemetry format description + * doc: Complete initial telemetry description + * doc: Fix a few minor telemetry doc mistakes + * Version strings must be < 8 bytes long + * altos: teledongle does not need ao_packet_slave.c + * altos: Shrink const space in ao_config + * altos: Add sat info to GPS report command + * altos: Shrink help text + * altos: Add split telemetry code + * altos: Complete new telemetry switchover + * altosui: Parse remaining standard telemetry packets + * doc: Chang Config and Location packets + * altos: Adapt to changes in telemetry Configuration packet + * doc: Add section about TeleDongle USB line format + * altosui: Elide nul bytes at end of telemetry string values + * altosui: Elide missing values from graphs + * altosui: Add main/drogue voltages to default graph + * altosui: Remove debug printf. + * altosui: Compress telemetry records marked with the same time + * altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd + * altos: Shrink ao_config_callsign_set + * altos: Shrink ao_add_task by rolling up a memset loop + * altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata + * altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata + * altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata + * altos: Switch ao_report.c __xdata to __pdata + * altos: Switch ao_rssi.c __xdata to __pdata + * altos: Switch ao_sample.c __xdata to __pdata + * altos: Switch ao_serial.c __xdata to __pdata + * altos: Switch ao_stdio.c __data to __pdata + * altos: Switch ao_telemetry.c __xdata to __pdata + * altos: Switch ao_usb.c __xdata to __pdata + * altos: Switch const for __code in struct ao_cmds + * altos: switch ao_cmd __xdata to __pdata + * altos: Switch ao_config.c __xdata to __pdata + * altos: Switch ao_dbg.c __xdata to __pdata + * altos: Switch ao_flight and ao_flight_nano __xdata to __pdata + * altos: Switch flash drivers __xdata to __pdata + * altos: Switch Tm and Tn to common telemetry code + * altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c + * altos: Ensure low-rate telem packets interleave with sensor telem packets + * altos: product defines are always in ao_product.h + * altosui: Build device constants into .java code + * altosui: Don't show missing igniter and gps values + * altos: new versions of sdcc require __ prefixes for custom keywords + * Set version to 0.9.4.3 for Bdale 2011-7-16 flights + * altosui: Start adding support for scanning radio for available devices + * altosui: Pop up monitor window from scan dialog + * altosui: Remove debugging printf from AltosLog + * altosui: Configuration telemetry record includes flight number + * altosui: Finish radio scanning UI + * altosui: Generalize and centralize telemetry constants, parse v0.8 telemetry + * altosui: Initialize channel and telemetry before use in ScanUI + * altosui: Set 'seen' bits in legacy telemetry packet reader + * altosui: Add map preloading GUI + * altosui: Try to avoid resize weirdness with map preloading + * altosui: Flush telemetry lines before starting to watch for scan results + * altosui: Display full map preload area in view. + * altosui: Remove a bunch of sitemap debugging printfs + + [ Anthony Towns ] + * altosui: Make sure degree and minute values are visible (map preload) + + [ Keith Packard ] + * Set version to 0.9.4.4 + * altos, altosui: Add igniter mode (dual, apogee, main) + * altosui: Download list of site locations for map preloading + * altosui: Add launch-sites.txt + * altosui: Add a bunch more site locations + * altosui: Mark preload site location with red circles (like launch) + * Fix NCR Pawnee location + * Add HARA Bragg Farms site + * altosui: Change continutity colors to yellow/magenta + * altos: Add ability to read new TELEM files to ao_flight_test + * altos: Average height values for landing detection + * altos: Reduce height averaging filter time constant + * altos: Require sequencing through 'main' state before landing + * altosui: Standard text field in flight UI needs more width (now 20) + * altosui: Parse accel cal from 'c s' command + * altosui: Simple timeouts don't work with query data + * altosui: Add idle monitor dialog + * altos/altosui: Add pad orientation configure option + + [ Bdale Garbee ] + * update version for a Bdale build for use turning on TeleMini v1.0 + * simplify version in last changelog entry so git-dch is less confused + * update changelogs for Debian build + * update changelogs for Debian build + * stop doing automatic tag push during builds + * build depend on bluetooth dev package + * clean up all existing lintian warnings + * rewind changelog for re-build of 0.9.4.5 + + -- Bdale Garbee Mon, 08 Aug 2011 09:37:04 -0600 + altos (0.9.1) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 30670732ca3f5a34025ab4bc4c69afa45637b4d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 11:58:23 -0700 Subject: altos: Correct flight log max on Tm to 5k Was using the wrong #define name to check for Tm/Tn devices that use internal flash for data storage. Signed-off-by: Keith Packard --- src/ao_config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ao_config.c b/src/ao_config.c index 215dda92..c4d80890 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -29,7 +29,12 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL #define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP -#if USE_INTERNAL_EEPROM +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif +#if USE_INTERNAL_FLASH #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) -- cgit v1.2.3 From 7207a95823dc2a27906759528dd88256cb20679f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:04:00 -0700 Subject: altosui: Change button to 'Configure Altimeter' Now that we've got more than one model. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 9b724fd7..033f233c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -137,7 +137,7 @@ public class AltosUI extends JFrame { ExportData(); } }); - b = addButton(0, 1, "Configure TeleMetrum"); + b = addButton(0, 1, "Configure Altimter"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureTeleMetrum(); -- cgit v1.2.3 From e1e5c9b3e24670e9f58c6f7389eafb3338efdb40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:08:45 -0700 Subject: altos: Remove pad_orientation functions from non-accel devices Anything without an accelerometer can't detect pad orientation. Signed-off-by: Keith Packard --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_config.c b/src/ao_config.c index c4d80890..5e80d55d 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -370,7 +370,7 @@ ao_config_ignite_mode_set(void) __reentrant } #endif -#if HAS_IGNITE +#if HAS_ACCEL void ao_config_pad_orientation_show(void) __reentrant { -- cgit v1.2.3 From ba5dc35388d28c5769eaabc970c4d4b8c2c2ff9c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Aug 2011 23:07:53 -0700 Subject: altos: Add ability to set arbitrary radio frequency This adds a separate config parameter to control the raw radio frequency setting, allowing the user to select an arbitrary frequency instead of being forced to choose one of the 10 pre-defined 'channels'. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_config.c | 28 +++++++++++++++++++++++++++- src/ao_radio.c | 6 +++--- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/ao.h b/src/ao.h index b315af7a..bb3c80ec 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1373,6 +1373,7 @@ struct ao_config { uint32_t flight_log_max; /* minor version 4 */ uint8_t ignite_mode; /* minor version 5 */ uint8_t pad_orientation; /* minor version 6 */ + uint32_t radio_setting; /* minor version 7 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/ao_config.c b/src/ao_config.c index 5e80d55d..a5796b03 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -84,6 +84,7 @@ _ao_config_get(void) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + ao_config.radio_setting = ao_radio_cal; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -106,6 +107,8 @@ _ao_config_get(void) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; if (ao_config.minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + if (ao_config.minor < 7) + ao_config.radio_setting = ao_config.radio_cal; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -309,7 +312,7 @@ ao_config_radio_cal_set(void) __reentrant return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.radio_cal = ao_cmd_lex_u32; + ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_cal_show(); @@ -399,6 +402,27 @@ ao_config_pad_orientation_set(void) __reentrant } #endif +void +ao_config_radio_setting_show(void) __reentrant +{ + printf("Radio setting: %ld\n", ao_config.radio_setting); +} + +void +ao_config_radio_setting_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.radio_setting = ao_cmd_lex_u32; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_radio_setting_show(); + ao_radio_recv_abort(); +} + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -443,6 +467,8 @@ __code struct ao_config_var ao_config_vars[] = { { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", ao_config_show, ao_config_show }, #if HAS_EEPROM diff --git a/src/ao_radio.c b/src/ao_radio.c index 4c382bb9..1fb0eea6 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -287,9 +287,9 @@ ao_radio_get(uint8_t len) ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_cal); + RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_setting); RF_PKTLEN = len; } -- cgit v1.2.3 From f03ca0ab8799bfa5100eaa2577cfd7b9c37d05bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 7 Aug 2011 14:52:29 -0700 Subject: altosui: Add dialogs to configure 'common' frequencies These are stored in preferences, but not yet hooked up to the TM/TD configure dialogs Signed-off-by: Keith Packard --- altosui/AltosConfigFreqUI.java | 418 +++++++++++++++++++++++++++++++++++++++++ altosui/AltosConfigureUI.java | 18 +- altosui/AltosFrequency.java | 51 +++++ altosui/AltosPreferences.java | 66 +++++++ altosui/Makefile.am | 2 + 5 files changed, 553 insertions(+), 2 deletions(-) create mode 100644 altosui/AltosConfigFreqUI.java create mode 100644 altosui/AltosFrequency.java diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java new file mode 100644 index 00000000..d68151ec --- /dev/null +++ b/altosui/AltosConfigFreqUI.java @@ -0,0 +1,418 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 javax.swing.plaf.basic.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class AltosEditFreqUI extends JDialog implements ActionListener { + Frame frame; + JTextField frequency; + JTextField description; + JButton ok_button, cancel_button; + boolean got_ok; + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if ("ok".equals(cmd)) { + got_ok = true; + setVisible(false); + } + if ("cancel".equals(cmd)) { + got_ok = false; + setVisible(false); + } + } + + public AltosFrequency get() { + if (!got_ok) + return null; + + String f_s = frequency.getText(); + String d_s = description.getText(); + + try { + double f_d = Double.parseDouble(f_s); + + return new AltosFrequency(f_d, d_s); + } catch (NumberFormatException ne) { + } + return null; + } + + public AltosEditFreqUI(Frame in_frame, AltosFrequency existing) { + super(in_frame, true); + + got_ok = false; + frame = in_frame; + + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets (4,4,4,4); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Frequency"), c); + + frequency = new JTextField(12); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(frequency, c); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Description"), c); + + description = new JTextField(12); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(description, c); + + ok_button = new JButton("OK"); + ok_button.setActionCommand("ok"); + ok_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(ok_button, c); + + cancel_button = new JButton("Cancel"); + cancel_button.setActionCommand("cancel"); + cancel_button.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(cancel_button, c); + + if (existing == null) + setTitle("Add New Frequency"); + else { + setTitle("Edit Existing Frequency"); + frequency.setText(String.format("%7.3f", existing.frequency)); + description.setText(existing.description); + } + getRootPane().setDefaultButton(ok_button); + + pack(); + setLocationRelativeTo(frame); + + } + + public AltosEditFreqUI(Frame in_frame) { + this(in_frame, (AltosFrequency) null); + } +} + +public class AltosConfigFreqUI extends JDialog implements ActionListener { + + Frame frame; + LinkedList listeners; + + class FrequencyList extends JList { + DefaultListModel list_model; + + public void add(AltosFrequency frequency) { + int i; + for (i = 0; i < list_model.size(); i++) { + AltosFrequency f = (AltosFrequency) list_model.get(i); + if (f.frequency == frequency.frequency) + return; + if (f.frequency > frequency.frequency) + break; + } + list_model.insertElementAt(frequency, i); + } + + public void remove(AltosFrequency frequency) { + list_model.removeElement(frequency); + } + + //Subclass JList to workaround bug 4832765, which can cause the + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + + public AltosFrequency selected() { + AltosFrequency f = (AltosFrequency) getSelectedValue(); + return f; + } + + public AltosFrequency[] frequencies() { + AltosFrequency[] ret; + + ret = new AltosFrequency[list_model.size()]; + for (int i = 0; i < list_model.size(); i++) + ret[i] = (AltosFrequency) list_model.get(i); + return ret; + } + + public FrequencyList(AltosFrequency[] in_frequencies) { + list_model = new DefaultListModel(); + setModel(list_model); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setLayoutOrientation(JList.HORIZONTAL_WRAP); + for (int i = 0; i < in_frequencies.length; i++) { + add(in_frequencies[i]); + } + setVisibleRowCount(in_frequencies.length); + } + } + + FrequencyList frequencies; + + void save_frequencies() { + AltosPreferences.set_common_frequencies(frequencies.frequencies()); + } + + JButton add, edit, remove; + + JButton cancel, ok; + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if ("ok".equals(cmd)) { + save_frequencies(); + setVisible(false); + } else if ("cancel".equals(cmd)) { + setVisible(false); + } else if ("add".equals(cmd)) { + AltosEditFreqUI ui = new AltosEditFreqUI(frame); + ui.setVisible(true); + AltosFrequency f = ui.get(); + if (f != null) + frequencies.add(f); + } else if ("edit".equals(cmd)) { + AltosFrequency old_f = frequencies.selected(); + if (old_f == null) + return; + AltosEditFreqUI ui = new AltosEditFreqUI(frame, old_f); + ui.setVisible(true); + AltosFrequency new_f = ui.get(); + if (new_f != null) { + if (old_f != null) + frequencies.remove(old_f); + frequencies.add(new_f); + } + } else if ("remove".equals(cmd)) { + AltosFrequency old_f = frequencies.selected(); + if (old_f == null) + return; + int ret = JOptionPane.showConfirmDialog(this, + String.format("Remove frequency \"%s\"?", + old_f.toShortString()), + "Remove Frequency", + JOptionPane.YES_NO_OPTION); + if (ret == JOptionPane.YES_OPTION) + frequencies.remove(old_f); + } + } + + public AltosFrequency[] frequencies() { + return frequencies.frequencies(); + } + + public AltosConfigFreqUI(Frame in_frame, + AltosFrequency[] in_frequencies) { + super(in_frame, "Manage Frequencies", true); + + frame = in_frame; + + listeners = new LinkedList(); + + frequencies = new FrequencyList(in_frequencies); + + Container pane = getContentPane(); + pane.setLayout(new GridBagLayout()); + + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(4,4,4,4); + + /* + * Frequencies label and list + */ + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 1; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(new JLabel("Frequencies"), c); + + JScrollPane list_scroller = new JScrollPane(frequencies); + list_scroller.setAlignmentX(LEFT_ALIGNMENT); + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 6; + c.gridheight = 2; + c.weightx = 1; + c.weighty = 1; + pane.add(list_scroller, c); + + add = new JButton("Add"); + add.setActionCommand("add"); + add.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(add, c); + + edit = new JButton("Edit"); + edit.setActionCommand("edit"); + edit.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 2; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(edit, c); + + remove = new JButton("Remove"); + remove.setActionCommand("remove"); + remove.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 4; + c.gridy = 3; + c.gridwidth = 2; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(remove, c); + + ok = new JButton("OK"); + ok.setActionCommand("ok"); + ok.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 3; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(ok, c); + + cancel = new JButton("Cancel"); + cancel.setActionCommand("cancel"); + cancel.addActionListener(this); + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.gridx = 3; + c.gridy = 4; + c.gridwidth = 3; + c.gridheight = 1; + c.weightx = 0; + c.weighty = 0; + pane.add(cancel, c); + + pack(); + setLocationRelativeTo(frame); + } + + public static void show(Component frameComp) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosConfigFreqUI dialog; + + dialog = new AltosConfigFreqUI(frame, AltosPreferences.common_frequencies()); + dialog.setVisible(true); + } + +} diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 0f5e4a3b..a8a70ffd 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -50,6 +50,7 @@ public class AltosConfigureUI JRadioButton serial_debug; JButton manage_bluetooth; + JButton manage_frequencies; /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { @@ -207,13 +208,26 @@ public class AltosConfigureUI AltosBTManage.show(owner, Altos.bt_known); } }); - c.gridx = 1; + c.gridx = 0; c.gridy = 6; - c.gridwidth = 3; + c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; pane.add(manage_bluetooth, c); + manage_frequencies = new JButton("Manage Frequencies"); + manage_frequencies.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosConfigFreqUI.show(owner); + } + }); + c.gridx = 2; + c.gridy = 6; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(manage_frequencies, c); + /* And a close button at the bottom */ close = new JButton("Close"); close.addActionListener(new ActionListener() { diff --git a/altosui/AltosFrequency.java b/altosui/AltosFrequency.java new file mode 100644 index 00000000..8265eafc --- /dev/null +++ b/altosui/AltosFrequency.java @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 javax.swing.plaf.basic.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosFrequency { + double frequency; + String description; + + public String toString() { + return String.format("%7.3f MHz %-20.20s", + frequency, description); + } + + public String toShortString() { + return String.format("%7.3f MHz %s", + frequency, description); + } + + public AltosFrequency(double f, String d) { + frequency = f; + description = d; + } +} \ No newline at end of file diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index c8dee743..e92b9532 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -64,6 +64,9 @@ class AltosPreferences { /* Channel (map serial to channel) */ static Hashtable channels; + /* Frequency (map serial to frequency) */ + static Hashtable frequencies; + /* Telemetry (map serial to telemetry format) */ static Hashtable telemetries; @@ -79,6 +82,55 @@ class AltosPreferences { /* Serial debug */ static boolean serial_debug; + /* List of frequencies */ + final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; + static AltosFrequency[] common_frequencies; + + final static String frequency_count = "COUNT"; + final static String frequency_format = "FREQUENCY-%d"; + final static String description_format = "DESCRIPTION-%d"; + + static AltosFrequency[] load_common_frequencies() { + AltosFrequency[] frequencies = null; + boolean existing = false; + try { + existing = preferences.nodeExists(common_frequencies_node_name); + } catch (BackingStoreException be) { + existing = false; + } + if (existing) { + Preferences node = preferences.node(common_frequencies_node_name); + int count = node.getInt(frequency_count, 0); + + frequencies = new AltosFrequency[count]; + for (int i = 0; i < count; i++) { + double frequency; + String description; + + frequency = node.getDouble(String.format(frequency_format, i), 0.0); + description = node.get(String.format(description_format, i), null); + frequencies[i] = new AltosFrequency(frequency, description); + } + } else { + frequencies = new AltosFrequency[10]; + for (int i = 0; i < 10; i++) { + frequencies[i] = new AltosFrequency(434.550 + i * .1, + String.format("Channel %d", i)); + } + } + return frequencies; + } + + static void save_common_frequencies(AltosFrequency[] frequencies) { + Preferences node = preferences.node(common_frequencies_node_name); + + node.putInt(frequency_count, frequencies.length); + for (int i = 0; i < frequencies.length; i++) { + node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); + node.put(String.format(description_format, i), frequencies[i].description); + } + } + public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -112,6 +164,8 @@ class AltosPreferences { serial_debug = preferences.getBoolean(serialDebugPreference, false); AltosSerial.set_debug(serial_debug); + + common_frequencies = load_common_frequencies(); } static { init(); } @@ -273,4 +327,16 @@ class AltosPreferences { public static Preferences bt_devices() { return preferences.node("bt_devices"); } + + public static AltosFrequency[] common_frequencies() { + return common_frequencies; + } + + public static void set_common_frequencies(AltosFrequency[] frequencies) { + common_frequencies = frequencies; + synchronized(preferences) { + save_common_frequencies(frequencies); + flush_preferences(); + } + } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 008bd097..d6fd0e6d 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -16,6 +16,7 @@ altosui_JAVA = \ AltosChannelMenu.java \ AltosConfig.java \ AltosConfigData.java \ + AltosConfigFreqUI.java \ AltosConfigUI.java \ AltosConfigureUI.java \ AltosConvert.java \ @@ -50,6 +51,7 @@ altosui_JAVA = \ AltosFlightReader.java \ AltosFlightStatus.java \ AltosFlightUI.java \ + AltosFrequency.java \ AltosGPS.java \ AltosGPSSat.java \ AltosGreatCircle.java \ -- cgit v1.2.3 From 0e3e4f9c1e6a6bf972514f12c9d622258aa2aec2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 01:47:29 -0700 Subject: altosui: Convert from channels to frequencies Major areas: * Preferences are stored as frequencies instead of channels * Serial configuration is done using frequencies * UI is presented with frequency lists Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 54 +++++++++++++--- altosui/AltosConfigData.java | 4 +- altosui/AltosConfigFreqUI.java | 4 +- altosui/AltosConfigUI.java | 58 ++++++++++++------ altosui/AltosConvert.java | 33 ++++++++++ altosui/AltosEepromDelete.java | 15 ++--- altosui/AltosEepromDownload.java | 13 ++-- altosui/AltosFlightReader.java | 7 ++- altosui/AltosFlightUI.java | 26 +++++--- altosui/AltosFreqList.java | 87 ++++++++++++++++++++++++++ altosui/AltosFrequency.java | 6 ++ altosui/AltosIdleMonitorUI.java | 35 ++++++----- altosui/AltosIgnite.java | 37 ++++++----- altosui/AltosPreferences.java | 47 ++++++++++---- altosui/AltosScanUI.java | 125 ++++++++++++++++++++++++-------------- altosui/AltosSerial.java | 72 +++++++++++++++------- altosui/AltosTelemetryReader.java | 27 ++++++-- altosui/AltosUI.java | 12 +++- altosui/Makefile.am | 1 + 19 files changed, 486 insertions(+), 177 deletions(-) create mode 100644 altosui/AltosFreqList.java diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 04d75528..694ef4db 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -64,6 +64,8 @@ public class AltosConfig implements ActionListener { AltosDevice device; AltosSerial serial_line; boolean remote; + AltosConfigData remote_config_data; + double remote_frequency; int_ref serial; int_ref main_deploy; int_ref apogee_delay; @@ -72,6 +74,7 @@ public class AltosConfig implements ActionListener { int_ref flight_log_max; int_ref ignite_mode; int_ref pad_orientation; + int_ref radio_setting; string_ref version; string_ref product; string_ref callsign; @@ -109,7 +112,7 @@ public class AltosConfig implements ActionListener { } } - void start_serial() throws InterruptedException { + void start_serial() throws InterruptedException, TimeoutException { serial_started = true; if (remote) serial_line.start_remote(); @@ -129,12 +132,13 @@ public class AltosConfig implements ActionListener { config_ui.set_version(version.get()); config_ui.set_main_deploy(main_deploy.get()); config_ui.set_apogee_delay(apogee_delay.get()); - config_ui.set_radio_channel(radio_channel.get()); + config_ui.set_radio_frequency(frequency()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); + config_ui.set_radio_setting(radio_setting.get()); config_ui.set_clean(); config_ui.make_visible(); } @@ -157,6 +161,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Max flight log:", flight_log_max); get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); + get_int(line, "Radio setting:", radio_setting); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -200,6 +205,7 @@ public class AltosConfig implements ActionListener { } } } catch (InterruptedException ie) { + } catch (TimeoutException te) { } finally { try { stop_serial(); @@ -211,16 +217,20 @@ public class AltosConfig implements ActionListener { void save_data() { try { - int channel; + double frequency = frequency(); + boolean has_setting = radio_setting.get() != 0; start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); - channel = radio_channel.get(); - serial_line.printf("c r %d\n", channel); + serial_line.set_radio_frequency(frequency, + has_setting, + radio_calibration.get()); if (remote) { serial_line.stop_remote(); - serial_line.set_channel(channel); - AltosPreferences.set_channel(device.getSerial(), channel); + serial_line.set_radio_frequency(frequency, + has_setting, + radio_calibration.get()); + AltosPreferences.set_frequency(device.getSerial(), frequency); serial_line.start_remote(); } if (!remote) @@ -234,6 +244,7 @@ public class AltosConfig implements ActionListener { serial_line.printf("c o %d\n", pad_orientation.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { + } catch (TimeoutException te) { } finally { try { stop_serial(); @@ -248,6 +259,7 @@ public class AltosConfig implements ActionListener { serial_line.printf("r eboot\n"); serial_line.flush_output(); } catch (InterruptedException ie) { + } catch (TimeoutException te) { } finally { try { stop_serial(); @@ -308,11 +320,32 @@ public class AltosConfig implements ActionListener { update_ui(); } + double frequency() { + int setting = radio_setting.get(); + + if (setting != 0) + return AltosConvert.radio_setting_to_frequency(setting, radio_calibration.get()); + else + return AltosConvert.radio_channel_to_frequency(radio_channel.get()); + } + + void set_frequency(double freq) { + int setting = radio_setting.get(); + + if (setting != 0) { + radio_setting.set(AltosConvert.radio_frequency_to_setting(freq, + radio_calibration.get())); + radio_channel.set(0); + } else { + radio_channel.set(AltosConvert.radio_frequency_to_channel(freq)); + } + } + void save_data() { main_deploy.set(config_ui.main_deploy()); apogee_delay.set(config_ui.apogee_delay()); - radio_channel.set(config_ui.radio_channel()); radio_calibration.set(config_ui.radio_calibration()); + set_frequency(config_ui.radio_frequency()); flight_log_max.set(config_ui.flight_log_max()); ignite_mode.set(config_ui.ignite_mode()); pad_orientation.set(config_ui.pad_orientation()); @@ -348,6 +381,7 @@ public class AltosConfig implements ActionListener { main_deploy = new int_ref(250); apogee_delay = new int_ref(0); radio_channel = new int_ref(0); + radio_setting = new int_ref(0); radio_calibration = new int_ref(1186611); flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); @@ -360,9 +394,9 @@ public class AltosConfig implements ActionListener { if (device != null) { try { serial_line = new AltosSerial(device); - if (!device.matchProduct(Altos.product_telemetrum)) - remote = true; try { + if (!device.matchProduct(Altos.product_telemetrum)) + remote = true; init_ui(); } catch (InterruptedException ie) { abort(); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 1d50ade9..aa7a90de 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -47,6 +47,7 @@ public class AltosConfigData implements Iterable { int main_deploy; int apogee_delay; int radio_channel; + int radio_setting; String callsign; int accel_cal_plus, accel_cal_minus; int radio_calibration; @@ -85,7 +86,7 @@ public class AltosConfigData implements Iterable { serial_line.printf("c s\nv\n"); lines = new LinkedList(); for (;;) { - String line = serial_line.get_reply_no_dialog(5000); + String line = serial_line.get_reply(); if (line == null) throw new TimeoutException(); if (line.contains("Syntax error")) @@ -95,6 +96,7 @@ public class AltosConfigData implements Iterable { try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} try { if (line.startsWith("Accel cal")) { String[] bits = line.split("\\s+"); diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index d68151ec..063d21b4 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -177,9 +177,9 @@ public class AltosConfigFreqUI extends JDialog implements ActionListener { int i; for (i = 0; i < list_model.size(); i++) { AltosFrequency f = (AltosFrequency) list_model.get(i); - if (f.frequency == frequency.frequency) + if (frequency.frequency == f.frequency) return; - if (f.frequency > frequency.frequency) + if (frequency.frequency < f.frequency) break; } list_model.insertElementAt(frequency, i); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 1a48c1d3..c109924e 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -43,8 +43,9 @@ public class AltosConfigUI JLabel serial_label; JLabel main_deploy_label; JLabel apogee_delay_label; - JLabel radio_channel_label; + JLabel frequency_label; JLabel radio_calibration_label; + JLabel radio_frequency_label; JLabel flight_log_max_label; JLabel ignite_mode_label; JLabel pad_orientation_label; @@ -58,7 +59,7 @@ public class AltosConfigUI JLabel serial_value; JComboBox main_deploy_value; JComboBox apogee_delay_value; - JComboBox radio_channel_value; + AltosFreqList radio_frequency_value; JTextField radio_calibration_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; @@ -98,13 +99,6 @@ public class AltosConfigUI "Antenna Down", }; - static String[] radio_channel_values = new String[10]; - { - for (int i = 0; i <= 9; i++) - radio_channel_values[i] = String.format("Channel %1d (%7.3fMHz)", - i, 434.550 + i * 0.1); - } - /* A window listener to catch closing events and tell the config code */ class ConfigListener extends WindowAdapter { AltosConfigUI ui; @@ -245,7 +239,7 @@ public class AltosConfigUI apogee_delay_value.addItemListener(this); pane.add(apogee_delay_value, c); - /* Radio channel */ + /* Frequency */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 5; c.gridwidth = 4; @@ -253,8 +247,8 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = il; c.ipady = 5; - radio_channel_label = new JLabel("Radio Channel:"); - pane.add(radio_channel_label, c); + radio_frequency_label = new JLabel("Frequency:"); + pane.add(radio_frequency_label, c); c = new GridBagConstraints(); c.gridx = 4; c.gridy = 5; @@ -264,10 +258,9 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - radio_channel_value = new JComboBox(radio_channel_values); - radio_channel_value.setEditable(false); - radio_channel_value.addItemListener(this); - pane.add(radio_channel_value, c); + radio_frequency_value = new AltosFreqList(); + radio_frequency_value.addItemListener(this); + pane.add(radio_frequency_value, c); /* Radio Calibration */ c = new GridBagConstraints(); @@ -501,6 +494,7 @@ public class AltosConfigUI /* set and get all of the dialog values */ public void set_product(String product) { + radio_frequency_value.set_product(product); product_value.setText(product); } @@ -509,6 +503,7 @@ public class AltosConfigUI } public void set_serial(int serial) { + radio_frequency_value.set_serial(serial); serial_value.setText(String.format("%d", serial)); } @@ -528,12 +523,32 @@ public class AltosConfigUI return Integer.parseInt(apogee_delay_value.getSelectedItem().toString()); } - public void set_radio_channel(int new_radio_channel) { - radio_channel_value.setSelectedIndex(new_radio_channel); + public void set_radio_frequency(double new_radio_frequency) { + int i; + for (i = 0; i < radio_frequency_value.getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i); + + if (f.close(new_radio_frequency)) { + radio_frequency_value.setSelectedIndex(i); + return; + } + } + for (i = 0; i < radio_frequency_value.getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i); + + if (new_radio_frequency < f.frequency) + break; + } + String description = String.format("%s serial %s", + product_value.getText(), + serial_value.getText()); + AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description); + AltosPreferences.add_common_frequency(new_frequency); + radio_frequency_value.insertItemAt(new_frequency, i); } - public int radio_channel() { - return radio_channel_value.getSelectedIndex(); + public double radio_frequency() { + return radio_frequency_value.frequency(); } public void set_radio_calibration(int new_radio_calibration) { @@ -548,6 +563,9 @@ public class AltosConfigUI callsign_value.setText(new_callsign); } + public void set_radio_setting(int new_radio_setting) { + } + public String callsign() { return callsign_value.getText(); } diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java index 8cc1df27..6a9b699c 100644 --- a/altosui/AltosConvert.java +++ b/altosui/AltosConvert.java @@ -189,4 +189,37 @@ public class AltosConvert { { return ignite / 32767 * 15.0; } + + static double + radio_setting_to_frequency(int setting, int cal) { + double f; + + f = 434.550 * setting / cal; + /* Round to nearest 50KHz */ + f = Math.floor (20.0 * f + 0.5) / 20.0; + return f; + } + + static int + radio_frequency_to_setting(double frequency, int cal) { + double set = frequency / 434.550 * cal; + + return (int) Math.floor (set + 0.5); + } + + static double + radio_channel_to_frequency(int channel) { + return 434.550 + channel * 0.100; + } + + static int + radio_frequency_to_channel(double frequency) { + int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); + + if (channel < 0) + channel = 0; + if (channel > 9) + channel = 9; + return channel; + } } diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index ecd82c18..94951ced 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -84,11 +84,11 @@ public class AltosEepromDelete implements Runnable { } public void run () { - if (remote) - serial_line.start_remote(); - success = false; try { + if (remote) + serial_line.start_remote(); + for (AltosEepromLog log : flights) { if (log.delete) { DeleteLog(log); @@ -103,11 +103,12 @@ public class AltosEepromDelete implements Runnable { show_error (String.format("Connection to \"%s\" failed", serial_line.device.toShortString()), "Connection Failed"); + } finally { + if (remote) + serial_line.stop_remote(); + serial_line.flush_output(); + serial_line.close(); } - if (remote) - serial_line.stop_remote(); - serial_line.flush_output(); - serial_line.close(); if (listener != null) { Runnable r = new Runnable() { public void run() { diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 82f01ef5..64dcdff7 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -264,11 +264,11 @@ public class AltosEepromDownload implements Runnable { } public void run () { - if (remote) - serial_line.start_remote(); - try { boolean failed = false; + if (remote) + serial_line.start_remote(); + for (AltosEepromLog log : flights) { parse_exception = null; if (log.download) { @@ -295,11 +295,12 @@ public class AltosEepromDownload implements Runnable { serial_line.device.toShortString()), "Connection Failed", JOptionPane.ERROR_MESSAGE); + } finally { + if (remote) + serial_line.stop_remote(); + serial_line.flush_output(); } - if (remote) - serial_line.stop_remote(); monitor.done(); - serial_line.flush_output(); if (listener != null) { Runnable r = new Runnable() { public void run() { diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java index f665bda8..3a171444 100644 --- a/altosui/AltosFlightReader.java +++ b/altosui/AltosFlightReader.java @@ -20,6 +20,7 @@ package altosui; import java.lang.*; import java.text.*; import java.io.*; +import java.util.concurrent.*; public class AltosFlightReader { String name; @@ -32,9 +33,13 @@ public class AltosFlightReader { void close(boolean interrupted) { } - void set_channel(int channel) { } + void set_frequency(double frequency) throws InterruptedException, TimeoutException { } + + void save_frequency() { } void set_telemetry(int telemetry) { } + void save_telemetry() { } + void update(AltosState state) throws InterruptedException { } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 04bfc90d..8c3f821e 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosVoice voice; @@ -118,7 +118,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } Container bag; - JComboBox channels; + AltosFreqList frequencies; JComboBox telemetries; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { @@ -141,18 +141,25 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { /* Stick channel selector at top of table for telemetry monitoring */ if (serial >= 0) { // Channel menu - channels = new AltosChannelMenu(AltosPreferences.channel(serial)); - channels.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int channel = channels.getSelectedIndex(); - reader.set_channel(channel); - } + frequencies = new AltosFreqList(AltosPreferences.frequency(serial)); + frequencies.set_product("Monitor"); + frequencies.set_serial(serial); + frequencies.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + double frequency = frequencies.frequency(); + reader.save_frequency(); + try { + reader.set_frequency(frequency); + } catch (TimeoutException te) { + } catch (InterruptedException ie) { + } + } }); c.gridx = 0; c.gridy = 0; c.insets = new Insets(3, 3, 3, 3); c.anchor = GridBagConstraints.WEST; - bag.add (channels, c); + bag.add (frequencies, c); // Telemetry format menu telemetries = new JComboBox(); @@ -168,6 +175,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { public void actionPerformed(ActionEvent e) { int telemetry = telemetries.getSelectedIndex() + 1; reader.set_telemetry(telemetry); + reader.save_telemetry(); } }); c.gridx = 1; diff --git a/altosui/AltosFreqList.java b/altosui/AltosFreqList.java new file mode 100644 index 00000000..59b0e127 --- /dev/null +++ b/altosui/AltosFreqList.java @@ -0,0 +1,87 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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; + +public class AltosFreqList extends JComboBox { + + String product; + int serial; + int calibrate; + + public void set_frequency(double new_frequency) { + int i; + for (i = 0; i < getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) getItemAt(i); + + if (f.close(new_frequency)) { + setSelectedIndex(i); + return; + } + } + for (i = 0; i < getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) getItemAt(i); + + if (new_frequency < f.frequency) + break; + } + String description = String.format("%s serial %d", product, serial); + AltosFrequency frequency = new AltosFrequency(new_frequency, description); + AltosPreferences.add_common_frequency(frequency); + insertItemAt(frequency, i); + setMaximumRowCount(getItemCount()); + } + + public void set_product(String new_product) { + product = new_product; + } + + public void set_serial(int new_serial) { + serial = new_serial; + } + + public double frequency() { + AltosFrequency f = (AltosFrequency) getSelectedItem(); + if (f != null) + return f.frequency; + return 434.550; + } + + public AltosFreqList () { + super(AltosPreferences.common_frequencies()); + setMaximumRowCount(getItemCount()); + setEditable(false); + product = "Unknown"; + serial = 0; + } + + public AltosFreqList(double in_frequency) { + this(); + set_frequency(in_frequency); + } +} diff --git a/altosui/AltosFrequency.java b/altosui/AltosFrequency.java index 8265eafc..0617ce74 100644 --- a/altosui/AltosFrequency.java +++ b/altosui/AltosFrequency.java @@ -44,6 +44,12 @@ public class AltosFrequency { frequency, description); } + public boolean close(double f) { + double diff = Math.abs(frequency - f); + + return diff < 0.010; + } + public AltosFrequency(double f, String d) { frequency = f; description = d; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index a4262cae..0370efa9 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -167,7 +167,7 @@ class AltosIdleMonitor extends Thread { AltosIdleMonitorUI ui; AltosState state; boolean remote; - int channel; + double frequency; AltosState previous_state; AltosConfigData config_data; AltosADC adc; @@ -178,7 +178,7 @@ class AltosIdleMonitor extends Thread { try { if (remote) { - set_channel(channel); + serial.set_radio_frequency(frequency); serial.start_remote(); } else serial.flush_input(); @@ -217,8 +217,8 @@ class AltosIdleMonitor extends Thread { state = new AltosState (record, state); } - void set_channel(int in_channel) { - channel = in_channel; + void set_frequency(double in_frequency) { + frequency = in_frequency; } public void post_state() { @@ -246,7 +246,7 @@ class AltosIdleMonitor extends Thread { } public AltosIdleMonitor(AltosIdleMonitorUI in_ui, AltosDevice in_device, boolean in_remote) - throws FileNotFoundException, AltosSerialInUseException { + throws FileNotFoundException, AltosSerialInUseException, InterruptedException, TimeoutException { device = in_device; ui = in_ui; serial = new AltosSerial(device); @@ -299,9 +299,10 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { } Container bag; - JComboBox channels; + AltosFreqList frequencies; - public AltosIdleMonitorUI(JFrame in_owner) throws FileNotFoundException, AltosSerialInUseException { + public AltosIdleMonitorUI(JFrame in_owner) + throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException { device = AltosDeviceDialog.show(in_owner, Altos.product_any); remote = false; @@ -320,21 +321,23 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { setTitle(String.format("AltOS %s", device.toShortString())); - /* Stick channel selector at top of table for telemetry monitoring */ + /* Stick frequency selector at top of table for telemetry monitoring */ if (remote && serial >= 0) { - // Channel menu - channels = new AltosChannelMenu(AltosPreferences.channel(serial)); - channels.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int channel = channels.getSelectedIndex(); - thread.set_channel(channel); - } + // Frequency menu + frequencies = new AltosFreqList(AltosPreferences.frequency(serial)); + frequencies.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + double frequency = frequencies.frequency(); + thread.set_frequency(frequency); + AltosPreferences.set_frequency(device.getSerial(), + frequency); + } }); c.gridx = 0; c.gridy = 0; c.insets = new Insets(3, 3, 3, 3); c.anchor = GridBagConstraints.WEST; - bag.add (channels, c); + bag.add (frequencies, c); } diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index 7a06c63d..3e52ea36 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -40,7 +40,7 @@ public class AltosIgnite { final static int Active = 2; final static int Open = 3; - private void start_serial() throws InterruptedException { + private void start_serial() throws InterruptedException, TimeoutException { serial_started = true; if (remote) serial.start_remote(); @@ -102,22 +102,25 @@ public class AltosIgnite { if (serial == null) return status; string_ref status_name = new string_ref(); - start_serial(); - serial.printf("t\n"); - for (;;) { - String line = serial.get_reply(5000); - if (line == null) - throw new TimeoutException(); - if (get_string(line, "Igniter: drogue Status: ", status_name)) - if (igniter == Apogee) - status = status(status_name.get()); - if (get_string(line, "Igniter: main Status: ", status_name)) { - if (igniter == Main) - status = status(status_name.get()); - break; + try { + start_serial(); + serial.printf("t\n"); + for (;;) { + String line = serial.get_reply(5000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Igniter: drogue Status: ", status_name)) + if (igniter == Apogee) + status = status(status_name.get()); + if (get_string(line, "Igniter: main Status: ", status_name)) { + if (igniter == Main) + status = status(status_name.get()); + break; + } } + } finally { + stop_serial(); } - stop_serial(); return status; } @@ -145,6 +148,7 @@ public class AltosIgnite { break; } } catch (InterruptedException ie) { + } catch (TimeoutException te) { } finally { try { stop_serial(); @@ -166,7 +170,8 @@ public class AltosIgnite { serial.set_frame(frame); } - public AltosIgnite(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + public AltosIgnite(AltosDevice in_device) + throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException { device = in_device; serial = new AltosSerial(device); diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index e92b9532..8609f94e 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -34,6 +34,9 @@ class AltosPreferences { /* channel preference name */ final static String channelPreferenceFormat = "CHANNEL-%d"; + /* frequency preference name */ + final static String frequencyPreferenceFormat = "FREQUENCY-%d"; + /* telemetry format preference name */ final static String telemetryPreferenceFormat = "TELEMETRY-%d"; @@ -61,9 +64,6 @@ class AltosPreferences { /* Map directory -- hangs of logdir */ static File mapdir; - /* Channel (map serial to channel) */ - static Hashtable channels; - /* Frequency (map serial to frequency) */ static Hashtable frequencies; @@ -148,7 +148,7 @@ class AltosPreferences { if (!mapdir.exists()) mapdir.mkdirs(); - channels = new Hashtable(); + frequencies = new Hashtable(); telemetries = new Hashtable(); @@ -242,20 +242,24 @@ class AltosPreferences { return mapdir; } - public static void set_channel(int serial, int new_channel) { - channels.put(serial, new_channel); + public static void set_frequency(int serial, double new_frequency) { + frequencies.put(serial, new_frequency); synchronized (preferences) { - preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel); + preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); flush_preferences(); } } - public static int channel(int serial) { - if (channels.containsKey(serial)) - return channels.get(serial); - int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); - channels.put(serial, channel); - return channel; + public static double frequency(int serial) { + if (frequencies.containsKey(serial)) + return frequencies.get(serial); + double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); + if (frequency == 0.0) { + int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + frequency = AltosConvert.radio_channel_to_frequency(channel); + } + frequencies.put(serial, frequency); + return frequency; } public static void set_telemetry(int serial, int new_telemetry) { @@ -339,4 +343,21 @@ class AltosPreferences { flush_preferences(); } } + + public static void add_common_frequency(AltosFrequency frequency) { + AltosFrequency[] new_frequencies = new AltosFrequency[common_frequencies.length + 1]; + int i; + + for (i = 0; i < common_frequencies.length; i++) { + if (frequency.frequency == common_frequencies[i].frequency) + return; + if (frequency.frequency < common_frequencies[i].frequency) + break; + new_frequencies[i] = common_frequencies[i]; + } + new_frequencies[i] = frequency; + for (; i < common_frequencies.length; i++) + new_frequencies[i+1] = common_frequencies[i]; + set_common_frequencies(new_frequencies); + } } diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 96cab73b..9a483138 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -33,27 +33,27 @@ class AltosScanResult { String callsign; int serial; int flight; - int channel; + double frequency; int telemetry; boolean interrupted = false; public String toString() { - return String.format("%-9.9s serial %-4d flight %-4d (channel %-2d %s)", - callsign, serial, flight, channel, Altos.telemetry_name(telemetry)); + return String.format("%-9.9s serial %-4d flight %-4d (frequency %7.3f %s)", + callsign, serial, flight, frequency, Altos.telemetry_name(telemetry)); } public String toShortString() { - return String.format("%s %d %d %d %d", - callsign, serial, flight, channel, telemetry); + return String.format("%s %d %d %7.3f %d", + callsign, serial, flight, frequency, telemetry); } public AltosScanResult(String in_callsign, int in_serial, - int in_flight, int in_channel, int in_telemetry) { + int in_flight, double in_frequency, int in_telemetry) { callsign = in_callsign; serial = in_serial; flight = in_flight; - channel = in_channel; + frequency = in_frequency; telemetry = in_telemetry; } @@ -61,7 +61,7 @@ class AltosScanResult { return (callsign.equals(other.callsign) && serial == other.serial && flight == other.flight && - channel == other.channel && + frequency == other.frequency && telemetry == other.telemetry); } } @@ -107,20 +107,25 @@ public class AltosScanUI { AltosUI owner; AltosDevice device; + AltosConfigData config_data; AltosTelemetryReader reader; private JList list; private JLabel scanning_label; + private JLabel frequency_label; + private JLabel telemetry_label; private JButton cancel_button; private JButton monitor_button; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); int telemetry; - int channel; + double frequency; final static int timeout = 1200; TelemetryHandler handler; Thread thread; + AltosFrequency[] frequencies; + int frequency_index; void scan_exception(Exception e) { if (e instanceof FileNotFoundException) { @@ -167,7 +172,7 @@ public class AltosScanUI final AltosScanResult result = new AltosScanResult(record.callsign, record.serial, record.flight, - channel, + frequency, telemetry); Runnable r = new Runnable() { public void run() { @@ -190,26 +195,30 @@ public class AltosScanUI } void set_label() { - scanning_label.setText(String.format("Scanning: channel %d %s", - channel, - Altos.telemetry_name(telemetry))); + frequency_label.setText(String.format("Frequency: %s", frequencies[frequency_index].toString())); + telemetry_label.setText(String.format("Telemetry: %s", Altos.telemetry_name(telemetry))); } - void next() { + void set_telemetry() { + reader.set_telemetry(telemetry); + } + + void set_frequency() throws InterruptedException, TimeoutException { + reader.set_frequency(frequencies[frequency_index].frequency); + } + + void next() throws InterruptedException, TimeoutException { reader.serial.set_monitor(false); - try { - Thread.sleep(100); - } catch (InterruptedException ie){ - } - ++channel; - if (channel > 9) { - channel = 0; + Thread.sleep(100); + ++frequency_index; + if (frequency_index >= frequencies.length) { + frequency_index = 0; ++telemetry; if (telemetry > Altos.ao_telemetry_max) telemetry = Altos.ao_telemetry_min; - reader.serial.set_telemetry(telemetry); + set_telemetry(); } - reader.serial.set_channel(channel); + set_frequency(); set_label(); reader.serial.set_monitor(true); } @@ -229,31 +238,37 @@ public class AltosScanUI dispose(); } - void tick_timer() { + void tick_timer() throws InterruptedException, TimeoutException { next(); } public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - if (cmd.equals("cancel")) - close(); - - if (cmd.equals("tick")) - tick_timer(); - - if (cmd.equals("monitor")) { - close(); - AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); - if (r != null) { - if (device != null) { - if (reader != null) { - reader.set_telemetry(r.telemetry); - reader.set_channel(r.channel); - owner.telemetry_window(device); + try { + if (cmd.equals("cancel")) + close(); + + if (cmd.equals("tick")) + tick_timer(); + + if (cmd.equals("monitor")) { + close(); + AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); + if (r != null) { + if (device != null) { + if (reader != null) { + reader.set_telemetry(r.telemetry); + reader.set_frequency(r.frequency); + owner.telemetry_window(device); + } } } } + } catch (TimeoutException te) { + close(); + } catch (InterruptedException ie) { + close(); } } @@ -278,8 +293,8 @@ public class AltosScanUI return false; try { reader = new AltosTelemetryReader(device); - reader.serial.set_channel(channel); - reader.serial.set_telemetry(telemetry); + set_frequency(); + set_telemetry(); try { Thread.sleep(100); } catch (InterruptedException ie) { @@ -306,6 +321,16 @@ public class AltosScanUI device.toShortString(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Timeout error", + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + "Interrupted exception", + JOptionPane.ERROR_MESSAGE); } if (reader != null) reader.close(false); @@ -316,7 +341,8 @@ public class AltosScanUI owner = in_owner; - channel = 0; + frequencies = AltosPreferences.common_frequencies(); + frequency_index = 0; telemetry = Altos.ao_telemetry_min; if (!open()) @@ -335,11 +361,13 @@ public class AltosScanUI pane.setLayout(new GridBagLayout()); scanning_label = new JLabel("Scanning:"); + frequency_label = new JLabel(""); + telemetry_label = new JLabel(""); set_label(); c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.CENTER; + c.anchor = GridBagConstraints.WEST; c.insets = i; c.weightx = 1; c.weighty = 1; @@ -347,9 +375,12 @@ public class AltosScanUI c.gridx = 0; c.gridy = 0; c.gridwidth = 2; - c.anchor = GridBagConstraints.CENTER; pane.add(scanning_label, c); + c.gridy = 1; + pane.add(frequency_label, c); + c.gridy = 2; + pane.add(telemetry_label, c); list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the @@ -417,7 +448,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 0; - c.gridy = 1; + c.gridy = 3; c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; @@ -434,7 +465,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 0; - c.gridy = 2; + c.gridy = 4; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; @@ -451,7 +482,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 1; - c.gridy = 2; + c.gridy = 4; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index f45aa18b..6c687f5f 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -54,11 +54,12 @@ public class AltosSerial implements Runnable { int line_count; boolean monitor_mode; int telemetry; - int channel; + double frequency; static boolean debug; boolean remote; LinkedList pending_output = new LinkedList(); Frame frame; + AltosConfigData config_data; static void set_debug(boolean new_debug) { debug = new_debug; @@ -154,7 +155,7 @@ public class AltosSerial implements Runnable { Object[] options = { "Cancel" }; JOptionPane pane = new JOptionPane(); - pane.setMessage(String.format("Connecting to %s", device.getPath())); + pane.setMessage(String.format("Connecting to %s, %7.3f MHz", device.toShortString(), frequency)); pane.setOptions(options); pane.setInitialValue(null); @@ -208,20 +209,13 @@ public class AltosSerial implements Runnable { } while (got_some); } - public String get_reply() throws InterruptedException { - if (SwingUtilities.isEventDispatchThread()) - System.out.printf("Uh-oh, reading serial device from swing thread\n"); - flush_output(); - AltosLine line = reply_queue.take(); - return line.line; - } - int in_reply; public String get_reply(int timeout) throws InterruptedException { boolean can_cancel = true; ++in_reply; + System.out.printf("get_reply %d\n", timeout); if (SwingUtilities.isEventDispatchThread()) { can_cancel = false; System.out.printf("Uh-oh, reading serial device from swing thread\n"); @@ -239,7 +233,6 @@ public class AltosSerial implements Runnable { --in_reply; return line.line; } - System.out.printf("no line remote %b can_cancel %b\n", remote, can_cancel); if (!remote || !can_cancel || check_timeout()) { --in_reply; return null; @@ -247,8 +240,13 @@ public class AltosSerial implements Runnable { } } + public String get_reply() throws InterruptedException { + return get_reply(5000); + } + public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { flush_output(); + System.out.printf("get_reply_no_dialog\n"); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) return line.line; @@ -267,6 +265,8 @@ public class AltosSerial implements Runnable { } public void close() { + if (remote) + stop_remote(); if (in_reply != 0) System.out.printf("Uh-oh. Closing active serial device\n"); @@ -328,19 +328,11 @@ public class AltosSerial implements Runnable { flush_output(); } - public void set_radio() { - telemetry = AltosPreferences.telemetry(device.getSerial()); - channel = AltosPreferences.channel(device.getSerial()); - set_channel(channel); - set_callsign(AltosPreferences.callsign()); - } - private int telemetry_len() { return Altos.telemetry_len(telemetry); } - public void set_channel(int in_channel) { - channel = in_channel; + private void set_channel(int channel) { if (altos != null) { if (monitor_mode) printf("m 0\nc r %d\nm %x\n", @@ -351,6 +343,33 @@ public class AltosSerial implements Runnable { } } + private void set_radio_setting(int setting) { + if (altos != null) { + if (monitor_mode) + printf("m 0\nc R %d\nc r 0\nm %x\n", + setting, telemetry_len()); + else + printf("c R %d\nc r 0\n", setting); + } + } + + public void set_radio_frequency(double frequency, + boolean has_setting, + int cal) { + if (has_setting) + set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); + else + set_channel(AltosConvert.radio_frequency_to_channel(frequency)); + } + + public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + config_data(); + set_radio_frequency(frequency, + config_data.radio_setting != 0, + config_data.radio_calibration); + } + public void set_telemetry(int in_telemetry) { telemetry = in_telemetry; if (altos != null) { @@ -378,10 +397,19 @@ public class AltosSerial implements Runnable { } } - public void start_remote() { + public AltosConfigData config_data() throws InterruptedException, TimeoutException { + if (config_data == null) + config_data = new AltosConfigData(this); + return config_data; + } + + public void start_remote() throws TimeoutException, InterruptedException { if (debug) System.out.printf("start remote\n"); - set_radio(); + if (frequency == 0.0) + frequency = AltosPreferences.frequency(device.getSerial()); + set_radio_frequency(frequency); + set_callsign(AltosPreferences.callsign()); printf("p\nE 0\n"); flush_input(); remote = true; diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 23524b2c..4512e761 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -27,6 +27,9 @@ class AltosTelemetryReader extends AltosFlightReader { AltosSerial serial; AltosLog log; AltosRecord previous; + AltosConfigData config_data; + double frequency; + int telemetry; LinkedBlockingQueue telem; @@ -49,18 +52,26 @@ class AltosTelemetryReader extends AltosFlightReader { serial.close(); } - void set_channel(int channel) { - serial.set_channel(channel); - AltosPreferences.set_channel(device.getSerial(), channel); + public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + serial.set_radio_frequency(frequency); } - void set_telemetry(int telemetry) { + void save_frequency() { + AltosPreferences.set_frequency(device.getSerial(), frequency); + } + + void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; serial.set_telemetry(telemetry); + } + + void save_telemetry() { AltosPreferences.set_telemetry(device.getSerial(), telemetry); } public AltosTelemetryReader (AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, IOException { + throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { device = in_device; serial = new AltosSerial(device); log = new AltosLog(serial); @@ -68,7 +79,11 @@ class AltosTelemetryReader extends AltosFlightReader { previous = null; telem = new LinkedBlockingQueue(); - serial.set_radio(); + frequency = AltosPreferences.frequency(device.getSerial()); + set_frequency(frequency); + telemetry = AltosPreferences.telemetry(device.getSerial()); + set_telemetry(telemetry); + serial.set_callsign(AltosPreferences.callsign()); serial.add_monitor(telem); } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 033f233c..885e60cd 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -26,7 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.*; import libaltosJNI.*; @@ -67,6 +67,16 @@ public class AltosUI extends JFrame { device.toShortString(), "Unkonwn I/O error", JOptionPane.ERROR_MESSAGE); + } catch (TimeoutException te) { + JOptionPane.showMessageDialog(this, + device.toShortString(), + "Timeout error", + JOptionPane.ERROR_MESSAGE); + } catch (InterruptedException ie) { + JOptionPane.showMessageDialog(this, + device.toShortString(), + "Interrupted exception", + JOptionPane.ERROR_MESSAGE); } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index d6fd0e6d..4bac6df1 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -52,6 +52,7 @@ altosui_JAVA = \ AltosFlightStatus.java \ AltosFlightUI.java \ AltosFrequency.java \ + AltosFreqList.java \ AltosGPS.java \ AltosGPSSat.java \ AltosGreatCircle.java \ -- cgit v1.2.3 From 84ba927f503f81543dec286c4881be30bb5e60c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 02:05:28 -0700 Subject: Set version to 0.9.5.0 Make the frequency-based systems distinct Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 72289226..eff1ea20 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.5) +AC_INIT([altos], 0.9.5.0) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From a65daf94e8fe3e22f770ef76d9104c3dd11d0330 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:25:30 -0700 Subject: altosui: altimeter is not spelled altimter Signed-off-by: Keith Packard --- altosui/AltosUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 885e60cd..fefe74e8 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -147,7 +147,7 @@ public class AltosUI extends JFrame { ExportData(); } }); - b = addButton(0, 1, "Configure Altimter"); + b = addButton(0, 1, "Configure Altimeter"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureTeleMetrum(); -- cgit v1.2.3 From a315b200cd0da1a964f5395cd59660be1b49672b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:31:48 -0700 Subject: altosui: Pull out BlueTooth support This leaves the code in place, but commented out so that it isn't used until we've got a bluetooth device ready for use. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosConfigureUI.java | 32 ++++++++++++++++++-------------- altosui/AltosDeviceDialog.java | 38 +++++++++++++++++++++++--------------- altosui/Makefile.am | 10 ++++++---- altosui/libaltos/cjnitest.c | 2 ++ altosui/libaltos/libaltos.c | 2 ++ altosui/libaltos/libaltos.h | 6 ++++++ 7 files changed, 58 insertions(+), 34 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 1acce949..b257ad7b 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -408,5 +408,5 @@ public class Altos { public final static String bt_product_telebt = bt_product_telebt(); - public static AltosBTKnown bt_known = new AltosBTKnown(); +// public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index a8a70ffd..abb54c74 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -49,7 +49,8 @@ public class AltosConfigureUI JRadioButton serial_debug; - JButton manage_bluetooth; +// BLUETOOTH +// JButton manage_bluetooth; JButton manage_frequencies; /* DocumentListener interface methods */ @@ -202,18 +203,19 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(serial_debug, c); - manage_bluetooth = new JButton("Manage Bluetooth"); - manage_bluetooth.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - AltosBTManage.show(owner, Altos.bt_known); - } - }); - c.gridx = 0; - c.gridy = 6; - c.gridwidth = 2; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - pane.add(manage_bluetooth, c); +// BLUETOOTH +// manage_bluetooth = new JButton("Manage Bluetooth"); +// manage_bluetooth.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// AltosBTManage.show(owner, Altos.bt_known); +// } +// }); +// c.gridx = 0; +// c.gridy = 6; +// c.gridwidth = 2; +// c.fill = GridBagConstraints.NONE; +// c.anchor = GridBagConstraints.WEST; +// pane.add(manage_bluetooth, c); manage_frequencies = new JButton("Manage Frequencies"); manage_frequencies.addActionListener(new ActionListener() { @@ -221,7 +223,9 @@ public class AltosConfigureUI AltosConfigFreqUI.show(owner); } }); - c.gridx = 2; +// BLUETOOTH +// c.gridx = 2; + c.gridx = 1; c.gridy = 6; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index e17504e2..fa9587bc 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -30,7 +30,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private JList list; private JButton cancel_button; private JButton select_button; - private JButton manage_bluetooth_button; +// BLUETOOTH +// private JButton manage_bluetooth_button; private Frame frame; private int product; @@ -40,14 +41,18 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private AltosDevice[] devices() { java.util.List usb_devices = AltosUSBDevice.list(product); - java.util.List bt_devices = Altos.bt_known.list(product); - AltosDevice[] devices = new AltosDevice[usb_devices.size() + bt_devices.size()]; + int num_devices = usb_devices.size(); +// BLUETOOTH +// java.util.List bt_devices = Altos.bt_known.list(product); +// num_devices += bt_devices.size(); + AltosDevice[] devices = new AltosDevice[num_devices]; for (int i = 0; i < usb_devices.size(); i++) devices[i] = usb_devices.get(i); - int off = usb_devices.size(); - for (int j = 0; j < bt_devices.size(); j++) - devices[off + j] = bt_devices.get(j); +// BLUETOOTH +// int off = usb_devices.size(); +// for (int j = 0; j < bt_devices.size(); j++) +// devices[off + j] = bt_devices.get(j); return devices; } @@ -70,9 +75,10 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); - manage_bluetooth_button = new JButton("Manage Bluetooth"); - manage_bluetooth_button.setActionCommand("manage"); - manage_bluetooth_button.addActionListener(this); +// BLUETOOTH +// manage_bluetooth_button = new JButton("Manage Bluetooth"); +// manage_bluetooth_button.setActionCommand("manage"); +// manage_bluetooth_button.addActionListener(this); select_button = new JButton("Select"); select_button.setActionCommand("select"); @@ -146,7 +152,8 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - buttonPane.add(manage_bluetooth_button); +// BLUETOOTH +// buttonPane.add(manage_bluetooth_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(select_button); @@ -166,11 +173,12 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); - if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, Altos.bt_known); - update_devices(); - return; - } +// BLUETOOTH +// if ("manage".equals(e.getActionCommand())) { +// AltosBTManage.show(frame, Altos.bt_known); +// update_devices(); +// return; +// } setVisible(false); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4bac6df1..713a02f4 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -10,6 +10,12 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:libaltos:$(FREETTS)/*:/ bin_SCRIPTS=altosui +altosui_BT = \ + AltosBTDevice.java \ + AltosBTDeviceIterator.java \ + AltosBTManage.java \ + AltosBTKnown.java + altosui_JAVA = \ GrabNDrag.java \ AltosAscent.java \ @@ -28,10 +34,6 @@ altosui_JAVA = \ AltosDeviceDialog.java \ AltosDevice.java \ AltosUSBDevice.java \ - AltosBTDevice.java \ - AltosBTDeviceIterator.java \ - AltosBTManage.java \ - AltosBTKnown.java \ AltosDisplayThread.java \ AltosEepromChunk.java \ AltosEepromDelete.java \ diff --git a/altosui/libaltos/cjnitest.c b/altosui/libaltos/cjnitest.c index 88e40d73..f0fe78f7 100644 --- a/altosui/libaltos/cjnitest.c +++ b/altosui/libaltos/cjnitest.c @@ -41,6 +41,7 @@ main () altos_close(file); } altos_list_finish(list); +#if HAS_BLUETOOTH bt_list = altos_bt_list_start(8); while (altos_bt_list_next(bt_list, &bt_device)) { printf ("%s %s\n", bt_device.name, bt_device.addr); @@ -64,6 +65,7 @@ main () } } altos_bt_list_finish(bt_list); +#endif altos_fini(); return 0; } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 5e507cdf..b00a7704 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -582,6 +582,7 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } +#if HAS_BLUETOOTH struct altos_bt_list { inquiry_info *ii; int sock; @@ -713,6 +714,7 @@ no_sock: no_file: return NULL; } +#endif /* HAS_BLUETOOTH */ #endif diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index f710919c..dd091e51 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -34,6 +34,8 @@ # define PUBLIC #endif +#define HAS_BLUETOOTH 0 + #define USB_VENDOR_FSF 0xfffe #define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF #define USB_PRODUCT_ALTUSMETRUM 0x000a @@ -109,6 +111,8 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); +#if HAS_BLUETOOTH + PUBLIC struct altos_bt_list * altos_bt_list_start(int inquiry_time); @@ -124,4 +128,6 @@ altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device); PUBLIC struct altos_file * altos_bt_open(struct altos_bt_device *device); +#endif + #endif /* _LIBALTOS_H_ */ -- cgit v1.2.3 From 40544dbfe09c64f7764a5f0686415805611fab25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 17:46:04 -0700 Subject: altos: minor type in comment about accel correction Kurt Roeckx found a typo in the equations describing how the accelerometer is corrected by the 5V reference measurement. Signed-off-by: Keith Packard --- src/ao_sample.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_sample.c b/src/ao_sample.c index 88ba58c5..b2b8e9f6 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -139,7 +139,7 @@ ao_sample(void) * * ao_sample_accel 32767 * = ------------ * ------------ - * 32737 ao_accel_ref + * 32767 ao_accel_ref * * Multiply through by 32767: * -- cgit v1.2.3 From dd383b86b9a13d7af2d6b07f4fb85ccc666ed898 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:45:36 -0700 Subject: altosui: Must set radio calibration before radio setting Setting the radio calibration erases any previous radio setting as the radio calibration change invalidates any previously computed radio setting for a specific frequency. Hence, the radio setting must be configured *after* the radio calibration value lest it be ignored. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 694ef4db..d5d7d56a 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -132,13 +132,12 @@ public class AltosConfig implements ActionListener { config_ui.set_version(version.get()); config_ui.set_main_deploy(main_deploy.get()); config_ui.set_apogee_delay(apogee_delay.get()); - config_ui.set_radio_frequency(frequency()); config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_radio_frequency(frequency()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); - config_ui.set_radio_setting(radio_setting.get()); config_ui.set_clean(); config_ui.make_visible(); } @@ -218,10 +217,12 @@ public class AltosConfig implements ActionListener { void save_data() { try { double frequency = frequency(); - boolean has_setting = radio_setting.get() != 0; + boolean has_setting = radio_setting.get() > 0; start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); + if (!remote) + serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.set_radio_frequency(frequency, has_setting, radio_calibration.get()); @@ -233,8 +234,6 @@ public class AltosConfig implements ActionListener { AltosPreferences.set_frequency(device.getSerial(), frequency); serial_line.start_remote(); } - if (!remote) - serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); @@ -321,18 +320,17 @@ public class AltosConfig implements ActionListener { } double frequency() { - int setting = radio_setting.get(); - - if (setting != 0) - return AltosConvert.radio_setting_to_frequency(setting, radio_calibration.get()); - else - return AltosConvert.radio_channel_to_frequency(radio_channel.get()); + System.out.printf("setting %d channel %d calibration %d\n", + radio_setting.get(), radio_channel.get(), radio_calibration.get()); + return AltosConvert.radio_to_frequency(radio_setting.get(), + radio_calibration.get(), + radio_channel.get()); } void set_frequency(double freq) { int setting = radio_setting.get(); - if (setting != 0) { + if (setting > 0) { radio_setting.set(AltosConvert.radio_frequency_to_setting(freq, radio_calibration.get())); radio_channel.set(0); -- cgit v1.2.3 From c8c01684fa011acf3bbe5c3ebbc84aa8e8457a5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:47:36 -0700 Subject: altosui: A few misc cleanups. Initialize radio_setting as it won't be set for older devices ever. Remove unused set_radio_frequency function from AltosConfigUI. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 1 + altosui/AltosConfigUI.java | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index aa7a90de..016033a3 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -85,6 +85,7 @@ public class AltosConfigData implements Iterable { public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { serial_line.printf("c s\nv\n"); lines = new LinkedList(); + radio_setting = 0; for (;;) { String line = serial_line.get_reply(); if (line == null) diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index c109924e..71664c91 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -563,9 +563,6 @@ public class AltosConfigUI callsign_value.setText(new_callsign); } - public void set_radio_setting(int new_radio_setting) { - } - public String callsign() { return callsign_value.getText(); } -- cgit v1.2.3 From 81bb6f42d8b859195ea5a35806c42d98ba82e8e1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:49:45 -0700 Subject: altosui: Have single radio_to_frequency function This takes all three radio params (setting, cal, channel) and computes the current frequency. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 2 -- altosui/AltosConvert.java | 22 ++++++++++------------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index d5d7d56a..7312ea6c 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -320,8 +320,6 @@ public class AltosConfig implements ActionListener { } double frequency() { - System.out.printf("setting %d channel %d calibration %d\n", - radio_setting.get(), radio_channel.get(), radio_calibration.get()); return AltosConvert.radio_to_frequency(radio_setting.get(), radio_calibration.get(), radio_channel.get()); diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java index 6a9b699c..c2ae9a50 100644 --- a/altosui/AltosConvert.java +++ b/altosui/AltosConvert.java @@ -190,30 +190,24 @@ public class AltosConvert { return ignite / 32767 * 15.0; } - static double - radio_setting_to_frequency(int setting, int cal) { + static double radio_to_frequency(int setting, int cal, int channel) { double f; + if (setting <= 0) + setting = cal; f = 434.550 * setting / cal; /* Round to nearest 50KHz */ f = Math.floor (20.0 * f + 0.5) / 20.0; - return f; + return f + channel * 0.100; } - static int - radio_frequency_to_setting(double frequency, int cal) { + static int radio_frequency_to_setting(double frequency, int cal) { double set = frequency / 434.550 * cal; return (int) Math.floor (set + 0.5); } - static double - radio_channel_to_frequency(int channel) { - return 434.550 + channel * 0.100; - } - - static int - radio_frequency_to_channel(double frequency) { + static int radio_frequency_to_channel(double frequency) { int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); if (channel < 0) @@ -222,4 +216,8 @@ public class AltosConvert { channel = 9; return channel; } + + static double radio_channel_to_frequency(int channel) { + return 434.550 + channel * 0.100; + } } -- cgit v1.2.3 From d4cc16e111229b02d1081e2693ace0b33f662498 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:51:16 -0700 Subject: altosui: Save frequency after setting it in AltosFlightUI Otherwise we'll just save the old frequency. Signed-off-by: Keith Packard --- altosui/AltosFlightUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 8c3f821e..c31e02bf 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -147,12 +147,12 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { frequencies.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double frequency = frequencies.frequency(); - reader.save_frequency(); try { reader.set_frequency(frequency); } catch (TimeoutException te) { } catch (InterruptedException ie) { } + reader.save_frequency(); } }); c.gridx = 0; -- cgit v1.2.3 From 364102d29ff4de0c252774f26417587fa88b7467 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:52:11 -0700 Subject: altosui: Show AltosFrequency in scan results Include frequency and description instead of just frequency. Signed-off-by: Keith Packard --- altosui/AltosScanUI.java | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 9a483138..b47405c8 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -30,17 +30,17 @@ import java.util.prefs.*; import java.util.concurrent.*; class AltosScanResult { - String callsign; - int serial; - int flight; - double frequency; - int telemetry; + String callsign; + int serial; + int flight; + AltosFrequency frequency; + int telemetry; boolean interrupted = false; public String toString() { - return String.format("%-9.9s serial %-4d flight %-4d (frequency %7.3f %s)", - callsign, serial, flight, frequency, Altos.telemetry_name(telemetry)); + return String.format("%-9.9s serial %-4d flight %-4d (%s %s)", + callsign, serial, flight, frequency.toShortString(), Altos.telemetry_name(telemetry)); } public String toShortString() { @@ -49,7 +49,7 @@ class AltosScanResult { } public AltosScanResult(String in_callsign, int in_serial, - int in_flight, double in_frequency, int in_telemetry) { + int in_flight, AltosFrequency in_frequency, int in_telemetry) { callsign = in_callsign; serial = in_serial; flight = in_flight; @@ -61,7 +61,7 @@ class AltosScanResult { return (callsign.equals(other.callsign) && serial == other.serial && flight == other.flight && - frequency == other.frequency && + frequency.frequency == other.frequency.frequency && telemetry == other.telemetry); } } @@ -119,7 +119,6 @@ public class AltosScanUI AltosScanResults results = new AltosScanResults(); int telemetry; - double frequency; final static int timeout = 1200; TelemetryHandler handler; @@ -172,7 +171,7 @@ public class AltosScanUI final AltosScanResult result = new AltosScanResult(record.callsign, record.serial, record.flight, - frequency, + frequencies[frequency_index], telemetry); Runnable r = new Runnable() { public void run() { @@ -259,7 +258,8 @@ public class AltosScanUI if (device != null) { if (reader != null) { reader.set_telemetry(r.telemetry); - reader.set_frequency(r.frequency); + reader.set_frequency(r.frequency.frequency); + reader.save_frequency(); owner.telemetry_window(device); } } -- cgit v1.2.3 From 97cf285d041062ae473c2823438b81c8fffe7f67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:53:03 -0700 Subject: altosui: Remove debugging printfs from AltosSerial Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 6c687f5f..c0eeb920 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -215,7 +215,6 @@ public class AltosSerial implements Runnable { boolean can_cancel = true; ++in_reply; - System.out.printf("get_reply %d\n", timeout); if (SwingUtilities.isEventDispatchThread()) { can_cancel = false; System.out.printf("Uh-oh, reading serial device from swing thread\n"); @@ -246,7 +245,6 @@ public class AltosSerial implements Runnable { public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { flush_output(); - System.out.printf("get_reply_no_dialog\n"); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) return line.line; -- cgit v1.2.3 From 13eacb49de4312509c3a729a31dcda4d601f8a8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:53:27 -0700 Subject: altosui: Flush radio setting to serial device When changing frequencies, make sure the device hears about it. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index c0eeb920..5d4510b4 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -348,6 +348,7 @@ public class AltosSerial implements Runnable { setting, telemetry_len()); else printf("c R %d\nc r 0\n", setting); + flush_output(); } } -- cgit v1.2.3 From 2662c577a895c96fce7b2bf815b9e752d2dfbde6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 18:53:59 -0700 Subject: altosui: Remove unused AltosConfigData from AltosTelemetryReader Now that AltosSerial manages this data, it's not needed here. Signed-off-by: Keith Packard --- altosui/AltosTelemetryReader.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 4512e761..6abe95d8 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -27,7 +27,6 @@ class AltosTelemetryReader extends AltosFlightReader { AltosSerial serial; AltosLog log; AltosRecord previous; - AltosConfigData config_data; double frequency; int telemetry; -- cgit v1.2.3 From 7146311d9df541e075b4450cf9656a9aa7ffdd93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 20:38:14 -0700 Subject: altosui: Reading serial from swing thread only bad if remote Make the warning on this condition based on whether the link is remote. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 5d4510b4..5e496d7f 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -217,7 +217,8 @@ public class AltosSerial implements Runnable { if (SwingUtilities.isEventDispatchThread()) { can_cancel = false; - System.out.printf("Uh-oh, reading serial device from swing thread\n"); + if (remote) + System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); } flush_output(); if (remote && can_cancel) { -- cgit v1.2.3 From cbf54a826d12c49b1b1996be247869d5ff4e2236 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 20:38:44 -0700 Subject: altosui: Make set of telemetries to use while scanning configurable with a preference to remember across application runs. Signed-off-by: Keith Packard --- altosui/AltosPreferences.java | 20 ++++++++++++++++++ altosui/AltosScanUI.java | 48 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 8609f94e..de926b38 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -52,6 +52,9 @@ class AltosPreferences { /* serial debug preference name */ final static String serialDebugPreference = "SERIAL-DEBUG"; + /* scanning telemetry preferences name */ + final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -82,6 +85,9 @@ class AltosPreferences { /* Serial debug */ static boolean serial_debug; + /* Scanning telemetry */ + static int scanning_telemetry; + /* List of frequencies */ final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; static AltosFrequency[] common_frequencies; @@ -156,6 +162,8 @@ class AltosPreferences { callsign = preferences.get(callsignPreference,"N0CALL"); + scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << Altos.ao_telemetry_standard)); + String firmwaredir_string = preferences.get(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); @@ -279,6 +287,18 @@ class AltosPreferences { return telemetry; } + public static void set_scanning_telemetry(int new_scanning_telemetry) { + scanning_telemetry = new_scanning_telemetry; + synchronized (preferences) { + preferences.putInt(scanningTelemetryPreference, scanning_telemetry); + flush_preferences(); + } + } + + public static int scanning_telemetry() { + return scanning_telemetry; + } + public static void set_voice(boolean new_voice) { voice = new_voice; synchronized (preferences) { diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index b47405c8..dd6672aa 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -115,6 +115,7 @@ public class AltosScanUI private JLabel telemetry_label; private JButton cancel_button; private JButton monitor_button; + private JCheckBox[] telemetry_boxes; javax.swing.Timer timer; AltosScanResults results = new AltosScanResults(); @@ -210,11 +211,15 @@ public class AltosScanUI reader.serial.set_monitor(false); Thread.sleep(100); ++frequency_index; - if (frequency_index >= frequencies.length) { + if (frequency_index >= frequencies.length || + !telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected()) + { frequency_index = 0; - ++telemetry; - if (telemetry > Altos.ao_telemetry_max) - telemetry = Altos.ao_telemetry_min; + do { + ++telemetry; + if (telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_min; + } while (!telemetry_boxes[telemetry - Altos.ao_telemetry_min].isSelected()); set_telemetry(); } set_frequency(); @@ -251,6 +256,21 @@ public class AltosScanUI if (cmd.equals("tick")) tick_timer(); + if (cmd.equals("telemetry")) { + int k; + int scanning_telemetry = 0; + for (k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) { + int j = k - Altos.ao_telemetry_min; + if (telemetry_boxes[j].isSelected()) + scanning_telemetry |= (1 << k); + } + if (scanning_telemetry == 0) { + scanning_telemetry |= (1 << Altos.ao_telemetry_standard); + telemetry_boxes[Altos.ao_telemetry_standard - Altos.ao_telemetry_min].setSelected(true); + } + AltosPreferences.set_scanning_telemetry(scanning_telemetry); + } + if (cmd.equals("monitor")) { close(); AltosScanResult r = (AltosScanResult) (list.getSelectedValue()); @@ -382,6 +402,20 @@ public class AltosScanUI c.gridy = 2; pane.add(telemetry_label, c); + int scanning_telemetry = AltosPreferences.scanning_telemetry(); + telemetry_boxes = new JCheckBox[Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1]; + for (int k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) { + int j = k - Altos.ao_telemetry_min; + telemetry_boxes[j] = new JCheckBox(Altos.ao_telemetry_name[k]); + c.gridy = 3 + j; + pane.add(telemetry_boxes[j], c); + telemetry_boxes[j].setActionCommand("telemetry"); + telemetry_boxes[j].addActionListener(this); + telemetry_boxes[j].setSelected((scanning_telemetry & (1 << k)) != 0); + } + + int y_offset = 3 + (Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1); + list = new JList(results) { //Subclass JList to workaround bug 4832765, which can cause the //scroll pane to not let the user easily scroll up to the beginning @@ -448,7 +482,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 0; - c.gridy = 3; + c.gridy = y_offset; c.gridwidth = 2; c.anchor = GridBagConstraints.CENTER; @@ -465,7 +499,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 0; - c.gridy = 4; + c.gridy = y_offset + 1; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; @@ -482,7 +516,7 @@ public class AltosScanUI c.weighty = 1; c.gridx = 1; - c.gridy = 4; + c.gridy = y_offset + 1; c.gridwidth = 1; c.anchor = GridBagConstraints.CENTER; -- cgit v1.2.3 From f3985ef8bc69bcec13ce155567a8ed7c5c6051cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 20:41:34 -0700 Subject: altosui: Add close button to 'fire' dialog Easier to hit than the tiny close box in the frame. Signed-off-by: Keith Packard --- altosui/AltosIgniteUI.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 42120b92..806b87b9 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -43,6 +43,7 @@ public class AltosIgniteUI JToggleButton arm; JButton fire; javax.swing.Timer timer; + JButton close; int apogee_status; int main_status; @@ -402,6 +403,16 @@ public class AltosIgniteUI fire.addActionListener(this); fire.setActionCommand("fire"); + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + close = new JButton ("Close"); + pane.add(close, c); + close.addActionListener(this); + close.setActionCommand("close"); + + pack(); setLocationRelativeTo(owner); -- cgit v1.2.3 From 81ad44d4b6d9ad2f6b91d0906e8543da82da424f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 14:26:43 -0700 Subject: altos: Switch telemini from v0.1 to v1.0 TeleMini production boards are firmware compatible with the v0.1 design, so instead of creating another product, just rename the existing one. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_adc.c | 2 +- src/ao_pins.h | 2 +- src/ao_telemetry.c | 2 +- src/telemini-v0.1/.gitignore | 2 -- src/telemini-v0.1/.sdcdbrc | 1 - src/telemini-v0.1/Makefile | 1 - src/telemini-v0.1/Makefile.defs | 9 --------- src/telemini-v1.0/.gitignore | 2 ++ src/telemini-v1.0/.sdcdbrc | 1 + src/telemini-v1.0/Makefile | 1 + src/telemini-v1.0/Makefile.defs | 9 +++++++++ 12 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 src/telemini-v0.1/.gitignore delete mode 100644 src/telemini-v0.1/.sdcdbrc delete mode 100644 src/telemini-v0.1/Makefile delete mode 100644 src/telemini-v0.1/Makefile.defs create mode 100644 src/telemini-v1.0/.gitignore create mode 100644 src/telemini-v1.0/.sdcdbrc create mode 100644 src/telemini-v1.0/Makefile create mode 100644 src/telemini-v1.0/Makefile.defs diff --git a/src/Makefile b/src/Makefile index 3eec3980..018f0c5c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ include Version SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ - telemini-v0.1 telenano-v0.1 \ + telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/ao_adc.c b/src/ao_adc.c index cbeb6a24..786dfd11 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -84,7 +84,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); -#ifdef TELEMINI_V_0_1 +#ifdef TELEMINI_V_1_0 switch (sequence) { case 0: /* pressure */ diff --git a/src/ao_pins.h b/src/ao_pins.h index 4a03ca50..bc07ad54 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -97,7 +97,7 @@ #define HAS_IGNITE 0 #endif -#if defined(TELEMINI_V_0_1) +#if defined(TELEMINI_V_1_0) #define HAS_FLIGHT 1 #define HAS_USB 0 #define HAS_BEEP 0 diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 172b6f17..52f818ed 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif -#if defined(TELEMINI_V_0_1) +#if defined(TELEMINI_V_1_0) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI #endif diff --git a/src/telemini-v0.1/.gitignore b/src/telemini-v0.1/.gitignore deleted file mode 100644 index 82868aac..00000000 --- a/src/telemini-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -telemini-* -ao_product.h diff --git a/src/telemini-v0.1/.sdcdbrc b/src/telemini-v0.1/.sdcdbrc deleted file mode 100644 index 710b4a2f..00000000 --- a/src/telemini-v0.1/.sdcdbrc +++ /dev/null @@ -1 +0,0 @@ ---directory=.. diff --git a/src/telemini-v0.1/Makefile b/src/telemini-v0.1/Makefile deleted file mode 100644 index d8867b19..00000000 --- a/src/telemini-v0.1/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.proto diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs deleted file mode 100644 index 94ac1268..00000000 --- a/src/telemini-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telemini-v0.1-$(VERSION).ihx - -SRC = \ - $(TMINI_BASE_SRC) - -PRODUCT=TeleMini-v0.1 -PRODUCT_DEF=-DTELEMINI_V_0_1 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telemini-v1.0/.gitignore b/src/telemini-v1.0/.gitignore new file mode 100644 index 00000000..82868aac --- /dev/null +++ b/src/telemini-v1.0/.gitignore @@ -0,0 +1,2 @@ +telemini-* +ao_product.h diff --git a/src/telemini-v1.0/.sdcdbrc b/src/telemini-v1.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemini-v1.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemini-v1.0/Makefile b/src/telemini-v1.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemini-v1.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs new file mode 100644 index 00000000..0e91f2fc --- /dev/null +++ b/src/telemini-v1.0/Makefile.defs @@ -0,0 +1,9 @@ +PROG = telemini-v1.0-$(VERSION).ihx + +SRC = \ + $(TMINI_BASE_SRC) + +PRODUCT=TeleMini-v1.0 +PRODUCT_DEF=-DTELEMINI_V_1_0 +IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From 12bfa6cc42e3689f09abae2bd2584cbacf2aa2e0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 18:26:07 -0700 Subject: altosui: Don't export product defs from libaltos As we add new products, that would change the ABI generated for java, invaliding old library versions sitting around for windows and mac. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 16 ++++++++++++++++ altosui/libaltos/libaltos.h | 19 +------------------ 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index b00a7704..00a75de9 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -20,6 +20,22 @@ #include #include +#define USB_VENDOR_FSF 0xfffe +#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF +#define USB_PRODUCT_ALTUSMETRUM 0x000a +#define USB_PRODUCT_TELEMETRUM 0x000b +#define USB_PRODUCT_TELEDONGLE 0x000c +#define USB_PRODUCT_TELETERRA 0x000d +#define USB_PRODUCT_TELEBT 0x000e +#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 + +#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ + (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ + (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) + +#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" + #define USE_POLL PUBLIC int diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index dd091e51..363a84fd 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -34,22 +34,6 @@ # define PUBLIC #endif -#define HAS_BLUETOOTH 0 - -#define USB_VENDOR_FSF 0xfffe -#define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF -#define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_TELEMETRUM 0x000b -#define USB_PRODUCT_TELEDONGLE 0x000c -#define USB_PRODUCT_TELETERRA 0x000d -#define USB_PRODUCT_TELEBT 0x000e -#define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 - -#define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ - (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ - (p) <= USB_PRODUCT_ALTUSMETRUM_MAX)) - struct altos_device { //%immutable; int vendor; @@ -60,8 +44,6 @@ struct altos_device { //%mutable; }; -#define BLUETOOTH_PRODUCT_TELEBT "TeleBT" - struct altos_bt_device { //%immutable; char name[256]; @@ -111,6 +93,7 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); +// #define HAS_BLUETOOTH 1 #if HAS_BLUETOOTH PUBLIC struct altos_bt_list * -- cgit v1.2.3 From a680ce61bdcffeacb7f0e4dcef71a03cb7cfe07d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 18:27:19 -0700 Subject: altosui: Ensure serial code tracks reply nesting correctly Trap any exceptional return conditions from 'get_reply' to make sure in_reply gets decremented. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 49 +++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 5e496d7f..b089c9c4 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -213,31 +213,38 @@ public class AltosSerial implements Runnable { public String get_reply(int timeout) throws InterruptedException { boolean can_cancel = true; - ++in_reply; + String reply = null; - if (SwingUtilities.isEventDispatchThread()) { - can_cancel = false; - if (remote) - System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); - } - flush_output(); - if (remote && can_cancel) { - timeout = 500; - } - abort = false; - timeout_started = false; - for (;;) { - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line != null) { - stop_timeout_dialog(); - --in_reply; - return line.line; + try { + ++in_reply; + + if (SwingUtilities.isEventDispatchThread()) { + can_cancel = false; + if (remote) + System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); } - if (!remote || !can_cancel || check_timeout()) { - --in_reply; - return null; + flush_output(); + if (remote && can_cancel) { + timeout = 500; } + abort = false; + timeout_started = false; + for (;;) { + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) { + stop_timeout_dialog(); + reply = line.line; + break; + } + if (!remote || !can_cancel || check_timeout()) { + reply = null; + break; + } + } + } finally { + --in_reply; } + return reply; } public String get_reply() throws InterruptedException { -- cgit v1.2.3 From 94d9a2c36fabdf24d6a0b985851e95e4eb181fd9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 18:28:19 -0700 Subject: altosui: Ship TeleMini v1.0 firmware with fat blobs Signed-off-by: Keith Packard --- altosui/Makefile.am | 5 ++++- altosui/altos-windows.nsi | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 713a02f4..a11e2c7f 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -160,7 +160,10 @@ FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1-$(VERSION).ihx FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) -FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD) +FIRMWARE_TELEMINI_1_0=$(top_srcdir)/src/telemini-v1.0-$(VERSION).ihx +FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) + +FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf ALTOS_DOC=$(top_srcdir)/doc/altos.pdf diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index a1238095..d92d1eb3 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -81,6 +81,7 @@ Section "TeleMetrum and TeleDongle Firmware" File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx" + File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx" File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" SectionEnd -- cgit v1.2.3 From 6ac604d11de44cd824f09e4b467264a2b74be7bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 13:35:26 -0700 Subject: Altosui: Add flight statistics tab to graph window Provide basic flight stats alongside the flight graph. Signed-off-by: Keith Packard --- altosui/Altos.java | 13 +++++ altosui/AltosFlightStats.java | 95 +++++++++++++++++++++++++++++++++ altosui/AltosFlightStatsTable.java | 104 +++++++++++++++++++++++++++++++++++++ altosui/AltosGraph.java | 1 + altosui/AltosGraphTime.java | 1 - altosui/AltosGraphUI.java | 36 ++++++++----- altosui/AltosState.java | 3 ++ altosui/Makefile.am | 2 + 8 files changed, 242 insertions(+), 13 deletions(-) create mode 100644 altosui/AltosFlightStats.java create mode 100644 altosui/AltosFlightStatsTable.java diff --git a/altosui/Altos.java b/altosui/Altos.java index b257ad7b..d90c4183 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -142,6 +142,19 @@ public class Altos { "invalid", }; + static String[] state_to_string_capital = { + "Startup", + "Idle", + "Pad", + "Boost", + "Fast", + "Coast", + "Drogue", + "Main", + "Landed", + "Invalid", + }; + static public int state(String state) { if (!map_initialized) initialize_map(); diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java new file mode 100644 index 00000000..e38142f0 --- /dev/null +++ b/altosui/AltosFlightStats.java @@ -0,0 +1,95 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +public class AltosFlightStats { + double max_height; + double max_speed; + double max_acceleration; + double[] state_speed = new double[Altos.ao_flight_invalid + 1]; + double[] state_baro_speed = new double[Altos.ao_flight_invalid + 1]; + double[] state_accel = new double[Altos.ao_flight_invalid + 1]; + int[] state_count = new int[Altos.ao_flight_invalid + 1]; + double[] state_start = new double[Altos.ao_flight_invalid + 1]; + double[] state_end = new double[Altos.ao_flight_invalid + 1]; + + public AltosFlightStats(AltosFlightReader reader) throws InterruptedException, IOException { + AltosState state = null; + AltosState new_state = null; + double boost_time = -1; + double start_time; + + for (;;) { + try { + AltosRecord record = reader.read(); + if (record == null) + break; + new_state = new AltosState(record, state); + if (state == null) { + start_time = new_state.time; + } + state = new_state; + if (0 <= state.state && state.state < Altos.ao_flight_invalid) { + if (boost_time == -1 && state.state >= Altos.ao_flight_boost) + boost_time = state.time; + state_accel[state.state] += state.acceleration; + state_speed[state.state] += state.speed; + state_baro_speed[state.state] += state.baro_speed; + state_count[state.state]++; + if (state_start[state.state] == 0.0) + state_start[state.state] = state.time; + if (state_end[state.state] < state.time) + state_end[state.state] = state.time; + max_height = state.max_height; + max_speed = state.max_speed; + max_acceleration = state.max_acceleration; + } + } catch (ParseException pp) { + System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); + } catch (AltosCRCException ce) { + + } + } + for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { + if (state_count[s] > 0) { + state_speed[s] /= state_count[s]; + state_baro_speed[s] /= state_count[s]; + state_accel[s] /= state_count[s]; + } + } + } + + public AltosFlightStats(AltosRecordIterable iterable, String filename) throws InterruptedException, IOException { + this(new AltosReplayReader(iterable.iterator(), filename)); + } + + public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { + this(iterable, ""); + } +} diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java new file mode 100644 index 00000000..8676d306 --- /dev/null +++ b/altosui/AltosFlightStatsTable.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +public class AltosFlightStatsTable extends JComponent { + GridBagLayout layout; + + class FlightStat { + JLabel label; + JTextField value; + + public FlightStat(GridBagLayout layout, int y, String label_text, String ... values) { + GridBagConstraints c = new GridBagConstraints(); + c.insets = new Insets(Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad, Altos.tab_elt_pad); + c.weighty = 1; + + label = new JLabel(label_text); + label.setFont(Altos.label_font); + label.setHorizontalAlignment(SwingConstants.LEFT); + c.gridx = 0; c.gridy = y; + c.anchor = GridBagConstraints.WEST; + c.fill = GridBagConstraints.VERTICAL; + c.weightx = 0; + layout.setConstraints(label, c); + add(label); + + for (int j = 0; j < values.length; j++) { + value = new JTextField(values[j]); + value.setFont(Altos.value_font); + value.setHorizontalAlignment(SwingConstants.RIGHT); + c.gridx = j+1; c.gridy = y; + c.anchor = GridBagConstraints.EAST; + c.fill = GridBagConstraints.BOTH; + c.weightx = 1; + layout.setConstraints(value, c); + add(value); + } + } + + } + + public AltosFlightStatsTable(AltosFlightStats stats) { + layout = new GridBagLayout(); + + setLayout(layout); + int y = 0; + new FlightStat(layout, y++, "Maximum height", + String.format("%5.0f m", stats.max_height), + String.format("%5.0f ft", stats.max_height * 100 / 2.54 / 12)); + new FlightStat(layout, y++, "Maximum speed", + String.format("%5.0f m/s", stats.max_speed), + String.format("%5.0f ft/s", stats.max_speed * 100 / 2.54 / 12), + String.format("Mach %5.3f", stats.max_speed / 343.0)); + new FlightStat(layout, y++, "Maximum acceleration", + String.format("%5.0f m/s²", stats.max_acceleration), + String.format("%5.0f ft/s²", stats.max_acceleration * 100 / 2.54 /12), + String.format("%5.2f G", stats.max_acceleration / 9.80665)); + new FlightStat(layout, y++, "Average boost acceleration", + String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), + String.format("%5.0f ft/s²", stats.state_accel[Altos.ao_flight_boost] * 100 / 2.54 /12), + String.format("%5.2f G", stats.state_accel[Altos.ao_flight_boost] / 9.80665)); + new FlightStat(layout, y++, "Drogue descent rate", + String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_drogue]), + String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_drogue] * 100 / 2.54 / 12)); + new FlightStat(layout, y++, "Main descent rate", + String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_main]), + String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_main] * 100 / 2.54 / 12)); + for (int s = Altos.ao_flight_boost; s <= Altos.ao_flight_main; s++) { + new FlightStat(layout, y++, String.format("%s time", Altos.state_to_string_capital[s]), + String.format("%6.2f s", stats.state_end[s] - stats.state_start[s])); + } + new FlightStat(layout, y++, "Flight Time", + String.format("%6.2f s", stats.state_end[Altos.ao_flight_main] - + stats.state_start[Altos.ao_flight_boost])); + + } + +} \ No newline at end of file diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java index 58c27979..fbcefd61 100644 --- a/altosui/AltosGraph.java +++ b/altosui/AltosGraph.java @@ -13,6 +13,7 @@ abstract class AltosGraph { public String filename; public abstract void addData(AltosDataPoint d); public abstract JFreeChart createChart(); + public String title; public void toPNG() throws java.io.IOException { toPNG(300, 500); } public void toPNG(int width, int height) throws java.io.IOException diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java index a5451280..ada6ef13 100644 --- a/altosui/AltosGraphTime.java +++ b/altosui/AltosGraphTime.java @@ -132,7 +132,6 @@ class AltosGraphTime extends AltosGraph { private Integer serial = null; private Integer flight = null; - private String title; private ArrayList elements; private HashMap axes; private HashMap datasets; diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index a27aa37f..16b0fd48 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -7,8 +7,11 @@ package altosui; import java.io.*; import java.util.ArrayList; -import javax.swing.JFrame; -import java.awt.Color; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; @@ -19,6 +22,8 @@ import org.jfree.ui.RefineryUtilities; public class AltosGraphUI extends JFrame { + JTabbedPane pane; + static final private Color red = new Color(194,31,31); static final private Color green = new Color(31,194,31); static final private Color blue = new Color(31,31,194); @@ -173,7 +178,7 @@ public class AltosGraphUI extends JFrame } } - public AltosGraphUI(AltosRecordIterable records) { + public AltosGraphUI(AltosRecordIterable records) throws InterruptedException, IOException { super("Altos Graph"); AltosDataPointReader reader = new AltosDataPointReader (records); @@ -181,25 +186,32 @@ public class AltosGraphUI extends JFrame return; if (reader.has_accel) - init(reader, 0); + init(reader, records, 0); else - init(reader, 1); + init(reader, records, 1); } - public AltosGraphUI(AltosDataPointReader data, int which) - { - super("Altos Graph"); - init(data, which); - } +// public AltosGraphUI(AltosDataPointReader data, int which) + // { +// super("Altos Graph"); +// init(data, which); +// } + + private void init(AltosDataPointReader data, AltosRecordIterable records, int which) throws InterruptedException, IOException { + pane = new JTabbedPane(); - private void init(AltosDataPointReader data, int which) { AltosGraph graph = createGraph(data, which); JFreeChart chart = graph.createChart(); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setMouseWheelEnabled(true); chartPanel.setPreferredSize(new java.awt.Dimension(800, 500)); - setContentPane(chartPanel); + pane.add(graph.title, chartPanel); + + AltosFlightStatsTable stats = new AltosFlightStatsTable(new AltosFlightStats(records)); + pane.add("Flight Statistics", stats); + + setContentPane (pane); pack(); diff --git a/altosui/AltosState.java b/altosui/AltosState.java index d374aed8..1ac816d5 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -28,6 +28,7 @@ public class AltosState { long report_time; + double time; double time_change; int tick; @@ -130,6 +131,8 @@ public class AltosState { time_change = 0; } + time = tick / 100.0; + if (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle) { /* Track consecutive 'good' gps reports, waiting for 10 of them */ diff --git a/altosui/Makefile.am b/altosui/Makefile.am index a11e2c7f..3bc68cdb 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -51,6 +51,8 @@ altosui_JAVA = \ AltosFlightDisplay.java \ AltosFlightInfoTableModel.java \ AltosFlightReader.java \ + AltosFlightStats.java \ + AltosFlightStatsTable.java \ AltosFlightStatus.java \ AltosFlightUI.java \ AltosFrequency.java \ -- cgit v1.2.3 From 9e1487b1a5db0afd1d23c86d82c60b1c1a62aab0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 14:08:21 -0700 Subject: altosui: Add a 'Graph Flight' button to the 'landed' tab This lets you see the results of a flight as soon as the rocket lands using the telemetry data. Signed-off-by: Keith Packard --- altosui/AltosFlightReader.java | 2 ++ altosui/AltosFlightStats.java | 6 ++-- altosui/AltosFlightUI.java | 2 +- altosui/AltosLanded.java | 59 +++++++++++++++++++++++++++++++++++++-- altosui/AltosLog.java | 6 ++++ altosui/AltosReplayReader.java | 8 ++++-- altosui/AltosTelemetryReader.java | 4 +++ altosui/AltosUI.java | 10 +++++-- 8 files changed, 86 insertions(+), 11 deletions(-) diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java index 3a171444..47df375d 100644 --- a/altosui/AltosFlightReader.java +++ b/altosui/AltosFlightReader.java @@ -42,4 +42,6 @@ public class AltosFlightReader { void save_telemetry() { } void update(AltosState state) throws InterruptedException { } + + File backing_file() { return null; } } diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index e38142f0..e644b0ba 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -85,11 +85,11 @@ public class AltosFlightStats { } } - public AltosFlightStats(AltosRecordIterable iterable, String filename) throws InterruptedException, IOException { - this(new AltosReplayReader(iterable.iterator(), filename)); + public AltosFlightStats(AltosRecordIterable iterable, File file) throws InterruptedException, IOException { + this(new AltosReplayReader(iterable.iterator(), file)); } public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { - this(iterable, ""); + this(iterable, new File("")); } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index c31e02bf..f0626e7c 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -210,7 +210,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { descent = new AltosDescent(); pane.add("Descent", descent); - landed = new AltosLanded(); + landed = new AltosLanded(reader); pane.add("Landed", landed); flightInfo = new AltosInfoTable(); diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index d5c8e434..47aca29d 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosLanded extends JComponent implements AltosFlightDisplay { +public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { GridBagLayout layout; Font label_font; Font value_font; @@ -214,11 +214,51 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { height.show(state, crc_errors); speed.show(state, crc_errors); accel.show(state, crc_errors); + if (reader.backing_file() != null) + graph.setEnabled(true); } - public AltosLanded() { + JButton graph; + AltosFlightReader reader; + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("graph")) { + File file = reader.backing_file(); + if (file != null) { + String filename = file.getName(); + try { + AltosRecordIterable records = null; + if (filename.endsWith("eeprom")) { + FileInputStream in = new FileInputStream(file); + records = new AltosEepromIterable(in); + } else if (filename.endsWith("telem")) { + FileInputStream in = new FileInputStream(file); + records = new AltosTelemetryIterable(in); + } else { + throw new FileNotFoundException(); + } + try { + new AltosGraphUI(records); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + } catch (FileNotFoundException fe) { + JOptionPane.showMessageDialog(null, + filename, + "Cannot open file", + JOptionPane.ERROR_MESSAGE); + } + } + } + } + + public AltosLanded(AltosFlightReader in_reader) { layout = new GridBagLayout(); + reader = in_reader; + label_font = new Font("Dialog", Font.PLAIN, 22); value_font = new Font("Monospaced", Font.PLAIN, 22); setLayout(layout); @@ -231,5 +271,20 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { height = new Height(layout, 4); speed = new Speed(layout, 5); accel = new Accel(layout, 6); + + graph = new JButton ("Graph Flight"); + graph.setActionCommand("graph"); + graph.addActionListener(this); + graph.setEnabled(false); + + GridBagConstraints c = new GridBagConstraints(); + + c.gridx = 0; c.gridy = 7; + c.insets = new Insets(10, 10, 10, 10); + c.anchor = GridBagConstraints.WEST; + c.weightx = 0; + c.weighty = 0; + c.fill = GridBagConstraints.VERTICAL; + add(graph, c); } } diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java index 6157a656..a5f1830d 100644 --- a/altosui/AltosLog.java +++ b/altosui/AltosLog.java @@ -35,6 +35,7 @@ class AltosLog implements Runnable { int flight; FileWriter log_file; Thread log_thread; + AltosFile file; private void close_log_file() { if (log_file != null) { @@ -54,6 +55,10 @@ class AltosLog implements Runnable { } } + File file() { + return file; + } + boolean open (AltosRecord telem) throws IOException { AltosFile a = new AltosFile(telem); @@ -69,6 +74,7 @@ class AltosLog implements Runnable { } } log_file.flush(); + file = a; } return log_file != null; } diff --git a/altosui/AltosReplayReader.java b/altosui/AltosReplayReader.java index 4e5e1d93..eed56cff 100644 --- a/altosui/AltosReplayReader.java +++ b/altosui/AltosReplayReader.java @@ -34,6 +34,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosReplayReader extends AltosFlightReader { Iterator iterator; + File file; public AltosRecord read() { if (iterator.hasNext()) @@ -50,8 +51,11 @@ public class AltosReplayReader extends AltosFlightReader { Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); } - public AltosReplayReader(Iterator in_iterator, String in_name) { + public File backing_file() { return file; } + + public AltosReplayReader(Iterator in_iterator, File in_file) { iterator = in_iterator; - name = in_name; + file = in_file; + name = file.getName(); } } diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 6abe95d8..1f327a67 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -69,6 +69,10 @@ class AltosTelemetryReader extends AltosFlightReader { AltosPreferences.set_telemetry(device.getSerial(), telemetry); } + File backing_file() { + return log.file(); + } + public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { device = in_device; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index fefe74e8..62e612ed 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -276,7 +276,7 @@ public class AltosUI extends JFrame { AltosRecordIterable iterable = chooser.runDialog(); if (iterable != null) { AltosFlightReader reader = new AltosReplayReader(iterable.iterator(), - chooser.filename()); + chooser.file()); new AltosFlightUI(voice, reader); } } @@ -310,7 +310,11 @@ public class AltosUI extends JFrame { AltosRecordIterable record_reader = chooser.runDialog(); if (record_reader == null) return; - new AltosGraphUI(record_reader); + try { + new AltosGraphUI(record_reader); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } } private void ConfigureAltosUI() { @@ -427,7 +431,7 @@ public class AltosUI extends JFrame { } else { recs = new AltosTelemetryIterable(in); } - reader = new AltosReplayReader(recs.iterator(), filename); + reader = new AltosReplayReader(recs.iterator(), new File(filename)); AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); flight_ui.set_exit_on_close(); return; -- cgit v1.2.3 From 01b9352eb8ca0e4e2d023ce973c4e863cdcc0c51 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 14:34:39 -0700 Subject: altosui: Prune telemetry file graphs to just the flight Remove data earlier than 1 second before boost and data after landing. Signed-off-by: Keith Packard --- altosui/AltosDataPointReader.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index fa48013f..c3aabb0c 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -69,10 +69,14 @@ class AltosDataPointReader implements Iterable { throw new UnsupportedOperationException(); } public boolean hasNext() { + if (record != null && record.state == Altos.ao_flight_landed) + return false; return iter.hasNext(); } public AltosDataPoint next() { - read_next_record(); + do { + read_next_record(); + } while (record.time < -1.0 && hasNext()); return current_dp(); } }; -- cgit v1.2.3 From 4962bcf1ce15c21a946ea718bd676b901f0f2bd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 14:35:21 -0700 Subject: altosui: Plot reasonable data from Tm files Don't plot acceleration based on baro data. Display baro speed if accel speed isn't available. Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 5 ++++- altosui/AltosFlightStatsTable.java | 18 ++++++++++-------- altosui/AltosState.java | 4 ++++ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index e644b0ba..19471e9f 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -67,7 +67,10 @@ public class AltosFlightStats { if (state_end[state.state] < state.time) state_end[state.state] = state.time; max_height = state.max_height; - max_speed = state.max_speed; + if (state.max_speed != 0) + max_speed = state.max_speed; + else + max_speed = state.max_baro_speed; max_acceleration = state.max_acceleration; } } catch (ParseException pp) { diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java index 8676d306..e2c0dd46 100644 --- a/altosui/AltosFlightStatsTable.java +++ b/altosui/AltosFlightStatsTable.java @@ -77,14 +77,16 @@ public class AltosFlightStatsTable extends JComponent { String.format("%5.0f m/s", stats.max_speed), String.format("%5.0f ft/s", stats.max_speed * 100 / 2.54 / 12), String.format("Mach %5.3f", stats.max_speed / 343.0)); - new FlightStat(layout, y++, "Maximum acceleration", - String.format("%5.0f m/s²", stats.max_acceleration), - String.format("%5.0f ft/s²", stats.max_acceleration * 100 / 2.54 /12), - String.format("%5.2f G", stats.max_acceleration / 9.80665)); - new FlightStat(layout, y++, "Average boost acceleration", - String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), - String.format("%5.0f ft/s²", stats.state_accel[Altos.ao_flight_boost] * 100 / 2.54 /12), - String.format("%5.2f G", stats.state_accel[Altos.ao_flight_boost] / 9.80665)); + if (stats.max_acceleration != AltosRecord.MISSING) { + new FlightStat(layout, y++, "Maximum acceleration", + String.format("%5.0f m/s²", stats.max_acceleration), + String.format("%5.0f ft/s²", stats.max_acceleration * 100 / 2.54 /12), + String.format("%5.2f G", stats.max_acceleration / 9.80665)); + new FlightStat(layout, y++, "Average boost acceleration", + String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), + String.format("%5.0f ft/s²", stats.state_accel[Altos.ao_flight_boost] * 100 / 2.54 /12), + String.format("%5.2f G", stats.state_accel[Altos.ao_flight_boost] / 9.80665)); + } new FlightStat(layout, y++, "Drogue descent rate", String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_drogue]), String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_drogue] * 100 / 2.54 / 12)); diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 1ac816d5..378930bf 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -49,6 +49,7 @@ public class AltosState { double max_height; double max_acceleration; double max_speed; + double max_baro_speed; AltosGPS gps; @@ -105,6 +106,7 @@ public class AltosState { max_height = prev_state.max_height; max_acceleration = prev_state.max_acceleration; max_speed = prev_state.max_speed; + max_baro_speed = prev_state.max_baro_speed; /* make sure the clock is monotonic */ while (tick < prev_state.tick) @@ -171,6 +173,8 @@ public class AltosState { max_acceleration = acceleration; if (ascent && speed > max_speed) max_speed = speed; + if (ascent && baro_speed > max_baro_speed) + max_baro_speed = baro_speed; if (height > max_height) max_height = height; -- cgit v1.2.3 From 9f5623c8c32a38eaeb63fa74ab370025ac015d52 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 15:00:44 -0700 Subject: altosui: Move launch-sites.txt file to altusmetrum.org The official URL is now: http://www.altusmetrum.org/AltOS/launch-sites.txt Signed-off-by: Keith Packard --- altosui/Altos.java | 2 ++ altosui/AltosSiteMapPreload.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index d90c4183..73dc7468 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -80,6 +80,8 @@ public class Altos { "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" }; + static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt"; + static final int ao_telemetry_standard_len = 32; static final int ao_telemetry_0_9_len = 95; static final int ao_telemetry_0_8_len = 94; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 5d437e17..aa07bebc 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -204,7 +204,7 @@ class AltosSites extends Thread { sites = new LinkedList(); preload = in_preload; try { - url = new URL("http://gag.com/~keithp/launch-sites.txt"); + url = new URL(Altos.launch_sites_url); } catch (java.net.MalformedURLException e) { notify_complete(); } -- cgit v1.2.3 From be65308182363ca87db69db530297933324f3806 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 16:01:25 -0700 Subject: Bump version to 0.9.6.0 Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index eff1ea20..2bd3120a 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.5.0) +AC_INIT([altos], 0.9.6.0) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 967c9d5ee691f87bf0d1e49ba055eb366e513e6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 17:43:58 -0700 Subject: doc: Update altusmetrum.xsl for v1.0 software and TeleMini Add TeleMini references and sections as appropriate, update AltosUI docs to describe new bits. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 835 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 549 insertions(+), 286 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 25f24593..0ee9d163 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -3,7 +3,7 @@ "/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd"> The Altus Metrum System - An Owner's Manual for TeleMetrum and TeleDongle Devices + An Owner's Manual for TeleMetrum, TeleMini and TeleDongle Devices Bdale @@ -35,6 +35,15 @@ + + 1.0 + 10 August 2011 + + Updated for software version 1.0. Note that 1.0 represents a + telemetry format change, meaning both ends of a link (TeleMetrum/TeleMini and + TeleDongle) must be updated or communications will fail. + + 0.9 18 January 2011 @@ -44,8 +53,6 @@ TeleDongle) must be updated or communications will fail. - - 0.8 24 November 2010 @@ -92,14 +99,19 @@ NAR #88757, TRA #12200 future as you wish! - The focal point of our community is TeleMetrum, a dual deploy altimeter - with fully integrated GPS and radio telemetry as standard features, and - a "companion interface" that will support optional capabilities in the - future. + The first device created for our community is TeleMetrum, a dual + deploy altimeter with fully integrated GPS and radio telemetry + as standard features, and a "companion interface" that will + support optional capabilities in the future. + + + The newest device is TeleMini, a dual deploy altimeter with + radio telemetry and radio direction finding. This device is only + 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm airframe. - Complementing TeleMetrum is TeleDongle, a USB to RF interface for - communicating with TeleMetrum. Combined with your choice of antenna and + Complementing TeleMetrum and TeleMini is TeleDongle, a USB to RF interface for + communicating with the altimeters. Combined with your choice of antenna and notebook computer, TeleDongle and our associated user interface software form a complete ground station capable of logging and displaying in-flight telemetry, aiding rocket recovery, then processing and archiving flight @@ -115,13 +127,19 @@ NAR #88757, TRA #12200 Getting Started The first thing to do after you check the inventory of parts in your - "starter kit" is to charge the battery by plugging it into the + "starter kit" is to charge the battery. + + + The TeleMetrum battery can be charged by plugging it into the corresponding socket of the TeleMetrum and then using the USB A to mini B cable to plug the Telemetrum into your computer's USB socket. The TeleMetrum circuitry will charge the battery whenever it is plugged in, because the TeleMetrum's on-off switch does NOT control the - charging circuitry. When the GPS chip is initially searching for + charging circuitry. + + + When the GPS chip is initially searching for satellites, TeleMetrum will consume more current than it can pull from the usb port, so the battery must be attached in order to get satellite lock. Once GPS is locked, the current consumption goes back @@ -132,6 +150,12 @@ NAR #88757, TRA #12200 battery is nearly full and the charger goes to trickle charge. It can take several hours to fully recharge a deeply discharged battery. + + The TeleMini battery can be charged by disconnecting it from the + TeleMini board and plugging it into the battery charger board, + and connecting that via a USB cable to a laptop or other USB + power source + The other active device in the starter kit is the TeleDongle USB to RF interface. If you plug it in to your Mac or Linux computer it should @@ -144,7 +168,7 @@ NAR #88757, TRA #12200 Next you should obtain and install the AltOS utilities. These include the AltosUI ground station program, current firmware images for - TeleMetrum and TeleDongle, and a number of standalone utilities that + TeleMetrum, TeleMini and TeleDongle, and a number of standalone utilities that are rarely needed. Pre-built binary packages are available for Debian Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode and build instructions for some other Linux variants are also available. @@ -161,6 +185,15 @@ NAR #88757, TRA #12200 respective on-board firmware and data using other command line programs in the AltOS software suite. + + TeleMini can be communicated with through a TeleDongle device + over the radio link. When first booted, TeleMini listens for a + TeleDongle device and if it receives a packet, it goes into + 'idle' mode. Otherwise, it goes into 'pad' mode and waits to be + launched. The easiest way to get it talking is to start the + communication link on the TeleDongle and the power up the + TeleMini board. + To access the device's firmware for configuration you need a terminal program such as you would use to talk to a modem. The software @@ -179,7 +212,7 @@ NAR #88757, TRA #12200 second use will be outlined later. - Both TeleMetrum and TeleDongle share the concept of a two level + All of the Altus Metrum devices share the concept of a two level command set in their firmware. The first layer has several single letter commands. Once you are using 'cu' (or 'cutecom') sending (typing) a '?' @@ -189,10 +222,8 @@ NAR #88757, TRA #12200 instance typing 'c?' will give you this second level of commands (all of which require the letter 'c' to access). Please note that most configuration options - are stored only in DataFlash memory, and only TeleMetrum has this - memory to save the various values entered like the channel number - and your callsign when powered off. TeleDongle requires that you - set these each time you plug it in, which ao-view can help with. + are stored only in Flash memory; TeleDongle doesn't provide any storage + for these options and so they'll all be lost when you unplug it. Try setting these config ('c' or second level menu) values. A good @@ -206,38 +237,40 @@ NAR #88757, TRA #12200 terminal program by sending the escape-disconnect mentioned above. - Note that the 'reboot' command, which is very useful on TeleMetrum, + Note that the 'reboot' command, which is very useful on the altimeters, will likely just cause problems with the dongle. The *correct* way to reset the dongle is just to unplug and re-plug it. A fun thing to do at the launch site and something you can do while learning how to use these units is to play with the rf-link access - of the TeleMetrum from the TeleDongle. Be aware that you *must* create + between an altimeter and the TeleDongle. Be aware that you *must* create some physical separation between the devices, otherwise the link will not function due to signal overload in the receivers in each device. Now might be a good time to take a break and read the rest of this - manual, particularly about the two "modes" that the TeleMetrum - can be placed in and how the position of the TeleMetrum when booting - up will determine whether the unit is in "pad" or "idle" mode. + manual, particularly about the two "modes" that the altimeters + can be placed in. TeleMetrum uses the position of the device when booting + up will determine whether the unit is in "pad" or "idle" mode. TeleMini + enters "idle" mode when it receives a command packet within the first 5 seconds + of being powered up, otherwise it enters "pad" mode. - You can access a TeleMetrum in idle mode from the Teledongle's USB + You can access an altimeter in idle mode from the Teledongle's USB connection using the rf link by issuing a 'p' command to the TeleDongle. Practice connecting and - disconnecting ('~~' while using 'cu') from the TeleMetrum. If + disconnecting ('~~' while using 'cu') from the altimeter. If you cannot escape out of the "p" command, (by using a '~~' when in CU) then it is likely that your kernel has issues. Try a newer version. - Using this rf link allows you to configure the TeleMetrum, test + Using this rf link allows you to configure the altimeter, test fire e-matches and igniters from the flight line, check pyro-match continuity and so forth. You can leave the unit turned on while it is in 'idle mode' and then place the rocket vertically on the launch pad, walk away and then issue a - reboot command. The TeleMetrum will reboot and start sending data + reboot command. The altimeter will reboot and start sending data having changed to the "pad" mode. If the TeleDongle is not receiving this data, you can disconnect 'cu' from the Teledongle using the procedures mentioned above and THEN connect to the TeleDongle from @@ -245,7 +278,7 @@ NAR #88757, TRA #12200 TeleDongle, unplug it, and try again after plugging it back in. - Eventually the GPS will find enough satellites, lock in on them, + On TeleMetrum, the GPS will eventually find enough satellites, lock in on them, and 'ao-view' will both auditorially announce and visually indicate that GPS is ready. Now you can launch knowing that you have a good data path and @@ -254,8 +287,13 @@ NAR #88757, TRA #12200 order for ao-view to be able to receive data. - Both RDF (radio direction finding) tones from the TeleMetrum and - GPS trekking data are available and together are very useful in + The altimeters provide RDF (radio direction finding) tones on + the pad, during descent and after landing. These can be used to + locate the rocket using a directional antenna; the signal + strength providing an indication of the direction from receiver to rocket. + + + TeleMetrum also provides GPS trekking data, which can further simplify locating the rocket once it has landed. (The last good GPS data received before touch-down will be on the data screen of 'ao-view'.) @@ -281,7 +319,7 @@ NAR #88757, TRA #12200
FAQ - The altimeter (TeleMetrum) seems to shut off when disconnected from the + TeleMetrum seems to shut off when disconnected from the computer. Make sure the battery is adequately charged. Remember the unit will pull more power than the USB port can deliver before the GPS enters "locked" mode. The battery charges best when TeleMetrum @@ -298,17 +336,18 @@ NAR #88757, TRA #12200 communication. - The amber LED (on the TeleMetrum/altimeter) lights up when both + The amber LED (on the TeleMetrum) lights up when both battery and USB are connected. Does this mean it's charging? Yes, the yellow LED indicates the charging at the 'regular' rate. If the led is out but the unit is still plugged into a USB port, then the battery is being charged at a 'trickle' rate. - There are no "dit-dah-dah-dit" sound like the manual mentions? + There are no "dit-dah-dah-dit" sound or lights like the manual mentions? That's the "pad" mode. Weak batteries might be the problem. - It is also possible that the unit is horizontal and the output - is instead a "dit-dit" meaning 'idle'. + It is also possible that the Telemetrum is horizontal and the output + is instead a "dit-dit" meaning 'idle'. For TeleMini, it's possible that + it received a command packet which would have left it in "pad" mode. It's unclear how to use 'ao-view' and other programs when 'cu' @@ -335,76 +374,130 @@ NAR #88757, TRA #12200 Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, can be modiied to support - optional separate pyro battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - +
+ TeleMetrum Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, can be modiied to support + optional separate pyro battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + +
+
+ TeleMini Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + On-board 5 kilobyte non-volatile memory for flight data storage. + + + + + RF interface for battery charging, configuration, and data recovery. + + + + + Support for LiPo rechargeable batteries, using an external charger. + + + + + Uses LiPo to fire e-matches, can be modiied to support + optional separate pyro battery if needed. + + + + + 1.5 x .5 inch board designed to fit inside 18mm airframe coupler tube. + + + +
Handling Precautions - TeleMetrum is a sophisticated electronic device. When handled gently and - properly installed in an airframe, it will deliver impressive results. + All Altus Metrum products are sophisticated electronic device. When handled gently and + properly installed in an airframe, theywill deliver impressive results. However, like all electronic devices, there are some precautions you must take. - The Lithium Polymer rechargeable batteries used with TeleMetrum have an + The Lithium Polymer rechargeable batteries have an extraordinary power density. This is great because we can fly with much less battery mass than if we used alkaline batteries or previous generation rechargeable batteries... but if they are punctured @@ -416,22 +509,22 @@ NAR #88757, TRA #12200 strapping them down, for example. - The TeleMetrum barometric sensor is sensitive to sunlight. In normal + The barometric sensor is sensitive to sunlight. In normal mounting situations, it and all of the other surface mount components are "down" towards whatever the underlying mounting surface is, so this is not normally a problem. Please consider this, though, when - designing an installation, for example, in a 29mm airframe with a + designing an installation, for example, in an airframe with a see-through plastic payload bay. - The TeleMetrum barometric sensor sampling port must be able to + The barometric sensor sampling port must be able to "breathe", both by not being covered by foam or tape or other materials that might directly block the hole on the top of the sensor, but also by having a suitable static vent to outside air. - As with all other rocketry electronics, TeleMetrum must be protected + As with all other rocketry electronics, Altus Metrum altimeters must be protected from exposure to corrosive motor exhaust and ejection charge gasses. @@ -449,7 +542,18 @@ NAR #88757, TRA #12200 bay for TeleMetrum should have at least 10 inches of interior length.
- A typical TeleMetrum installation using the on-board GPS antenna and + TeleMini is a 0.5 inch by 1.5 inch circuit board. It was designed to + fit inside an 18mm airframe tube, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMini should have at least 9 inches of interior length. + + + A typical TeleMetrum or TeleMini installation using the on-board devices and default wire UHF antenna involves attaching only a suitable Lithium Polymer battery, a single pole switch for power on/off, and two pairs of wires connecting e-matches for the apogee and main ejection @@ -460,38 +564,32 @@ NAR #88757, TRA #12200 to fire ejection charges. This works marvelously with standard low-current e-matches like the J-Tek from MJG Technologies, and with Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, the board can be factory - modified to do so. This involves cutting two traces and adding a jumper - in a densely populated part of the board on TeleMetrum v1.0 and v1.1, - along with installation of a pyro battery connector at location B2. + want or need to use a separate pyro battery, check out the "External Pyro Battery" + section in this manual for instructions on how to wire that up. The + altimeters are designed to work with an external pyro battery of up to 15V. - We offer two choices of pyro and power switch connector, or you can - choose neither and solder wires directly to the board. All three choices - are reasonable depending on the constraints of your airframe. Our - favorite option when there is sufficient room above the board is to use - the Tyco pin header with polarization and locking. If you choose this - option, you crimp individual wires for the power switch and e-matches - into a mating connector, and installing and removing the TeleMetrum - board from an airframe is as easy as plugging or unplugging two - connectors. If the airframe will not support this much height or if - you want to be able to directly attach e-match leads to the board, we - offer a screw terminal block. This is very similar to what most other - altimeter vendors provide and so may be the most familiar option. - You'll need a very small straight blade screwdriver to connect - and disconnect the board in this case, such as you might find in a - jeweler's screwdriver set. Finally, you can forego both options and - solder wires directly to the board, which may be the best choice for - minimum diameter and/or minimum mass designs. + Ejection charges are wired directly to the screw terminal block + at the aft end of the altimeter. This is very similar to what + most other altimeter vendors provide and so may be the most + familiar option. You'll need a very small straight blade + screwdriver to connect and disconnect the board in this case, + such as you might find in a jeweler's screwdriver set. - For most airframes, the integrated GPS antenna and wire UHF antenna are - a great combination. However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to use - off-board external antennas instead. In this case, you can order - TeleMetrum with an SMA connector for the UHF antenna connection, and - you can unplug the integrated GPS antenna and select an appropriate - off-board GPS antenna with cable terminating in a U.FL connector. + TeleMetrum also uses the screw terminal block for the power + switch leads. On TeleMini, the power switch leads are soldered + directly to the board and can be connected directly to the switch. + + + For most airframes, the integrated antennas are more than + adequate However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to + use off-board external antennas instead. In this case, you can + order an altimeter with an SMA connector for the UHF antenna + connection, and, on TeleMetrum, you can unplug the integrated GPS + antenna and select an appropriate off-board GPS antenna with + cable terminating in a U.FL connector. @@ -499,53 +597,59 @@ NAR #88757, TRA #12200
Firmware Modes - The AltOS firmware build for TeleMetrum has two fundamental modes, - "idle" and "flight". Which of these modes the firmware operates in - is determined by the orientation of the rocket (well, actually the - board, of course...) at the time power is switched on. If the rocket - is "nose up", then TeleMetrum assumes it's on a rail or rod being - prepared for launch, so the firmware chooses flight mode. However, - if the rocket is more or less horizontal, the firmware instead enters - idle mode. + The AltOS firmware build for the altimeters has two + fundamental modes, "idle" and "flight". Which of these modes + the firmware operates in is determined at startup time. For + TeleMetrum, the mode is controlled by the orientation of the + rocket (well, actually the board, of course...) at the time + power is switched on. If the rocket is "nose up", then + TeleMetrum assumes it's on a rail or rod being prepared for + launch, so the firmware chooses flight mode. However, if the + rocket is more or less horizontal, the firmware instead enters + idle mode. For TeleMini, "idle" mode is selected when the + board receives a command packet within the first five seconds + of operation; if no packet is received, the board enters + "flight" mode. - At power on, you will hear three beeps + At power on, you will hear three beeps or see three flashes ("S" in Morse code for startup) and then a pause while - TeleMetrum completes initialization and self tests, and decides which + the altimeter completes initialization and self tests, and decides which mode to enter next. - In flight or "pad" mode, TeleMetrum turns on the GPS system, - engages the flight - state machine, goes into transmit-only mode on the RF link sending - telemetry, and waits for launch to be detected. Flight mode is - indicated by an audible "di-dah-dah-dit" ("P" for pad) on the - beeper, followed by - beeps indicating the state of the pyrotechnic igniter continuity. - One beep indicates apogee continuity, two beeps indicate - main continuity, three beeps indicate both apogee and main continuity, - and one longer "brap" sound indicates no continuity. For a dual - deploy flight, make sure you're getting three beeps before launching! - For apogee-only or motor eject flights, do what makes sense. + In flight or "pad" mode, the altimeter engages the flight + state machine, goes into transmit-only mode on the RF link + sending telemetry, and waits for launch to be detected. + Flight mode is indicated by an "di-dah-dah-dit" ("P" for pad) + on the beeper or lights, followed by beeps or flashes + indicating the state of the pyrotechnic igniter continuity. + One beep/flash indicates apogee continuity, two beeps/flashes + indicate main continuity, three beeps/flashes indicate both + apogee and main continuity, and one longer "brap" sound or + rapidly alternating lights indicates no continuity. For a + dual deploy flight, make sure you're getting three beeps or + flashes before launching! For apogee-only or motor eject + flights, do what makes sense. - In idle mode, you will hear an audible "di-dit" ("I" for idle), and + In idle mode, you will hear an audible "di-dit" or see two short flashes ("I" for idle), and the normal flight state machine is disengaged, thus - no ejection charges will fire. TeleMetrum also listens on the RF + no ejection charges will fire. The altimeters also listen on the RF link when in idle mode for packet mode requests sent from TeleDongle. Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. - Idle mode is useful for configuring TeleMetrum, for extracting data + USB or the RF link equivalently. TeleMini uses only the RF link. + Idle mode is useful for configuring the altimeter, for extracting data from the on-board storage chip after flight, and for ground testing pyro charges. - One "neat trick" of particular value when TeleMetrum is used with very + One "neat trick" of particular value when the altimeter is used with very large airframes, is that you can power the board up while the rocket is horizontal, such that it comes up in idle mode. Then you can raise the airframe to launch position, use a TeleDongle to open a packet connection, and issue a 'reset' command which will cause - TeleMetrum to reboot, realize it's now nose-up, and thus choose + the altimeter to reboot and come up in flight mode. This is much safer than standing on the top step of a rickety step-ladder or hanging off the side of a launch tower with a screw-driver trying to turn on your avionics before installing @@ -582,18 +686,20 @@ NAR #88757, TRA #12200 An important aspect of preparing a rocket using electronic deployment for flight is ground testing the recovery system. Thanks to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum-equipped rocket without as + this can be accomplished in a TeleMetrum- or TeleMini- equipped rocket without as much work as you may be accustomed to with other systems. It can even be fun! - Just prep the rocket for flight, then power up TeleMetrum while the - airframe is horizontal. This will cause the firmware to go into - "idle" mode, in which the normal flight state machine is disabled and - charges will not fire without manual command. Then, establish an - RF packet connection from a TeleDongle-equipped computer using the - P command from a safe distance. You can now command TeleMetrum to - fire the apogee or main charges to complete your testing. + Just prep the rocket for flight, then power up the altimeter + in "idle" mode (placing airframe horizontal for TeleMetrum or + starting the RF packet connection for TeleMini). This will cause the + firmware to go into "idle" mode, in which the normal flight + state machine is disabled and charges will not fire without + manual command. Then, establish an RF packet connection from + a TeleDongle-equipped computer using the P command from a safe + distance. You can now command the altimeter to fire the apogee + or main charges to complete your testing. In order to reduce the chance of accidental firing of pyrotechnic @@ -614,12 +720,12 @@ NAR #88757, TRA #12200 link. - By design, TeleMetrum firmware listens for an RF connection when - it's in "idle mode" (turned on while the rocket is horizontal), which + By design, the altimeter firmware listens for an RF connection when + it's in "idle mode", which allows us to use the RF link to configure the rocket, do things like ejection tests, and extract data after a flight without having to crack open the airframe. However, when the board is in "flight - mode" (turned on when the rocket is vertical) the TeleMetrum only + mode", the altimeter only transmits and doesn't listen at all. That's because we want to put ultimate priority on event detection and getting telemetry out of the rocket and out over @@ -645,35 +751,43 @@ NAR #88757, TRA #12200
Configurable Parameters - Configuring a TeleMetrum board for flight is very simple. Because we - have both acceleration and pressure sensors, there is no need to set - a "mach delay", for example. The few configurable parameters can all - be set using a simple terminal program over the USB port or RF link - via TeleDongle. + Configuring an Altus Metrum altimeter for flight is very + simple. Through the use of a Kalman filter, there is no need + to set a "mach delay" . The few configurable parameters can + all be set using a simple terminal program over the USB port + or RF link via TeleDongle.
- Radio Channel - - Our firmware supports 10 channels. The default channel 0 corresponds - to a center frequency of 434.550 Mhz, and channels are spaced every - 100 khz. Thus, channel 1 is 434.650 Mhz, and channel 9 is 435.550 Mhz. - At any given launch, we highly recommend coordinating who will use - each channel and when to avoid interference. And of course, both - TeleMetrum and TeleDongle must be configured to the same channel to - successfully communicate with each other. - - - To set the radio channel, use the 'c r' command, like 'c r 3' to set - channel 3. + Radio Frequencies + + The Altus Metrum boards support frequencies in the 70cm + band. By default, the configuration interface provides a + list of 10 common frequencies -- 100kHz channels starting at + 434.550MHz. However, you can configure the firmware to use + any 50kHz multiple within the 70cm band. At any given + launch, we highly recommend coordinating who will use each + frequency and when to avoid interference. And of course, both + altimeter and TeleDongle must be configured to the same + frequency to successfully communicate with each other. + + + To set the radio frequency, use the 'c R' command to specify the + radio transceiver configuration parameter. This parameter is computed + using the desired frequency, 'F', the radio calibration parameter, 'C' (showed by the 'c s' command) and + the standard calibration reference frequency, 'S', (normally 434.550Mhz): + + R = F / S * C + + Round the result to the nearest integer value. As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip on - your TeleMetrum board if you want the change to stay in place across reboots. + change to the parameter block in the on-board flash on + your altimeter board if you want the change to stay in place across reboots.
Apogee Delay - Apogee delay is the number of seconds after TeleMetrum detects flight + Apogee delay is the number of seconds after the altimeter detects flight apogee that the drogue charge should be fired. In most cases, this should be left at the default of 0. However, if you are flying redundant electronics such as for an L3 certification, you may wish @@ -686,20 +800,21 @@ NAR #88757, TRA #12200 change to the parameter block in the on-board DataFlash chip. - Please note that the TeleMetrum apogee detection algorithm always - fires a fraction of a second *after* apogee. If you are also flying - an altimeter like the PerfectFlite MAWD, which only supports selecting - 0 or 1 seconds of apogee delay, you may wish to set the MAWD to 0 - seconds delay and set the TeleMetrum to fire your backup 2 or 3 - seconds later to avoid any chance of both charges firing - simultaneously. We've flown several airframes this way quite happily, - including Keith's successful L3 cert. + Please note that the Altus Metrum apogee detection algorithm + fires exactly at apogee. If you are also flying an + altimeter like the PerfectFlite MAWD, which only supports + selecting 0 or 1 seconds of apogee delay, you may wish to + set the MAWD to 0 seconds delay and set the TeleMetrum to + fire your backup 2 or 3 seconds later to avoid any chance of + both charges firing simultaneously. We've flown several + airframes this way quite happily, including Keith's + successful L3 cert.
Main Deployment Altitude - By default, TeleMetrum will fire the main deployment charge at an + By default, the altimeter will fire the main deployment charge at an elevation of 250 meters (about 820 feet) above ground. We think this is a good elevation for most airframes, but feel free to change this to suit. In particular, if you are flying two altimeters, you may @@ -719,7 +834,7 @@ NAR #88757, TRA #12200 Calibration There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle. + only one for TeleDongle and TeleMini.
Radio Frequency @@ -737,7 +852,7 @@ NAR #88757, TRA #12200 To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to channel 0, and use the 'C' + frequency counter, set the board to 434.550MHz, and use the 'C' command to generate a CW carrier. Wait for the transmitter temperature to stabilize and the frequency to settle down. Then, divide 434.550 Mhz by the @@ -749,11 +864,17 @@ NAR #88757, TRA #12200 As with all 'c' sub-commands, follow this with a 'c w' to write the change to the parameter block in the on-board DataFlash chip. + + when the radio calibration value is changed, the radio + frequency value is reset to the same value, so you'll need + to recompute and reset the radio frequency value using the + new radio calibration value. +
- Accelerometer + TeleMetrum Accelerometer - The accelerometer we use has its own 5 volt power supply and + The TeleMerum accelerometer we use has its own 5 volt power supply and the output must be passed through a resistive voltage divider to match the input of our 3.3 volt ADC. This means that unlike the barometric sensor, the output of the acceleration sensor is not ratiometric to @@ -804,9 +925,10 @@ NAR #88757, TRA #12200 Updating Device Firmware The big conceptual thing to realize is that you have to use a - TeleDongle as a programmer to update a TeleMetrum, and vice versa. + TeleDongle as a programmer to update a TeleMetrum or TeleMini, + and a TeleMetrum or other TeleDongle to program the TeleDongle Due to limited memory resources in the cc1111, we don't support - programming either unit directly over USB. + programming directly over USB. You may wish to begin by ensuring you have current firmware images. @@ -818,7 +940,7 @@ NAR #88757, TRA #12200 version from . - We recommend updating TeleMetrum first, before updating TeleDongle. + We recommend updating the altimeter first, before updating TeleDongle.
Updating TeleMetrum Firmware @@ -856,7 +978,7 @@ NAR #88757, TRA #12200 Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.0-0.7.1.ihx. It should be visible + name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find it. @@ -880,12 +1002,72 @@ NAR #88757, TRA #12200
+
+ Updating TeleMini Firmware + + + You'll need a special 'programming cable' to reprogram the + TeleMini. It's available on the Altus Metrum web store, or + you can make your own using an 8-pin MicroMaTch connector on + one end and a set of four pins on the other. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the matching + connector on the TeleDongle, and the 4-pins into the holes + in the TeleMini circuit board. Note that the MicroMaTch + connector has an alignment pin that goes through a hole in + the PC board when you have the cable oriented correctly, and + that pin 1 on the TeleMini board is marked with a square pad + while the other pins have round pads. + + + Attach a battery to the TeleMini board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMini + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMini, which should have a + name in the form telemini-v1.0-1.0.0.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMini with new firmware, showing a progress bar. + + + Confirm that the TeleMini board seems to have updated ok, which you + can do by configuring it over the RF link through the TeleDongle, or + letting it come up in "flight" mode and listening for telemetry. + + + If something goes wrong, give it another try. + + +
Updating TeleDongle Firmware - Updating TeleDongle's firmware is just like updating TeleMetrum - firmware, but you switch which board is the programmer and which - is the programming target. + Updating TeleDongle's firmware is just like updating TeleMetrum or TeleMini + firmware, but you use either a TeleMetrum or another TeleDongle as the programmer. @@ -895,37 +1077,37 @@ NAR #88757, TRA #12200 Find the USB cable that you got as part of the starter kit, and - plug the "mini" end in to the mating connector on TeleMetrum. + plug the "mini" end in to the mating connector on TeleMetrum or TeleDongle. Take the 2 screws out of the TeleDongle case to get access to the circuit board. - Plug the 8-pin end of the programming cable to the (latching) - matching connector on the TeleMetrum, and the 4-pin end to the + Plug the 8-pin end of the programming cable to the + matching connector on the programmer, and the 4-pin end to the matching connector on the TeleDongle. Note that each MicroMaTch connector has an alignment pin that goes through a hole in the PC board when you have the cable oriented correctly. - Attach a battery to the TeleMetrum board. + Attach a battery to the TeleMetrum board if you're using one. - Plug both TeleMetrum and TeleDongle into your computer's USB - ports, and power up the TeleMetrum. + Plug both the programmer and the TeleDongle into your computer's USB + ports, and power up the programmer. Run AltosUI, and select 'Flash Image' from the File menu. - Pick the TeleMetrum device from the list, identifying it as the + Pick the programmer device from the list, identifying it as the programming device. Select the image you want put on the TeleDongle, which should have a - name in the form teledongle-v0.2-0.7.1.ihx. It should be visible + name in the form teledongle-v0.2-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find it. @@ -963,8 +1145,6 @@ NAR #88757, TRA #12200
- - @@ -972,8 +1152,8 @@ NAR #88757, TRA #12200 The AltosUI program provides a graphical user interface for interacting with the Altus Metrum product family, including - TeleMetrum and TeleDongle. AltosUI can monitor telemetry data, - configure TeleMetrum and TeleDongle devices and many other + TeleMetrum, TeleMini and TeleDongle. AltosUI can monitor telemetry data, + configure TeleMetrum, TeleMini and TeleDongle devices and many other tasks. The primary interface window provides a selection of buttons, one for each major activity in the system. This manual is split into chapters, each of which documents one of the tasks @@ -981,12 +1161,12 @@ NAR #88757, TRA #12200
Packet Command Mode - Controlling TeleMetrum Over The Radio Link + Controlling An Altimeter Over The Radio Link One of the unique features of the Altus Metrum environment is the ability to create a two way command link between TeleDongle - and TeleMetrum using the digital radio transceivers built into - each device. This allows you to interact with TeleMetrum from + and an altimeter using the digital radio transceivers built into + each device. This allows you to interact with the altimeter from afar, as if it were directly connected to the computer. @@ -999,16 +1179,16 @@ NAR #88757, TRA #12200 One oddity in the current interface is how AltosUI selects the - channel for packet mode communications. Instead of providing - an interface to specifically configure the channel, it uses - whatever channel was most recently selected for the target + frequency for packet mode communications. Instead of providing + an interface to specifically configure the frequency, it uses + whatever frequency was most recently selected for the target TeleDongle device in Monitor Flight mode. If you haven't ever used that mode with the TeleDongle in question, select the Monitor Flight button from the top level UI, pick the appropriate TeleDongle device. Once the flight monitoring - window is open, select the desired channel and then close it + window is open, select the desired frequency and then close it down again. All Packet Command Mode operations will now use - that channel. + that frequency. @@ -1019,12 +1199,12 @@ NAR #88757, TRA #12200 - Configure TeleMetrum—Reset apogee delays or main deploy - heights to respond to changing launch conditions. You can - also 'reboot' the TeleMetrum device. Use this to remotely - enable the flight computer by turning TeleMetrum on while - horizontal, then once the airframe is oriented for launch, - you can reboot TeleMetrum and have it restart in pad mode + Configure altimeter apogee delays or main deploy heights + to respond to changing launch conditions. You can also + 'reboot' the altimeter. Use this to remotely enable the + flight computer by turning TeleMetrum on in "idle" mode, + then once the airframe is oriented for launch, you can + reboot the altimeter and have it restart in pad mode without having to climb the scary ladder. @@ -1033,15 +1213,15 @@ NAR #88757, TRA #12200 Fire Igniters—Test your deployment charges without snaking wires out through holes in the airframe. Simply assembly the rocket as if for flight with the apogee and main charges - loaded, then remotely command TeleMetrum to fire the + loaded, then remotely command the altimeter to fire the igniters. - Packet command mode uses the same RF channels as telemetry - mode. Configure the desired TeleDongle channel using the - flight monitor window channel selector and then close that + Packet command mode uses the same RF frequencies as telemetry + mode. Configure the desired TeleDongle frequency using the + flight monitor window frequency selector and then close that window before performing the desired operation. @@ -1050,13 +1230,19 @@ NAR #88757, TRA #12200 it on. Otherwise, TeleMetrum will start in 'pad' mode ready for flight and will not be listening for command packets from TeleDongle. + + TeleMini listens for a command packet for five seconds after + first being turned on, if it doesn't hear anything, it enters + 'pad' mode, ready for flight and will no longer listen for + command packets. + When packet command mode is enabled, you can monitor the link - by watching the lights on the TeleDongle and TeleMetrum - devices. The red LED will flash each time TeleDongle or - TeleMetrum transmit a packet while the green LED will light up + by watching the lights on the + devices. The red LED will flash each time they + transmit a packet while the green LED will light up on TeleDongle while it is waiting to receive a packet from - TeleMetrum. + the altimeter.
@@ -1074,27 +1260,27 @@ NAR #88757, TRA #12200 date and rocket serial and flight numbers. - The radio channel being monitored by the TeleDongle device is + The radio frequency being monitored by the TeleDongle device is displayed at the top of the window. You can configure the - channel by clicking on the channel box and selecting the desired - channel. AltosUI remembers the last channel selected for each + frequecy by clicking on the frequency box and selecting the desired + frequency. AltosUI remembers the last frequency selected for each TeleDongle and selects that automatically the next time you use that device. - Below the TeleDongle channel selector, the window contains a few - significant pieces of information about the TeleMetrum providing + Below the TeleDongle frequency selector, the window contains a few + significant pieces of information about the altimeter providing the telemetry data stream: - The TeleMetrum callsign + The configured callsign - The TeleMetrum serial number + The device serial number - The flight number. Each TeleMetrum remembers how many + The flight number. Each altimeter remembers how many times it has flown. @@ -1161,14 +1347,14 @@ NAR #88757, TRA #12200 - GPS Locked. This indicates whether the GPS receiver is + GPS Locked. For a TeleMetrum device, this indicates whether the GPS receiver is currently able to compute position information. GPS requires at least 4 satellites to compute an accurate position. - GPS Ready. This indicates whether GPS has reported at least + GPS Ready. For a TeleMetrum device, this indicates whether GPS has reported at least 10 consecutive positions without losing lock. This ensures that the GPS receiver has reliable reception from the satellites. @@ -1196,7 +1382,7 @@ NAR #88757, TRA #12200 flight. - The current latitude and longitude reported by the GPS are + The current latitude and longitude reported by the TeleMetrum GPS are also shown. Note that under high acceleration, these values may not get updated as the GPS receiver loses position fix. Once the rocket starts coasting, the receiver should @@ -1222,7 +1408,8 @@ NAR #88757, TRA #12200 height. Good descent rates generally range from 15-30m/s. - To help locate the rocket in the sky, use the elevation and + For TeleMetrum altimeters, you can locate the rocket in the sky + using the elevation and bearing information to figure out where to look. Elevation is in degrees above the horizon. Bearing is reported in degrees relative to true north. Range can help figure out how big the @@ -1252,6 +1439,13 @@ NAR #88757, TRA #12200 latitude and longitude and enter them into your handheld GPS unit and have that compute a track to the landing location. + + Both TeleMini and TeleMetrum will continue to transmit RDF + tones after landing, allowing you to locate the rocket by + following the radio signal. You may need to get away from + the clutter of the flight line, or even get up on a hill (or + your neighbor's RV) to receive the RDF signal. + Finally, the maximum height, speed and acceleration reported during the flight are displayed for your admiring observers. @@ -1260,7 +1454,7 @@ NAR #88757, TRA #12200
Site Map - When the rocket gets a GPS fix, the Site Map tab will map + When the TeleMetrum gets a GPS fix, the Site Map tab will map the rocket's position to make it easier for you to locate the rocket, both while it is in the air, and when it has landed. The rocket's state is indicated by colour: white for pad, red for @@ -1278,24 +1472,30 @@ NAR #88757, TRA #12200 the rocket's path will be traced on a dark grey background instead. + + You can pre-load images for your favorite launch sites + before you leave home; check out the 'Preload Maps' section below. +
Save Flight Data - TeleMetrum records flight data to its internal flash memory. - This data is recorded at a much higher rate than the telemetry + The altimeter records flight data to its internal flash memory. + The TeleMetrum data is recorded at a much higher rate than the telemetry system can handle, and is not subject to radio drop-outs. As such, it provides a more complete and precise record of the flight. The 'Save Flight Data' button allows you to read the - flash memory and write it to disk. + flash memory and write it to disk. As TeleMini has only a barometer, it + records data at the same rate as the telemetry signal, but there will be + no data lost due to telemetry drop-outs. Clicking on the 'Save Flight Data' button brings up a list of connected TeleMetrum and TeleDongle devices. If you select a TeleMetrum device, the flight data will be downloaded from that device directly. If you select a TeleDongle device, flight data - will be downloaded from a TeleMetrum device connected via the + will be downloaded from a TeleMetrum or TeleMini device connected via the packet command link to the specified TeleDongle. See the chapter on Packet Command Mode for more information about this. @@ -1312,7 +1512,7 @@ NAR #88757, TRA #12200 The filename for each flight log is computed automatically - from the recorded flight date, TeleMetrum serial number and + from the recorded flight date, altimeter serial number and flight number information.
@@ -1321,7 +1521,7 @@ NAR #88757, TRA #12200 Select this button and you are prompted to select a flight record file, either a .telem file recording telemetry data or a - .eeprom file containing flight data saved from the TeleMetrum + .eeprom file containing flight data saved from the altimeter flash memory. @@ -1335,7 +1535,7 @@ NAR #88757, TRA #12200 Select this button and you are prompted to select a flight record file, either a .telem file recording telemetry data or a - .eeprom file containing flight data saved from the TeleMetrum + .eeprom file containing flight data saved from flash memory. @@ -1353,10 +1553,8 @@ NAR #88757, TRA #12200 Note that telemetry files will generally produce poor graphs - due to the lower sampling rate and missed telemetry packets, - and will also often have significant amounts of data received - while the rocket was waiting on the pad. Use saved flight data - for graphing where possible. + due to the lower sampling rate and missed telemetry packets. + Use saved flight data for graphing where possible.
@@ -1376,7 +1574,7 @@ NAR #88757, TRA #12200 This is a text file containing the data in a form suitable for import into a spreadsheet or other external data analysis tool. The first few lines of the file contain the version and - configuration information from the TeleMetrum device, then + configuration information from the altimeter, then there is a single header line which labels all of the fields. All of these lines start with a '#' character which most tools can be configured to skip over. @@ -1400,17 +1598,17 @@ NAR #88757, TRA #12200
- Configure TeleMetrum + Configure Altimeter Select this button and then select either a TeleMetrum or TeleDongle Device from the list provided. Selecting a TeleDongle - device will use Packet Comamnd Mode to configure remote - TeleMetrum device. Learn how to use this in the Packet Command + device will use Packet Comamnd Mode to configure a remote + altimeter. Learn how to use this in the Packet Command Mode chapter. The first few lines of the dialog provide information about the - connected TeleMetrum device, including the product name, + connected device, including the product name, software version and hardware serial number. Below that are the individual configuration entries. @@ -1420,7 +1618,7 @@ NAR #88757, TRA #12200 - Save. This writes any changes to the TeleMetrum + Save. This writes any changes to the configuration parameter block in flash memory. If you don't press this button, any changes you make will be lost. @@ -1433,7 +1631,7 @@ NAR #88757, TRA #12200 - Reboot. This reboots the TeleMetrum device. Use this to + Reboot. This reboots the device. Use this to switch from idle to pad mode by rebooting once the rocket is oriented for flight. @@ -1472,12 +1670,12 @@ NAR #88757, TRA #12200
- Radio Channel + Radio Frequency - This configures which of the 10 radio channels to use for both + This configures which of the configured frequencies to use for both telemetry and packet command mode. Note that if you set this value via packet command mode, you will have to reconfigure - the TeleDongle channel before you will be able to use packet + the TeleDongle frequency before you will be able to use packet command mode again.
@@ -1486,7 +1684,7 @@ NAR #88757, TRA #12200 The radios in every Altus Metrum device are calibrated at the factory to ensure that they transmit and receive on the - specified frequency for each channel. You can adjust that + specified frequency. You can adjust that calibration by changing this value. To change the TeleDongle's calibration, you must reprogram the unit completely. @@ -1526,6 +1724,11 @@ NAR #88757, TRA #12200 memory, on v1.0 boards that's just 256 bytes. However, the flash part on the v1.1 boards uses 64kB for each block.
+ + TeleMini has 5kB of on-board storage, which is plenty for a + single flight. Make sure you download and delete the data + before a subsequent flight or it will not log any data. +
@@ -1588,6 +1791,17 @@ NAR #88757, TRA #12200 various serial communication issues.
+
+ Manage Frequencies + + This brings up a dialog where you can configure the set of + frequencies shown in the various frequency menus. You can + add as many as you like, or even reconfigure the default + set. Changing this list does not affect the frequency + settings of any devices, it only changes the set of + frequencies shown in the menus. + +
Flash Image @@ -1655,6 +1869,52 @@ NAR #88757, TRA #12200 selecting the desired igniter.
+
+ Scan Channels + + This listens for telemetry packets on all of the configured + frequencies, displaying information about each device it + receives a packet from. You can select which of the three + telemetry formats should be tried; by default, it only listens + for the standard telemetry packets used in v1.0 and later + firmware. + +
+
+ Load Maps + + Before heading out to a new launch site, you can use this to + load satellite images in case you don't have internet + connectivity at the site. This loads a fairly large area + around the launch site, which should cover any flight you're likely to make. + + + There's a drop-down menu of launch sites we know about; if + your favorites aren't there, please let us know the lat/lon + and name of the site. The contents of this list are actually + downloaded at run-time, so as new sites are sent in, they'll + get automatically added to this list. + + + If the launch site isn't in the list, you can manually enter the lat/lon values + + + Clicking the 'Load Map' button will fetch images from Google + Maps; note that Google limits how many images you can fetch at + once, so if you load more than one launch site, you may get + some gray areas in the map which indicate that Google is tired + of sending data to you. Try again later. + +
+
+ Monitor Idle + + This brings up a dialog similar to the Monitor Flight UI, + except it works with the altimeter in "idle" mode by sending + query commands to discover the current state rather than + listening for telemetry packets. + +
Using Altus Metrum Products @@ -1669,12 +1929,15 @@ NAR #88757, TRA #12200
In the Rocket - In the rocket itself, you just need a TeleMetrum board and + In the rocket itself, you just need a TeleMetrum or + TeleMini board and a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a TeleMetrum for hours. + alkaline battery, and will run a TeleMetrum for hours. + A 110mAh battery weighs less than a triple A battery and will run a TeleMetrum for + a few hours, or a TeleMini for much (much) longer. - By default, we ship TeleMetrum with a simple wire antenna. If your + By default, we ship the altimeters with a simple wire antenna. If your electronics bay or the airframe it resides within is made of carbon fiber, which is opaque to RF signals, you may choose to have an SMA connector installed so that you can run a coaxial cable to an antenna mounted @@ -1697,14 +1960,14 @@ NAR #88757, TRA #12200 After the flight, you can use the RF link to extract the more detailed data - logged in the rocket, or you can use a mini USB cable to plug into the + logged in either TeleMetrum or TeleMini devices, or you can use a mini USB cable to plug into the TeleMetrum board directly. Pulling out the data without having to open up the rocket is pretty cool! A USB cable is also how you charge the LiPo battery, so you'll want one of those anyway... the same cable used by lots of digital cameras and other modern electronic stuff will work fine. - If your rocket lands out of sight, you may enjoy having a hand-held GPS + If your TeleMetrum-equiped rocket lands out of sight, you may enjoy having a hand-held GPS receiver, so that you can put in a waypoint for the last reported rocket position before touch-down. This makes looking for your rocket a lot like Geo-Cacheing... just go to the waypoint and look around starting from there. @@ -1745,7 +2008,7 @@ NAR #88757, TRA #12200 Arrow Antennas. The 440-3 and 440-5 are both good choices for finding a - TeleMetrum-equipped rocket when used with a suitable 70cm HT. + TeleMetrum- or TeleMini- equipped rocket when used with a suitable 70cm HT.
@@ -1753,12 +2016,12 @@ NAR #88757, TRA #12200 Our software makes it easy to log the data from each flight, both the telemetry received over the RF link during the flight itself, and the more - complete data log recorded in the DataFlash memory on the TeleMetrum + complete data log recorded in the flash memory on the altimeter board. Once this data is on your computer, our postflight tools make it easy to quickly get to the numbers everyone wants, like apogee altitude, max acceleration, and max velocity. You can also generate and view a standard set of plots showing the altitude, acceleration, and - velocity of the rocket during flight. And you can even export a data file + velocity of the rocket during flight. And you can even export a TeleMetrum data file useable with Google Maps and Google Earth for visualizing the flight path in two or three dimensions! -- cgit v1.2.3 From 21837e0026c87635abf4baf2c6c574a7b274f449 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 18:14:10 -0700 Subject: doc: Document Ignite Mode and Pad Orientation configuration options Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 0ee9d163..17984336 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1730,6 +1730,67 @@ NAR #88757, TRA #12200 before a subsequent flight or it will not log any data.
+
+ Ignite Mode + + TeleMetrum and TeleMini provide two igniter channels as they + were originally designed as dual-deploy flight + computers. This configuration parameter allows the two + channels to be used in different configurations. + + + + + Dual Deploy. This is the usual mode of operation; the + 'apogee' channel is fired at apogee and the 'main' + channel at the height above ground specified by the + 'Main Deploy Altitude' during descent. + + + + + Redundant Apogee. This fires both channels at + apogee, the 'apogee' channel first followed after a two second + delay by the 'main' channel. + + + + + Redundant Main. This fires both channels at the + height above ground specified by the Main Deploy + Altitude setting during descent. The 'apogee' + channel is fired first, followed after a two second + delay by the 'main' channel. + + + +
+
+ Pad Orientation + + Because it includes an accelerometer, TeleMetrum is + sensitive to the orientation of the board. By default, it + expects the antenna end to point forward. This parameter + allows that default to be changed, permitting the board to + be mounted with the antenna pointing aft instead. + + + + + Antenna Up. In this mode, the antenna end of the + TeleMetrum board must point forward, in line with the + expected flight path. + + + + + Antenna Down. In this mode, the antenna end of the + TeleMetrum board must point aft, in line with the + expected flight path. + + + +
Configure AltosUI -- cgit v1.2.3 From 7283deaa91e752acc45018ef2ea2f560b09af354 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 18:22:16 -0700 Subject: doc: Describe 'stats' tab in Graph UI, 'Graph Flight' button. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 17984336..a3078b82 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1447,9 +1447,14 @@ NAR #88757, TRA #12200 your neighbor's RV) to receive the RDF signal. - Finally, the maximum height, speed and acceleration reported + The maximum height, speed and acceleration reported during the flight are displayed for your admiring observers. + + To get more detailed information about the flight, you can + click on the 'Graph Flight' button which will bring up a + graph window for the current flight. +
Site Map @@ -1539,9 +1544,14 @@ NAR #88757, TRA #12200 flash memory. - Once a flight record is selected, the acceleration (blue), - velocity (green) and altitude (red) of the flight are plotted and - displayed, measured in metric units. + Once a flight record is selected, a window with two tabs is + opened. The first tab contains a graph with acceleration + (blue), velocity (green) and altitude (red) of the flight are + plotted and displayed, measured in metric units. The + apogee(yellow) and main(magenta) igniter voltages are also + displayed; high voltages indicate continuity, low voltages + indicate open circuits. The second tab contains some basic + flight statistics. The graph can be zoomed into a particular area by clicking and -- cgit v1.2.3 From 5aa3e49f794ba5ed2680016f3dca47d67ae99836 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 18:32:05 -0700 Subject: doc: Add telemetry docs to debian/linux/mac/windows packages Signed-off-by: Keith Packard --- altosui/Makefile.am | 3 ++- altosui/altos-windows.nsi | 1 + debian/docs | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 3bc68cdb..bab8f816 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -169,9 +169,10 @@ FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf ALTOS_DOC=$(top_srcdir)/doc/altos.pdf +TELEMETRY_DOC=$(top_srcdir)/doc/telemetry.pdf TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf -DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TEMPLATE_DOC) +DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC) # Distribution targets LINUX_DIST=Altos-Linux-$(VERSION).tar.bz2 diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index d92d1eb3..7c9b7a28 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -92,6 +92,7 @@ Section "Documentation" File "../doc/altusmetrum.pdf" File "../doc/altos.pdf" + File "../doc/telemetry.pdf" File "../doc/telemetrum-outline.pdf" SectionEnd diff --git a/debian/docs b/debian/docs index 13fda8f2..6652abf7 100644 --- a/debian/docs +++ b/debian/docs @@ -2,3 +2,8 @@ NEWS README doc/altusmetrum.html doc/altusmetrum.pdf +doc/telemetry.html +doc/telemetry.pdf +doc/altos.html +doc/altos.pdf +doc/telemetrum-outline.pdf -- cgit v1.2.3 From a07b07d48f71b9a11e73a82db075cc57bad0c09f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 22:14:32 -0700 Subject: doc: Add release notes, include them in altusmetrum doc. Shuffle altusmetrum This adds release notes and includes them in the main altusmetrum doc as well as making stand-alone html available for inclusion in the website. Signed-off-by: Keith Packard --- doc/Makefile | 9 +- doc/altusmetrum.xsl | 1213 ++++++++++++++++++++++--------------------- doc/release-notes-0.7.1.xsl | 57 ++ doc/release-notes-0.8.xsl | 56 ++ doc/release-notes-0.9.2.xsl | 20 + doc/release-notes-0.9.xsl | 31 ++ 6 files changed, 783 insertions(+), 603 deletions(-) create mode 100644 doc/release-notes-0.7.1.xsl create mode 100644 doc/release-notes-0.8.xsl create mode 100644 doc/release-notes-0.9.2.xsl create mode 100644 doc/release-notes-0.9.xsl diff --git a/doc/Makefile b/doc/Makefile index b431f4ca..6d9ea8eb 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -2,7 +2,12 @@ # http://docbook.sourceforge.net/release/xsl/current/README # -HTML=altusmetrum.html altos.html telemetry.html +RELNOTES=\ + release-notes-0.7.1.html \ + release-notes-0.8.html \ + release-notes-0.9.html \ + release-notes-0.9.2.html +HTML=altusmetrum.html altos.html telemetry.html $(RELNOTES) PDF=altusmetrum.pdf altos.pdf telemetry.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl @@ -11,7 +16,7 @@ PDFSTYLE= .SUFFIXES: .xsl .html .fo .pdf -XSLTFLAGS=--stringparam section.autolabel 1 +XSLTFLAGS=--stringparam section.autolabel 1 --xinclude .xsl.html: xsltproc $(XSLTFLAGS) -o $@ $(HTMLSTYLE) $*.xsl diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index a3078b82..88c9b80a 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -175,541 +175,229 @@ NAR #88757, TRA #12200 The latest version may always be downloaded from . + + + Handling Precautions - Both Telemetrum and TeleDongle can be directly communicated - with using USB ports. The first thing you should try after getting - both units plugged into to your computer's usb port(s) is to run - 'ao-list' from a terminal-window to see what port-device-name each - device has been assigned by the operating system. - You will need this information to access the devices via their - respective on-board firmware and data using other command line - programs in the AltOS software suite. - - - TeleMini can be communicated with through a TeleDongle device - over the radio link. When first booted, TeleMini listens for a - TeleDongle device and if it receives a packet, it goes into - 'idle' mode. Otherwise, it goes into 'pad' mode and waits to be - launched. The easiest way to get it talking is to start the - communication link on the TeleDongle and the power up the - TeleMini board. - - - To access the device's firmware for configuration you need a terminal - program such as you would use to talk to a modem. The software - authors prefer using the program 'cu' which comes from the UUCP package - on most Unix-like systems such as Linux. An example command line for - cu might be 'cu -l /dev/ttyACM0', substituting the correct number - indicated from running the - ao-list program. Another reasonable terminal program for Linux is - 'cutecom'. The default 'escape' - character used by CU (i.e. the character you use to - issue commands to cu itself instead of sending the command as input - to the connected device) is a '~'. You will need this for use in - only two different ways during normal operations. First is to exit - the program by sending a '~.' which is called a 'escape-disconnect' - and allows you to close-out from 'cu'. The - second use will be outlined later. - - - All of the Altus Metrum devices share the concept of a two level - command set in their firmware. - The first layer has several single letter commands. Once - you are using 'cu' (or 'cutecom') sending (typing) a '?' - returns a full list of these - commands. The second level are configuration sub-commands accessed - using the 'c' command, for - instance typing 'c?' will give you this second level of commands - (all of which require the - letter 'c' to access). Please note that most configuration options - are stored only in Flash memory; TeleDongle doesn't provide any storage - for these options and so they'll all be lost when you unplug it. + All Altus Metrum products are sophisticated electronic device. When handled gently and + properly installed in an airframe, theywill deliver impressive results. + However, like all electronic devices, there are some precautions you + must take. - Try setting these config ('c' or second level menu) values. A good - place to start is by setting your call sign. By default, the boards - use 'N0CALL' which is cute, but not exactly legal! - Spend a few minutes getting comfortable with the units, their - firmware, and 'cu' (or possibly 'cutecom'). - For instance, try to send - (type) a 'c r 2' and verify the channel change by sending a 'c s'. - Verify you can connect and disconnect from the units while in your - terminal program by sending the escape-disconnect mentioned above. + The Lithium Polymer rechargeable batteries have an + extraordinary power density. This is great because we can fly with + much less battery mass than if we used alkaline batteries or previous + generation rechargeable batteries... but if they are punctured + or their leads are allowed to short, they can and will release their + energy very rapidly! + Thus we recommend that you take some care when handling our batteries + and consider giving them some extra protection in your airframe. We + often wrap them in suitable scraps of closed-cell packing foam before + strapping them down, for example. - Note that the 'reboot' command, which is very useful on the altimeters, - will likely just cause problems with the dongle. The *correct* way - to reset the dongle is just to unplug and re-plug it. + The barometric sensor is sensitive to sunlight. In normal + mounting situations, it and all of the other surface mount components + are "down" towards whatever the underlying mounting surface is, so + this is not normally a problem. Please consider this, though, when + designing an installation, for example, in an airframe with a + see-through plastic payload bay. - A fun thing to do at the launch site and something you can do while - learning how to use these units is to play with the rf-link access - between an altimeter and the TeleDongle. Be aware that you *must* create - some physical separation between the devices, otherwise the link will - not function due to signal overload in the receivers in each device. + The barometric sensor sampling port must be able to + "breathe", + both by not being covered by foam or tape or other materials that might + directly block the hole on the top of the sensor, but also by having a + suitable static vent to outside air. - Now might be a good time to take a break and read the rest of this - manual, particularly about the two "modes" that the altimeters - can be placed in. TeleMetrum uses the position of the device when booting - up will determine whether the unit is in "pad" or "idle" mode. TeleMini - enters "idle" mode when it receives a command packet within the first 5 seconds - of being powered up, otherwise it enters "pad" mode. + As with all other rocketry electronics, Altus Metrum altimeters must be protected + from exposure to corrosive motor exhaust and ejection charge gasses. + + + Hardware Overview - You can access an altimeter in idle mode from the Teledongle's USB - connection using the rf link - by issuing a 'p' command to the TeleDongle. Practice connecting and - disconnecting ('~~' while using 'cu') from the altimeter. If - you cannot escape out of the "p" command, (by using a '~~' when in - CU) then it is likely that your kernel has issues. Try a newer version. + TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to + fit inside coupler for 29mm airframe tubing, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMetrum should have at least 10 inches of interior length. - Using this rf link allows you to configure the altimeter, test - fire e-matches and igniters from the flight line, check pyro-match - continuity and so forth. You can leave the unit turned on while it - is in 'idle mode' and then place the - rocket vertically on the launch pad, walk away and then issue a - reboot command. The altimeter will reboot and start sending data - having changed to the "pad" mode. If the TeleDongle is not receiving - this data, you can disconnect 'cu' from the Teledongle using the - procedures mentioned above and THEN connect to the TeleDongle from - inside 'ao-view'. If this doesn't work, disconnect from the - TeleDongle, unplug it, and try again after plugging it back in. + TeleMini is a 0.5 inch by 1.5 inch circuit board. It was designed to + fit inside an 18mm airframe tube, but using it in a tube that + small in diameter may require some creativity in mounting and wiring + to succeed! The default 1/4 + wave UHF wire antenna attached to the center of the nose-cone end of + the board is about 7 inches long, and wiring for a power switch and + the e-matches for apogee and main ejection charges depart from the + fin can end of the board. Given all this, an ideal "simple" avionics + bay for TeleMini should have at least 9 inches of interior length. - On TeleMetrum, the GPS will eventually find enough satellites, lock in on them, - and 'ao-view' will both auditorially announce and visually indicate - that GPS is ready. - Now you can launch knowing that you have a good data path and - good satellite lock for flight data and recovery. Remember - you MUST tell ao-view to connect to the TeleDongle explicitly in - order for ao-view to be able to receive data. + A typical TeleMetrum or TeleMini installation using the on-board devices and + default wire UHF antenna involves attaching only a suitable + Lithium Polymer battery, a single pole switch for power on/off, and + two pairs of wires connecting e-matches for the apogee and main ejection + charges. - The altimeters provide RDF (radio direction finding) tones on - the pad, during descent and after landing. These can be used to - locate the rocket using a directional antenna; the signal - strength providing an indication of the direction from receiver to rocket. + By default, we use the unregulated output of the LiPo battery directly + to fire ejection charges. This works marvelously with standard + low-current e-matches like the J-Tek from MJG Technologies, and with + Quest Q2G2 igniters. However, if you + want or need to use a separate pyro battery, check out the "External Pyro Battery" + section in this manual for instructions on how to wire that up. The + altimeters are designed to work with an external pyro battery of up to 15V. - TeleMetrum also provides GPS trekking data, which can further simplify - locating the rocket once it has landed. (The last good GPS data - received before touch-down will be on the data screen of 'ao-view'.) + Ejection charges are wired directly to the screw terminal block + at the aft end of the altimeter. This is very similar to what + most other altimeter vendors provide and so may be the most + familiar option. You'll need a very small straight blade + screwdriver to connect and disconnect the board in this case, + such as you might find in a jeweler's screwdriver set. - Once you have recovered the rocket you can download the eeprom - contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over - either a USB cable or over the radio link using TeleDongle. - And by following the man page for 'ao-postflight' you can create - various data output reports, graphs, and even kml data to see the - flight trajectory in google-earth. (Moving the viewing angle making - sure to connect the yellow lines while in google-earth is the proper - technique.) + TeleMetrum also uses the screw terminal block for the power + switch leads. On TeleMini, the power switch leads are soldered + directly to the board and can be connected directly to the switch. - As for ao-view.... some things are in the menu but don't do anything - very useful. The developers have stopped working on ao-view to focus - on a new, cross-platform ground station program. So ao-view may or - may not be updated in the future. Mostly you just use - the Log and Device menus. It has a wonderful display of the incoming - flight data and I am sure you will enjoy what it has to say to you - once you enable the voice output! + For most airframes, the integrated antennas are more than + adequate However, if you are installing in a carbon-fiber + electronics bay which is opaque to RF signals, you may need to + use off-board external antennas instead. In this case, you can + order an altimeter with an SMA connector for the UHF antenna + connection, and, on TeleMetrum, you can unplug the integrated GPS + antenna and select an appropriate off-board GPS antenna with + cable terminating in a U.FL connector. + + + System Operation
- FAQ - - TeleMetrum seems to shut off when disconnected from the - computer. Make sure the battery is adequately charged. Remember the - unit will pull more power than the USB port can deliver before the - GPS enters "locked" mode. The battery charges best when TeleMetrum - is turned off. - + Firmware Modes - It's impossible to stop the TeleDongle when it's in "p" mode, I have - to unplug the USB cable? Make sure you have tried to "escape out" of - this mode. If this doesn't work the reboot procedure for the - TeleDongle *is* to simply unplug it. 'cu' however will retain it's - outgoing buffer IF your "escape out" ('~~') does not work. - At this point using either 'ao-view' (or possibly - 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed - communication. + The AltOS firmware build for the altimeters has two + fundamental modes, "idle" and "flight". Which of these modes + the firmware operates in is determined at startup time. For + TeleMetrum, the mode is controlled by the orientation of the + rocket (well, actually the board, of course...) at the time + power is switched on. If the rocket is "nose up", then + TeleMetrum assumes it's on a rail or rod being prepared for + launch, so the firmware chooses flight mode. However, if the + rocket is more or less horizontal, the firmware instead enters + idle mode. For TeleMini, "idle" mode is selected when the + board receives a command packet within the first five seconds + of operation; if no packet is received, the board enters + "flight" mode. - The amber LED (on the TeleMetrum) lights up when both - battery and USB are connected. Does this mean it's charging? - Yes, the yellow LED indicates the charging at the 'regular' rate. - If the led is out but the unit is still plugged into a USB port, - then the battery is being charged at a 'trickle' rate. + At power on, you will hear three beeps or see three flashes + ("S" in Morse code for startup) and then a pause while + the altimeter completes initialization and self tests, and decides which + mode to enter next. - There are no "dit-dah-dah-dit" sound or lights like the manual mentions? - That's the "pad" mode. Weak batteries might be the problem. - It is also possible that the Telemetrum is horizontal and the output - is instead a "dit-dit" meaning 'idle'. For TeleMini, it's possible that - it received a command packet which would have left it in "pad" mode. + In flight or "pad" mode, the altimeter engages the flight + state machine, goes into transmit-only mode on the RF link + sending telemetry, and waits for launch to be detected. + Flight mode is indicated by an "di-dah-dah-dit" ("P" for pad) + on the beeper or lights, followed by beeps or flashes + indicating the state of the pyrotechnic igniter continuity. + One beep/flash indicates apogee continuity, two beeps/flashes + indicate main continuity, three beeps/flashes indicate both + apogee and main continuity, and one longer "brap" sound or + rapidly alternating lights indicates no continuity. For a + dual deploy flight, make sure you're getting three beeps or + flashes before launching! For apogee-only or motor eject + flights, do what makes sense. - It's unclear how to use 'ao-view' and other programs when 'cu' - is running. You cannot have more than one program connected to - the TeleDongle at one time without apparent data loss as the - incoming data will not make it to both programs intact. - Disconnect whatever programs aren't currently being used. + In idle mode, you will hear an audible "di-dit" or see two short flashes ("I" for idle), and + the normal flight state machine is disengaged, thus + no ejection charges will fire. The altimeters also listen on the RF + link when in idle mode for packet mode requests sent from TeleDongle. + Commands can be issued to a TeleMetrum in idle mode over either + USB or the RF link equivalently. TeleMini uses only the RF link. + Idle mode is useful for configuring the altimeter, for extracting data + from the on-board storage chip after flight, and for ground testing + pyro charges. - How do I save flight data? - Live telemetry is written to file(s) whenever 'ao-view' is connected - to the TeleDongle. The file area defaults to ~/altos - but is easily changed using the menus in 'ao-view'. The files that - are written end in '.telem'. The after-flight - data-dumped files will end in .eeprom and represent continuous data - unlike the rf-linked .telem files that are subject to the - turnarounds/data-packaging time slots in the half-duplex rf data path. - See the above instructions on what and how to save the eeprom stored - data after physically retrieving your TeleMetrum. Make sure to save - the on-board data after each flight, as the current firmware will - over-write any previous flight data during a new flight. + One "neat trick" of particular value when the altimeter is used with very + large airframes, is that you can power the board up while the rocket + is horizontal, such that it comes up in idle mode. Then you can + raise the airframe to launch position, use a TeleDongle to open + a packet connection, and issue a 'reset' command which will cause + the altimeter to reboot and come up in + flight mode. This is much safer than standing on the top step of a + rickety step-ladder or hanging off the side of a launch tower with + a screw-driver trying to turn on your avionics before installing + igniters!
-
- - Specifications
- TeleMetrum Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - 1-axis high-g accelerometer for motor characterization, capable of - +/- 50g using default part. - - - - - On-board, integrated GPS receiver with 5hz update rate capability. - - - - - On-board 1 megabyte non-volatile memory for flight data storage. - - - - - USB interface for battery charging, configuration, and data recovery. - - - - - Fully integrated support for LiPo rechargeable batteries. - - - - - Uses LiPo to fire e-matches, can be modiied to support - optional separate pyro battery if needed. - - - - - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. - - - + GPS + + TeleMetrum includes a complete GPS receiver. See a later section for + a brief explanation of how GPS works that will help you understand + the information in the telemetry stream. The bottom line is that + the TeleMetrum GPS receiver needs to lock onto at least four + satellites to obtain a solid 3 dimensional position fix and know + what time it is! + + + TeleMetrum provides backup power to the GPS chip any time a LiPo + battery is connected. This allows the receiver to "warm start" on + the launch rail much faster than if every power-on were a "cold start" + for the GPS receiver. In typical operations, powering up TeleMetrum + on the flight line in idle mode while performing final airframe + preparation will be sufficient to allow the GPS receiver to cold + start and acquire lock. Then the board can be powered down during + RSO review and installation on a launch rod or rail. When the board + is turned back on, the GPS system should lock very quickly, typically + long before igniter installation and return to the flight line are + complete. +
- TeleMini Specifications - - - - Recording altimeter for model rocketry. - - - - - Supports dual deployment (can fire 2 ejection charges). - - - - - 70cm ham-band transceiver for telemetry downlink. - - - - - Barometric pressure sensor good to 45k feet MSL. - - - - - On-board 5 kilobyte non-volatile memory for flight data storage. - - - - - RF interface for battery charging, configuration, and data recovery. - - - - - Support for LiPo rechargeable batteries, using an external charger. - - - - - Uses LiPo to fire e-matches, can be modiied to support - optional separate pyro battery if needed. - - - - - 1.5 x .5 inch board designed to fit inside 18mm airframe coupler tube. - - - -
-
- - Handling Precautions - - All Altus Metrum products are sophisticated electronic device. When handled gently and - properly installed in an airframe, theywill deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. - - - The Lithium Polymer rechargeable batteries have an - extraordinary power density. This is great because we can fly with - much less battery mass than if we used alkaline batteries or previous - generation rechargeable batteries... but if they are punctured - or their leads are allowed to short, they can and will release their - energy very rapidly! - Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We - often wrap them in suitable scraps of closed-cell packing foam before - strapping them down, for example. - - - The barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components - are "down" towards whatever the underlying mounting surface is, so - this is not normally a problem. Please consider this, though, when - designing an installation, for example, in an airframe with a - see-through plastic payload bay. - - - The barometric sensor sampling port must be able to - "breathe", - both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a - suitable static vent to outside air. - - - As with all other rocketry electronics, Altus Metrum altimeters must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. - - - - Hardware Overview - - TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMetrum should have at least 10 inches of interior length. - - - TeleMini is a 0.5 inch by 1.5 inch circuit board. It was designed to - fit inside an 18mm airframe tube, but using it in a tube that - small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and - the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics - bay for TeleMini should have at least 9 inches of interior length. - - - A typical TeleMetrum or TeleMini installation using the on-board devices and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. - - - By default, we use the unregulated output of the LiPo battery directly - to fire ejection charges. This works marvelously with standard - low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, check out the "External Pyro Battery" - section in this manual for instructions on how to wire that up. The - altimeters are designed to work with an external pyro battery of up to 15V. - - - Ejection charges are wired directly to the screw terminal block - at the aft end of the altimeter. This is very similar to what - most other altimeter vendors provide and so may be the most - familiar option. You'll need a very small straight blade - screwdriver to connect and disconnect the board in this case, - such as you might find in a jeweler's screwdriver set. - - - TeleMetrum also uses the screw terminal block for the power - switch leads. On TeleMini, the power switch leads are soldered - directly to the board and can be connected directly to the switch. - - - For most airframes, the integrated antennas are more than - adequate However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to - use off-board external antennas instead. In this case, you can - order an altimeter with an SMA connector for the UHF antenna - connection, and, on TeleMetrum, you can unplug the integrated GPS - antenna and select an appropriate off-board GPS antenna with - cable terminating in a U.FL connector. - - - - System Operation -
- Firmware Modes - - The AltOS firmware build for the altimeters has two - fundamental modes, "idle" and "flight". Which of these modes - the firmware operates in is determined at startup time. For - TeleMetrum, the mode is controlled by the orientation of the - rocket (well, actually the board, of course...) at the time - power is switched on. If the rocket is "nose up", then - TeleMetrum assumes it's on a rail or rod being prepared for - launch, so the firmware chooses flight mode. However, if the - rocket is more or less horizontal, the firmware instead enters - idle mode. For TeleMini, "idle" mode is selected when the - board receives a command packet within the first five seconds - of operation; if no packet is received, the board enters - "flight" mode. - - - At power on, you will hear three beeps or see three flashes - ("S" in Morse code for startup) and then a pause while - the altimeter completes initialization and self tests, and decides which - mode to enter next. - - - In flight or "pad" mode, the altimeter engages the flight - state machine, goes into transmit-only mode on the RF link - sending telemetry, and waits for launch to be detected. - Flight mode is indicated by an "di-dah-dah-dit" ("P" for pad) - on the beeper or lights, followed by beeps or flashes - indicating the state of the pyrotechnic igniter continuity. - One beep/flash indicates apogee continuity, two beeps/flashes - indicate main continuity, three beeps/flashes indicate both - apogee and main continuity, and one longer "brap" sound or - rapidly alternating lights indicates no continuity. For a - dual deploy flight, make sure you're getting three beeps or - flashes before launching! For apogee-only or motor eject - flights, do what makes sense. - - - In idle mode, you will hear an audible "di-dit" or see two short flashes ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. The altimeters also listen on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. TeleMini uses only the RF link. - Idle mode is useful for configuring the altimeter, for extracting data - from the on-board storage chip after flight, and for ground testing - pyro charges. - - - One "neat trick" of particular value when the altimeter is used with very - large airframes, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - the altimeter to reboot and come up in - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! - -
-
- GPS - - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! - - - TeleMetrum provides backup power to the GPS chip any time a LiPo - battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe - preparation will be sufficient to allow the GPS receiver to cold - start and acquire lock. Then the board can be powered down during - RSO review and installation on a launch rod or rail. When the board - is turned back on, the GPS system should lock very quickly, typically - long before igniter installation and return to the flight line are - complete. - -
-
- Ground Testing - - An important aspect of preparing a rocket using electronic deployment - for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum- or TeleMini- equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! - - - Just prep the rocket for flight, then power up the altimeter - in "idle" mode (placing airframe horizontal for TeleMetrum or - starting the RF packet connection for TeleMini). This will cause the - firmware to go into "idle" mode, in which the normal flight - state machine is disabled and charges will not fire without - manual command. Then, establish an RF packet connection from - a TeleDongle-equipped computer using the P command from a safe - distance. You can now command the altimeter to fire the apogee - or main charges to complete your testing. - - - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. - + Ground Testing + + An important aspect of preparing a rocket using electronic deployment + for flight is ground testing the recovery system. Thanks + to the bi-directional RF link central to the Altus Metrum system, + this can be accomplished in a TeleMetrum- or TeleMini- equipped rocket without as + much work as you may be accustomed to with other systems. It can + even be fun! + + + Just prep the rocket for flight, then power up the altimeter + in "idle" mode (placing airframe horizontal for TeleMetrum or + starting the RF packet connection for TeleMini). This will cause the + firmware to go into "idle" mode, in which the normal flight + state machine is disabled and charges will not fire without + manual command. Then, establish an RF packet connection from + a TeleDongle-equipped computer using the P command from a safe + distance. You can now command the altimeter to fire the apogee + or main charges to complete your testing. + + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. +
Radio Link @@ -918,9 +606,6 @@ NAR #88757, TRA #12200
- - -
Updating Device Firmware @@ -1159,92 +844,6 @@ NAR #88757, TRA #12200 is split into chapters, each of which documents one of the tasks provided from the top-level toolbar. -
- Packet Command Mode - Controlling An Altimeter Over The Radio Link - - One of the unique features of the Altus Metrum environment is - the ability to create a two way command link between TeleDongle - and an altimeter using the digital radio transceivers built into - each device. This allows you to interact with the altimeter from - afar, as if it were directly connected to the computer. - - - Any operation which can be performed with TeleMetrum - can either be done with TeleMetrum directly connected to - the computer via the USB cable, or through the packet - link. Simply select the appropriate TeleDongle device when - the list of devices is presented and AltosUI will use packet - command mode. - - - One oddity in the current interface is how AltosUI selects the - frequency for packet mode communications. Instead of providing - an interface to specifically configure the frequency, it uses - whatever frequency was most recently selected for the target - TeleDongle device in Monitor Flight mode. If you haven't ever - used that mode with the TeleDongle in question, select the - Monitor Flight button from the top level UI, pick the - appropriate TeleDongle device. Once the flight monitoring - window is open, select the desired frequency and then close it - down again. All Packet Command Mode operations will now use - that frequency. - - - - - Save Flight Data—Recover flight data from the rocket without - opening it up. - - - - - Configure altimeter apogee delays or main deploy heights - to respond to changing launch conditions. You can also - 'reboot' the altimeter. Use this to remotely enable the - flight computer by turning TeleMetrum on in "idle" mode, - then once the airframe is oriented for launch, you can - reboot the altimeter and have it restart in pad mode - without having to climb the scary ladder. - - - - - Fire Igniters—Test your deployment charges without snaking - wires out through holes in the airframe. Simply assembly the - rocket as if for flight with the apogee and main charges - loaded, then remotely command the altimeter to fire the - igniters. - - - - - Packet command mode uses the same RF frequencies as telemetry - mode. Configure the desired TeleDongle frequency using the - flight monitor window frequency selector and then close that - window before performing the desired operation. - - - TeleMetrum only enables packet command mode in 'idle' mode, so - make sure you have TeleMetrum lying horizontally when you turn - it on. Otherwise, TeleMetrum will start in 'pad' mode ready for - flight and will not be listening for command packets from TeleDongle. - - - TeleMini listens for a command packet for five seconds after - first being turned on, if it doesn't hear anything, it enters - 'pad' mode, ready for flight and will no longer listen for - command packets. - - - When packet command mode is enabled, you can monitor the link - by watching the lights on the - devices. The red LED will flash each time they - transmit a packet while the green LED will light up - on TeleDongle while it is waiting to receive a packet from - the altimeter. - -
Monitor Flight Receive, Record and Display Telemetry Data @@ -1484,19 +1083,105 @@ NAR #88757, TRA #12200
- Save Flight Data - - The altimeter records flight data to its internal flash memory. - The TeleMetrum data is recorded at a much higher rate than the telemetry - system can handle, and is not subject to radio drop-outs. As - such, it provides a more complete and precise record of the - flight. The 'Save Flight Data' button allows you to read the - flash memory and write it to disk. As TeleMini has only a barometer, it - records data at the same rate as the telemetry signal, but there will be - no data lost due to telemetry drop-outs. - + Packet Command Mode + Controlling An Altimeter Over The Radio Link - Clicking on the 'Save Flight Data' button brings up a list of + One of the unique features of the Altus Metrum environment is + the ability to create a two way command link between TeleDongle + and an altimeter using the digital radio transceivers built into + each device. This allows you to interact with the altimeter from + afar, as if it were directly connected to the computer. + + + Any operation which can be performed with TeleMetrum + can either be done with TeleMetrum directly connected to + the computer via the USB cable, or through the packet + link. Simply select the appropriate TeleDongle device when + the list of devices is presented and AltosUI will use packet + command mode. + + + One oddity in the current interface is how AltosUI selects the + frequency for packet mode communications. Instead of providing + an interface to specifically configure the frequency, it uses + whatever frequency was most recently selected for the target + TeleDongle device in Monitor Flight mode. If you haven't ever + used that mode with the TeleDongle in question, select the + Monitor Flight button from the top level UI, pick the + appropriate TeleDongle device. Once the flight monitoring + window is open, select the desired frequency and then close it + down again. All Packet Command Mode operations will now use + that frequency. + + + + + Save Flight Data—Recover flight data from the rocket without + opening it up. + + + + + Configure altimeter apogee delays or main deploy heights + to respond to changing launch conditions. You can also + 'reboot' the altimeter. Use this to remotely enable the + flight computer by turning TeleMetrum on in "idle" mode, + then once the airframe is oriented for launch, you can + reboot the altimeter and have it restart in pad mode + without having to climb the scary ladder. + + + + + Fire Igniters—Test your deployment charges without snaking + wires out through holes in the airframe. Simply assembly the + rocket as if for flight with the apogee and main charges + loaded, then remotely command the altimeter to fire the + igniters. + + + + + Packet command mode uses the same RF frequencies as telemetry + mode. Configure the desired TeleDongle frequency using the + flight monitor window frequency selector and then close that + window before performing the desired operation. + + + TeleMetrum only enables packet command mode in 'idle' mode, so + make sure you have TeleMetrum lying horizontally when you turn + it on. Otherwise, TeleMetrum will start in 'pad' mode ready for + flight and will not be listening for command packets from TeleDongle. + + + TeleMini listens for a command packet for five seconds after + first being turned on, if it doesn't hear anything, it enters + 'pad' mode, ready for flight and will no longer listen for + command packets. + + + When packet command mode is enabled, you can monitor the link + by watching the lights on the + devices. The red LED will flash each time they + transmit a packet while the green LED will light up + on TeleDongle while it is waiting to receive a packet from + the altimeter. + +
+
+ Save Flight Data + + The altimeter records flight data to its internal flash memory. + The TeleMetrum data is recorded at a much higher rate than the telemetry + system can handle, and is not subject to radio drop-outs. As + such, it provides a more complete and precise record of the + flight. The 'Save Flight Data' button allows you to read the + flash memory and write it to disk. As TeleMini has only a barometer, it + records data at the same rate as the telemetry signal, but there will be + no data lost due to telemetry drop-outs. + + + Clicking on the 'Save Flight Data' button brings up a list of connected TeleMetrum and TeleDongle devices. If you select a TeleMetrum device, the flight data will be downloaded from that device directly. If you select a TeleDongle device, flight data @@ -1877,10 +1562,10 @@ NAR #88757, TRA #12200
Flash Image - This reprograms any Altus Metrum device by using a TeleMetrum or - TeleDongle as a programming dongle. Please read the directions - for connecting the programming cable in the main TeleMetrum - manual before reading these instructions. + This reprograms any Altus Metrum device by using a TeleMetrum + or TeleDongle as a programming dongle. Please read the + directions for flashing devices in the Updating Device + Firmware section above Once you have the programmer and target devices connected, @@ -2125,4 +1810,330 @@ NAR #88757, TRA #12200
+ + Hardware Specifications +
+ TeleMetrum Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + 1-axis high-g accelerometer for motor characterization, capable of + +/- 50g using default part. + + + + + On-board, integrated GPS receiver with 5hz update rate capability. + + + + + On-board 1 megabyte non-volatile memory for flight data storage. + + + + + USB interface for battery charging, configuration, and data recovery. + + + + + Fully integrated support for LiPo rechargeable batteries. + + + + + Uses LiPo to fire e-matches, can be modiied to support + optional separate pyro battery if needed. + + + + + 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + + + +
+
+ TeleMini Specifications + + + + Recording altimeter for model rocketry. + + + + + Supports dual deployment (can fire 2 ejection charges). + + + + + 70cm ham-band transceiver for telemetry downlink. + + + + + Barometric pressure sensor good to 45k feet MSL. + + + + + On-board 5 kilobyte non-volatile memory for flight data storage. + + + + + RF interface for battery charging, configuration, and data recovery. + + + + + Support for LiPo rechargeable batteries, using an external charger. + + + + + Uses LiPo to fire e-matches, can be modiied to support + optional separate pyro battery if needed. + + + + + 1.5 x .5 inch board designed to fit inside 18mm airframe coupler tube. + + + +
+
+ + FAQ + + TeleMetrum seems to shut off when disconnected from the + computer. Make sure the battery is adequately charged. Remember the + unit will pull more power than the USB port can deliver before the + GPS enters "locked" mode. The battery charges best when TeleMetrum + is turned off. + + + It's impossible to stop the TeleDongle when it's in "p" mode, I have + to unplug the USB cable? Make sure you have tried to "escape out" of + this mode. If this doesn't work the reboot procedure for the + TeleDongle *is* to simply unplug it. 'cu' however will retain it's + outgoing buffer IF your "escape out" ('~~') does not work. + At this point using either 'ao-view' (or possibly + 'cutemon') instead of 'cu' will 'clear' the issue and allow renewed + communication. + + + The amber LED (on the TeleMetrum) lights up when both + battery and USB are connected. Does this mean it's charging? + Yes, the yellow LED indicates the charging at the 'regular' rate. + If the led is out but the unit is still plugged into a USB port, + then the battery is being charged at a 'trickle' rate. + + + There are no "dit-dah-dah-dit" sound or lights like the manual mentions? + That's the "pad" mode. Weak batteries might be the problem. + It is also possible that the Telemetrum is horizontal and the output + is instead a "dit-dit" meaning 'idle'. For TeleMini, it's possible that + it received a command packet which would have left it in "pad" mode. + + + How do I save flight data? + Live telemetry is written to file(s) whenever AltosUI is connected + to the TeleDongle. The file area defaults to ~/TeleMetrum + but is easily changed using the menus in AltosUI. The files that + are written end in '.telem'. The after-flight + data-dumped files will end in .eeprom and represent continuous data + unlike the rf-linked .telem files that are subject to losses + along the rf data path. + See the above instructions on what and how to save the eeprom stored + data after physically retrieving your altimeter. Make sure to save + the on-board data after each flight; while the TeleMetrum can store + multiple flights, you never know when you'll lose the altimeter... + + + + Notes for Older Software + + + Before AltosUI was written, using Altus Metrum devices required + some finesse with the Linux command line. There was a limited + GUI tool, ao-view, which provided functionality similar to the + Monitor Flight window in AltosUI, but everything else was a + fairly 80's experience. This appendix includes documentation for + using that software. + + + + Both Telemetrum and TeleDongle can be directly communicated + with using USB ports. The first thing you should try after getting + both units plugged into to your computer's usb port(s) is to run + 'ao-list' from a terminal-window to see what port-device-name each + device has been assigned by the operating system. + You will need this information to access the devices via their + respective on-board firmware and data using other command line + programs in the AltOS software suite. + + + TeleMini can be communicated with through a TeleDongle device + over the radio link. When first booted, TeleMini listens for a + TeleDongle device and if it receives a packet, it goes into + 'idle' mode. Otherwise, it goes into 'pad' mode and waits to be + launched. The easiest way to get it talking is to start the + communication link on the TeleDongle and the power up the + TeleMini board. + + + To access the device's firmware for configuration you need a terminal + program such as you would use to talk to a modem. The software + authors prefer using the program 'cu' which comes from the UUCP package + on most Unix-like systems such as Linux. An example command line for + cu might be 'cu -l /dev/ttyACM0', substituting the correct number + indicated from running the + ao-list program. Another reasonable terminal program for Linux is + 'cutecom'. The default 'escape' + character used by CU (i.e. the character you use to + issue commands to cu itself instead of sending the command as input + to the connected device) is a '~'. You will need this for use in + only two different ways during normal operations. First is to exit + the program by sending a '~.' which is called a 'escape-disconnect' + and allows you to close-out from 'cu'. The + second use will be outlined later. + + + All of the Altus Metrum devices share the concept of a two level + command set in their firmware. + The first layer has several single letter commands. Once + you are using 'cu' (or 'cutecom') sending (typing) a '?' + returns a full list of these + commands. The second level are configuration sub-commands accessed + using the 'c' command, for + instance typing 'c?' will give you this second level of commands + (all of which require the + letter 'c' to access). Please note that most configuration options + are stored only in Flash memory; TeleDongle doesn't provide any storage + for these options and so they'll all be lost when you unplug it. + + + Try setting these config ('c' or second level menu) values. A good + place to start is by setting your call sign. By default, the boards + use 'N0CALL' which is cute, but not exactly legal! + Spend a few minutes getting comfortable with the units, their + firmware, and 'cu' (or possibly 'cutecom'). + For instance, try to send + (type) a 'c r 2' and verify the channel change by sending a 'c s'. + Verify you can connect and disconnect from the units while in your + terminal program by sending the escape-disconnect mentioned above. + + + Note that the 'reboot' command, which is very useful on the altimeters, + will likely just cause problems with the dongle. The *correct* way + to reset the dongle is just to unplug and re-plug it. + + + A fun thing to do at the launch site and something you can do while + learning how to use these units is to play with the rf-link access + between an altimeter and the TeleDongle. Be aware that you *must* create + some physical separation between the devices, otherwise the link will + not function due to signal overload in the receivers in each device. + + + Now might be a good time to take a break and read the rest of this + manual, particularly about the two "modes" that the altimeters + can be placed in. TeleMetrum uses the position of the device when booting + up will determine whether the unit is in "pad" or "idle" mode. TeleMini + enters "idle" mode when it receives a command packet within the first 5 seconds + of being powered up, otherwise it enters "pad" mode. + + + You can access an altimeter in idle mode from the Teledongle's USB + connection using the rf link + by issuing a 'p' command to the TeleDongle. Practice connecting and + disconnecting ('~~' while using 'cu') from the altimeter. If + you cannot escape out of the "p" command, (by using a '~~' when in + CU) then it is likely that your kernel has issues. Try a newer version. + + + Using this rf link allows you to configure the altimeter, test + fire e-matches and igniters from the flight line, check pyro-match + continuity and so forth. You can leave the unit turned on while it + is in 'idle mode' and then place the + rocket vertically on the launch pad, walk away and then issue a + reboot command. The altimeter will reboot and start sending data + having changed to the "pad" mode. If the TeleDongle is not receiving + this data, you can disconnect 'cu' from the Teledongle using the + procedures mentioned above and THEN connect to the TeleDongle from + inside 'ao-view'. If this doesn't work, disconnect from the + TeleDongle, unplug it, and try again after plugging it back in. + + + On TeleMetrum, the GPS will eventually find enough satellites, lock in on them, + and 'ao-view' will both auditorially announce and visually indicate + that GPS is ready. + Now you can launch knowing that you have a good data path and + good satellite lock for flight data and recovery. Remember + you MUST tell ao-view to connect to the TeleDongle explicitly in + order for ao-view to be able to receive data. + + + The altimeters provide RDF (radio direction finding) tones on + the pad, during descent and after landing. These can be used to + locate the rocket using a directional antenna; the signal + strength providing an indication of the direction from receiver to rocket. + + + TeleMetrum also provides GPS trekking data, which can further simplify + locating the rocket once it has landed. (The last good GPS data + received before touch-down will be on the data screen of 'ao-view'.) + + + Once you have recovered the rocket you can download the eeprom + contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over + either a USB cable or over the radio link using TeleDongle. + And by following the man page for 'ao-postflight' you can create + various data output reports, graphs, and even kml data to see the + flight trajectory in google-earth. (Moving the viewing angle making + sure to connect the yellow lines while in google-earth is the proper + technique.) + + + As for ao-view.... some things are in the menu but don't do anything + very useful. The developers have stopped working on ao-view to focus + on a new, cross-platform ground station program. So ao-view may or + may not be updated in the future. Mostly you just use + the Log and Device menus. It has a wonderful display of the incoming + flight data and I am sure you will enjoy what it has to say to you + once you enable the voice output! + + + + Release Notes + + + + + diff --git a/doc/release-notes-0.7.1.xsl b/doc/release-notes-0.7.1.xsl new file mode 100644 index 00000000..75158a02 --- /dev/null +++ b/doc/release-notes-0.7.1.xsl @@ -0,0 +1,57 @@ + + + +
+ +Version 0.7.1 is the first release containing our new cross-platform Java-based user interface. AltosUI can: + + + + Receive and log telemetry from a connected TeleDongle + device. All data received is saved to log files named with the + current date and the connected rocket serial and flight + numbers. There is no mode in which telemetry data will not be + saved. + + + Download logged data from TeleMetrum devices, either through a + direct USB connection or over the air through a TeleDongle + device. + + + Configure a TeleMetrum device, setting the radio channel, + callsign, apogee delay and main deploy height. This can be done + through either a USB connection or over a radio link via a + TeleDongle device. + + + Replay a flight in real-time. This takes a saved telemetry log + or eeprom download and replays it through the user interface so + you can relive your favorite rocket flights. + + + Reprogram Altus Metrum devices. Using an Altus Metrum device + connected via USB, another Altus Metrum device can be + reprogrammed using the supplied programming cable between the + two devices. + + + Export Flight data to a comma-separated-values file. This takes + either telemetry or on-board flight data and generates data + suitable for use in external applications. All data is exported + using standard units so that no device-specific knowledge is + needed to handle the data. + + + Speak to you during the flight. Instead of spending the flight + hunched over your laptop looking at the screen, enjoy the view + while the computer tells you what’s going on up there. During + ascent, you hear the current flight state and altitude + information. During descent, you get azimuth, elevation and + range information to try and help you find your rocket in the + air. Once on the ground, the direction and distance are + reported. + + +
diff --git a/doc/release-notes-0.8.xsl b/doc/release-notes-0.8.xsl new file mode 100644 index 00000000..c54f97e9 --- /dev/null +++ b/doc/release-notes-0.8.xsl @@ -0,0 +1,56 @@ + + + +
+ + Version 0.8 offers a major upgrade in the AltosUI + interface. Significant new features include: + + + + Post-flight graphing tool. This lets you explore the behaviour + of your rocket after flight with a scroll-able and zoom-able + chart showing the altitude, speed and acceleration of the + airframe along with events recorded by the flight computer. You + can export graphs to PNG files, or print them directly. + + + Real-time moving map which overlays the in-progress flight on + satellite imagery fetched from Google Maps. This lets you see in + pictures where your rocket has landed, allowing you to plan + recovery activities more accurately. + + + Wireless recovery system testing. Prep your rocket for flight + and test fire the deployment charges to make sure things work as + expected. All without threading wires through holes in your + airframe. + + + Optimized flight status displays. Each flight state now has it's + own custom 'tab' in the flight monitoring window so you can + focus on the most important details. Pre-flight, the system + shows a set of red/green status indicators for battery voltage, + apogee/main igniter continutity and GPS reception. Wait until + they're all green and your rocket is ready for flight. There are + also tabs for ascent, descent and landing along with the + original tabular view of the data. + + + Monitor multiple flights simultaneously. If you have more than + one TeleDongle, you can monitor a flight with each one on the + same computer. + + + Automatic flight monitoring at startup. Plug TeleDongle into the + machine before starting AltosUI and it will automatically + connect to it and prepare to monitor a flight. + + + Exports Google Earth flight tracks. Using the Keyhole Markup + Language (.kml) file format, this provides a 3D view of your + rocket flight through the Google Earth program. + + +
diff --git a/doc/release-notes-0.9.2.xsl b/doc/release-notes-0.9.2.xsl new file mode 100644 index 00000000..e5f66c60 --- /dev/null +++ b/doc/release-notes-0.9.2.xsl @@ -0,0 +1,20 @@ + + + +
+ + Version 0.9.2 is an AltosUI bug-fix release, with no firmware changes. + + + + Fix plotting problems due to missing file in the Mac OS install image. + + + Always read whole eeprom blocks, mark empty records invalid, display parsing errors to user. + + + Add software version to Configure AltosUI dialog + + +
diff --git a/doc/release-notes-0.9.xsl b/doc/release-notes-0.9.xsl new file mode 100644 index 00000000..547f46b1 --- /dev/null +++ b/doc/release-notes-0.9.xsl @@ -0,0 +1,31 @@ + + + +
+ + Version 0.9 adds a few new firmware features and accompanying + AltosUI changes, along with new hardware support. + + + + Support for TeleMetrum v1.1 hardware. Sources for the flash + memory part used in v1.0 dried up, so v1.1 uses a different part + which required a new driver and support for explicit flight log + erasing. + + + Multiple flight log support. This stores more than one flight + log in the on-board flash memory. It also requires the user to + explicitly erase flights so that you won't lose flight logs just + because you fly the same board twice in one day. + + + Telemetry support for devices with serial number >= + 256. Previous versions used a telemetry packet format that + provided only 8 bits for the device serial number. This change + requires that both ends of the telemetry link be running the 0.9 + firmware or they will not communicate. + + +
-- cgit v1.2.3 From 566b16e67be38c6425e616a5c38d641c4e1a9b12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 10 Aug 2011 22:43:26 -0700 Subject: doc: Add 1.0 release notes. Signed-off-by: Keith Packard --- doc/Makefile | 8 +++- doc/altusmetrum.xsl | 1 + doc/release-notes-1.0.xsl | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 doc/release-notes-1.0.xsl diff --git a/doc/Makefile b/doc/Makefile index 6d9ea8eb..35858b15 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -6,7 +6,10 @@ RELNOTES=\ release-notes-0.7.1.html \ release-notes-0.8.html \ release-notes-0.9.html \ - release-notes-0.9.2.html + release-notes-0.9.2.html \ + release-notes-1.0.html + +RELNOTES_XSL=$(RELNOTES:.html=.xsl) HTML=altusmetrum.html altos.html telemetry.html $(RELNOTES) PDF=altusmetrum.pdf altos.pdf telemetry.pdf DOC=$(HTML) $(PDF) @@ -45,6 +48,9 @@ clean: distclean: rm -f $(HTML) $(PDF) *.fo +altusmetrum.html: $(RELNOTES_XSL) +altusmetrum.fo: $(RELNOTES_XSL) + indent: altusmetrum.xsl xmlindent -i 2 < altusmetrum.xsl > altusmetrum.new diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 88c9b80a..e97666ae 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -2131,6 +2131,7 @@ NAR #88757, TRA #12200 Release Notes + diff --git a/doc/release-notes-1.0.xsl b/doc/release-notes-1.0.xsl new file mode 100644 index 00000000..b42917c5 --- /dev/null +++ b/doc/release-notes-1.0.xsl @@ -0,0 +1,96 @@ + + + +
+ + Version 1.0 is a major release, adding support for the TeleMini + device and lots of new AltosUI features + + + AltOS Firmware Changes + + + Add TeleMini v1.0 support. Firmware images for TeleMini are + included in AltOS releases. + + + Change telemetry to be encoded in multiple 32-byte packets. This + enables support for TeleMini and other devices without requiring + further updates to the TeleDongle firmware. + + + Support operation of TeleMetrum with the antenna pointing + aft. Previous firmware versions required the antenna to be + pointing upwards, now there is a configuration option allowing + the antenna to point aft, to aid installation in some airframes. + + + Arbitrary frequency selection. The radios in Altus Metrum + devices can be programmed to a wide range of frequencies, so + instead of limiting devices to 10 pre-selected 'channels', the + new firmware allows the user to choose any frequency in the + 70cm band. Note that the RF matching circuit on the boards is + tuned for around 435MHz, so frequencies far from that may + reduce the available range. + + + Kalman-filter based flight-tracking. The model based sensor + fusion approach of a Kalman filter means that AltOS now + computes apogee much more accurately than before, generally + within a fraction of a second. In addition, this approach + allows the baro-only TeleMini device to correctly identify + Mach transitions, avoiding the error-prone selection of a Mach + delay. + + + + + AltosUI Changes + + + Wait for altimeter when using packet mode. Instead of quicly + timing out when trying to initialize a packet mode + configuration connection, AltosUI now waits indefinitely for + the remote device to appear, providing a cancel button should + the user get bored. This is necessary as the TeleMini can only + be placed in "Idle" mode if AltosUI is polling it. + + + Add main/apogee voltage graphs to the data plot. This provides + a visual indication if the igniters fail before being fired. + + + Scan for altimeter devices by watching the defined telemetry + frequencies. This avoids the problem of remembering what + frequency a device was configured to use, which is especially + important with TeleMini which does not include a USB connection. + + + Monitor altimeter state in "Idle" mode. This provides much of + the information presented in the "Pad" dialog from the Monitor + Flight command, monitoring the igniters, battery and GPS + status withing requiring the flight computer to be armed and + ready for flight. + + + Pre-load map images from home. For those launch sites which + don't provide free Wi-Fi, this allows you to download the + necessary satellite images given the location of the launch + site. A list of known launch sites is maintained at + altusmetrum.org which AltosUI downloads to populate a menu; if + you've got a launch site not on that list, please send the + name of it, latitude and longitude along with a link to the + web site of the controlling club to the altusmetrum mailing list. + + + Flight statistics are now displayed in the Graph data + window. These include max height/speed/accel, average descent + rates and a few other bits of information. The Graph Data + window can now be reached from the 'Landed' tab in the Monitor + Flight window so you can immediately see the results of a + flight. + + + +
-- cgit v1.2.3 From b520c32bcddabd42c07ceafa827694a3ae23a76f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 15:57:58 -0700 Subject: altos: Pull igniter pins low as soon as possible at boot time This reduces the pulse width on the igniter circuit caused by the default cc1111 pin configuration at powerup time. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_ignite.c | 8 +++++++- src/ao_telemetrum.c | 7 ++++++- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index bb3c80ec..0699fc2c 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1350,6 +1350,9 @@ enum ao_igniter_status { enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); +void +ao_ignite_set_pins(void); + void ao_igniter_init(void); diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 512ec622..5238beb4 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -202,11 +202,17 @@ __code struct ao_cmds ao_ignite_cmds[] = { __xdata struct ao_task ao_igniter_task; void -ao_igniter_init(void) +ao_ignite_set_pins(void) { AO_IGNITER_DROGUE = 0; AO_IGNITER_MAIN = 0; AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); ao_cmd_register(&ao_ignite_cmds[0]); ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 4ace415c..d9ea1fc8 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -28,8 +28,13 @@ ao_set_monitor(uint8_t monitoring) void main(void) { - ao_clock_init(); + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + ao_clock_init(); /* Turn on the red LED until the system is stable */ ao_led_init(LEDS_AVAILABLE); -- cgit v1.2.3 From 1d13460412046c53f36466193329caaa657bb278 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 15:59:47 -0700 Subject: altos: Apply igniter boot pulse-width reduction to telemini TeleMini needs the same fix as TeleMetrum to reduce startup igniter pulses. Signed-off-by: Keith Packard --- src/ao_telemini.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 19d03692..6c612481 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -28,8 +28,13 @@ ao_set_monitor(uint8_t monitoring) void main(void) { - ao_clock_init(); + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + ao_clock_init(); /* Turn on the red LED until the system is stable */ ao_led_init(LEDS_AVAILABLE); -- cgit v1.2.3 From 640422c028a2be898aa3a9048a0f6fad2e43dd8d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 16:11:34 -0700 Subject: altos: remove monitor disable stubs from altimeter code Monitor mode in the ground-station boards must be disabled when the radio is going to be used for another purpose, or the radio parameters changed. That places monitor-mode disable calls in other parts of the system which are shared with the altimeter code. Elide the ao_set_monitor calls for builds which do not include any monitoring code. Signed-off-by: Keith Packard --- src/ao_monitor.c | 4 ++++ src/ao_packet_master.c | 2 ++ src/ao_pins.h | 13 +++++++++++++ src/ao_radio.c | 2 ++ src/ao_telemetrum.c | 7 ------- src/ao_telemini.c | 7 ------- src/ao_telenano.c | 7 ------- 7 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 8f1b9e12..69eb58e8 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -18,6 +18,10 @@ #include "ao.h" #include "ao_telem.h" +#if !HAS_MONITOR +#error Must define HAS_MONITOR to 1 +#endif + __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index e721ffba..b0fdf5a8 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -109,7 +109,9 @@ ao_packet_forward(void) __reentrant ao_cmd_white(); flush(); +#if HAS_MONITOR ao_set_monitor(0); +#endif ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); while ((c = getchar()) != '~') { diff --git a/src/ao_pins.h b/src/ao_pins.h index bc07ad54..89907b9c 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -42,6 +42,7 @@ #define HAS_ACCEL_REF 0 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEMETRUM_V_1_1) @@ -72,6 +73,7 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEDONGLE_V_0_2) @@ -95,6 +97,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TELEMINI_V_1_0) @@ -120,6 +123,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELENANO_V_0_1) @@ -144,6 +148,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define HAS_MONITOR 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -172,6 +177,7 @@ #define SPI_CS_ON_P0 0 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEDONGLE_V_0_1) @@ -195,6 +201,7 @@ #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TIDONGLE) @@ -217,6 +224,7 @@ #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TELEBT_V_0_0) @@ -245,6 +253,7 @@ #define BT_LINK_ON_P1 0 #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 #endif #if defined(TELEBT_V_0_1) @@ -280,6 +289,7 @@ #define BT_LINK_ON_P1 1 #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 #endif #if DBG_ON_P1 @@ -376,4 +386,7 @@ #error Please define PACKET_HAS_SLAVE #endif +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif #endif /* _AO_PINS_H_ */ diff --git a/src/ao_radio.c b/src/ao_radio.c index 1fb0eea6..00816b33 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,7 +432,9 @@ ao_radio_test(void) } mode++; if ((mode & 2) && !radio_on) { +#if HAS_MONITOR ao_set_monitor(0); +#endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); #endif diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index d9ea1fc8..6fa70b3a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemetrum doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 6c612481..fa23de01 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemini doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { diff --git a/src/ao_telenano.c b/src/ao_telenano.c index 40822b6e..d91983d0 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemini doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { -- cgit v1.2.3 From 3b87dd6f46922cf5f98deb2dffa2148c4244e48e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 15:00:14 -0700 Subject: ao-tools: ao-list was crashing with more than 3 devices connected the list of devices was getting realloced for each new device, but that realloc was too small. Signed-off-by: Keith Packard --- ao-tools/lib/cc-usbdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-tools/lib/cc-usbdev.c b/ao-tools/lib/cc-usbdev.c index afa91d49..a19e231c 100644 --- a/ao-tools/lib/cc-usbdev.c +++ b/ao-tools/lib/cc-usbdev.c @@ -223,7 +223,7 @@ cc_usbdevs_scan(void) if (dev->idVendor == 0xfffe && dev->tty) { if (devs->dev) devs->dev = realloc(devs->dev, - devs->ndev + 1 * sizeof (struct usbdev *)); + (devs->ndev + 1) * sizeof (struct usbdev *)); else devs->dev = malloc (sizeof (struct usbdev *)); devs->dev[devs->ndev++] = dev; -- cgit v1.2.3 From 313d740b5284b24f1cc7a1ba5779136b55d49ebe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:33:07 -0700 Subject: libaltos: Mis-allocated device list in libaltos Would overrun mis-allocated array, causing chaos. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 00a75de9..f2c8bd8d 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -559,7 +559,7 @@ altos_list_start(void) if (USB_IS_ALTUSMETRUM(dev->idVendor, dev->idProduct)) { if (devs->dev) devs->dev = realloc(devs->dev, - devs->ndev + 1 * sizeof (struct usbdev *)); + (devs->ndev + 1) * sizeof (struct usbdev *)); else devs->dev = malloc (sizeof (struct usbdev *)); devs->dev[devs->ndev++] = dev; -- cgit v1.2.3 From 7bcf25606cd5892d58295649f3d475d284494ee8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:26:09 -0700 Subject: altos: shrink text space from ao_config.c Eliminate redundant config initializers by setting minor to zero and letting upgrade code handle all of the new values. Stop computing (fake) frequency when showing radio channel Stop computing feet when showing main deploy height Signed-off-by: Keith Packard --- src/ao_config.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index a5796b03..36bd47c4 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -71,21 +71,11 @@ _ao_config_get(void) #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; - ao_config.minor = AO_CONFIG_MINOR; + ao_config.minor = 0; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - ao_config.accel_plus_g = 0; - ao_config.accel_minus_g = 0; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_cal = ao_radio_cal; - ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; - ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - ao_config.radio_setting = ao_radio_cal; - ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ @@ -159,12 +149,8 @@ ao_config_callsign_set(void) __reentrant void ao_config_radio_channel_show(void) __reentrant { - uint32_t freq = 434550L + ao_config.radio_channel * 100L; - uint16_t mhz = freq / 1000L; - uint16_t khz = freq % 1000L; - - printf("Radio channel: %d (%d.%03dMHz)\n", - ao_config.radio_channel, mhz, khz); + printf("Radio channel: %d\n", + ao_config.radio_channel); } void @@ -187,9 +173,8 @@ ao_config_radio_channel_set(void) __reentrant void ao_config_main_deploy_show(void) __reentrant { - printf("Main deploy: %d meters (%d feet)\n", - ao_config.main_deploy, - (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100)); + printf("Main deploy: %d meters\n", + ao_config.main_deploy); } void -- cgit v1.2.3 From c2f2f519dbc8ce233ab36222088c1be6b1362f01 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:28:38 -0700 Subject: altos: re-write a bit of GPS parsing code to reduce size Use a local variable while computing hdop. Place the next incoming character in data instead of pdata. Saved a surprising amount of memory. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index e7d1d2ef..7ac26946 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -24,7 +24,7 @@ static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; -static __pdata char ao_gps_char; +static __data char ao_gps_char; static __pdata uint8_t ao_gps_cksum; static __pdata uint8_t ao_gps_error; @@ -238,14 +238,14 @@ ao_nmea_gga() ao_gps_next.flags |= i; ao_gps_lexchar(); - ao_gps_next.hdop = ao_gps_decimal(0xff); - if (ao_gps_next.hdop <= 50) { - ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + i = ao_gps_decimal(0xff); + if (i <= 50) { + i = (uint8_t) 5 * i; if (ao_gps_char == '.') - ao_gps_next.hdop = (ao_gps_next.hdop + - ((uint8_t) ao_gps_decimal(1) >> 1)); + i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); } else - ao_gps_next.hdop = 255; + i = 255; + ao_gps_next.hdop = i; ao_gps_skip_field(); ao_gps_next.altitude = ao_gps_decimal(0xff); -- cgit v1.2.3 From bf06af154e232d4caa1585a1d6d5279a075292e4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 21:43:56 -0700 Subject: altos/altosui: Report log format in the version command This will make it easier to figure out what the contents of the flash should look like from altosui; the current 'guessing' mechanism will not scale to many more formats. Signed-off-by: Keith Packard --- altosui/Altos.java | 32 ++++++++++++++++++++++++++++++++ altosui/AltosConfig.java | 3 +++ altosui/AltosConfigData.java | 2 ++ altosui/AltosEepromDownload.java | 26 +++++++++++++------------- altosui/AltosEepromRecord.java | 3 +++ src/ao.h | 9 +++++++++ src/ao_cmd.c | 3 +++ src/ao_log.c | 2 ++ src/ao_log_tiny.c | 2 ++ src/ao_telebt.c | 2 ++ 10 files changed, 71 insertions(+), 13 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index 73dc7468..416d9328 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -51,6 +51,7 @@ public class Altos { static final int AO_LOG_MANUFACTURER = 2000; static final int AO_LOG_PRODUCT = 2001; static final int AO_LOG_SERIAL_NUMBER = 2002; + static final int AO_LOG_LOG_FORMAT = 2003; static final int AO_LOG_SOFTWARE_VERSION = 9999; /* Added to flag invalid records */ @@ -177,6 +178,13 @@ public class Altos { static final int AO_GPS_NUM_SAT_SHIFT = 0; static final int AO_GPS_NUM_SAT_MASK = 0xf; + static final int AO_LOG_FORMAT_UNKNOWN = 0; + static final int AO_LOG_FORMAT_FULL = 1; + static final int AO_LOG_FORMAT_TINY = 2; + static final int AO_LOG_FORMAT_TELEMETRY = 3; + static final int AO_LOG_FORMAT_TELESCIENCE = 4; + static final int AO_LOG_FORMAT_NONE = 127; + static boolean isspace(int c) { switch (c) { case ' ': @@ -404,12 +412,36 @@ public class Altos { return 0x000e; } + static int usb_product_telelaunch() { + load_library(); + return 0x000f; + } + + static int usb_product_telelco() { + load_library(); + return 0x0010; + } + + static int usb_product_telescience() { + load_library(); + return 0x0011; + } + + static int usb_product_telepyro() { + load_library(); + return 0x0012; + } + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); public final static int product_altusmetrum = usb_product_altusmetrum(); public final static int product_telemetrum = usb_product_telemetrum(); public final static int product_teledongle = usb_product_teledongle(); public final static int product_teleterra = usb_product_teleterra(); public final static int product_telebt = usb_product_telebt(); + public final static int product_telelaunch = usb_product_telelaunch(); + public final static int product_tele10 = usb_product_telelco(); + public final static int product_telescience = usb_product_telescience(); + public final static int product_telepyro = usb_product_telepyro(); public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 7312ea6c..ffabe209 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -67,6 +67,7 @@ public class AltosConfig implements ActionListener { AltosConfigData remote_config_data; double remote_frequency; int_ref serial; + int_ref log_format; int_ref main_deploy; int_ref apogee_delay; int_ref radio_channel; @@ -153,6 +154,7 @@ public class AltosConfig implements ActionListener { return; } get_int(line, "serial-number", serial); + get_int(line, "log-format", log_format); get_int(line, "Main deploy:", main_deploy); get_int(line, "Apogee delay:", apogee_delay); get_int(line, "Radio channel:", radio_channel); @@ -374,6 +376,7 @@ public class AltosConfig implements ActionListener { owner = given_owner; serial = new int_ref(0); + log_format = new int_ref(Altos.AO_LOG_FORMAT_UNKNOWN); main_deploy = new int_ref(250); apogee_delay = new int_ref(0); radio_channel = new int_ref(0); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 016033a3..710231d7 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -36,6 +36,7 @@ public class AltosConfigData implements Iterable { String manufacturer; String product; String version; + int log_format; int serial; /* Strings returned */ @@ -94,6 +95,7 @@ public class AltosConfigData implements Iterable { continue; lines.add(line); try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { log_format = get_int(line, "log-format"); } catch (Exception e) {} try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 64dcdff7..417aab00 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -89,9 +89,6 @@ public class AltosEepromDownload implements Runnable { } } - static final int log_full = 1; - static final int log_tiny = 2; - boolean done; int state; @@ -186,7 +183,7 @@ public class AltosEepromDownload implements Runnable { void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; - int log_style = 0; + int log_format = flights.config_data.log_format; state = 0; done = false; @@ -215,21 +212,24 @@ public class AltosEepromDownload implements Runnable { AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); /* - * Figure out what kind of data is there + * Guess what kind of data is there if the device + * didn't tell us */ - if (block == log.start_block) { - if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) - log_style = log_full; - else - log_style = log_tiny; + if (log_format == Altos.AO_LOG_FORMAT_UNKNOWN) { + if (block == log.start_block) { + if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) + log_format = Altos.AO_LOG_FORMAT_FULL; + else + log_format = Altos.AO_LOG_FORMAT_TINY; + } } - switch (log_style) { - case log_full: + switch (log_format) { + case Altos.AO_LOG_FORMAT_FULL: CaptureFull(eechunk); break; - case log_tiny: + case Altos.AO_LOG_FORMAT_TINY: CaptureTiny(eechunk); break; } diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 52acb435..c0f97035 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -143,6 +143,9 @@ public class AltosEepromRecord { } else if (tokens[0].equals("serial-number")) { cmd = Altos.AO_LOG_SERIAL_NUMBER; a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = Altos.AO_LOG_LOG_FORMAT; + a = Integer.parseInt(tokens[1]); } else if (tokens[0].equals("software-version")) { cmd = Altos.AO_LOG_SOFTWARE_VERSION; data = tokens[1]; diff --git a/src/ao.h b/src/ao.h index 0699fc2c..1c8f5bbf 100644 --- a/src/ao.h +++ b/src/ao.h @@ -539,6 +539,15 @@ extern __pdata enum flight_state ao_log_state; /* required functions from the underlying log system */ +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + /* Return the flight number from the given log slot, 0 if none */ uint16_t ao_log_flight(uint8_t slot); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 6d3ae38d..1442ebea 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -219,6 +219,9 @@ version(void) printf("manufacturer %s\n", ao_manufacturer); printf("product %s\n", ao_product); printf("serial-number %u\n", ao_serial_number); +#if HAS_EEPROM + printf("log-format %u\n", ao_log_format); +#endif printf("software-version %s\n", ao_version); } diff --git a/src/ao_log.c b/src/ao_log.c index 80d7243d..6d3ad535 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -24,6 +24,8 @@ __xdata uint8_t ao_log_running; __pdata enum flight_state ao_log_state; __xdata uint16_t ao_flight_number; +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + void ao_log_flush(void) { diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index d26e0080..d5a3b99f 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -28,6 +28,8 @@ static __data uint16_t ao_log_tiny_interval; #define AO_PAD_RING 2 #endif +__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; + void ao_log_tiny_set_interval(uint16_t ticks) { diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 8e77c4d9..85565172 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -17,6 +17,8 @@ #include "ao.h" +__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + void main(void) { -- cgit v1.2.3 From 578c4b17b8f62f2727654ebda78ee139f9fe13fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:38:38 -0700 Subject: altos: Don't try to use non-basestations for remote eeprom download Companion boards may also have eeprom data to fetch; don't try to use them as a radio. Signed-off-by: Keith Packard --- altosui/AltosEepromManage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index cd2b74fe..0652ca04 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -206,7 +206,7 @@ public class AltosEepromManage implements ActionListener { if (device != null) { try { serial_line = new AltosSerial(device); - if (!device.matchProduct(Altos.product_telemetrum)) + if (device.matchProduct(Altos.product_basestation)) remote = true; serial_line.set_frame(frame); -- cgit v1.2.3 From 30abbdc7ffcfc809b4a3fc31486fe968161ea225 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 16:59:16 -0700 Subject: altos: Add SPI-based companion board support This sends current flight state information and retrieves companion data to include in telemetry. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 +++ src/ao.h | 72 ++++++++++++++++++++++++++++- src/ao_companion.c | 96 +++++++++++++++++++++++++++++++++++++++ src/ao_ee.c | 14 +----- src/ao_flash.c | 14 +----- src/ao_m25.c | 4 +- src/ao_pins.h | 16 +++++++ src/ao_spi.c | 8 ++-- src/ao_telemetrum.c | 3 ++ src/ao_telemetry.c | 45 +++++++++++++++++- src/telemetrum-v1.0/Makefile.defs | 1 + src/telemetrum-v1.1/Makefile.defs | 1 + 12 files changed, 248 insertions(+), 32 deletions(-) create mode 100644 src/ao_companion.c diff --git a/src/Makefile.proto b/src/Makefile.proto index d4a8c4ea..8f98d354 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -150,6 +150,12 @@ SKY_DRIVER_SRC = \ BTM_DRIVER_SRC = \ ao_btm.c +# +# Companion port driver source +# +COMPANION_SRC = \ + ao_companion.c + # # Tasks run on TeleMetrum # diff --git a/src/ao.h b/src/ao.h index 1c8f5bbf..de47f3df 100644 --- a/src/ao.h +++ b/src/ao.h @@ -965,6 +965,34 @@ ao_serial_init(void); * ao_spi.c */ +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + void ao_spi_send(void __xdata *block, uint16_t len) __reentrant; @@ -1089,12 +1117,29 @@ struct ao_telemetry_satellite { /* 32 */ }; +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; struct ao_telemetry_configuration configuration; struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; }; /* @@ -1529,8 +1574,33 @@ ao_btm_isr(void) #endif ; - void ao_btm_init(void); +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + #endif /* _AO_H_ */ diff --git a/src/ao_companion.c b/src/ao_companion.c new file mode 100644 index 00000000..8db3273e --- /dev/null +++ b/src/ao_companion.c @@ -0,0 +1,96 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define COMPANION_SELECT() ao_spi_get_bit(COMPANION_CS) +#define COMPANION_DESELECT() ao_spi_put_bit(COMPANION_CS) + +static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_setup ao_companion_setup; + +__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; +__pdata uint8_t ao_companion_running; +__xdata uint8_t ao_companion_mutex; + +static void +ao_companion_send_command(uint8_t command) +{ + ao_companion_command.command = command; + ao_companion_command.flight_state = ao_flight_state; + ao_companion_command.tick = ao_time(); + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); +} + +static uint8_t +ao_companion_get_setup(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_SETUP); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + COMPANION_DESELECT(); + if (ao_companion_setup.board_id != ~ao_companion_setup.board_id) + return 0; + return 1; +} + +static void +ao_companion_get_data(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_FETCH); + ao_mutex_get(&ao_companion_mutex); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + COMPANION_DESELECT(); +} + +void +ao_companion(void) +{ + if (!ao_companion_get_setup()) + ao_exit(); + ao_companion_running = 1; + for (;;) { + ao_delay(ao_companion_setup.update_period); + ao_companion_get_data(); + } +} + +void +ao_companion_status(void) __reentrant +{ +} + +__code struct ao_cmds ao_companion_cmds[] = { + { ao_companion_status, "L\0Companion link status" }, + { 0, NULL }, +}; + +static __xdata struct ao_task ao_companion_task; + +void +ao_companion_init(void) +{ + COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ + COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ + COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ + + ao_cmd_register(&ao_companion_cmds[0]); + + ao_add_task(&ao_companion_task, ao_companion, "companion"); +} diff --git a/src/ao_ee.c b/src/ao_ee.c index 83863af5..a2fe8dc1 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -49,19 +49,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -static void ao_ee_cs_low(void) -{ - ao_ee_delay(); - EE_CS = 0; - ao_ee_delay(); -} +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) -static void ao_ee_cs_high(void) -{ - ao_ee_delay(); - EE_CS = 1; - ao_ee_delay(); -} +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) struct ao_ee_instruction { uint8_t instruction; diff --git a/src/ao_flash.c b/src/ao_flash.c index 00e96398..bb40f6f7 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -43,19 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -void ao_flash_cs_low(void) -{ - ao_flash_delay(); - FLASH_CS = 0; - ao_flash_delay(); -} +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) -void ao_flash_cs_high(void) -{ - ao_flash_delay(); - FLASH_CS = 1; - ao_flash_delay(); -} +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) struct ao_flash_instruction { uint8_t instruction; diff --git a/src/ao_m25.c b/src/ao_m25.c index 208c69ba..d7208273 100644 --- a/src/ao_m25.c +++ b/src/ao_m25.c @@ -99,8 +99,8 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) (SPI_CS_PORT &= ~(cs)) -#define M25_DESELECT(cs) (SPI_CS_PORT |= (cs)) +#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) +#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L diff --git a/src/ao_pins.h b/src/ao_pins.h index 89907b9c..e1f5459f 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -36,6 +36,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -63,6 +68,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -328,6 +338,12 @@ #endif /* DBG_ON_P0 */ +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + #if SPI_CS_ON_P1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL diff --git a/src/ao_spi.c b/src/ao_spi.c index bd52a0d4..fbe613c7 100644 --- a/src/ao_spi.c +++ b/src/ao_spi.c @@ -17,6 +17,10 @@ #include "ao.h" +/* Shared mutex to protect SPI bus, must cover the entire + * operation, from CS low to CS high. This means that any SPI + * user must protect the SPI bus with this mutex + */ __xdata uint8_t ao_spi_mutex; __xdata uint8_t ao_spi_dma_in_done; __xdata uint8_t ao_spi_dma_out_done; @@ -36,7 +40,6 @@ static __xdata uint8_t ao_spi_const = 0xff; void ao_spi_send(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, &ao_spi_const, @@ -64,7 +67,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* Receive bytes over SPI. @@ -76,7 +78,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant void ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, block, @@ -104,7 +105,6 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 6fa70b3a..f560740a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -61,6 +61,9 @@ main(void) ao_igniter_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 52f818ed..15ba4302 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -25,6 +25,10 @@ static __pdata int8_t ao_telemetry_config_cur; static __pdata int8_t ao_telemetry_loc_cur; static __pdata int8_t ao_telemetry_sat_cur; #endif +#if HAS_COMPANION +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; +#endif static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; @@ -149,6 +153,26 @@ ao_send_satellite(void) } #endif +#if HAS_COMPANION +static void +ao_send_companion(void) +{ + if (--ao_telemetry_companion_cur <= 0) { + telemetry.generic.type = AO_TELEMETRY_COMPANION; + telemetry.companion.board_id = ao_companion_setup.board_id; + telemetry.companion.update_period = ao_companion_setup.update_period; + telemetry.companion.channels = ao_companion_setup.channels; + ao_mutex_get(&ao_companion_mutex); + memcpy(&telemetry.companion.companion_data, + ao_companion_data, + ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_companion_cur = ao_telemetry_companion_max; + } +} +#endif + void ao_telemetry(void) { @@ -168,6 +192,10 @@ ao_telemetry(void) ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif ao_send_configuration(); #if HAS_GPS ao_send_location(); @@ -193,10 +221,25 @@ void ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; + +#if HAS_COMPANION + if (!ao_companion_setup.update_period) + ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); + ao_telemetry_companion_max = ao_companion_setup.update_period / interval; + ao_telemetry_companion_cur = 1; +#endif + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +#if HAS_COMPANION + ao_telemetry_config_cur = ao_telemetry_companion_cur; + if (ao_telemetry_config_max > ao_telemetry_config_cur) + ao_telemetry_config_cur++; +#else ao_telemetry_config_cur = 1; +#endif + #if HAS_GPS - ao_telemetry_loc_cur = 1; + ao_telemetry_loc_cur = ao_telemetry_config_cur; if (ao_telemetry_config_max > ao_telemetry_loc_cur) ao_telemetry_loc_cur++; ao_telemetry_sat_cur = ao_telemetry_loc_cur; diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index a60a501a..5eefc392 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(FLASH_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.0 diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs index f38226c6..3c8b8793 100644 --- a/src/telemetrum-v1.1/Makefile.defs +++ b/src/telemetrum-v1.1/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(M25_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.1 -- cgit v1.2.3 From ebe2ffb29944abc4d6a35889c7b5f3d9f2871077 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:38:16 -0700 Subject: altos: Put SPI in slower mode when talking to companion board The AVR CPU on the other side just can't go very fast. This reduces the SPI clock by a factor of 16, just under 200kHz. As the companion commands are reasonably short, this shouldn't have a huge effect on overall SPI utilization. Signed-off-by: Keith Packard --- src/ao_companion.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/ao_companion.c b/src/ao_companion.c index 8db3273e..556ce044 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -17,8 +17,18 @@ #include "ao.h" -#define COMPANION_SELECT() ao_spi_get_bit(COMPANION_CS) -#define COMPANION_DESELECT() ao_spi_put_bit(COMPANION_CS) +#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) + +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) static __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; -- cgit v1.2.3 From f87f0787fa5aa528674f3f4919eb22646c87c25a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:41:15 -0700 Subject: altos: Make sure companion task exits cleanly when done Signed-off-by: Keith Packard --- src/ao_companion.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_companion.c b/src/ao_companion.c index 556ce044..e2e6d05a 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -79,6 +79,7 @@ ao_companion(void) ao_delay(ao_companion_setup.update_period); ao_companion_get_data(); } + ao_exit(); } void -- cgit v1.2.3 From aa642cf55c43188e9a21198d828d7ea90ff54280 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:42:05 -0700 Subject: altos: add the 'L' command to show the status of a linked companion board This prints out whether there is a board connected, along with the various values fetched from it. Signed-off-by: Keith Packard --- src/ao_companion.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ao_companion.c b/src/ao_companion.c index e2e6d05a..b424dd89 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -85,6 +85,15 @@ ao_companion(void) void ao_companion_status(void) __reentrant { + uint8_t i; + printf("Companion running: %d\n", ao_companion_running); + printf("device: %d\n", ao_companion_setup.board_id); + printf("update period: %d\n", ao_companion_setup.update_period); + printf("channels: %d\n", ao_companion_setup.channels); + printf("data:"); + for(i = 0; i < ao_companion_setup.channels; i++) + printf(" %5u", ao_companion_data[i]); + printf("\n"); } __code struct ao_cmds ao_companion_cmds[] = { @@ -102,6 +111,5 @@ ao_companion_init(void) COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ ao_cmd_register(&ao_companion_cmds[0]); - ao_add_task(&ao_companion_task, ao_companion, "companion"); } -- cgit v1.2.3 From 18369c58e62bc64b969a7cf8be3103aa33c6d4aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 06:29:13 -0700 Subject: altos: Check for companion init packet validity was busted Was using board_id == ~board_id instead of board_id == ~board_id_inverse. Signed-off-by: Keith Packard --- src/ao_companion.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/ao_companion.c b/src/ao_companion.c index b424dd89..f54f5251 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -53,9 +53,8 @@ ao_companion_get_setup(void) ao_companion_send_command(AO_COMPANION_SETUP); ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); COMPANION_DESELECT(); - if (ao_companion_setup.board_id != ~ao_companion_setup.board_id) - return 0; - return 1; + return (ao_companion_setup.board_id == + ~ao_companion_setup.board_id_inverse); } static void @@ -72,10 +71,8 @@ ao_companion_get_data(void) void ao_companion(void) { - if (!ao_companion_get_setup()) - ao_exit(); - ao_companion_running = 1; - for (;;) { + ao_companion_running = ao_companion_get_setup(); + while (ao_companion_running) { ao_delay(ao_companion_setup.update_period); ao_companion_get_data(); } -- cgit v1.2.3 From c7f540330c040c521f9d7626009a406e704a5e41 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 14:58:34 -0700 Subject: altosui: Add companion support to the flight UI and CSV conversion Shows the companion data in a new tab. Also put companion data into CSV file. Signed-off-by: Keith Packard --- altosui/AltosCSV.java | 49 +++++++++++-- altosui/AltosCompanionInfo.java | 111 +++++++++++++++++++++++++++++ altosui/AltosFlightUI.java | 20 +++++- altosui/AltosRecord.java | 5 ++ altosui/AltosRecordCompanion.java | 38 ++++++++++ altosui/AltosState.java | 1 - altosui/AltosTelemetryRecordCompanion.java | 52 ++++++++++++++ altosui/AltosTelemetryRecordRaw.java | 10 ++- altosui/Makefile.am | 3 + 9 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 altosui/AltosCompanionInfo.java create mode 100644 altosui/AltosRecordCompanion.java create mode 100644 altosui/AltosTelemetryRecordCompanion.java diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index 5277c160..cf649db0 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -31,9 +31,9 @@ public class AltosCSV implements AltosWriter { LinkedList pad_records; AltosState state; - static final int ALTOS_CSV_VERSION = 2; + static final int ALTOS_CSV_VERSION = 3; - /* Version 2 format: + /* Version 3 format: * * General info * version number @@ -81,6 +81,13 @@ public class AltosCSV implements AltosWriter { * * GPS Sat data * C/N0 data for all 32 valid SDIDs + * + * Companion data + * companion_id (1-255. 10 is TeleScience) + * time of last companion data (seconds since boost) + * update_period (0.1-2.55 minimum telemetry interval) + * channels (0-12) + * channel data for all 12 possible channels */ void write_general_header() { @@ -179,7 +186,32 @@ public class AltosCSV implements AltosWriter { } } - void write_header(boolean gps) { + void write_companion_header() { + out.printf("companion_id,companion_time,companion_update,companion_channels"); + for (int i = 0; i < 12; i++) + out.printf(",companion_%02d", i); + } + + void write_companion(AltosRecord record) { + AltosRecordCompanion companion = record.companion; + + int channels_written = 0; + if (companion == null) { + out.printf("0,0,0,0"); + } else { + out.printf("%3d,%5.2f,%5.2f,%2d", + companion.board_id, + (companion.tick - boost_tick) / 100.0, + companion.update_period / 100.0, + companion.channels); + for (; channels_written < companion.channels; channels_written++) + out.printf(",%5d", companion.companion_data[channels_written]); + } + for (; channels_written < 12; channels_written++) + out.printf(",0"); + } + + void write_header(boolean gps, boolean companion) { out.printf("#"); write_general_header(); out.printf(","); write_flight_header(); out.printf(","); write_basic_header(); @@ -187,6 +219,9 @@ public class AltosCSV implements AltosWriter { out.printf(","); write_gps_header(); out.printf(","); write_gps_sat_header(); } + if (companion) { + out.printf(","); write_companion_header(); + } out.printf ("\n"); } @@ -200,6 +235,10 @@ public class AltosCSV implements AltosWriter { write_gps(record); out.printf(","); write_gps_sat(record); } + if (record.companion != null) { + out.printf(","); + write_companion(record); + } out.printf ("\n"); } @@ -210,8 +249,10 @@ public class AltosCSV implements AltosWriter { } public void write(AltosRecord record) { + if (record.state == Altos.ao_flight_startup) + return; if (!header_written) { - write_header(record.gps != null); + write_header(record.gps != null, record.companion != null); header_written = true; } if (!seen_boost) { diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java new file mode 100644 index 00000000..f287a8ea --- /dev/null +++ b/altosui/AltosCompanionInfo.java @@ -0,0 +1,111 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public class AltosCompanionInfo extends JTable { + private AltosFlightInfoTableModel model; + + private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); + private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); + + static final int info_columns = 2; + static final int info_rows = 17; + + int desired_row_height() { + FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); + return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; + } + + public AltosCompanionInfo() { + super(new AltosFlightInfoTableModel(info_rows, info_columns)); + model = (AltosFlightInfoTableModel) getModel(); + setFont(infoValueFont); + setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); + setShowGrid(true); + setRowHeight(desired_row_height()); + doLayout(); + } + + public Dimension getPreferredScrollableViewportSize() { + return getPreferredSize(); + } + + void info_reset() { + model.reset(); + } + + void info_add_row(int col, String name, String value) { + model.addRow(col, name, value); + } + + void info_add_row(int col, String name, String format, Object... parameters) { + info_add_row (col, name, String.format(format, parameters)); + } + + void info_finish() { + model.finish(); + } + + public void clear() { + model.clear(); + } + + AltosRecordCompanion companion; + + public String board_name() { + if (companion == null) + return "None"; + switch (companion.board_id) { + case AltosRecordCompanion.board_id_telescience: + return "TeleScience"; + default: + return String.format("%02x\n", companion.board_id); + } + } + + public void show(AltosState state, int crc_errors) { + if (state == null) + return; + if (state.data.companion != null) + companion = state.data.companion; + info_reset(); + info_add_row(0, "Companion board", "%s", board_name()); + if (companion != null) { + info_add_row(0, "Last Data", "%5d", companion.tick); + info_add_row(0, "Update period", "%5.2f s", + companion.update_period / 100.0); + info_add_row(0, "Channels", "%3d", companion.channels); + + for (int i = 0; i < companion.channels; i++) + info_add_row(1, String.format("Channel %2d", i), + "%6d", companion.companion_data[i]); + } + info_finish(); + } +} diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index f0626e7c..51768046 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -39,8 +39,10 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosAscent ascent; AltosDescent descent; AltosLanded landed; + AltosCompanionInfo companion; AltosSiteMap sitemap; boolean has_map; + boolean has_companion; private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; @@ -96,7 +98,20 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } flightStatus.show(state, crc_errors); flightInfo.show(state, crc_errors); - if (state.gps != null) { + + if (state.data.companion != null) { + if (!has_companion) { + pane.add("Companion", companion); + has_companion= true; + } + companion.show(state, crc_errors); + } else { + if (has_companion) { + pane.remove(companion); + has_companion = false; + } + } + if (state.gps != null && state.gps.connected) { if (!has_map) { pane.add("Site Map", sitemap); has_map = true; @@ -216,6 +231,9 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { flightInfo = new AltosInfoTable(); pane.add("Table", new JScrollPane(flightInfo)); + companion = new AltosCompanionInfo(); + has_companion = false; + sitemap = new AltosSiteMap(); has_map = false; diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 144b1c3c..ce6d86ab 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -32,6 +32,7 @@ public class AltosRecord { static final int seen_gps_time = 16; static final int seen_gps_lat = 32; static final int seen_gps_lon = 64; + static final int seen_companion = 128; int seen; int version; @@ -74,6 +75,8 @@ public class AltosRecord { int main_deploy; int flight_log_max; String firmware_version; + + AltosRecordCompanion companion; /* * Values for our MP3H6115A pressure sensor * @@ -267,6 +270,7 @@ public class AltosRecord { speed = old.speed; height = old.height; gps = new AltosGPS(old.gps); + companion = old.companion; } public AltosRecord() { @@ -296,5 +300,6 @@ public class AltosRecord { speed = MISSING; height = MISSING; gps = new AltosGPS(); + companion = null; } } diff --git a/altosui/AltosRecordCompanion.java b/altosui/AltosRecordCompanion.java new file mode 100644 index 00000000..0a8f9f4b --- /dev/null +++ b/altosui/AltosRecordCompanion.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosRecordCompanion { + final static int board_id_telescience = 0x0a; + final static int MAX_CHANNELS = 12; + + int tick; + int board_id; + int update_period; + int channels; + int[] companion_data; + + public AltosRecordCompanion(int in_channels) { + channels = in_channels; + if (channels < 0) + channels = 0; + if (channels > MAX_CHANNELS) + channels = MAX_CHANNELS; + companion_data = new int[channels]; + } +} diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 378930bf..072cb790 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -73,7 +73,6 @@ public class AltosState { int speak_tick; double speak_altitude; - void init (AltosRecord cur, AltosState prev_state) { int i; AltosRecord prev; diff --git a/altosui/AltosTelemetryRecordCompanion.java b/altosui/AltosTelemetryRecordCompanion.java new file mode 100644 index 00000000..11b349e1 --- /dev/null +++ b/altosui/AltosTelemetryRecordCompanion.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { + + AltosRecordCompanion companion; + + public AltosTelemetryRecordCompanion(int[] in_bytes) { + super(in_bytes); + + int off = 0; + if (uint8(6) == 0) + off = 1; + int channels = uint8(7+off); + + if (off != 0 && channels >= 12) + channels = 11; + + companion = new AltosRecordCompanion(channels); + companion.tick = tick; + companion.board_id = uint8(5); + companion.update_period = uint8(6+off); + for (int i = 0; i < channels; i++) + companion.companion_data[i] = uint16(8 + off + i * 2); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.companion = companion; + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + companion.tick = tick; + return next; + } +} diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index 4b34f017..39b2ba07 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -33,6 +33,7 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { final static int packet_type_configuration = 0x04; final static int packet_type_location = 0x05; final static int packet_type_satellite = 0x06; + final static int packet_type_companion = 0x07; final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); @@ -89,6 +90,9 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { case packet_type_satellite: r = new AltosTelemetryRecordSatellite(bytes); break; + case packet_type_companion: + r = new AltosTelemetryRecordCompanion(bytes); + break; default: r = new AltosTelemetryRecordRaw(bytes); break; @@ -139,9 +143,11 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { public AltosRecord update_state(AltosRecord previous) { AltosRecord next; - if (previous != null) + if (previous != null) { next = new AltosRecord(previous); - else + while (tick < previous.tick) + tick += 65536; + } else next = new AltosRecord(); next.serial = serial; next.tick = tick; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index bab8f816..83510352 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -20,6 +20,7 @@ altosui_JAVA = \ GrabNDrag.java \ AltosAscent.java \ AltosChannelMenu.java \ + AltosCompanionInfo.java \ AltosConfig.java \ AltosConfigData.java \ AltosConfigFreqUI.java \ @@ -77,6 +78,7 @@ altosui_JAVA = \ AltosPreferences.java \ AltosReader.java \ AltosRecord.java \ + AltosRecordCompanion.java \ AltosRecordIterable.java \ AltosTelemetryReader.java \ AltosTelemetryRecord.java \ @@ -86,6 +88,7 @@ altosui_JAVA = \ AltosTelemetryRecordConfiguration.java \ AltosTelemetryRecordLocation.java \ AltosTelemetryRecordSatellite.java \ + AltosTelemetryRecordCompanion.java \ AltosTelemetryRecordLegacy.java \ AltosTelemetryMap.java \ AltosReplayReader.java \ -- cgit v1.2.3 From fa7dd04741bf3fd9cedc59ed3b45b69ef9312609 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 21:41:25 -0700 Subject: altos: Send SPI message at flight state changes Get the companion board starting its data logging as soon as possible after boost starts. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_companion.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/ao.h b/src/ao.h index de47f3df..b14b65f2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1581,6 +1581,7 @@ ao_btm_init(void); #define AO_COMPANION_SETUP 1 #define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 struct ao_companion_command { uint8_t command; diff --git a/src/ao_companion.c b/src/ao_companion.c index f54f5251..f0ce3f12 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -68,13 +68,24 @@ ao_companion_get_data(void) COMPANION_DESELECT(); } +static void +ao_companion_notify(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_NOTIFY); + COMPANION_DESELECT(); +} + void ao_companion(void) { ao_companion_running = ao_companion_get_setup(); while (ao_companion_running) { - ao_delay(ao_companion_setup.update_period); - ao_companion_get_data(); + ao_alarm(ao_companion_setup.update_period); + if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) + ao_companion_get_data(); + else + ao_companion_notify(); } ao_exit(); } -- cgit v1.2.3 From 41e5be32819d305c8268e6f992be91411ea13435 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:30:00 -0700 Subject: altos: Send serial/flight to companion board Lets the companion log them for later matching with TeleMetrum log Signed-off-by: Keith Packard --- src/ao.h | 2 ++ src/ao_companion.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/ao.h b/src/ao.h index b14b65f2..6a4da31e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1587,6 +1587,8 @@ struct ao_companion_command { uint8_t command; uint8_t flight_state; uint16_t tick; + uint16_t serial; + uint16_t flight; }; struct ao_companion_setup { diff --git a/src/ao_companion.c b/src/ao_companion.c index f0ce3f12..8f23ba25 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -43,6 +43,8 @@ ao_companion_send_command(uint8_t command) ao_companion_command.command = command; ao_companion_command.flight_state = ao_flight_state; ao_companion_command.tick = ao_time(); + ao_companion_command.serial = ao_serial_number; + ao_companion_command.flight = ao_flight_number; ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); } -- cgit v1.2.3 From b0ec30de37aa822ba66d25ceaa8cf8dc967b4371 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:31:08 -0700 Subject: altos: wait 10s for companion to boot In case the companion is delayed while booting, retry the setup 10 times with a 1s delay between tries. Signed-off-by: Keith Packard --- src/ao_companion.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/ao_companion.c b/src/ao_companion.c index 8f23ba25..4c8f4269 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -81,7 +81,14 @@ ao_companion_notify(void) void ao_companion(void) { - ao_companion_running = ao_companion_get_setup(); + uint8_t i; + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + for (i = 0; i < 10; i++) { + ao_delay(AO_SEC_TO_TICKS(1)); + if ((ao_companion_running = ao_companion_get_setup())) + break; + } while (ao_companion_running) { ao_alarm(ao_companion_setup.update_period); if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) -- cgit v1.2.3 From 5a3e96bef31959a287b8696778d7d8cf911a7dc4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:36:18 -0700 Subject: altosui: Clean up eeprom parsing a bit Export basic parsing and checksum functions for shared use. Create 'erased' function to check a chunk of eeprom data for data. Signed-off-by: Keith Packard --- altosui/AltosConvert.java | 20 ++++++++++++++++++++ altosui/AltosEepromChunk.java | 7 +++++++ altosui/AltosEepromRecord.java | 30 +++--------------------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java index c2ae9a50..207470a5 100644 --- a/altosui/AltosConvert.java +++ b/altosui/AltosConvert.java @@ -220,4 +220,24 @@ public class AltosConvert { static double radio_channel_to_frequency(int channel) { return 434.550 + channel * 0.100; } + + static int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + static int checksum(int[] data, int start, int length) { + int csum = 0x5a; + for (int i = 0; i < length; i++) + csum += data[i + start]; + return csum & 0xff; + } } diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index 1e42077f..fb632a3f 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -52,6 +52,13 @@ public class AltosEepromChunk { return data[offset] | (data[offset + 1] << 8); } + boolean erased(int start, int len) { + for (int i = 0; i < len; i++) + if (data[start+i] != 0xff) + return false; + return true; + } + public AltosEepromChunk(AltosSerial serial_line, int block) throws TimeoutException, InterruptedException { diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index c0f97035..d8a07951 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -40,42 +40,18 @@ public class AltosEepromRecord { static final int record_length = 8; - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - int checksum(int[] data, int start) { - int csum = 0x5a; - for (int i = 0; i < record_length; i++) - csum += data[i + start]; - return csum & 0xff; - } - public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { cmd = chunk.data(start); tick_valid = true; - int i; - for (i = 0; i < record_length; i++) - if (chunk.data[start + i] != 0xff) - break; - if (i != 8) { - if (checksum(chunk.data, start) != 0) + tick_valid = !chunk.erased(start, record_length); + if (tick_valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) throw new ParseException(String.format("invalid checksum at 0x%x", chunk.address + start), 0); } else { cmd = Altos.AO_LOG_INVALID; - tick_valid = false; } tick = chunk.data16(start + 2); -- cgit v1.2.3 From 03e201e1acc8742399054e4ad36b533120ea1612 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:39:35 -0700 Subject: altosui: Add support for TeleScience eeprom download Using the existing eeprom methods, fetch and save TeleScience eeprom data, storing to a filename generated from the serial/flight from the TM connected to the TS board. Signed-off-by: Keith Packard --- altosui/AltosEepromDownload.java | 95 +++++++++++++++++++++++++++++++++---- altosui/AltosEepromList.java | 4 +- altosui/AltosEepromLog.java | 65 +++++++++++++------------ altosui/AltosEepromTeleScience.java | 64 +++++++++++++++++++++++++ altosui/Makefile.am | 1 + 5 files changed, 188 insertions(+), 41 deletions(-) create mode 100644 altosui/AltosEepromTeleScience.java diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 417aab00..6112a3b1 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -39,6 +39,7 @@ public class AltosEepromDownload implements Runnable { AltosEepromMonitor monitor; int flight; + int serial; int year, month, day; boolean want_file; FileWriter eeprom_file; @@ -48,6 +49,7 @@ public class AltosEepromDownload implements Runnable { ActionListener listener; boolean success; ParseException parse_exception; + String extension; private void FlushPending() throws IOException { for (String s : flights.config_data) { @@ -64,10 +66,13 @@ public class AltosEepromDownload implements Runnable { return; if (force || (flight != 0 && want_file)) { AltosFile eeprom_name; + + if (extension == null) + extension = "data"; if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, flights.config_data.serial, flight, "eeprom"); + eeprom_name = new AltosFile(year, month, day, serial, flight, extension); else - eeprom_name = new AltosFile(flights.config_data.serial, flight, "eeprom"); + eeprom_name = new AltosFile(serial, flight, extension); eeprom_file = new FileWriter(eeprom_name); if (eeprom_file != null) { @@ -89,18 +94,29 @@ public class AltosEepromDownload implements Runnable { } } + void set_serial(int in_serial) { + serial = in_serial; + monitor.set_serial(serial); + } + + void set_flight(int in_flight) { + flight = in_flight; + monitor.set_flight(flight); + } + boolean done; int state; void CaptureFull(AltosEepromChunk eechunk) throws IOException { boolean any_valid = false; + + extension = "eeprom"; + set_serial(flights.config_data.serial); for (int i = 0; i < eechunk.chunk_size && !done; i += AltosEepromRecord.record_length) { try { AltosEepromRecord r = new AltosEepromRecord(eechunk, i); - if (r.cmd == Altos.AO_LOG_FLIGHT) { - flight = r.b; - monitor.set_flight(flight); - } + if (r.cmd == Altos.AO_LOG_FLIGHT) + set_flight(r.b); /* Monitor state transitions to update display */ if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { @@ -137,6 +153,8 @@ public class AltosEepromDownload implements Runnable { void CaptureTiny (AltosEepromChunk eechunk) throws IOException { boolean any_valid = false; + extension = "eeprom"; + set_serial(flights.config_data.serial); for (int i = 0; i < eechunk.data.length && !done; i += 2) { int v = eechunk.data16(i); AltosEepromRecord r; @@ -144,8 +162,7 @@ public class AltosEepromDownload implements Runnable { if (i == 0 && start) { tiny_tick = 0; start = false; - flight = v; - monitor.set_flight(flight); + set_flight(v); r = new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v); any_valid = true; } else { @@ -181,6 +198,56 @@ public class AltosEepromDownload implements Runnable { done = true; } + void LogTeleScience(AltosEepromTeleScience r) throws IOException { + if (r.type != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %4x %d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", + r.type, r.tick, r.tm_tick, r.tm_state, + r.data[0], r.data[1], r.data[2], r.data[3], + r.data[4], r.data[5], r.data[6], r.data[7], + r.data[8], r.data[9], r.data[10], r.data[11]); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + } + } + + boolean telescience_start; + + void CaptureTeleScience (AltosEepromChunk eechunk) throws IOException { + boolean any_valid = false; + + extension = "science"; + for (int i = 0; i < eechunk.chunk_size && !done; i += AltosEepromTeleScience.record_length) { + try { + AltosEepromTeleScience r = new AltosEepromTeleScience(eechunk, i); + if (r.type == AltosEepromTeleScience.AO_LOG_TELESCIENCE_START) { + if (telescience_start) { + done = true; + break; + } + set_serial(r.data[0]); + set_flight(r.data[1]); + telescience_start = true; + } else { + if (!telescience_start) + break; + } + state = r.tm_state; + want_file =true; + any_valid = true; + LogTeleScience(r); + } catch (ParseException pe) { + if (parse_exception == null) + parse_exception = pe; + } + } + + CheckFile(false); + if (!any_valid) + done = true; + } + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; int log_format = flights.config_data.log_format; @@ -202,7 +269,6 @@ public class AltosEepromDownload implements Runnable { eeprom_pending = new LinkedList(); /* Set serial number in the monitor dialog window */ - monitor.set_serial(flights.config_data.serial); /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ state = 0; state_block = log.start_block; @@ -227,11 +293,21 @@ public class AltosEepromDownload implements Runnable { switch (log_format) { case Altos.AO_LOG_FORMAT_FULL: + extension = "eeprom"; CaptureFull(eechunk); break; case Altos.AO_LOG_FORMAT_TINY: + extension = "eeprom"; CaptureTiny(eechunk); break; +// case Altos.AO_LOG_FORMAT_TELEMETRY: +// extension = "telem"; +// CaptureTelemetry(eechunk); +// break; + case Altos.AO_LOG_FORMAT_TELESCIENCE: + extension = "science"; + CaptureTeleScience(eechunk); + break; } } CheckFile(true); @@ -290,6 +366,7 @@ public class AltosEepromDownload implements Runnable { serial_line.device.toShortString(), JOptionPane.ERROR_MESSAGE); } catch (InterruptedException ie) { + System.out.printf("download interrupted\n"); } catch (TimeoutException te) { show_message(String.format("Connection to \"%s\" failed", serial_line.device.toShortString()), diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index 185fec91..da4b1166 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -67,7 +67,7 @@ public class AltosEepromList extends ArrayList { ArrayList flights = new ArrayList(); - if (config_data.flight_log_max != 0) { + if (config_data.flight_log_max != 0 || config_data.log_format != 0) { /* Devices with newer firmware will support the 'l' * command which will list the region of storage @@ -113,7 +113,7 @@ public class AltosEepromList extends ArrayList { * firmware, this will also extract the flight number. */ for (AltosEepromFlight flight : flights) { - add(new AltosEepromLog(serial_line, config_data.serial, + add(new AltosEepromLog(config_data, serial_line, flight.flight, flight.start, flight.end)); } } finally { diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index 0cf420d9..be2549cb 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -46,7 +46,8 @@ public class AltosEepromLog { boolean download; boolean delete; - public AltosEepromLog(AltosSerial serial_line, int in_serial, + public AltosEepromLog(AltosConfigData config_data, + AltosSerial serial_line, int in_flight, int in_start_block, int in_end_block) throws InterruptedException, TimeoutException { @@ -54,51 +55,55 @@ public class AltosEepromLog { int block; boolean has_date = false; + flight = in_flight; + if (flight != 0) + has_flight = true; start_block = in_start_block; end_block = in_end_block; - serial = in_serial; + serial = config_data.serial; /* * By default, request that every log be downloaded but not deleted */ download = true; delete = false; + /* - * Only look in the first two blocks so that this - * process doesn't take a long time + * Look in TeleMetrum log data for date */ - if (in_end_block > in_start_block + 2) - in_end_block = in_start_block + 2; + if (config_data.log_format == Altos.AO_LOG_FORMAT_UNKNOWN || + config_data.log_format == Altos.AO_LOG_FORMAT_FULL) + { + /* + * Only look in the first two blocks so that this + * process doesn't take a long time + */ + if (in_end_block > in_start_block + 2) + in_end_block = in_start_block + 2; - for (block = in_start_block; block < in_end_block; block++) { - AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); + for (block = in_start_block; block < in_end_block; block++) { + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); - if (block == in_start_block) { - if (eechunk.data16(0) == in_flight) { - flight = in_flight; - has_flight = true; - break; - } - } - for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { - try { - AltosEepromRecord r = new AltosEepromRecord(eechunk, i); + for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { + try { + AltosEepromRecord r = new AltosEepromRecord(eechunk, i); - if (r.cmd == Altos.AO_LOG_FLIGHT) { - flight = r.b; - has_flight = true; - } - if (r.cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (r.a & 0xff); - month = (r.a >> 8) & 0xff; - day = (r.b & 0xff); - has_date = true; + if (r.cmd == Altos.AO_LOG_FLIGHT) { + flight = r.b; + has_flight = true; + } + if (r.cmd == Altos.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + has_date = true; + } + } catch (ParseException pe) { } - } catch (ParseException pe) { } + if (has_date && has_flight) + break; } - if (has_date && has_flight) - break; } } } diff --git a/altosui/AltosEepromTeleScience.java b/altosui/AltosEepromTeleScience.java new file mode 100644 index 00000000..ee1840b0 --- /dev/null +++ b/altosui/AltosEepromTeleScience.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +public class AltosEepromTeleScience { + int type; + int tick; + int tm_state; + int tm_tick; + int[] data; + boolean valid; + + static final int AO_LOG_TELESCIENCE_START = 's'; + static final int AO_LOG_TELESCIENCE_DATA = 'd'; + + static final int max_data = 12; + static final int record_length = 32; + + public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { + type = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + type = Altos.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + tm_tick = chunk.data16(start+4); + tm_state = chunk.data(start+6); + data = new int[max_data]; + for (int i = 0; i < max_data; i++) + data[i] = chunk.data16(start + 8 + i * 2); + } +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 83510352..e4986ba5 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -45,6 +45,7 @@ altosui_JAVA = \ AltosEepromMonitor.java \ AltosEepromIterable.java \ AltosEepromRecord.java \ + AltosEepromTeleScience.java \ AltosEepromSelect.java \ AltosFile.java \ AltosFlash.java \ -- cgit v1.2.3 From 3ba7b6196f68078f4ed4538c4e7fe30699dfe908 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 21:05:46 -0700 Subject: altosui: Devices with log-format can also delete flights Any device with either flight-log-max or log-format can delete flights. Signed-off-by: Keith Packard --- altosui/AltosEepromDelete.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index 94951ced..cd9abfab 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -42,7 +42,7 @@ public class AltosEepromDelete implements Runnable { private void DeleteLog (AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { - if (flights.config_data.flight_log_max != 0) { + if (flights.config_data.flight_log_max != 0 || flights.config_data.log_format != 0) { /* Devices with newer firmware can erase the * flash blocks containing each flight -- cgit v1.2.3 From dcd15032eec45f3fdd003050710ebd5b85052662 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 21:09:19 -0700 Subject: altosui: Eliminate inter-chunk flush_input calls Once the serial line is nicely synchronized, we don't need to flush input between chunks. This speeds up eeprom downloading quite a bit. Signed-off-by: Keith Packard --- altosui/AltosEepromChunk.java | 5 +++-- altosui/AltosEepromDownload.java | 2 +- altosui/AltosEepromLog.java | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index fb632a3f..59767c2a 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -59,14 +59,15 @@ public class AltosEepromChunk { return true; } - public AltosEepromChunk(AltosSerial serial_line, int block) + public AltosEepromChunk(AltosSerial serial_line, int block, boolean flush) throws TimeoutException, InterruptedException { int offset; data = new int[chunk_size]; address = block * chunk_size; - serial_line.flush_input(); + if (flush) + serial_line.flush_input(); serial_line.printf("e %x\n", block); for (offset = 0; offset < chunk_size; offset += per_line) { diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 6112a3b1..b44a1451 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -275,7 +275,7 @@ public class AltosEepromDownload implements Runnable { for (block = log.start_block; !done && block < log.end_block; block++) { monitor.set_value(Altos.state_to_string[state], state, block - state_block); - AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block, block == log.start_block); /* * Guess what kind of data is there if the device diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index be2549cb..ee77e5c8 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -82,7 +82,7 @@ public class AltosEepromLog { in_end_block = in_start_block + 2; for (block = in_start_block; block < in_end_block; block++) { - AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); + AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block, block == in_start_block); for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { try { -- cgit v1.2.3 From 924d56a4d2d8b16530cd378b18cfc5d6e08420ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 21:10:15 -0700 Subject: altos: AltosSerial.flush_input shouldn't discard Interrupted exceptions The eeprom download code wants to interrupt serial communication so that it can stop downloading stuff in the middle of a run. Make flush_input pass the exception along instead of discarding it. Signed-off-by: Keith Packard --- altosui/AltosDebug.java | 5 ++++- altosui/AltosEepromDelete.java | 12 ++++++++---- altosui/AltosEepromDownload.java | 8 ++++++-- altosui/AltosEepromManage.java | 5 ++++- altosui/AltosSerial.java | 17 +++++++++-------- 5 files changed, 31 insertions(+), 16 deletions(-) diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java index 8d435b66..d18de80d 100644 --- a/altosui/AltosDebug.java +++ b/altosui/AltosDebug.java @@ -62,7 +62,10 @@ public class AltosDebug extends AltosSerial { void ensure_debug_mode() { if (!debug_mode) { printf("D\n"); - flush_input(); + try { + flush_input(); + } catch (InterruptedException ie) { + } debug_mode = true; } } diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index cd9abfab..a9d77788 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -104,10 +104,14 @@ public class AltosEepromDelete implements Runnable { serial_line.device.toShortString()), "Connection Failed"); } finally { - if (remote) - serial_line.stop_remote(); - serial_line.flush_output(); - serial_line.close(); + try { + if (remote) + serial_line.stop_remote(); + } catch (InterruptedException ie) { + } finally { + serial_line.flush_output(); + serial_line.close(); + } } if (listener != null) { Runnable r = new Runnable() { diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index b44a1451..358ad337 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -373,8 +373,12 @@ public class AltosEepromDownload implements Runnable { "Connection Failed", JOptionPane.ERROR_MESSAGE); } finally { - if (remote) - serial_line.stop_remote(); + if (remote) { + try { + serial_line.stop_remote(); + } catch (InterruptedException ie) { + } + } serial_line.flush_output(); } monitor.done(); diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 0652ca04..2e520628 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -44,7 +44,10 @@ public class AltosEepromManage implements ActionListener { public void finish() { if (serial_line != null) { - serial_line.flush_input(); + try { + serial_line.flush_input(); + } catch (InterruptedException ie) { + } serial_line.close(); serial_line = null; } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index b089c9c4..f0e25fa5 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -187,7 +187,7 @@ public class AltosSerial implements Runnable { return abort; } - public void flush_input() { + public void flush_input() throws InterruptedException { flush_output(); boolean got_some; @@ -195,10 +195,7 @@ public class AltosSerial implements Runnable { if (remote) timeout = 500; do { - try { - Thread.sleep(timeout); - } catch (InterruptedException ie) { - } + Thread.sleep(timeout); got_some = !reply_queue.isEmpty(); synchronized(this) { if (!"VERSION".startsWith(line) && @@ -271,8 +268,12 @@ public class AltosSerial implements Runnable { } public void close() { - if (remote) - stop_remote(); + if (remote) { + try { + stop_remote(); + } catch (InterruptedException ie) { + } + } if (in_reply != 0) System.out.printf("Uh-oh. Closing active serial device\n"); @@ -422,7 +423,7 @@ public class AltosSerial implements Runnable { remote = true; } - public void stop_remote() { + public void stop_remote() throws InterruptedException { if (debug) System.out.printf("stop remote\n"); try { -- cgit v1.2.3 From 7f74761051f2a5ab45b82c4dd79a8569376bbe2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:56:06 -0700 Subject: altos: Correct AO_CONFIG_MINOR from 6 to 7 Forgot to bump this when adding radio setting. Signed-off-by: Keith Packard --- src/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao.h b/src/ao.h index 6a4da31e..79452862 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1415,7 +1415,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 6 +#define AO_CONFIG_MINOR 7 struct ao_config { uint8_t major; -- cgit v1.2.3 From aa71c2cdcb417eba2a2d30792ece9a47b8b3fc82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:56:55 -0700 Subject: altos: Reset radio channel to zero when using radio setting Otherwise, it's hard to set the frequency over the radio link. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_config.c b/src/ao_config.c index 36bd47c4..331509e2 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -402,6 +402,7 @@ ao_config_radio_setting_set(void) __reentrant ao_mutex_get(&ao_config_mutex); _ao_config_get(); ao_config.radio_setting = ao_cmd_lex_u32; + ao_config.radio_channel = 0; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_setting_show(); -- cgit v1.2.3 From 709485f20fb039f8dd087c8491c5f5a76718ae53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:58:03 -0700 Subject: altos: use raw height while waiting for landing This avoids any noise introduced by the kalman filter, making landing detection much more reliable. This patch also changes the interval to 10s so that the height bounds can be increased to 4m. Signed-off-by: Keith Packard --- src/ao_flight.c | 4 ++-- src/ao_kalman.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index af3d6bfa..85c1825b 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -54,7 +54,7 @@ __pdata uint8_t ao_flight_force_idle; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) #define abs(a) ((a) < 0 ? -(a) : (a)) @@ -286,7 +286,7 @@ ao_flight(void) ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) { ao_flight_state = ao_flight_landed; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index 203d727a..ee01949e 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -277,7 +277,7 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; #ifdef AO_FLIGHT_TEST if (ao_sample_tick - ao_sample_prev_tick > 50) ao_avg_height = (ao_avg_height_scaled + 1) >> 1; -- cgit v1.2.3 From 746d6a472a20243a8c0eacc8edf8e81e0641bc17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 00:00:07 -0700 Subject: altosui: don't set channel when using radio setting altos now sets the radio back to channel 0 when the radio setting is changed. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index f0e25fa5..0a531aa9 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -353,10 +353,10 @@ public class AltosSerial implements Runnable { private void set_radio_setting(int setting) { if (altos != null) { if (monitor_mode) - printf("m 0\nc R %d\nc r 0\nm %x\n", + printf("m 0\nc R %d\nm %x\n", setting, telemetry_len()); else - printf("c R %d\nc r 0\n", setting); + printf("c R %d\n", setting); flush_output(); } } @@ -364,6 +364,8 @@ public class AltosSerial implements Runnable { public void set_radio_frequency(double frequency, boolean has_setting, int cal) { + if (debug) + System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); if (has_setting) set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); else @@ -413,7 +415,7 @@ public class AltosSerial implements Runnable { public void start_remote() throws TimeoutException, InterruptedException { if (debug) - System.out.printf("start remote\n"); + System.out.printf("start remote %7.3f\n", frequency); if (frequency == 0.0) frequency = AltosPreferences.frequency(device.getSerial()); set_radio_frequency(frequency); -- cgit v1.2.3 From ef7f60df841f1eb22b9cec0d7f68cf2c003d6b30 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 00:00:54 -0700 Subject: altosui: Respect storage limits in flight log max config Compute the maximum flight log using the data returned from the 'f' command (total storage and erase block size). Limit menu to choices which fall within this limit, complain if the user asks for too big a value. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 40 ++++++++++++++++++++++++++++++++++------ altosui/AltosConfigData.java | 8 ++++++-- altosui/AltosConfigUI.java | 22 ++++++++++++++++++++-- 3 files changed, 60 insertions(+), 10 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index ffabe209..9a44c1c5 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -76,6 +76,8 @@ public class AltosConfig implements ActionListener { int_ref ignite_mode; int_ref pad_orientation; int_ref radio_setting; + int_ref storage_size; + int_ref storage_erase_unit; string_ref version; string_ref product; string_ref callsign; @@ -127,6 +129,15 @@ public class AltosConfig implements ActionListener { serial_line.stop_remote(); } + int log_limit() { + if (storage_size.get() > 0 && storage_erase_unit.get() > 0) { + int log_limit = storage_size.get() - storage_erase_unit.get(); + if (log_limit > 0) + return log_limit / 1024; + } + return 1024; + } + void update_ui() { config_ui.set_serial(serial.get()); config_ui.set_product(product.get()); @@ -135,6 +146,7 @@ public class AltosConfig implements ActionListener { config_ui.set_apogee_delay(apogee_delay.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); + config_ui.set_flight_log_max_limit(log_limit()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_pad_orientation(pad_orientation.get()); @@ -163,6 +175,8 @@ public class AltosConfig implements ActionListener { get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); get_int(line, "Radio setting:", radio_setting); + get_int(line, "Storage size:", storage_size); + get_int(line, "Storage erase unit:", storage_erase_unit); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -192,7 +206,7 @@ public class AltosConfig implements ActionListener { void get_data() { try { config.start_serial(); - config.serial_line.printf("c s\nv\n"); + config.serial_line.printf("c s\nf\nv\n"); for (;;) { try { String line = config.serial_line.get_reply(5000); @@ -230,9 +244,7 @@ public class AltosConfig implements ActionListener { radio_calibration.get()); if (remote) { serial_line.stop_remote(); - serial_line.set_radio_frequency(frequency, - has_setting, - radio_calibration.get()); + serial_line.set_radio_frequency(frequency); AltosPreferences.set_frequency(device.getSerial(), frequency); serial_line.start_remote(); } @@ -340,13 +352,27 @@ public class AltosConfig implements ActionListener { } void save_data() { + + /* bounds check stuff */ + if (config_ui.flight_log_max() > log_limit()) { + JOptionPane.showMessageDialog(owner, + String.format("Requested flight log, %dk, is larger than the available space, %dk.\n", + config_ui.flight_log_max(), + log_limit()), + "Maximum Flight Log Too Large", + JOptionPane.ERROR_MESSAGE); + return; + } + main_deploy.set(config_ui.main_deploy()); apogee_delay.set(config_ui.apogee_delay()); radio_calibration.set(config_ui.radio_calibration()); set_frequency(config_ui.radio_frequency()); flight_log_max.set(config_ui.flight_log_max()); - ignite_mode.set(config_ui.ignite_mode()); - pad_orientation.set(config_ui.pad_orientation()); + if (ignite_mode.get() >= 0) + ignite_mode.set(config_ui.ignite_mode()); + if (pad_orientation.get() >= 0) + pad_orientation.set(config_ui.pad_orientation()); callsign.set(config_ui.callsign()); run_serial_thread(serial_mode_save); } @@ -385,6 +411,8 @@ public class AltosConfig implements ActionListener { flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); pad_orientation = new int_ref(-1); + storage_size = new int_ref(-1); + storage_erase_unit = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 710231d7..272dd402 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -54,7 +54,8 @@ public class AltosConfigData implements Iterable { int radio_calibration; int flight_log_max; int ignite_mode; - + int storage_size; + int storage_erase_unit; static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { @@ -84,7 +85,7 @@ public class AltosConfigData implements Iterable { } public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { - serial_line.printf("c s\nv\n"); + serial_line.printf("c s\nf\nv\n"); lines = new LinkedList(); radio_setting = 0; for (;;) { @@ -116,6 +117,9 @@ public class AltosConfigData implements Iterable { try { version = get_string(line,"software-version"); } catch (Exception e) {} try { product = get_string(line,"product"); } catch (Exception e) {} + try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} + try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} + /* signals the end of the version info */ if (line.startsWith("software-version")) break; diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 71664c91..63e0ba78 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -577,6 +577,18 @@ public class AltosConfigUI return Integer.parseInt(flight_log_max_value.getSelectedItem().toString()); } + public void set_flight_log_max_limit(int flight_log_max_limit) { + boolean any_added = false; + flight_log_max_value.removeAllItems(); + for (int i = 0; i < flight_log_max_values.length; i++) { + if (Integer.parseInt(flight_log_max_values[i]) < flight_log_max_limit){ + flight_log_max_value.addItem(flight_log_max_values[i]); + any_added = true; + } + } + flight_log_max_value.addItem(String.format("%d", flight_log_max_limit)); + } + public void set_ignite_mode(int new_ignite_mode) { if (new_ignite_mode < 0) { ignite_mode_value.setEnabled(false); @@ -588,7 +600,10 @@ public class AltosConfigUI } public int ignite_mode() { - return ignite_mode_value.getSelectedIndex(); + if (ignite_mode_value.isEnabled()) + return ignite_mode_value.getSelectedIndex(); + else + return -1; } @@ -603,7 +618,10 @@ public class AltosConfigUI } public int pad_orientation() { - return pad_orientation_value.getSelectedIndex(); + if (pad_orientation_value.isEnabled()) + return pad_orientation_value.getSelectedIndex(); + else + return -1; } public void set_clean() { -- cgit v1.2.3 From 4f64d66295a8f76680af8cfda4650aa4c4f8576d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 19:19:50 -0700 Subject: altos: Lost change that reported flight 0 when log memory was full commit 52ac83fedbfd380d14d4df2e79992bbdfba3552a added coded to check for a full flight log and complain with a special tone. It also reported flight 0 over telemetry, and that part of the patch got lost when moving to the new telemetry format. This patch resurrects that piece. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 15ba4302..8a18ba07 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -101,7 +101,7 @@ ao_send_configuration(void) { telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.configuration.config_major = AO_CONFIG_MAJOR; telemetry.configuration.config_minor = AO_CONFIG_MINOR; telemetry.configuration.apogee_delay = ao_config.apogee_delay; -- cgit v1.2.3 From adb7d345963ab9981c49c7cc68c6b4d7156dce46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 21:09:42 -0700 Subject: altosui: Ancient log files used 'apogee' for 'coast' state 2009-07-18-serial-004-flight-000 says 'apogee' for the apogee-detect phase of the flight; map this to coast so that this flight replays correctly (although the log terminates at apogee...) Signed-off-by: Keith Packard --- altosui/Altos.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/Altos.java b/altosui/Altos.java index 416d9328..d3f8fa67 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -112,6 +112,7 @@ public class Altos { string_to_state.put("fast", ao_flight_fast); string_to_state.put("coast", ao_flight_coast); string_to_state.put("drogue", ao_flight_drogue); + string_to_state.put("apogee", ao_flight_coast); string_to_state.put("main", ao_flight_main); string_to_state.put("landed", ao_flight_landed); string_to_state.put("invalid", ao_flight_invalid); -- cgit v1.2.3 From 048b3eb45169e572f33c68ff152b89db9ef97d31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 21:11:41 -0700 Subject: altosui: Add 'On-board Data Logging' indicator to pad tab This shows whether the on-board data memory is full, or is ready to record the flight. This is indicated in the telemetry stream by a flight number of '0'. Signed-off-by: Keith Packard --- altosui/AltosPad.java | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index d08925be..2ed1ab2c 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -173,6 +173,29 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { Main main; + class LoggingReady extends LaunchStatus { + void show (AltosState state, int crc_errors) { + show(); + System.out.printf("flight %d state %d\n", state.data.flight, state.data.state); + if (state.data.flight != 0) { + if (state.data.state <= Altos.ao_flight_pad) + value.setText("Ready to record"); + else if (state.data.state < Altos.ao_flight_landed) + value.setText("Recording data"); + else + value.setText("Recorded data"); + } + else + value.setText("Storage full"); + lights.set(state.data.flight != 0); + } + public LoggingReady (GridBagLayout layout, int y) { + super(layout, y, "On-board Data Logging"); + } + } + + LoggingReady logging_ready; + class GPSLocked extends LaunchStatus { void show (AltosState state, int crc_errors) { show(); @@ -252,6 +275,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery.reset(); apogee.reset(); main.reset(); + logging_ready.reset(); gps_locked.reset(); gps_ready.reset(); pad_lat.reset(); @@ -269,6 +293,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { main.hide(); else main.show(state, crc_errors); + logging_ready.show(state, crc_errors); pad_alt.show(state, crc_errors); if (state.gps != null && state.gps.connected) { gps_locked.show(state, crc_errors); @@ -301,10 +326,11 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery = new Battery(layout, 0); apogee = new Apogee(layout, 1); main = new Main(layout, 2); - gps_locked = new GPSLocked(layout, 3); - gps_ready = new GPSReady(layout, 4); - pad_lat = new PadLat(layout, 5); - pad_lon = new PadLon(layout, 6); - pad_alt = new PadAlt(layout, 7); + logging_ready = new LoggingReady(layout, 3); + gps_locked = new GPSLocked(layout, 4); + gps_ready = new GPSReady(layout, 5); + pad_lat = new PadLat(layout, 6); + pad_lon = new PadLon(layout, 7); + pad_alt = new PadAlt(layout, 8); } } -- cgit v1.2.3 From 605627d03eeb9f34026a84134992ad061b5b3946 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 19 Aug 2011 22:47:50 -0600 Subject: update changelogs for Debian build --- ChangeLog | 707 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 71 ++++++ 2 files changed, 778 insertions(+) diff --git a/ChangeLog b/ChangeLog index bd8253c9..92baf49c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,710 @@ +commit ef7f60df841f1eb22b9cec0d7f68cf2c003d6b30 +Author: Keith Packard +Date: Sun Aug 14 00:00:54 2011 -0700 + + altosui: Respect storage limits in flight log max config + + Compute the maximum flight log using the data returned from the 'f' + command (total storage and erase block size). Limit menu to choices + which fall within this limit, complain if the user asks for too big a value. + + Signed-off-by: Keith Packard + +commit 746d6a472a20243a8c0eacc8edf8e81e0641bc17 +Author: Keith Packard +Date: Sun Aug 14 00:00:07 2011 -0700 + + altosui: don't set channel when using radio setting + + altos now sets the radio back to channel 0 when the radio setting is + changed. + + Signed-off-by: Keith Packard + +commit 709485f20fb039f8dd087c8491c5f5a76718ae53 +Author: Keith Packard +Date: Sat Aug 13 23:58:03 2011 -0700 + + altos: use raw height while waiting for landing + + This avoids any noise introduced by the kalman filter, making landing + detection much more reliable. This patch also changes the interval to + 10s so that the height bounds can be increased to 4m. + + Signed-off-by: Keith Packard + +commit aa71c2cdcb417eba2a2d30792ece9a47b8b3fc82 +Author: Keith Packard +Date: Sat Aug 13 23:56:55 2011 -0700 + + altos: Reset radio channel to zero when using radio setting + + Otherwise, it's hard to set the frequency over the radio link. + + Signed-off-by: Keith Packard + +commit 7f74761051f2a5ab45b82c4dd79a8569376bbe2e +Author: Keith Packard +Date: Sat Aug 13 23:56:06 2011 -0700 + + altos: Correct AO_CONFIG_MINOR from 6 to 7 + + Forgot to bump this when adding radio setting. + + Signed-off-by: Keith Packard + +commit 924d56a4d2d8b16530cd378b18cfc5d6e08420ed +Author: Keith Packard +Date: Sat Aug 13 21:10:15 2011 -0700 + + altos: AltosSerial.flush_input shouldn't discard Interrupted exceptions + + The eeprom download code wants to interrupt serial communication so + that it can stop downloading stuff in the middle of a run. Make + flush_input pass the exception along instead of discarding it. + + Signed-off-by: Keith Packard + +commit dcd15032eec45f3fdd003050710ebd5b85052662 +Author: Keith Packard +Date: Sat Aug 13 21:09:19 2011 -0700 + + altosui: Eliminate inter-chunk flush_input calls + + Once the serial line is nicely synchronized, we don't need to flush + input between chunks. This speeds up eeprom downloading quite a bit. + + Signed-off-by: Keith Packard + +commit 3ba7b6196f68078f4ed4538c4e7fe30699dfe908 +Author: Keith Packard +Date: Sat Aug 13 21:05:46 2011 -0700 + + altosui: Devices with log-format can also delete flights + + Any device with either flight-log-max or log-format can delete flights. + + Signed-off-by: Keith Packard + +commit 03e201e1acc8742399054e4ad36b533120ea1612 +Author: Keith Packard +Date: Sat Aug 13 18:39:35 2011 -0700 + + altosui: Add support for TeleScience eeprom download + + Using the existing eeprom methods, fetch and save TeleScience eeprom + data, storing to a filename generated from the serial/flight from the + TM connected to the TS board. + + Signed-off-by: Keith Packard + +commit 5a3e96bef31959a287b8696778d7d8cf911a7dc4 +Author: Keith Packard +Date: Sat Aug 13 18:36:18 2011 -0700 + + altosui: Clean up eeprom parsing a bit + + Export basic parsing and checksum functions for shared use. + Create 'erased' function to check a chunk of eeprom data for data. + + Signed-off-by: Keith Packard + +commit b0ec30de37aa822ba66d25ceaa8cf8dc967b4371 +Author: Keith Packard +Date: Sat Aug 13 18:31:08 2011 -0700 + + altos: wait 10s for companion to boot + + In case the companion is delayed while booting, retry the setup 10 + times with a 1s delay between tries. + + Signed-off-by: Keith Packard + +commit 41e5be32819d305c8268e6f992be91411ea13435 +Author: Keith Packard +Date: Sat Aug 13 18:30:00 2011 -0700 + + altos: Send serial/flight to companion board + + Lets the companion log them for later matching with TeleMetrum log + + Signed-off-by: Keith Packard + +commit fa7dd04741bf3fd9cedc59ed3b45b69ef9312609 +Author: Keith Packard +Date: Fri Aug 12 21:41:25 2011 -0700 + + altos: Send SPI message at flight state changes + + Get the companion board starting its data logging as soon as possible + after boost starts. + + Signed-off-by: Keith Packard + +commit c7f540330c040c521f9d7626009a406e704a5e41 +Author: Keith Packard +Date: Fri Aug 12 14:58:34 2011 -0700 + + altosui: Add companion support to the flight UI and CSV conversion + + Shows the companion data in a new tab. Also put companion data into + CSV file. + + Signed-off-by: Keith Packard + +commit 18369c58e62bc64b969a7cf8be3103aa33c6d4aa +Author: Keith Packard +Date: Fri Aug 12 06:29:13 2011 -0700 + + altos: Check for companion init packet validity was busted + + Was using board_id == ~board_id instead of board_id == + ~board_id_inverse. + + Signed-off-by: Keith Packard + +commit aa642cf55c43188e9a21198d828d7ea90ff54280 +Author: Keith Packard +Date: Fri Aug 12 05:42:05 2011 -0700 + + altos: add the 'L' command to show the status of a linked companion board + + This prints out whether there is a board connected, along with the + various values fetched from it. + + Signed-off-by: Keith Packard + +commit f87f0787fa5aa528674f3f4919eb22646c87c25a +Author: Keith Packard +Date: Fri Aug 12 05:41:15 2011 -0700 + + altos: Make sure companion task exits cleanly when done + + Signed-off-by: Keith Packard + +commit ebe2ffb29944abc4d6a35889c7b5f3d9f2871077 +Author: Keith Packard +Date: Fri Aug 12 05:38:16 2011 -0700 + + altos: Put SPI in slower mode when talking to companion board + + The AVR CPU on the other side just can't go very fast. This reduces + the SPI clock by a factor of 16, just under 200kHz. As the companion + commands are reasonably short, this shouldn't have a huge effect on + overall SPI utilization. + + Signed-off-by: Keith Packard + +commit 30abbdc7ffcfc809b4a3fc31486fe968161ea225 +Author: Keith Packard +Date: Sat Jul 9 16:59:16 2011 -0700 + + altos: Add SPI-based companion board support + + This sends current flight state information and retrieves companion + data to include in telemetry. + + Signed-off-by: Keith Packard + +commit 578c4b17b8f62f2727654ebda78ee139f9fe13fa +Author: Keith Packard +Date: Sat Aug 13 18:38:38 2011 -0700 + + altos: Don't try to use non-basestations for remote eeprom download + + Companion boards may also have eeprom data to fetch; don't try to use + them as a radio. + + Signed-off-by: Keith Packard + +commit bf06af154e232d4caa1585a1d6d5279a075292e4 +Author: Keith Packard +Date: Fri Aug 12 21:43:56 2011 -0700 + + altos/altosui: Report log format in the version command + + This will make it easier to figure out what the contents of the flash + should look like from altosui; the current 'guessing' mechanism will + not scale to many more formats. + + Signed-off-by: Keith Packard + +commit c2f2f519dbc8ce233ab36222088c1be6b1362f01 +Author: Keith Packard +Date: Sat Aug 13 18:28:38 2011 -0700 + + altos: re-write a bit of GPS parsing code to reduce size + + Use a local variable while computing hdop. + Place the next incoming character in data instead of pdata. + + Saved a surprising amount of memory. + + Signed-off-by: Keith Packard + +commit 7bcf25606cd5892d58295649f3d475d284494ee8 +Author: Keith Packard +Date: Fri Aug 12 05:26:09 2011 -0700 + + altos: shrink text space from ao_config.c + + Eliminate redundant config initializers by setting minor to zero and + letting upgrade code handle all of the new values. + + Stop computing (fake) frequency when showing radio channel + Stop computing feet when showing main deploy height + + Signed-off-by: Keith Packard + +commit 313d740b5284b24f1cc7a1ba5779136b55d49ebe +Author: Keith Packard +Date: Sat Aug 13 18:33:07 2011 -0700 + + libaltos: Mis-allocated device list in libaltos + + Would overrun mis-allocated array, causing chaos. + + Signed-off-by: Keith Packard + +commit 3b87dd6f46922cf5f98deb2dffa2148c4244e48e +Author: Keith Packard +Date: Sat Aug 13 15:00:14 2011 -0700 + + ao-tools: ao-list was crashing with more than 3 devices connected + + the list of devices was getting realloced for each new device, but + that realloc was too small. + + Signed-off-by: Keith Packard + +commit 640422c028a2be898aa3a9048a0f6fad2e43dd8d +Author: Keith Packard +Date: Thu Aug 11 16:11:34 2011 -0700 + + altos: remove monitor disable stubs from altimeter code + + Monitor mode in the ground-station boards must be disabled when the + radio is going to be used for another purpose, or the radio parameters + changed. That places monitor-mode disable calls in other parts of the + system which are shared with the altimeter code. + + Elide the ao_set_monitor calls for builds which do not include any + monitoring code. + + Signed-off-by: Keith Packard + +commit 1d13460412046c53f36466193329caaa657bb278 +Author: Keith Packard +Date: Thu Aug 11 15:59:47 2011 -0700 + + altos: Apply igniter boot pulse-width reduction to telemini + + TeleMini needs the same fix as TeleMetrum to reduce startup igniter + pulses. + + Signed-off-by: Keith Packard + +commit b520c32bcddabd42c07ceafa827694a3ae23a76f +Author: Keith Packard +Date: Thu Aug 11 15:57:58 2011 -0700 + + altos: Pull igniter pins low as soon as possible at boot time + + This reduces the pulse width on the igniter circuit caused by the + default cc1111 pin configuration at powerup time. + + Signed-off-by: Keith Packard + +commit 566b16e67be38c6425e616a5c38d641c4e1a9b12 +Author: Keith Packard +Date: Wed Aug 10 22:43:26 2011 -0700 + + doc: Add 1.0 release notes. + + Signed-off-by: Keith Packard + +commit a07b07d48f71b9a11e73a82db075cc57bad0c09f +Author: Keith Packard +Date: Wed Aug 10 22:14:32 2011 -0700 + + doc: Add release notes, include them in altusmetrum doc. Shuffle altusmetrum + + This adds release notes and includes them in the main altusmetrum doc + as well as making stand-alone html available for inclusion in the website. + + Signed-off-by: Keith Packard + +commit 5aa3e49f794ba5ed2680016f3dca47d67ae99836 +Author: Keith Packard +Date: Wed Aug 10 18:32:05 2011 -0700 + + doc: Add telemetry docs to debian/linux/mac/windows packages + + Signed-off-by: Keith Packard + +commit 7283deaa91e752acc45018ef2ea2f560b09af354 +Author: Keith Packard +Date: Wed Aug 10 18:22:16 2011 -0700 + + doc: Describe 'stats' tab in Graph UI, 'Graph Flight' button. + + Signed-off-by: Keith Packard + +commit 21837e0026c87635abf4baf2c6c574a7b274f449 +Author: Keith Packard +Date: Wed Aug 10 18:14:10 2011 -0700 + + doc: Document Ignite Mode and Pad Orientation configuration options + + Signed-off-by: Keith Packard + +commit 967c9d5ee691f87bf0d1e49ba055eb366e513e6a +Author: Keith Packard +Date: Wed Aug 10 17:43:58 2011 -0700 + + doc: Update altusmetrum.xsl for v1.0 software and TeleMini + + Add TeleMini references and sections as appropriate, update AltosUI + docs to describe new bits. + + Signed-off-by: Keith Packard + +commit be65308182363ca87db69db530297933324f3806 +Author: Keith Packard +Date: Wed Aug 10 16:01:25 2011 -0700 + + Bump version to 0.9.6.0 + + Signed-off-by: Keith Packard + +commit 9f5623c8c32a38eaeb63fa74ab370025ac015d52 +Author: Keith Packard +Date: Wed Aug 10 15:00:44 2011 -0700 + + altosui: Move launch-sites.txt file to altusmetrum.org + + The official URL is now: + + http://www.altusmetrum.org/AltOS/launch-sites.txt + + Signed-off-by: Keith Packard + +commit 4962bcf1ce15c21a946ea718bd676b901f0f2bd0 +Author: Keith Packard +Date: Wed Aug 10 14:35:21 2011 -0700 + + altosui: Plot reasonable data from Tm files + + Don't plot acceleration based on baro data. + Display baro speed if accel speed isn't available. + + Signed-off-by: Keith Packard + +commit 01b9352eb8ca0e4e2d023ce973c4e863cdcc0c51 +Author: Keith Packard +Date: Wed Aug 10 14:34:39 2011 -0700 + + altosui: Prune telemetry file graphs to just the flight + + Remove data earlier than 1 second before boost and data after landing. + + Signed-off-by: Keith Packard + +commit 9e1487b1a5db0afd1d23c86d82c60b1c1a62aab0 +Author: Keith Packard +Date: Wed Aug 10 14:08:21 2011 -0700 + + altosui: Add a 'Graph Flight' button to the 'landed' tab + + This lets you see the results of a flight as soon as the rocket lands + using the telemetry data. + + Signed-off-by: Keith Packard + +commit 6ac604d11de44cd824f09e4b467264a2b74be7bd +Author: Keith Packard +Date: Wed Aug 10 13:35:26 2011 -0700 + + Altosui: Add flight statistics tab to graph window + + Provide basic flight stats alongside the flight graph. + + Signed-off-by: Keith Packard + +commit 94d9a2c36fabdf24d6a0b985851e95e4eb181fd9 +Author: Keith Packard +Date: Tue Aug 9 18:28:19 2011 -0700 + + altosui: Ship TeleMini v1.0 firmware with fat blobs + + Signed-off-by: Keith Packard + +commit a680ce61bdcffeacb7f0e4dcef71a03cb7cfe07d +Author: Keith Packard +Date: Tue Aug 9 18:27:19 2011 -0700 + + altosui: Ensure serial code tracks reply nesting correctly + + Trap any exceptional return conditions from 'get_reply' to make sure + in_reply gets decremented. + + Signed-off-by: Keith Packard + +commit 12bfa6cc42e3689f09abae2bd2584cbacf2aa2e0 +Author: Keith Packard +Date: Tue Aug 9 18:26:07 2011 -0700 + + altosui: Don't export product defs from libaltos + + As we add new products, that would change the ABI generated for java, + invaliding old library versions sitting around for windows and mac. + + Signed-off-by: Keith Packard + +commit 81ad44d4b6d9ad2f6b91d0906e8543da82da424f +Author: Keith Packard +Date: Tue Aug 9 14:26:43 2011 -0700 + + altos: Switch telemini from v0.1 to v1.0 + + TeleMini production boards are firmware compatible with the v0.1 + design, so instead of creating another product, just rename the + existing one. + + Signed-off-by: Keith Packard + +commit f3985ef8bc69bcec13ce155567a8ed7c5c6051cb +Author: Keith Packard +Date: Mon Aug 8 20:41:34 2011 -0700 + + altosui: Add close button to 'fire' dialog + + Easier to hit than the tiny close box in the frame. + + Signed-off-by: Keith Packard + +commit cbf54a826d12c49b1b1996be247869d5ff4e2236 +Author: Keith Packard +Date: Mon Aug 8 20:38:44 2011 -0700 + + altosui: Make set of telemetries to use while scanning configurable + + with a preference to remember across application runs. + + Signed-off-by: Keith Packard + +commit 7146311d9df541e075b4450cf9656a9aa7ffdd93 +Author: Keith Packard +Date: Mon Aug 8 20:38:14 2011 -0700 + + altosui: Reading serial from swing thread only bad if remote + + Make the warning on this condition based on whether the link is remote. + + Signed-off-by: Keith Packard + +commit 2662c577a895c96fce7b2bf815b9e752d2dfbde6 +Author: Keith Packard +Date: Mon Aug 8 18:53:59 2011 -0700 + + altosui: Remove unused AltosConfigData from AltosTelemetryReader + + Now that AltosSerial manages this data, it's not needed here. + + Signed-off-by: Keith Packard + +commit 13eacb49de4312509c3a729a31dcda4d601f8a8b +Author: Keith Packard +Date: Mon Aug 8 18:53:27 2011 -0700 + + altosui: Flush radio setting to serial device + + When changing frequencies, make sure the device hears about it. + + Signed-off-by: Keith Packard + +commit 97cf285d041062ae473c2823438b81c8fffe7f67 +Author: Keith Packard +Date: Mon Aug 8 18:53:03 2011 -0700 + + altosui: Remove debugging printfs from AltosSerial + + Signed-off-by: Keith Packard + +commit 364102d29ff4de0c252774f26417587fa88b7467 +Author: Keith Packard +Date: Mon Aug 8 18:52:11 2011 -0700 + + altosui: Show AltosFrequency in scan results + + Include frequency and description instead of just frequency. + + Signed-off-by: Keith Packard + +commit d4cc16e111229b02d1081e2693ace0b33f662498 +Author: Keith Packard +Date: Mon Aug 8 18:51:16 2011 -0700 + + altosui: Save frequency after setting it in AltosFlightUI + + Otherwise we'll just save the old frequency. + + Signed-off-by: Keith Packard + +commit 81bb6f42d8b859195ea5a35806c42d98ba82e8e1 +Author: Keith Packard +Date: Mon Aug 8 18:49:45 2011 -0700 + + altosui: Have single radio_to_frequency function + + This takes all three radio params (setting, cal, channel) and computes + the current frequency. + + Signed-off-by: Keith Packard + +commit c8c01684fa011acf3bbe5c3ebbc84aa8e8457a5e +Author: Keith Packard +Date: Mon Aug 8 18:47:36 2011 -0700 + + altosui: A few misc cleanups. + + Initialize radio_setting as it won't be set for older devices ever. + Remove unused set_radio_frequency function from AltosConfigUI. + + Signed-off-by: Keith Packard + +commit dd383b86b9a13d7af2d6b07f4fb85ccc666ed898 +Author: Keith Packard +Date: Mon Aug 8 18:45:36 2011 -0700 + + altosui: Must set radio calibration before radio setting + + Setting the radio calibration erases any previous radio setting as + the radio calibration change invalidates any previously computed radio + setting for a specific frequency. + + Hence, the radio setting must be configured *after* the radio + calibration value lest it be ignored. + + Signed-off-by: Keith Packard + +commit 40544dbfe09c64f7764a5f0686415805611fab25 +Author: Keith Packard +Date: Mon Aug 8 17:46:04 2011 -0700 + + altos: minor type in comment about accel correction + + Kurt Roeckx found a typo in the equations describing how the + accelerometer is corrected by the 5V reference measurement. + + Signed-off-by: Keith Packard + +commit a315b200cd0da1a964f5395cd59660be1b49672b +Author: Keith Packard +Date: Mon Aug 8 12:31:48 2011 -0700 + + altosui: Pull out BlueTooth support + + This leaves the code in place, but commented out so that it isn't used + until we've got a bluetooth device ready for use. + + Signed-off-by: Keith Packard + +commit a65daf94e8fe3e22f770ef76d9104c3dd11d0330 +Author: Keith Packard +Date: Mon Aug 8 12:25:30 2011 -0700 + + altosui: altimeter is not spelled altimter + + Signed-off-by: Keith Packard + +commit 84ba927f503f81543dec286c4881be30bb5e60c5 +Author: Keith Packard +Date: Mon Aug 8 02:05:28 2011 -0700 + + Set version to 0.9.5.0 + + Make the frequency-based systems distinct + + Signed-off-by: Keith Packard + +commit 0e3e4f9c1e6a6bf972514f12c9d622258aa2aec2 +Author: Keith Packard +Date: Mon Aug 8 01:47:29 2011 -0700 + + altosui: Convert from channels to frequencies + + Major areas: + + * Preferences are stored as frequencies instead + of channels + + * Serial configuration is done using frequencies + + * UI is presented with frequency lists + + Signed-off-by: Keith Packard + +commit f03ca0ab8799bfa5100eaa2577cfd7b9c37d05bf +Author: Keith Packard +Date: Sun Aug 7 14:52:29 2011 -0700 + + altosui: Add dialogs to configure 'common' frequencies + + These are stored in preferences, but not yet hooked up to the TM/TD + configure dialogs + + Signed-off-by: Keith Packard + +commit ba5dc35388d28c5769eaabc970c4d4b8c2c2ff9c +Author: Keith Packard +Date: Wed Aug 3 23:07:53 2011 -0700 + + altos: Add ability to set arbitrary radio frequency + + This adds a separate config parameter to control the raw radio + frequency setting, allowing the user to select an arbitrary frequency + instead of being forced to choose one of the 10 pre-defined 'channels'. + + Signed-off-by: Keith Packard + +commit e1e5c9b3e24670e9f58c6f7389eafb3338efdb40 +Author: Keith Packard +Date: Mon Aug 8 12:08:45 2011 -0700 + + altos: Remove pad_orientation functions from non-accel devices + + Anything without an accelerometer can't detect pad orientation. + + Signed-off-by: Keith Packard + +commit 7207a95823dc2a27906759528dd88256cb20679f +Author: Keith Packard +Date: Mon Aug 8 12:04:00 2011 -0700 + + altosui: Change button to 'Configure Altimeter' + + Now that we've got more than one model. + + Signed-off-by: Keith Packard + +commit 30670732ca3f5a34025ab4bc4c69afa45637b4d6 +Author: Keith Packard +Date: Mon Aug 8 11:58:23 2011 -0700 + + altos: Correct flight log max on Tm to 5k + + Was using the wrong #define name to check for Tm/Tn devices that use + internal flash for data storage. + + Signed-off-by: Keith Packard + +commit a67c16958df8e60b131b01e00fd5bca590af0e7d +Author: Bdale Garbee +Date: Mon Aug 8 09:38:53 2011 -0600 + + update changelogs for Debian build + commit 4a507898d6de631bb2e8ed4aa3e0933d97222323 Author: Bdale Garbee Date: Mon Aug 8 09:34:59 2011 -0600 diff --git a/debian/changelog b/debian/changelog index 858a65b3..e786b10f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,74 @@ +altos (0.9.6.0) unstable; urgency=low + + [ Keith Packard ] + * altos: Correct flight log max on Tm to 5k + * altosui: Change button to 'Configure Altimeter' + * altos: Remove pad_orientation functions from non-accel devices + * altos: Add ability to set arbitrary radio frequency + * altosui: Add dialogs to configure 'common' frequencies + * altosui: Convert from channels to frequencies + * Set version to 0.9.5.0 + * altosui: altimeter is not spelled altimter + * altosui: Pull out BlueTooth support + * altos: minor type in comment about accel correction + * altosui: Must set radio calibration before radio setting + * altosui: A few misc cleanups. + * altosui: Have single radio_to_frequency function + * altosui: Save frequency after setting it in AltosFlightUI + * altosui: Show AltosFrequency in scan results + * altosui: Remove debugging printfs from AltosSerial + * altosui: Flush radio setting to serial device + * altosui: Remove unused AltosConfigData from AltosTelemetryReader + * altosui: Reading serial from swing thread only bad if remote + * altosui: Make set of telemetries to use while scanning configurable + * altosui: Add close button to 'fire' dialog + * altos: Switch telemini from v0.1 to v1.0 + * altosui: Don't export product defs from libaltos + * altosui: Ensure serial code tracks reply nesting correctly + * altosui: Ship TeleMini v1.0 firmware with fat blobs + * Altosui: Add flight statistics tab to graph window + * altosui: Add a 'Graph Flight' button to the 'landed' tab + * altosui: Prune telemetry file graphs to just the flight + * altosui: Plot reasonable data from Tm files + * altosui: Move launch-sites.txt file to altusmetrum.org + * Bump version to 0.9.6.0 + * doc: Update altusmetrum.xsl for v1.0 software and TeleMini + * doc: Document Ignite Mode and Pad Orientation configuration options + * doc: Describe 'stats' tab in Graph UI, 'Graph Flight' button. + * doc: Add telemetry docs to debian/linux/mac/windows packages + * doc: Add release notes, include them in altusmetrum doc. Shuffle altusmetrum + * doc: Add 1.0 release notes. + * altos: Pull igniter pins low as soon as possible at boot time + * altos: Apply igniter boot pulse-width reduction to telemini + * altos: remove monitor disable stubs from altimeter code + * ao-tools: ao-list was crashing with more than 3 devices connected + * libaltos: Mis-allocated device list in libaltos + * altos: shrink text space from ao_config.c + * altos: re-write a bit of GPS parsing code to reduce size + * altos/altosui: Report log format in the version command + * altos: Don't try to use non-basestations for remote eeprom download + * altos: Add SPI-based companion board support + * altos: Put SPI in slower mode when talking to companion board + * altos: Make sure companion task exits cleanly when done + * altos: add the 'L' command to show the status of a linked companion board + * altos: Check for companion init packet validity was busted + * altosui: Add companion support to the flight UI and CSV conversion + * altos: Send SPI message at flight state changes + * altos: Send serial/flight to companion board + * altos: wait 10s for companion to boot + * altosui: Clean up eeprom parsing a bit + * altosui: Add support for TeleScience eeprom download + * altosui: Devices with log-format can also delete flights + * altosui: Eliminate inter-chunk flush_input calls + * altos: AltosSerial.flush_input shouldn't discard Interrupted exceptions + * altos: Correct AO_CONFIG_MINOR from 6 to 7 + * altos: Reset radio channel to zero when using radio setting + * altos: use raw height while waiting for landing + * altosui: don't set channel when using radio setting + * altosui: Respect storage limits in flight log max config + + -- Bdale Garbee Fri, 19 Aug 2011 22:47:25 -0600 + altos (0.9.4.5) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 787e4305a05e344c018abb872f788749203690d7 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 20 Aug 2011 09:24:29 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index 92baf49c..b977d89c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 605627d03eeb9f34026a84134992ad061b5b3946 +Author: Bdale Garbee +Date: Fri Aug 19 22:47:50 2011 -0600 + + update changelogs for Debian build + commit ef7f60df841f1eb22b9cec0d7f68cf2c003d6b30 Author: Keith Packard Date: Sun Aug 14 00:00:54 2011 -0700 -- cgit v1.2.3 From 3366cfe6145f64cdb04654854d5390c671a288e3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 20 Aug 2011 09:28:04 -0600 Subject: update changelogs for Debian build --- ChangeLog | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ChangeLog b/ChangeLog index b977d89c..14a32f04 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +commit 787e4305a05e344c018abb872f788749203690d7 +Author: Bdale Garbee +Date: Sat Aug 20 09:24:29 2011 -0600 + + update changelogs for Debian build + commit 605627d03eeb9f34026a84134992ad061b5b3946 Author: Bdale Garbee Date: Fri Aug 19 22:47:50 2011 -0600 -- cgit v1.2.3 From fcff63baf8fde1174571a2c7c860099e19dbf629 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Aug 2011 10:43:28 -0700 Subject: altosui: remove debug printf in pad pane Signed-off-by: Keith Packard --- altosui/AltosPad.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 2ed1ab2c..3a8d04fe 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -176,7 +176,6 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class LoggingReady extends LaunchStatus { void show (AltosState state, int crc_errors) { show(); - System.out.printf("flight %d state %d\n", state.data.flight, state.data.state); if (state.data.flight != 0) { if (state.data.state <= Altos.ao_flight_pad) value.setText("Ready to record"); -- cgit v1.2.3 From 67f28c58db0deca8f8050d33e97ad96017f4baaa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Aug 2011 11:19:57 -0700 Subject: altosui: Disable 'max flight log' config when there are stored flights When flights are stored in flash, the maximum flight log value cannot be changed as the flight data might need to be moved around in memory. Check for this case by looking for stored flights and disabling the combo box when storage is not empty. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 7 ++++++- altosui/AltosConfigUI.java | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 9a44c1c5..84c8a4a3 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -78,6 +78,7 @@ public class AltosConfig implements ActionListener { int_ref radio_setting; int_ref storage_size; int_ref storage_erase_unit; + int_ref stored_flight; string_ref version; string_ref product; string_ref callsign; @@ -146,6 +147,7 @@ public class AltosConfig implements ActionListener { config_ui.set_apogee_delay(apogee_delay.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); + config_ui.set_flight_log_max_enabled(stored_flight.get() < 0); config_ui.set_flight_log_max_limit(log_limit()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); @@ -177,6 +179,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Radio setting:", radio_setting); get_int(line, "Storage size:", storage_size); get_int(line, "Storage erase unit:", storage_erase_unit); + get_int(line, "flight", stored_flight); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -206,7 +209,8 @@ public class AltosConfig implements ActionListener { void get_data() { try { config.start_serial(); - config.serial_line.printf("c s\nf\nv\n"); + stored_flight.set(-1); + config.serial_line.printf("c s\nf\nl\nv\n"); for (;;) { try { String line = config.serial_line.get_reply(5000); @@ -413,6 +417,7 @@ public class AltosConfig implements ActionListener { pad_orientation = new int_ref(-1); storage_size = new int_ref(-1); storage_erase_unit = new int_ref(-1); + stored_flight = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 63e0ba78..69afd691 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -573,6 +573,10 @@ public class AltosConfigUI flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max)); } + public void set_flight_log_max_enabled(boolean enable) { + flight_log_max_value.setEnabled(enable); + } + public int flight_log_max() { return Integer.parseInt(flight_log_max_value.getSelectedItem().toString()); } -- cgit v1.2.3 From f2b0900f8b83fcb3085f3d042ffd961ffd758d5d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Aug 2011 11:28:53 -0700 Subject: altos: Merge common config code in ao_config.c This shuffles code around in ao_config.c to share some common code segments for starting and committing config changes. This also stops printing out changes as they are made which aren't needed by the UI code. Signed-off-by: Keith Packard --- src/ao_config.c | 104 +++++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 62 deletions(-) diff --git a/src/ao_config.c b/src/ao_config.c index 331509e2..e0eae78e 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -105,11 +105,24 @@ _ao_config_get(void) ao_config_loaded = 1; } -void -ao_config_get(void) +static void +_ao_config_edit_start(void) { ao_mutex_get(&ao_config_mutex); _ao_config_get(); +} + +static void +_ao_config_edit_finish(void) +{ + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_get(void) +{ + _ao_config_edit_start(); ao_mutex_put(&ao_config_mutex); } @@ -137,13 +150,10 @@ ao_config_callsign_set(void) __reentrant } if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); memcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_callsign_show(); + _ao_config_edit_finish(); } void @@ -159,12 +169,9 @@ ao_config_radio_channel_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_channel = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_channel_show(); + _ao_config_edit_finish(); ao_radio_recv_abort(); } @@ -183,12 +190,9 @@ ao_config_main_deploy_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.main_deploy = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_main_deploy_show(); + _ao_config_edit_finish(); } #if HAS_ACCEL @@ -250,13 +254,10 @@ ao_config_accel_calibrate_set(void) __reentrant up, down); return; } - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.accel_plus_g = up; ao_config.accel_minus_g = down; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_accel_calibrate_show(); + _ao_config_edit_finish(); } #endif /* HAS_ACCEL */ @@ -273,12 +274,9 @@ ao_config_apogee_delay_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.apogee_delay = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_apogee_delay_show(); + _ao_config_edit_finish(); } #endif /* HAS_ADC */ @@ -295,12 +293,9 @@ ao_config_radio_cal_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_cal_show(); + _ao_config_edit_finish(); } #if HAS_EEPROM @@ -326,12 +321,9 @@ ao_config_log_set(void) __reentrant else if (ao_cmd_lex_i > config) printf("Flight log max %d kB\n", config); else { - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + _ao_config_edit_finish(); } } #endif /* HAS_EEPROM */ @@ -349,12 +341,9 @@ ao_config_ignite_mode_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.ignite_mode = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_ignite_mode_show(); + _ao_config_edit_finish(); } #endif @@ -371,8 +360,7 @@ ao_config_pad_orientation_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_cmd_lex_i &= 1; if (ao_config.pad_orientation != ao_cmd_lex_i) { uint16_t t; @@ -381,9 +369,7 @@ ao_config_pad_orientation_set(void) __reentrant ao_config.accel_minus_g = 0x7fff - t; } ao_config.pad_orientation = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_pad_orientation_show(); + _ao_config_edit_finish(); } #endif @@ -399,13 +385,10 @@ ao_config_radio_setting_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_setting = ao_cmd_lex_u32; ao_config.radio_channel = 0; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_setting_show(); + _ao_config_edit_finish(); ao_radio_recv_abort(); } @@ -456,13 +439,13 @@ __code struct ao_config_var ao_config_vars[] = { { "R \0Radio freq control (freq = 434.550 * setting/cal)", ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", - ao_config_show, ao_config_show }, + ao_config_show, 0 }, #if HAS_EEPROM { "w\0Write to eeprom", - ao_config_write, ao_config_write }, + ao_config_write, 0 }, #endif { "?\0Help", - ao_config_help, ao_config_help }, + ao_config_help, 0 }, { 0, 0, 0 } }; @@ -479,13 +462,10 @@ ao_config_set(void) func = 0; for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].str[0] == c) { - func = ao_config_vars[cmd].set; - break; + (*ao_config_vars[cmd].set)(); + return; } - if (func) - (*func)(); - else - ao_cmd_status = ao_cmd_syntax_error; + ao_cmd_status = ao_cmd_syntax_error; } static void @@ -505,7 +485,7 @@ ao_config_show(void) __reentrant printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) + if (ao_config_vars[cmd].show) (*ao_config_vars[cmd].show)(); } -- cgit v1.2.3 From a08e7ac8bd3840b699c9a1ffc6b1e115b2b84bad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Aug 2011 11:35:55 -0700 Subject: Bump version to 0.9.7 Bdale is flying 0.9.6 at chili blaster, make sure later firmware gets a later version number. Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2bd3120a..93f53115 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.6.0) +AC_INIT([altos], 0.9.7.0) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 6823ad5e48fc0a19791d96f886b5689f88c4311b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Aug 2011 18:02:02 -0700 Subject: altos/altosui: Add ability to disable telemetry/rdf completely This turns off the telemetry system so that it never transmits telemetry or RDF tones. In idle mode, it will still accept packet mode connections. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 8 ++++++ altosui/AltosConfigUI.java | 65 +++++++++++++++++++++++++++++++++++++--------- src/ao.h | 3 ++- src/ao_config.c | 25 ++++++++++++++++-- src/ao_telemetry.c | 2 ++ 5 files changed, 88 insertions(+), 15 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 84c8a4a3..b1e6bc12 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -79,6 +79,7 @@ public class AltosConfig implements ActionListener { int_ref storage_size; int_ref storage_erase_unit; int_ref stored_flight; + int_ref radio_enable; string_ref version; string_ref product; string_ref callsign; @@ -148,6 +149,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); config_ui.set_flight_log_max_enabled(stored_flight.get() < 0); + config_ui.set_radio_enable(radio_enable.get()); config_ui.set_flight_log_max_limit(log_limit()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); @@ -177,6 +179,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); get_int(line, "Radio setting:", radio_setting); + get_int(line, "Radio enable:", radio_enable); get_int(line, "Storage size:", storage_size); get_int(line, "Storage erase unit:", storage_erase_unit); get_int(line, "flight", stored_flight); @@ -255,6 +258,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); + if (radio_enable.get() >= 0) + serial_line.printf("c e %d\n", radio_enable.get()); if (ignite_mode.get() >= 0) serial_line.printf("c i %d\n", ignite_mode.get()); if (pad_orientation.get() >= 0) @@ -373,6 +378,8 @@ public class AltosConfig implements ActionListener { radio_calibration.set(config_ui.radio_calibration()); set_frequency(config_ui.radio_frequency()); flight_log_max.set(config_ui.flight_log_max()); + if (radio_enable.get() >= 0) + radio_enable.set(config_ui.radio_enable()); if (ignite_mode.get() >= 0) ignite_mode.set(config_ui.ignite_mode()); if (pad_orientation.get() >= 0) @@ -412,6 +419,7 @@ public class AltosConfig implements ActionListener { radio_channel = new int_ref(0); radio_setting = new int_ref(0); radio_calibration = new int_ref(1186611); + radio_enable = new int_ref(-1); flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); pad_orientation = new int_ref(-1); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 69afd691..bb9e1cd2 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -46,6 +46,7 @@ public class AltosConfigUI JLabel frequency_label; JLabel radio_calibration_label; JLabel radio_frequency_label; + JLabel radio_enable_label; JLabel flight_log_max_label; JLabel ignite_mode_label; JLabel pad_orientation_label; @@ -61,6 +62,7 @@ public class AltosConfigUI JComboBox apogee_delay_value; AltosFreqList radio_frequency_value; JTextField radio_calibration_value; + JRadioButton radio_enable_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; JComboBox pad_orientation_value; @@ -287,7 +289,7 @@ public class AltosConfigUI radio_calibration_value.setEnabled(false); pane.add(radio_calibration_value, c); - /* Callsign */ + /* Radio Enable */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 7; c.gridwidth = 4; @@ -295,11 +297,34 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = il; c.ipady = 5; + radio_enable_label = new JLabel("Telemetry/RDF Enable:"); + pane.add(radio_enable_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 7; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_enable_value = new JRadioButton("Enabled"); + radio_enable_value.addItemListener(this); + pane.add(radio_enable_value, c); + + /* Callsign */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 8; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; callsign_label = new JLabel("Callsign:"); pane.add(callsign_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 7; + c.gridx = 4; c.gridy = 8; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -312,7 +337,7 @@ public class AltosConfigUI /* Flight log max */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; + c.gridx = 0; c.gridy = 9; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -322,7 +347,7 @@ public class AltosConfigUI pane.add(flight_log_max_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 8; + c.gridx = 4; c.gridy = 9; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -336,7 +361,7 @@ public class AltosConfigUI /* Ignite mode */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 9; + c.gridx = 0; c.gridy = 10; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -346,7 +371,7 @@ public class AltosConfigUI pane.add(ignite_mode_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 9; + c.gridx = 4; c.gridy = 10; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -360,7 +385,7 @@ public class AltosConfigUI /* Pad orientation */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 10; + c.gridx = 0; c.gridy = 11; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -370,7 +395,7 @@ public class AltosConfigUI pane.add(pad_orientation_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 10; + c.gridx = 4; c.gridy = 11; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -384,7 +409,7 @@ public class AltosConfigUI /* Buttons */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 11; + c.gridx = 0; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -395,7 +420,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 11; + c.gridx = 2; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -406,7 +431,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 11; + c.gridx = 4; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -417,7 +442,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 11; + c.gridx = 6; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -559,6 +584,22 @@ public class AltosConfigUI return Integer.parseInt(radio_calibration_value.getText()); } + public void set_radio_enable(int new_radio_enable) { + if (new_radio_enable >= 0) + radio_enable_value.setSelected(new_radio_enable > 0); + else { + radio_enable_value.setSelected(true); + radio_enable_value.setEnabled(false); + } + } + + public int radio_enable() { + if (radio_enable_value.isEnabled()) + return radio_enable_value.isSelected() ? 1 : 0; + else + return -1; + } + public void set_callsign(String new_callsign) { callsign_value.setText(new_callsign); } diff --git a/src/ao.h b/src/ao.h index 79452862..8ac9ac3d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1415,7 +1415,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 7 +#define AO_CONFIG_MINOR 8 struct ao_config { uint8_t major; @@ -1431,6 +1431,7 @@ struct ao_config { uint8_t ignite_mode; /* minor version 5 */ uint8_t pad_orientation; /* minor version 6 */ uint32_t radio_setting; /* minor version 7 */ + uint8_t radio_enable; /* minor version 8 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/ao_config.c b/src/ao_config.c index e0eae78e..eb1eea3f 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -99,6 +99,8 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 7) ao_config.radio_setting = ao_config.radio_cal; + if (ao_config.minor < 8) + ao_config.radio_enable = TRUE; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -392,6 +394,23 @@ ao_config_radio_setting_set(void) __reentrant ao_radio_recv_abort(); } +void +ao_config_radio_enable_show(void) __reentrant +{ + printf("Radio enable: %d\n", ao_config.radio_enable); +} + +void +ao_config_radio_enable_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_enable = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -418,6 +437,10 @@ __code struct ao_config_var ao_config_vars[] = { ao_config_radio_channel_set, ao_config_radio_channel_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, + { "e <0 disable, 1 enable>\0Enable telemetry and RDF", + ao_config_radio_enable_set, ao_config_radio_enable_show }, #if HAS_ACCEL { "a <+g> <-g>\0Accel calib (0 for auto)", ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, @@ -436,8 +459,6 @@ __code struct ao_config_var ao_config_vars[] = { { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", ao_config_show, 0 }, #if HAS_EEPROM diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 8a18ba07..c7338a58 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -180,6 +180,8 @@ ao_telemetry(void) int16_t delay; ao_config_get(); + if (!ao_config.radio_enable) + ao_exit(); while (!ao_flight_number) ao_sleep(&ao_flight_number); -- cgit v1.2.3 From 55be3db2e31fe97e7f351e3c490b8bc4cf7192b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 19:18:54 -0700 Subject: altosui: Clean up command line processing. Add --graph Make the command line processing a bit less ad-hoc, track 'mode' of processing and deal with all files on the command line. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 188 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 123 insertions(+), 65 deletions(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 62e612ed..b2c5107e 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -364,93 +364,151 @@ public class AltosUI extends JFrame { } } + static final int process_none = 0; static final int process_csv = 1; static final int process_kml = 2; + static final int process_graph = 3; + static final int process_replay = 4; - static void process_file(String input, int process) { + static void process_csv(String input) { AltosRecordIterable iterable = open_logfile(input); if (iterable == null) return; - if (process == 0) - process = process_csv; - if ((process & process_csv) != 0) { - String output = Altos.replace_extension(input,".csv"); - System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); - if (input.equals(output)) { - System.out.printf("Not processing '%s'\n", input); - } else { - AltosWriter writer = open_csv("/dev/stdout"); - if (writer != null) { - writer.write(iterable); - writer.close(); - } - } + + String output = Altos.replace_extension(input,".csv"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_csv(output); + if (writer == null) + return; + writer.write(iterable); + writer.close(); } - if ((process & process_kml) != 0) { - String output = Altos.replace_extension(input,".kml"); - System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); - if (input.equals(output)) { - System.out.printf("Not processing '%s'\n", input); - } else { - AltosWriter writer = open_kml(output); - if (writer == null) - return; - writer.write(iterable); - writer.close(); - } + } + + static void process_kml(String input) { + AltosRecordIterable iterable = open_logfile(input); + if (iterable == null) + return; + + String output = Altos.replace_extension(input,".kml"); + System.out.printf("Processing \"%s\" to \"%s\"\n", input, output); + if (input.equals(output)) { + System.out.printf("Not processing '%s'\n", input); + } else { + AltosWriter writer = open_kml(output); + if (writer == null) + return; + writer.write(iterable); + writer.close(); } } - public static void main(final String[] args) { - int process = 0; - /* Handle batch-mode */ - if (args.length == 1 && args[0].equals("--help")) { + static void process_replay(String filename) { + FileInputStream in; + try { + in = new FileInputStream(filename); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", filename); + return; + } + AltosRecordIterable recs; + AltosReplayReader reader; + if (filename.endsWith("eeprom")) { + recs = new AltosEepromIterable(in); + } else { + recs = new AltosTelemetryIterable(in); + } + reader = new AltosReplayReader(recs.iterator(), new File(filename)); + AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); + flight_ui.set_exit_on_close(); + } + + static void process_graph(String filename) { + FileInputStream in; + try { + in = new FileInputStream(filename); + } catch (Exception e) { + System.out.printf("Failed to open file '%s'\n", filename); + return; + } + AltosRecordIterable recs; + if (filename.endsWith("eeprom")) { + recs = new AltosEepromIterable(in); + } else { + recs = new AltosTelemetryIterable(in); + } + try { + new AltosGraphUI(recs); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + } + + public static void help(int code) { System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); System.out.printf(" Options:\n"); System.out.printf(" --fetchmaps \tpre-fetch maps for site map view\n"); System.out.printf(" --replay \t\trelive the glory of past flights \n"); + System.out.printf(" --graph \t\tgraph a flight\n"); System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n"); System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n"); - } else if (args.length == 3 && args[0].equals("--fetchmaps")) { - double lat = Double.parseDouble(args[1]); - double lon = Double.parseDouble(args[2]); - AltosSiteMap.prefetchMaps(lat, lon, 5, 5); - } else if (args.length == 2 && args[0].equals("--replay")) { - String filename = args[1]; - FileInputStream in; - try { - in = new FileInputStream(filename); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); - return; - } - AltosRecordIterable recs; - AltosReplayReader reader; - if (filename.endsWith("eeprom")) { - recs = new AltosEepromIterable(in); - } else { - recs = new AltosTelemetryIterable(in); - } - reader = new AltosReplayReader(recs.iterator(), new File(filename)); - AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); - flight_ui.set_exit_on_close(); - return; - } else if (args.length > 0) { - for (int i = 0; i < args.length; i++) { - if (args[i].equals("--kml")) - process |= process_kml; - else if (args[i].equals("--csv")) - process |= process_csv; - else - process_file(args[i], process); - } - } else { + System.exit(code); + } + + public static void main(final String[] args) { + /* Handle batch-mode */ + if (args.length == 0) { AltosUI altosui = new AltosUI(); altosui.setVisible(true); java.util.List devices = AltosUSBDevice.list(Altos.product_basestation); for (AltosDevice device : devices) altosui.telemetry_window(device); + } else { + int process = process_none; + for (int i = 0; i < args.length; i++) { + if (args[i].equals("--help")) + help(0); + else if (args[i].equals("--fetchmaps")) { + if (args.length < i + 3) { + help(1); + } else { + double lat = Double.parseDouble(args[i+1]); + double lon = Double.parseDouble(args[i+2]); + AltosSiteMap.prefetchMaps(lat, lon, 5, 5); + i += 2; + } + } else if (args[i].equals("--replay")) + process = process_replay; + else if (args[i].equals("--kml")) + process = process_kml; + else if (args[i].equals("--csv")) + process = process_csv; + else if (args[i].equals("--graph")) + process = process_graph; + else if (args[i].startsWith("--")) + help(1); + else { + switch (process) { + case process_none: + case process_graph: + process_graph(args[i]); + break; + case process_replay: + process_replay(args[i]); + break; + case process_kml: + process_kml(args[i]); + break; + case process_csv: + process_csv(args[i]); + break; + } + } + } } } } -- cgit v1.2.3 From 2353d83be15b398754c2564f95374c6ea0f8de92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 22:12:04 -0700 Subject: altos-fat/windows: Check and install Java 1.6 as needed Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 7c9b7a28..70dc03ca 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -1,4 +1,8 @@ !addplugindir Instdrv/NSIS/Plugins +; Definitions for Java 1.6 Detection +!define JRE_VERSION "1.6" +!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=18714&/jre-6u5-windows-i586-p.exe" +!define PRODUCT_NAME "Altus Metrum Windows Software" Name "Altus Metrum Installer" @@ -18,6 +22,31 @@ ShowInstDetails Show ComponentText "Altus Metrum Software and Driver Installer" +Function GetJRE + MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION}, it will now \ + be downloaded and installed" + + StrCpy $2 "$TEMP\Java Runtime Environment.exe" + nsisdl::download /TIMEOUT=30000 ${JRE_URL} $2 + Pop $R0 ;Get the return value + StrCmp $R0 "success" +3 + MessageBox MB_OK "Download failed: $R0" + Quit + ExecWait $2 + Delete $2 +FunctionEnd + + +Function DetectJRE + ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \ + "CurrentVersion" + StrCmp $2 ${JRE_VERSION} done + + Call GetJRE + + done: +FunctionEnd + ; Pages to present Page license @@ -51,6 +80,8 @@ Section "Install Driver" InstDriver SectionEnd Section "AltosUI Application" + Call DetectJRE + SetOutPath $INSTDIR File "altosui-fat.jar" @@ -68,7 +99,7 @@ Section "AltosUI Application" File "../icon/*.ico" - CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$INSTDIR\altosui-fat.jar" "" "$INSTDIR\altus-metrum.ico" + CreateShortCut "$SMPROGRAMS\AltusMetrum.lnk" "$SYSDIR\javaw.exe" "-jar altosui-fat.jar" "$INSTDIR\altus-metrum.ico" SectionEnd Section "AltosUI Desktop Shortcut" @@ -99,12 +130,12 @@ 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"' -- cgit v1.2.3 From d5bd40847b17c32405dfba864a2a5a3b19aa7e85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 22:12:53 -0700 Subject: altosui/windows: Fix a bunch of windows compiler warnings. Some of these may have actually been serious -- a write length was getting stored in a signed char... Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index f2c8bd8d..21e94ca0 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -882,7 +882,7 @@ altos_list_start(void) list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES|DIGCF_PRESENT); if (list->dev_info == INVALID_HANDLE_VALUE) { - printf("SetupDiGetClassDevs failed %d\n", GetLastError()); + printf("SetupDiGetClassDevs failed %ld\n", GetLastError()); free(list); return NULL; } @@ -894,13 +894,13 @@ PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device) { SP_DEVINFO_DATA dev_info_data; - char port[128]; + BYTE port[128]; DWORD port_len; char friendlyname[256]; - char symbolic[256]; + BYTE symbolic[256]; DWORD symbolic_len; HKEY dev_key; - int vid, pid; + unsigned int vid, pid; int serial; HRESULT result; DWORD friendlyname_type; @@ -931,11 +931,11 @@ altos_list_next(struct altos_list *list, struct altos_device *device) continue; } vid = pid = serial = 0; - sscanf(symbolic + sizeof("\\??\\USB#VID_") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1, "%04X", &vid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1, "%04X", &pid); - sscanf(symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, + sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1, "%d", &serial); if (!USB_IS_ALTUSMETRUM(vid, pid)) { RegCloseKey(dev_key); @@ -971,12 +971,12 @@ altos_list_next(struct altos_list *list, struct altos_device *device) device->serial = serial; strcpy(device->name, friendlyname); - strcpy(device->path, port); + strcpy(device->path, (char *) port); return 1; } result = GetLastError(); if (result != ERROR_NO_MORE_ITEMS) - printf ("SetupDiEnumDeviceInfo failed error %d\n", result); + printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); return 0; } @@ -1059,10 +1059,10 @@ altos_fill(struct altos_file *file, int timeout) PUBLIC int altos_flush(struct altos_file *file) { - DWORD put; - char *data = file->out_data; - char used = file->out_used; - DWORD ret; + DWORD put; + unsigned char *data = file->out_data; + int used = file->out_used; + DWORD ret; while (used) { if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { @@ -1150,7 +1150,7 @@ altos_free(struct altos_file *file) free(file); } -int +PUBLIC int altos_putchar(struct altos_file *file, char c) { int ret; @@ -1166,7 +1166,7 @@ altos_putchar(struct altos_file *file, char c) return LIBALTOS_SUCCESS; } -int +PUBLIC int altos_getchar(struct altos_file *file, int timeout) { int ret; -- cgit v1.2.3 From 393d231b9689cd1c358600ee76e0e808f89670c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Aug 2011 22:52:45 -0700 Subject: altosui: Attempt to make both 32- and 64-bit windows DLLs We'll see if they work... Signed-off-by: Keith Packard --- altosui/Altos.java | 8 +++++++- altosui/Makefile.am | 18 ++++++++++++++++-- altosui/libaltos/Makefile.am | 15 ++++++++++++++- altosui/libaltos/altos.dll | Bin 31765 -> 91605 bytes 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index d3f8fa67..ddf1005a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -366,7 +366,13 @@ public class Altos { libaltos.altos_init(); loaded_library = true; } catch (UnsatisfiedLinkError e) { - loaded_library = false; + try { + System.loadLibrary("altos64"); + libaltos.altos_init(); + loaded_library = true; + } catch (UnsatisfiedLinkError e2) { + loaded_library = false; + } } initialized = true; } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e4986ba5..f626d3fa 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -191,7 +191,7 @@ 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) +WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb @@ -282,10 +282,24 @@ libaltos.dylib: -rm -f "$@" $(LN_S) libaltos/"$@" . -altos.dll: +altos.dll: libaltos/altos.dll -rm -f "$@" $(LN_S) libaltos/"$@" . +altos64.dll: libaltos/altos64.dll + -rm -f "$@" + $(LN_S) libaltos/"$@" . + +libaltos/altos.dll: build-altos-dll + +libaltos/altos64.dll: build-altos64-dll + +build-altos-dll: + +cd libaltos && make altos.dll + +build-altos64-dll: + +cd libaltos && make altos64.dll + $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . diff --git a/altosui/libaltos/Makefile.am b/altosui/libaltos/Makefile.am index 3f5f3ee2..b5ab1ddb 100644 --- a/altosui/libaltos/Makefile.am +++ b/altosui/libaltos/Makefile.am @@ -37,5 +37,18 @@ classlibaltos.stamp: $(SWIG_FILE) $(JAVAC) -d . $(AM_JAVACFLAGS) $(JAVACFLAGS) *.java && \ touch classlibaltos.stamp +MINGCC32=i686-w64-mingw32-gcc +MINGCC64=x86_64-w64-mingw32-gcc +MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE) +MINGLIBS=-lsetupapi + +fat: altos.dll altos64.dll + +altos.dll: $(libaltos_la_SOURCES) + $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + +altos64.dll: $(libaltos_la_SOURCES) + $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS) + clean-local: - -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c + -rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll index 28e9b4ad..a96d3129 100755 Binary files a/altosui/libaltos/altos.dll and b/altosui/libaltos/altos.dll differ -- cgit v1.2.3 From a0f62b8569c5535a2598cfb6ab52db79f0a52f92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 17:17:43 -0700 Subject: doc: Add note about telemetry disable mode to 1.0 release notes Signed-off-by: Keith Packard --- doc/release-notes-1.0.xsl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/release-notes-1.0.xsl b/doc/release-notes-1.0.xsl index b42917c5..a3fc22d9 100644 --- a/doc/release-notes-1.0.xsl +++ b/doc/release-notes-1.0.xsl @@ -25,6 +25,13 @@ pointing upwards, now there is a configuration option allowing the antenna to point aft, to aid installation in some airframes. + + Ability to disable telemetry. For airframes where an antenna + just isn't possible, or where radio transmissions might cause + trouble with other electronics, there's a configuration option + to disable all telemetry. Note that the board will still + enable packet mode in idle mode. + Arbitrary frequency selection. The radios in Altus Metrum devices can be programmed to a wide range of frequencies, so -- cgit v1.2.3 From b83d8eca433ed5796835f6a09271f50c7f27cc81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 17:18:02 -0700 Subject: doc: Add Installation Recommendations chapter Document installation suggestions, including mounting, RFI, antenna issues and ground testing. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 214 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index e97666ae..601b62eb 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1810,6 +1810,220 @@ NAR #88757, TRA #12200
+ + Altimeter Installation Recommendations + + Building high-power rockets that fly safely is hard enough. Mix + in some sophisticated electronics and a bunch of radio energy + and oftentimes you find few perfect solutions. This chapter + contains some suggestions about how to install AltusMetrum + products into the rocket airframe, including how to safely and + reliably mix a variety of electronics into the same airframe. + +
+ Mounting the Altimeter + + The first consideration is to ensure that the altimeter is + securely fastened to the airframe. For TeleMetrum, we use + nylon standoffs and nylon screws; they're good to at least 50G + and cannot cause any electrical issues on the board. For + TeleMini, we usually cut small pieces of 1/16" balsa to fit + under the screw holes, and then take 2x56 nylon screws and + screw them through the TeleMini mounting holes, through the + balsa and into the underlying material. + + + + Make sure TeleMetrum is aligned precisely along the axis of + acceleration so that the accelerometer can accurately + capture data during the flight. + + + Watch for any metal touching components on the + board. Shorting out connections on the bottom of the board + can cause the altimeter to fail during flight. + + +
+
+ Dealing with the Antenna + + The antenna supplied is just a piece of solid, insulated, + wire. If it gets damaged or broken, it can be easily + replaced. It should be kept straight and not cut; bending or + cutting it will change the resonant frequency and/or + impedence, making it a less efficient radiator and thus + reducing the range of the telemetry signal. + + + Keeping metal away from the antenna will provide better range + and a more even radiation pattern. In most rockets, it's not + entirely possible to isolate the antenna from metal + components; there are often bolts, all-thread and wires from other + electronics to contend with. Just be aware that the more stuff + like this around the antenna, the lower the range. + + + Make sure the antenna is not inside a tube made or covered + with conducting material. Carbon fibre is the most common + culprit here -- CF is a good conductor and will effectively + shield the antenna, dramatically reducing signal strength and + range. Metalic flake paint is another effective shielding + material which is to be avoided around any antennas. + + + If the ebay is large enough, it can be convenient to simply + mount the altimeter at one end and stretch the antenna out + inside. Taping the antenna to the sled can keep it straight + under acceleration. If there are metal rods, keep the + antenna as far away as possible. + + + For a shorter ebay, it's quite practical to have the antenna + run through a bulkhead and into an adjacent bay. Drill a small + hole in the bulkhead, pass the antenna wire through it and + then seal it up with glue or clay. We've also used acrylic + tubing to create a cavity for the antenna wire. This works a + bit better in that the antenna is known to stay straight and + not get folded by recovery components in the bay. Angle the + tubing towards the side wall of the rocket and it ends up + consuming very little space. + + + If you need to place the antenna at a distance from the + altimeter, you can replace the antenna with an edge-mounted + SMA connector, and then run 50Ω coax from the board to the + antenna. Building a remote antenna is beyond the scope of this + manual. + +
+
+ Preserving GPS Reception + + The GPS antenna and receiver in TeleMetrum are highly + sensitive and normally have no trouble tracking enough + satellites to provide accurate position information for + recovering the rocket. However, there are many ways to + attenuate the GPS signal. + + + Conductive tubing or coatings. Carbon fiber and metal + tubing, or metalic paint will all dramatically attenuate the + GPS signal. We've never heard of anyone successfully + receiving GPS from inside these materials. + + + Metal components near the GPS patch antenna. These will + de-tune the patch antenna, changing the resonant frequency + away from the L1 carrier and reduce the effectiveness of the + antenna. You can place as much stuff as you like beneath the + antenna as that's covered with a ground plane. But, keep + wires and metal out from above the patch antenna. + + + +
+
+ Radio Frequency Interference + + Any altimeter will generate RFI; the digital circuits use + high-frequency clocks that spray radio interference across a + wide band. Altusmetrum altimeters generate intentional radio + signals as well, increasing the amount of RF energy around the board. + + + Rocketry altimeters also use precise sensors measuring air + pressure and acceleration. Tiny changes in voltage can cause + these sensor readings to vary by a huge amount. When the + sensors start mis-reporting data, the altimeter can either + fire the igniters at the wrong time, or not fire them at all. + + + Voltages are induced when radio frequency energy is + transmitted from one circuit to another. Here are things that + increase the induced voltage and current: + + + + Keep wires from different circuits apart. Moving circuits + further apart will reduce RFI. + + + Avoid parallel wires from different circuits. The longer two + wires run parallel to one another, the larger the amount of + transferred energy. Cross wires at right angles to reduce + RFI. + + + Twist wires from the same circuits. Two wires the same + distance from the transmitter will get the same amount of + induced energy which will then cancel out. Any time you have + a wire pair running together, twist the pair together to + even out distances and reduce RFI. For altimeters, this + includes battery leads, switch hookups and igniter + circuits. + + + Avoid resonant lengths. Know what frequencies are present + in the environment and avoid having wire lengths near a + natural resonant length. Altusmetrum products transmit on the + 70cm amateur band, so you should avoid lengths that are a + simple ratio of that length; essentially any multiple of 1/4 + of the wavelength (17.5cm). + + +
+
+ The Barometric Sensor + + Altusmetrum altimeters measure altitude with a barometric + sensor, essentially measuring the amount of air above the + rocket to figure out how high it is. A large number of + measurements are taken as the altimeter initializes itself to + figure out the pad altitude. Subsequent measurements are then + used to compute the height above the pad. + + + To accurately measure atmospheric pressure, the ebay + containing the altimeter must be vented outside the + airframe. The vent must be placed in a region of linear + airflow, smooth and not in an area of increasing or decreasing + pressure. + + + The barometric sensor in the altimeter is quite sensitive to + chemical damage from the products of APCP or BP combustion, so + make sure the ebay is carefully sealed from any compartment + which contains ejection charges or motors. + +
+
+ Ground Testing + + The most important aspect of any installation is careful + ground testing. Bringing an airframe up to the LCO table which + hasn't been ground tested can lead to delays or ejection + charges firing on the pad, or, even worse, a recovery system + failure. + + + Do a 'full systems' test that includes wiring up all igniters + without any BP and turning on all of the electronics in flight + mode. This will catch any mistakes in wiring and any residual + RFI issues that might accidentally fire igniters at the wrong + time. Let the airframe sit for several minutes, checking for + adequate telemetry signal strength and GPS lock. + + + Ground test the ejection charges. Prepare the rocket for + flight, loading ejection charges and igniters. Completely + assemble the airframe and then use the 'Fire Igniters' + interface through a TeleDongle to command each charge to + fire. Make sure the charge is sufficient to robustly separate + the airframe and deploy the recovery system. + +
+
Hardware Specifications
-- cgit v1.2.3 From 5ef731bd87c6d2a71a4edcc69a218eaf1aa7c465 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:21:35 -0700 Subject: altosui: Add a few simple unit conversions Signed-off-by: Keith Packard --- altosui/AltosConvert.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java index 207470a5..db7039ec 100644 --- a/altosui/AltosConvert.java +++ b/altosui/AltosConvert.java @@ -234,6 +234,18 @@ public class AltosConvert { return array; } + static double meters_to_feet(double meters) { + return meters * (100 / (2.54 * 12)); + } + + static double meters_to_mach(double meters) { + return meters / 343; /* something close to mach at usual rocket sites */ + } + + static double meters_to_g(double meters) { + return meters / 9.80665; + } + static int checksum(int[] data, int start, int length) { int csum = 0x5a; for (int i = 0; i < length; i++) -- cgit v1.2.3 From b4c71ba56c471720c72853057d0a527825a78fa0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:22:21 -0700 Subject: altosui: Capture date/time/serial/flight in AltosFlightStats Time is the time when boost was detected. Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index 19471e9f..2067951e 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -38,6 +38,10 @@ public class AltosFlightStats { int[] state_count = new int[Altos.ao_flight_invalid + 1]; double[] state_start = new double[Altos.ao_flight_invalid + 1]; double[] state_end = new double[Altos.ao_flight_invalid + 1]; + int serial; + int flight; + int year, month, day; + int hour, minute, second; public AltosFlightStats(AltosFlightReader reader) throws InterruptedException, IOException { AltosState state = null; @@ -45,19 +49,37 @@ public class AltosFlightStats { double boost_time = -1; double start_time; + year = month = day = -1; + hour = minute = second = -1; + serial = flight = -1; for (;;) { try { AltosRecord record = reader.read(); if (record == null) break; + if (serial < 0) + serial = record.serial; + if ((record.seen & AltosRecord.seen_flight) != 0 && flight < 0) + flight = record.flight; new_state = new AltosState(record, state); if (state == null) { start_time = new_state.time; } state = new_state; if (0 <= state.state && state.state < Altos.ao_flight_invalid) { - if (boost_time == -1 && state.state >= Altos.ao_flight_boost) - boost_time = state.time; + if (state.state >= Altos.ao_flight_boost) { + if (boost_time == -1) + boost_time = state.time; + if (state.gps != null && state.gps.locked && + year < 0) { + year = state.gps.year; + month = state.gps.month; + day = state.gps.day; + hour = state.gps.hour; + minute = state.gps.minute; + second = state.gps.second; + } + } state_accel[state.state] += state.acceleration; state_speed[state.state] += state.speed; state_baro_speed[state.state] += state.baro_speed; -- cgit v1.2.3 From f4ea46dc205454411c224ada7805f813989efd4a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:23:41 -0700 Subject: altosui: Add date/time/serial/flight to flight stats tab And switch to using the AltosConvert units conversions functions. Signed-off-by: Keith Packard --- altosui/AltosFlightStatsTable.java | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java index e2c0dd46..3fecf921 100644 --- a/altosui/AltosFlightStatsTable.java +++ b/altosui/AltosFlightStatsTable.java @@ -70,29 +70,37 @@ public class AltosFlightStatsTable extends JComponent { setLayout(layout); int y = 0; + new FlightStat(layout, y++, "Serial", String.format("%d", stats.serial)); + new FlightStat(layout, y++, "Flight", String.format("%d", stats.flight)); + if (stats.year > 0) + new FlightStat(layout, y++, "Date", + String.format("%04d-%02d-%02d", stats.year, stats.month, stats.day)); + if (stats.hour > 0) + new FlightStat(layout, y++, "Time", + String.format("%02d:%02d:%02d UTC", stats.hour, stats.minute, stats.second)); new FlightStat(layout, y++, "Maximum height", String.format("%5.0f m", stats.max_height), - String.format("%5.0f ft", stats.max_height * 100 / 2.54 / 12)); + String.format("%5.0f ft", AltosConvert.meters_to_feet(stats.max_height))); new FlightStat(layout, y++, "Maximum speed", String.format("%5.0f m/s", stats.max_speed), - String.format("%5.0f ft/s", stats.max_speed * 100 / 2.54 / 12), - String.format("Mach %5.3f", stats.max_speed / 343.0)); + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.max_speed)), + String.format("Mach %5.3f", AltosConvert.meters_to_mach(stats.max_speed))); if (stats.max_acceleration != AltosRecord.MISSING) { new FlightStat(layout, y++, "Maximum acceleration", String.format("%5.0f m/s²", stats.max_acceleration), - String.format("%5.0f ft/s²", stats.max_acceleration * 100 / 2.54 /12), - String.format("%5.2f G", stats.max_acceleration / 9.80665)); + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), + String.format("%5.2f G", AltosConvert.meters_to_g(stats.max_acceleration))); new FlightStat(layout, y++, "Average boost acceleration", String.format("%5.0f m/s²", stats.state_accel[Altos.ao_flight_boost]), - String.format("%5.0f ft/s²", stats.state_accel[Altos.ao_flight_boost] * 100 / 2.54 /12), - String.format("%5.2f G", stats.state_accel[Altos.ao_flight_boost] / 9.80665)); + String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[Altos.ao_flight_boost])), + String.format("%5.2f G", AltosConvert.meters_to_g(stats.state_accel[Altos.ao_flight_boost]))); } new FlightStat(layout, y++, "Drogue descent rate", String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_drogue]), - String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_drogue] * 100 / 2.54 / 12)); + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_drogue]))); new FlightStat(layout, y++, "Main descent rate", String.format("%5.0f m/s", stats.state_baro_speed[Altos.ao_flight_main]), - String.format("%5.0f ft/s", stats.state_baro_speed[Altos.ao_flight_main] * 100 / 2.54 / 12)); + String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_main]))); for (int s = Altos.ao_flight_boost; s <= Altos.ao_flight_main; s++) { new FlightStat(layout, y++, String.format("%s time", Altos.state_to_string_capital[s]), String.format("%6.2f s", stats.state_end[s] - stats.state_start[s])); -- cgit v1.2.3 From 4e2fd7ae76c23aa8da1390ebcbd8f45276cd7a32 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:24:54 -0700 Subject: altosui: Show filename in AltosGraph window Makes it easier to tell multiple windows apart Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 4 ++-- altosui/AltosLanded.java | 2 +- altosui/AltosUI.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 16b0fd48..be52bd4e 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -178,8 +178,8 @@ public class AltosGraphUI extends JFrame } } - public AltosGraphUI(AltosRecordIterable records) throws InterruptedException, IOException { - super("Altos Graph"); + public AltosGraphUI(AltosRecordIterable records, String name) throws InterruptedException, IOException { + super(String.format("Altos Graph %s", name)); AltosDataPointReader reader = new AltosDataPointReader (records); if (reader == null) diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 47aca29d..71c10663 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -240,7 +240,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio throw new FileNotFoundException(); } try { - new AltosGraphUI(records); + new AltosGraphUI(records, filename); } catch (InterruptedException ie) { } catch (IOException ie) { } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index b2c5107e..0317f569 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -311,7 +311,7 @@ public class AltosUI extends JFrame { if (record_reader == null) return; try { - new AltosGraphUI(record_reader); + new AltosGraphUI(record_reader, chooser.filename()); } catch (InterruptedException ie) { } catch (IOException ie) { } -- cgit v1.2.3 From afe6aba9cb91e93234ffee2a22eee40f848ddedd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 18:25:34 -0700 Subject: altosui: Add --summary option to dump flight stats to stdout useful for quickly capturing sense of a flight. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 80 ++++++++++++++++++++++++++++++++++++--------- altosui/libaltos/altos.dll | Bin 91605 -> 0 bytes 2 files changed, 64 insertions(+), 16 deletions(-) delete mode 100755 altosui/libaltos/altos.dll diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 0317f569..13cda637 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -369,6 +369,7 @@ public class AltosUI extends JFrame { static final int process_kml = 2; static final int process_graph = 3; static final int process_replay = 4; + static final int process_summary = 5; static void process_csv(String input) { AltosRecordIterable iterable = open_logfile(input); @@ -406,13 +407,13 @@ public class AltosUI extends JFrame { } } - static void process_replay(String filename) { + static AltosRecordIterable record_iterable_file(String filename) { FileInputStream in; try { in = new FileInputStream(filename); } catch (Exception e) { System.out.printf("Failed to open file '%s'\n", filename); - return; + return null; } AltosRecordIterable recs; AltosReplayReader reader; @@ -421,32 +422,74 @@ public class AltosUI extends JFrame { } else { recs = new AltosTelemetryIterable(in); } - reader = new AltosReplayReader(recs.iterator(), new File(filename)); + return recs; + } + + static AltosReplayReader replay_file(String filename) { + AltosRecordIterable recs = record_iterable_file(filename); + if (recs == null) + return null; + return new AltosReplayReader(recs.iterator(), new File(filename)); + } + + static void process_replay(String filename) { + AltosReplayReader reader = replay_file(filename); AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader); flight_ui.set_exit_on_close(); } static void process_graph(String filename) { - FileInputStream in; - try { - in = new FileInputStream(filename); - } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); + AltosRecordIterable recs = record_iterable_file(filename); + if (recs == null) return; - } - AltosRecordIterable recs; - if (filename.endsWith("eeprom")) { - recs = new AltosEepromIterable(in); - } else { - recs = new AltosTelemetryIterable(in); - } try { - new AltosGraphUI(recs); + new AltosGraphUI(recs, filename); } catch (InterruptedException ie) { } catch (IOException ie) { } } + static void process_summary(String filename) { + AltosReplayReader reader = replay_file(filename); + try { + AltosFlightStats stats = new AltosFlightStats(reader); + if (stats.serial > 0) + System.out.printf("Serial: %5d\n", stats.serial); + if (stats.flight > 0) + System.out.printf("Flight: %5d\n", stats.flight); + if (stats.year > 0) + System.out.printf("Date: %04d-%02d-%02d\n", + stats.year, stats.month, stats.day); + if (stats.hour > 0) + System.out.printf("Time: %02d:%02d:%02d UTC\n", + stats.hour, stats.minute, stats.second); + System.out.printf("Max height: %6.0f m %6.0f ft\n", + stats.max_height, + AltosConvert.meters_to_feet(stats.max_height)); + System.out.printf("Max speed: %6.0f m/s %6.0f ft/s %6.4f Mach\n", + stats.max_speed, + AltosConvert.meters_to_feet(stats.max_speed), + AltosConvert.meters_to_mach(stats.max_speed)); + if (stats.max_acceleration != AltosRecord.MISSING) { + System.out.printf("Max accel: %6.0f m/s² %6.0f ft/s² %6.2f g\n", + stats.max_acceleration, + AltosConvert.meters_to_feet(stats.max_acceleration), + AltosConvert.meters_to_g(stats.max_acceleration)); + } + System.out.printf("Drogue rate: %6.0f m/s %6.0f ft/s\n", + stats.state_baro_speed[Altos.ao_flight_drogue], + AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_drogue])); + System.out.printf("Main rate: %6.0f m/s %6.0f ft/s\n", + stats.state_baro_speed[Altos.ao_flight_main], + AltosConvert.meters_to_feet(stats.state_baro_speed[Altos.ao_flight_main])); + System.out.printf("Flight time: %6.0f s\n", + stats.state_end[Altos.ao_flight_main] - + stats.state_start[Altos.ao_flight_boost]); + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + } + public static void help(int code) { System.out.printf("Usage: altosui [OPTION]... [FILE]...\n"); System.out.printf(" Options:\n"); @@ -489,6 +532,8 @@ public class AltosUI extends JFrame { process = process_csv; else if (args[i].equals("--graph")) process = process_graph; + else if (args[i].equals("--summary")) + process = process_summary; else if (args[i].startsWith("--")) help(1); else { @@ -506,6 +551,9 @@ public class AltosUI extends JFrame { case process_csv: process_csv(args[i]); break; + case process_summary: + process_summary(args[i]); + break; } } } diff --git a/altosui/libaltos/altos.dll b/altosui/libaltos/altos.dll deleted file mode 100755 index a96d3129..00000000 Binary files a/altosui/libaltos/altos.dll and /dev/null differ -- cgit v1.2.3 From 3a84e8e0cc86481c301f4335843a0e1a94bad5c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:12:30 -0700 Subject: altosui: Make monitor-idle display correct 'On-board data logging' status Count number of stored flights and see if there's space for another one. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 23 ++++++++++++++++++++++- altosui/AltosIdleMonitorUI.java | 2 +- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 272dd402..c14dc5a1 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -54,6 +54,7 @@ public class AltosConfigData implements Iterable { int radio_calibration; int flight_log_max; int ignite_mode; + int stored_flight; int storage_size; int storage_erase_unit; @@ -84,10 +85,29 @@ public class AltosConfigData implements Iterable { return lines.iterator(); } + public int log_available() { + switch (log_format) { + case Altos.AO_LOG_FORMAT_TINY: + if (stored_flight == 0) + return 1; + return 0; + default: + if (flight_log_max <= 0) + return 1; + int log_space = storage_size - storage_erase_unit; + int log_used = stored_flight * flight_log_max; + + if (log_used >= log_space) + return 0; + return (log_space - log_used) / flight_log_max; + } + } + public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { - serial_line.printf("c s\nf\nv\n"); + serial_line.printf("c s\nf\nl\nv\n"); lines = new LinkedList(); radio_setting = 0; + stored_flight = 0; for (;;) { String line = serial_line.get_reply(); if (line == null) @@ -117,6 +137,7 @@ public class AltosConfigData implements Iterable { try { version = get_string(line,"software-version"); } catch (Exception e) {} try { product = get_string(line,"product"); } catch (Exception e) {} + try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 0370efa9..142f0278 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -193,7 +193,7 @@ class AltosIdleMonitor extends Thread { record.version = 0; record.callsign = config_data.callsign; record.serial = config_data.serial; - record.flight = 0; + record.flight = config_data.log_available() > 0 ? 255 : 0; record.rssi = 0; record.status = 0; record.state = Altos.ao_flight_idle; -- cgit v1.2.3 From 4aebe65b089e4b825a5ae238b81e2181bd88175a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:31:54 -0700 Subject: altosui: Can't configure flight log max on TeleMini It's only got space for one flight. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index b1e6bc12..f1743608 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -148,7 +148,17 @@ public class AltosConfig implements ActionListener { config_ui.set_apogee_delay(apogee_delay.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); - config_ui.set_flight_log_max_enabled(stored_flight.get() < 0); + boolean max_enabled = true; + switch (log_format.get()) { + case Altos.AO_LOG_FORMAT_TINY: + max_enabled = false; + break; + default: + if (stored_flight.get() >= 0) + max_enabled = false; + break; + } + config_ui.set_flight_log_max_enabled(max_enabled); config_ui.set_radio_enable(radio_enable.get()); config_ui.set_flight_log_max_limit(log_limit()); config_ui.set_flight_log_max(flight_log_max.get()); -- cgit v1.2.3 From e9254c3472e42d93181674b2c3cd80fe6eea696e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:32:36 -0700 Subject: altosui: fix 'magic' string to signal end of config data Was using "done", which happens to be displayed by the 'l' command. Switch to 'all finished' which doesn't appear in the config data output. Yes, this method is a kludge. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index f1743608..7cd8cb8b 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -174,7 +174,7 @@ public class AltosConfig implements ActionListener { abort(); return; } - if (line.equals("done")) { + if (line.equals("all finished")) { if (serial_line != null) update_ui(); return; @@ -244,7 +244,7 @@ public class AltosConfig implements ActionListener { } catch (InterruptedException ie) { } } - callback("done"); + callback("all finished"); } void save_data() { -- cgit v1.2.3 From d249da3fb064754753bd20cd2ca1e5ffcce294ca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:33:52 -0700 Subject: altosui: Only 'show' config dialog once Otherwise, the dialog jumps back to the initial position each time the data is updated. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 7cd8cb8b..45521665 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -85,6 +85,7 @@ public class AltosConfig implements ActionListener { string_ref callsign; AltosConfigUI config_ui; boolean serial_started; + boolean made_visible; boolean get_int(String line, String label, int_ref x) { if (line.startsWith(label)) { @@ -166,7 +167,10 @@ public class AltosConfig implements ActionListener { config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); - config_ui.make_visible(); + if (!made_visible) { + made_visible = true; + config_ui.make_visible(); + } } void process_line(String line) { -- cgit v1.2.3 From 955989147f90a4fd22c1375d1b41425dae4e7dd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:34:55 -0700 Subject: altosui: Reset all config data on 'reset' command This lets you switch altimeters without getting any stale data. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 45521665..122ebecc 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -223,10 +223,31 @@ public class AltosConfig implements ActionListener { SwingUtilities.invokeLater(r); } + void reset_data() { + serial.set(0); + log_format.set(Altos.AO_LOG_FORMAT_UNKNOWN); + main_deploy.set(250); + apogee_delay.set(0); + radio_channel.set(0); + radio_setting.set(0); + radio_calibration.set(1186611); + radio_enable.set(-1); + flight_log_max.set(0); + ignite_mode.set(-1); + pad_orientation.set(-1); + storage_size.set(-1); + storage_erase_unit.set(-1); + stored_flight.set(-1); + callsign.set("N0CALL"); + version.set("unknown"); + product.set("unknown"); + } + void get_data() { try { config.start_serial(); - stored_flight.set(-1); + reset_data(); + config.serial_line.printf("c s\nf\nl\nv\n"); for (;;) { try { -- cgit v1.2.3 From fa6df3fa21e8f09e70371e6c6cc7827a533b4fe6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Aug 2011 23:35:28 -0700 Subject: altosui: Update mac os X library This has been tested on 32-bit OS X and it works; dunno about 64-bit. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.dylib | Bin 54176 -> 41648 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/altosui/libaltos/libaltos.dylib b/altosui/libaltos/libaltos.dylib index 89aa12e7..1038817d 100755 Binary files a/altosui/libaltos/libaltos.dylib and b/altosui/libaltos/libaltos.dylib differ -- cgit v1.2.3 From 754b9591574c12ddd6e4ab590c6a5f3806b80213 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2011 13:29:23 -0700 Subject: libaltos: fix Mac OS X function signatures altos_list_start was declared to take a (int time) parameter for some reason. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 21e94ca0..d1f445bd 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -794,8 +794,8 @@ get_number(io_object_t object, CFStringRef entry, int *result) return 0; } -struct altos_list * -altos_list_start(int time) +PUBLIC struct altos_list * +altos_list_start(void) { struct altos_list *list = calloc (sizeof (struct altos_list), 1); CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice"); @@ -810,7 +810,7 @@ altos_list_start(int time) return list; } -int +PUBLIC int altos_list_next(struct altos_list *list, struct altos_device *device) { io_object_t object; @@ -837,7 +837,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) } } -void +PUBLIC void altos_list_finish(struct altos_list *list) { IOObjectRelease (list->iterator); -- cgit v1.2.3 From 998adccc1c4f8f6c44833bbf4a52d9441748b996 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2011 18:56:07 -0700 Subject: altosui: add tool-tips to the button box. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 13cda637..36c08882 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -123,50 +123,56 @@ public class AltosUI extends JFrame { ConnectToDevice(); } }); + b.setToolTipText("Connect to TeleDongle and monitor telemetry"); b = addButton(1, 0, "Save Flight Data"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { SaveFlightData(); } }); + b.setToolTipText("Download and/or delete flight data from an altimeter"); b = addButton(2, 0, "Replay Flight"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Replay(); } }); + b.setToolTipText("Watch an old flight in real-time"); b = addButton(3, 0, "Graph Data"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { GraphData(); } }); + b.setToolTipText("Present flight data in a graph and table of statistics"); b = addButton(4, 0, "Export Data"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ExportData(); } }); + b.setToolTipText("Convert flight data for a spreadsheet or GoogleEarth"); b = addButton(0, 1, "Configure Altimeter"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureTeleMetrum(); } }); - + b.setToolTipText("Set flight, storage and communication parameters"); b = addButton(1, 1, "Configure AltosUI"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ConfigureAltosUI(); } }); - + b.setToolTipText("Global AltosUI settings"); b = addButton(2, 1, "Flash Image"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { FlashImage(); } }); + b.setToolTipText("Replace the firmware in any AltusMetrum product"); b = addButton(3, 1, "Fire Igniter"); b.addActionListener(new ActionListener() { @@ -174,35 +180,35 @@ public class AltosUI extends JFrame { FireIgniter(); } }); - + b.setToolTipText("Remote control of igniters for deployment testing"); b = addButton(4, 1, "Quit"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }); - - + b.setToolTipText("Close all active windows and terminate AltosUI"); b = addButton(0, 2, "Scan Channels"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ScanChannels(); } }); - + b.setToolTipText("Find what channel an altimeter is sending telemetry on"); b = addButton(1, 2, "Load Maps"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { LoadMaps(); } }); - + b.setToolTipText("Download satellite images for off-line flight monitoring"); b = addButton(2, 2, "Monitor Idle"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { IdleMonitor(); } }); + b.setToolTipText("Check flight readiness of altimeter in idle mode"); setTitle("AltOS"); -- cgit v1.2.3 From fc7e46b1215ea2b4cc138ed77d8eaa122369b15f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Aug 2011 20:10:14 -0600 Subject: turn off auto-tagging during Debian build --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 1353321d..028b548f 100755 --- a/debian/rules +++ b/debian/rules @@ -12,7 +12,7 @@ prebuild: git log > ChangeLog git commit -n ChangeLog debian/changelog \ -m "update changelogs for Debian build" - git tag debian/$(DEB_VERSION) +# git tag debian/$(DEB_VERSION) # git push --tags origin master configure: configure-stamp -- cgit v1.2.3 From 192881b7cae49af375cc2b8b7305c937079ee724 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Aug 2011 20:11:01 -0600 Subject: update changelogs for Debian build --- ChangeLog | 305 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 36 +++++++ 2 files changed, 341 insertions(+) diff --git a/ChangeLog b/ChangeLog index 14a32f04..024d4494 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,269 @@ +commit fc7e46b1215ea2b4cc138ed77d8eaa122369b15f +Author: Bdale Garbee +Date: Tue Aug 23 20:10:14 2011 -0600 + + turn off auto-tagging during Debian build + +commit 998adccc1c4f8f6c44833bbf4a52d9441748b996 +Author: Keith Packard +Date: Tue Aug 23 18:56:07 2011 -0700 + + altosui: add tool-tips to the button box. + + Signed-off-by: Keith Packard + +commit 754b9591574c12ddd6e4ab590c6a5f3806b80213 +Author: Keith Packard +Date: Tue Aug 23 13:29:23 2011 -0700 + + libaltos: fix Mac OS X function signatures + + altos_list_start was declared to take a (int time) parameter for some reason. + + Signed-off-by: Keith Packard + +commit fa6df3fa21e8f09e70371e6c6cc7827a533b4fe6 +Author: Keith Packard +Date: Mon Aug 22 23:35:28 2011 -0700 + + altosui: Update mac os X library + + This has been tested on 32-bit OS X and it works; dunno about + 64-bit. + + Signed-off-by: Keith Packard + +commit 955989147f90a4fd22c1375d1b41425dae4e7dd1 +Author: Keith Packard +Date: Mon Aug 22 23:34:55 2011 -0700 + + altosui: Reset all config data on 'reset' command + + This lets you switch altimeters without getting any stale data. + + Signed-off-by: Keith Packard + +commit d249da3fb064754753bd20cd2ca1e5ffcce294ca +Author: Keith Packard +Date: Mon Aug 22 23:33:52 2011 -0700 + + altosui: Only 'show' config dialog once + + Otherwise, the dialog jumps back to the initial position each time the + data is updated. + + Signed-off-by: Keith Packard + +commit e9254c3472e42d93181674b2c3cd80fe6eea696e +Author: Keith Packard +Date: Mon Aug 22 23:32:36 2011 -0700 + + altosui: fix 'magic' string to signal end of config data + + Was using "done", which happens to be displayed by the 'l' + command. Switch to 'all finished' which doesn't appear in the config + data output. Yes, this method is a kludge. + + Signed-off-by: Keith Packard + +commit 4aebe65b089e4b825a5ae238b81e2181bd88175a +Author: Keith Packard +Date: Mon Aug 22 23:31:54 2011 -0700 + + altosui: Can't configure flight log max on TeleMini + + It's only got space for one flight. + + Signed-off-by: Keith Packard + +commit 3a84e8e0cc86481c301f4335843a0e1a94bad5c0 +Author: Keith Packard +Date: Mon Aug 22 23:12:30 2011 -0700 + + altosui: Make monitor-idle display correct 'On-board data logging' status + + Count number of stored flights and see if there's space for another + one. + + Signed-off-by: Keith Packard + +commit afe6aba9cb91e93234ffee2a22eee40f848ddedd +Author: Keith Packard +Date: Mon Aug 22 18:25:34 2011 -0700 + + altosui: Add --summary option to dump flight stats to stdout + + useful for quickly capturing sense of a flight. + + Signed-off-by: Keith Packard + +commit 4e2fd7ae76c23aa8da1390ebcbd8f45276cd7a32 +Author: Keith Packard +Date: Mon Aug 22 18:24:54 2011 -0700 + + altosui: Show filename in AltosGraph window + + Makes it easier to tell multiple windows apart + + Signed-off-by: Keith Packard + +commit f4ea46dc205454411c224ada7805f813989efd4a +Author: Keith Packard +Date: Mon Aug 22 18:23:41 2011 -0700 + + altosui: Add date/time/serial/flight to flight stats tab + + And switch to using the AltosConvert units conversions functions. + + Signed-off-by: Keith Packard + +commit b4c71ba56c471720c72853057d0a527825a78fa0 +Author: Keith Packard +Date: Mon Aug 22 18:22:21 2011 -0700 + + altosui: Capture date/time/serial/flight in AltosFlightStats + + Time is the time when boost was detected. + + Signed-off-by: Keith Packard + +commit 5ef731bd87c6d2a71a4edcc69a218eaf1aa7c465 +Author: Keith Packard +Date: Mon Aug 22 18:21:35 2011 -0700 + + altosui: Add a few simple unit conversions + + Signed-off-by: Keith Packard + +commit b83d8eca433ed5796835f6a09271f50c7f27cc81 +Author: Keith Packard +Date: Mon Aug 22 17:18:02 2011 -0700 + + doc: Add Installation Recommendations chapter + + Document installation suggestions, including mounting, RFI, antenna + issues and ground testing. + + Signed-off-by: Keith Packard + +commit a0f62b8569c5535a2598cfb6ab52db79f0a52f92 +Author: Keith Packard +Date: Mon Aug 22 17:17:43 2011 -0700 + + doc: Add note about telemetry disable mode to 1.0 release notes + + Signed-off-by: Keith Packard + +commit 393d231b9689cd1c358600ee76e0e808f89670c8 +Author: Keith Packard +Date: Sun Aug 21 22:52:45 2011 -0700 + + altosui: Attempt to make both 32- and 64-bit windows DLLs + + We'll see if they work... + + Signed-off-by: Keith Packard + +commit d5bd40847b17c32405dfba864a2a5a3b19aa7e85 +Author: Keith Packard +Date: Sun Aug 21 22:12:53 2011 -0700 + + altosui/windows: Fix a bunch of windows compiler warnings. + + Some of these may have actually been serious -- a write length was + getting stored in a signed char... + + Signed-off-by: Keith Packard + +commit 2353d83be15b398754c2564f95374c6ea0f8de92 +Author: Keith Packard +Date: Sun Aug 21 22:12:04 2011 -0700 + + altos-fat/windows: Check and install Java 1.6 as needed + + Signed-off-by: Keith Packard + +commit a08826292ebd802a1ff2effccac3b96fd061c47d +Merge: 3366cfe 55be3db +Author: Bdale Garbee +Date: Mon Aug 22 16:08:55 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 55be3db2e31fe97e7f351e3c490b8bc4cf7192b2 +Author: Keith Packard +Date: Sun Aug 21 19:18:54 2011 -0700 + + altosui: Clean up command line processing. Add --graph + + Make the command line processing a bit less ad-hoc, track 'mode' of + processing and deal with all files on the command line. + + Signed-off-by: Keith Packard + +commit 6823ad5e48fc0a19791d96f886b5689f88c4311b +Author: Keith Packard +Date: Thu Aug 18 18:02:02 2011 -0700 + + altos/altosui: Add ability to disable telemetry/rdf completely + + This turns off the telemetry system so that it never transmits telemetry + or RDF tones. In idle mode, it will still accept packet mode connections. + + Signed-off-by: Keith Packard + +commit a08e7ac8bd3840b699c9a1ffc6b1e115b2b84bad +Author: Keith Packard +Date: Sat Aug 20 11:35:55 2011 -0700 + + Bump version to 0.9.7 + + Bdale is flying 0.9.6 at chili blaster, make sure later firmware gets + a later version number. + + Signed-off-by: Keith Packard + +commit f2b0900f8b83fcb3085f3d042ffd961ffd758d5d +Author: Keith Packard +Date: Sat Aug 20 11:28:53 2011 -0700 + + altos: Merge common config code in ao_config.c + + This shuffles code around in ao_config.c to share some common code + segments for starting and committing config changes. + + This also stops printing out changes as they are made which aren't + needed by the UI code. + + Signed-off-by: Keith Packard + +commit 67f28c58db0deca8f8050d33e97ad96017f4baaa +Author: Keith Packard +Date: Sat Aug 20 11:19:57 2011 -0700 + + altosui: Disable 'max flight log' config when there are stored flights + + When flights are stored in flash, the maximum flight log value cannot + be changed as the flight data might need to be moved around in + memory. Check for this case by looking for stored flights and + disabling the combo box when storage is not empty. + + Signed-off-by: Keith Packard + +commit fcff63baf8fde1174571a2c7c860099e19dbf629 +Author: Keith Packard +Date: Sat Aug 20 10:43:28 2011 -0700 + + altosui: remove debug printf in pad pane + + Signed-off-by: Keith Packard + +commit 3366cfe6145f64cdb04654854d5390c671a288e3 +Author: Bdale Garbee +Date: Sat Aug 20 09:28:04 2011 -0600 + + update changelogs for Debian build + commit 787e4305a05e344c018abb872f788749203690d7 Author: Bdale Garbee Date: Sat Aug 20 09:24:29 2011 -0600 @@ -10,6 +276,45 @@ Date: Fri Aug 19 22:47:50 2011 -0600 update changelogs for Debian build +commit 048b3eb45169e572f33c68ff152b89db9ef97d31 +Author: Keith Packard +Date: Sun Aug 14 21:11:41 2011 -0700 + + altosui: Add 'On-board Data Logging' indicator to pad tab + + This shows whether the on-board data memory is full, or is ready to + record the flight. This is indicated in the telemetry stream by a + flight number of '0'. + + Signed-off-by: Keith Packard + +commit adb7d345963ab9981c49c7cc68c6b4d7156dce46 +Author: Keith Packard +Date: Sun Aug 14 21:09:42 2011 -0700 + + altosui: Ancient log files used 'apogee' for 'coast' state + + 2009-07-18-serial-004-flight-000 says 'apogee' for the apogee-detect + phase of the flight; map this to coast so that this flight replays + correctly (although the log terminates at apogee...) + + Signed-off-by: Keith Packard + +commit 4f64d66295a8f76680af8cfda4650aa4c4f8576d +Author: Keith Packard +Date: Sun Aug 14 19:19:50 2011 -0700 + + altos: Lost change that reported flight 0 when log memory was full + + commit 52ac83fedbfd380d14d4df2e79992bbdfba3552a added coded to check + for a full flight log and complain with a special tone. + + It also reported flight 0 over telemetry, and that part of the patch + got lost when moving to the new telemetry format. This patch + resurrects that piece. + + Signed-off-by: Keith Packard + commit ef7f60df841f1eb22b9cec0d7f68cf2c003d6b30 Author: Keith Packard Date: Sun Aug 14 00:00:54 2011 -0700 diff --git a/debian/changelog b/debian/changelog index e786b10f..670732e6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,39 @@ +altos (0.9.6.0+32+gfc7e46b) unstable; urgency=low + + [ Keith Packard ] + * altos: Lost change that reported flight 0 when log memory was full + * altosui: Ancient log files used 'apogee' for 'coast' state + * altosui: Add 'On-board Data Logging' indicator to pad tab + * altosui: remove debug printf in pad pane + * altosui: Disable 'max flight log' config when there are stored flights + * altos: Merge common config code in ao_config.c + * Bump version to 0.9.7 + * altos/altosui: Add ability to disable telemetry/rdf completely + * altosui: Clean up command line processing. Add --graph + * altos-fat/windows: Check and install Java 1.6 as needed + * altosui/windows: Fix a bunch of windows compiler warnings. + * altosui: Attempt to make both 32- and 64-bit windows DLLs + * doc: Add note about telemetry disable mode to 1.0 release notes + * doc: Add Installation Recommendations chapter + * altosui: Add a few simple unit conversions + * altosui: Capture date/time/serial/flight in AltosFlightStats + * altosui: Add date/time/serial/flight to flight stats tab + * altosui: Show filename in AltosGraph window + * altosui: Add --summary option to dump flight stats to stdout + * altosui: Make monitor-idle display correct 'On-board data logging' status + * altosui: Can't configure flight log max on TeleMini + * altosui: fix 'magic' string to signal end of config data + * altosui: Only 'show' config dialog once + * altosui: Reset all config data on 'reset' command + * altosui: Update mac os X library + * libaltos: fix Mac OS X function signatures + * altosui: add tool-tips to the button box. + + [ Bdale Garbee ] + * turn off auto-tagging during Debian build + + -- Bdale Garbee Tue, 23 Aug 2011 20:10:38 -0600 + altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 99316a17a9642a207c45610e7cc1c33c2600ece0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Aug 2011 21:33:53 -0600 Subject: rewind changelog to 0.9.6.0 for rebuild --- debian/changelog | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/debian/changelog b/debian/changelog index 670732e6..e786b10f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,39 +1,3 @@ -altos (0.9.6.0+32+gfc7e46b) unstable; urgency=low - - [ Keith Packard ] - * altos: Lost change that reported flight 0 when log memory was full - * altosui: Ancient log files used 'apogee' for 'coast' state - * altosui: Add 'On-board Data Logging' indicator to pad tab - * altosui: remove debug printf in pad pane - * altosui: Disable 'max flight log' config when there are stored flights - * altos: Merge common config code in ao_config.c - * Bump version to 0.9.7 - * altos/altosui: Add ability to disable telemetry/rdf completely - * altosui: Clean up command line processing. Add --graph - * altos-fat/windows: Check and install Java 1.6 as needed - * altosui/windows: Fix a bunch of windows compiler warnings. - * altosui: Attempt to make both 32- and 64-bit windows DLLs - * doc: Add note about telemetry disable mode to 1.0 release notes - * doc: Add Installation Recommendations chapter - * altosui: Add a few simple unit conversions - * altosui: Capture date/time/serial/flight in AltosFlightStats - * altosui: Add date/time/serial/flight to flight stats tab - * altosui: Show filename in AltosGraph window - * altosui: Add --summary option to dump flight stats to stdout - * altosui: Make monitor-idle display correct 'On-board data logging' status - * altosui: Can't configure flight log max on TeleMini - * altosui: fix 'magic' string to signal end of config data - * altosui: Only 'show' config dialog once - * altosui: Reset all config data on 'reset' command - * altosui: Update mac os X library - * libaltos: fix Mac OS X function signatures - * altosui: add tool-tips to the button box. - - [ Bdale Garbee ] - * turn off auto-tagging during Debian build - - -- Bdale Garbee Tue, 23 Aug 2011 20:10:38 -0600 - altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 4b5369dc3da2fc8441eeacbf094537b0cf52240d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 23 Aug 2011 21:37:17 -0600 Subject: update changelogs for Debian build --- ChangeLog | 12 ++++++++++++ debian/changelog | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/ChangeLog b/ChangeLog index 024d4494..2a95a1ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +commit 99316a17a9642a207c45610e7cc1c33c2600ece0 +Author: Bdale Garbee +Date: Tue Aug 23 21:33:53 2011 -0600 + + rewind changelog to 0.9.6.0 for rebuild + +commit 192881b7cae49af375cc2b8b7305c937079ee724 +Author: Bdale Garbee +Date: Tue Aug 23 20:11:01 2011 -0600 + + update changelogs for Debian build + commit fc7e46b1215ea2b4cc138ed77d8eaa122369b15f Author: Bdale Garbee Date: Tue Aug 23 20:10:14 2011 -0600 diff --git a/debian/changelog b/debian/changelog index e786b10f..6bec4012 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,39 @@ +altos (0.9.7.0) unstable; urgency=low + + [ Keith Packard ] + * altos: Lost change that reported flight 0 when log memory was full + * altosui: Ancient log files used 'apogee' for 'coast' state + * altosui: Add 'On-board Data Logging' indicator to pad tab + * altosui: remove debug printf in pad pane + * altosui: Disable 'max flight log' config when there are stored flights + * altos: Merge common config code in ao_config.c + * Bump version to 0.9.7 + * altos/altosui: Add ability to disable telemetry/rdf completely + * altosui: Clean up command line processing. Add --graph + * altos-fat/windows: Check and install Java 1.6 as needed + * altosui/windows: Fix a bunch of windows compiler warnings. + * altosui: Attempt to make both 32- and 64-bit windows DLLs + * doc: Add note about telemetry disable mode to 1.0 release notes + * doc: Add Installation Recommendations chapter + * altosui: Add a few simple unit conversions + * altosui: Capture date/time/serial/flight in AltosFlightStats + * altosui: Add date/time/serial/flight to flight stats tab + * altosui: Show filename in AltosGraph window + * altosui: Add --summary option to dump flight stats to stdout + * altosui: Make monitor-idle display correct 'On-board data logging' status + * altosui: Can't configure flight log max on TeleMini + * altosui: fix 'magic' string to signal end of config data + * altosui: Only 'show' config dialog once + * altosui: Reset all config data on 'reset' command + * altosui: Update mac os X library + * libaltos: fix Mac OS X function signatures + * altosui: add tool-tips to the button box. + + [ Bdale Garbee ] + * turn off auto-tagging during Debian build + + -- Bdale Garbee Tue, 23 Aug 2011 21:36:50 -0600 + altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 186dfc7c72aa7eba281f29f917088e49e44c2ddc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2011 22:51:57 -0700 Subject: altosui: Use system look&feel Turn on the 'be less ugly bit' Signed-off-by: Keith Packard --- altosui/AltosUI.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 36c08882..27c41838 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -508,6 +508,10 @@ public class AltosUI extends JFrame { } public static void main(final String[] args) { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + } /* Handle batch-mode */ if (args.length == 0) { AltosUI altosui = new AltosUI(); -- cgit v1.2.3 From 63808e0392f43633f92fee137d968e969dd364c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Aug 2011 23:20:00 -0700 Subject: Remove stale tools (ao-dumplog, ao-postflight, ao-view) These tools have all been supplanted by altosui at this point, and keeping them around increases the build dependencies by quite a lot. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/lib/Makefile.am | 4 +++- configure.ac | 25 ------------------------- debian/control | 4 ++-- 4 files changed, 6 insertions(+), 29 deletions(-) diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 2850e909..8144be1c 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-dumplog ao-bitbang ao-eeprom ao-list ao-load ao-postflight ao-view +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index 79972f46..da355db5 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -2,6 +2,9 @@ noinst_LIBRARIES = libao-tools.a AM_CFLAGS=$(WARN_CFLAGS) $(LIBUSB_CFLAGS) $(GNOME_CFLAGS) +libao_tools_a_uneeded = \ + cc-log.c + libao_tools_a_SOURCES = \ ccdbg-command.c \ ccdbg-debug.c \ @@ -17,7 +20,6 @@ libao_tools_a_SOURCES = \ cc-analyse.c \ cc-convert.c \ cc-dsp.c \ - cc-log.c \ cc-integrate.c \ cc-period.c \ cc-process.c \ diff --git a/configure.ac b/configure.ac index 93f53115..0a6001b8 100644 --- a/configure.ac +++ b/configure.ac @@ -95,20 +95,6 @@ if test "x$GCC" = "xyes"; then fi AC_SUBST(WARN_CFLAGS) -AC_CHECK_HEADERS(flite/flite.h,HAVE_FLITE_H=yes,HAVE_FLITE_H=no) -AC_CHECK_LIB(flite, flite_init,HAVE_LIBFLITE=yes,HAVE_LIBFLITE=no,-lasound -lm) - -if test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes"; then - AC_DEFINE(HAVE_FLITE,1,[Define if the flite library is usable]) - AC_SUBST(FLITE_LIBS,"-lflite_cmu_us_kal16 -lflite_usenglish -lflite_cmulex -lflite -lasound -lm") - AC_SUBST(FLITE_INCS,-Iflite) - save_LIBS="$LIBS" - LIBS="$LIBS $FLITE_LIBS" - AC_CHECK_FUNCS([register_cmu_us_kal16 register_cmu_us_kal],break) - LIBS="$save_LIBS" -fi -AM_CONDITIONAL(USE_FLITE,test "x$HAVE_FLITE_H" = "xyes" -a "x$HAVE_LIBFLITE" = "xyes") - AC_CHECK_PROG([HAVE_SDCC], [sdcc], yes, no) if test "x$HAVE_SDCC" = "xno"; then AC_MSG_ERROR([Please install sdcc to build AltOs]) @@ -121,16 +107,8 @@ fi AC_CHECK_LIB(readline, readline) -PKG_CHECK_MODULES([GNOME], [gtk+-2.0 libglade-2.0 gconf-2.0]) - PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) -PKG_CHECK_MODULES([ALSA], [alsa]) - -PKG_CHECK_MODULES([PLPLOT], [plplotd]) - -PKG_CHECK_MODULES([SNDFILE], [sndfile]) - AC_OUTPUT([ Makefile altosui/Makefile @@ -140,13 +118,10 @@ ao-tools/Makefile ao-tools/lib/Makefile ao-tools/ao-rawload/Makefile ao-tools/ao-dbg/Makefile -ao-tools/ao-dumplog/Makefile ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile -ao-tools/ao-postflight/Makefile -ao-tools/ao-view/Makefile ao-utils/Makefile src/Version ]) diff --git a/debian/control b/debian/control index fc70c8e0..f784a702 100644 --- a/debian/control +++ b/debian/control @@ -3,13 +3,13 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -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, libtool, libjfreechart-java, libbluetooth-dev +Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, openjdk-6-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev Standards-Version: 3.9.2 Homepage: http://altusmetrum.org/AltOS Package: altos Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, default-jre | java2-runtime, freetts, nickle, plplot9-driver-cairo +Depends: ${shlibs:Depends}, ${misc:Depends}, default-jre | java2-runtime, freetts, nickle Suggests: slim | gdm Replaces: altusmetrum-themes, slim-altusmetrum Conflicts: altusmetrum-themes, slim-altusmetrum -- cgit v1.2.3 From 2165e82327faaada23f0503b8e49b80f938b746c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 00:09:51 -0700 Subject: altosui: Add tool-tips to config dialogs Provides more information about the various settings, and, when they're disabled, tells the user why. Signed-off-by: Keith Packard --- altosui/AltosConfigUI.java | 78 +++++++++++++++++++++++++++++++++++++++++-- altosui/AltosConfigureUI.java | 6 ++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index bb9e1cd2..d20dd073 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -116,6 +116,63 @@ public class AltosConfigUI } } + boolean is_telemini() { + String product = product_value.getText(); + return product != null && product.startsWith("TeleMini"); + } + + boolean is_telemetrum() { + String product = product_value.getText(); + return product != null && product.startsWith("TeleMetrum"); + } + + void set_radio_calibration_tool_tip() { + if (radio_calibration_value.isEnabled()) + radio_calibration_value.setToolTipText("Tune radio output to match desired frequency"); + else + radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode"); + } + + void set_radio_enable_tool_tip() { + if (radio_enable_value.isEnabled()) + radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions"); + else + radio_enable_value.setToolTipText("Firmware version does not support disabling radio"); + } + + void set_flight_log_max_tool_tip() { + if (flight_log_max_value.isEnabled()) + flight_log_max_value.setToolTipText("Size reserved for each flight log (in kB)"); + else { + if (is_telemetrum()) + flight_log_max_value.setToolTipText("Cannot set max value with flight logs in memory"); + else if (is_telemini()) + flight_log_max_value.setToolTipText("TeleMini stores only one flight"); + else + flight_log_max_value.setToolTipText("Cannot set max flight log value"); + } + } + + void set_ignite_mode_tool_tip() { + if (ignite_mode_value.isEnabled()) + ignite_mode_value.setToolTipText("Select when igniters will be fired"); + else + ignite_mode_value.setToolTipText("Older firmware could not select ignite mode"); + } + + void set_pad_orientation_tool_tip() { + if (pad_orientation_value.isEnabled()) + pad_orientation_value.setToolTipText("How will TeleMetrum be mounted in the airframe"); + else { + if (is_telemetrum()) + pad_orientation_value.setToolTipText("Older TeleMetrum firmware must fly antenna forward"); + else if (is_telemini()) + pad_orientation_value.setToolTipText("TeleMini doesn't care how it is mounted"); + else + pad_orientation_value.setToolTipText("Can't select orientation"); + } + } + /* Build the UI using a grid bag */ public AltosConfigUI(JFrame in_owner, boolean remote) { super (in_owner, "Configure TeleMetrum", false); @@ -216,6 +273,7 @@ public class AltosConfigUI main_deploy_value.setEditable(true); main_deploy_value.addItemListener(this); pane.add(main_deploy_value, c); + main_deploy_value.setToolTipText("Height above pad altitude to fire main charge"); /* Apogee delay */ c = new GridBagConstraints(); @@ -240,6 +298,7 @@ public class AltosConfigUI apogee_delay_value.setEditable(true); apogee_delay_value.addItemListener(this); pane.add(apogee_delay_value, c); + apogee_delay_value.setToolTipText("Delay after apogee before charge fires"); /* Frequency */ c = new GridBagConstraints(); @@ -263,6 +322,7 @@ public class AltosConfigUI radio_frequency_value = new AltosFreqList(); radio_frequency_value.addItemListener(this); pane.add(radio_frequency_value, c); + radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency"); /* Radio Calibration */ c = new GridBagConstraints(); @@ -288,6 +348,7 @@ public class AltosConfigUI if (remote) radio_calibration_value.setEnabled(false); pane.add(radio_calibration_value, c); + set_radio_calibration_tool_tip(); /* Radio Enable */ c = new GridBagConstraints(); @@ -311,6 +372,7 @@ public class AltosConfigUI radio_enable_value = new JRadioButton("Enabled"); radio_enable_value.addItemListener(this); pane.add(radio_enable_value, c); + set_radio_enable_tool_tip(); /* Callsign */ c = new GridBagConstraints(); @@ -334,6 +396,7 @@ public class AltosConfigUI callsign_value = new JTextField(AltosPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); pane.add(callsign_value, c); + callsign_value.setToolTipText("Callsign reported in telemetry data"); /* Flight log max */ c = new GridBagConstraints(); @@ -358,6 +421,7 @@ public class AltosConfigUI flight_log_max_value.setEditable(true); flight_log_max_value.addItemListener(this); pane.add(flight_log_max_value, c); + set_flight_log_max_tool_tip(); /* Ignite mode */ c = new GridBagConstraints(); @@ -382,6 +446,7 @@ public class AltosConfigUI ignite_mode_value.setEditable(false); ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); + set_ignite_mode_tool_tip(); /* Pad orientation */ c = new GridBagConstraints(); @@ -406,6 +471,7 @@ public class AltosConfigUI pad_orientation_value.setEditable(false); pad_orientation_value.addItemListener(this); pane.add(pad_orientation_value, c); + set_pad_orientation_tool_tip(); /* Buttons */ c = new GridBagConstraints(); @@ -521,6 +587,8 @@ public class AltosConfigUI public void set_product(String product) { radio_frequency_value.set_product(product); product_value.setText(product); + set_pad_orientation_tool_tip(); + set_flight_log_max_tool_tip(); } public void set_version(String version) { @@ -585,12 +653,14 @@ public class AltosConfigUI } public void set_radio_enable(int new_radio_enable) { - if (new_radio_enable >= 0) + if (new_radio_enable >= 0) { radio_enable_value.setSelected(new_radio_enable > 0); - else { + radio_enable_value.setEnabled(true); + } else { radio_enable_value.setSelected(true); radio_enable_value.setEnabled(false); } + set_radio_enable_tool_tip(); } public int radio_enable() { @@ -612,10 +682,12 @@ public class AltosConfigUI if (new_flight_log_max == 0) flight_log_max_value.setEnabled(false); flight_log_max_value.setSelectedItem(Integer.toString(new_flight_log_max)); + set_flight_log_max_tool_tip(); } public void set_flight_log_max_enabled(boolean enable) { flight_log_max_value.setEnabled(enable); + set_flight_log_max_tool_tip(); } public int flight_log_max() { @@ -642,6 +714,7 @@ public class AltosConfigUI ignite_mode_value.setEnabled(true); } ignite_mode_value.setSelectedIndex(new_ignite_mode); + set_ignite_mode_tool_tip(); } public int ignite_mode() { @@ -660,6 +733,7 @@ public class AltosConfigUI pad_orientation_value.setEnabled(true); } pad_orientation_value.setSelectedIndex(new_pad_orientation); + set_pad_orientation_tool_tip(); } public int pad_orientation() { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index abb54c74..0c865d0e 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -125,6 +125,7 @@ public class AltosConfigureUI c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; pane.add(enable_voice, c); + enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); c.gridx = 2; c.gridy = 2; @@ -139,6 +140,7 @@ public class AltosConfigureUI } }); pane.add(test_voice, c); + test_voice.setToolTipText("Play a stock audio clip to check volume"); /* Log directory settings */ c.gridx = 0; @@ -161,6 +163,7 @@ public class AltosConfigureUI c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; pane.add(configure_log, c); + configure_log.setToolTipText("Which directory flight logs are stored in"); /* Callsign setting */ c.gridx = 0; @@ -178,6 +181,7 @@ public class AltosConfigureUI c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; pane.add(callsign_value, c); + callsign_value.setToolTipText("Callsign sent in packet mode"); /* Serial debug setting */ c.gridx = 0; @@ -195,6 +199,7 @@ public class AltosConfigureUI AltosPreferences.set_serial_debug(enabled); } }); + serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); c.gridx = 1; c.gridy = 5; @@ -223,6 +228,7 @@ public class AltosConfigureUI AltosConfigFreqUI.show(owner); } }); + manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); // BLUETOOTH // c.gridx = 2; c.gridx = 1; -- cgit v1.2.3 From 3b0a9a1c87390747492bfef435ac8e0829ec748f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 00:29:36 -0700 Subject: altosui: Try to get dialogs to look a little better grid bag constraints are not my friend. Signed-off-by: Keith Packard --- altosui/AltosFlightUI.java | 7 +++++++ altosui/AltosIgniteUI.java | 5 ++--- altosui/AltosScanUI.java | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 51768046..abe08a18 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -172,7 +172,10 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { }); c.gridx = 0; c.gridy = 0; + c.weightx = 0; + c.weighty = 0; c.insets = new Insets(3, 3, 3, 3); + c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; bag.add (frequencies, c); @@ -186,6 +189,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { telemetry = Altos.ao_telemetry_standard; telemetries.setSelectedIndex(telemetry - 1); telemetries.setMaximumRowCount(Altos.ao_telemetry_max); + telemetries.setPreferredSize(null); + telemetries.revalidate(); telemetries.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int telemetry = telemetries.getSelectedIndex() + 1; @@ -195,6 +200,8 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { }); c.gridx = 1; c.gridy = 0; + c.weightx = 0; + c.weighty = 0; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; bag.add (telemetries, c); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 806b87b9..c11a8614 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -341,8 +341,8 @@ public class AltosIgniteUI c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; c.insets = i; - c.weightx = 1; - c.weighty = 1; + c.weightx = 0; + c.weighty = 0; c.gridx = 0; c.gridy = 0; @@ -412,7 +412,6 @@ public class AltosIgniteUI close.addActionListener(this); close.setActionCommand("close"); - pack(); setLocationRelativeTo(owner); diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index dd6672aa..bce4b32c 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -386,7 +386,7 @@ public class AltosScanUI set_label(); - c.fill = GridBagConstraints.NONE; + c.fill = GridBagConstraints.HORIZONTAL; c.anchor = GridBagConstraints.WEST; c.insets = i; c.weightx = 1; -- cgit v1.2.3 From 06aee245eb74e839e50226fa2ddb967c3977fe7c Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:41:53 -0600 Subject: another test round --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 0a6001b8..9f386680 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.7.0) +AC_INIT([altos], 0.9.7.1) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From bf6f00693c394f885d3378415dc7c8a1815a31ed Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:43:59 -0600 Subject: roll changelog back in prep for another test build --- debian/changelog | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/debian/changelog b/debian/changelog index 6bec4012..e786b10f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,39 +1,3 @@ -altos (0.9.7.0) unstable; urgency=low - - [ Keith Packard ] - * altos: Lost change that reported flight 0 when log memory was full - * altosui: Ancient log files used 'apogee' for 'coast' state - * altosui: Add 'On-board Data Logging' indicator to pad tab - * altosui: remove debug printf in pad pane - * altosui: Disable 'max flight log' config when there are stored flights - * altos: Merge common config code in ao_config.c - * Bump version to 0.9.7 - * altos/altosui: Add ability to disable telemetry/rdf completely - * altosui: Clean up command line processing. Add --graph - * altos-fat/windows: Check and install Java 1.6 as needed - * altosui/windows: Fix a bunch of windows compiler warnings. - * altosui: Attempt to make both 32- and 64-bit windows DLLs - * doc: Add note about telemetry disable mode to 1.0 release notes - * doc: Add Installation Recommendations chapter - * altosui: Add a few simple unit conversions - * altosui: Capture date/time/serial/flight in AltosFlightStats - * altosui: Add date/time/serial/flight to flight stats tab - * altosui: Show filename in AltosGraph window - * altosui: Add --summary option to dump flight stats to stdout - * altosui: Make monitor-idle display correct 'On-board data logging' status - * altosui: Can't configure flight log max on TeleMini - * altosui: fix 'magic' string to signal end of config data - * altosui: Only 'show' config dialog once - * altosui: Reset all config data on 'reset' command - * altosui: Update mac os X library - * libaltos: fix Mac OS X function signatures - * altosui: add tool-tips to the button box. - - [ Bdale Garbee ] - * turn off auto-tagging during Debian build - - -- Bdale Garbee Tue, 23 Aug 2011 21:36:50 -0600 - altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From cf2823cab40aa450375c108bae8ed6b051fbefe5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:45:28 -0600 Subject: update changelogs for Debian build --- ChangeLog | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 43 ++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2a95a1ef..9d7732aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,70 @@ +commit bf6f00693c394f885d3378415dc7c8a1815a31ed +Author: Bdale Garbee +Date: Wed Aug 24 01:43:59 2011 -0600 + + roll changelog back in prep for another test build + +commit 06aee245eb74e839e50226fa2ddb967c3977fe7c +Author: Bdale Garbee +Date: Wed Aug 24 01:41:53 2011 -0600 + + another test round + +commit 4d94e8f9f807a0bbeab0cdead011e74eeca1d1b6 +Merge: 4b5369d 3b0a9a1 +Author: Bdale Garbee +Date: Wed Aug 24 01:38:58 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 3b0a9a1c87390747492bfef435ac8e0829ec748f +Author: Keith Packard +Date: Wed Aug 24 00:29:36 2011 -0700 + + altosui: Try to get dialogs to look a little better + + grid bag constraints are not my friend. + + Signed-off-by: Keith Packard + +commit 2165e82327faaada23f0503b8e49b80f938b746c +Author: Keith Packard +Date: Wed Aug 24 00:09:51 2011 -0700 + + altosui: Add tool-tips to config dialogs + + Provides more information about the various settings, and, when + they're disabled, tells the user why. + + Signed-off-by: Keith Packard + +commit 63808e0392f43633f92fee137d968e969dd364c9 +Author: Keith Packard +Date: Tue Aug 23 23:20:00 2011 -0700 + + Remove stale tools (ao-dumplog, ao-postflight, ao-view) + + These tools have all been supplanted by altosui at this point, and + keeping them around increases the build dependencies by quite a lot. + + Signed-off-by: Keith Packard + +commit 186dfc7c72aa7eba281f29f917088e49e44c2ddc +Author: Keith Packard +Date: Tue Aug 23 22:51:57 2011 -0700 + + altosui: Use system look&feel + + Turn on the 'be less ugly bit' + + Signed-off-by: Keith Packard + +commit 4b5369dc3da2fc8441eeacbf094537b0cf52240d +Author: Bdale Garbee +Date: Tue Aug 23 21:37:17 2011 -0600 + + update changelogs for Debian build + commit 99316a17a9642a207c45610e7cc1c33c2600ece0 Author: Bdale Garbee Date: Tue Aug 23 21:33:53 2011 -0600 diff --git a/debian/changelog b/debian/changelog index e786b10f..f00e35f2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,46 @@ +altos (0.9.7.1) unstable; urgency=low + + [ Keith Packard ] + * altos: Lost change that reported flight 0 when log memory was full + * altosui: Ancient log files used 'apogee' for 'coast' state + * altosui: Add 'On-board Data Logging' indicator to pad tab + * altosui: remove debug printf in pad pane + * altosui: Disable 'max flight log' config when there are stored flights + * altos: Merge common config code in ao_config.c + * Bump version to 0.9.7 + * altos/altosui: Add ability to disable telemetry/rdf completely + * altosui: Clean up command line processing. Add --graph + * altos-fat/windows: Check and install Java 1.6 as needed + * altosui/windows: Fix a bunch of windows compiler warnings. + * altosui: Attempt to make both 32- and 64-bit windows DLLs + * doc: Add note about telemetry disable mode to 1.0 release notes + * doc: Add Installation Recommendations chapter + * altosui: Add a few simple unit conversions + * altosui: Capture date/time/serial/flight in AltosFlightStats + * altosui: Add date/time/serial/flight to flight stats tab + * altosui: Show filename in AltosGraph window + * altosui: Add --summary option to dump flight stats to stdout + * altosui: Make monitor-idle display correct 'On-board data logging' status + * altosui: Can't configure flight log max on TeleMini + * altosui: fix 'magic' string to signal end of config data + * altosui: Only 'show' config dialog once + * altosui: Reset all config data on 'reset' command + * altosui: Update mac os X library + * libaltos: fix Mac OS X function signatures + * altosui: add tool-tips to the button box. + * altosui: Use system look&feel + * Remove stale tools (ao-dumplog, ao-postflight, ao-view) + * altosui: Add tool-tips to config dialogs + * altosui: Try to get dialogs to look a little better + + [ Bdale Garbee ] + * turn off auto-tagging during Debian build + * update changelogs for Debian build + * rewind changelog to 0.9.6.0 for rebuild + * update changelogs for Debian build + + -- Bdale Garbee Wed, 24 Aug 2011 01:44:46 -0600 + altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 82634eae16f9691a6c70a48d0858a399814631f2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:50:56 -0600 Subject: add pkg-config to the build deps --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index f784a702..beac70dc 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,7 @@ Section: otherosfs Priority: extra Maintainer: Bdale Garbee Uploaders: Keith Packard -Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, openjdk-6-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev +Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, openjdk-6-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config Standards-Version: 3.9.2 Homepage: http://altusmetrum.org/AltOS -- cgit v1.2.3 From 1d286dab223e6c44a25180f944ccb5ba8ed9d5f5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:51:54 -0600 Subject: prepare for another rebuild --- debian/changelog | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/debian/changelog b/debian/changelog index f00e35f2..e786b10f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,46 +1,3 @@ -altos (0.9.7.1) unstable; urgency=low - - [ Keith Packard ] - * altos: Lost change that reported flight 0 when log memory was full - * altosui: Ancient log files used 'apogee' for 'coast' state - * altosui: Add 'On-board Data Logging' indicator to pad tab - * altosui: remove debug printf in pad pane - * altosui: Disable 'max flight log' config when there are stored flights - * altos: Merge common config code in ao_config.c - * Bump version to 0.9.7 - * altos/altosui: Add ability to disable telemetry/rdf completely - * altosui: Clean up command line processing. Add --graph - * altos-fat/windows: Check and install Java 1.6 as needed - * altosui/windows: Fix a bunch of windows compiler warnings. - * altosui: Attempt to make both 32- and 64-bit windows DLLs - * doc: Add note about telemetry disable mode to 1.0 release notes - * doc: Add Installation Recommendations chapter - * altosui: Add a few simple unit conversions - * altosui: Capture date/time/serial/flight in AltosFlightStats - * altosui: Add date/time/serial/flight to flight stats tab - * altosui: Show filename in AltosGraph window - * altosui: Add --summary option to dump flight stats to stdout - * altosui: Make monitor-idle display correct 'On-board data logging' status - * altosui: Can't configure flight log max on TeleMini - * altosui: fix 'magic' string to signal end of config data - * altosui: Only 'show' config dialog once - * altosui: Reset all config data on 'reset' command - * altosui: Update mac os X library - * libaltos: fix Mac OS X function signatures - * altosui: add tool-tips to the button box. - * altosui: Use system look&feel - * Remove stale tools (ao-dumplog, ao-postflight, ao-view) - * altosui: Add tool-tips to config dialogs - * altosui: Try to get dialogs to look a little better - - [ Bdale Garbee ] - * turn off auto-tagging during Debian build - * update changelogs for Debian build - * rewind changelog to 0.9.6.0 for rebuild - * update changelogs for Debian build - - -- Bdale Garbee Wed, 24 Aug 2011 01:44:46 -0600 - altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 02d65453225a3807e61b2ac6e2a26da31a05bd45 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 01:53:02 -0600 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/ChangeLog b/ChangeLog index 9d7732aa..79be2032 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 1d286dab223e6c44a25180f944ccb5ba8ed9d5f5 +Author: Bdale Garbee +Date: Wed Aug 24 01:51:54 2011 -0600 + + prepare for another rebuild + +commit 82634eae16f9691a6c70a48d0858a399814631f2 +Author: Bdale Garbee +Date: Wed Aug 24 01:50:56 2011 -0600 + + add pkg-config to the build deps + +commit cf2823cab40aa450375c108bae8ed6b051fbefe5 +Author: Bdale Garbee +Date: Wed Aug 24 01:45:28 2011 -0600 + + update changelogs for Debian build + commit bf6f00693c394f885d3378415dc7c8a1815a31ed Author: Bdale Garbee Date: Wed Aug 24 01:43:59 2011 -0600 diff --git a/debian/changelog b/debian/changelog index e786b10f..e870885c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,55 @@ +altos (0.9.7.1) unstable; urgency=low + + [ Keith Packard ] + * altos: Lost change that reported flight 0 when log memory was full + * altosui: Ancient log files used 'apogee' for 'coast' state + * altosui: Add 'On-board Data Logging' indicator to pad tab + * altosui: remove debug printf in pad pane + * altosui: Disable 'max flight log' config when there are stored flights + * altos: Merge common config code in ao_config.c + * Bump version to 0.9.7 + * altos/altosui: Add ability to disable telemetry/rdf completely + * altosui: Clean up command line processing. Add --graph + * altos-fat/windows: Check and install Java 1.6 as needed + * altosui/windows: Fix a bunch of windows compiler warnings. + * altosui: Attempt to make both 32- and 64-bit windows DLLs + * doc: Add note about telemetry disable mode to 1.0 release notes + * doc: Add Installation Recommendations chapter + * altosui: Add a few simple unit conversions + * altosui: Capture date/time/serial/flight in AltosFlightStats + * altosui: Add date/time/serial/flight to flight stats tab + * altosui: Show filename in AltosGraph window + * altosui: Add --summary option to dump flight stats to stdout + * altosui: Make monitor-idle display correct 'On-board data logging' status + * altosui: Can't configure flight log max on TeleMini + * altosui: fix 'magic' string to signal end of config data + * altosui: Only 'show' config dialog once + * altosui: Reset all config data on 'reset' command + * altosui: Update mac os X library + * libaltos: fix Mac OS X function signatures + * altosui: add tool-tips to the button box. + + [ Bdale Garbee ] + * turn off auto-tagging during Debian build + * update changelogs for Debian build + * rewind changelog to 0.9.6.0 for rebuild + * update changelogs for Debian build + + [ Keith Packard ] + * altosui: Use system look&feel + * Remove stale tools (ao-dumplog, ao-postflight, ao-view) + * altosui: Add tool-tips to config dialogs + * altosui: Try to get dialogs to look a little better + + [ Bdale Garbee ] + * another test round + * roll changelog back in prep for another test build + * update changelogs for Debian build + * add pkg-config to the build deps + * prepare for another rebuild + + -- Bdale Garbee Wed, 24 Aug 2011 01:52:35 -0600 + altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 9849883a754a73b861dd7be530753ff5c2abb499 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 01:48:28 -0700 Subject: altosui: Don't trust companion telemetry record 'channels' count It can be bogus, allowing the code to walk off the end of the allocated data array. Signed-off-by: Keith Packard --- altosui/AltosTelemetryRecordCompanion.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosTelemetryRecordCompanion.java b/altosui/AltosTelemetryRecordCompanion.java index 11b349e1..52d7f4cf 100644 --- a/altosui/AltosTelemetryRecordCompanion.java +++ b/altosui/AltosTelemetryRecordCompanion.java @@ -36,7 +36,7 @@ public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { companion.tick = tick; companion.board_id = uint8(5); companion.update_period = uint8(6+off); - for (int i = 0; i < channels; i++) + for (int i = 0; i < companion.companion_data.length; i++) companion.companion_data[i] = uint16(8 + off + i * 2); } -- cgit v1.2.3 From cbfbaabb39f9f7709d00cf3dc63cc1bc7563062e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 19:13:03 -0700 Subject: altosui: Make flight monitor font size configurable Tiny netbooks aren't tall enough for the 'usual' font size, so provide a smaller option. Then provide a bigger option, just because. Signed-off-by: Keith Packard --- altosui/Altos.java | 42 ++++++++++++++++++++++++++-- altosui/AltosAscent.java | 30 +++++++++++++++++++- altosui/AltosCompanionInfo.java | 15 +++++----- altosui/AltosConfigureUI.java | 61 +++++++++++++++++++++++++++++++---------- altosui/AltosDescent.java | 28 +++++++++++++++++++ altosui/AltosFlightDisplay.java | 2 ++ altosui/AltosFlightStatus.java | 14 ++++++++++ altosui/AltosFlightUI.java | 21 +++++++++++++- altosui/AltosFontListener.java | 22 +++++++++++++++ altosui/AltosIdleMonitorUI.java | 5 ++++ altosui/AltosInfoTable.java | 12 ++++---- altosui/AltosLanded.java | 23 ++++++++++++---- altosui/AltosPad.java | 22 +++++++++++++++ altosui/AltosPreferences.java | 42 ++++++++++++++++++++++++++++ altosui/AltosSiteMap.java | 4 +++ altosui/Makefile.am | 1 + doc/altusmetrum.xsl | 7 +++++ 17 files changed, 314 insertions(+), 37 deletions(-) create mode 100644 altosui/AltosFontListener.java diff --git a/altosui/Altos.java b/altosui/Altos.java index ddf1005a..e4f974f9 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -97,9 +97,45 @@ public class Altos { static final int tab_elt_pad = 5; - static final Font label_font = new Font("Dialog", Font.PLAIN, 22); - static final Font value_font = new Font("Monospaced", Font.PLAIN, 22); - static final Font status_font = new Font("SansSerif", Font.BOLD, 24); + static Font label_font; + static Font value_font; + static Font status_font; + static Font table_label_font; + static Font table_value_font; + + final static int font_size_small = 1; + final static int font_size_medium = 2; + final static int font_size_large = 3; + + static void set_fonts(int size) { + int brief_size; + int table_size; + int status_size; + + switch (size) { + case font_size_small: + brief_size = 16; + status_size = 18; + table_size = 11; + break; + default: + case font_size_medium: + brief_size = 22; + status_size = 24; + table_size = 14; + break; + case font_size_large: + brief_size = 26; + status_size = 30; + table_size = 17; + break; + } + label_font = new Font("Dialog", Font.PLAIN, brief_size); + value_font = new Font("Monospaced", Font.PLAIN, brief_size); + status_font = new Font("SansSerif", Font.BOLD, status_size); + table_label_font = new Font("SansSerif", Font.PLAIN, table_size); + table_value_font = new Font("Monospaced", Font.PLAIN, table_size); + } static final int text_width = 20; diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index d607b0c5..c8e5f3af 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -30,6 +30,7 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; + JLabel cur, max; public class AscentStatus { JLabel label; @@ -54,6 +55,11 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { lights.set(false); } + void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + public AscentStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -109,6 +115,11 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { label.setVisible(false); value.setVisible(false); } + void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + public AscentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -151,6 +162,12 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { max = AltosRecord.MISSING; } + void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + max_value.setFont(Altos.value_font); + } + void show(String format, double v) { if (v == AltosRecord.MISSING) { value.setText("Missing"); @@ -314,6 +331,18 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { accel.reset(); } + public void set_font() { + cur.setFont(Altos.label_font); + max.setFont(Altos.label_font); + lat.set_font(); + lon.set_font(); + main.set_font(); + apogee.set_font(); + height.set_font(); + speed.set_font(); + accel.set_font(); + } + public void show(AltosState state, int crc_errors) { if (state.gps != null && state.gps.connected) { lat.show(state, crc_errors); @@ -337,7 +366,6 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { public void labels(GridBagLayout layout, int y) { GridBagConstraints c; - JLabel cur, max; cur = new JLabel("Current"); cur.setFont(Altos.label_font); diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index f287a8ea..82bde623 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -31,25 +31,26 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosCompanionInfo extends JTable { private AltosFlightInfoTableModel model; - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); - static final int info_columns = 2; static final int info_rows = 17; int desired_row_height() { - FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); + FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font); return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; } + public void set_font() { + setFont(Altos.table_value_font); + setRowHeight(desired_row_height()); + doLayout(); + } + public AltosCompanionInfo() { super(new AltosFlightInfoTableModel(info_rows, info_columns)); model = (AltosFlightInfoTableModel) getModel(); - setFont(infoValueFont); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); setShowGrid(true); - setRowHeight(desired_row_height()); - doLayout(); + set_font(); } public Dimension getPreferredScrollableViewportSize() { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 0c865d0e..bcb9636b 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -47,12 +47,17 @@ public class AltosConfigureUI JLabel callsign_label; JTextField callsign_value; + JLabel font_size_label; + JComboBox font_size_value; + JRadioButton serial_debug; // BLUETOOTH // JButton manage_bluetooth; JButton manage_frequencies; + final static String[] font_size_names = { "Small", "Medium", "Large" }; + /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { AltosPreferences.set_callsign(callsign_value.getText()); @@ -73,6 +78,8 @@ public class AltosConfigureUI Insets insets = new Insets(4, 4, 4, 4); + int row = 0; + owner = in_owner; voice = in_voice; pane = getContentPane(); @@ -85,14 +92,14 @@ public class AltosConfigureUI /* Nice label at the top */ c.gridx = 0; - c.gridy = 0; + c.gridy = row++; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; pane.add(new JLabel ("Configure AltOS UI"), c); c.gridx = 0; - c.gridy = 1; + c.gridy = row++; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -100,7 +107,7 @@ public class AltosConfigureUI /* Voice settings */ c.gridx = 0; - c.gridy = 2; + c.gridy = row; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -119,7 +126,7 @@ public class AltosConfigureUI } }); c.gridx = 1; - c.gridy = 2; + c.gridy = row; c.gridwidth = 1; c.weightx = 1; c.fill = GridBagConstraints.NONE; @@ -128,7 +135,7 @@ public class AltosConfigureUI enable_voice.setToolTipText("Enable/Disable all audio in-flight announcements"); c.gridx = 2; - c.gridy = 2; + c.gridy = row++; c.gridwidth = 1; c.weightx = 1; c.fill = GridBagConstraints.NONE; @@ -144,7 +151,7 @@ public class AltosConfigureUI /* Log directory settings */ c.gridx = 0; - c.gridy = 3; + c.gridy = row; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -158,7 +165,7 @@ public class AltosConfigureUI } }); c.gridx = 1; - c.gridy = 3; + c.gridy = row++; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; @@ -167,7 +174,7 @@ public class AltosConfigureUI /* Callsign setting */ c.gridx = 0; - c.gridy = 4; + c.gridy = row; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -176,16 +183,42 @@ public class AltosConfigureUI callsign_value = new JTextField(AltosPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); c.gridx = 1; - c.gridy = 4; + c.gridy = row++; c.gridwidth = 2; c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.WEST; pane.add(callsign_value, c); callsign_value.setToolTipText("Callsign sent in packet mode"); + /* Font size setting */ + c.gridx = 0; + c.gridy = row; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Font size"), c); + + font_size_value = new JComboBox(font_size_names); + int font_size = AltosPreferences.font_size(); + font_size_value.setSelectedIndex(font_size - Altos.font_size_small); + font_size_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int size = font_size_value.getSelectedIndex() + Altos.font_size_small; + + AltosPreferences.set_font_size(size); + } + }); + c.gridx = 1; + c.gridy = row++; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + pane.add(font_size_value, c); + font_size_value.setToolTipText("Font size used in telemetry window"); + /* Serial debug setting */ c.gridx = 0; - c.gridy = 5; + c.gridy = row; c.gridwidth = 1; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -202,7 +235,7 @@ public class AltosConfigureUI serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); c.gridx = 1; - c.gridy = 5; + c.gridy = row++; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -216,7 +249,7 @@ public class AltosConfigureUI // } // }); // c.gridx = 0; -// c.gridy = 6; +// c.gridy = row++; // c.gridwidth = 2; // c.fill = GridBagConstraints.NONE; // c.anchor = GridBagConstraints.WEST; @@ -232,7 +265,7 @@ public class AltosConfigureUI // BLUETOOTH // c.gridx = 2; c.gridx = 1; - c.gridy = 6; + c.gridy = row++; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.WEST; @@ -246,7 +279,7 @@ public class AltosConfigureUI } }); c.gridx = 0; - c.gridy = 7; + c.gridy = row++; c.gridwidth = 3; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 2a9e7eef..0fcd690b 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -55,6 +55,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { lights.set(false); } + void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + public DescentStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -121,6 +126,11 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value.setText(v); } + void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + public DescentValue (GridBagLayout layout, int x, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -169,6 +179,12 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2.setVisible(false); } + void set_font() { + label.setFont(Altos.label_font); + value1.setFont(Altos.value_font); + value2.setFont(Altos.value_font); + } + abstract void show(AltosState state, int crc_errors); void show(String v1, String v2) { @@ -361,6 +377,18 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { apogee.reset(); } + public void set_font() { + lat.set_font(); + lon.set_font(); + height.set_font(); + speed.set_font(); + bearing.set_font(); + range.set_font(); + elevation.set_font(); + main.set_font(); + apogee.set_font(); + } + public void show(AltosState state, int crc_errors) { height.show(state, crc_errors); speed.show(state, crc_errors); diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java index d18d1d1f..f633c8e6 100644 --- a/altosui/AltosFlightDisplay.java +++ b/altosui/AltosFlightDisplay.java @@ -21,4 +21,6 @@ public interface AltosFlightDisplay { void reset(); void show(AltosState state, int crc_errors); + + void set_font(); } diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 59c9e9db..ed273384 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -40,6 +40,12 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay void reset() { value.setText(""); } + + void set_font() { + label.setFont(Altos.status_font); + value.setFont(Altos.status_font); + } + public FlightValue (GridBagLayout layout, int x, String text) { GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); @@ -127,6 +133,14 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay rssi.reset(); } + public void set_font () { + call.set_font(); + serial.set_font(); + flight.set_font(); + flight_state.set_font(); + rssi.set_font(); + } + public void show (AltosState state, int crc_errors) { call.show(state, crc_errors); serial.show(state, crc_errors); diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index abe08a18..b44b9d43 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -public class AltosFlightUI extends JFrame implements AltosFlightDisplay { +public class AltosFlightUI extends JFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; @@ -83,6 +83,21 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { sitemap.reset(); } + public void set_font() { + pad.set_font(); + ascent.set_font(); + descent.set_font(); + landed.set_font(); + flightStatus.set_font(); + flightInfo.set_font(); + sitemap.set_font(); + companion.set_font(); + } + + public void font_size_changed(int font_size) { + set_font(); + } + public void show(AltosState state, int crc_errors) { JComponent tab = which_tab(state); try { @@ -254,12 +269,16 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { bag.add(pane, c); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + AltosPreferences.register_font_listener(this); + addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { disconnect(); setVisible(false); dispose(); + AltosPreferences.unregister_font_listener(AltosFlightUI.this); if (exit_on_close) System.exit(0); } diff --git a/altosui/AltosFontListener.java b/altosui/AltosFontListener.java new file mode 100644 index 00000000..0dda0f29 --- /dev/null +++ b/altosui/AltosFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 interface AltosFontListener { + void font_size_changed(int font_size); +} diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 142f0278..988a797c 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -284,6 +284,11 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { flightInfo.clear(); } + public void set_font() { + pad.set_font(); + flightInfo.set_font(); + } + public void show(AltosState state, int crc_errors) { try { pad.show(state, crc_errors); diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 8ebeaba1..c023369e 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -31,27 +31,29 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosInfoTable extends JTable { private AltosFlightInfoTableModel model; - private Font infoLabelFont = new Font("SansSerif", Font.PLAIN, 14); - private Font infoValueFont = new Font("Monospaced", Font.PLAIN, 14); - static final int info_columns = 3; static final int info_rows = 17; int desired_row_height() { - FontMetrics infoValueMetrics = getFontMetrics(infoValueFont); + FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font); return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; } public AltosInfoTable() { super(new AltosFlightInfoTableModel(info_rows, info_columns)); model = (AltosFlightInfoTableModel) getModel(); - setFont(infoValueFont); + setFont(Altos.table_value_font); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); setShowGrid(true); setRowHeight(desired_row_height()); doLayout(); } + public void set_font() { + setFont(Altos.table_value_font); + doLayout(); + } + public Dimension getPreferredScrollableViewportSize() { return getPreferredSize(); } diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 71c10663..50e6b542 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -30,8 +30,6 @@ import java.util.concurrent.LinkedBlockingQueue; public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { GridBagLayout layout; - Font label_font; - Font value_font; public class LandedValue { JLabel label; @@ -47,6 +45,11 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio value.setVisible(true); } + public void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + void hide() { label.setVisible(false); value.setVisible(false); @@ -63,7 +66,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio c.weighty = 1; label = new JLabel(text); - label.setFont(label_font); + label.setFont(Altos.label_font); label.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridy = y; c.insets = new Insets(10, 10, 10, 10); @@ -74,7 +77,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio add(label); value = new JTextField(Altos.text_width); - value.setFont(value_font); + value.setFont(Altos.value_font); value.setHorizontalAlignment(SwingConstants.RIGHT); c.gridx = 1; c.gridy = y; c.anchor = GridBagConstraints.WEST; @@ -199,6 +202,16 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio accel.reset(); } + public void set_font() { + lat.set_font(); + lon.set_font(); + bearing.set_font(); + distance.set_font(); + height.set_font(); + speed.set_font(); + accel.set_font(); + } + public void show(AltosState state, int crc_errors) { if (state.gps != null && state.gps.connected) { bearing.show(state, crc_errors); @@ -259,8 +272,6 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio reader = in_reader; - label_font = new Font("Dialog", Font.PLAIN, 22); - value_font = new Font("Monospaced", Font.PLAIN, 22); setLayout(layout); /* Elements in descent display */ diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 3a8d04fe..6ef66f7a 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -54,6 +54,11 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { lights.setVisible(false); } + public void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + public LaunchStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -105,6 +110,11 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { value.setVisible(false); } + public void set_font() { + label.setFont(Altos.label_font); + value.setFont(Altos.value_font); + } + void reset() { value.setText(""); } @@ -282,6 +292,18 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { pad_alt.reset(); } + public void set_font() { + battery.set_font(); + apogee.set_font(); + main.set_font(); + logging_ready.set_font(); + gps_locked.set_font(); + gps_ready.set_font(); + pad_lat.set_font(); + pad_lon.set_font(); + pad_alt.set_font(); + } + public void show(AltosState state, int crc_errors) { battery.show(state, crc_errors); if (state.drogue_sense == AltosRecord.MISSING) diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index de926b38..716559ab 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -55,6 +55,9 @@ class AltosPreferences { /* scanning telemetry preferences name */ final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; + /* font size preferences name */ + final static String fontSizePreference = "FONT-SIZE"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -88,6 +91,10 @@ class AltosPreferences { /* Scanning telemetry */ static int scanning_telemetry; + static LinkedList font_listeners; + + static int font_size = Altos.font_size_medium; + /* List of frequencies */ final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; static AltosFrequency[] common_frequencies; @@ -164,6 +171,11 @@ class AltosPreferences { scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << Altos.ao_telemetry_standard)); + font_listeners = new LinkedList(); + + font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); + Altos.set_fonts(font_size); + String firmwaredir_string = preferences.get(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); @@ -335,6 +347,36 @@ class AltosPreferences { return firmwaredir; } + public static int font_size() { + return font_size; + } + + static void set_fonts() { + } + + public static void set_font_size(int new_font_size) { + font_size = new_font_size; + synchronized (preferences) { + preferences.putInt(fontSizePreference, font_size); + flush_preferences(); + Altos.set_fonts(font_size); + for (AltosFontListener l : font_listeners) + l.font_size_changed(font_size); + } + } + + public static void register_font_listener(AltosFontListener l) { + synchronized (preferences) { + font_listeners.add(l); + } + } + + public static void unregister_font_listener(AltosFontListener l) { + synchronized (preferences) { + font_listeners.remove(l); + } + } + public static void set_serial_debug(boolean new_serial_debug) { serial_debug = new_serial_debug; AltosSerial.set_debug(serial_debug); diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index b3fb3c54..c258b3e5 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -146,6 +146,10 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // nothing } + public void set_font() { + // nothing + } + private void loadMap(final AltosSiteMapTile tile, File pngfile, String pngurl) { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f626d3fa..ba1c830c 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -57,6 +57,7 @@ altosui_JAVA = \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ AltosFlightUI.java \ + AltosFontListener.java \ AltosFrequency.java \ AltosFreqList.java \ AltosGPS.java \ diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 601b62eb..df1e6635 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1537,6 +1537,13 @@ NAR #88757, TRA #12200 your local radio regulations.
+
+ Font Size + + Selects the set of fonts used in the flight monitor + window. Choose between the small, medium and large sets. + +
Serial Debug -- cgit v1.2.3 From 5a9972d41a87d4204c6c93cacf14e2962cc1c59c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 20:22:29 -0700 Subject: altos/windows: Get latest JRE 1.6 version (Version 6 update 27) No reason to download stale java bits. Signed-off-by: Keith Packard --- altosui/altos-windows.nsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index 70dc03ca..cbcb389d 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -1,7 +1,7 @@ !addplugindir Instdrv/NSIS/Plugins ; Definitions for Java 1.6 Detection !define JRE_VERSION "1.6" -!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=18714&/jre-6u5-windows-i586-p.exe" +!define JRE_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586-p.exe" !define PRODUCT_NAME "Altus Metrum Windows Software" Name "Altus Metrum Installer" @@ -23,7 +23,7 @@ ShowInstDetails Show ComponentText "Altus Metrum Software and Driver Installer" Function GetJRE - MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION}, it will now \ + MessageBox MB_OK "${PRODUCT_NAME} uses Java ${JRE_VERSION} 32-bit, it will now \ be downloaded and installed" StrCpy $2 "$TEMP\Java Runtime Environment.exe" -- cgit v1.2.3 From 963649aa064acfe75d2ff4babd9a0d35dc254e86 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 21:39:21 -0600 Subject: doc tweaks through chap 3 --- doc/altusmetrum.xsl | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index df1e6635..9c13bd89 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -99,7 +99,7 @@ NAR #88757, TRA #12200 future as you wish! - The first device created for our community is TeleMetrum, a dual + The first device created for our community was TeleMetrum, a dual deploy altimeter with fully integrated GPS and radio telemetry as standard features, and a "companion interface" that will support optional capabilities in the future. @@ -152,8 +152,8 @@ NAR #88757, TRA #12200 The TeleMini battery can be charged by disconnecting it from the - TeleMini board and plugging it into the battery charger board, - and connecting that via a USB cable to a laptop or other USB + TeleMini board and plugging it into a standalone battery charger + board, and connecting that via a USB cable to a laptop or other USB power source @@ -161,9 +161,11 @@ NAR #88757, TRA #12200 RF interface. If you plug it in to your Mac or Linux computer it should "just work", showing up as a serial port device. Windows systems need driver information that is part of the AltOS download to know that the - existing USB modem driver will work. If you are using Linux and are - having problems, try moving to a fresher kernel (2.6.33 or newer), as - the USB serial driver had ugly bugs in some earlier versions. + existing USB modem driver will work. We therefore recommend installing + our software before plugging in TeleDongle if you are using a Windows + computer. If you are using Linux and are having problems, try moving + to a fresher kernel (2.6.33 or newer), as the USB serial driver had + ugly bugs in some earlier versions. Next you should obtain and install the AltOS utilities. These include @@ -179,10 +181,10 @@ NAR #88757, TRA #12200 Handling Precautions - All Altus Metrum products are sophisticated electronic device. When handled gently and - properly installed in an airframe, theywill deliver impressive results. - However, like all electronic devices, there are some precautions you - must take. + All Altus Metrum products are sophisticated electronic devices. + When handled gently and properly installed in an airframe, they + will deliver impressive results. However, like all electronic + devices, there are some precautions you must take. The Lithium Polymer rechargeable batteries have an @@ -197,23 +199,30 @@ NAR #88757, TRA #12200 strapping them down, for example. - The barometric sensor is sensitive to sunlight. In normal - mounting situations, it and all of the other surface mount components + The barometric sensors used on both TeleMetrum and TeleMini are + sensitive to sunlight. In normal TeleMetrum mounting situations, it + and all of the other surface mount components are "down" towards whatever the underlying mounting surface is, so this is not normally a problem. Please consider this, though, when designing an installation, for example, in an airframe with a - see-through plastic payload bay. + see-through plastic payload bay. It is particularly important to + consider this with TeleMini, both because the baro sensor is on the + "top" of the board, and because many model rockets with payload bays + use clear plastic for the payload bay! Replacing these with an opaque + cardboard tube, painting them, or wrapping them with a layer of masking + tape are all reasonable approaches to keep the sensor out of direct + sunlight. - The barometric sensor sampling port must be able to - "breathe", + The barometric sensor sampling port must be able to "breathe", both by not being covered by foam or tape or other materials that might - directly block the hole on the top of the sensor, but also by having a + directly block the hole on the top of the sensor, and also by having a suitable static vent to outside air. - As with all other rocketry electronics, Altus Metrum altimeters must be protected - from exposure to corrosive motor exhaust and ejection charge gasses. + As with all other rocketry electronics, Altus Metrum altimeters must + be protected from exposure to corrosive motor exhaust and ejection + charge gasses. -- cgit v1.2.3 From ca0879ba6e5295b4fa790705f742eb647a462ea0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 20:42:09 -0700 Subject: doc: Spelling corrections in altusmetrum.xsl Lots of minor spelling errors. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 213 ++++++++++++++++++++++++++-------------------------- 1 file changed, 108 insertions(+), 105 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 9c13bd89..ddb40719 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -67,7 +67,7 @@ Kit" which has turned into the Getting Started chapter in this book. Bob was one of our first customers for a production TeleMetrum, and the enthusiasm that led to his contribution of - this section is immensely gratifying and highy appreciated! + this section is immensely gratifying and highly appreciated! And thanks to Anthony (AJ) Towns for contributing the @@ -107,7 +107,7 @@ NAR #88757, TRA #12200 The newest device is TeleMini, a dual deploy altimeter with radio telemetry and radio direction finding. This device is only - 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm airframe. + 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm air-frame. Complementing TeleMetrum and TeleMini is TeleDongle, a USB to RF interface for @@ -133,7 +133,7 @@ NAR #88757, TRA #12200 The TeleMetrum battery can be charged by plugging it into the corresponding socket of the TeleMetrum and then using the USB A to mini B - cable to plug the Telemetrum into your computer's USB socket. The + cable to plug the TeleMetrum into your computer's USB socket. The TeleMetrum circuitry will charge the battery whenever it is plugged in, because the TeleMetrum's on-off switch does NOT control the charging circuitry. @@ -141,7 +141,7 @@ NAR #88757, TRA #12200 When the GPS chip is initially searching for satellites, TeleMetrum will consume more current than it can pull - from the usb port, so the battery must be attached in order to get + from the USB port, so the battery must be attached in order to get satellite lock. Once GPS is locked, the current consumption goes back down enough to enable charging while running. So it's a good idea to fully charge the battery as your @@ -172,7 +172,7 @@ NAR #88757, TRA #12200 the AltosUI ground station program, current firmware images for TeleMetrum, TeleMini and TeleDongle, and a number of standalone utilities that are rarely needed. Pre-built binary packages are available for Debian - Linux, Microsoft Windows, and recent MacOSX versions. Full sourcecode + Linux, Microsoft Windows, and recent MacOSX versions. Full source code and build instructions for some other Linux variants are also available. The latest version may always be downloaded from . @@ -182,7 +182,7 @@ NAR #88757, TRA #12200 Handling Precautions All Altus Metrum products are sophisticated electronic devices. - When handled gently and properly installed in an airframe, they + When handled gently and properly installed in an air-frame, they will deliver impressive results. However, like all electronic devices, there are some precautions you must take. @@ -194,7 +194,7 @@ NAR #88757, TRA #12200 or their leads are allowed to short, they can and will release their energy very rapidly! Thus we recommend that you take some care when handling our batteries - and consider giving them some extra protection in your airframe. We + and consider giving them some extra protection in your air-frame. We often wrap them in suitable scraps of closed-cell packing foam before strapping them down, for example. @@ -204,7 +204,7 @@ NAR #88757, TRA #12200 and all of the other surface mount components are "down" towards whatever the underlying mounting surface is, so this is not normally a problem. Please consider this, though, when - designing an installation, for example, in an airframe with a + designing an installation, for example, in an air-frame with a see-through plastic payload bay. It is particularly important to consider this with TeleMini, both because the baro sensor is on the "top" of the board, and because many model rockets with payload bays @@ -229,7 +229,7 @@ NAR #88757, TRA #12200 Hardware Overview TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to - fit inside coupler for 29mm airframe tubing, but using it in a tube that + fit inside coupler for 29mm air-frame tubing, but using it in a tube that small in diameter may require some creativity in mounting and wiring to succeed! The default 1/4 wave UHF wire antenna attached to the center of the nose-cone end of @@ -240,7 +240,7 @@ NAR #88757, TRA #12200 TeleMini is a 0.5 inch by 1.5 inch circuit board. It was designed to - fit inside an 18mm airframe tube, but using it in a tube that + fit inside an 18mm air-frame tube, but using it in a tube that small in diameter may require some creativity in mounting and wiring to succeed! The default 1/4 wave UHF wire antenna attached to the center of the nose-cone end of @@ -257,7 +257,7 @@ NAR #88757, TRA #12200 charges. - By default, we use the unregulated output of the LiPo battery directly + By default, we use the unregulated output of the Li-Po battery directly to fire ejection charges. This works marvelously with standard low-current e-matches like the J-Tek from MJG Technologies, and with Quest Q2G2 igniters. However, if you @@ -279,7 +279,7 @@ NAR #88757, TRA #12200 directly to the board and can be connected directly to the switch. - For most airframes, the integrated antennas are more than + For most air-frames, the integrated antennas are more than adequate However, if you are installing in a carbon-fiber electronics bay which is opaque to RF signals, you may need to use off-board external antennas instead. In this case, you can @@ -296,7 +296,7 @@ NAR #88757, TRA #12200 The AltOS firmware build for the altimeters has two fundamental modes, "idle" and "flight". Which of these modes - the firmware operates in is determined at startup time. For + the firmware operates in is determined at start up time. For TeleMetrum, the mode is controlled by the orientation of the rocket (well, actually the board, of course...) at the time power is switched on. If the rocket is "nose up", then @@ -310,7 +310,7 @@ NAR #88757, TRA #12200 At power on, you will hear three beeps or see three flashes - ("S" in Morse code for startup) and then a pause while + ("S" in Morse code for start up) and then a pause while the altimeter completes initialization and self tests, and decides which mode to enter next. @@ -342,9 +342,9 @@ NAR #88757, TRA #12200 One "neat trick" of particular value when the altimeter is used with very - large airframes, is that you can power the board up while the rocket + large air-frames, is that you can power the board up while the rocket is horizontal, such that it comes up in idle mode. Then you can - raise the airframe to launch position, use a TeleDongle to open + raise the air-frame to launch position, use a TeleDongle to open a packet connection, and issue a 'reset' command which will cause the altimeter to reboot and come up in flight mode. This is much safer than standing on the top step of a @@ -364,11 +364,11 @@ NAR #88757, TRA #12200 what time it is! - TeleMetrum provides backup power to the GPS chip any time a LiPo + TeleMetrum provides backup power to the GPS chip any time a Li-Po battery is connected. This allows the receiver to "warm start" on the launch rail much faster than if every power-on were a "cold start" for the GPS receiver. In typical operations, powering up TeleMetrum - on the flight line in idle mode while performing final airframe + on the flight line in idle mode while performing final air-frame preparation will be sufficient to allow the GPS receiver to cold start and acquire lock. Then the board can be powered down during RSO review and installation on a launch rod or rail. When the board @@ -389,7 +389,7 @@ NAR #88757, TRA #12200 Just prep the rocket for flight, then power up the altimeter - in "idle" mode (placing airframe horizontal for TeleMetrum or + in "idle" mode (placing air-frame horizontal for TeleMetrum or starting the RF packet connection for TeleMini). This will cause the firmware to go into "idle" mode, in which the normal flight state machine is disabled and charges will not fire without @@ -421,7 +421,7 @@ NAR #88757, TRA #12200 it's in "idle mode", which allows us to use the RF link to configure the rocket, do things like ejection tests, and extract data after a flight without having to - crack open the airframe. However, when the board is in "flight + crack open the air-frame. However, when the board is in "flight mode", the altimeter only transmits and doesn't listen at all. That's because we want to put ultimate priority on event detection and getting telemetry out of @@ -432,7 +432,7 @@ NAR #88757, TRA #12200 We don't use a 'normal packet radio' mode because they're just too inefficient. The GFSK modulation we use is just FSK with the - baseband pulses passed through a + base-band pulses passed through a Gaussian filter before they go into the modulator to limit the transmitted bandwidth. When combined with the hardware forward error correction support in the cc1111 chip, this allows us to have a very @@ -471,7 +471,7 @@ NAR #88757, TRA #12200 To set the radio frequency, use the 'c R' command to specify the radio transceiver configuration parameter. This parameter is computed using the desired frequency, 'F', the radio calibration parameter, 'C' (showed by the 'c s' command) and - the standard calibration reference frequency, 'S', (normally 434.550Mhz): + the standard calibration reference frequency, 'S', (normally 434.550MHz): R = F / S * C @@ -504,7 +504,7 @@ NAR #88757, TRA #12200 set the MAWD to 0 seconds delay and set the TeleMetrum to fire your backup 2 or 3 seconds later to avoid any chance of both charges firing simultaneously. We've flown several - airframes this way quite happily, including Keith's + air-frames this way quite happily, including Keith's successful L3 cert.
@@ -513,7 +513,7 @@ NAR #88757, TRA #12200 By default, the altimeter will fire the main deployment charge at an elevation of 250 meters (about 820 feet) above ground. We think this - is a good elevation for most airframes, but feel free to change this + is a good elevation for most air-frames, but feel free to change this to suit. In particular, if you are flying two altimeters, you may wish to set the deployment elevation for the backup altimeter to be something lower @@ -536,7 +536,7 @@ NAR #88757, TRA #12200
Radio Frequency - The radio frequency is synthesized from a clock based on the 48 Mhz + The radio frequency is synthesized from a clock based on the 48 MHz crystal on the board. The actual frequency of this oscillator must be measured to generate a calibration constant. While our GFSK modulation bandwidth is wide enough to allow boards to communicate even when @@ -552,7 +552,7 @@ NAR #88757, TRA #12200 frequency counter, set the board to 434.550MHz, and use the 'C' command to generate a CW carrier. Wait for the transmitter temperature to stabilize and the frequency to settle down. - Then, divide 434.550 Mhz by the + Then, divide 434.550 MHz by the measured frequency and multiply by the current radio cal value show in the 'c s' command. For an unprogrammed board, the default value is 1186611. Take the resulting integer and program it using the 'c f' @@ -571,10 +571,10 @@ NAR #88757, TRA #12200
TeleMetrum Accelerometer - The TeleMerum accelerometer we use has its own 5 volt power supply and + The TeleMetrum accelerometer we use has its own 5 volt power supply and the output must be passed through a resistive voltage divider to match the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratiometric to + sensor, the output of the acceleration sensor is not ratio-metric to the ADC converter, and calibration is required. We also support the use of any of several accelerometers from a Freescale family that includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, @@ -686,7 +686,7 @@ NAR #88757, TRA #12200 the TeleMetrum with new firmware, showing a progress bar. - Confirm that the TeleMetrum board seems to have updated ok, which you + Confirm that the TeleMetrum board seems to have updated OK, which you can do by plugging in to it over USB and using a terminal program to connect to the board and issue the 'v' command to check the version, etc. @@ -748,7 +748,7 @@ NAR #88757, TRA #12200 the TeleMini with new firmware, showing a progress bar. - Confirm that the TeleMini board seems to have updated ok, which you + Confirm that the TeleMini board seems to have updated OK, which you can do by configuring it over the RF link through the TeleDongle, or letting it come up in "flight" mode and listening for telemetry. @@ -818,7 +818,7 @@ NAR #88757, TRA #12200 the TeleDongle with new firmware, showing a progress bar. - Confirm that the TeleDongle board seems to have updated ok, which you + Confirm that the TeleDongle board seems to have updated OK, which you can do by plugging in to it over USB and using a terminal program to connect to the board and issue the 'v' command to check the version, etc. Once you're happy, remove the programming cable @@ -870,7 +870,7 @@ NAR #88757, TRA #12200 The radio frequency being monitored by the TeleDongle device is displayed at the top of the window. You can configure the - frequecy by clicking on the frequency box and selecting the desired + frequency by clicking on the frequency box and selecting the desired frequency. AltosUI remembers the last frequency selected for each TeleDongle and selects that automatically the next time you use that device. @@ -882,7 +882,7 @@ NAR #88757, TRA #12200 - The configured callsign + The configured call-sign The device serial number @@ -904,7 +904,7 @@ NAR #88757, TRA #12200 The Received Signal Strength Indicator value. This lets you know how strong a signal TeleDongle is receiving. The radio inside TeleDongle operates down to about -99dBm; - weaker signals may not be receiveable. The packet link uses + weaker signals may not be receivable. The packet link uses error correction and detection techniques which prevent incorrect data from being reported. @@ -929,7 +929,7 @@ NAR #88757, TRA #12200 - Battery Voltage. This indicates whether the LiPo battery + Battery Voltage. This indicates whether the Li-Po battery powering the TeleMetrum has sufficient charge to last for the duration of the flight. A value of more than 3.7V is required for a 'GO' status. @@ -940,7 +940,7 @@ NAR #88757, TRA #12200 Apogee Igniter Voltage. This indicates whether the apogee igniter has continuity. If the igniter has a low resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is + to the Li-Po battery voltage. A value greater than 3.2V is required for a 'GO' status. @@ -949,7 +949,7 @@ NAR #88757, TRA #12200 Main Igniter Voltage. This indicates whether the main igniter has continuity. If the igniter has a low resistance, then the voltage measured here will be close - to the LiPo battery voltage. A value greater than 3.2V is + to the Li-Po battery voltage. A value greater than 3.2V is required for a 'GO' status. @@ -970,7 +970,7 @@ NAR #88757, TRA #12200 - The LaunchPad tab also shows the computed launch pad position + The Launchpad tab also shows the computed launch pad position and altitude, averaging many reported positions to improve the accuracy of the fix. @@ -985,7 +985,7 @@ NAR #88757, TRA #12200 The height, speed and acceleration are shown along with the - maxium values for each of them. This allows you to quickly + maximum values for each of them. This allows you to quickly answer the most commonly asked questions you'll hear during flight. @@ -1044,7 +1044,7 @@ NAR #88757, TRA #12200 latitude and longitude as well as a bearing and distance from the launch pad. The distance should give you a good idea of whether you'll want to walk or hitch a ride. Take the reported - latitude and longitude and enter them into your handheld GPS + latitude and longitude and enter them into your hand-held GPS unit and have that compute a track to the landing location. @@ -1070,19 +1070,19 @@ NAR #88757, TRA #12200 When the TeleMetrum gets a GPS fix, the Site Map tab will map the rocket's position to make it easier for you to locate the rocket, both while it is in the air, and when it has landed. The - rocket's state is indicated by colour: white for pad, red for + rocket's state is indicated by color: white for pad, red for boost, pink for fast, yellow for coast, light blue for drogue, dark blue for main, and black for landed. The map's scale is approximately 3m (10ft) per pixel. The map can be dragged using the left mouse button. The map will attempt - to keep the rocket roughly centred while data is being received. + to keep the rocket roughly centered while data is being received. Images are fetched automatically via the Google Maps Static API, and are cached for reuse. If map images cannot be downloaded, - the rocket's path will be traced on a dark grey background + the rocket's path will be traced on a dark gray background instead. @@ -1135,7 +1135,7 @@ NAR #88757, TRA #12200 to respond to changing launch conditions. You can also 'reboot' the altimeter. Use this to remotely enable the flight computer by turning TeleMetrum on in "idle" mode, - then once the airframe is oriented for launch, you can + then once the air-frame is oriented for launch, you can reboot the altimeter and have it restart in pad mode without having to climb the scary ladder. @@ -1143,7 +1143,7 @@ NAR #88757, TRA #12200 Fire Igniters—Test your deployment charges without snaking - wires out through holes in the airframe. Simply assembly the + wires out through holes in the air-frame. Simply assembly the rocket as if for flight with the apogee and main charges loaded, then remotely command the altimeter to fire the igniters. @@ -1210,7 +1210,7 @@ NAR #88757, TRA #12200 data will be recorded for a flight. - The filename for each flight log is computed automatically + The file name for each flight log is computed automatically from the recorded flight date, altimeter serial number and flight number information. @@ -1252,7 +1252,7 @@ NAR #88757, TRA #12200 dragging down and to the right. Once zoomed, the graph can be reset by clicking and dragging up and to the left. Holding down control and clicking and dragging allows the graph to be panned. - The right mouse button causes a popup menu to be displayed, giving + The right mouse button causes a pop-up menu to be displayed, giving you the option save or print the plot. @@ -1306,7 +1306,7 @@ NAR #88757, TRA #12200 Select this button and then select either a TeleMetrum or TeleDongle Device from the list provided. Selecting a TeleDongle - device will use Packet Comamnd Mode to configure a remote + device will use Packet Command Mode to configure a remote altimeter. Learn how to use this in the Packet Command Mode chapter. @@ -1366,8 +1366,8 @@ NAR #88757, TRA #12200 When flying redundant electronics, it's often important to ensure that multiple apogee charges don't fire at precisely - the same time as that can overpressurize the apogee deployment - bay and cause a structural failure of the airframe. The Apogee + the same time as that can over pressurize the apogee deployment + bay and cause a structural failure of the air-frame. The Apogee Delay parameter tells the flight computer to fire the apogee charge a certain number of seconds after apogee has been detected. @@ -1396,7 +1396,7 @@ NAR #88757, TRA #12200
Callsign - This sets the callsign included in each telemetry packet. Set this + This sets the call sign included in each telemetry packet. Set this as needed to conform to your local radio regulations.
@@ -1504,7 +1504,7 @@ NAR #88757, TRA #12200
Voice Settings - AltosUI provides voice annoucements during flight so that you + AltosUI provides voice announcements during flight so that you can keep your eyes on the sky and still get information about the current flight status. However, sometimes you don't want to hear them. @@ -1516,7 +1516,7 @@ NAR #88757, TRA #12200 Test Voice—Plays a short message allowing you to verify - that the audio systme is working and the volume settings + that the audio system is working and the volume settings are reasonable @@ -1542,7 +1542,7 @@ NAR #88757, TRA #12200 in each packet sent from TeleDongle and received from TeleMetrum. It is not used in telemetry mode as that transmits packets only from TeleMetrum to TeleDongle. Configure this - with the AltosUI operators callsign as needed to comply with + with the AltosUI operators call sign as needed to comply with your local radio regulations.
@@ -1621,13 +1621,13 @@ NAR #88757, TRA #12200 recovery systems deployment. Because this command can operate over the Packet Command Link, you can prepare the rocket as for flight and then test the recovery system without needing - to snake wires inside the airframe. + to snake wires inside the air-frame.
Selecting the 'Fire Igniter' button brings up the usual device selection dialog. Pick the desired TeleDongle or TeleMetrum device. This brings up another window which shows the current - continutity test status for both apogee and main charges. + continuity test status for both apogee and main charges. Next, select the desired igniter to fire. This will enable the @@ -1703,14 +1703,14 @@ NAR #88757, TRA #12200 In the rocket itself, you just need a TeleMetrum or TeleMini board and - a LiPo rechargeable battery. An 860mAh battery weighs less than a 9V + a Li-Po rechargeable battery. An 860mAh battery weighs less than a 9V alkaline battery, and will run a TeleMetrum for hours. A 110mAh battery weighs less than a triple A battery and will run a TeleMetrum for a few hours, or a TeleMini for much (much) longer. By default, we ship the altimeters with a simple wire antenna. If your - electronics bay or the airframe it resides within is made of carbon fiber, + electronics bay or the air-frame it resides within is made of carbon fiber, which is opaque to RF signals, you may choose to have an SMA connector installed so that you can run a coaxial cable to an antenna mounted elsewhere in the rocket. @@ -1720,7 +1720,7 @@ NAR #88757, TRA #12200 On the Ground To receive the data stream from the rocket, you need an antenna and short - feedline connected to one of our TeleDongle units. The + feed-line connected to one of our TeleDongle units. The TeleDongle in turn plugs directly into the USB port on a notebook computer. Because TeleDongle looks like a simple serial port, your computer does not require special device drivers... just plug it in. @@ -1734,15 +1734,15 @@ NAR #88757, TRA #12200 After the flight, you can use the RF link to extract the more detailed data logged in either TeleMetrum or TeleMini devices, or you can use a mini USB cable to plug into the TeleMetrum board directly. Pulling out the data without having to open up - the rocket is pretty cool! A USB cable is also how you charge the LiPo + the rocket is pretty cool! A USB cable is also how you charge the Li-Po battery, so you'll want one of those anyway... the same cable used by lots of digital cameras and other modern electronic stuff will work fine. - If your TeleMetrum-equiped rocket lands out of sight, you may enjoy having a hand-held GPS - receiver, so that you can put in a waypoint for the last reported rocket + If your TeleMetrum-equipped rocket lands out of sight, you may enjoy having a hand-held GPS + receiver, so that you can put in a way-point for the last reported rocket position before touch-down. This makes looking for your rocket a lot like - Geo-Cacheing... just go to the waypoint and look around starting from there. + Geo-Caching... just go to the way-point and look around starting from there. You may also enjoy having a ham radio "HT" that covers the 70cm band... you @@ -1757,7 +1757,7 @@ NAR #88757, TRA #12200 So, to recap, on the ground the hardware you'll need includes: - an antenna and feedline + an antenna and feed-line a TeleDongle @@ -1766,10 +1766,10 @@ NAR #88757, TRA #12200 a notebook computer - optionally, a handheld GPS receiver + optionally, a hand-held GPS receiver - optionally, an HT or receiver covering 435 Mhz + optionally, an HT or receiver covering 435 MHz @@ -1789,12 +1789,12 @@ NAR #88757, TRA #12200 Our software makes it easy to log the data from each flight, both the telemetry received over the RF link during the flight itself, and the more complete data log recorded in the flash memory on the altimeter - board. Once this data is on your computer, our postflight tools make it + board. Once this data is on your computer, our post-flight tools make it easy to quickly get to the numbers everyone wants, like apogee altitude, max acceleration, and max velocity. You can also generate and view a standard set of plots showing the altitude, acceleration, and velocity of the rocket during flight. And you can even export a TeleMetrum data file - useable with Google Maps and Google Earth for visualizing the flight path + usable with Google Maps and Google Earth for visualizing the flight path in two or three dimensions! @@ -1832,15 +1832,15 @@ NAR #88757, TRA #12200 Building high-power rockets that fly safely is hard enough. Mix in some sophisticated electronics and a bunch of radio energy and oftentimes you find few perfect solutions. This chapter - contains some suggestions about how to install AltusMetrum - products into the rocket airframe, including how to safely and - reliably mix a variety of electronics into the same airframe. + contains some suggestions about how to install Altus Metrum + products into the rocket air-frame, including how to safely and + reliably mix a variety of electronics into the same air-frame.
Mounting the Altimeter The first consideration is to ensure that the altimeter is - securely fastened to the airframe. For TeleMetrum, we use + securely fastened to the air-frame. For TeleMetrum, we use nylon standoffs and nylon screws; they're good to at least 50G and cannot cause any electrical issues on the board. For TeleMini, we usually cut small pieces of 1/16" balsa to fit @@ -1868,7 +1868,7 @@ NAR #88757, TRA #12200 wire. If it gets damaged or broken, it can be easily replaced. It should be kept straight and not cut; bending or cutting it will change the resonant frequency and/or - impedence, making it a less efficient radiator and thus + impedance, making it a less efficient radiator and thus reducing the range of the telemetry signal. @@ -1881,10 +1881,10 @@ NAR #88757, TRA #12200 Make sure the antenna is not inside a tube made or covered - with conducting material. Carbon fibre is the most common + with conducting material. Carbon fiber is the most common culprit here -- CF is a good conductor and will effectively shield the antenna, dramatically reducing signal strength and - range. Metalic flake paint is another effective shielding + range. Metallic flake paint is another effective shielding material which is to be avoided around any antennas. @@ -1924,7 +1924,7 @@ NAR #88757, TRA #12200 Conductive tubing or coatings. Carbon fiber and metal - tubing, or metalic paint will all dramatically attenuate the + tubing, or metallic paint will all dramatically attenuate the GPS signal. We've never heard of anyone successfully receiving GPS from inside these materials. @@ -2002,7 +2002,7 @@ NAR #88757, TRA #12200 To accurately measure atmospheric pressure, the ebay containing the altimeter must be vented outside the - airframe. The vent must be placed in a region of linear + air-frame. The vent must be placed in a region of linear airflow, smooth and not in an area of increasing or decreasing pressure. @@ -2017,7 +2017,7 @@ NAR #88757, TRA #12200 Ground Testing The most important aspect of any installation is careful - ground testing. Bringing an airframe up to the LCO table which + ground testing. Bringing an air-frame up to the LCO table which hasn't been ground tested can lead to delays or ejection charges firing on the pad, or, even worse, a recovery system failure. @@ -2027,16 +2027,16 @@ NAR #88757, TRA #12200 without any BP and turning on all of the electronics in flight mode. This will catch any mistakes in wiring and any residual RFI issues that might accidentally fire igniters at the wrong - time. Let the airframe sit for several minutes, checking for + time. Let the air-frame sit for several minutes, checking for adequate telemetry signal strength and GPS lock. Ground test the ejection charges. Prepare the rocket for flight, loading ejection charges and igniters. Completely - assemble the airframe and then use the 'Fire Igniters' + assemble the air-frame and then use the 'Fire Igniters' interface through a TeleDongle to command each charge to fire. Make sure the charge is sufficient to robustly separate - the airframe and deploy the recovery system. + the air-frame and deploy the recovery system.
@@ -2057,7 +2057,7 @@ NAR #88757, TRA #12200
- 70cm ham-band transceiver for telemetry downlink. + 70cm ham-band transceiver for telemetry down-link. @@ -2073,7 +2073,7 @@ NAR #88757, TRA #12200 - On-board, integrated GPS receiver with 5hz update rate capability. + On-board, integrated GPS receiver with 5Hz update rate capability. @@ -2088,18 +2088,18 @@ NAR #88757, TRA #12200 - Fully integrated support for LiPo rechargeable batteries. + Fully integrated support for Li-Po rechargeable batteries. - Uses LiPo to fire e-matches, can be modiied to support + Uses Li-Po to fire e-matches, can be modified to support optional separate pyro battery if needed. - 2.75 x 1 inch board designed to fit inside 29mm airframe coupler tube. + 2.75 x 1 inch board designed to fit inside 29mm air-frame coupler tube. @@ -2119,7 +2119,7 @@ NAR #88757, TRA #12200 - 70cm ham-band transceiver for telemetry downlink. + 70cm ham-band transceiver for telemetry down-link. @@ -2139,18 +2139,18 @@ NAR #88757, TRA #12200 - Support for LiPo rechargeable batteries, using an external charger. + Support for Li-Po rechargeable batteries, using an external charger. - Uses LiPo to fire e-matches, can be modiied to support + Uses Li-Po to fire e-matches, can be modified to support optional separate pyro battery if needed. - 1.5 x .5 inch board designed to fit inside 18mm airframe coupler tube. + 1.5 x .5 inch board designed to fit inside 18mm air-frame coupler tube. @@ -2185,7 +2185,7 @@ NAR #88757, TRA #12200 There are no "dit-dah-dah-dit" sound or lights like the manual mentions? That's the "pad" mode. Weak batteries might be the problem. - It is also possible that the Telemetrum is horizontal and the output + It is also possible that the TeleMetrum is horizontal and the output is instead a "dit-dit" meaning 'idle'. For TeleMini, it's possible that it received a command packet which would have left it in "pad" mode. @@ -2196,8 +2196,8 @@ NAR #88757, TRA #12200 but is easily changed using the menus in AltosUI. The files that are written end in '.telem'. The after-flight data-dumped files will end in .eeprom and represent continuous data - unlike the rf-linked .telem files that are subject to losses - along the rf data path. + unlike the RF-linked .telem files that are subject to losses + along the RF data path. See the above instructions on what and how to save the eeprom stored data after physically retrieving your altimeter. Make sure to save the on-board data after each flight; while the TeleMetrum can store @@ -2217,9 +2217,9 @@ NAR #88757, TRA #12200 - Both Telemetrum and TeleDongle can be directly communicated + Both TeleMetrum and TeleDongle can be directly communicated with using USB ports. The first thing you should try after getting - both units plugged into to your computer's usb port(s) is to run + both units plugged into to your computer's USB port(s) is to run 'ao-list' from a terminal-window to see what port-device-name each device has been assigned by the operating system. You will need this information to access the devices via their @@ -2267,7 +2267,7 @@ NAR #88757, TRA #12200 for these options and so they'll all be lost when you unplug it. - Try setting these config ('c' or second level menu) values. A good + Try setting these configuration ('c' or second level menu) values. A good place to start is by setting your call sign. By default, the boards use 'N0CALL' which is cute, but not exactly legal! Spend a few minutes getting comfortable with the units, their @@ -2284,7 +2284,7 @@ NAR #88757, TRA #12200 A fun thing to do at the launch site and something you can do while - learning how to use these units is to play with the rf-link access + learning how to use these units is to play with the RF-link access between an altimeter and the TeleDongle. Be aware that you *must* create some physical separation between the devices, otherwise the link will not function due to signal overload in the receivers in each device. @@ -2298,29 +2298,29 @@ NAR #88757, TRA #12200 of being powered up, otherwise it enters "pad" mode. - You can access an altimeter in idle mode from the Teledongle's USB - connection using the rf link + You can access an altimeter in idle mode from the TeleDongle's USB + connection using the RF link by issuing a 'p' command to the TeleDongle. Practice connecting and disconnecting ('~~' while using 'cu') from the altimeter. If you cannot escape out of the "p" command, (by using a '~~' when in CU) then it is likely that your kernel has issues. Try a newer version. - Using this rf link allows you to configure the altimeter, test + Using this RF link allows you to configure the altimeter, test fire e-matches and igniters from the flight line, check pyro-match continuity and so forth. You can leave the unit turned on while it is in 'idle mode' and then place the rocket vertically on the launch pad, walk away and then issue a reboot command. The altimeter will reboot and start sending data having changed to the "pad" mode. If the TeleDongle is not receiving - this data, you can disconnect 'cu' from the Teledongle using the + this data, you can disconnect 'cu' from the TeleDongle using the procedures mentioned above and THEN connect to the TeleDongle from inside 'ao-view'. If this doesn't work, disconnect from the TeleDongle, unplug it, and try again after plugging it back in. On TeleMetrum, the GPS will eventually find enough satellites, lock in on them, - and 'ao-view' will both auditorially announce and visually indicate + and 'ao-view' will both auditorily announce and visually indicate that GPS is ready. Now you can launch knowing that you have a good data path and good satellite lock for flight data and recovery. Remember @@ -2343,9 +2343,9 @@ NAR #88757, TRA #12200 contents using either 'ao-dumplog' (or possibly 'ao-eeprom'), over either a USB cable or over the radio link using TeleDongle. And by following the man page for 'ao-postflight' you can create - various data output reports, graphs, and even kml data to see the - flight trajectory in google-earth. (Moving the viewing angle making - sure to connect the yellow lines while in google-earth is the proper + various data output reports, graphs, and even KML data to see the + flight trajectory in Google-earth. (Moving the viewing angle making + sure to connect the yellow lines while in Google-earth is the proper technique.) @@ -2368,3 +2368,6 @@ NAR #88757, TRA #12200 + + -- cgit v1.2.3 From 6eff8d5831dde8e690586cd2a97ddf1595cd2674 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 20:59:28 -0700 Subject: doc: Document pad-mode 'on-board data logging' indicator There wasn't any documentation for this field in the 'Launch Pad' tab. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index ddb40719..0fe0dc79 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -953,6 +953,21 @@ NAR #88757, TRA #12200 required for a 'GO' status. + + + On-board Data Logging. This indicates whether there is + space remaining on-board to store flight data for the + upcoming flight. If you've downloaded data, but failed + to erase flights, there may not be any space + left. TeleMetrum can store multiple flights, depending + on the configured maximum flight log size. TeleMini + stores only a single flight, so it will need to be + downloaded and erased after each flight to capture + data. This only affects on-board flight logging; the + altimeter will still transmit telemetry and fire + ejection charges at the proper times. + + GPS Locked. For a TeleMetrum device, this indicates whether the GPS receiver is -- cgit v1.2.3 From d4e1aa92b6ce2f3e4c51029595d1d44a7f2f14a0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 22:27:35 -0600 Subject: more doc tweaking --- doc/altusmetrum.xsl | 138 ++++++++++++++++++++++++++-------------------------- 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 0fe0dc79..af892e0f 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -231,57 +231,56 @@ NAR #88757, TRA #12200 TeleMetrum is a 1 inch by 2.75 inch circuit board. It was designed to fit inside coupler for 29mm air-frame tubing, but using it in a tube that small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of - the board is about 7 inches long, and wiring for a power switch and + to succeed! The presence of an accelerometer means TeleMetrum should + be aligned along the flight axis of the airframe, and by default the 1/4 + wave UHF wire antenna should be on the nose-cone end of the board. The + antenna wire is about 7 inches long, and wiring for a power switch and the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics + fin can end of the board, meaning an ideal "simple" avionics bay for TeleMetrum should have at least 10 inches of interior length. TeleMini is a 0.5 inch by 1.5 inch circuit board. It was designed to fit inside an 18mm air-frame tube, but using it in a tube that small in diameter may require some creativity in mounting and wiring - to succeed! The default 1/4 - wave UHF wire antenna attached to the center of the nose-cone end of + to succeed! Since there is no accelerometer, TeleMini can be mounted + in any convenient orientation. The default 1/4 + wave UHF wire antenna attached to the center of one end of the board is about 7 inches long, and wiring for a power switch and the e-matches for apogee and main ejection charges depart from the - fin can end of the board. Given all this, an ideal "simple" avionics + other end of the board, meaning an ideal "simple" avionics bay for TeleMini should have at least 9 inches of interior length. - A typical TeleMetrum or TeleMini installation using the on-board devices and - default wire UHF antenna involves attaching only a suitable - Lithium Polymer battery, a single pole switch for power on/off, and - two pairs of wires connecting e-matches for the apogee and main ejection - charges. + A typical TeleMetrum or TeleMini installation involves attaching + only a suitable Lithium Polymer battery, a single pole switch for + power on/off, and two pairs of wires connecting e-matches for the + apogee and main ejection charges. By default, we use the unregulated output of the Li-Po battery directly to fire ejection charges. This works marvelously with standard low-current e-matches like the J-Tek from MJG Technologies, and with - Quest Q2G2 igniters. However, if you - want or need to use a separate pyro battery, check out the "External Pyro Battery" - section in this manual for instructions on how to wire that up. The - altimeters are designed to work with an external pyro battery of up to 15V. + Quest Q2G2 igniters. However, if you want or need to use a separate + pyro battery, check out the "External Pyro Battery" section in this + manual for instructions on how to wire that up. The altimeters are + designed to work with an external pyro battery of no more than 15 volts. Ejection charges are wired directly to the screw terminal block - at the aft end of the altimeter. This is very similar to what - most other altimeter vendors provide and so may be the most - familiar option. You'll need a very small straight blade - screwdriver to connect and disconnect the board in this case, - such as you might find in a jeweler's screwdriver set. + at the aft end of the altimeter. You'll need a very small straight + blade screwdriver for these screws, such as you might find in a + jeweler's screwdriver set. TeleMetrum also uses the screw terminal block for the power switch leads. On TeleMini, the power switch leads are soldered - directly to the board and can be connected directly to the switch. + directly to the board and can be connected directly to a switch. For most air-frames, the integrated antennas are more than - adequate However, if you are installing in a carbon-fiber - electronics bay which is opaque to RF signals, you may need to + adequate. However, if you are installing in a carbon-fiber or + metal electronics bay which is opaque to RF signals, you may need to use off-board external antennas instead. In this case, you can order an altimeter with an SMA connector for the UHF antenna connection, and, on TeleMetrum, you can unplug the integrated GPS @@ -303,7 +302,8 @@ NAR #88757, TRA #12200 TeleMetrum assumes it's on a rail or rod being prepared for launch, so the firmware chooses flight mode. However, if the rocket is more or less horizontal, the firmware instead enters - idle mode. For TeleMini, "idle" mode is selected when the + idle mode. Since TeleMini doesn't have an accelerometer we can + use to determine orientation, "idle" mode is selected when the board receives a command packet within the first five seconds of operation; if no packet is received, the board enters "flight" mode. @@ -311,8 +311,8 @@ NAR #88757, TRA #12200 At power on, you will hear three beeps or see three flashes ("S" in Morse code for start up) and then a pause while - the altimeter completes initialization and self tests, and decides which - mode to enter next. + the altimeter completes initialization and self test, and decides + which mode to enter next. In flight or "pad" mode, the altimeter engages the flight @@ -330,44 +330,43 @@ NAR #88757, TRA #12200 flights, do what makes sense. - In idle mode, you will hear an audible "di-dit" or see two short flashes ("I" for idle), and - the normal flight state machine is disengaged, thus - no ejection charges will fire. The altimeters also listen on the RF - link when in idle mode for packet mode requests sent from TeleDongle. - Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. TeleMini uses only the RF link. + If idle mode is entered, you will hear an audible "di-dit" or see + two short flashes ("I" for idle), and the flight state machine is + disengaged, thus no ejection charges will fire. The altimeters also + listen on the RF link when in idle mode for requests sent via + TeleDongle. Commands can be issued to a TeleMetrum in idle mode + over either + USB or the RF link equivalently. TeleMini only has the RF link. Idle mode is useful for configuring the altimeter, for extracting data from the on-board storage chip after flight, and for ground testing pyro charges. - One "neat trick" of particular value when the altimeter is used with very - large air-frames, is that you can power the board up while the rocket - is horizontal, such that it comes up in idle mode. Then you can - raise the air-frame to launch position, use a TeleDongle to open - a packet connection, and issue a 'reset' command which will cause - the altimeter to reboot and come up in - flight mode. This is much safer than standing on the top step of a - rickety step-ladder or hanging off the side of a launch tower with - a screw-driver trying to turn on your avionics before installing - igniters! + One "neat trick" of particular value when TeleMetrum is used with + very large air-frames, is that you can power the board up while the + rocket is horizontal, such that it comes up in idle mode. Then you can + raise the air-frame to launch position, and issue a 'reset' command + via TeleDongle over the RF link to cause the altimeter to reboot and + come up in flight mode. This is much safer than standing on the top + step of a rickety step-ladder or hanging off the side of a launch + tower with a screw-driver trying to turn on your avionics before + installing igniters!
GPS - TeleMetrum includes a complete GPS receiver. See a later section for - a brief explanation of how GPS works that will help you understand - the information in the telemetry stream. The bottom line is that - the TeleMetrum GPS receiver needs to lock onto at least four - satellites to obtain a solid 3 dimensional position fix and know - what time it is! + TeleMetrum includes a complete GPS receiver. A complete explanation + of how GPS works is beyond the scope of this manual, but the bottom + line is that the TeleMetrum GPS receiver needs to lock onto at least + four satellites to obtain a solid 3 dimensional position fix and know + what time it is. - TeleMetrum provides backup power to the GPS chip any time a Li-Po + TeleMetrum provides backup power to the GPS chip any time a battery is connected. This allows the receiver to "warm start" on - the launch rail much faster than if every power-on were a "cold start" - for the GPS receiver. In typical operations, powering up TeleMetrum + the launch rail much faster than if every power-on were a GPS + "cold start". In typical operations, powering up TeleMetrum on the flight line in idle mode while performing final air-frame preparation will be sufficient to allow the GPS receiver to cold start and acquire lock. Then the board can be powered down during @@ -383,29 +382,19 @@ NAR #88757, TRA #12200 An important aspect of preparing a rocket using electronic deployment for flight is ground testing the recovery system. Thanks to the bi-directional RF link central to the Altus Metrum system, - this can be accomplished in a TeleMetrum- or TeleMini- equipped rocket without as - much work as you may be accustomed to with other systems. It can - even be fun! + this can be accomplished in a TeleMetrum or TeleMini equipped rocket + with less work than you may be accustomed to with other systems. It + can even be fun! Just prep the rocket for flight, then power up the altimeter in "idle" mode (placing air-frame horizontal for TeleMetrum or - starting the RF packet connection for TeleMini). This will cause the - firmware to go into "idle" mode, in which the normal flight + selected the Configure Altimeter tab for TeleMini). This will cause + the firmware to go into "idle" mode, in which the normal flight state machine is disabled and charges will not fire without - manual command. Then, establish an RF packet connection from - a TeleDongle-equipped computer using the P command from a safe - distance. You can now command the altimeter to fire the apogee - or main charges to complete your testing. - - - In order to reduce the chance of accidental firing of pyrotechnic - charges, the command to fire a charge is intentionally somewhat - difficult to type, and the built-in help is slightly cryptic to - prevent accidental echoing of characters from the help text back at - the board from firing a charge. The command to fire the apogee - drogue charge is 'i DoIt drogue' and the command to fire the main - charge is 'i DoIt main'. + manual command. You can now command the altimeter to fire the apogee + or main charges from a safe distance using your computer and + TeleDongle and the Fire Igniter tab to complete ejection testing.
@@ -2333,6 +2322,15 @@ NAR #88757, TRA #12200 inside 'ao-view'. If this doesn't work, disconnect from the TeleDongle, unplug it, and try again after plugging it back in. + + In order to reduce the chance of accidental firing of pyrotechnic + charges, the command to fire a charge is intentionally somewhat + difficult to type, and the built-in help is slightly cryptic to + prevent accidental echoing of characters from the help text back at + the board from firing a charge. The command to fire the apogee + drogue charge is 'i DoIt drogue' and the command to fire the main + charge is 'i DoIt main'. + On TeleMetrum, the GPS will eventually find enough satellites, lock in on them, and 'ao-view' will both auditorily announce and visually indicate -- cgit v1.2.3 From 221157af586c6fd7368ee858a390f38bc5ed50f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 21:31:05 -0700 Subject: doc: Describe packet command mode a bit better. Include comments about TeleMini in the introduction, and then explain a bit better what the best method of reliably initiating packet command mode are (start operation, then boot telemini). Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index af892e0f..231371c7 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1106,12 +1106,13 @@ NAR #88757, TRA #12200 afar, as if it were directly connected to the computer. - Any operation which can be performed with TeleMetrum - can either be done with TeleMetrum directly connected to - the computer via the USB cable, or through the packet - link. Simply select the appropriate TeleDongle device when - the list of devices is presented and AltosUI will use packet - command mode. + Any operation which can be performed with TeleMetrum can + either be done with TeleMetrum directly connected to the + computer via the USB cable, or through the packet + link. TeleMini doesn't provide a USB connector and so it can + only be controlled through the packet link. Select the + appropriate TeleDongle device when the list of devices is + presented and AltosUI will use packet command mode. One oddity in the current interface is how AltosUI selects the @@ -1170,7 +1171,12 @@ NAR #88757, TRA #12200 TeleMini listens for a command packet for five seconds after first being turned on, if it doesn't hear anything, it enters 'pad' mode, ready for flight and will no longer listen for - command packets. + command packets. The easiest way to connect to TeleMini is to + initiate the command and select the TeleDongle device. At this + point, the TeleDongle will be attempting to communicate with + the TeleMini. Now turn TeleMini on, and it should immediately + start communicating with the TeleDongle and the desired + operation can be performed. When packet command mode is enabled, you can monitor the link -- cgit v1.2.3 From 03c8b2702a45a12c4748cd1ec801d720c816d9e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 21:39:48 -0700 Subject: doc: Move Packet Command Mode section to System Operations chapter It makes far more sense here. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 184 ++++++++++++++++++++++++++-------------------------- 1 file changed, 92 insertions(+), 92 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 231371c7..f1dff1f5 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -376,6 +376,98 @@ NAR #88757, TRA #12200 complete.
+
+ Packet Command Mode + Controlling An Altimeter Over The Radio Link + + One of the unique features of the Altus Metrum environment is + the ability to create a two way command link between TeleDongle + and an altimeter using the digital radio transceivers built into + each device. This allows you to interact with the altimeter from + afar, as if it were directly connected to the computer. + + + Any operation which can be performed with TeleMetrum can + either be done with TeleMetrum directly connected to the + computer via the USB cable, or through the packet + link. TeleMini doesn't provide a USB connector and so it is + always controlled through the packet link. Select the + appropriate TeleDongle device when the list of devices is + presented and AltosUI will use packet command mode. + + + One oddity in the current interface is how AltosUI selects the + frequency for packet mode communications. Instead of providing + an interface to specifically configure the frequency, it uses + whatever frequency was most recently selected for the target + TeleDongle device in Monitor Flight mode. If you haven't ever + used that mode with the TeleDongle in question, select the + Monitor Flight button from the top level UI, pick the + appropriate TeleDongle device. Once the flight monitoring + window is open, select the desired frequency and then close it + down again. All Packet Command Mode operations will now use + that frequency. + + + + + Save Flight Data—Recover flight data from the rocket without + opening it up. + + + + + Configure altimeter apogee delays or main deploy heights + to respond to changing launch conditions. You can also + 'reboot' the altimeter. Use this to remotely enable the + flight computer by turning TeleMetrum on in "idle" mode, + then once the air-frame is oriented for launch, you can + reboot the altimeter and have it restart in pad mode + without having to climb the scary ladder. + + + + + Fire Igniters—Test your deployment charges without snaking + wires out through holes in the air-frame. Simply assembly the + rocket as if for flight with the apogee and main charges + loaded, then remotely command the altimeter to fire the + igniters. + + + + + Packet command mode uses the same RF frequencies as telemetry + mode. Configure the desired TeleDongle frequency using the + flight monitor window frequency selector and then close that + window before performing the desired operation. + + + TeleMetrum only enables packet command mode in 'idle' mode, so + make sure you have TeleMetrum lying horizontally when you turn + it on. Otherwise, TeleMetrum will start in 'pad' mode ready for + flight and will not be listening for command packets from TeleDongle. + + + TeleMini listens for a command packet for five seconds after + first being turned on, if it doesn't hear anything, it enters + 'pad' mode, ready for flight and will no longer listen for + command packets. The easiest way to connect to TeleMini is to + initiate the command and select the TeleDongle device. At this + point, the TeleDongle will be attempting to communicate with + the TeleMini. Now turn TeleMini on, and it should immediately + start communicating with the TeleDongle and the desired + operation can be performed. + + + When packet command mode is enabled, you can monitor the link + by watching the lights on the + devices. The red LED will flash each time they + transmit a packet while the green LED will light up + on TeleDongle while it is waiting to receive a packet from + the altimeter. + +
Ground Testing @@ -1095,98 +1187,6 @@ NAR #88757, TRA #12200
-
- Packet Command Mode - Controlling An Altimeter Over The Radio Link - - One of the unique features of the Altus Metrum environment is - the ability to create a two way command link between TeleDongle - and an altimeter using the digital radio transceivers built into - each device. This allows you to interact with the altimeter from - afar, as if it were directly connected to the computer. - - - Any operation which can be performed with TeleMetrum can - either be done with TeleMetrum directly connected to the - computer via the USB cable, or through the packet - link. TeleMini doesn't provide a USB connector and so it can - only be controlled through the packet link. Select the - appropriate TeleDongle device when the list of devices is - presented and AltosUI will use packet command mode. - - - One oddity in the current interface is how AltosUI selects the - frequency for packet mode communications. Instead of providing - an interface to specifically configure the frequency, it uses - whatever frequency was most recently selected for the target - TeleDongle device in Monitor Flight mode. If you haven't ever - used that mode with the TeleDongle in question, select the - Monitor Flight button from the top level UI, pick the - appropriate TeleDongle device. Once the flight monitoring - window is open, select the desired frequency and then close it - down again. All Packet Command Mode operations will now use - that frequency. - - - - - Save Flight Data—Recover flight data from the rocket without - opening it up. - - - - - Configure altimeter apogee delays or main deploy heights - to respond to changing launch conditions. You can also - 'reboot' the altimeter. Use this to remotely enable the - flight computer by turning TeleMetrum on in "idle" mode, - then once the air-frame is oriented for launch, you can - reboot the altimeter and have it restart in pad mode - without having to climb the scary ladder. - - - - - Fire Igniters—Test your deployment charges without snaking - wires out through holes in the air-frame. Simply assembly the - rocket as if for flight with the apogee and main charges - loaded, then remotely command the altimeter to fire the - igniters. - - - - - Packet command mode uses the same RF frequencies as telemetry - mode. Configure the desired TeleDongle frequency using the - flight monitor window frequency selector and then close that - window before performing the desired operation. - - - TeleMetrum only enables packet command mode in 'idle' mode, so - make sure you have TeleMetrum lying horizontally when you turn - it on. Otherwise, TeleMetrum will start in 'pad' mode ready for - flight and will not be listening for command packets from TeleDongle. - - - TeleMini listens for a command packet for five seconds after - first being turned on, if it doesn't hear anything, it enters - 'pad' mode, ready for flight and will no longer listen for - command packets. The easiest way to connect to TeleMini is to - initiate the command and select the TeleDongle device. At this - point, the TeleDongle will be attempting to communicate with - the TeleMini. Now turn TeleMini on, and it should immediately - start communicating with the TeleDongle and the desired - operation can be performed. - - - When packet command mode is enabled, you can monitor the link - by watching the lights on the - devices. The red LED will flash each time they - transmit a packet while the green LED will light up - on TeleDongle while it is waiting to receive a packet from - the altimeter. - -
Save Flight Data -- cgit v1.2.3 From a476e76622b6fa70bf7c8883d2a2a64a382fbd78 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 22:42:33 -0600 Subject: more doc tweaks --- doc/altusmetrum.xsl | 66 +++++++++++++++++++++++++++-------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index af892e0f..6a56a4ff 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -37,11 +37,12 @@ 1.0 - 10 August 2011 + 24 August 2011 Updated for software version 1.0. Note that 1.0 represents a - telemetry format change, meaning both ends of a link (TeleMetrum/TeleMini and - TeleDongle) must be updated or communications will fail. + telemetry format change, meaning both ends of a link + (TeleMetrum/TeleMini and TeleDongle) must be updated or + communications will fail. @@ -64,17 +65,17 @@ Thanks to Bob Finch, W9YA, NAR 12965, TRA 12350 for writing "The Mere-Mortals Quick Start/Usage Guide to the Altus Metrum Starter - Kit" which has turned into the Getting Started chapter in this - book. Bob was one of our first customers for a production - TeleMetrum, and the enthusiasm that led to his contribution of - this section is immensely gratifying and highly appreciated! + Kit" which formed the basis of the original Getting Started chapter + in this book. Bob was one of our first customers for a production + TeleMetrum, and his continued enthusiasm and contributions + are immensely gratifying and highly appreciated! - And thanks to Anthony (AJ) Towns for contributing the - AltosUI graphing and site map code and documentation. Free - software means that our customers and friends can become our + And thanks to Anthony (AJ) Towns for major contributions including + the AltosUI graphing and site map code and associated documentation. + Free software means that our customers and friends can become our collaborators, and we certainly appreciate this level of - contribution. + contribution! Have fun using these products, and we hope to meet all of you @@ -110,8 +111,9 @@ NAR #88757, TRA #12200 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm air-frame. - Complementing TeleMetrum and TeleMini is TeleDongle, a USB to RF interface for - communicating with the altimeters. Combined with your choice of antenna and + Complementing TeleMetrum and TeleMini is TeleDongle, a USB to RF + interface for communicating with the altimeters. Combined with your + choice of antenna and notebook computer, TeleDongle and our associated user interface software form a complete ground station capable of logging and displaying in-flight telemetry, aiding rocket recovery, then processing and archiving flight @@ -168,12 +170,12 @@ NAR #88757, TRA #12200 ugly bugs in some earlier versions. - Next you should obtain and install the AltOS utilities. These include + Next you should obtain and install the AltOS software. These include the AltosUI ground station program, current firmware images for - TeleMetrum, TeleMini and TeleDongle, and a number of standalone utilities that - are rarely needed. Pre-built binary packages are available for Debian - Linux, Microsoft Windows, and recent MacOSX versions. Full source code - and build instructions for some other Linux variants are also available. + TeleMetrum, TeleMini and TeleDongle, and a number of standalone + utilities that are rarely needed. Pre-built binary packages are + available for Linux, Microsoft Windows, and recent MacOSX versions. + Full source code and build instructions are also available. The latest version may always be downloaded from . @@ -419,28 +421,28 @@ NAR #88757, TRA #12200 data later... - We don't use a 'normal packet radio' mode because they're just too - inefficient. The GFSK modulation we use is just FSK with the + We don't use a 'normal packet radio' mode like APRS because they're + just too inefficient. The GFSK modulation we use is FSK with the base-band pulses passed through a Gaussian filter before they go into the modulator to limit the transmitted bandwidth. When combined with the hardware forward error correction support in the cc1111 chip, this allows us to have a very - robust 38.4 kilobit data link with only 10 milliwatts of transmit power, - a whip antenna in the rocket, and a hand-held Yagi on the ground. We've - had flights to above 21k feet AGL with good reception, and calculations - suggest we should be good to well over 40k feet AGL with a 5-element yagi on - the ground. We hope to fly boards to higher altitudes soon, and would - of course appreciate customer feedback on performance in higher - altitude flights! + robust 38.4 kilobit data link with only 10 milliwatts of transmit + power, a whip antenna in the rocket, and a hand-held Yagi on the + ground. We've had flights to above 21k feet AGL with great reception, + and calculations suggest we should be good to well over 40k feet AGL + with a 5-element yagi on the ground. We hope to fly boards to higher + altitudes over time, and would of course appreciate customer feedback + on performance in higher altitude flights!
Configurable Parameters Configuring an Altus Metrum altimeter for flight is very - simple. Through the use of a Kalman filter, there is no need - to set a "mach delay" . The few configurable parameters can - all be set using a simple terminal program over the USB port + simple. Even on our baro-only TeleMini board, the use of a Kalman + filter means there is no need to set a "mach delay". The few + configurable parameters can all be set using AltosUI over USB or or RF link via TeleDongle.
@@ -448,8 +450,8 @@ NAR #88757, TRA #12200 The Altus Metrum boards support frequencies in the 70cm band. By default, the configuration interface provides a - list of 10 common frequencies -- 100kHz channels starting at - 434.550MHz. However, you can configure the firmware to use + list of 10 common frequencies in 100kHz channels starting at + 434.550MHz. However, the firmware supports use of any 50kHz multiple within the 70cm band. At any given launch, we highly recommend coordinating who will use each frequency and when to avoid interference. And of course, both -- cgit v1.2.3 From 65ca6f0d7c96432413868274b2cfdea4b76683e4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 23:03:23 -0600 Subject: more tweaks --- doc/altusmetrum.xsl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index b42a8ca7..b8aee238 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -108,7 +108,8 @@ NAR #88757, TRA #12200 The newest device is TeleMini, a dual deploy altimeter with radio telemetry and radio direction finding. This device is only - 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm air-frame. + 13mm by 38mm (½ inch by 1½ inches) and can fit easily in an 18mm + air-frame. Complementing TeleMetrum and TeleMini is TeleDongle, a USB to RF @@ -379,10 +380,9 @@ NAR #88757, TRA #12200
- Packet Command Mode - Controlling An Altimeter Over The Radio Link + Controlling An Altimeter Over The Radio Link - One of the unique features of the Altus Metrum environment is + One of the unique features of the Altus Metrum system is the ability to create a two way command link between TeleDongle and an altimeter using the digital radio transceivers built into each device. This allows you to interact with the altimeter from @@ -391,11 +391,12 @@ NAR #88757, TRA #12200 Any operation which can be performed with TeleMetrum can either be done with TeleMetrum directly connected to the - computer via the USB cable, or through the packet + computer via the USB cable, or through the radio link. TeleMini doesn't provide a USB connector and so it is - always controlled through the packet link. Select the + always controlled through the radio link. Select the appropriate TeleDongle device when the list of devices is - presented and AltosUI will use packet command mode. + presented and AltosUI will interact with an altimter over the + radio link. One oddity in the current interface is how AltosUI selects the -- cgit v1.2.3 From d92c173615a5fb0278ff6878595bed3f8d813e03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 22:12:39 -0700 Subject: doc: use 'radio link' to refer to packet command mode Make sure 'radio link' doesn't refer to telemetry and eliminate use of 'RF link' and other similar but not identical phrases. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index b8aee238..1b036220 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -319,8 +319,8 @@ NAR #88757, TRA #12200 In flight or "pad" mode, the altimeter engages the flight - state machine, goes into transmit-only mode on the RF link - sending telemetry, and waits for launch to be detected. + state machine, goes into transmit-only mode to + send telemetry, and waits for launch to be detected. Flight mode is indicated by an "di-dah-dah-dit" ("P" for pad) on the beeper or lights, followed by beeps or flashes indicating the state of the pyrotechnic igniter continuity. @@ -336,10 +336,10 @@ NAR #88757, TRA #12200 If idle mode is entered, you will hear an audible "di-dit" or see two short flashes ("I" for idle), and the flight state machine is disengaged, thus no ejection charges will fire. The altimeters also - listen on the RF link when in idle mode for requests sent via + listen for the radio link when in idle mode for requests sent via TeleDongle. Commands can be issued to a TeleMetrum in idle mode over either - USB or the RF link equivalently. TeleMini only has the RF link. + USB or the radio link equivalently. TeleMini only has the radio link. Idle mode is useful for configuring the altimeter, for extracting data from the on-board storage chip after flight, and for ground testing pyro charges. @@ -349,7 +349,7 @@ NAR #88757, TRA #12200 very large air-frames, is that you can power the board up while the rocket is horizontal, such that it comes up in idle mode. Then you can raise the air-frame to launch position, and issue a 'reset' command - via TeleDongle over the RF link to cause the altimeter to reboot and + via TeleDongle over the radio link to cause the altimeter to reboot and come up in flight mode. This is much safer than standing on the top step of a rickety step-ladder or hanging off the side of a launch tower with a screw-driver trying to turn on your avionics before @@ -476,7 +476,7 @@ NAR #88757, TRA #12200 An important aspect of preparing a rocket using electronic deployment for flight is ground testing the recovery system. Thanks - to the bi-directional RF link central to the Altus Metrum system, + to the bi-directional radio link central to the Altus Metrum system, this can be accomplished in a TeleMetrum or TeleMini equipped rocket with less work than you may be accustomed to with other systems. It can even be fun! @@ -501,16 +501,16 @@ NAR #88757, TRA #12200 link. - By design, the altimeter firmware listens for an RF connection when + By design, the altimeter firmware listens for the radio link when it's in "idle mode", which - allows us to use the RF link to configure the rocket, do things like + allows us to use the radio link to configure the rocket, do things like ejection tests, and extract data after a flight without having to crack open the air-frame. However, when the board is in "flight mode", the altimeter only transmits and doesn't listen at all. That's because we want to put ultimate priority on event detection and getting telemetry out of - the rocket and out over - the RF link in case the rocket crashes and we aren't able to extract + the rocket through + the radio in case the rocket crashes and we aren't able to extract data later... @@ -536,7 +536,7 @@ NAR #88757, TRA #12200 simple. Even on our baro-only TeleMini board, the use of a Kalman filter means there is no need to set a "mach delay". The few configurable parameters can all be set using AltosUI over USB or - or RF link via TeleDongle. + or radio link via TeleDongle.
Radio Frequencies @@ -685,7 +685,7 @@ NAR #88757, TRA #12200 In the unlikely event an accel cal that goes badly, it is possible that TeleMetrum may always come up in 'pad mode' and as such not be - listening to either the USB or radio interfaces. If that happens, + listening to either the USB or radio link. If that happens, there is a special hook in the firmware to force the board back in to 'idle mode' so you can re-do the cal. To use this hook, you just need to ground the SPI clock pin at power-on. This pin is @@ -833,7 +833,7 @@ NAR #88757, TRA #12200 Confirm that the TeleMini board seems to have updated OK, which you - can do by configuring it over the RF link through the TeleDongle, or + can do by configuring it over the radio link through the TeleDongle, or letting it come up in "flight" mode and listening for telemetry. @@ -1744,7 +1744,7 @@ NAR #88757, TRA #12200 for Linux which can perform most of the same tasks. - After the flight, you can use the RF link to extract the more detailed data + After the flight, you can use the radio link to extract the more detailed data logged in either TeleMetrum or TeleMini devices, or you can use a mini USB cable to plug into the TeleMetrum board directly. Pulling out the data without having to open up the rocket is pretty cool! A USB cable is also how you charge the Li-Po @@ -1800,7 +1800,7 @@ NAR #88757, TRA #12200 Data Analysis Our software makes it easy to log the data from each flight, both the - telemetry received over the RF link during the flight itself, and the more + telemetry received during the flight itself, and the more complete data log recorded in the flash memory on the altimeter board. Once this data is on your computer, our post-flight tools make it easy to quickly get to the numbers everyone wants, like apogee altitude, @@ -2209,7 +2209,7 @@ NAR #88757, TRA #12200 but is easily changed using the menus in AltosUI. The files that are written end in '.telem'. The after-flight data-dumped files will end in .eeprom and represent continuous data - unlike the RF-linked .telem files that are subject to losses + unlike the .telem files that are subject to losses along the RF data path. See the above instructions on what and how to save the eeprom stored data after physically retrieving your altimeter. Make sure to save @@ -2297,7 +2297,7 @@ NAR #88757, TRA #12200 A fun thing to do at the launch site and something you can do while - learning how to use these units is to play with the RF-link access + learning how to use these units is to play with the radio link access between an altimeter and the TeleDongle. Be aware that you *must* create some physical separation between the devices, otherwise the link will not function due to signal overload in the receivers in each device. @@ -2312,14 +2312,14 @@ NAR #88757, TRA #12200 You can access an altimeter in idle mode from the TeleDongle's USB - connection using the RF link + connection using the radio link by issuing a 'p' command to the TeleDongle. Practice connecting and disconnecting ('~~' while using 'cu') from the altimeter. If you cannot escape out of the "p" command, (by using a '~~' when in CU) then it is likely that your kernel has issues. Try a newer version. - Using this RF link allows you to configure the altimeter, test + Using this radio link allows you to configure the altimeter, test fire e-matches and igniters from the flight line, check pyro-match continuity and so forth. You can leave the unit turned on while it is in 'idle mode' and then place the -- cgit v1.2.3 From 425fa995aeaccc1ec9ecf011f185b4406df61541 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 23:15:15 -0600 Subject: more tweaking --- doc/altusmetrum.xsl | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index b8aee238..752012d0 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -66,7 +66,7 @@ Thanks to Bob Finch, W9YA, NAR 12965, TRA 12350 for writing "The Mere-Mortals Quick Start/Usage Guide to the Altus Metrum Starter Kit" which formed the basis of the original Getting Started chapter - in this book. Bob was one of our first customers for a production + in this manual. Bob was one of our first customers for a production TeleMetrum, and his continued enthusiasm and contributions are immensely gratifying and highly appreciated! @@ -186,7 +186,7 @@ NAR #88757, TRA #12200 All Altus Metrum products are sophisticated electronic devices. When handled gently and properly installed in an air-frame, they - will deliver impressive results. However, like all electronic + will deliver impressive results. However, as with all electronic devices, there are some precautions you must take. @@ -393,23 +393,21 @@ NAR #88757, TRA #12200 either be done with TeleMetrum directly connected to the computer via the USB cable, or through the radio link. TeleMini doesn't provide a USB connector and so it is - always controlled through the radio link. Select the - appropriate TeleDongle device when the list of devices is - presented and AltosUI will interact with an altimter over the - radio link. + always communicated with over radio. Select the appropriate + TeleDongle device when the list of devices is presented and + AltosUI will interact with an altimeter over the radio link. One oddity in the current interface is how AltosUI selects the - frequency for packet mode communications. Instead of providing + frequency for radio communications. Instead of providing an interface to specifically configure the frequency, it uses whatever frequency was most recently selected for the target TeleDongle device in Monitor Flight mode. If you haven't ever used that mode with the TeleDongle in question, select the - Monitor Flight button from the top level UI, pick the - appropriate TeleDongle device. Once the flight monitoring + Monitor Flight button from the top level UI, and pick the + appropriate TeleDongle device. Once the flight monitoring window is open, select the desired frequency and then close it - down again. All Packet Command Mode operations will now use - that frequency. + down again. All radio communications will now use that frequency. @@ -440,10 +438,11 @@ NAR #88757, TRA #12200 - Packet command mode uses the same RF frequencies as telemetry - mode. Configure the desired TeleDongle frequency using the - flight monitor window frequency selector and then close that - window before performing the desired operation. + Operation over the radio link for configuring an altimeter, ground + testing igniters, and so forth uses the same RF frequencies as flight + telemetry. To configure the desired TeleDongle frequency, select + the monitor flight tab, then use the frequency selector and + close the window before performing other desired radio operations. TeleMetrum only enables packet command mode in 'idle' mode, so -- cgit v1.2.3 From 11099fab63d32f53d0f2e04a7ab04392e39b5963 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 22:18:29 -0700 Subject: doc: Move updating device firmware section to separate chapter This isn't central to operation of the devices, so move it out to a separate chapter Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 446 ++++++++++++++++++++++++++-------------------------- 1 file changed, 223 insertions(+), 223 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 791fd8ed..08787369 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -698,229 +698,6 @@ NAR #88757, TRA #12200
-
- Updating Device Firmware - - The big conceptual thing to realize is that you have to use a - TeleDongle as a programmer to update a TeleMetrum or TeleMini, - and a TeleMetrum or other TeleDongle to program the TeleDongle - Due to limited memory resources in the cc1111, we don't support - programming directly over USB. - - - You may wish to begin by ensuring you have current firmware images. - These are distributed as part of the AltOS software bundle that - also includes the AltosUI ground station program. Newer ground - station versions typically work fine with older firmware versions, - so you don't need to update your devices just to try out new - software features. You can always download the most recent - version from . - - - We recommend updating the altimeter first, before updating TeleDongle. - -
- Updating TeleMetrum Firmware - - - Find the 'programming cable' that you got as part of the starter - kit, that has a red 8-pin MicroMaTch connector on one end and a - red 4-pin MicroMaTch connector on the other end. - - - Take the 2 screws out of the TeleDongle case to get access - to the circuit board. - - - Plug the 8-pin end of the programming cable to the - matching connector on the TeleDongle, and the 4-pin end to the - matching connector on the TeleMetrum. - Note that each MicroMaTch connector has an alignment pin that - goes through a hole in the PC board when you have the cable - oriented correctly. - - - Attach a battery to the TeleMetrum board. - - - Plug the TeleDongle into your computer's USB port, and power - up the TeleMetrum. - - - Run AltosUI, and select 'Flash Image' from the File menu. - - - Pick the TeleDongle device from the list, identifying it as the - programming device. - - - Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible - in the default directory, if not you may have to poke around - your system to find it. - - - Make sure the configuration parameters are reasonable - looking. If the serial number and/or RF configuration - values aren't right, you'll need to change them. - - - Hit the 'OK' button and the software should proceed to flash - the TeleMetrum with new firmware, showing a progress bar. - - - Confirm that the TeleMetrum board seems to have updated OK, which you - can do by plugging in to it over USB and using a terminal program - to connect to the board and issue the 'v' command to check - the version, etc. - - - If something goes wrong, give it another try. - - -
-
- Updating TeleMini Firmware - - - You'll need a special 'programming cable' to reprogram the - TeleMini. It's available on the Altus Metrum web store, or - you can make your own using an 8-pin MicroMaTch connector on - one end and a set of four pins on the other. - - - Take the 2 screws out of the TeleDongle case to get access - to the circuit board. - - - Plug the 8-pin end of the programming cable to the matching - connector on the TeleDongle, and the 4-pins into the holes - in the TeleMini circuit board. Note that the MicroMaTch - connector has an alignment pin that goes through a hole in - the PC board when you have the cable oriented correctly, and - that pin 1 on the TeleMini board is marked with a square pad - while the other pins have round pads. - - - Attach a battery to the TeleMini board. - - - Plug the TeleDongle into your computer's USB port, and power - up the TeleMini - - - Run AltosUI, and select 'Flash Image' from the File menu. - - - Pick the TeleDongle device from the list, identifying it as the - programming device. - - - Select the image you want put on the TeleMini, which should have a - name in the form telemini-v1.0-1.0.0.ihx. It should be visible - in the default directory, if not you may have to poke around - your system to find it. - - - Make sure the configuration parameters are reasonable - looking. If the serial number and/or RF configuration - values aren't right, you'll need to change them. - - - Hit the 'OK' button and the software should proceed to flash - the TeleMini with new firmware, showing a progress bar. - - - Confirm that the TeleMini board seems to have updated OK, which you - can do by configuring it over the radio link through the TeleDongle, or - letting it come up in "flight" mode and listening for telemetry. - - - If something goes wrong, give it another try. - - -
-
- Updating TeleDongle Firmware - - Updating TeleDongle's firmware is just like updating TeleMetrum or TeleMini - firmware, but you use either a TeleMetrum or another TeleDongle as the programmer. - - - - Find the 'programming cable' that you got as part of the starter - kit, that has a red 8-pin MicroMaTch connector on one end and a - red 4-pin MicroMaTch connector on the other end. - - - Find the USB cable that you got as part of the starter kit, and - plug the "mini" end in to the mating connector on TeleMetrum or TeleDongle. - - - Take the 2 screws out of the TeleDongle case to get access - to the circuit board. - - - Plug the 8-pin end of the programming cable to the - matching connector on the programmer, and the 4-pin end to the - matching connector on the TeleDongle. - Note that each MicroMaTch connector has an alignment pin that - goes through a hole in the PC board when you have the cable - oriented correctly. - - - Attach a battery to the TeleMetrum board if you're using one. - - - Plug both the programmer and the TeleDongle into your computer's USB - ports, and power up the programmer. - - - Run AltosUI, and select 'Flash Image' from the File menu. - - - Pick the programmer device from the list, identifying it as the - programming device. - - - Select the image you want put on the TeleDongle, which should have a - name in the form teledongle-v0.2-1.0.0.ihx. It should be visible - in the default directory, if not you may have to poke around - your system to find it. - - - Make sure the configuration parameters are reasonable - looking. If the serial number and/or RF configuration - values aren't right, you'll need to change them. The TeleDongle - serial number is on the "bottom" of the circuit board, and can - usually be read through the translucent blue plastic case without - needing to remove the board from the case. - - - Hit the 'OK' button and the software should proceed to flash - the TeleDongle with new firmware, showing a progress bar. - - - Confirm that the TeleDongle board seems to have updated OK, which you - can do by plugging in to it over USB and using a terminal program - to connect to the board and issue the 'v' command to check - the version, etc. Once you're happy, remove the programming cable - and put the cover back on the TeleDongle. - - - If something goes wrong, give it another try. - - - - Be careful removing the programming cable from the locking 8-pin - connector on TeleMetrum. You'll need a fingernail or perhaps a thin - screwdriver or knife blade to gently pry the locking ears out - slightly to extract the connector. We used a locking connector on - TeleMetrum to help ensure that the cabling to companion boards - used in a rocket don't ever come loose accidentally in flight. - -
-
@@ -2052,6 +1829,229 @@ NAR #88757, TRA #12200
+ + Updating Device Firmware + + The big conceptual thing to realize is that you have to use a + TeleDongle as a programmer to update a TeleMetrum or TeleMini, + and a TeleMetrum or other TeleDongle to program the TeleDongle + Due to limited memory resources in the cc1111, we don't support + programming directly over USB. + + + You may wish to begin by ensuring you have current firmware images. + These are distributed as part of the AltOS software bundle that + also includes the AltosUI ground station program. Newer ground + station versions typically work fine with older firmware versions, + so you don't need to update your devices just to try out new + software features. You can always download the most recent + version from . + + + We recommend updating the altimeter first, before updating TeleDongle. + +
+ Updating TeleMetrum Firmware + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the + matching connector on the TeleDongle, and the 4-pin end to the + matching connector on the TeleMetrum. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMetrum. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMetrum, which should have a + name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMetrum with new firmware, showing a progress bar. + + + Confirm that the TeleMetrum board seems to have updated OK, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. + + + If something goes wrong, give it another try. + + +
+
+ Updating TeleMini Firmware + + + You'll need a special 'programming cable' to reprogram the + TeleMini. It's available on the Altus Metrum web store, or + you can make your own using an 8-pin MicroMaTch connector on + one end and a set of four pins on the other. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the matching + connector on the TeleDongle, and the 4-pins into the holes + in the TeleMini circuit board. Note that the MicroMaTch + connector has an alignment pin that goes through a hole in + the PC board when you have the cable oriented correctly, and + that pin 1 on the TeleMini board is marked with a square pad + while the other pins have round pads. + + + Attach a battery to the TeleMini board. + + + Plug the TeleDongle into your computer's USB port, and power + up the TeleMini + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the TeleDongle device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleMini, which should have a + name in the form telemini-v1.0-1.0.0.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. + + + Hit the 'OK' button and the software should proceed to flash + the TeleMini with new firmware, showing a progress bar. + + + Confirm that the TeleMini board seems to have updated OK, which you + can do by configuring it over the radio link through the TeleDongle, or + letting it come up in "flight" mode and listening for telemetry. + + + If something goes wrong, give it another try. + + +
+
+ Updating TeleDongle Firmware + + Updating TeleDongle's firmware is just like updating TeleMetrum or TeleMini + firmware, but you use either a TeleMetrum or another TeleDongle as the programmer. + + + + Find the 'programming cable' that you got as part of the starter + kit, that has a red 8-pin MicroMaTch connector on one end and a + red 4-pin MicroMaTch connector on the other end. + + + Find the USB cable that you got as part of the starter kit, and + plug the "mini" end in to the mating connector on TeleMetrum or TeleDongle. + + + Take the 2 screws out of the TeleDongle case to get access + to the circuit board. + + + Plug the 8-pin end of the programming cable to the + matching connector on the programmer, and the 4-pin end to the + matching connector on the TeleDongle. + Note that each MicroMaTch connector has an alignment pin that + goes through a hole in the PC board when you have the cable + oriented correctly. + + + Attach a battery to the TeleMetrum board if you're using one. + + + Plug both the programmer and the TeleDongle into your computer's USB + ports, and power up the programmer. + + + Run AltosUI, and select 'Flash Image' from the File menu. + + + Pick the programmer device from the list, identifying it as the + programming device. + + + Select the image you want put on the TeleDongle, which should have a + name in the form teledongle-v0.2-1.0.0.ihx. It should be visible + in the default directory, if not you may have to poke around + your system to find it. + + + Make sure the configuration parameters are reasonable + looking. If the serial number and/or RF configuration + values aren't right, you'll need to change them. The TeleDongle + serial number is on the "bottom" of the circuit board, and can + usually be read through the translucent blue plastic case without + needing to remove the board from the case. + + + Hit the 'OK' button and the software should proceed to flash + the TeleDongle with new firmware, showing a progress bar. + + + Confirm that the TeleDongle board seems to have updated OK, which you + can do by plugging in to it over USB and using a terminal program + to connect to the board and issue the 'v' command to check + the version, etc. Once you're happy, remove the programming cable + and put the cover back on the TeleDongle. + + + If something goes wrong, give it another try. + + + + Be careful removing the programming cable from the locking 8-pin + connector on TeleMetrum. You'll need a fingernail or perhaps a thin + screwdriver or knife blade to gently pry the locking ears out + slightly to extract the connector. We used a locking connector on + TeleMetrum to help ensure that the cabling to companion boards + used in a rocket don't ever come loose accidentally in flight. + +
+
Hardware Specifications
-- cgit v1.2.3 From ec96f11666f9cbd98e16caeccd5d399978bde81b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 22:20:29 -0700 Subject: doc: Updating Firmware is now a separate chapter The Flash Image paragraph references it, change the reference wording. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 08787369..d5418f24 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -1370,7 +1370,7 @@ NAR #88757, TRA #12200 This reprograms any Altus Metrum device by using a TeleMetrum or TeleDongle as a programming dongle. Please read the directions for flashing devices in the Updating Device - Firmware section above + Firmware chapter below. Once you have the programmer and target devices connected, -- cgit v1.2.3 From c74ab82a7b7a6ad6f79129a9ef5954270e7e8f11 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 23:23:45 -0600 Subject: more changes --- doc/altusmetrum.xsl | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 791fd8ed..40c91bc1 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -445,10 +445,10 @@ NAR #88757, TRA #12200 close the window before performing other desired radio operations. - TeleMetrum only enables packet command mode in 'idle' mode, so + TeleMetrum only enables radio commanding in 'idle' mode, so make sure you have TeleMetrum lying horizontally when you turn it on. Otherwise, TeleMetrum will start in 'pad' mode ready for - flight and will not be listening for command packets from TeleDongle. + flight, and will not be listening for command packets from TeleDongle. TeleMini listens for a command packet for five seconds after @@ -462,12 +462,10 @@ NAR #88757, TRA #12200 operation can be performed. - When packet command mode is enabled, you can monitor the link - by watching the lights on the - devices. The red LED will flash each time they - transmit a packet while the green LED will light up - on TeleDongle while it is waiting to receive a packet from - the altimeter. + You can monitor the operation of the radio link by watching the + lights on the devices. The red LED will flash each time a packet + is tramsitted, while the green LED will light up on TeleDongle when + it is waiting to receive a packet from the altimeter.
@@ -540,13 +538,13 @@ NAR #88757, TRA #12200
Radio Frequencies - The Altus Metrum boards support frequencies in the 70cm + Altus Metrum boards support radio frequencies in the 70cm band. By default, the configuration interface provides a - list of 10 common frequencies in 100kHz channels starting at + list of 10 "standard" frequencies in 100kHz channels starting at 434.550MHz. However, the firmware supports use of any 50kHz multiple within the 70cm band. At any given - launch, we highly recommend coordinating who will use each - frequency and when to avoid interference. And of course, both + launch, we highly recommend coordinating when and by whom each + frequency will be used to avoid interference. And of course, both altimeter and TeleDongle must be configured to the same frequency to successfully communicate with each other. -- cgit v1.2.3 From 94a1b220bbfbb64b9772f3ee64a8e9d353d65e94 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 22:29:56 -0700 Subject: doc: Move the remaining command-mode descriptions to the appendix Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 95 ++++++++++++++++++++++++++--------------------------- 1 file changed, 47 insertions(+), 48 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 3a8f51d3..1b1f76a4 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -548,19 +548,6 @@ NAR #88757, TRA #12200 altimeter and TeleDongle must be configured to the same frequency to successfully communicate with each other. - - To set the radio frequency, use the 'c R' command to specify the - radio transceiver configuration parameter. This parameter is computed - using the desired frequency, 'F', the radio calibration parameter, 'C' (showed by the 'c s' command) and - the standard calibration reference frequency, 'S', (normally 434.550MHz): - - R = F / S * C - - Round the result to the nearest integer value. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board flash on - your altimeter board if you want the change to stay in place across reboots. -
Apogee Delay @@ -573,20 +560,14 @@ NAR #88757, TRA #12200 primary and backup pyrotechnic charges do not fire simultaneously. - To set the apogee delay, use the 'c d' command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - Please note that the Altus Metrum apogee detection algorithm - fires exactly at apogee. If you are also flying an - altimeter like the PerfectFlite MAWD, which only supports - selecting 0 or 1 seconds of apogee delay, you may wish to - set the MAWD to 0 seconds delay and set the TeleMetrum to - fire your backup 2 or 3 seconds later to avoid any chance of - both charges firing simultaneously. We've flown several - air-frames this way quite happily, including Keith's - successful L3 cert. + The Altus Metrum apogee detection algorithm fires exactly at + apogee. If you are also flying an altimeter like the + PerfectFlite MAWD, which only supports selecting 0 or 1 + seconds of apogee delay, you may wish to set the MAWD to 0 + seconds delay and set the TeleMetrum to fire your backup 2 + or 3 seconds later to avoid any chance of both charges + firing simultaneously. We've flown several air-frames this + way quite happily, including Keith's successful L3 cert.
@@ -601,11 +582,6 @@ NAR #88757, TRA #12200 than the primary so that both pyrotechnic charges don't fire simultaneously. - - To set the main deployment altitude, use the 'c m' command. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. -
@@ -628,22 +604,8 @@ NAR #88757, TRA #12200 temperature changes is small enough that re-calibration by customers should generally not be required. - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to 434.550MHz, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 MHz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - when the radio calibration value is changed, the radio + When the radio calibration value is changed, the radio frequency value is reset to the same value, so you'll need to recompute and reset the radio frequency value using the new radio calibration value. @@ -2287,6 +2249,43 @@ NAR #88757, TRA #12200 Verify you can connect and disconnect from the units while in your terminal program by sending the escape-disconnect mentioned above. + + To set the radio frequency, use the 'c R' command to specify the + radio transceiver configuration parameter. This parameter is computed + using the desired frequency, 'F', the radio calibration parameter, 'C' (showed by the 'c s' command) and + the standard calibration reference frequency, 'S', (normally 434.550MHz): + + R = F / S * C + + Round the result to the nearest integer value. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board flash on + your altimeter board if you want the change to stay in place across reboots. + + + To set the apogee delay, use the 'c d' command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + To set the main deployment altitude, use the 'c m' command. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to 434.550MHz, and use the 'C' + command to generate a CW carrier. Wait for the transmitter temperature + to stabilize and the frequency to settle down. + Then, divide 434.550 MHz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + Note that the 'reboot' command, which is very useful on the altimeters, will likely just cause problems with the dongle. The *correct* way @@ -2353,7 +2352,7 @@ NAR #88757, TRA #12200 strength providing an indication of the direction from receiver to rocket. - TeleMetrum also provides GPS trekking data, which can further simplify + TeleMetrum also provides GPS tracking data, which can further simplify locating the rocket once it has landed. (The last good GPS data received before touch-down will be on the data screen of 'ao-view'.) -- cgit v1.2.3 From 5c1cf7492b82e63a9db9d0238ecbcd2b59486893 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 24 Aug 2011 23:50:31 -0600 Subject: tweak tweak tweak --- doc/altusmetrum.xsl | 201 +++++++++++++++++++++++++--------------------- doc/release-notes-1.0.xsl | 2 +- 2 files changed, 110 insertions(+), 93 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 3a8f51d3..2a02421b 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -608,94 +608,6 @@ NAR #88757, TRA #12200
-
- Calibration - - There are only two calibrations required for a TeleMetrum board, and - only one for TeleDongle and TeleMini. - -
- Radio Frequency - - The radio frequency is synthesized from a clock based on the 48 MHz - crystal on the board. The actual frequency of this oscillator must be - measured to generate a calibration constant. While our GFSK modulation - bandwidth is wide enough to allow boards to communicate even when - their oscillators are not on exactly the same frequency, performance - is best when they are closely matched. - Radio frequency calibration requires a calibrated frequency counter. - Fortunately, once set, the variation in frequency due to aging and - temperature changes is small enough that re-calibration by customers - should generally not be required. - - - To calibrate the radio frequency, connect the UHF antenna port to a - frequency counter, set the board to 434.550MHz, and use the 'C' - command to generate a CW carrier. Wait for the transmitter temperature - to stabilize and the frequency to settle down. - Then, divide 434.550 MHz by the - measured frequency and multiply by the current radio cal value show - in the 'c s' command. For an unprogrammed board, the default value - is 1186611. Take the resulting integer and program it using the 'c f' - command. Testing with the 'C' command again should show a carrier - within a few tens of Hertz of the intended frequency. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - when the radio calibration value is changed, the radio - frequency value is reset to the same value, so you'll need - to recompute and reset the radio frequency value using the - new radio calibration value. - -
-
- TeleMetrum Accelerometer - - The TeleMetrum accelerometer we use has its own 5 volt power supply and - the output must be passed through a resistive voltage divider to match - the input of our 3.3 volt ADC. This means that unlike the barometric - sensor, the output of the acceleration sensor is not ratio-metric to - the ADC converter, and calibration is required. We also support the - use of any of several accelerometers from a Freescale family that - includes at least +/- 40g, 50g, 100g, and 200g parts. Using gravity, - a simple 2-point calibration yields acceptable results capturing both - the different sensitivities and ranges of the different accelerometer - parts and any variation in power supply voltages or resistor values - in the divider network. - - - To calibrate the acceleration sensor, use the 'c a 0' command. You - will be prompted to orient the board vertically with the UHF antenna - up and press a key, then to orient the board vertically with the - UHF antenna down and press a key. - As with all 'c' sub-commands, follow this with a 'c w' to write the - change to the parameter block in the on-board DataFlash chip. - - - The +1g and -1g calibration points are included in each telemetry - frame and are part of the header extracted by ao-dumplog after flight. - Note that we always store and return raw ADC samples for each - sensor... nothing is permanently "lost" or "damaged" if the - calibration is poor. - - - In the unlikely event an accel cal that goes badly, it is possible - that TeleMetrum may always come up in 'pad mode' and as such not be - listening to either the USB or radio link. If that happens, - there is a special hook in the firmware to force the board back - in to 'idle mode' so you can re-do the cal. To use this hook, you - just need to ground the SPI clock pin at power-on. This pin is - available as pin 2 on the 8-pin companion connector, and pin 1 is - ground. So either carefully install a fine-gauge wire jumper - between the two pins closest to the index hole end of the 8-pin - connector, or plug in the programming cable to the 8-pin connector - and use a small screwdriver or similar to short the two pins closest - to the index post on the 4-pin end of the programming cable, and - power up the board. It should come up in 'idle mode' (two beeps). - -
-
@@ -1325,10 +1237,10 @@ NAR #88757, TRA #12200
Callsign - This value is used in command packet mode and is transmitted - in each packet sent from TeleDongle and received from - TeleMetrum. It is not used in telemetry mode as that transmits - packets only from TeleMetrum to TeleDongle. Configure this + This value is transmitted in each command packet sent from + TeleDongle and received from an altimeter. It is not used in + telemetry mode, as the callsign configured in the altimeter board + is included in all telemetry packets. Configure this with the AltosUI operators call sign as needed to comply with your local radio regulations. @@ -2377,6 +2289,111 @@ NAR #88757, TRA #12200 once you enable the voice output! + + Calibration + + There are only two calibrations required for a TeleMetrum board, and + only one for TeleDongle and TeleMini. All boards are shipped from + the factory pre-calibrated, but the procedures are documented here + in case they are ever needed. Re-calibration is not supported by + AltosUI, you must connect to the board with a serial terminal program + and interact directly with the on-board command interpreter to effect + calibration. + +
+ Radio Frequency + + The radio frequency is synthesized from a clock based on the 48 MHz + crystal on the board. The actual frequency of this oscillator + must be measured to generate a calibration constant. While our + GFSK modulation + bandwidth is wide enough to allow boards to communicate even when + their oscillators are not on exactly the same frequency, performance + is best when they are closely matched. + Radio frequency calibration requires a calibrated frequency counter. + Fortunately, once set, the variation in frequency due to aging and + temperature changes is small enough that re-calibration by customers + should generally not be required. + + + To calibrate the radio frequency, connect the UHF antenna port to a + frequency counter, set the board to 434.550MHz, and use the 'C' + command in the on-board command interpreter to generate a CW + carrier. For TeleMetrum, this is best done over USB. For TeleMini, + note that the only way to escape the 'C' command is via power cycle + since the board will no longer be listening for commands once it + starts generating a CW carrier. + + + Wait for the transmitter temperature to stabilize and the frequency + to settle down. Then, divide 434.550 MHz by the + measured frequency and multiply by the current radio cal value show + in the 'c s' command. For an unprogrammed board, the default value + is 1186611. Take the resulting integer and program it using the 'c f' + command. Testing with the 'C' command again should show a carrier + within a few tens of Hertz of the intended frequency. + As with all 'c' sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + Note that any time you re-do the radio frequency calibration, the + radio frequency is reset to the default 434.550 Mhz. If you want + to use another frequency, you will have to set that again after + calibration is completed. + +
+
+ TeleMetrum Accelerometer + + The TeleMetrum accelerometer we use has its own 5 volt power + supply and + the output must be passed through a resistive voltage divider to match + the input of our 3.3 volt ADC. This means that unlike the barometric + sensor, the output of the acceleration sensor is not ratio-metric to + the ADC converter, and calibration is required. Explicitly + calibrating the accelerometers also allows us to load any device + from a Freescale family that includes at least +/- 40g, 50g, 100g, + and 200g parts. Using gravity, + a simple 2-point calibration yields acceptable results capturing both + the different sensitivities and ranges of the different accelerometer + parts and any variation in power supply voltages or resistor values + in the divider network. + + + To calibrate the acceleration sensor, use the 'c a 0' command. You + will be prompted to orient the board vertically with the UHF antenna + up and press a key, then to orient the board vertically with the + UHF antenna down and press a key. Note that the accuracy of this + calibration depends primarily on how perfectly vertical and still + the board is held during the cal process. As with all 'c' + sub-commands, follow this with a 'c w' to write the + change to the parameter block in the on-board DataFlash chip. + + + The +1g and -1g calibration points are included in each telemetry + frame and are part of the header stored in onboard flash to be + downloaded after flight. We always store and return raw ADC + samples for each sensor... so nothing is permanently "lost" or + "damaged" if the calibration is poor. + + + In the unlikely event an accel cal goes badly, it is possible + that TeleMetrum may always come up in 'pad mode' and as such not be + listening to either the USB or radio link. If that happens, + there is a special hook in the firmware to force the board back + in to 'idle mode' so you can re-do the cal. To use this hook, you + just need to ground the SPI clock pin at power-on. This pin is + available as pin 2 on the 8-pin companion connector, and pin 1 is + ground. So either carefully install a fine-gauge wire jumper + between the two pins closest to the index hole end of the 8-pin + connector, or plug in the programming cable to the 8-pin connector + and use a small screwdriver or similar to short the two pins closest + to the index post on the 4-pin end of the programming cable, and + power up the board. It should come up in 'idle mode' (two beeps), + allowing a re-cal. + +
+
Release Notes diff --git a/doc/release-notes-1.0.xsl b/doc/release-notes-1.0.xsl index a3fc22d9..1a06a43d 100644 --- a/doc/release-notes-1.0.xsl +++ b/doc/release-notes-1.0.xsl @@ -30,7 +30,7 @@ just isn't possible, or where radio transmissions might cause trouble with other electronics, there's a configuration option to disable all telemetry. Note that the board will still - enable packet mode in idle mode. + enable the radio link in idle mode. Arbitrary frequency selection. The radios in Altus Metrum -- cgit v1.2.3 From 458f816ad23fd6784757b13b244057d4be64260e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 23:06:01 -0700 Subject: doc: Describe max flight log, ignite mode and pad orientation These describe what these configuration parmaeters do, not how to set them. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 1b1f76a4..c778b1e1 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -536,7 +536,7 @@ NAR #88757, TRA #12200 or radio link via TeleDongle.
- Radio Frequencies + Radio Frequency Altus Metrum boards support radio frequencies in the 70cm band. By default, the configuration interface provides a @@ -583,6 +583,79 @@ NAR #88757, TRA #12200 simultaneously.
+
+ Maximum Flight Log + + TeleMetrum version 1.1 has 2MB of on-board flash storage, + enough to hold over 40 minutes of data at full data rate + (100 samples/second). TeleMetrum 1.0 has 1MB of on-board + storage. As data are stored at a reduced rate during + descent, there's plenty of space to store many flights worth + of data. + + + The on-board flash is partitioned into separate flight logs, + each of a fixed maximum size. Increase the maximum size of + each log and you reduce the number of flights that can be + stored. Decrease the size and TeleMetrum can store more + flights. + + + All of the configuration data is also stored in the flash + memory, which consumes 64kB on TeleMetrum v1.1 and 256B on + TeleMetrum v1.0. This configuration space is not available + for storing flight log data. + + + To compute the amount of space needed for a single flight, + you can multiply the expected ascent time (in seconds) by + 800, multiply the expected descent time (in seconds) by 80 + and add the two together. That will slightly under-estimate + the storage (in bytes) needed for the flight. For instance, + a flight spending 20 seconds in ascent and 150 seconds in + descent will take about (20 * 800) + (150 * 80) = 28000 + bytes of storage. You could store dozens of these flights in + the on-board flash. + + + The default size, 192kB, allows for 10 flights of storage on + TeleMetrum v1.1 and 5 flights on TeleMetrum v1.0. This + ensures that you won't need to erase the memory before + flying each time while still allowing more than sufficient + storage for each flight. + +
+
+ Ignite Mode + + Instead of firing one charge at apogee and another charge at + a fixed height above the ground, you can configure the + altimeter to fire both at apogee or both during + descent. This was added to support an airframe that has two + TeleMetrum computers, one in the fin can and one in the + nose. + + + Providing the ability to use both igniters for apogee or + main allows some level of redundancy without needing two + flight computers. In Redundant Apogee or Redundant Main + mode, the two charges will be fired two seconds apart. + +
+
+ Pad Orientation + + TeleMetrum measures acceleration along the axis of the + board. Which way the board is oriented affects the sign of + the acceleration value. Instead of trying to guess which way + the board is mounted in the air frame, TeleMetrum must be + explicitly configured for either Antenna Up or Antenna + Down. The default, Antenna Up, expects the end of the + TeleMetrum board connected to the 70cm antenna to be nearest + the nose of the rocket, with the end containing the screw + terminals nearest the tail. + +
Calibration -- cgit v1.2.3 From 5158493c8df527e7527057c719c75248609eb3dc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Aug 2011 23:21:02 -0700 Subject: doc: Remove duplicate documentation about max flight log This was described in detail in both the System Operation and AltosUI chapters. Remove the duplicate from the AltosUI chapter. Signed-off-by: Keith Packard --- doc/altusmetrum.xsl | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index aeb43acb..329739e0 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -589,9 +589,9 @@ NAR #88757, TRA #12200 TeleMetrum version 1.1 has 2MB of on-board flash storage, enough to hold over 40 minutes of data at full data rate (100 samples/second). TeleMetrum 1.0 has 1MB of on-board - storage. As data are stored at a reduced rate during - descent, there's plenty of space to store many flights worth - of data. + storage. As data are stored at a reduced rate during descent + (10 samples/second), there's plenty of space to store many + flights worth of data. The on-board flash is partitioned into separate flight logs, @@ -624,6 +624,17 @@ NAR #88757, TRA #12200 flying each time while still allowing more than sufficient storage for each flight. + + As TeleMini does not contain an accelerometer, it stores + data at 10 samples per second during ascent and one sample + per second during descent. Each sample is a two byte reading + from the barometer. These are stored in 5kB of + on-chip flash memory which can hold 256 seconds at the + ascent rate or 2560 seconds at the descent rate. Because of + the limited storage, TeleMini cannot hold data for more than + one flight, and so must be erased after each flight or it + will not capture data for subsequent flights. +
Ignite Mode @@ -1156,31 +1167,6 @@ NAR #88757, TRA #12200 size. A smaller value will allow more flights to be stored, a larger value will record data from longer flights. - - During ascent, TeleMetrum records barometer and - accelerometer values 100 times per second, other analog - information (voltages and temperature) 6 times per second - and GPS data once per second. During descent, the non-GPS - data is recorded 1/10th as often. Each barometer + - accelerometer record takes 8 bytes. - - - The default, 192kB, will store over 200 seconds of data at - the ascent rate, or over 2000 seconds of data at the descent - rate. That's plenty for most flights. This leaves enough - storage for five flights in a 1MB system, or 10 flights in a - 2MB system. - - - The configuration block takes the last available block of - memory, on v1.0 boards that's just 256 bytes. However, the - flash part on the v1.1 boards uses 64kB for each block. - - - TeleMini has 5kB of on-board storage, which is plenty for a - single flight. Make sure you download and delete the data - before a subsequent flight or it will not log any data. -
Ignite Mode -- cgit v1.2.3 From 1bd781da934c738e0c9294197c7eb622b0710a9a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 00:32:47 -0600 Subject: more tweaks --- doc/altusmetrum.xsl | 105 +++++++++++++++++++++++++++++----------------------- 1 file changed, 58 insertions(+), 47 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index c8ffedac..66c2b339 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -651,7 +651,7 @@ NAR #88757, TRA #12200 you know how strong a signal TeleDongle is receiving. The radio inside TeleDongle operates down to about -99dBm; weaker signals may not be receivable. The packet link uses - error correction and detection techniques which prevent + error detection and correction techniques which prevent incorrect data from being reported. @@ -662,8 +662,8 @@ NAR #88757, TRA #12200 They're arranged in 'flight order' so that as the flight progresses, the selected tab automatically switches to display data relevant to the current state of the flight. You can select - other tabs at any time. The final 'table' tab contains all of - the telemetry data in one place. + other tabs at any time. The final 'table' tab displays all of + the raw telemetry values in one place in a spreadsheet-like format.
Launch Pad @@ -774,7 +774,9 @@ NAR #88757, TRA #12200 To monitor whether the apogee charge operated correctly, the current descent rate is reported along with the current - height. Good descent rates generally range from 15-30m/s. + height. Good descent rates vary based on the choice of recovery + components, but generally range from 15-30m/s on drogue and should + be below 10m/s when under the main parachute in a dual-deploy flight. For TeleMetrum altimeters, you can locate the rocket in the sky @@ -789,14 +791,17 @@ NAR #88757, TRA #12200 Finally, the igniter voltages are reported in this tab as well, both to monitor the main charge as well as to see what - the status of the apogee charge is. + the status of the apogee charge is. Note that some commercial + e-matches are designed to retain continuity even after being + fired, and will continue to show as green or return from red to + green after firing.
Landed Once the rocket is on the ground, attention switches to - recovery. While the radio signal is generally lost once the + recovery. While the radio signal is often lost once the rocket is on the ground, the last reported GPS position is generally within a short distance of the actual landing location. @@ -804,20 +809,24 @@ NAR #88757, TRA #12200 The last reported GPS position is reported both by latitude and longitude as well as a bearing and distance from the launch pad. The distance should give you a good idea of - whether you'll want to walk or hitch a ride. Take the reported + whether to walk or hitch a ride. Take the reported latitude and longitude and enter them into your hand-held GPS unit and have that compute a track to the landing location. Both TeleMini and TeleMetrum will continue to transmit RDF tones after landing, allowing you to locate the rocket by - following the radio signal. You may need to get away from - the clutter of the flight line, or even get up on a hill (or - your neighbor's RV) to receive the RDF signal. + following the radio signal if necessary. You may need to get + away from the clutter of the flight line, or even get up on + a hill (or your neighbor's RV roof) to receive the RDF signal. The maximum height, speed and acceleration reported during the flight are displayed for your admiring observers. + The accuracy of these immediate values depends on the quality + of your radio link and how many packets were received. + Recovering the on-board data after flight will likely yield + more precise results. To get more detailed information about the flight, you can @@ -828,7 +837,7 @@ NAR #88757, TRA #12200
Site Map - When the TeleMetrum gets a GPS fix, the Site Map tab will map + When the TeleMetrum has a GPS fix, the Site Map tab will map the rocket's position to make it easier for you to locate the rocket, both while it is in the air, and when it has landed. The rocket's state is indicated by color: white for pad, red for @@ -842,7 +851,7 @@ NAR #88757, TRA #12200 Images are fetched automatically via the Google Maps Static API, - and are cached for reuse. If map images cannot be downloaded, + and cached on disk for reuse. If map images cannot be downloaded, the rocket's path will be traced on a dark gray background instead. @@ -856,7 +865,7 @@ NAR #88757, TRA #12200 Save Flight Data The altimeter records flight data to its internal flash memory. - The TeleMetrum data is recorded at a much higher rate than the telemetry + TeleMetrum data is recorded at a much higher rate than the telemetry system can handle, and is not subject to radio drop-outs. As such, it provides a more complete and precise record of the flight. The 'Save Flight Data' button allows you to read the @@ -869,9 +878,9 @@ NAR #88757, TRA #12200 connected TeleMetrum and TeleDongle devices. If you select a TeleMetrum device, the flight data will be downloaded from that device directly. If you select a TeleDongle device, flight data - will be downloaded from a TeleMetrum or TeleMini device connected via the - packet command link to the specified TeleDongle. See the chapter - on Packet Command Mode for more information about this. + will be downloaded from an altimeter over radio link via the + specified TeleDongle. See the chapter on Controlling An Altimeter + Over The Radio Link for more information. After the device has been selected, a dialog showing the @@ -879,10 +888,10 @@ NAR #88757, TRA #12200 select which flights to download and which to delete. With version 0.9 or newer firmware, you must erase flights in order for the space they consume to be reused by another - flight. This prevents you from accidentally losing flight data + flight. This prevents accidentally losing flight data if you neglect to download data before flying again. Note that if there is no more space available in the device, then no - data will be recorded for a flight. + data will be recorded during the next flight. The file name for each flight log is computed automatically @@ -915,8 +924,8 @@ NAR #88757, TRA #12200 Once a flight record is selected, a window with two tabs is opened. The first tab contains a graph with acceleration - (blue), velocity (green) and altitude (red) of the flight are - plotted and displayed, measured in metric units. The + (blue), velocity (green) and altitude (red) of the flight, + measured in metric units. The apogee(yellow) and main(magenta) igniter voltages are also displayed; high voltages indicate continuity, low voltages indicate open circuits. The second tab contains some basic @@ -933,14 +942,15 @@ NAR #88757, TRA #12200 Note that telemetry files will generally produce poor graphs due to the lower sampling rate and missed telemetry packets. - Use saved flight data for graphing where possible. + Use saved flight data in .eeprom files for graphing where possible.
Export Data This tool takes the raw data files and makes them available for - external analysis. When you select this button, you are prompted to select a flight + external analysis. When you select this button, you are prompted to + select a flight data file (either .eeprom or .telem will do, remember that .eeprom files contain higher resolution and more continuous data). Next, a second dialog appears which is used to select @@ -956,7 +966,7 @@ NAR #88757, TRA #12200 configuration information from the altimeter, then there is a single header line which labels all of the fields. All of these lines start with a '#' character which - most tools can be configured to skip over. + many tools can be configured to skip over. The remaining lines of the file contain the data, with each @@ -969,10 +979,9 @@ NAR #88757, TRA #12200
Keyhole Markup Language (for Google Earth) - This is the format used by - Googleearth to provide an overlay within that - application. With this, you can use Googleearth to see the - whole flight path in 3D. + This is the format used by Google Earth to provide an overlay + within that application. With this, you can use Google Earth to + see the whole flight path in 3D.
@@ -981,9 +990,7 @@ NAR #88757, TRA #12200 Select this button and then select either a TeleMetrum or TeleDongle Device from the list provided. Selecting a TeleDongle - device will use Packet Command Mode to configure a remote - altimeter. Learn how to use this in the Packet Command - Mode chapter. + device will use the radio link to configure a remote altimeter. The first few lines of the dialog provide information about the @@ -1012,7 +1019,8 @@ NAR #88757, TRA #12200 Reboot. This reboots the device. Use this to switch from idle to pad mode by rebooting once the rocket is - oriented for flight. + oriented for flight, or to confirm changes you think you saved + are really saved. @@ -1041,7 +1049,7 @@ NAR #88757, TRA #12200 When flying redundant electronics, it's often important to ensure that multiple apogee charges don't fire at precisely - the same time as that can over pressurize the apogee deployment + the same time, as that can over pressurize the apogee deployment bay and cause a structural failure of the air-frame. The Apogee Delay parameter tells the flight computer to fire the apogee charge a certain number of seconds after apogee has been @@ -1063,9 +1071,11 @@ NAR #88757, TRA #12200 The radios in every Altus Metrum device are calibrated at the factory to ensure that they transmit and receive on the - specified frequency. You can adjust that - calibration by changing this value. To change the TeleDongle's - calibration, you must reprogram the unit completely. + specified frequency. If you need to you can adjust the calibration + by changing this value. Do not do this without understanding what + the value means, read the appendix on calibration and/or the source + code for more information. To change a TeleDongle's calibration, + you must reprogram the unit completely.
@@ -1095,8 +1105,8 @@ NAR #88757, TRA #12200 The default, 192kB, will store over 200 seconds of data at the ascent rate, or over 2000 seconds of data at the descent rate. That's plenty for most flights. This leaves enough - storage for five flights in a 1MB system, or 10 flights in a - 2MB system. + storage for five flights in 1MB systems, or 10 flights in 2MB + systems. The configuration block takes the last available block of @@ -1106,7 +1116,7 @@ NAR #88757, TRA #12200 TeleMini has 5kB of on-board storage, which is plenty for a single flight. Make sure you download and delete the data - before a subsequent flight or it will not log any data. + before subsequent flights, or TeleMini will not log any data.
@@ -1483,8 +1493,7 @@ NAR #88757, TRA #12200 In the future, we intend to offer "companion boards" for the rocket that will plug in to TeleMetrum to collect additional data, provide more pyro channels, - and so forth. A reference design for a companion board will be documented - soon, and will be compatible with open source Arduino programming tools. + and so forth. We are also working on the design of a hand-held ground terminal that will @@ -1619,7 +1628,7 @@ NAR #88757, TRA #12200 Any altimeter will generate RFI; the digital circuits use high-frequency clocks that spray radio interference across a - wide band. Altusmetrum altimeters generate intentional radio + wide band. Altus Metrum altimeters generate intentional radio signals as well, increasing the amount of RF energy around the board. @@ -1632,7 +1641,7 @@ NAR #88757, TRA #12200 Voltages are induced when radio frequency energy is transmitted from one circuit to another. Here are things that - increase the induced voltage and current: + influence the induced voltage and current: @@ -1678,8 +1687,8 @@ NAR #88757, TRA #12200 To accurately measure atmospheric pressure, the ebay containing the altimeter must be vented outside the air-frame. The vent must be placed in a region of linear - airflow, smooth and not in an area of increasing or decreasing - pressure. + airflow, have smooth edges, and away from areas of increasing or + decreasing pressure. The barometric sensor in the altimeter is quite sensitive to @@ -1703,7 +1712,9 @@ NAR #88757, TRA #12200 mode. This will catch any mistakes in wiring and any residual RFI issues that might accidentally fire igniters at the wrong time. Let the air-frame sit for several minutes, checking for - adequate telemetry signal strength and GPS lock. + adequate telemetry signal strength and GPS lock. If any igniters + fire unexpectedly, find and resolve the issue before loading any + BP charges! Ground test the ejection charges. Prepare the rocket for @@ -1718,11 +1729,11 @@ NAR #88757, TRA #12200 Updating Device Firmware - The big conceptual thing to realize is that you have to use a + The big concept to understand is that you have to use a TeleDongle as a programmer to update a TeleMetrum or TeleMini, and a TeleMetrum or other TeleDongle to program the TeleDongle Due to limited memory resources in the cc1111, we don't support - programming directly over USB. + programming directly over USB. You may wish to begin by ensuring you have current firmware images. -- cgit v1.2.3 From 3fc92a529dae410a41038cce38c6a44f5e58bd1f Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:11:47 -0600 Subject: prepare to release --- configure.ac | 2 +- debian/copyright | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9f386680..f9002508 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.7.1) +AC_INIT([altos], 1.0) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/debian/copyright b/debian/copyright index 50cbcd80..55841bca 100644 --- a/debian/copyright +++ b/debian/copyright @@ -10,8 +10,23 @@ Upstream Authors: Copyright: - Copyright © 2009-2011 Keith Packard + The overall AltOS package is + Copyright © 2009-2011 Keith Packard + + Significant contributions include + + Copyright © 2009-2011 Bdale Garbee + Copyright © 2009-2011 Anthony Towns + + Some files incorporated from other projects carry other copyrights: + + Copyright © 2001, 2002, 2003 Jan Kiszka (Jan.Kiszka@web.de) + Copyright © 1991-1995 Paul J Turner, Portland, OR + Copyright © 1996-2000 Grace Development Team + Copyright © 1984, 1987, 1989, 1995 Stephen L. Moshier + Copyright © 2003 Maarten Brock, sourceforge.brock@dse.nl + License: This program is free software; you can redistribute it and/or modify -- cgit v1.2.3 From 2992184f7a032c95e22023080fbc26443ed786f5 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:30:36 -0600 Subject: don't deliver sources.list fragment in official Debian packages --- debian/altos.install | 1 - 1 file changed, 1 deletion(-) diff --git a/debian/altos.install b/debian/altos.install index c23e1628..884fdaa7 100644 --- a/debian/altos.install +++ b/debian/altos.install @@ -1,5 +1,4 @@ debian/altos.desktop usr/share/applications -debian/altos.list etc/apt/sources.list.d debian/altusmetrum.xpm usr/share/pixmaps src/*.ihx usr/share/altos src/*.map usr/share/altos -- cgit v1.2.3 From a7ee1049519bf46b3864666999249876009fc3bf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:35:06 -0600 Subject: changes in preparation for upload to Debian --- debian/control | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/debian/control b/debian/control index beac70dc..15176565 100644 --- a/debian/control +++ b/debian/control @@ -1,11 +1,13 @@ Source: altos -Section: otherosfs -Priority: extra +Section: electronics +Priority: optional Maintainer: Bdale Garbee Uploaders: Keith Packard Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, openjdk-6-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config Standards-Version: 3.9.2 Homepage: http://altusmetrum.org/AltOS +Vcs-Git: git://git.gag.com/fw/altos +Vcs-Browser: http://git.gag.com/?p=fw/altos Package: altos Architecture: any @@ -14,7 +16,7 @@ Suggests: slim | gdm Replaces: altusmetrum-themes, slim-altusmetrum Conflicts: altusmetrum-themes, slim-altusmetrum Description: Altus Metrum firmware and utilities - Firmware and utilities needed to support the TeleMetrum dual-deploy - recording altimeter for high power model rocketry. + Firmware and utilities needed to support high power model rocketry products + from Altus Metrum, including TeleMetrum, TeleMini, and TeleDongle. . See http://altusmetrum.org/ for more information. -- cgit v1.2.3 From f0891fc2e4fa4fd6dd5c2bfc74e4514de986a295 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:35:18 -0600 Subject: ao-view is no longer included in the altos package, so have the old-style Debian menu entry point to altosui instead --- debian/menu | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/menu b/debian/menu index c175534d..b479ee5e 100644 --- a/debian/menu +++ b/debian/menu @@ -1,6 +1,6 @@ ?package(altos): \ needs="X11" \ section="Applications/Viewers" \ - title="ao-view" \ - command="/usr/bin/ao-view" \ + title="AltOS UI" \ + command="/usr/bin/altosui" \ icon="/usr/share/pixmaps/altusmetrum.xpm" -- cgit v1.2.3 From 0b1d5b678f0e36fbe09d4d3babffb77f857f098d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:37:31 -0600 Subject: rewind packaging changelog to last tagged version --- debian/changelog | 52 ---------------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/debian/changelog b/debian/changelog index e870885c..e786b10f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,55 +1,3 @@ -altos (0.9.7.1) unstable; urgency=low - - [ Keith Packard ] - * altos: Lost change that reported flight 0 when log memory was full - * altosui: Ancient log files used 'apogee' for 'coast' state - * altosui: Add 'On-board Data Logging' indicator to pad tab - * altosui: remove debug printf in pad pane - * altosui: Disable 'max flight log' config when there are stored flights - * altos: Merge common config code in ao_config.c - * Bump version to 0.9.7 - * altos/altosui: Add ability to disable telemetry/rdf completely - * altosui: Clean up command line processing. Add --graph - * altos-fat/windows: Check and install Java 1.6 as needed - * altosui/windows: Fix a bunch of windows compiler warnings. - * altosui: Attempt to make both 32- and 64-bit windows DLLs - * doc: Add note about telemetry disable mode to 1.0 release notes - * doc: Add Installation Recommendations chapter - * altosui: Add a few simple unit conversions - * altosui: Capture date/time/serial/flight in AltosFlightStats - * altosui: Add date/time/serial/flight to flight stats tab - * altosui: Show filename in AltosGraph window - * altosui: Add --summary option to dump flight stats to stdout - * altosui: Make monitor-idle display correct 'On-board data logging' status - * altosui: Can't configure flight log max on TeleMini - * altosui: fix 'magic' string to signal end of config data - * altosui: Only 'show' config dialog once - * altosui: Reset all config data on 'reset' command - * altosui: Update mac os X library - * libaltos: fix Mac OS X function signatures - * altosui: add tool-tips to the button box. - - [ Bdale Garbee ] - * turn off auto-tagging during Debian build - * update changelogs for Debian build - * rewind changelog to 0.9.6.0 for rebuild - * update changelogs for Debian build - - [ Keith Packard ] - * altosui: Use system look&feel - * Remove stale tools (ao-dumplog, ao-postflight, ao-view) - * altosui: Add tool-tips to config dialogs - * altosui: Try to get dialogs to look a little better - - [ Bdale Garbee ] - * another test round - * roll changelog back in prep for another test build - * update changelogs for Debian build - * add pkg-config to the build deps - * prepare for another rebuild - - -- Bdale Garbee Wed, 24 Aug 2011 01:52:35 -0600 - altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 3ec03792adebbeadc9c0d4985c6f51877e8ab969 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:48:11 -0600 Subject: update desktop file for consistency with package section --- debian/altos.desktop | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/debian/altos.desktop b/debian/altos.desktop index 4345cf09..a74ecafa 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -1,10 +1,10 @@ [Desktop Entry] Type=Application Name=AltOS UI -GenericName=TeleMetrum Telemetry Viewer -Comment=View and log downlink data from TeleMetrum +GenericName=Altus Metrum Ground Station +Comment=View and log downlink data from Altus Metrum products Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/altosui %f Terminal=false MimeType=text/plain; -Categories=Education;Science; +Categories=Electronics;Science; -- cgit v1.2.3 From 0579bd5de9e7686d227a16951dd520439ca5472b Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 01:55:32 -0600 Subject: we need a main category in the desktop file --- debian/altos.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/altos.desktop b/debian/altos.desktop index a74ecafa..88b99f97 100644 --- a/debian/altos.desktop +++ b/debian/altos.desktop @@ -7,4 +7,4 @@ Icon=/usr/share/pixmaps/altusmetrum.xpm Exec=/usr/bin/altosui %f Terminal=false MimeType=text/plain; -Categories=Electronics;Science; +Categories=Education;Electronics;Science; -- cgit v1.2.3 From d65e4f6b0a8ba8f67c8a916f2e8be0ec5c75f47d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 02:05:49 -0600 Subject: really, I mean it, no longer deliver the sources.list fragment --- debian/altos.list | 2 -- debian/dirs | 1 - 2 files changed, 3 deletions(-) delete mode 100644 debian/altos.list diff --git a/debian/altos.list b/debian/altos.list deleted file mode 100644 index 201a4a2f..00000000 --- a/debian/altos.list +++ /dev/null @@ -1,2 +0,0 @@ -deb http://altusmetrum.org/apt sid main -deb-src http://altusmetrum.org/apt sid main diff --git a/debian/dirs b/debian/dirs index 1cffaa67..c7f7918e 100644 --- a/debian/dirs +++ b/debian/dirs @@ -1,4 +1,3 @@ -etc/apt/sources.list.d usr/bin usr/lib/altos usr/share/altos/themes -- cgit v1.2.3 From 41998645c04a2ee856dec272b40c2dc5913291d3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 02:16:17 -0600 Subject: add a postinst to remove sources.list.d fragment delivered by old private versions of this package, no longer needed once we have official packages --- debian/altos.postinst | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 debian/altos.postinst diff --git a/debian/altos.postinst b/debian/altos.postinst new file mode 100644 index 00000000..2ef9a686 --- /dev/null +++ b/debian/altos.postinst @@ -0,0 +1,9 @@ +#!/bin/sh +set -e + +test "$1" = 'configure' || exit 0 + +rm -f /etc/apt/sources.list.d/altos.list + +#DEBHELPER# + -- cgit v1.2.3 From f9d87de0e2681c2ec5753f4fffef0e61a3a9e144 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 02:22:53 -0600 Subject: update changelogs for Debian build --- ChangeLog | 300 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 120 ++++++++++++++++++++++ 2 files changed, 420 insertions(+) diff --git a/ChangeLog b/ChangeLog index 79be2032..87d7951f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,303 @@ +commit 41998645c04a2ee856dec272b40c2dc5913291d3 +Author: Bdale Garbee +Date: Thu Aug 25 02:16:17 2011 -0600 + + add a postinst to remove sources.list.d fragment delivered by old private + versions of this package, no longer needed once we have official packages + +commit d65e4f6b0a8ba8f67c8a916f2e8be0ec5c75f47d +Author: Bdale Garbee +Date: Thu Aug 25 02:05:49 2011 -0600 + + really, I mean it, no longer deliver the sources.list fragment + +commit 0579bd5de9e7686d227a16951dd520439ca5472b +Author: Bdale Garbee +Date: Thu Aug 25 01:55:32 2011 -0600 + + we need a main category in the desktop file + +commit 3ec03792adebbeadc9c0d4985c6f51877e8ab969 +Author: Bdale Garbee +Date: Thu Aug 25 01:48:11 2011 -0600 + + update desktop file for consistency with package section + +commit 0b1d5b678f0e36fbe09d4d3babffb77f857f098d +Author: Bdale Garbee +Date: Thu Aug 25 01:37:31 2011 -0600 + + rewind packaging changelog to last tagged version + +commit f0891fc2e4fa4fd6dd5c2bfc74e4514de986a295 +Author: Bdale Garbee +Date: Thu Aug 25 01:35:18 2011 -0600 + + ao-view is no longer included in the altos package, so have the old-style + Debian menu entry point to altosui instead + +commit a7ee1049519bf46b3864666999249876009fc3bf +Author: Bdale Garbee +Date: Thu Aug 25 01:35:06 2011 -0600 + + changes in preparation for upload to Debian + +commit 2992184f7a032c95e22023080fbc26443ed786f5 +Author: Bdale Garbee +Date: Thu Aug 25 01:30:36 2011 -0600 + + don't deliver sources.list fragment in official Debian packages + +commit 3fc92a529dae410a41038cce38c6a44f5e58bd1f +Author: Bdale Garbee +Date: Thu Aug 25 01:11:47 2011 -0600 + + prepare to release + +commit 73abe19acf709c00f5352ec12e8cd6edae1d1963 +Merge: 1bd781d 5158493 +Author: Bdale Garbee +Date: Thu Aug 25 00:34:49 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + + Conflicts: + doc/altusmetrum.xsl + +commit 1bd781da934c738e0c9294197c7eb622b0710a9a +Author: Bdale Garbee +Date: Thu Aug 25 00:32:47 2011 -0600 + + more tweaks + +commit 5158493c8df527e7527057c719c75248609eb3dc +Author: Keith Packard +Date: Wed Aug 24 23:21:02 2011 -0700 + + doc: Remove duplicate documentation about max flight log + + This was described in detail in both the System Operation and AltosUI + chapters. Remove the duplicate from the AltosUI chapter. + + Signed-off-by: Keith Packard + +commit e268798dc260311f5f0167909481b41c9d27fc1c +Merge: 458f816 242344d +Author: Keith Packard +Date: Wed Aug 24 23:06:44 2011 -0700 + + Merge remote-tracking branch 'origin/master' + +commit 458f816ad23fd6784757b13b244057d4be64260e +Author: Keith Packard +Date: Wed Aug 24 23:06:01 2011 -0700 + + doc: Describe max flight log, ignite mode and pad orientation + + These describe what these configuration parmaeters do, not how to set them. + + Signed-off-by: Keith Packard + +commit 242344d3e32e7c7cd9270d708555923fa888e4d8 +Merge: 5c1cf74 94a1b22 +Author: Bdale Garbee +Date: Wed Aug 24 23:51:38 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + + Conflicts: + doc/altusmetrum.xsl + +commit 5c1cf7492b82e63a9db9d0238ecbcd2b59486893 +Author: Bdale Garbee +Date: Wed Aug 24 23:50:31 2011 -0600 + + tweak tweak tweak + +commit 94a1b220bbfbb64b9772f3ee64a8e9d353d65e94 +Author: Keith Packard +Date: Wed Aug 24 22:29:56 2011 -0700 + + doc: Move the remaining command-mode descriptions to the appendix + + Signed-off-by: Keith Packard + +commit edfb553bb4fa5b0c7c6c658505b2a99d05fb13bf +Merge: c74ab82 ec96f11 +Author: Bdale Garbee +Date: Wed Aug 24 23:23:56 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit c74ab82a7b7a6ad6f79129a9ef5954270e7e8f11 +Author: Bdale Garbee +Date: Wed Aug 24 23:23:45 2011 -0600 + + more changes + +commit ec96f11666f9cbd98e16caeccd5d399978bde81b +Author: Keith Packard +Date: Wed Aug 24 22:20:29 2011 -0700 + + doc: Updating Firmware is now a separate chapter + + The Flash Image paragraph references it, change the reference wording. + + Signed-off-by: Keith Packard + +commit 11099fab63d32f53d0f2e04a7ab04392e39b5963 +Author: Keith Packard +Date: Wed Aug 24 22:18:29 2011 -0700 + + doc: Move updating device firmware section to separate chapter + + This isn't central to operation of the devices, so move it out to a + separate chapter + + Signed-off-by: Keith Packard + +commit 50769fbbeaaf61111d363411e0ef0b2868681cf4 +Merge: 425fa99 d92c173 +Author: Bdale Garbee +Date: Wed Aug 24 23:15:20 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 425fa995aeaccc1ec9ecf011f185b4406df61541 +Author: Bdale Garbee +Date: Wed Aug 24 23:15:15 2011 -0600 + + more tweaking + +commit d92c173615a5fb0278ff6878595bed3f8d813e03 +Author: Keith Packard +Date: Wed Aug 24 22:12:39 2011 -0700 + + doc: use 'radio link' to refer to packet command mode + + Make sure 'radio link' doesn't refer to telemetry and eliminate use of + 'RF link' and other similar but not identical phrases. + + Signed-off-by: Keith Packard + +commit 65ca6f0d7c96432413868274b2cfdea4b76683e4 +Author: Bdale Garbee +Date: Wed Aug 24 23:03:23 2011 -0600 + + more tweaks + +commit 09981cd024297fd4ef093c7468de2b9d5f3c2691 +Merge: a476e76 03c8b27 +Author: Bdale Garbee +Date: Wed Aug 24 22:42:39 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit a476e76622b6fa70bf7c8883d2a2a64a382fbd78 +Author: Bdale Garbee +Date: Wed Aug 24 22:42:33 2011 -0600 + + more doc tweaks + +commit 03c8b2702a45a12c4748cd1ec801d720c816d9e9 +Author: Keith Packard +Date: Wed Aug 24 21:39:48 2011 -0700 + + doc: Move Packet Command Mode section to System Operations chapter + + It makes far more sense here. + + Signed-off-by: Keith Packard + +commit 221157af586c6fd7368ee858a390f38bc5ed50f5 +Author: Keith Packard +Date: Wed Aug 24 21:31:05 2011 -0700 + + doc: Describe packet command mode a bit better. + + Include comments about TeleMini in the introduction, and then explain + a bit better what the best method of reliably initiating packet + command mode are (start operation, then boot telemini). + + Signed-off-by: Keith Packard + +commit d4e1aa92b6ce2f3e4c51029595d1d44a7f2f14a0 +Author: Bdale Garbee +Date: Wed Aug 24 22:27:35 2011 -0600 + + more doc tweaking + +commit 6eff8d5831dde8e690586cd2a97ddf1595cd2674 +Author: Keith Packard +Date: Wed Aug 24 20:59:28 2011 -0700 + + doc: Document pad-mode 'on-board data logging' indicator + + There wasn't any documentation for this field in the 'Launch Pad' tab. + + Signed-off-by: Keith Packard + +commit ca0879ba6e5295b4fa790705f742eb647a462ea0 +Author: Keith Packard +Date: Wed Aug 24 20:42:09 2011 -0700 + + doc: Spelling corrections in altusmetrum.xsl + + Lots of minor spelling errors. + + Signed-off-by: Keith Packard + +commit 963649aa064acfe75d2ff4babd9a0d35dc254e86 +Author: Bdale Garbee +Date: Wed Aug 24 21:39:21 2011 -0600 + + doc tweaks through chap 3 + +commit 3d88e0493ab446d7c7011786390d30618a72d045 +Merge: 02d6545 5a9972d +Author: Bdale Garbee +Date: Wed Aug 24 21:26:26 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 5a9972d41a87d4204c6c93cacf14e2962cc1c59c +Author: Keith Packard +Date: Wed Aug 24 20:22:29 2011 -0700 + + altos/windows: Get latest JRE 1.6 version (Version 6 update 27) + + No reason to download stale java bits. + + Signed-off-by: Keith Packard + +commit cbfbaabb39f9f7709d00cf3dc63cc1bc7563062e +Author: Keith Packard +Date: Wed Aug 24 19:13:03 2011 -0700 + + altosui: Make flight monitor font size configurable + + Tiny netbooks aren't tall enough for the 'usual' font size, so provide + a smaller option. Then provide a bigger option, just because. + + Signed-off-by: Keith Packard + +commit 9849883a754a73b861dd7be530753ff5c2abb499 +Author: Keith Packard +Date: Wed Aug 24 01:48:28 2011 -0700 + + altosui: Don't trust companion telemetry record 'channels' count + + It can be bogus, allowing the code to walk off the end of the + allocated data array. + + Signed-off-by: Keith Packard + +commit 02d65453225a3807e61b2ac6e2a26da31a05bd45 +Author: Bdale Garbee +Date: Wed Aug 24 01:53:02 2011 -0600 + + update changelogs for Debian build + commit 1d286dab223e6c44a25180f944ccb5ba8ed9d5f5 Author: Bdale Garbee Date: Wed Aug 24 01:51:54 2011 -0600 diff --git a/debian/changelog b/debian/changelog index e786b10f..906c0ded 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,123 @@ +altos (1.0) unstable; urgency=low + + [ Keith Packard ] + * altos: Lost change that reported flight 0 when log memory was full + * altosui: Ancient log files used 'apogee' for 'coast' state + * altosui: Add 'On-board Data Logging' indicator to pad tab + + [ Bdale Garbee ] + * update changelogs for Debian build + * update changelogs for Debian build + + [ Keith Packard ] + * altosui: remove debug printf in pad pane + * altosui: Disable 'max flight log' config when there are stored flights + * altos: Merge common config code in ao_config.c + * Bump version to 0.9.7 + * altos/altosui: Add ability to disable telemetry/rdf completely + * altosui: Clean up command line processing. Add --graph + * altos-fat/windows: Check and install Java 1.6 as needed + * altosui/windows: Fix a bunch of windows compiler warnings. + * altosui: Attempt to make both 32- and 64-bit windows DLLs + * doc: Add note about telemetry disable mode to 1.0 release notes + * doc: Add Installation Recommendations chapter + * altosui: Add a few simple unit conversions + * altosui: Capture date/time/serial/flight in AltosFlightStats + * altosui: Add date/time/serial/flight to flight stats tab + * altosui: Show filename in AltosGraph window + * altosui: Add --summary option to dump flight stats to stdout + * altosui: Make monitor-idle display correct 'On-board data logging' status + * altosui: Can't configure flight log max on TeleMini + * altosui: fix 'magic' string to signal end of config data + * altosui: Only 'show' config dialog once + * altosui: Reset all config data on 'reset' command + * altosui: Update mac os X library + * libaltos: fix Mac OS X function signatures + * altosui: add tool-tips to the button box. + + [ Bdale Garbee ] + * turn off auto-tagging during Debian build + * update changelogs for Debian build + * rewind changelog to 0.9.6.0 for rebuild + * update changelogs for Debian build + + [ Keith Packard ] + * altosui: Use system look&feel + * Remove stale tools (ao-dumplog, ao-postflight, ao-view) + * altosui: Add tool-tips to config dialogs + * altosui: Try to get dialogs to look a little better + + [ Bdale Garbee ] + * another test round + * roll changelog back in prep for another test build + * update changelogs for Debian build + * add pkg-config to the build deps + * prepare for another rebuild + * update changelogs for Debian build + + [ Keith Packard ] + * altosui: Don't trust companion telemetry record 'channels' count + * altosui: Make flight monitor font size configurable + * altos/windows: Get latest JRE 1.6 version (Version 6 update 27) + + [ Bdale Garbee ] + * doc tweaks through chap 3 + + [ Keith Packard ] + * doc: Spelling corrections in altusmetrum.xsl + * doc: Document pad-mode 'on-board data logging' indicator + + [ Bdale Garbee ] + * more doc tweaking + + [ Keith Packard ] + * doc: Describe packet command mode a bit better. + * doc: Move Packet Command Mode section to System Operations chapter + + [ Bdale Garbee ] + * more doc tweaks + * more tweaks + + [ Keith Packard ] + * doc: use 'radio link' to refer to packet command mode + + [ Bdale Garbee ] + * more tweaking + + [ Keith Packard ] + * doc: Move updating device firmware section to separate chapter + * doc: Updating Firmware is now a separate chapter + + [ Bdale Garbee ] + * more changes + + [ Keith Packard ] + * doc: Move the remaining command-mode descriptions to the appendix + + [ Bdale Garbee ] + * tweak tweak tweak + + [ Keith Packard ] + * doc: Describe max flight log, ignite mode and pad orientation + * doc: Remove duplicate documentation about max flight log + + [ Bdale Garbee ] + * more tweaks + * prepare to release + * don't deliver sources.list fragment in official Debian packages + * changes in preparation for upload to Debian + * ao-view is no longer included in the altos package, so have the + old-style Debian menu entry point to altosui instead + * rewind packaging changelog to last tagged version + * update desktop file for consistency with package section + * we need a main category in the desktop file + * really, I mean it, no longer deliver the sources.list fragment + * add a postinst to remove sources.list.d fragment delivered by old + private versions of this package, no longer needed once we have + official packages + + -- Bdale Garbee Thu, 25 Aug 2011 02:22:21 -0600 + altos (0.9.6.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From c3314dae2d3df82e188daf6ba8520cce833592c6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 03:36:25 -0600 Subject: use multimaint-merge to make Debian changelogs less ugly --- debian/rules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/rules b/debian/rules index 028b548f..9f24321b 100755 --- a/debian/rules +++ b/debian/rules @@ -8,7 +8,7 @@ DEB_VERSION := $(shell if [ -x /usr/bin/git ]; then git describe; else echo 0; f # this target invoked by git-buildpackage using a clean hook, see .gbp.conf prebuild: echo $(DEB_VERSION) - git-dch --release --new-version=$(DEB_VERSION) + git-dch --release --new-version=$(DEB_VERSION) --multimaint-merge git log > ChangeLog git commit -n ChangeLog debian/changelog \ -m "update changelogs for Debian build" -- cgit v1.2.3 From 93ecaf7f18f8f4c15953c2e80dc9e1b20d04fdfa Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 25 Aug 2011 15:46:30 -0600 Subject: update TeleMini turnon script now that we've made a stable firmware release --- ao-bringup/turnon_telemini | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 8f694203..0cb3d029 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -18,13 +18,13 @@ else exit 1 fi -echo "TeleMini v0.1 Turn-On and Calibration Program" +echo "TeleMini v1.0 Turn-On and Calibration Program" echo "Copyright 2011 by Bdale Garbee. Released under GPL v2" echo echo "Expectations:" -echo "\tTeleMini v0.1 powered from LiPo" +echo "\tTeleMini v1.0 powered from LiPo" echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" -echo "\t\twith coax from SMA to frequency counter" +echo "\t\twith frequency counter able to sample RF output" echo echo -n "TeleMini serial number: " read SERIAL @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/telemini-v0.1*.ihx $SERIAL +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v0.1*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 3bfe8df44b575ca430ffaa051e20faa955a06c03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 18:02:45 -0700 Subject: altos: Clear callsign on initial config load Before being written the first time, ao_config will get set to 0xff when the config storage is read. This leaves the tail of the callsign filled with invalid bytes. Zero the whole thing before loading the default callsign to make sure any extra bytes are set correctly. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ao_config.c b/src/ao_config.c index eb1eea3f..0c10e608 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -74,6 +74,7 @@ _ao_config_get(void) ao_config.minor = 0; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; + memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); } -- cgit v1.2.3 From 9513be7f9d3d0b0ec29f6487fa9dc8f1ac24d0de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 20:43:44 -0700 Subject: altos: Restructure altos build to prepare for multi-arch support Split out sources into separate directories: core: architecture and product independent bits cc1111: cc1111-specific code drivers: architecture independent drivers product: product-specific sources and Makefile fragments util: scripts for building stuff This should have no effect on the built products, but testing is encouraged Signed-off-by: Keith Packard --- configure.ac | 2 +- src/25lc1024.h | 41 - src/Makefile | 25 +- src/Makefile.proto | 380 -------- src/_bp.c | 26 - src/altitude.h | 132 --- src/ao-make-product.5c | 103 -- src/ao.h | 1610 -------------------------------- src/ao_adc.c | 196 ---- src/ao_adc_fake.c | 27 - src/ao_beep.c | 52 -- src/ao_btm.c | 302 ------ src/ao_cmd.c | 320 ------- src/ao_companion.c | 132 --- src/ao_config.c | 542 ----------- src/ao_convert.c | 85 -- src/ao_convert_test.c | 75 -- src/ao_dbg.c | 364 -------- src/ao_dma.c | 131 --- src/ao_ee.c | 241 ----- src/ao_ee_fake.c | 37 - src/ao_flash.c | 318 ------- src/ao_flight.c | 315 ------- src/ao_flight_nano.c | 120 --- src/ao_flight_test.c | 716 -------------- src/ao_gps_print.c | 112 --- src/ao_gps_report.c | 99 -- src/ao_gps_sirf.c | 442 --------- src/ao_gps_skytraq.c | 490 ---------- src/ao_gps_test.c | 508 ---------- src/ao_gps_test_skytraq.c | 490 ---------- src/ao_host.h | 127 --- src/ao_ignite.c | 218 ----- src/ao_intflash.c | 209 ----- src/ao_kalman.c | 292 ------ src/ao_led.c | 61 -- src/ao_log.c | 284 ------ src/ao_log_big.c | 158 ---- src/ao_log_telem.c | 30 - src/ao_log_tiny.c | 161 ---- src/ao_m25.c | 380 -------- src/ao_main.c | 43 - src/ao_monitor.c | 277 ------ src/ao_mutex.c | 41 - src/ao_packet.c | 148 --- src/ao_packet_master.c | 144 --- src/ao_packet_slave.c | 64 -- src/ao_panic.c | 66 -- src/ao_pins.h | 408 -------- src/ao_product.c | 155 --- src/ao_radio.c | 475 ---------- src/ao_reboot.c | 28 - src/ao_report.c | 180 ---- src/ao_romconfig.c | 32 - src/ao_rssi.c | 53 -- src/ao_sample.c | 209 ----- src/ao_serial.c | 175 ---- src/ao_spi.c | 157 ---- src/ao_state.c | 23 - src/ao_stdio.c | 84 -- src/ao_storage.c | 184 ---- src/ao_task.c | 275 ------ src/ao_telebt.c | 50 - src/ao_teledongle.c | 40 - src/ao_telem.h | 172 ---- src/ao_telemetrum.c | 70 -- src/ao_telemetry.c | 270 ------ src/ao_telemini.c | 49 - src/ao_telenano.c | 43 - src/ao_teleterra.c | 38 - src/ao_test.c | 117 --- src/ao_tidongle.c | 42 - src/ao_timer.c | 111 --- src/ao_usb.c | 460 --------- src/ao_usb.h | 100 -- src/at45db161d.h | 45 - src/cc1111.h | 1306 -------------------------- src/cc1111/Makefile.cc1111 | 27 + src/cc1111/_bp.c | 26 + src/cc1111/ao_adc.c | 196 ++++ src/cc1111/ao_beep.c | 52 ++ src/cc1111/ao_dbg.c | 364 ++++++++ src/cc1111/ao_dma.c | 131 +++ src/cc1111/ao_ignite.c | 218 +++++ src/cc1111/ao_intflash.c | 209 +++++ src/cc1111/ao_led.c | 61 ++ src/cc1111/ao_packet.c | 148 +++ src/cc1111/ao_packet_master.c | 144 +++ src/cc1111/ao_packet_slave.c | 64 ++ src/cc1111/ao_radio.c | 475 ++++++++++ src/cc1111/ao_reboot.c | 28 + src/cc1111/ao_romconfig.c | 32 + src/cc1111/ao_serial.c | 175 ++++ src/cc1111/ao_spi.c | 157 ++++ src/cc1111/ao_timer.c | 111 +++ src/cc1111/ao_usb.c | 460 +++++++++ src/cc1111/ao_usb.h | 100 ++ src/cc1111/cc1111.h | 1306 ++++++++++++++++++++++++++ src/check-stack | 13 - src/core/altitude.h | 132 +++ src/core/ao.h | 1610 ++++++++++++++++++++++++++++++++ src/core/ao_cmd.c | 320 +++++++ src/core/ao_config.c | 542 +++++++++++ src/core/ao_convert.c | 85 ++ src/core/ao_convert_test.c | 75 ++ src/core/ao_ee_fake.c | 37 + src/core/ao_flight.c | 315 +++++++ src/core/ao_flight_nano.c | 120 +++ src/core/ao_gps_print.c | 112 +++ src/core/ao_gps_report.c | 99 ++ src/core/ao_host.h | 127 +++ src/core/ao_kalman.c | 292 ++++++ src/core/ao_log.c | 284 ++++++ src/core/ao_log_big.c | 158 ++++ src/core/ao_log_telem.c | 30 + src/core/ao_log_tiny.c | 161 ++++ src/core/ao_monitor.c | 277 ++++++ src/core/ao_mutex.c | 41 + src/core/ao_panic.c | 66 ++ src/core/ao_pins.h | 408 ++++++++ src/core/ao_product.c | 155 +++ src/core/ao_report.c | 180 ++++ src/core/ao_rssi.c | 53 ++ src/core/ao_sample.c | 209 +++++ src/core/ao_state.c | 23 + src/core/ao_stdio.c | 84 ++ src/core/ao_storage.c | 184 ++++ src/core/ao_task.c | 275 ++++++ src/core/ao_telem.h | 172 ++++ src/core/ao_telemetry.c | 270 ++++++ src/drivers/ao_25lc1024.c | 241 +++++ src/drivers/ao_25lc1024.h | 41 + src/drivers/ao_at45db161d.c | 318 +++++++ src/drivers/ao_at45db161d.h | 45 + src/drivers/ao_btm.c | 302 ++++++ src/drivers/ao_companion.c | 132 +++ src/drivers/ao_gps_sirf.c | 442 +++++++++ src/drivers/ao_gps_skytraq.c | 490 ++++++++++ src/drivers/ao_m25.c | 380 ++++++++ src/gps-cksum | 17 - src/make-altitude | 283 ------ src/make-kalman | 19 - src/product/Makefile.telebt | 97 ++ src/product/Makefile.teledongle | 96 ++ src/product/Makefile.telemetrum | 111 +++ src/product/Makefile.telemini | 100 ++ src/product/Makefile.telenano | 99 ++ src/product/ao_telebt.c | 50 + src/product/ao_teledongle.c | 40 + src/product/ao_telemetrum.c | 70 ++ src/product/ao_telemini.c | 49 + src/product/ao_telenano.c | 43 + src/product/ao_teleterra.c | 38 + src/product/ao_test.c | 117 +++ src/product/ao_tidongle.c | 42 + src/sirf-cksum | 44 - src/skytraq-cksum | 44 - src/telebt-v0.0/Makefile | 10 +- src/telebt-v0.0/Makefile.defs | 8 - src/telebt-v0.1/Makefile | 20 +- src/telebt-v0.1/Makefile.defs | 8 - src/teledongle-v0.1/Makefile | 9 +- src/teledongle-v0.1/Makefile.defs | 9 - src/teledongle-v0.2/Makefile | 9 +- src/teledongle-v0.2/Makefile.defs | 9 - src/telemetrum-v0.1-sirf/Makefile | 17 +- src/telemetrum-v0.1-sirf/Makefile.defs | 12 - src/telemetrum-v0.1-sky/Makefile | 17 +- src/telemetrum-v0.1-sky/Makefile.defs | 12 - src/telemetrum-v1.0/Makefile | 17 +- src/telemetrum-v1.0/Makefile.defs | 13 - src/telemetrum-v1.1/Makefile | 17 +- src/telemetrum-v1.1/Makefile.defs | 13 - src/telemini-v1.0/Makefile | 9 +- src/telemini-v1.0/Makefile.defs | 9 - src/telenano-v0.1/Makefile | 10 +- src/telenano-v0.1/Makefile.defs | 9 - src/test/Makefile | 20 +- src/test/ao_flight_test.c | 716 ++++++++++++++ src/test/ao_gps_test.c | 508 ++++++++++ src/test/ao_gps_test_skytraq.c | 490 ++++++++++ src/tidongle/Makefile | 93 +- src/tidongle/Makefile.defs | 9 - src/util/ao-make-product.5c | 103 ++ src/util/check-stack | 13 + src/util/gps-cksum | 17 + src/util/make-altitude | 283 ++++++ src/util/make-kalman | 19 + src/util/sirf-cksum | 44 + src/util/skytraq-cksum | 44 + 190 files changed, 17208 insertions(+), 17018 deletions(-) delete mode 100644 src/25lc1024.h delete mode 100644 src/Makefile.proto delete mode 100644 src/_bp.c delete mode 100644 src/altitude.h delete mode 100644 src/ao-make-product.5c delete mode 100644 src/ao.h delete mode 100644 src/ao_adc.c delete mode 100644 src/ao_adc_fake.c delete mode 100644 src/ao_beep.c delete mode 100644 src/ao_btm.c delete mode 100644 src/ao_cmd.c delete mode 100644 src/ao_companion.c delete mode 100644 src/ao_config.c delete mode 100644 src/ao_convert.c delete mode 100644 src/ao_convert_test.c delete mode 100644 src/ao_dbg.c delete mode 100644 src/ao_dma.c delete mode 100644 src/ao_ee.c delete mode 100644 src/ao_ee_fake.c delete mode 100644 src/ao_flash.c delete mode 100644 src/ao_flight.c delete mode 100644 src/ao_flight_nano.c delete mode 100644 src/ao_flight_test.c delete mode 100644 src/ao_gps_print.c delete mode 100644 src/ao_gps_report.c delete mode 100644 src/ao_gps_sirf.c delete mode 100644 src/ao_gps_skytraq.c delete mode 100644 src/ao_gps_test.c delete mode 100644 src/ao_gps_test_skytraq.c delete mode 100644 src/ao_host.h delete mode 100644 src/ao_ignite.c delete mode 100644 src/ao_intflash.c delete mode 100644 src/ao_kalman.c delete mode 100644 src/ao_led.c delete mode 100644 src/ao_log.c delete mode 100644 src/ao_log_big.c delete mode 100644 src/ao_log_telem.c delete mode 100644 src/ao_log_tiny.c delete mode 100644 src/ao_m25.c delete mode 100644 src/ao_main.c delete mode 100644 src/ao_monitor.c delete mode 100644 src/ao_mutex.c delete mode 100644 src/ao_packet.c delete mode 100644 src/ao_packet_master.c delete mode 100644 src/ao_packet_slave.c delete mode 100644 src/ao_panic.c delete mode 100644 src/ao_pins.h delete mode 100644 src/ao_product.c delete mode 100644 src/ao_radio.c delete mode 100644 src/ao_reboot.c delete mode 100644 src/ao_report.c delete mode 100644 src/ao_romconfig.c delete mode 100644 src/ao_rssi.c delete mode 100644 src/ao_sample.c delete mode 100644 src/ao_serial.c delete mode 100644 src/ao_spi.c delete mode 100644 src/ao_state.c delete mode 100644 src/ao_stdio.c delete mode 100644 src/ao_storage.c delete mode 100644 src/ao_task.c delete mode 100644 src/ao_telebt.c delete mode 100644 src/ao_teledongle.c delete mode 100644 src/ao_telem.h delete mode 100644 src/ao_telemetrum.c delete mode 100644 src/ao_telemetry.c delete mode 100644 src/ao_telemini.c delete mode 100644 src/ao_telenano.c delete mode 100644 src/ao_teleterra.c delete mode 100644 src/ao_test.c delete mode 100644 src/ao_tidongle.c delete mode 100644 src/ao_timer.c delete mode 100644 src/ao_usb.c delete mode 100644 src/ao_usb.h delete mode 100644 src/at45db161d.h delete mode 100644 src/cc1111.h create mode 100644 src/cc1111/Makefile.cc1111 create mode 100644 src/cc1111/_bp.c create mode 100644 src/cc1111/ao_adc.c create mode 100644 src/cc1111/ao_beep.c create mode 100644 src/cc1111/ao_dbg.c create mode 100644 src/cc1111/ao_dma.c create mode 100644 src/cc1111/ao_ignite.c create mode 100644 src/cc1111/ao_intflash.c create mode 100644 src/cc1111/ao_led.c create mode 100644 src/cc1111/ao_packet.c create mode 100644 src/cc1111/ao_packet_master.c create mode 100644 src/cc1111/ao_packet_slave.c create mode 100644 src/cc1111/ao_radio.c create mode 100644 src/cc1111/ao_reboot.c create mode 100644 src/cc1111/ao_romconfig.c create mode 100644 src/cc1111/ao_serial.c create mode 100644 src/cc1111/ao_spi.c create mode 100644 src/cc1111/ao_timer.c create mode 100644 src/cc1111/ao_usb.c create mode 100644 src/cc1111/ao_usb.h create mode 100644 src/cc1111/cc1111.h delete mode 100755 src/check-stack create mode 100644 src/core/altitude.h create mode 100644 src/core/ao.h create mode 100644 src/core/ao_cmd.c create mode 100644 src/core/ao_config.c create mode 100644 src/core/ao_convert.c create mode 100644 src/core/ao_convert_test.c create mode 100644 src/core/ao_ee_fake.c create mode 100644 src/core/ao_flight.c create mode 100644 src/core/ao_flight_nano.c create mode 100644 src/core/ao_gps_print.c create mode 100644 src/core/ao_gps_report.c create mode 100644 src/core/ao_host.h create mode 100644 src/core/ao_kalman.c create mode 100644 src/core/ao_log.c create mode 100644 src/core/ao_log_big.c create mode 100644 src/core/ao_log_telem.c create mode 100644 src/core/ao_log_tiny.c create mode 100644 src/core/ao_monitor.c create mode 100644 src/core/ao_mutex.c create mode 100644 src/core/ao_panic.c create mode 100644 src/core/ao_pins.h create mode 100644 src/core/ao_product.c create mode 100644 src/core/ao_report.c create mode 100644 src/core/ao_rssi.c create mode 100644 src/core/ao_sample.c create mode 100644 src/core/ao_state.c create mode 100644 src/core/ao_stdio.c create mode 100644 src/core/ao_storage.c create mode 100644 src/core/ao_task.c create mode 100644 src/core/ao_telem.h create mode 100644 src/core/ao_telemetry.c create mode 100644 src/drivers/ao_25lc1024.c create mode 100644 src/drivers/ao_25lc1024.h create mode 100644 src/drivers/ao_at45db161d.c create mode 100644 src/drivers/ao_at45db161d.h create mode 100644 src/drivers/ao_btm.c create mode 100644 src/drivers/ao_companion.c create mode 100644 src/drivers/ao_gps_sirf.c create mode 100644 src/drivers/ao_gps_skytraq.c create mode 100644 src/drivers/ao_m25.c delete mode 100755 src/gps-cksum delete mode 100644 src/make-altitude delete mode 100644 src/make-kalman create mode 100644 src/product/Makefile.telebt create mode 100644 src/product/Makefile.teledongle create mode 100644 src/product/Makefile.telemetrum create mode 100644 src/product/Makefile.telemini create mode 100644 src/product/Makefile.telenano create mode 100644 src/product/ao_telebt.c create mode 100644 src/product/ao_teledongle.c create mode 100644 src/product/ao_telemetrum.c create mode 100644 src/product/ao_telemini.c create mode 100644 src/product/ao_telenano.c create mode 100644 src/product/ao_teleterra.c create mode 100644 src/product/ao_test.c create mode 100644 src/product/ao_tidongle.c delete mode 100755 src/sirf-cksum delete mode 100644 src/skytraq-cksum delete mode 100644 src/telebt-v0.0/Makefile.defs delete mode 100644 src/telebt-v0.1/Makefile.defs delete mode 100644 src/teledongle-v0.1/Makefile.defs delete mode 100644 src/teledongle-v0.2/Makefile.defs delete mode 100644 src/telemetrum-v0.1-sirf/Makefile.defs delete mode 100644 src/telemetrum-v0.1-sky/Makefile.defs delete mode 100644 src/telemetrum-v1.0/Makefile.defs delete mode 100644 src/telemetrum-v1.1/Makefile.defs delete mode 100644 src/telemini-v1.0/Makefile.defs delete mode 100644 src/telenano-v0.1/Makefile.defs create mode 100644 src/test/ao_flight_test.c create mode 100644 src/test/ao_gps_test.c create mode 100644 src/test/ao_gps_test_skytraq.c delete mode 100644 src/tidongle/Makefile.defs create mode 100644 src/util/ao-make-product.5c create mode 100755 src/util/check-stack create mode 100755 src/util/gps-cksum create mode 100644 src/util/make-altitude create mode 100644 src/util/make-kalman create mode 100755 src/util/sirf-cksum create mode 100644 src/util/skytraq-cksum diff --git a/configure.ac b/configure.ac index f9002508..da9d9991 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) AC_INIT([altos], 1.0) -AC_CONFIG_SRCDIR([src/ao.h]) +AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/25lc1024.h b/src/25lc1024.h deleted file mode 100644 index 44e52387..00000000 --- a/src/25lc1024.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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. - */ - -/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ - -#ifndef _25LC1024_H_ -#define _25LC1024_H_ - -#define EE_READ 0x03 -#define EE_WRITE 0x02 -#define EE_WREN 0x06 -#define EE_WRDI 0x04 -#define EE_RDSR 0x05 -#define EE_WRSR 0x01 -#define EE_PE 0x42 -#define EE_SE 0xd8 -#define EE_CE 0xc7 -#define EE_RDID 0xab -#define EE_DPD 0xb9 - -#define EE_STATUS_WIP (1 << 0) -#define EE_STATUS_WEL (1 << 1) -#define EE_STATUS_BP0 (1 << 2) -#define EE_STATUS_BP1 (1 << 3) -#define EE_STATUS_WPEN (1 << 7) - -#endif /* _25LC1024_H_ */ diff --git a/src/Makefile b/src/Makefile index 018f0c5c..4e40c2bf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,13 @@ # AltOS build # # -CC=sdcc + +vpath make-altitude util +vpath make-kalman util +vpath kalman.5c kalman +vpath kalman_filter.5c kalman +vpath load_csv.5c kalman +vpath matrix.5c kalman include Version @@ -14,7 +20,7 @@ SUBDIRS=\ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test -all: all-recursive +all: all-local all-recursive RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive @@ -27,8 +33,21 @@ $(RECURSIVE_TARGETS): distclean: clean -clean: clean-recursive +clean: clean-local clean-recursive install: install-recursive uninstall: + +all-recursive: all-local + +all-local: altitude.h ao_kalman.h + +altitude.h: make-altitude + nickle $< > $@ + +ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< kalman > $@ + +clean-local: + rm -f altitude.h ao_kalman.h \ No newline at end of file diff --git a/src/Makefile.proto b/src/Makefile.proto deleted file mode 100644 index 8f98d354..00000000 --- a/src/Makefile.proto +++ /dev/null @@ -1,380 +0,0 @@ -# -# AltOS build -# -# -vpath %.c .. -vpath %.h .. -vpath make-altitude .. -vpath make-kalman .. -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c .. - -CC=sdcc - -ifndef VERSION -include ../Version -endif - -CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) - -CODESIZE ?= 0x8000 - -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ - --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff - -INC = \ - ao.h \ - ao_pins.h \ - cc1111.h \ - altitude.h \ - ao_kalman.h \ - 25lc1024.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ - ao_cmd.c \ - ao_dma.c \ - ao_mutex.c \ - ao_panic.c \ - ao_task.c \ - ao_timer.c \ - ao_romconfig.c \ - _bp.c - -# -# Shared AltOS drivers -# -ALTOS_DRIVER_SRC = \ - ao_config.c \ - ao_led.c \ - ao_radio.c \ - ao_stdio.c - -BEEP_DRIVER_SRC = \ - ao_beep.c - -USB_DRIVER_SRC = \ - ao_usb.c - -TELE_COMMON_SRC = \ - ao_packet.c - -# -# Receiver code -# -TELE_RECEIVER_SRC =\ - ao_monitor.c \ - ao_gps_print.c \ - ao_packet_master.c \ - ao_state.c \ - ao_rssi.c - -# -# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) -# - -TELE_DRIVER_SRC = \ - ao_convert.c - -# -# Serial port driver -# -SERIAL_DRIVER_SRC = \ - ao_serial.c - -# -# Spi bus driver -# -SPI_DRIVER_SRC = \ - ao_spi.c - -# -# Debug dongle driver (only on TI) -# -DBG_SRC = \ - ao_dbg.c - -# -# Drivers only on TeleMetrum -# -TM_DRIVER_SRC = \ - ao_adc.c \ - ao_gps_report.c \ - ao_ignite.c \ - ao_packet_slave.c \ - $(BEEP_DRIVER_SRC) \ - $(USB_DRIVER_SRC) - -# -# 25LC1024 driver source -EE_DRIVER_SRC = \ - ao_storage.c \ - ao_ee.c - -# -# AT45DB161D driver source - -FLASH_DRIVER_SRC = \ - ao_storage.c \ - ao_flash.c - -# -# Numonyx M25P80 driver source -# - -M25_DRIVER_SRC = \ - ao_storage.c \ - ao_m25.c - -# -# SiRF driver source -# -SIRF_DRIVER_SRC = \ - ao_gps_sirf.c - -# -# Skytraq driver source -# -SKY_DRIVER_SRC = \ - ao_gps_skytraq.c - - -# -# BTM-182 driver source -# -BTM_DRIVER_SRC = \ - ao_btm.c - -# -# Companion port driver source -# -COMPANION_SRC = \ - ao_companion.c - -# -# Tasks run on TeleMetrum -# -TM_TASK_SRC = \ - ao_flight.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_big.c \ - ao_report.c \ - ao_telemetry.c - -TM_MAIN_SRC = \ - ao_telemetrum.c - -# -# Base sources for TeleMetrum -# -TM_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(SERIAL_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TM_DRIVER_SRC) \ - $(TM_TASK_SRC) \ - $(TM_MAIN_SRC) - -# -# Sources for TeleMini -TMINI_DRIVER_SRC = \ - ao_adc.c \ - ao_ignite.c \ - ao_config.c \ - ao_storage.c \ - ao_packet_slave.c \ - ao_intflash.c - -TMINI_TASK_SRC = \ - ao_flight.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_tiny.c \ - ao_report.c \ - ao_telemetry.c - -TMINI_MAIN_SRC = \ - ao_telemini.c - -TMINI_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TMINI_DRIVER_SRC) \ - $(TMINI_TASK_SRC) \ - $(TMINI_MAIN_SRC) - -# -# Sources for TeleNano -TNANO_DRIVER_SRC = \ - ao_adc.c \ - ao_config.c \ - ao_storage.c \ - ao_packet_slave.c \ - ao_intflash.c - -TNANO_TASK_SRC = \ - ao_flight_nano.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_tiny.c \ - ao_report.c \ - ao_telemetry.c - -TNANO_MAIN_SRC = \ - ao_telenano.c - -TNANO_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TNANO_DRIVER_SRC) \ - $(TNANO_TASK_SRC) \ - $(TNANO_MAIN_SRC) - -# -# Sources for TeleBluetooth -# - -TBT_MAIN_SRC = \ - ao_telebt.c - -TBT_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(SERIAL_DRIVER_SRC) \ - $(USB_DRIVER_SRC) \ - $(BTM_DRIVER_SRC) \ - $(DBG_SRC) \ - $(TBT_MAIN_SRC) - -TBT_V_0_1_SRC = \ - $(TBT_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(M25_DRIVER_SRC) \ - $(BEEP_DRIVER_SRC) \ - ao_log_telem.c - -# -# TI Dongle sources -# -TI_MAIN_SRC = \ - ao_tidongle.c - -# -# All sources for the TI debug dongle -# -TI_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TI_MAIN_SRC) \ - $(DBG_SRC) - -TT_MAIN_SRC = \ - ao_teleterra.c -# -# All sources for TeleTerra -# -TT_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TT_MAIN_SRC) - - -# -# Sources for TeleDongle -# - -TD_MAIN_SRC = \ - ao_teledongle.c - -TD_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TD_MAIN_SRC) - -include Makefile.defs - -CFLAGS += $(PRODUCT_DEF) -I. - -NICKLE=nickle -CHECK_STACK=sh ../check-stack - -REL=$(SRC:.c=.rel) ao_product.rel -ADB=$(REL:.rel=.adb) -ASM=$(REL:.rel=.asm) -LNK=$(REL:.rel=.lnk) -LST=$(REL:.rel=.lst) -RST=$(REL:.rel=.rst) -SYM=$(REL:.rel=.sym) - -PCDB=$(PROG:.ihx=.cdb) -PLNK=$(PROG:.ihx=.lnk) -PMAP=$(PROG:.ihx=.map) -PMEM=$(PROG:.ihx=.mem) -PAOM=$(PROG:.ihx=) - -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - -%.rel : %.c $(INC) - $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< - -all: ../$(PROG) - -../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../ao.h $(PMEM) - -../altitude.h: make-altitude - nickle $< > $@ - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< > $@ - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -$(REL): ao_product.h - -distclean: clean - -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) - -install: - -uninstall: diff --git a/src/_bp.c b/src/_bp.c deleted file mode 100644 index 6bf135bc..00000000 --- a/src/_bp.c +++ /dev/null @@ -1,26 +0,0 @@ -/*------------------------------------------------------------------------- - - _bp.c :- just declares bp as a variable - - Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This library 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 Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! --------------------------------------------------------------------------*/ - -__data unsigned char bp ; diff --git a/src/altitude.h b/src/altitude.h deleted file mode 100644 index a278bbc6..00000000 --- a/src/altitude.h +++ /dev/null @@ -1,132 +0,0 @@ -/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ -#define NALT 129 -#define ALT_FRAC_BITS 8 - 15835, /* 10.56 kPa 0.000% */ - 15332, /* 11.42 kPa 0.781% */ - 14868, /* 12.29 kPa 1.563% */ - 14435, /* 13.16 kPa 2.344% */ - 14030, /* 14.02 kPa 3.125% */ - 13649, /* 14.90 kPa 3.906% */ - 13290, /* 15.76 kPa 4.688% */ - 12950, /* 16.63 kPa 5.469% */ - 12627, /* 17.50 kPa 6.250% */ - 12320, /* 18.37 kPa 7.031% */ - 12027, /* 19.24 kPa 7.813% */ - 11747, /* 20.10 kPa 8.594% */ - 11479, /* 20.97 kPa 9.375% */ - 11222, /* 21.84 kPa 10.156% */ - 10975, /* 22.71 kPa 10.938% */ - 10736, /* 23.58 kPa 11.719% */ - 10504, /* 24.44 kPa 12.500% */ - 10278, /* 25.31 kPa 13.281% */ - 10059, /* 26.18 kPa 14.063% */ - 9846, /* 27.05 kPa 14.844% */ - 9638, /* 27.91 kPa 15.625% */ - 9435, /* 28.78 kPa 16.406% */ - 9237, /* 29.65 kPa 17.188% */ - 9044, /* 30.52 kPa 17.969% */ - 8855, /* 31.39 kPa 18.750% */ - 8670, /* 32.26 kPa 19.531% */ - 8490, /* 33.13 kPa 20.313% */ - 8313, /* 33.99 kPa 21.094% */ - 8140, /* 34.86 kPa 21.875% */ - 7970, /* 35.73 kPa 22.656% */ - 7803, /* 36.60 kPa 23.438% */ - 7640, /* 37.47 kPa 24.219% */ - 7480, /* 38.33 kPa 25.000% */ - 7322, /* 39.20 kPa 25.781% */ - 7168, /* 40.07 kPa 26.563% */ - 7016, /* 40.94 kPa 27.344% */ - 6867, /* 41.80 kPa 28.125% */ - 6720, /* 42.67 kPa 28.906% */ - 6575, /* 43.54 kPa 29.688% */ - 6433, /* 44.41 kPa 30.469% */ - 6294, /* 45.28 kPa 31.250% */ - 6156, /* 46.15 kPa 32.031% */ - 6020, /* 47.01 kPa 32.813% */ - 5887, /* 47.88 kPa 33.594% */ - 5755, /* 48.75 kPa 34.375% */ - 5625, /* 49.62 kPa 35.156% */ - 5497, /* 50.49 kPa 35.938% */ - 5371, /* 51.35 kPa 36.719% */ - 5247, /* 52.22 kPa 37.500% */ - 5124, /* 53.09 kPa 38.281% */ - 5003, /* 53.96 kPa 39.063% */ - 4883, /* 54.83 kPa 39.844% */ - 4765, /* 55.69 kPa 40.625% */ - 4648, /* 56.56 kPa 41.406% */ - 4533, /* 57.43 kPa 42.188% */ - 4419, /* 58.30 kPa 42.969% */ - 4307, /* 59.17 kPa 43.750% */ - 4196, /* 60.03 kPa 44.531% */ - 4086, /* 60.90 kPa 45.313% */ - 3977, /* 61.77 kPa 46.094% */ - 3870, /* 62.63 kPa 46.875% */ - 3764, /* 63.51 kPa 47.656% */ - 3659, /* 64.38 kPa 48.438% */ - 3555, /* 65.24 kPa 49.219% */ - 3453, /* 66.11 kPa 50.000% */ - 3351, /* 66.98 kPa 50.781% */ - 3250, /* 67.85 kPa 51.563% */ - 3151, /* 68.72 kPa 52.344% */ - 3052, /* 69.58 kPa 53.125% */ - 2955, /* 70.45 kPa 53.906% */ - 2858, /* 71.32 kPa 54.688% */ - 2763, /* 72.19 kPa 55.469% */ - 2668, /* 73.06 kPa 56.250% */ - 2574, /* 73.92 kPa 57.031% */ - 2482, /* 74.79 kPa 57.813% */ - 2390, /* 75.66 kPa 58.594% */ - 2298, /* 76.52 kPa 59.375% */ - 2208, /* 77.40 kPa 60.156% */ - 2119, /* 78.26 kPa 60.938% */ - 2030, /* 79.13 kPa 61.719% */ - 1942, /* 80.00 kPa 62.500% */ - 1855, /* 80.87 kPa 63.281% */ - 1769, /* 81.74 kPa 64.063% */ - 1683, /* 82.60 kPa 64.844% */ - 1598, /* 83.47 kPa 65.625% */ - 1514, /* 84.34 kPa 66.406% */ - 1430, /* 85.21 kPa 67.188% */ - 1347, /* 86.08 kPa 67.969% */ - 1265, /* 86.94 kPa 68.750% */ - 1184, /* 87.81 kPa 69.531% */ - 1103, /* 88.68 kPa 70.313% */ - 1023, /* 89.55 kPa 71.094% */ - 943, /* 90.41 kPa 71.875% */ - 864, /* 91.28 kPa 72.656% */ - 786, /* 92.15 kPa 73.438% */ - 708, /* 93.02 kPa 74.219% */ - 631, /* 93.89 kPa 75.000% */ - 554, /* 94.76 kPa 75.781% */ - 478, /* 95.63 kPa 76.563% */ - 403, /* 96.49 kPa 77.344% */ - 328, /* 97.36 kPa 78.125% */ - 254, /* 98.23 kPa 78.906% */ - 180, /* 99.10 kPa 79.688% */ - 106, /* 99.97 kPa 80.469% */ - 34, /* 100.83 kPa 81.250% */ - -39, /* 101.70 kPa 82.031% */ - -111, /* 102.57 kPa 82.813% */ - -182, /* 103.44 kPa 83.594% */ - -253, /* 104.30 kPa 84.375% */ - -323, /* 105.17 kPa 85.156% */ - -393, /* 106.04 kPa 85.938% */ - -462, /* 106.91 kPa 86.719% */ - -531, /* 107.78 kPa 87.500% */ - -600, /* 108.65 kPa 88.281% */ - -668, /* 109.51 kPa 89.063% */ - -736, /* 110.38 kPa 89.844% */ - -803, /* 111.25 kPa 90.625% */ - -870, /* 112.12 kPa 91.406% */ - -936, /* 112.99 kPa 92.188% */ - -1002, /* 113.85 kPa 92.969% */ - -1068, /* 114.72 kPa 93.750% */ - -1133, /* 115.59 kPa 94.531% */ - -1198, /* 116.46 kPa 95.313% */ - -1262, /* 117.33 kPa 96.094% */ - -1326, /* 118.19 kPa 96.875% */ - -1389, /* 119.06 kPa 97.656% */ - -1453, /* 119.93 kPa 98.438% */ - -1516, /* 120.80 kPa 99.219% */ - -1578, /* 121.67 kPa 100.000% */ diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c deleted file mode 100644 index 5f2eb8e8..00000000 --- a/src/ao-make-product.5c +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/sh - -autoimport ParseArgs; - -void -write_ucs2(string a, string description) -{ - int len = String::length(a); - - printf("/* %s */\n", description); - printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2); - printf("#define AO_%s_STRING \"%s\"\n", description, a); - printf("#define AO_%s_UCS2", description); - for (int i = 0; i < len; i++) { - int c = a[i]; - if (i > 0) - printf(","); - if (0x20 <= c && c < 128) - printf(" '%c', 0", c); - else - printf(" LE_WORD(0x%04x),", c); - } - printf("\n\n"); -} - -void -write_string(string a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_STRING \"%s\"\n", description, a); -} - -void -write_int(int a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_NUMBER %d\n\n", description, a); -} - -void -write_hex(int a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); -} - -string manufacturer = "altusmetrum.org"; -string product = "TeleMetrum"; -string version = "0.0"; -int serial = 1; -int user_argind = 0; -int id_product = 0x000a; - -argdesc argd = { - .args = { - { - .var = { .arg_string = &manufacturer }, - .abbr = 'm', - .name = "manufacturer", - .expr_name = "manf", - .desc = "Manufacturer name." }, - { - .var = { .arg_string = &product }, - .abbr = 'p', - .name = "product", - .expr_name = "prod", - .desc = "Product name." }, - { - .var = { .arg_int = &id_product }, - .abbr = 'i', - .name = "id_product", - .expr_name = "id_p", - .desc = "Product ID." }, - { - .var = { .arg_int = &serial }, - .abbr = 's', - .name = "serial", - .expr_name = "number", - .desc = "Serial number." }, - { - .var = { .arg_string = &version }, - .abbr = 'v', - .name = "version", - .expr_name = "string", - .desc = "Program version." }, - }, - .prog_name = "usb descriptors", -}; - -void -main() -{ - string[dim(argv)-1] nargv = {[n] = argv[n+1]}; - parseargs(&argd, &nargv); - write_ucs2(manufacturer, "iManufacturer"); - write_ucs2(product, "iProduct"); - write_ucs2(sprintf("%06d", serial), "iSerial"); - write_int(serial, "iSerial"); - write_hex(id_product, "idProduct"); - write_string(version, "iVersion"); -} - -main(); diff --git a/src/ao.h b/src/ao.h deleted file mode 100644 index 8ac9ac3d..00000000 --- a/src/ao.h +++ /dev/null @@ -1,1610 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_H_ -#define _AO_H_ - -#include -#include -#include -#include -#include "cc1111.h" -#include "ao_pins.h" - -#define TRUE 1 -#define FALSE 0 - -/* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* Stack runs from above the allocated __data space to 0xfe, which avoids - * writing to 0xff as that triggers the stack overflow indicator - */ -#define AO_STACK_START 0x90 -#define AO_STACK_END 0xfe -#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) - -/* An AltOS task */ -struct ao_task { - __xdata void *wchan; /* current wait channel (NULL if running) */ - uint16_t alarm; /* abort ao_sleep time */ - uint8_t stack_count; /* amount of saved stack */ - uint8_t task_id; /* unique id */ - __code char *name; /* task name */ - uint8_t stack[AO_STACK_SIZE]; /* saved stack */ -}; - -extern __xdata struct ao_task *__data ao_cur_task; - -#define AO_NUM_TASKS 16 /* maximum number of tasks */ -#define AO_NO_TASK 0 /* no task id */ - -/* - ao_task.c - */ - -/* Suspend the current task until wchan is awoken. - * returns: - * 0 on normal wake - * 1 on alarm - */ -uint8_t -ao_sleep(__xdata void *wchan); - -/* Wake all tasks sleeping on wchan */ -void -ao_wakeup(__xdata void *wchan); - -/* set an alarm to go off in 'delay' ticks */ -void -ao_alarm(uint16_t delay); - -/* Yield the processor to another task */ -void -ao_yield(void) __naked; - -/* Add a task to the run queue */ -void -ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; - -/* Terminate the current task */ -void -ao_exit(void); - -/* Dump task info to console */ -void -ao_task_info(void); - -/* Start the scheduler. This will not return */ -void -ao_start_scheduler(void); - -/* - * ao_panic.c - */ - -#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */ -#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */ -#define AO_PANIC_MUTEX 3 /* Mis-using mutex API */ -#define AO_PANIC_EE 4 /* Mis-using eeprom API */ -#define AO_PANIC_LOG 5 /* Failing to read/write log data */ -#define AO_PANIC_CMD 6 /* Too many command sets registered */ -#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ -#define AO_PANIC_REBOOT 8 /* Reboot failed */ -#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ -#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ -#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ - -/* Stop the operating system, beeping and blinking the reason */ -void -ao_panic(uint8_t reason); - -/* - * ao_timer.c - */ - -/* Our timer runs at 100Hz */ -#define AO_HERTZ 100 -#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) -#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) - -/* Returns the current time in ticks */ -uint16_t -ao_time(void); - -/* Suspend the current task until ticks time has passed */ -void -ao_delay(uint16_t ticks); - -/* Set the ADC interval */ -void -ao_timer_set_adc_interval(uint8_t interval) __critical; - -/* Timer interrupt */ -void -ao_timer_isr(void) __interrupt 9; - -/* Initialize the timer */ -void -ao_timer_init(void); - -/* Initialize the hardware clock. Must be called first */ -void -ao_clock_init(void); - -/* - * One set of samples read from the A/D converter or telemetry - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#if HAS_ADC - -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif - -/* - * ao_adc.c - */ - -#define AO_ADC_RING 32 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif - -/* Trigger a conversion sequence (called from the timer interrupt) */ -void -ao_adc_poll(void); - -/* Suspend the current task until another A/D sample is converted */ -void -ao_adc_sleep(void); - -/* Get a copy of the last complete A/D sample set */ -void -ao_adc_get(__xdata struct ao_adc *packet); - -/* The A/D interrupt handler */ - -void -ao_adc_isr(void) __interrupt 1; - -/* Initialize the A/D converter */ -void -ao_adc_init(void); - -#endif /* HAS_ADC */ - -/* - * ao_beep.c - */ - -/* - * Various pre-defined beep frequencies - * - * frequency = 1/2 (24e6/32) / beep - */ - -#define AO_BEEP_LOW 150 /* 2500Hz */ -#define AO_BEEP_MID 94 /* 3989Hz */ -#define AO_BEEP_HIGH 75 /* 5000Hz */ -#define AO_BEEP_OFF 0 /* off */ - -#define AO_BEEP_g 240 /* 1562.5Hz */ -#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ -#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ -#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ -#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ -#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ -#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ -#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ -#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ -#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ -#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ -#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ -#define AO_BEEP_gg 120 /* 3125Hz */ -#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ -#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ -#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ -#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ -#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ -#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ -#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ -#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ -#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ -#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ -#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ -#define AO_BEEP_ggg 60 /* 6250Hz */ - -/* Set the beeper to the specified tone */ -void -ao_beep(uint8_t beep); - -/* Turn on the beeper for the specified time */ -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; - -/* Initialize the beeper */ -void -ao_beep_init(void); - -/* - * ao_led.c - */ - -#define AO_LED_NONE 0 - -/* Turn on the specified LEDs */ -void -ao_led_on(uint8_t colors); - -/* Turn off the specified LEDs */ -void -ao_led_off(uint8_t colors); - -/* Set all of the LEDs to the specified state */ -void -ao_led_set(uint8_t colors); - -/* Toggle the specified LEDs */ -void -ao_led_toggle(uint8_t colors); - -/* Turn on the specified LEDs for the indicated interval */ -void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; - -/* Initialize the LEDs */ -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; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - -/* - * ao_usb.c - */ - -/* Put one character to the USB output queue */ -void -ao_usb_putchar(char c); - -/* Get one character from the USB input queue */ -char -ao_usb_getchar(void); - -/* Poll for a charcter on the USB input queue. - * returns AO_READ_AGAIN if none are available - */ -char -ao_usb_pollchar(void); - -/* Flush the USB output queue */ -void -ao_usb_flush(void); - -#if HAS_USB -/* USB interrupt handler */ -void -ao_usb_isr(void) __interrupt 6; -#endif - -/* Enable the USB controller */ -void -ao_usb_enable(void); - -/* Disable the USB controller */ -void -ao_usb_disable(void); - -/* Initialize the USB system */ -void -ao_usb_init(void); - -/* - * ao_cmd.c - */ - -enum ao_cmd_status { - ao_cmd_success = 0, - ao_cmd_lex_error = 1, - ao_cmd_syntax_error = 2, -}; - -extern __pdata uint16_t ao_cmd_lex_i; -extern __pdata uint32_t ao_cmd_lex_u32; -extern __pdata char ao_cmd_lex_c; -extern __pdata enum ao_cmd_status ao_cmd_status; - -void -ao_cmd_lex(void); - -void -ao_cmd_put8(uint8_t v); - -void -ao_cmd_put16(uint16_t v); - -void -ao_cmd_white(void); - -void -ao_cmd_hex(void); - -void -ao_cmd_decimal(void); - -uint8_t -ao_match_word(__code char *word); - -struct ao_cmds { - void (*func)(void); - __code char *help; -}; - -void -ao_cmd_register(__code struct ao_cmds *cmds); - -void -ao_cmd_init(void); - -#if HAS_CMD_FILTER -/* - * Provided by an external module to filter raw command lines - */ -uint8_t -ao_cmd_filter(void); -#endif - -/* - * ao_dma.c - */ - -/* Allocate a DMA channel. the 'done' parameter will be set when the - * dma is finished and will be used to wakeup any waiters - */ - -uint8_t -ao_dma_alloc(__xdata uint8_t * done); - -/* Setup a DMA channel */ -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1); - -/* Start a DMA channel */ -void -ao_dma_start(uint8_t id); - -/* Manually trigger a DMA channel */ -void -ao_dma_trigger(uint8_t id); - -/* Abort a running DMA transfer */ -void -ao_dma_abort(uint8_t id); - -/* DMA interrupt routine */ -void -ao_dma_isr(void) __interrupt 8; - -/* - * ao_mutex.c - */ - -void -ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; - -void -ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; - -/* - * Storage interface, provided by one of the eeprom or flash - * drivers - */ - -/* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __pdata uint16_t ao_storage_unit; - -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - -/* Initialize above values. Can only be called once the OS is running */ -void -ao_storage_setup(void) __reentrant; - -/* Write data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Read data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Erase a block of storage. This always clears ao_storage_block bytes */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant; - -/* Flush any pending writes to stable storage */ -void -ao_storage_flush(void) __reentrant; - -/* Initialize the storage code */ -void -ao_storage_init(void); - -/* - * Low-level functions wrapped by ao_storage.c - */ - -/* Read data within a storage unit */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Write data within a storage unit */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Initialize low-level device bits */ -void -ao_storage_device_init(void); - -/* Print out information about flash chips */ -void -ao_storage_device_info(void) __reentrant; - -/* - * ao_log.c - */ - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -extern __pdata uint32_t ao_log_current_pos; -extern __pdata uint32_t ao_log_end_pos; -extern __pdata uint32_t ao_log_start_pos; -extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; - -/* required functions from the underlying log system */ - -#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ -#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ -#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ -#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ -#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_NONE 127 /* No log at all */ - -extern __code uint8_t ao_log_format; - -/* Return the flight number from the given log slot, 0 if none */ -uint16_t -ao_log_flight(uint8_t slot); - -/* Flush the log */ -void -ao_log_flush(void); - -/* Logging thread main routine */ -void -ao_log(void); - -/* functions provided in ao_log.c */ - -/* Figure out the current flight number */ -void -ao_log_scan(void) __reentrant; - -/* Return the position of the start of the given log slot */ -uint32_t -ao_log_pos(uint8_t slot); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - -/* - * ao_log_big.c - */ - -/* - * The data log is recorded in the eeprom as a sequence - * of data packets. - * - * Each packet starts with a 4-byte header that has the - * packet type, the packet checksum and the tick count. Then - * they all contain 2 16 bit values which hold packet-specific - * data. - * - * For each flight, the first packet - * is FLIGHT packet, indicating the serial number of the - * device and a unique number marking the number of flights - * recorded by this device. - * - * During flight, data from the accelerometer and barometer - * are recorded in SENSOR packets, using the raw 16-bit values - * read from the A/D converter. - * - * Also during flight, but at a lower rate, the deployment - * sensors are recorded in DEPLOY packets. The goal here is to - * detect failure in the deployment circuits. - * - * STATE packets hold state transitions as the flight computer - * transitions through different stages of the flight. - */ -#define AO_LOG_FLIGHT 'F' -#define AO_LOG_SENSOR 'A' -#define AO_LOG_TEMP_VOLT 'T' -#define AO_LOG_DEPLOY 'D' -#define AO_LOG_STATE 'S' -#define AO_LOG_GPS_TIME 'G' -#define AO_LOG_GPS_LAT 'N' -#define AO_LOG_GPS_LON 'W' -#define AO_LOG_GPS_ALT 'H' -#define AO_LOG_GPS_SAT 'V' -#define AO_LOG_GPS_DATE 'Y' - -#define AO_LOG_POS_NONE (~0UL) - -struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; - union { - struct { - int16_t ground_accel; - uint16_t flight; - } flight; - struct { - int16_t accel; - int16_t pres; - } sensor; - struct { - int16_t temp; - int16_t v_batt; - } temp_volt; - struct { - int16_t drogue; - int16_t main; - } deploy; - struct { - uint16_t state; - uint16_t reason; - } state; - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - } gps_time; - int32_t gps_latitude; - int32_t gps_longitude; - struct { - int16_t altitude; - uint16_t unused; - } gps_altitude; - struct { - uint16_t svid; - uint8_t unused; - uint8_t c_n; - } gps_sat; - struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t extra; - } gps_date; - struct { - uint16_t d0; - uint16_t d1; - } anon; - } u; -}; - -/* Write a record to the eeprom log */ -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant; - -/* - * ao_flight.c - */ - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern __pdata enum ao_flight_state ao_flight_state; - -extern __pdata uint16_t ao_launch_time; -extern __pdata uint8_t ao_flight_force_idle; - -/* Flight thread */ -void -ao_flight(void); - -/* Initialize flight thread */ -void -ao_flight_init(void); - -/* - * ao_flight_nano.c - */ - -void -ao_flight_nano_init(void); - -/* - * ao_sample.c - */ - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -/* - * Speed and acceleration are scaled by 16 to provide a bit more - * resolution while still having reasonable range. Note that this - * limits speed to 2047m/s (around mach 6) and acceleration to - * 2047m/s² (over 200g) - */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ -extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ - -#if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ -#endif - -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -void ao_sample_init(void); - -/* returns FALSE in preflight mode, TRUE in flight mode */ -uint8_t ao_sample(void); - -/* - * ao_kalman.c - */ - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ - -extern __pdata int16_t ao_error_h; -extern __pdata int16_t ao_error_h_sq_avg; - -#if HAS_ACCEL -extern __pdata int16_t ao_error_a; -#endif - -void ao_kalman(void); - -/* - * ao_report.c - */ - -void -ao_report_init(void); - -/* - * ao_convert.c - * - * Given raw data, convert to SI units - */ - -/* pressure from the sensor to altitude in meters */ -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant; - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant; - -int16_t -ao_temp_to_dC(int16_t temp) __reentrant; - -/* - * ao_dbg.c - * - * debug another telemetrum board - */ - -/* Send a byte to the dbg target */ -void -ao_dbg_send_byte(uint8_t byte); - -/* Receive a byte from the dbg target */ -uint8_t -ao_dbg_recv_byte(void); - -/* Start a bulk transfer to/from dbg target memory */ -void -ao_dbg_start_transfer(uint16_t addr); - -/* End a bulk transfer to/from dbg target memory */ -void -ao_dbg_end_transfer(void); - -/* Write a byte to dbg target memory */ -void -ao_dbg_write_byte(uint8_t byte); - -/* Read a byte from dbg target memory */ -uint8_t -ao_dbg_read_byte(void); - -/* Enable dbg mode, switching use of the pins */ -void -ao_dbg_debug_mode(void); - -/* Reset the dbg target */ -void -ao_dbg_reset(void); - -void -ao_dbg_init(void); - -/* - * ao_serial.c - */ - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#if HAS_SERIAL_1 -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -void -ao_serial_rx1_isr(void) __interrupt 3; - -void -ao_serial_tx1_isr(void) __interrupt 14; - -char -ao_serial_getchar(void) __critical; - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical; - -void -ao_serial_set_stdin(uint8_t stdin); -#endif - -void -ao_serial_putchar(char c) __critical; - -void -ao_serial_drain(void) __critical; - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_19200 2 -#define AO_SERIAL_SPEED_57600 3 - -void -ao_serial_set_speed(uint8_t speed); - -void -ao_serial_init(void); -#endif - -/* - * ao_spi.c - */ - -extern __xdata uint8_t ao_spi_mutex; - -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ - } while (0) - -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ - } while (0) - -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -/* - * The SPI mutex must be held to call either of these - * functions -- this mutex covers the entire SPI operation, - * from chip select low to chip select high - */ - -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_init(void); - -/* - * ao_telemetry.c - */ -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#define AO_MAX_TELEMETRY 128 - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10â·) */ - int32_t longitude; /* 12 longitude (degrees * 10â·) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -#define AO_TELEMETRY_COMPANION 0x07 - -#define AO_COMPANION_MAX_CHANNELS 12 - -struct ao_telemetry_companion { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t board_id; /* 5 */ - - uint8_t update_period; /* 6 */ - uint8_t channels; /* 7 */ - uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; - struct ao_telemetry_companion companion; -}; - -/* - * ao_gps.c - */ - -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -extern __pdata uint16_t ao_gps_tick; -extern __xdata uint8_t ao_gps_mutex; -extern __xdata struct ao_telemetry_location ao_gps_data; -extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10â· */ - int32_t longitude; /* degrees * 10â· */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -void -ao_gps(void); - -void -ao_gps_print(__xdata struct ao_gps_orig *gps_data); - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); - -void -ao_gps_init(void); - -/* - * ao_gps_report.c - */ - -void -ao_gps_report(void); - -void -ao_gps_report_init(void); - -/* - * ao_telemetry_orig.c - */ - -struct ao_telemetry_orig { - uint16_t serial; - uint16_t flight; - uint8_t flight_state; - int16_t accel; - int16_t ground_accel; - union { - struct { - int16_t speed; - int16_t unused; - } k; - int32_t flight_vel; - } u; - int16_t height; - int16_t ground_pres; - int16_t accel_plus_g; - int16_t accel_minus_g; - struct ao_adc adc; - struct ao_gps_orig gps; - char callsign[AO_MAX_CALLSIGN]; - struct ao_gps_tracking_orig gps_tracking; -}; - -struct ao_telemetry_tiny { - uint16_t serial; - uint16_t flight; - uint8_t flight_state; - int16_t height; /* AGL in meters */ - int16_t speed; /* in m/s * 16 */ - int16_t accel; /* in m/s² * 16 */ - int16_t ground_pres; /* sensor units */ - struct ao_adc adc; /* raw ADC readings */ - char callsign[AO_MAX_CALLSIGN]; -}; - -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { - uint8_t packet[AO_MAX_TELEMETRY + 2]; -}; - -struct ao_telemetry_orig_recv { - struct ao_telemetry_orig telemetry_orig; - int8_t rssi; - uint8_t status; -}; - -struct ao_telemetry_tiny_recv { - struct ao_telemetry_tiny telemetry_tiny; - int8_t rssi; - uint8_t status; -}; - -/* Set delay between telemetry reports (0 to disable) */ - -#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) -#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) -#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) - -void -ao_telemetry_set_interval(uint16_t interval); - -void -ao_rdf_set(uint8_t rdf); - -void -ao_telemetry_init(void); - -void -ao_telemetry_orig_init(void); - -void -ao_telemetry_tiny_init(void); - -/* - * ao_radio.c - */ - -extern __xdata uint8_t ao_radio_dma; -extern __xdata uint8_t ao_radio_dma_done; -extern __xdata uint8_t ao_radio_done; -extern __xdata uint8_t ao_radio_mutex; - -void -ao_radio_general_isr(void) __interrupt 16; - -void -ao_radio_get(uint8_t len); - -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) - -void -ao_radio_set_packet(void); - -void -ao_radio_send(__xdata void *data, uint8_t size) __reentrant; - -uint8_t -ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; - -void -ao_radio_recv_abort(void); - -void -ao_radio_rdf(int ms); - -void -ao_radio_rdf_abort(void); - -void -ao_radio_idle(void); - -void -ao_radio_init(void); - -/* - * ao_monitor.c - */ - -extern const char const * const ao_state_names[]; - -void -ao_monitor(void); - -#define AO_MONITORING_OFF 0 -#define AO_MONITORING_ORIG 1 -#define AO_MONITORING_TINY 2 - -void -ao_set_monitor(uint8_t monitoring); - -void -ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; - -/* - * ao_stdio.c - */ - -#define AO_READ_AGAIN ((char) -1) - -struct ao_stdio { - char (*pollchar)(void); - void (*putchar)(char c) __reentrant; - void (*flush)(void); - uint8_t echo; -}; - -extern __xdata struct ao_stdio ao_stdios[]; -extern __pdata int8_t ao_cur_stdio; -extern __pdata int8_t ao_num_stdios; - -void -flush(void); - -extern __xdata uint8_t ao_stdin_ready; - -uint8_t -ao_echo(void); - -int8_t -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char) __reentrant, - void (*flush)(void)) __reentrant; - -/* - * ao_ignite.c - */ - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -void -ao_ignite(enum ao_igniter igniter); - -enum ao_igniter_status { - ao_igniter_unknown, /* unknown status (ambiguous voltage) */ - ao_igniter_ready, /* continuity detected */ - ao_igniter_active, /* igniter firing */ - ao_igniter_open, /* open circuit detected */ -}; - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter); - -void -ao_ignite_set_pins(void); - -void -ao_igniter_init(void); - -/* - * ao_config.c - */ - -#define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 8 - -struct ao_config { - uint8_t major; - uint8_t minor; - uint16_t main_deploy; - int16_t accel_plus_g; /* changed for minor version 2 */ - uint8_t radio_channel; - char callsign[AO_MAX_CALLSIGN + 1]; - uint8_t apogee_delay; /* minor version 1 */ - int16_t accel_minus_g; /* minor version 2 */ - uint32_t radio_cal; /* minor version 3 */ - uint32_t flight_log_max; /* minor version 4 */ - uint8_t ignite_mode; /* minor version 5 */ - uint8_t pad_orientation; /* minor version 6 */ - uint32_t radio_setting; /* minor version 7 */ - uint8_t radio_enable; /* minor version 8 */ -}; - -#define AO_IGNITE_MODE_DUAL 0 -#define AO_IGNITE_MODE_APOGEE 1 -#define AO_IGNITE_MODE_MAIN 2 - -#define AO_PAD_ORIENTATION_ANTENNA_UP 0 -#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 - -extern __xdata struct ao_config ao_config; - -#define AO_CONFIG_MAX_SIZE 128 - -void -ao_config_get(void); - -void -ao_config_put(void); - -void -ao_config_init(void); - -/* - * ao_rssi.c - */ - -void -ao_rssi_set(int rssi_value); - -void -ao_rssi_init(uint8_t rssi_led); - -/* - * ao_product.c - * - * values which need to be defined for - * each instance of a product - */ - -extern const char ao_version[]; -extern const char ao_manufacturer[]; -extern const char ao_product[]; - -/* - * Fifos - */ - -#define AO_FIFO_SIZE 32 - -struct ao_fifo { - uint8_t insert; - uint8_t remove; - char fifo[AO_FIFO_SIZE]; -}; - -#define ao_fifo_insert(f,c) do { \ - (f).fifo[(f).insert] = (c); \ - (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \ -} while(0) - -#define ao_fifo_remove(f,c) do {\ - c = (f).fifo[(f).remove]; \ - (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ -} while(0) - -#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) -#define ao_fifo_empty(f) ((f).insert == (f).remove) - -/* - * ao_packet.c - * - * Packet-based command interface - */ - -#define AO_PACKET_MAX 64 -#define AO_PACKET_SYN (uint8_t) 0xff - -struct ao_packet { - uint8_t addr; - uint8_t len; - uint8_t seq; - uint8_t ack; - uint8_t d[AO_PACKET_MAX]; - uint8_t callsign[AO_MAX_CALLSIGN]; -}; - -struct ao_packet_recv { - struct ao_packet packet; - int8_t rssi; - uint8_t status; -}; - -extern __xdata struct ao_packet_recv ao_rx_packet; -extern __xdata struct ao_packet ao_tx_packet; -extern __xdata struct ao_task ao_packet_task; -extern __xdata uint8_t ao_packet_enable; -extern __xdata uint8_t ao_packet_master_sleeping; -extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -void -ao_packet_send(void); - -uint8_t -ao_packet_recv(void); - -void -ao_packet_flush(void); - -void -ao_packet_putchar(char c) __reentrant; - -char -ao_packet_pollchar(void) __critical; - -/* ao_packet_master.c */ - -void -ao_packet_master_init(void); - -/* ao_packet_slave.c */ - -void -ao_packet_slave_start(void); - -void -ao_packet_slave_stop(void); - -void -ao_packet_slave_init(uint8_t enable); - -/* ao_btm.c */ - -/* If bt_link is on P2, this interrupt is shared by USB, so the USB - * code calls this function. Otherwise, it's a regular ISR. - */ - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 -#endif - ; - -void -ao_btm_init(void); - -/* ao_companion.c */ - -#define AO_COMPANION_SETUP 1 -#define AO_COMPANION_FETCH 2 -#define AO_COMPANION_NOTIFY 3 - -struct ao_companion_command { - uint8_t command; - uint8_t flight_state; - uint16_t tick; - uint16_t serial; - uint16_t flight; -}; - -struct ao_companion_setup { - uint16_t board_id; - uint16_t board_id_inverse; - uint8_t update_period; - uint8_t channels; -}; - -extern __pdata uint8_t ao_companion_running; -extern __xdata struct ao_companion_setup ao_companion_setup; -extern __xdata uint8_t ao_companion_mutex; -extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; - -void -ao_companion_init(void); - -#endif /* _AO_H_ */ diff --git a/src/ao_adc.c b/src/ao_adc.c deleted file mode 100644 index 786dfd11..00000000 --- a/src/ao_adc.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -#if HAS_ACCEL_REF -volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -volatile __data uint8_t ao_adc_head; - -void -ao_adc_poll(void) -{ -#if HAS_ACCEL_REF - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; -#else -# ifdef TELENANO_V_0_1 - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; -# else - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; -# endif -#endif -} - -void -ao_adc_get(__xdata struct ao_adc *packet) -{ - uint8_t i = ao_adc_ring_prev(ao_sample_adc); - memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); -} - -void -ao_adc_isr(void) __interrupt 1 -{ - uint8_t sequence; - uint8_t __xdata *a; - - sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; -#if IGNITE_ON_P2 - /* TeleMetrum readings */ -#if HAS_ACCEL_REF - if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); - sequence = 0; - } else -#endif - { - if (sequence == ADCCON3_ECH_TEMP) - sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); - sequence++; - } -#define GOT_ADC - a[0] = ADCL; - a[1] = ADCH; - if (sequence < 6) { -#if HAS_EXTERNAL_TEMP == 0 - /* start next channel conversion */ - /* v0.2 replaces external temp sensor with internal one */ - if (sequence == 2) - ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - else -#endif - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; - } -#endif - -#if IGNITE_ON_P0 - /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); -#ifdef TELEMINI_V_1_0 - switch (sequence) { - case 0: - /* pressure */ - a += 0; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; - break; - case 1: - /* drogue sense */ - a += 6; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; - break; - case 2: - /* main sense */ - a += 8; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; - break; - case 3: - /* battery */ - a += 4; - sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - break; - case ADCCON3_ECH_TEMP: - a += 2; - sequence = 0; - break; - } -#define GOT_ADC -#endif -#ifdef TELENANO_V_0_1 - switch (sequence) { - case 1: - /* pressure */ - a += 0; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; - break; - case 3: - /* battery */ - a += 4; - sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - break; - case ADCCON3_ECH_TEMP: - a += 2; - sequence = 0; - break; - } -#define GOT_ADC -#endif - a[0] = ADCL; - a[1] = ADCH; - if (sequence) { - /* Start next conversion */ - ADCCON3 = sequence; - } -#endif -#ifndef GOT_ADC -#error No known ADC configuration set -#endif - - else { - /* record this conversion series */ - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); - } -} - -static void -ao_adc_dump(void) __reentrant -{ - static __xdata struct ao_adc packet; - ao_adc_get(&packet); - printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", - packet.tick, packet.accel, packet.pres, packet.temp, - packet.v_batt, packet.sense_d, packet.sense_m); -} - -__code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Current ADC" }, - { 0, NULL }, -}; - -void -ao_adc_init(void) -{ -#if IGNITE_ON_P2 - /* TeleMetrum configuration */ - ADCCFG = ((1 << 0) | /* acceleration */ - (1 << 1) | /* pressure */ -#if HAS_EXTERNAL_TEMP - (1 << 2) | /* v0.1 temperature */ -#endif - (1 << 3) | /* battery voltage */ - (1 << 4) | /* drogue sense */ - (1 << 5)); /* main sense */ -#endif - -#if IGNITE_ON_P0 - /* TeleMini configuration */ - ADCCFG = ((1 << 0) | /* pressure */ - (1 << 1) | /* drogue sense */ - (1 << 2) | /* main sense */ - (1 << 3)); /* battery voltage */ -#endif - - /* enable interrupts */ - ADCIF = 0; - IEN0 |= IEN0_ADCIE; - ao_cmd_register(&ao_adc_cmds[0]); -} diff --git a/src/ao_adc_fake.c b/src/ao_adc_fake.c deleted file mode 100644 index 6ca88d4e..00000000 --- a/src/ao_adc_fake.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; - -/* Stub for systems which have no ADC */ -void -ao_adc_poll(void) -{ -} diff --git a/src/ao_beep.c b/src/ao_beep.c deleted file mode 100644 index 3642f4c6..00000000 --- a/src/ao_beep.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -ao_beep(uint8_t beep) -{ - if (beep == 0) { - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - T4CTL = 0; - } else { - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; - T4CC0 = beep; - T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; - } -} - -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant -{ - ao_beep(beep); - ao_delay(ticks); - ao_beep(0); -} - -void -ao_beep_init(void) -{ - /* Our beeper is on P2_0, which is hooked to timer 4 using - * configuration alternative 2 - */ - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; - T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; -} diff --git a/src/ao_btm.c b/src/ao_btm.c deleted file mode 100644 index 44155ec1..00000000 --- a/src/ao_btm.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -int8_t ao_btm_stdio; -__xdata uint8_t ao_btm_connected; - -#define AO_BTM_MAX_REPLY 16 -__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; - -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; - -/* - * Read a line of data from the serial port, truncating - * it after a few characters. - */ - -uint8_t -ao_btm_get_line(void) -{ - uint8_t ao_btm_reply_len = 0; - char c; - - for (;;) { - - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { - if (ao_btm_reply_len < sizeof (ao_btm_reply)) - ao_btm_reply[ao_btm_reply_len++] = c; - if (c == '\r' || c == '\n') - goto done; - } - for (c = 0; c < 10; c++) { - ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) - break; - } - if (c == 10) - goto done; - } -done: - for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) - ao_btm_reply[c++] = '\0'; - return ao_btm_reply_len; -} - -/* - * Drain the serial port completely - */ -void -ao_btm_drain() -{ - while (ao_btm_get_line()) - ; -} - -/* - * Set the stdio echo for the bluetooth link - */ -void -ao_btm_echo(uint8_t echo) -{ - ao_stdios[ao_btm_stdio].echo = echo; -} - -/* - * Delay between command charaters; the BT module - * can't keep up with 57600 baud - */ - -void -ao_btm_putchar(char c) -{ - ao_serial_putchar(c); - ao_delay(1); -} - -/* - * Wait for the bluetooth device to return - * status from the previously executed command - */ -uint8_t -ao_btm_wait_reply(void) -{ - for (;;) { - ao_btm_get_line(); - if (!strncmp(ao_btm_reply, "OK", 2)) - return 1; - if (!strncmp(ao_btm_reply, "ERROR", 5)) - return -1; - if (ao_btm_reply[0] == '\0') - return 0; - } -} - -void -ao_btm_string(__code char *cmd) -{ - char c; - - while (c = *cmd++) - ao_btm_putchar(c); -} - -uint8_t -ao_btm_cmd(__code char *cmd) -{ - ao_btm_drain(); - ao_btm_string(cmd); - return ao_btm_wait_reply(); -} - -uint8_t -ao_btm_set_name(void) -{ - char sn[8]; - char *s = sn + 8; - char c; - int n; - ao_btm_string("ATN=TeleBT-"); - *--s = '\0'; - *--s = '\r'; - n = ao_serial_number; - do { - *--s = '0' + n % 10; - } while (n /= 10); - while ((c = *s++)) - ao_btm_putchar(c); - return ao_btm_wait_reply(); -} - -uint8_t -ao_btm_try_speed(uint8_t speed) -{ - ao_serial_set_speed(speed); - ao_btm_drain(); - (void) ao_btm_cmd("\rATE0\rATQ0\r"); - if (ao_btm_cmd("AT\r") == 1) - return 1; - return 0; -} - -/* - * A thread to initialize the bluetooth device and - * hang around to blink the LED when connected - */ -void -ao_btm(void) -{ - /* - * Wait for the bluetooth device to boot - */ - ao_delay(AO_SEC_TO_TICKS(3)); - -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - - /* - * The first time we connect, the BTM-180 comes up at 19200 baud. - * After that, it will remember and come up at 57600 baud. So, see - * if it is already running at 57600 baud, and if that doesn't work - * then tell it to switch to 57600 from 19200 baud. - */ - while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { - ao_delay(AO_SEC_TO_TICKS(1)); - if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) - ao_btm_cmd("ATL4\r"); - ao_delay(AO_SEC_TO_TICKS(1)); - } - - /* Disable echo */ - ao_btm_cmd("ATE0\r"); - - /* Enable flow control */ - ao_btm_cmd("ATC1\r"); - - /* Set the reported name to something we can find on the host */ - ao_btm_set_name(); - - /* Turn off status reporting */ - ao_btm_cmd("ATQ1\r"); - - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); - ao_btm_echo(0); - - for (;;) { - while (!ao_btm_connected) - ao_sleep(&ao_btm_connected); - while (ao_btm_connected) { - ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); - ao_delay(AO_SEC_TO_TICKS(3)); - } - } -} - -__xdata struct ao_task ao_btm_task; - -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - -void -ao_btm_check_link() __critical -{ - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } -} - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 -#endif -{ -#if BT_LINK_ON_P1 - P1IF = 0; -#endif - if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { - ao_btm_check_link(); - ao_wakeup(&ao_btm_connected); - } - BT_PIFG = 0; -} - -void -ao_btm_init (void) -{ - ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); - -#if BT_LINK_ON_P1 - /* - * Configure ser reset line - */ - - P1_6 = 0; - P1DIR |= (1 << 6); -#endif - - /* - * Configure link status line - */ - - /* Set pin to input */ - BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); - - /* Set pin to tri-state */ - BT_PINP |= (1 << BT_LINK_PIN_INDEX); - - /* Enable interrupts */ - IEN2 |= BT_IEN2_PIE; - - /* Check current pin state */ - ao_btm_check_link(); - -#if BT_LINK_ON_P2 - /* Eable the pin interrupt */ - PICTL |= PICTL_P2IEN; -#endif -#if BT_LINK_ON_P1 - /* Enable pin interrupt */ - P1IEN |= (1 << BT_LINK_PIN_INDEX); -#endif - - ao_add_task(&ao_btm_task, ao_btm, "bt"); -} diff --git a/src/ao_cmd.c b/src/ao_cmd.c deleted file mode 100644 index 1442ebea..00000000 --- a/src/ao_cmd.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__pdata uint16_t ao_cmd_lex_i; -__pdata uint32_t ao_cmd_lex_u32; -__pdata char ao_cmd_lex_c; -__pdata enum ao_cmd_status ao_cmd_status; - -#define CMD_LEN 32 - -static __xdata char cmd_line[CMD_LEN]; -static __pdata uint8_t cmd_len; -static __pdata uint8_t cmd_i; - -static void -put_string(__code char *s) -{ - char c; - while (c = *s++) - putchar(c); -} - -static void -readline(void) -{ - __pdata char c; - if (ao_echo()) - put_string("> "); - cmd_len = 0; - for (;;) { - flush(); - c = getchar(); - /* backspace/delete */ - if (c == '\010' || c == '\177') { - if (cmd_len != 0) { - if (ao_echo()) - put_string("\010 \010"); - --cmd_len; - } - continue; - } - - /* ^U */ - if (c == '\025') { - while (cmd_len != 0) { - if (ao_echo()) - put_string("\010 \010"); - --cmd_len; - } - continue; - } - - /* map CR to NL */ - if (c == '\r') - c = '\n'; - - if (c == '\n') { - if (ao_echo()) - putchar('\n'); - break; - } - - if (cmd_len >= CMD_LEN - 2) { - if (ao_echo()) - putchar('\007'); - continue; - } - cmd_line[cmd_len++] = c; - if (ao_echo()) - putchar(c); - } - cmd_line[cmd_len++] = '\n'; - cmd_line[cmd_len++] = '\0'; - cmd_i = 0; -} - -void -ao_cmd_lex(void) -{ - ao_cmd_lex_c = '\n'; - if (cmd_i < cmd_len) - ao_cmd_lex_c = cmd_line[cmd_i++]; -} - -static void -putnibble(uint8_t v) -{ - if (v < 10) - putchar(v + '0'); - else - putchar(v + ('a' - 10)); -} - -void -ao_cmd_put16(uint16_t v) -{ - ao_cmd_put8(v >> 8); - ao_cmd_put8(v); -} - -void -ao_cmd_put8(uint8_t v) -{ - putnibble((v >> 4) & 0xf); - putnibble(v & 0xf); -} - -void -ao_cmd_white(void) -{ - while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') - ao_cmd_lex(); -} - -void -ao_cmd_hex(void) -{ - __pdata uint8_t r = ao_cmd_lex_error; - uint8_t n; - - ao_cmd_lex_i = 0; - ao_cmd_white(); - for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - n = (ao_cmd_lex_c - '0'); - else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - n = (ao_cmd_lex_c - 'a' + 10); - else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - n = (ao_cmd_lex_c - 'A' + 10); - else - break; - ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; - r = ao_cmd_success; - ao_cmd_lex(); - } - if (r != ao_cmd_success) - ao_cmd_status = r; -} - -void -ao_cmd_decimal(void) -{ - __pdata uint8_t r = ao_cmd_lex_error; - - ao_cmd_lex_u32 = 0; - ao_cmd_white(); - for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); - else - break; - r = ao_cmd_success; - ao_cmd_lex(); - } - if (r != ao_cmd_success) - ao_cmd_status = r; - ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; -} - -uint8_t -ao_match_word(__code char *word) -{ - while (*word) { - if (ao_cmd_lex_c != *word) { - ao_cmd_status = ao_cmd_syntax_error; - return 0; - } - word++; - ao_cmd_lex(); - } - return 1; -} - -static void -eol(void) -{ - while (ao_cmd_lex_c != '\n') - ao_cmd_lex(); -} - -static void -echo(void) -{ - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) - ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; -} - -static void -ao_reboot(void) -{ - ao_cmd_white(); - if (!ao_match_word("eboot")) - return; - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_delay(AO_SEC_TO_TICKS(2)); - ao_panic(AO_PANIC_REBOOT); -} - -static void -version(void) -{ - printf("manufacturer %s\n", ao_manufacturer); - printf("product %s\n", ao_product); - printf("serial-number %u\n", ao_serial_number); -#if HAS_EEPROM - printf("log-format %u\n", ao_log_format); -#endif - printf("software-version %s\n", ao_version); -} - -#define NUM_CMDS 11 - -static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); -static __pdata uint8_t ao_ncmds; - -static void -help(void) -{ - register uint8_t cmds; - register uint8_t cmd; - register __code struct ao_cmds * cs; - - for (cmds = 0; cmds < ao_ncmds; cmds++) { - cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); - } -} - -static void -report(void) -{ - switch(ao_cmd_status) { - case ao_cmd_lex_error: - case ao_cmd_syntax_error: - puts("Syntax error"); - ao_cmd_status = 0; - break; - } -} - -void -ao_cmd_register(__code struct ao_cmds *cmds) -{ - if (ao_ncmds >= NUM_CMDS) - ao_panic(AO_PANIC_CMD); - ao_cmds[ao_ncmds++] = cmds; -} - -void -ao_cmd(void) -{ - char c; - uint8_t cmd, cmds; - __code struct ao_cmds * __xdata cs; - void (*__xdata func)(void); - - for (;;) { - readline(); - ao_cmd_lex(); - ao_cmd_white(); - c = ao_cmd_lex_c; - ao_cmd_lex(); - if (c == '\r' || c == '\n') - continue; - func = (void (*)(void)) NULL; - for (cmds = 0; cmds < ao_ncmds; cmds++) { - cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - if (cs[cmd].help[0] == c) { - func = cs[cmd].func; - break; - } - if (func) - break; - } - if (func) - (*func)(); - else - ao_cmd_status = ao_cmd_syntax_error; - report(); - } -} - -__xdata struct ao_task ao_cmd_task; - -__code struct ao_cmds ao_base_cmds[] = { - { help, "?\0Help" }, - { ao_task_info, "T\0Show tasks" }, - { echo, "E <0 off, 1 on>\0Set echo mode" }, - { ao_reboot, "r eboot\0Reboot" }, - { version, "v\0Version" }, - { 0, NULL }, -}; - -void -ao_cmd_init(void) -{ - ao_cmd_register(&ao_base_cmds[0]); - ao_add_task(&ao_cmd_task, ao_cmd, "cmd"); -} diff --git a/src/ao_companion.c b/src/ao_companion.c deleted file mode 100644 index 4c8f4269..00000000 --- a/src/ao_companion.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) - -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) - -static __xdata struct ao_companion_command ao_companion_command; -__xdata struct ao_companion_setup ao_companion_setup; - -__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; -__pdata uint8_t ao_companion_running; -__xdata uint8_t ao_companion_mutex; - -static void -ao_companion_send_command(uint8_t command) -{ - ao_companion_command.command = command; - ao_companion_command.flight_state = ao_flight_state; - ao_companion_command.tick = ao_time(); - ao_companion_command.serial = ao_serial_number; - ao_companion_command.flight = ao_flight_number; - ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); -} - -static uint8_t -ao_companion_get_setup(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_SETUP); - ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); - COMPANION_DESELECT(); - return (ao_companion_setup.board_id == - ~ao_companion_setup.board_id_inverse); -} - -static void -ao_companion_get_data(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_FETCH); - ao_mutex_get(&ao_companion_mutex); - ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); - ao_mutex_put(&ao_companion_mutex); - COMPANION_DESELECT(); -} - -static void -ao_companion_notify(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_NOTIFY); - COMPANION_DESELECT(); -} - -void -ao_companion(void) -{ - uint8_t i; - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - for (i = 0; i < 10; i++) { - ao_delay(AO_SEC_TO_TICKS(1)); - if ((ao_companion_running = ao_companion_get_setup())) - break; - } - while (ao_companion_running) { - ao_alarm(ao_companion_setup.update_period); - if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) - ao_companion_get_data(); - else - ao_companion_notify(); - } - ao_exit(); -} - -void -ao_companion_status(void) __reentrant -{ - uint8_t i; - printf("Companion running: %d\n", ao_companion_running); - printf("device: %d\n", ao_companion_setup.board_id); - printf("update period: %d\n", ao_companion_setup.update_period); - printf("channels: %d\n", ao_companion_setup.channels); - printf("data:"); - for(i = 0; i < ao_companion_setup.channels; i++) - printf(" %5u", ao_companion_data[i]); - printf("\n"); -} - -__code struct ao_cmds ao_companion_cmds[] = { - { ao_companion_status, "L\0Companion link status" }, - { 0, NULL }, -}; - -static __xdata struct ao_task ao_companion_task; - -void -ao_companion_init(void) -{ - COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ - COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ - COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ - - ao_cmd_register(&ao_companion_cmds[0]); - ao_add_task(&ao_companion_task, ao_companion, "companion"); -} diff --git a/src/ao_config.c b/src/ao_config.c deleted file mode 100644 index 0c10e608..00000000 --- a/src/ao_config.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata struct ao_config ao_config; -__pdata uint8_t ao_config_loaded; -__pdata uint8_t ao_config_dirty; -__xdata uint8_t ao_config_mutex; - -#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 -#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 -#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" -#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 -#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL -#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif -#if USE_INTERNAL_FLASH -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config -#else -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) -#endif - -#if HAS_EEPROM -static void -_ao_config_put(void) -{ - ao_storage_setup(); - ao_storage_erase(ao_storage_config); - ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); - ao_log_write_erase(0); - ao_storage_flush(); -} - -void -ao_config_put(void) -{ - ao_mutex_get(&ao_config_mutex); - _ao_config_put(); - ao_mutex_put(&ao_config_mutex); -} -#endif - -static void -_ao_config_get(void) -{ - if (ao_config_loaded) - return; -#if HAS_EEPROM - ao_storage_setup(); - ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); -#endif - if (ao_config.major != AO_CONFIG_MAJOR) { - ao_config.major = AO_CONFIG_MAJOR; - ao_config.minor = 0; - ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; - ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, - sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - } - if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for minor version 1 */ - if (ao_config.minor < 1) - ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - /* Fixups for minor version 2 */ - if (ao_config.minor < 2) { - ao_config.accel_plus_g = 0; - ao_config.accel_minus_g = 0; - } - /* Fixups for minor version 3 */ - if (ao_config.minor < 3) - ao_config.radio_cal = ao_radio_cal; - /* Fixups for minor version 4 */ - if (ao_config.minor < 4) - ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; - /* Fixupes for minor version 5 */ - if (ao_config.minor < 5) - ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - if (ao_config.minor < 6) - ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 7) - ao_config.radio_setting = ao_config.radio_cal; - if (ao_config.minor < 8) - ao_config.radio_enable = TRUE; - ao_config.minor = AO_CONFIG_MINOR; - ao_config_dirty = 1; - } - ao_config_loaded = 1; -} - -static void -_ao_config_edit_start(void) -{ - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); -} - -static void -_ao_config_edit_finish(void) -{ - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); -} - -void -ao_config_get(void) -{ - _ao_config_edit_start(); - ao_mutex_put(&ao_config_mutex); -} - -void -ao_config_callsign_show(void) -{ - printf ("Callsign: \"%s\"\n", ao_config.callsign); -} - -void -ao_config_callsign_set(void) __reentrant -{ - uint8_t c; - static __xdata char callsign[AO_MAX_CALLSIGN + 1]; - - memset(callsign, '\0', sizeof callsign); - ao_cmd_white(); - c = 0; - while (ao_cmd_lex_c != '\n') { - if (c < AO_MAX_CALLSIGN) - callsign[c++] = ao_cmd_lex_c; - else - ao_cmd_status = ao_cmd_lex_error; - ao_cmd_lex(); - } - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - memcpy(&ao_config.callsign, &callsign, - AO_MAX_CALLSIGN + 1); - _ao_config_edit_finish(); -} - -void -ao_config_radio_channel_show(void) __reentrant -{ - printf("Radio channel: %d\n", - ao_config.radio_channel); -} - -void -ao_config_radio_channel_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_channel = ao_cmd_lex_i; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - -#if HAS_ADC - -void -ao_config_main_deploy_show(void) __reentrant -{ - printf("Main deploy: %d meters\n", - ao_config.main_deploy); -} - -void -ao_config_main_deploy_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.main_deploy = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -#if HAS_ACCEL -void -ao_config_accel_calibrate_show(void) __reentrant -{ - printf("Accel cal +1g: %d -1g: %d\n", - ao_config.accel_plus_g, ao_config.accel_minus_g); -} - -#define ACCEL_CALIBRATE_SAMPLES 1024 -#define ACCEL_CALIBRATE_SHIFT 10 - -static int16_t -ao_config_accel_calibrate_auto(char *orientation) __reentrant -{ - uint16_t i; - int32_t accel_total; - uint8_t cal_adc_ring; - - printf("Orient antenna %s and press a key...", orientation); - flush(); - (void) getchar(); - puts("\r\n"); flush(); - puts("Calibrating..."); flush(); - i = ACCEL_CALIBRATE_SAMPLES; - accel_total = 0; - cal_adc_ring = ao_sample_adc; - while (i) { - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (i && cal_adc_ring != ao_sample_adc) { - accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; - cal_adc_ring = ao_adc_ring_next(cal_adc_ring); - i--; - } - } - return accel_total >> ACCEL_CALIBRATE_SHIFT; -} - -void -ao_config_accel_calibrate_set(void) __reentrant -{ - int16_t up, down; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_cmd_lex_i == 0) { - up = ao_config_accel_calibrate_auto("up"); - down = ao_config_accel_calibrate_auto("down"); - } else { - up = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - down = ao_cmd_lex_i; - } - if (up >= down) { - printf("Invalid accel: up (%d) down (%d)\n", - up, down); - return; - } - _ao_config_edit_start(); - ao_config.accel_plus_g = up; - ao_config.accel_minus_g = down; - _ao_config_edit_finish(); -} -#endif /* HAS_ACCEL */ - -void -ao_config_apogee_delay_show(void) __reentrant -{ - printf("Apogee delay: %d seconds\n", - ao_config.apogee_delay); -} - -void -ao_config_apogee_delay_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.apogee_delay = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -#endif /* HAS_ADC */ - -void -ao_config_radio_cal_show(void) __reentrant -{ - printf("Radio cal: %ld\n", ao_config.radio_cal); -} - -void -ao_config_radio_cal_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; - _ao_config_edit_finish(); -} - -#if HAS_EEPROM -void -ao_config_log_show(void) __reentrant -{ - printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); -} - -void -ao_config_log_set(void) __reentrant -{ - uint16_t block = (uint16_t) (ao_storage_block >> 10); - uint16_t config = (uint16_t) (ao_storage_config >> 10); - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_log_present()) - printf("Storage must be empty before changing log size\n"); - else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) - printf("Flight log size must be multiple of %d kB\n", block); - else if (ao_cmd_lex_i > config) - printf("Flight log max %d kB\n", config); - else { - _ao_config_edit_start(); - ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; - _ao_config_edit_finish(); - } -} -#endif /* HAS_EEPROM */ - -#if HAS_IGNITE -void -ao_config_ignite_mode_show(void) __reentrant -{ - printf("Ignite mode: %d\n", ao_config.ignite_mode); -} - -void -ao_config_ignite_mode_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.ignite_mode = ao_cmd_lex_i; - _ao_config_edit_finish(); -} -#endif - -#if HAS_ACCEL -void -ao_config_pad_orientation_show(void) __reentrant -{ - printf("Pad orientation: %d\n", ao_config.pad_orientation); -} - -void -ao_config_pad_orientation_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_cmd_lex_i &= 1; - if (ao_config.pad_orientation != ao_cmd_lex_i) { - uint16_t t; - t = ao_config.accel_plus_g; - ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; - ao_config.accel_minus_g = 0x7fff - t; - } - ao_config.pad_orientation = ao_cmd_lex_i; - _ao_config_edit_finish(); -} -#endif - -void -ao_config_radio_setting_show(void) __reentrant -{ - printf("Radio setting: %ld\n", ao_config.radio_setting); -} - -void -ao_config_radio_setting_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_cmd_lex_u32; - ao_config.radio_channel = 0; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - -void -ao_config_radio_enable_show(void) __reentrant -{ - printf("Radio enable: %d\n", ao_config.radio_enable); -} - -void -ao_config_radio_enable_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_enable = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -struct ao_config_var { - __code char *str; - void (*set)(void) __reentrant; - void (*show)(void) __reentrant; -}; - -static void -ao_config_help(void) __reentrant; - -static void -ao_config_show(void) __reentrant; - -static void -ao_config_write(void) __reentrant; - -__code struct ao_config_var ao_config_vars[] = { -#if HAS_ADC - { "m \0Main deploy (in meters)", - ao_config_main_deploy_set, ao_config_main_deploy_show, }, - { "d \0Apogee delay (in seconds)", - ao_config_apogee_delay_set, ao_config_apogee_delay_show }, -#endif /* HAS_ADC */ - { "r \0Radio channel (freq = 434.550 + chan * .1)", - ao_config_radio_channel_set, ao_config_radio_channel_show }, - { "c \0Callsign (8 char max)", - ao_config_callsign_set, ao_config_callsign_show }, - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, - { "e <0 disable, 1 enable>\0Enable telemetry and RDF", - ao_config_radio_enable_set, ao_config_radio_enable_show }, -#if HAS_ACCEL - { "a <+g> <-g>\0Accel calib (0 for auto)", - ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, -#endif /* HAS_ACCEL */ - { "f \0Radio calib (cal = rf/(xtal/2^16))", - ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM - { "l \0Flight log size in kB", - ao_config_log_set, ao_config_log_show }, -#endif -#if HAS_IGNITE - { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", - ao_config_ignite_mode_set, ao_config_ignite_mode_show }, -#endif -#if HAS_ACCEL - { "o <0 antenna up, 1 antenna down>\0Set pad orientation", - ao_config_pad_orientation_set,ao_config_pad_orientation_show }, -#endif - { "s\0Show", - ao_config_show, 0 }, -#if HAS_EEPROM - { "w\0Write to eeprom", - ao_config_write, 0 }, -#endif - { "?\0Help", - ao_config_help, 0 }, - { 0, 0, 0 } -}; - -void -ao_config_set(void) -{ - char c; - uint8_t cmd; - void (*__xdata func)(void) __reentrant; - - ao_cmd_white(); - c = ao_cmd_lex_c; - ao_cmd_lex(); - func = 0; - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].str[0] == c) { - (*ao_config_vars[cmd].set)(); - return; - } - ao_cmd_status = ao_cmd_syntax_error; -} - -static void -ao_config_help(void) __reentrant -{ - uint8_t cmd; - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - printf("%-20s %s\n", - ao_config_vars[cmd].str, - ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); -} - -static void -ao_config_show(void) __reentrant -{ - uint8_t cmd; - printf("Config version: %d.%d\n", - ao_config.major, ao_config.minor); - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].show) - (*ao_config_vars[cmd].show)(); -} - -#if HAS_EEPROM -static void -ao_config_write(void) __reentrant -{ - uint8_t saved = 0; - ao_mutex_get(&ao_config_mutex); - if (ao_config_dirty) { - _ao_config_put(); - ao_config_dirty = 0; - saved = 1; - } - ao_mutex_put(&ao_config_mutex); - if (saved) - puts("Saved"); - else - puts("Nothing to save"); -} -#endif - -__code struct ao_cmds ao_config_cmds[] = { - { ao_config_set, "c \0Set config variable (? for help, s to show)" }, - { 0, NULL }, -}; - -void -ao_config_init(void) -{ - ao_cmd_register(&ao_config_cmds[0]); -} diff --git a/src/ao_convert.c b/src/ao_convert.c deleted file mode 100644 index 0969f107..00000000 --- a/src/ao_convert.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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. - */ - -#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) -#include "ao.h" -#endif - -static const int16_t altitude_table[] = { -#include "altitude.h" -}; - -#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) -#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - uint8_t o; - int16_t part; - - if (pres < 0) - pres = 0; - o = pres >> ALT_FRAC_BITS; - part = pres & ALT_FRAC_MASK; - - return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + - (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t span, sub_span; - uint8_t l, h, m; - int32_t pres; - - l = 0; - h = NALT - 1; - while ((h - l) != 1) { - m = (l + h) >> 1; - if (altitude_table[m] < alt) - h = m; - else - l = m; - } - span = altitude_table[l] - altitude_table[h]; - sub_span = altitude_table[l] - alt; - pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; - if (pres > 32767) - pres = 32767; - if (pres < 0) - pres = 0; - return (int16_t) pres; -} - -int16_t -ao_temp_to_dC(int16_t temp) __reentrant -{ - int16_t ret; - - /* Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - * ≃ (value - 19791) * 1012 / 65536 - */ - ret = ((temp - 19791) * 1012L) >> 16; - return ret; -} diff --git a/src/ao_convert_test.c b/src/ao_convert_test.c deleted file mode 100644 index e2c28b73..00000000 --- a/src/ao_convert_test.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 -#define AO_CONVERT_TEST -#include "ao_host.h" -#include "ao_convert.c" - -#define STEP 1 - -static inline i_abs(int i) { return i < 0 ? -i : i; } - -main () -{ - int i; - int16_t p_to_a, p_to_a_to_p; - int16_t a_to_p, a_to_p_to_a; - int max_p_error = 0, max_p_error_p = -1; - int max_a_error = 0, max_a_error_a = -1; - int p_error; - int a_error; - int ret = 0; - - for (i = 0; i < 32767 + STEP; i += STEP) { - if (i > 32767) - i = 32767; - p_to_a = ao_pres_to_altitude(i); - p_to_a_to_p = ao_altitude_to_pres(p_to_a); - p_error = i_abs(p_to_a_to_p - i); - if (p_error > max_p_error) { - max_p_error = p_error; - max_p_error_p = i; - } -// printf ("pres %d alt %d pres %d\n", -// i, p_to_a, p_to_a_to_p); - } - for (i = -1578; i < 15835 + STEP; i += STEP) { - if (i > 15835) - i = 15835; - a_to_p = ao_altitude_to_pres(i); - a_to_p_to_a = ao_pres_to_altitude(a_to_p); - a_error = i_abs(a_to_p_to_a - i); - if (a_error > max_a_error) { - max_a_error = a_error; - max_a_error_a = i; - } -// printf ("alt %d pres %d alt %d\n", -// i, a_to_p, a_to_p_to_a); - } - if (max_p_error > 2) { - printf ("max p error %d at %d\n", max_p_error, - max_p_error_p); - ret++; - } - if (max_a_error > 1) { - printf ("max a error %d at %d\n", max_a_error, - max_a_error_a); - ret++; - } - return ret; -} diff --git a/src/ao_dbg.c b/src/ao_dbg.c deleted file mode 100644 index d4c9567f..00000000 --- a/src/ao_dbg.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -static void -ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant -{ - DBG_PORT = (DBG_PORT & ~msk) | (val & msk); - _asm - nop - nop - _endasm; -} - -void -ao_dbg_send_byte(uint8_t byte) -{ - __pdata uint8_t b, d; - - DBG_PORT |= DBG_DATA; - DBG_PORT_DIR |= DBG_DATA; - for (b = 0; b < 8; b++) { - d = 0; - if (byte & 0x80) - d = DBG_DATA; - byte <<= 1; - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); - } - DBG_PORT_DIR &= ~DBG_DATA; -} - -uint8_t -ao_dbg_recv_byte(void) -{ - __pdata uint8_t byte, b; - - byte = 0; - for (b = 0; b < 8; b++) { - byte = byte << 1; - ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK); - if (DBG_DATA_PIN) - byte |= 1; - ao_dbg_send_bits(DBG_CLOCK, 0); - } - return byte; -} - -/* 8051 instructions - */ -#define NOP 0x00 -#define MOV_direct_data 0x75 -#define LJMP 0x02 -#define MOV_Rn_data(n) (0x78 | (n)) -#define DJNZ_Rn_rel(n) (0xd8 | (n)) -#define MOV_A_direct 0xe5 -#define MOV_direct1_direct2 0x85 -#define MOV_direct_A 0xf5 -#define MOV_DPTR_data16 0x90 -#define MOV_A_data 0x74 -#define MOVX_atDPTR_A 0xf0 -#define MOVX_A_atDPTR 0xe0 -#define INC_DPTR 0xa3 -#define TRAP 0xa5 -#define SJMP 0x80 -#define JB 0x20 - -#define DEBUG_INSTR(l) (0x54 | (l)) - -#define SFR_PSW 0xD0 -#define SFR_DPL0 0x82 -#define SFR_DPH0 0x83 -#define SFR_DPL1 0x84 -#define SFR_DPH1 0x85 - -__pdata uint8_t save_acc; -__pdata uint8_t save_psw; -__pdata uint8_t save_dpl0; -__pdata uint8_t save_dph0; -__pdata uint8_t save_dpl1; -__pdata uint8_t save_dph1; - -static uint8_t -ao_dbg_inst1(uint8_t a) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(1)); - ao_dbg_send_byte(a); - return ao_dbg_recv_byte(); -} - -static uint8_t -ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(2)); - ao_dbg_send_byte(a); - ao_dbg_send_byte(b); - return ao_dbg_recv_byte(); -} - -static uint8_t -ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(3)); - ao_dbg_send_byte(a); - ao_dbg_send_byte(b); - ao_dbg_send_byte(c); - return ao_dbg_recv_byte(); -} - -void -ao_dbg_start_transfer(uint16_t addr) -{ - save_acc = ao_dbg_inst1(NOP); - save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW); - save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0); - save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0); - save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1); - save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1); - ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr); -} - -void -ao_dbg_end_transfer(void) -{ - ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0); - ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0); - ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1); - ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1); - ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw); - ao_dbg_inst2(MOV_A_data, save_acc); -} - -void -ao_dbg_write_byte(uint8_t byte) -{ - ao_dbg_inst2(MOV_A_data, byte); - ao_dbg_inst1(MOVX_atDPTR_A); - ao_dbg_inst1(INC_DPTR); -} - -uint8_t -ao_dbg_read_byte(void) -{ - ao_dbg_inst1(MOVX_A_atDPTR); - return ao_dbg_inst1(INC_DPTR); -} - -static void -ao_dbg_set_pins(void) -{ - /* Make the DBG pins GPIOs. On TeleMetrum, this will - * disable the SPI link, so don't expect SPI to work after - * using the debugger. - */ - DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); - - /* make DBG_DATA tri-state */ - DBG_PORT_INP |= DBG_DATA; - - /* Raise RESET_N and CLOCK */ - DBG_PORT |= DBG_RESET_N | DBG_CLOCK; - - /* RESET_N and CLOCK are outputs now */ - DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; - DBG_PORT_DIR &= ~DBG_DATA; -} - -static void -ao_dbg_long_delay(void) -{ - uint8_t n; - - for (n = 0; n < 20; n++) - _asm nop _endasm; -} - -#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) -#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) - -void -ao_dbg_debug_mode(void) -{ - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); -} - -void -ao_dbg_reset(void) -{ - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); -} - -static void -debug_enable(void) -{ - ao_dbg_debug_mode(); -} - -static void -debug_reset(void) -{ - ao_dbg_reset(); -} - -static void -debug_put(void) -{ - for (;;) { - ao_cmd_white (); - if (ao_cmd_lex_c == '\n') - break; - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - break; - ao_dbg_send_byte(ao_cmd_lex_i); - } -} - -static void -debug_get(void) -{ - __pdata uint16_t count; - __pdata uint16_t i; - __pdata uint8_t byte; - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - count = ao_cmd_lex_i; - if (count > 256) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - for (i = 0; i < count; i++) { - if (i && (i & 7) == 0) - putchar('\n'); - byte = ao_dbg_recv_byte(); - ao_cmd_put8(byte); - putchar(' '); - } - putchar('\n'); -} - -static uint8_t -getnibble(void) -{ - __pdata char c; - - c = getchar(); - 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); - ao_cmd_status = ao_cmd_lex_error; - return 0; -} - -static void -debug_input(void) -{ - __pdata uint16_t count; - __pdata uint16_t addr; - __pdata uint8_t b; - __pdata uint8_t i; - - ao_cmd_hex(); - count = ao_cmd_lex_i; - ao_cmd_hex(); - addr = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - ao_dbg_start_transfer(addr); - i = 0; - while (count--) { - if (!(i++ & 7)) - putchar('\n'); - b = ao_dbg_read_byte(); - ao_cmd_put8(b); - } - ao_dbg_end_transfer(); - putchar('\n'); -} - -static void -debug_output(void) -{ - __pdata uint16_t count; - __pdata uint16_t addr; - __pdata uint8_t b; - - ao_cmd_hex(); - count = ao_cmd_lex_i; - ao_cmd_hex(); - addr = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - ao_dbg_start_transfer(addr); - while (count--) { - b = getnibble() << 4; - b |= getnibble(); - if (ao_cmd_status != ao_cmd_success) - return; - ao_dbg_write_byte(b); - } - ao_dbg_end_transfer(); -} - -__code struct ao_cmds ao_dbg_cmds[7] = { - { debug_enable, "D\0Enable debug" }, - { debug_get, "G \0Get data" }, - { debug_input, "I \0Input at " }, - { debug_output, "O \0Output at " }, - { debug_put, "P ...\0Put data" }, - { debug_reset, "R\0Reset" }, - { 0, NULL }, -}; - -void -ao_dbg_init(void) -{ - ao_cmd_register(&ao_dbg_cmds[0]); -} diff --git a/src/ao_dma.c b/src/ao_dma.c deleted file mode 100644 index 6052964a..00000000 --- a/src/ao_dma.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -#define NUM_DMA 5 - -/* - * The config address for DMA0 is programmed - * separately from that of DMA1-4, but for simplicity, - * we make them all contiguous. - */ - -static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; -static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; -static __data uint8_t ao_next_dma; - -uint8_t -ao_dma_alloc(__xdata uint8_t *done) -{ - uint8_t id; - - if (ao_next_dma == NUM_DMA) - ao_panic(AO_PANIC_DMA); - id = ao_next_dma++; - ao_dma_done[id] = done; - - /* When the first dma object is allocated, set up the DMA - * controller - */ - if (id == 0) { - DMAIRQ = 0; - DMAIF = 0; - IEN1 |= IEN1_DMAIE; - } - - return id; -} - -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1) -{ - if (DMAARM & (1 << id)) - ao_panic(AO_PANIC_DMA); - ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; - ao_dma_config[id].src_low = ((uint16_t) srcaddr); - ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; - ao_dma_config[id].dst_low = ((uint16_t) dstaddr); - ao_dma_config[id].len_high = count >> 8; - ao_dma_config[id].len_low = count; - ao_dma_config[id].cfg0 = cfg0; - ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; - if (id == 0) { - DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; - DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); - } else { - DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; - DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); - } -} - -#define nop() _asm nop _endasm; - -void -ao_dma_start(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAIRQ &= ~mask; - DMAARM = 0x80 | mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); - *(ao_dma_done[id]) = 0; - DMAARM = mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); - nop(); -} - -void -ao_dma_trigger(uint8_t id) -{ - DMAREQ |= (1 << id); -} - -void -ao_dma_abort(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAARM = 0x80 | mask; - DMAIRQ &= ~mask; -} - -void -ao_dma_isr(void) __interrupt 8 -{ - uint8_t id, mask; - - /* Find the first DMA channel which is done */ - mask = 1; - for (id = 0; id < ao_next_dma; id++) { - if (DMAIRQ & mask) { - /* Clear CPU interrupt flag */ - DMAIF = 0; - /* Clear the completed ID */ - DMAIRQ = ~mask; - *(ao_dma_done[id]) = 1; - ao_wakeup(ao_dma_done[id]); - break; - } - mask <<= 1; - } -} diff --git a/src/ao_ee.c b/src/ao_ee.c deleted file mode 100644 index a2fe8dc1..00000000 --- a/src/ao_ee.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "25lc1024.h" - -#define EE_BLOCK_SIZE ((uint16_t) (256)) -#define EE_BLOCK_SHIFT 8 -#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -/* - * Using SPI on USART 0, with P1_2 as the chip select - */ - -#define EE_CS P1_2 -#define EE_CS_INDEX 2 - -static __xdata uint8_t ao_ee_mutex; - -#define ao_ee_delay() do { \ - _asm nop _endasm; \ - _asm nop _endasm; \ - _asm nop _endasm; \ -} while(0) - -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) - -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) - -struct ao_ee_instruction { - uint8_t instruction; - uint8_t address[3]; -} __xdata ao_ee_instruction; - -static void -ao_ee_write_enable(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WREN; - ao_spi_send(&ao_ee_instruction, 1); - ao_ee_cs_high(); -} - -static uint8_t -ao_ee_rdsr(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_RDSR; - ao_spi_send(&ao_ee_instruction, 1); - ao_spi_recv(&ao_ee_instruction, 1); - ao_ee_cs_high(); - return ao_ee_instruction.instruction; -} - -static void -ao_ee_wrsr(uint8_t status) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WRSR; - ao_ee_instruction.address[0] = status; - ao_spi_send(&ao_ee_instruction, 2); - ao_ee_cs_high(); -} - -#define EE_BLOCK_NONE 0xffff - -static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; -static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; -static __pdata uint8_t ao_ee_block_dirty; - -/* Write the current block to the EEPROM */ -static void -ao_ee_write_block(void) -{ - uint8_t status; - - status = ao_ee_rdsr(); - if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) { - status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN); - ao_ee_wrsr(status); - } - ao_ee_write_enable(); - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WRITE; - ao_ee_instruction.address[0] = ao_ee_block >> 8; - ao_ee_instruction.address[1] = ao_ee_block; - ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); - ao_ee_cs_high(); - for (;;) { - uint8_t status = ao_ee_rdsr(); - if ((status & EE_STATUS_WIP) == 0) - break; - } -} - -/* Read the current block from the EEPROM */ -static void -ao_ee_read_block(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_READ; - ao_ee_instruction.address[0] = ao_ee_block >> 8; - ao_ee_instruction.address[1] = ao_ee_block; - ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); - ao_ee_cs_high(); -} - -static void -ao_ee_flush_internal(void) -{ - if (ao_ee_block_dirty) { - ao_ee_write_block(); - ao_ee_block_dirty = 0; - } -} - -static void -ao_ee_fill(uint16_t block) -{ - if (block != ao_ee_block) { - ao_ee_flush_internal(); - ao_ee_block = block; - ao_ee_read_block(); - } -} - -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - if (len != EE_BLOCK_SIZE) - ao_ee_fill(block); - else { - ao_ee_flush_internal(); - ao_ee_block = block; - } - memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(block); - memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - } ao_mutex_put(&ao_ee_mutex); -} - -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -static void -ee_store(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ - if (ao_storage_total == 0) { - ao_storage_total = EE_DEVICE_SIZE; - ao_storage_block = EE_BLOCK_SIZE; - ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; - ao_storage_unit = EE_BLOCK_SIZE; - } -} - -void -ao_storage_device_info(void) __reentrant -{ -} - -/* - * To initialize the chip, set up the CS line and - * the SPI interface - */ -void -ao_storage_device_init(void) -{ - /* set up CS */ - EE_CS = 1; - P1DIR |= (1 << EE_CS_INDEX); - P1SEL &= ~(1 << EE_CS_INDEX); -} diff --git a/src/ao_ee_fake.c b/src/ao_ee_fake.c deleted file mode 100644 index b0c1d61e..00000000 --- a/src/ao_ee_fake.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -/* - * For hardware without eeprom, the config code still - * wants to call these functions - */ -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant -{ - (void) buf; - (void) len; - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - memset(buf, '\0', len); - return 1; -} diff --git a/src/ao_flash.c b/src/ao_flash.c deleted file mode 100644 index bb40f6f7..00000000 --- a/src/ao_flash.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "at45db161d.h" - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -#define FLASH_CS P1_1 -#define FLASH_CS_INDEX 1 - -#define FLASH_BLOCK_SIZE_MAX 512 - -__xdata uint8_t ao_flash_mutex; - -#define ao_flash_delay() do { \ - _asm nop _endasm; \ - _asm nop _endasm; \ - _asm nop _endasm; \ -} while(0) - -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) - -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) - -struct ao_flash_instruction { - uint8_t instruction; - uint8_t address[3]; -} __xdata ao_flash_instruction; - -static void -ao_flash_set_pagesize_512(void) -{ - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_SET_CONFIG; - ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; - ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; - ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_spi_send(&ao_flash_instruction, 4); - ao_flash_cs_high(); -} - - -static uint8_t -ao_flash_read_status(void) -{ - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_spi_send(&ao_flash_instruction, 1); - ao_spi_recv(&ao_flash_instruction, 1); - ao_flash_cs_high(); - return ao_flash_instruction.instruction; -} - -#define FLASH_BLOCK_NONE 0xffff - -static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; -static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; -static __pdata uint8_t ao_flash_block_dirty; -static __pdata uint8_t ao_flash_write_pending; -static __pdata uint8_t ao_flash_setup_done; -static __pdata uint8_t ao_flash_block_shift; -static __pdata uint16_t ao_flash_block_size; -static __pdata uint16_t ao_flash_block_mask; - -void -ao_storage_setup(void) __reentrant -{ - uint8_t status; - - if (ao_flash_setup_done) - return; - - ao_mutex_get(&ao_flash_mutex); - if (ao_flash_setup_done) { - ao_mutex_put(&ao_flash_mutex); - return; - } - - /* On first use, check to see if the flash chip has - * been programmed to use 512 byte pages. If not, do so. - * And then, because the flash part must be power cycled - * for that change to take effect, panic. - */ - status = ao_flash_read_status(); - - if (!(status & FLASH_STATUS_PAGESIZE_512)) { - ao_flash_set_pagesize_512(); - ao_panic(AO_PANIC_FLASH); - } - - switch (status & 0x3c) { - - /* AT45DB321D */ - case 0x34: - ao_flash_block_shift = 9; - ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB161D */ - case 0x2c: - ao_flash_block_shift = 9; - ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB081D */ - case 0x24: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB041D */ - case 0x1c: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); - break; - - /* AT45DB021D */ - case 0x14: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); - break; - - /* AT45DB011D */ - case 0x0c: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); - break; - - default: - ao_panic(AO_PANIC_FLASH); - } - ao_flash_block_size = 1 << ao_flash_block_shift; - ao_flash_block_mask = ao_flash_block_size - 1; - - ao_storage_block = ao_flash_block_size; - ao_storage_config = ao_storage_total - ao_storage_block; - ao_storage_unit = ao_flash_block_size; - - ao_flash_setup_done = 1; - ao_mutex_put(&ao_flash_mutex); -} - -static void -ao_flash_wait_write(void) -{ - if (ao_flash_write_pending) { - for (;;) { - uint8_t status = ao_flash_read_status(); - if ((status & FLASH_STATUS_RDY)) - break; - } - ao_flash_write_pending = 0; - } -} - -/* Write the current block to the FLASHPROM */ -static void -ao_flash_write_block(void) -{ - ao_flash_wait_write(); - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_WRITE; - - /* 13/14 block bits + 9/8 byte bits (always 0) */ - ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); - ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); - ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, ao_storage_block); - ao_flash_cs_high(); - ao_flash_write_pending = 1; -} - -/* Read the current block from the FLASHPROM */ -static void -ao_flash_read_block(void) -{ - ao_flash_wait_write(); - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_READ; - - /* 13/14 block bits + 9/8 byte bits (always 0) */ - ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); - ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); - ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, ao_flash_block_size); - ao_flash_cs_high(); -} - -static void -ao_flash_flush_internal(void) -{ - if (ao_flash_block_dirty) { - ao_flash_write_block(); - ao_flash_block_dirty = 0; - } -} - -static void -ao_flash_fill(uint16_t block) -{ - if (block != ao_flash_block) { - ao_flash_flush_internal(); - ao_flash_block = block; - ao_flash_read_block(); - } -} - -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - if (len != ao_flash_block_size) - ao_flash_fill(block); - else { - ao_flash_flush_internal(); - ao_flash_block = block; - } - memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), - buf, - len); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); - memcpy(buf, - ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), - len); - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - } ao_mutex_put(&ao_flash_mutex); -} - -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); - memset(ao_flash_data, 0xff, ao_flash_block_size); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -void -ao_storage_device_info(void) __reentrant -{ - uint8_t status; - - ao_storage_setup(); - ao_mutex_get(&ao_flash_mutex); { - status = ao_flash_read_status(); - printf ("Flash status: 0x%02x\n", status); - printf ("Flash block shift: %d\n", ao_flash_block_shift); - printf ("Flash block size: %d\n", ao_flash_block_size); - printf ("Flash block mask: %d\n", ao_flash_block_mask); - printf ("Flash device size: %ld\n", ao_storage_total); - } ao_mutex_put(&ao_flash_mutex); -} - -/* - * To initialize the chip, set up the CS line and - * the SPI interface - */ -void -ao_storage_device_init(void) -{ - /* set up CS */ - FLASH_CS = 1; - P1DIR |= (1 << FLASH_CS_INDEX); - P1SEL &= ~(1 << FLASH_CS_INDEX); -} diff --git a/src/ao_flight.c b/src/ao_flight.c deleted file mode 100644 index 85c1825b..00000000 --- a/src/ao_flight.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - - /* Disable packet mode in pad state */ - ao_packet_slave_stop(); - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#endif - case ao_flight_coast: - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); - - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { - ao_ignite(ao_igniter_main); - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c deleted file mode 100644 index 2e332b12..00000000 --- a/src/ao_flight_nano.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; - -__pdata uint8_t ao_flight_force_idle; - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) - -static void -ao_flight_nano(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - - for (;;) { - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - if (ao_flight_force_idle) { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - } else { - ao_flight_state = ao_flight_pad; - /* Disable packet mode in pad state */ - ao_packet_slave_stop(); - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - } - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; - case ao_flight_pad: - if (ao_height> AO_M_TO_HEIGHT(20)) { - ao_flight_state = ao_flight_drogue; - ao_launch_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_drogue: - /* drogue/main to land: - * - * barometer: altitude stable - */ - - if (ao_height < ao_interval_min_height) - ao_interval_min_height = ao_height; - if (ao_height > ao_interval_max_height) - ao_interval_max_height = ao_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_nano_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight_nano, "flight"); -} diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c deleted file mode 100644 index 56733c89..00000000 --- a/src/ao_flight_test.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#define AO_HERTZ 100 - -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -/* - * One set of samples read from the A/D converter - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t pres_real; /* unclipped */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#define __pdata -#define __data -#define __xdata -#define __code -#define __reentrant - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 -#define AO_BARO_SATURATE 13000 -#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern enum ao_flight_state ao_flight_state; - -#define FALSE 0 -#define TRUE 1 - -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; -int ao_summary = 0; - -#define ao_led_on(l) -#define ao_led_off(l) -#define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state() -#define ao_cmd_register(c) -#define ao_usb_disable() -#define ao_telemetry_set_interval(x) -#define ao_rdf_set(rdf) -#define ao_packet_slave_start() -#define ao_packet_slave_stop() - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -struct ao_adc ao_adc_static; - -int drogue_height; -double drogue_time; -int main_height; -double main_time; - -int tick_offset; - -static int32_t ao_k_height; - -void -ao_ignite(enum ao_igniter igniter) -{ - double time = (double) (ao_adc_static.tick + tick_offset) / 100; - - if (igniter == ao_igniter_drogue) { - drogue_time = time; - drogue_height = ao_k_height >> 16; - } else { - main_time = time; - main_height = ao_k_height >> 16; - } -} - -struct ao_task { - int dummy; -}; - -#define ao_add_task(t,f,n) - -#define ao_log_start() -#define ao_log_stop() - -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) - -#define AO_FLIGHT_TEST - -int ao_flight_debug; - -FILE *emulator_in; -char *emulator_app; -char *emulator_name; -double emulator_error_max = 4; -double emulator_height_error_max = 20; /* noise in the baro sensor */ - -void -ao_dump_state(void); - -void -ao_sleep(void *wchan); - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; - -struct ao_cmds { - void (*func)(void); - const char *help; -}; - -#include "ao_convert.c" - -struct ao_config { - uint16_t main_deploy; - int16_t accel_plus_g; - int16_t accel_minus_g; - uint8_t pad_orientation; -}; - -#define AO_PAD_ORIENTATION_ANTENNA_UP 0 -#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 - -#define ao_config_get() - -struct ao_config ao_config; - -#define DATA_TO_XDATA(x) (x) - -#define HAS_FLIGHT 1 -#define HAS_ADC 1 -#define HAS_USB 1 -#define HAS_GPS 1 -#ifndef HAS_ACCEL -#define HAS_ACCEL 1 -#define HAS_ACCEL_REF 0 -#endif - -#define GRAVITY 9.80665 -extern int16_t ao_ground_accel, ao_flight_accel; -extern int16_t ao_accel_2g; - -extern uint16_t ao_sample_tick; - -extern int16_t ao_sample_height; -extern int16_t ao_sample_accel; -extern int32_t ao_accel_scale; -extern int16_t ao_ground_height; -extern int16_t ao_sample_alt; - -int ao_sample_prev_tick; -uint16_t prev_tick; - -#include "ao_kalman.c" -#include "ao_sample.c" -#include "ao_flight.c" - -#define to_double(f) ((f) / 65536.0) - -static int ao_records_read = 0; -static int ao_eof_read = 0; -static int ao_flight_ground_accel; -static int ao_flight_started = 0; -static int ao_test_max_height; -static double ao_test_max_height_time; -static int ao_test_main_height; -static double ao_test_main_height_time; -static double ao_test_landed_time; -static double ao_test_landed_height; -static double ao_test_landed_time; -static int landed_set; -static double landed_time; -static double landed_height; - -void -ao_test_exit(void) -{ - double drogue_error; - double main_error; - double landed_error; - double landed_time_error; - - if (!ao_test_main_height_time) { - ao_test_main_height_time = ao_test_max_height_time; - ao_test_main_height = ao_test_max_height; - } - drogue_error = fabs(ao_test_max_height_time - drogue_time); - main_error = fabs(ao_test_main_height_time - main_time); - landed_error = fabs(ao_test_landed_height - landed_height); - landed_time_error = ao_test_landed_time - landed_time; - if (drogue_error > emulator_error_max || main_error > emulator_error_max || - landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { - printf ("%s %s\n", - emulator_app, emulator_name); - printf ("\tApogee error %g\n", drogue_error); - printf ("\tMain error %g\n", main_error); - printf ("\tLanded height error %g\n", landed_error); - printf ("\tLanded time error %g\n", landed_time_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", - ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time, - ao_test_landed_height, ao_test_landed_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", - drogue_height, drogue_time, main_height, main_time, - landed_height, landed_time); - exit (1); - } - exit(0); -} - -void -ao_insert(void) -{ - double time; - - ao_adc_ring[ao_adc_head] = ao_adc_static; - ao_adc_head = ao_adc_ring_next(ao_adc_head); - if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / - (ao_config.accel_minus_g - ao_config.accel_plus_g); - - if (!tick_offset) - tick_offset = -ao_adc_static.tick; - if ((prev_tick - ao_adc_static.tick) > 0x400) - tick_offset += 65536; - prev_tick = ao_adc_static.tick; - time = (double) (ao_adc_static.tick + tick_offset) / 100; - - if (ao_test_max_height < height) { - ao_test_max_height = height; - ao_test_max_height_time = time; - ao_test_landed_height = height; - ao_test_landed_time = time; - } - if (height > ao_config.main_deploy) { - ao_test_main_height_time = time; - ao_test_main_height = height; - } - - if (ao_test_landed_height > height) { - ao_test_landed_height = height; - ao_test_landed_time = time; - } - - if (ao_flight_state == ao_flight_landed && !landed_set) { - landed_set = 1; - landed_time = time; - landed_height = height; - } - - if (!ao_summary) { - printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", - time, - height, - accel, - ao_state_names[ao_flight_state], - ao_k_height / 65536.0, - ao_k_speed / 65536.0 / 16.0, - ao_k_accel / 65536.0 / 16.0, - ao_avg_height, - drogue_height, - main_height, - ao_error_h_sq_avg); - -// if (ao_flight_state == ao_flight_landed) -// ao_test_exit(); - } - } -} - -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#define AO_MAX_TELEMETRY 128 - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10â·) */ - int32_t longitude; /* 12 longitude (degrees * 10â·) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; -}; - -uint16_t -uint16(uint8_t *bytes, int off) -{ - off++; - return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); -} - -int16_t -int16(uint8_t *bytes, int off) -{ - return (int16_t) uint16(bytes, off); -} - -void -ao_sleep(void *wchan) -{ - if (wchan == &ao_adc_head) { - char type; - uint16_t tick; - uint16_t a, b; - int ret; - uint8_t bytes[1024]; - union ao_telemetry_all telem; - char line[1024]; - char *saveptr; - char *l; - char *words[64]; - int nword; - - for (;;) { - if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) - { - ao_adc_static.accel = ao_flight_ground_accel; - ao_insert(); - return; - } - - if (!fgets(line, sizeof (line), emulator_in)) { - if (++ao_eof_read >= 1000) { - if (!ao_summary) - printf ("no more data, exiting simulation\n"); - ao_test_exit(); - } - ao_adc_static.tick += 10; - ao_insert(); - return; - } - l = line; - for (nword = 0; nword < 64; nword++) { - words[nword] = strtok_r(l, " \t\n", &saveptr); - l = NULL; - if (words[nword] == NULL) - break; - } - if (nword == 4) { - type = words[0][0]; - tick = strtoul(words[1], NULL, 16); - a = strtoul(words[2], NULL, 16); - b = strtoul(words[3], NULL, 16); - if (type == 'P') - type = 'A'; - } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { - ao_config.accel_plus_g = atoi(words[3]); - ao_config.accel_minus_g = atoi(words[5]); - } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { - ao_config.main_deploy = atoi(words[2]); - } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { - tick = atoi(words[10]); - if (!ao_flight_started) { - type = 'F'; - a = atoi(words[26]); - ao_flight_started = 1; - } else { - type = 'A'; - a = atoi(words[12]); - b = atoi(words[14]); - } - } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { - tick = strtol(words[1], NULL, 16); - a = 16384 - 328; - b = strtol(words[2], NULL, 10); - type = 'A'; - if (!ao_flight_started) { - ao_flight_ground_accel = 16384 - 328; - ao_config.accel_plus_g = 16384 - 328; - ao_config.accel_minus_g = 16384 + 328; - ao_flight_started = 1; - } - } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { - char *hex = words[1]; - char elt[3]; - int i, len; - uint8_t sum; - - len = strlen(hex); - if (len > sizeof (bytes) * 2) { - len = sizeof (bytes)*2; - hex[len] = '\0'; - } - for (i = 0; i < len; i += 2) { - elt[0] = hex[i]; - elt[1] = hex[i+1]; - elt[2] = '\0'; - bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); - } - len = i/2; - if (bytes[0] != len - 2) { - printf ("bad length %d != %d\n", bytes[0], len - 2); - continue; - } - sum = 0x5a; - for (i = 1; i < len-1; i++) - sum += bytes[i]; - if (sum != bytes[len-1]) { - printf ("bad checksum\n"); - continue; - } - if ((bytes[len-2] & 0x80) == 0) { - continue; - } - if (len == 36) { - memcpy(&telem, bytes + 1, 32); - tick = telem.generic.tick; - switch (telem.generic.type) { - case AO_TELEMETRY_SENSOR_TELEMETRUM: - case AO_TELEMETRY_SENSOR_TELEMINI: - case AO_TELEMETRY_SENSOR_TELENANO: - if (!ao_flight_started) { - ao_flight_ground_accel = telem.sensor.ground_accel; - ao_config.accel_plus_g = telem.sensor.accel_plus_g; - ao_config.accel_minus_g = telem.sensor.accel_minus_g; - ao_flight_started = 1; - } - type = 'A'; - a = telem.sensor.accel; - b = telem.sensor.pres; - break; - } - } else if (len == 99) { - ao_flight_started = 1; - tick = uint16(bytes, 21); - ao_flight_ground_accel = int16(bytes, 7); - ao_config.accel_plus_g = int16(bytes, 17); - ao_config.accel_minus_g = int16(bytes, 19); - type = 'A'; - a = int16(bytes, 23); - b = int16(bytes, 25); - } else if (len == 98) { - ao_flight_started = 1; - tick = uint16(bytes, 20); - ao_flight_ground_accel = int16(bytes, 6); - ao_config.accel_plus_g = int16(bytes, 16); - ao_config.accel_minus_g = int16(bytes, 18); - type = 'A'; - a = int16(bytes, 22); - b = int16(bytes, 24); - } else { - printf("unknown len %d\n", len); - continue; - } - } - if (type != 'F' && !ao_flight_started) - continue; - - switch (type) { - case 'F': - ao_flight_ground_accel = a; - if (ao_config.accel_plus_g == 0) { - ao_config.accel_plus_g = a; - ao_config.accel_minus_g = a + 530; - } - if (ao_config.main_deploy == 0) - ao_config.main_deploy = 250; - ao_flight_started = 1; - break; - case 'S': - break; - case 'A': - ao_adc_static.tick = tick; - ao_adc_static.accel = a; - ao_adc_static.pres_real = b; - if (b < AO_MIN_BARO_VALUE) - b = AO_MIN_BARO_VALUE; - ao_adc_static.pres = b; - ao_records_read++; - ao_insert(); - return; - case 'T': - ao_adc_static.tick = tick; - ao_adc_static.temp = a; - ao_adc_static.v_batt = b; - break; - case 'D': - case 'G': - case 'N': - case 'W': - case 'H': - break; - } - } - - } -} -#define COUNTS_PER_G 264.8 - -void -ao_dump_state(void) -{ -} - -static const struct option options[] = { - { .name = "summary", .has_arg = 0, .val = 's' }, - { .name = "debug", .has_arg = 0, .val = 'd' }, - { 0, 0, 0, 0}, -}; - -void run_flight_fixed(char *name, FILE *f, int summary) -{ - emulator_name = name; - emulator_in = f; - ao_summary = summary; - ao_flight_init(); - ao_flight(); -} - -int -main (int argc, char **argv) -{ - int summary = 0; - int c; - int i; - -#if HAS_ACCEL - emulator_app="full"; -#else - emulator_app="baro"; -#endif - while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { - switch (c) { - case 's': - summary = 1; - break; - case 'd': - ao_flight_debug = 1; - break; - } - } - - if (optind == argc) - run_flight_fixed("", stdin, summary); - else - for (i = optind; i < argc; i++) { - FILE *f = fopen(argv[i], "r"); - if (!f) { - perror(argv[i]); - continue; - } - run_flight_fixed(argv[i], f, summary); - fclose(f); - } -} diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c deleted file mode 100644 index fcdedd30..00000000 --- a/src/ao_gps_print.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif -#include "ao_telem.h" - -void -ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant -{ - char state; - - if (gps_data->flags & AO_GPS_VALID) - state = AO_TELEM_GPS_STATE_LOCKED; - else if (gps_data->flags & AO_GPS_RUNNING) - state = AO_TELEM_GPS_STATE_UNLOCKED; - else - state = AO_TELEM_GPS_STATE_ERROR; - printf(AO_TELEM_GPS_STATE " %c " - AO_TELEM_GPS_NUM_SAT " %d ", - state, - (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); - if (!(gps_data->flags & AO_GPS_VALID)) - return; - printf(AO_TELEM_GPS_LATITUDE " %ld " - AO_TELEM_GPS_LONGITUDE " %ld " - AO_TELEM_GPS_ALTITUDE " %d ", - gps_data->latitude, - gps_data->longitude, - gps_data->altitude); - - if (gps_data->flags & AO_GPS_DATE_VALID) - printf(AO_TELEM_GPS_YEAR " %d " - AO_TELEM_GPS_MONTH " %d " - AO_TELEM_GPS_DAY " %d ", - gps_data->year, - gps_data->month, - gps_data->day); - - printf(AO_TELEM_GPS_HOUR " %d " - AO_TELEM_GPS_MINUTE " %d " - AO_TELEM_GPS_SECOND " %d ", - gps_data->hour, - gps_data->minute, - gps_data->second); - - printf(AO_TELEM_GPS_HDOP " %d ", - gps_data->hdop * 2); - - if (gps_data->flags & AO_GPS_COURSE_VALID) { - printf(AO_TELEM_GPS_HERROR " %d " - AO_TELEM_GPS_VERROR " %d " - AO_TELEM_GPS_VERTICAL_SPEED " %d " - AO_TELEM_GPS_HORIZONTAL_SPEED " %d " - AO_TELEM_GPS_COURSE " %d ", - gps_data->h_error, - gps_data->v_error, - gps_data->climb_rate, - gps_data->ground_speed, - (int) gps_data->course * 2); - } -} - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant -{ - uint8_t c, n, v; - __xdata struct ao_gps_sat_orig *sat; - - n = gps_tracking_data->channels; - if (n == 0) - return; - - sat = gps_tracking_data->sats; - v = 0; - for (c = 0; c < n; c++) { - if (sat->svid) - v++; - sat++; - } - - printf (AO_TELEM_SAT_NUM " %d ", - v); - - sat = gps_tracking_data->sats; - v = 0; - for (c = 0; c < n; c++) { - if (sat->svid) { - printf (AO_TELEM_SAT_SVID "%d %d " - AO_TELEM_SAT_C_N_0 "%d %d ", - v, sat->svid, - v, sat->c_n_1); - v++; - } - sat++; - } -} diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c deleted file mode 100644 index e57f8744..00000000 --- a/src/ao_gps_report.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -ao_gps_report(void) -{ - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_telemetry_location gps_data; - uint8_t date_reported = 0; - - for (;;) { - ao_sleep(&ao_gps_data); - ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(gps_data.flags & AO_GPS_VALID)) - continue; - - gps_log.tick = ao_gps_tick; - gps_log.type = AO_LOG_GPS_TIME; - gps_log.u.gps_time.hour = gps_data.hour; - gps_log.u.gps_time.minute = gps_data.minute; - gps_log.u.gps_time.second = gps_data.second; - gps_log.u.gps_time.flags = gps_data.flags; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LAT; - gps_log.u.gps_latitude = gps_data.latitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LON; - gps_log.u.gps_longitude = gps_data.longitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_ALT; - gps_log.u.gps_altitude.altitude = gps_data.altitude; - gps_log.u.gps_altitude.unused = 0xffff; - ao_log_data(&gps_log); - if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { - 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; - gps_log.u.gps_date.extra = 0; - date_reported = ao_log_data(&gps_log); - } - } -} - -void -ao_gps_tracking_report(void) -{ - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_telemetry_satellite gps_tracking_data; - uint8_t c, n; - - for (;;) { - ao_sleep(&ao_gps_tracking_data); - ao_mutex_get(&ao_gps_mutex); - gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(n = gps_tracking_data.channels)) - continue; - - gps_log.type = AO_LOG_GPS_SAT; - for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) - { - gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; - ao_log_data(&gps_log); - } - } -} - -__xdata struct ao_task ao_gps_report_task; -__xdata struct ao_task ao_gps_tracking_report_task; - -void -ao_gps_report_init(void) -{ - ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); - ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); -} diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c deleted file mode 100644 index f2abbf84..00000000 --- a/src/ao_gps_sirf.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -__xdata uint8_t ao_gps_mutex; -__pdata uint16_t ao_gps_tick; -__xdata struct ao_telemetry_location ao_gps_data; -__xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; - -const char ao_gps_config[] = { - - 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ - 136, /* mode control */ - 0, 0, /* reserved */ - 0, /* degraded mode (allow 1-SV navigation) */ - 0, 0, /* reserved */ - 0, 0, /* user specified altitude */ - 2, /* alt hold mode (disabled, require 3d fixes) */ - 0, /* alt hold source (use last computed altitude) */ - 0, /* reserved */ - 10, /* Degraded time out (10 sec) */ - 10, /* Dead Reckoning time out (10 sec) */ - 0, /* Track smoothing (disabled) */ - 0x00, 0x8e, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ - 166, /* Set message rate */ - 2, /* enable/disable all messages */ - 0, /* message id (ignored) */ - 0, /* update rate (0 = disable) */ - 0, 0, 0, 0, /* reserved */ - 0x00, 0xa8, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ - 143, /* static navigation */ - 0, /* disable */ - 0x00, 0x8f, 0xb0, 0xb3, -}; - -#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) -#define NAV_TYPE_NO_FIX (0 << 0) -#define NAV_TYPE_SV_KF (1 << 0) -#define NAV_TYPE_2_SV_KF (2 << 0) -#define NAV_TYPE_3_SV_KF (3 << 0) -#define NAV_TYPE_4_SV_KF (4 << 0) -#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) -#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) -#define NAV_TYPE_DR (7 << 0) -#define NAV_TYPE_TRICKLE_POWER (1 << 3) -#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) -#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) -#define NAV_TYPE_DGPS_APPLIED (1 << 7) -#define NAV_TYPE_SENSOR_DR (1 << 8) -#define NAV_TYPE_OVERDETERMINED (1 << 9) -#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) -#define NAV_TYPE_FIX_MI_EDIT (1 << 11) -#define NAV_TYPE_INVALID_VELOCITY (1 << 12) -#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) -#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) - -struct sirf_geodetic_nav_data { - uint16_t nav_type; - uint16_t utc_year; - uint8_t utc_month; - uint8_t utc_day; - uint8_t utc_hour; - uint8_t utc_minute; - uint16_t utc_second; - int32_t lat; - int32_t lon; - int32_t alt_msl; - uint16_t ground_speed; - uint16_t course; - int16_t climb_rate; - uint32_t h_error; - uint32_t v_error; - uint8_t num_sv; - uint8_t hdop; -}; - -static __xdata struct sirf_geodetic_nav_data ao_sirf_data; - -struct sirf_measured_sat_data { - uint8_t svid; - uint8_t c_n_1; -}; - -struct sirf_measured_tracker_data { - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - struct sirf_measured_sat_data sats[12]; -}; - -static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; - -static __pdata uint16_t ao_sirf_cksum; -static __pdata uint16_t ao_sirf_len; - -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) - -static uint8_t data_byte(void) -{ - uint8_t c = ao_sirf_byte(); - --ao_sirf_len; - ao_sirf_cksum += c; - return c; -} - -static char __xdata *sirf_target; - -static void sirf_u16(uint8_t offset) -{ - uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); - uint16_t val; - - val = data_byte() << 8; - val |= data_byte (); - *ptr = val; -} - -static void sirf_u8(uint8_t offset) -{ - uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); - uint8_t val; - - val = data_byte (); - *ptr = val; -} - -static void sirf_u32(uint8_t offset) __reentrant -{ - uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); - uint32_t val; - - val = ((uint32_t) data_byte ()) << 24; - val |= ((uint32_t) data_byte ()) << 16; - val |= ((uint32_t) data_byte ()) << 8; - val |= ((uint32_t) data_byte ()); - *ptr = val; -} - -static void sirf_discard(uint8_t len) -{ - while (len--) - data_byte(); -} - -#define SIRF_END 0 -#define SIRF_DISCARD 1 -#define SIRF_U8 2 -#define SIRF_U16 3 -#define SIRF_U32 4 -#define SIRF_U8X10 5 - -struct sirf_packet_parse { - uint8_t type; - uint8_t offset; -}; - -static void -ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant -{ - uint8_t i, offset, j; - - sirf_target = target; - for (i = 0; ; i++) { - offset = parse[i].offset; - switch (parse[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - case SIRF_U8X10: - for (j = 10; j--;) - sirf_u8(offset++); - break; - } - } -} - -static const struct sirf_packet_parse geodetic_nav_data_packet[] = { - { SIRF_DISCARD, 2 }, /* 1 nav valid */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ - { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ - { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ - { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ - { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ - { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ - { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ - { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, - clock bias error, clock drift, - clock drift error, distance, - distance error, heading error */ /* 58 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ - { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ - { SIRF_END, 0 }, /* 91 */ -}; - -static void -ao_sirf_parse_41(void) __reentrant -{ - ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); -} - -static const struct sirf_packet_parse measured_tracker_data_packet[] = { - { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ - { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ - { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ - { SIRF_END, 0 }, -}; - -static const struct sirf_packet_parse measured_sat_data_packet[] = { - { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ - { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ - { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ - { SIRF_END, 0 }, -}; - -static void -ao_sirf_parse_4(void) __reentrant -{ - uint8_t i; - ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); - for (i = 0; i < 12; i++) - ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); -} - -static void -ao_gps_setup(void) __reentrant -{ - uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); - for (k = 0; k < 3; k++) - for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); -} - -static const char ao_gps_set_message_rate[] = { - 0xa0, 0xa2, 0x00, 0x08, - 166, - 0, -}; - -void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant -{ - uint16_t cksum = 0x00a6; - uint8_t i; - - for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); - cksum = 0xa6 + msg + rate; - for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); -} - -static const uint8_t sirf_disable[] = { - 2, - 9, - 10, - 27, - 50, - 52, -}; - -void -ao_gps(void) __reentrant -{ - uint8_t i, k; - uint16_t cksum; - - ao_gps_setup(); - for (k = 0; k < 5; k++) - { - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (i = 0; i < sizeof (sirf_disable); i++) - ao_sirf_set_message_rate(sirf_disable[i], 0); - ao_sirf_set_message_rate(41, 1); - ao_sirf_set_message_rate(4, 1); - } - for (;;) { - /* Locate the begining of the next record */ - while (ao_sirf_byte() != (uint8_t) 0xa0) - ; - if (ao_sirf_byte() != (uint8_t) 0xa2) - continue; - - /* Length */ - ao_sirf_len = ao_sirf_byte() << 8; - ao_sirf_len |= ao_sirf_byte(); - if (ao_sirf_len > 1023) - continue; - - ao_sirf_cksum = 0; - - /* message ID */ - i = data_byte (); /* 0 */ - - switch (i) { - case 41: - if (ao_sirf_len < 90) - break; - ao_sirf_parse_41(); - break; - case 4: - if (ao_sirf_len < 187) - break; - ao_sirf_parse_4(); - break; - } - if (ao_sirf_len != 0) - continue; - - /* verify checksum and end sequence */ - ao_sirf_cksum &= 0x7fff; - cksum = ao_sirf_byte() << 8; - cksum |= ao_sirf_byte(); - if (ao_sirf_cksum != cksum) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb0) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb3) - continue; - - switch (i) { - case 41: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_time(); - ao_gps_data.hour = ao_sirf_data.utc_hour; - ao_gps_data.minute = ao_sirf_data.utc_minute; - ao_gps_data.second = ao_sirf_data.utc_second / 1000; - ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; - if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) - ao_gps_data.flags |= AO_GPS_VALID; - ao_gps_data.latitude = ao_sirf_data.lat; - ao_gps_data.longitude = ao_sirf_data.lon; - ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; - ao_gps_data.ground_speed = ao_sirf_data.ground_speed; - ao_gps_data.course = ao_sirf_data.course / 200; - ao_gps_data.hdop = ao_sirf_data.hdop; - ao_gps_data.climb_rate = ao_sirf_data.climb_rate; - ao_gps_data.flags |= AO_GPS_COURSE_VALID; -#if 0 - if (ao_sirf_data.h_error > 6553500) - ao_gps_data.h_error = 65535; - else - ao_gps_data.h_error = ao_sirf_data.h_error / 100; - if (ao_sirf_data.v_error > 6553500) - ao_gps_data.v_error = 65535; - else - ao_gps_data.v_error = ao_sirf_data.v_error / 100; -#endif - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - break; - case 4: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; - for (i = 0; i < 12; i++) { - ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; - } - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - break; - } - } -} - -__xdata struct ao_task ao_gps_task; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); -} diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c deleted file mode 100644 index 7ac26946..00000000 --- a/src/ao_gps_skytraq.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -#define AO_GPS_LEADER 2 - -static __code char ao_gps_header[] = "GP"; - -__xdata uint8_t ao_gps_mutex; -static __data char ao_gps_char; -static __pdata uint8_t ao_gps_cksum; -static __pdata uint8_t ao_gps_error; - -__pdata uint16_t ao_gps_tick; -__xdata struct ao_telemetry_location ao_gps_data; -__xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -static __pdata uint16_t ao_gps_next_tick; -static __xdata struct ao_telemetry_location ao_gps_next; -static __pdata uint8_t ao_gps_date_flags; -static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; - -#define STQ_S 0xa0, 0xa1 -#define STQ_E 0x0d, 0x0a -#define SKYTRAQ_MSG_2(id,a,b) \ - STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E -#define SKYTRAQ_MSG_3(id,a,b,c) \ - STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E -#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ - STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E -#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ - STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ - (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E - -static __code uint8_t ao_gps_config[] = { - SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ - /* gga interval */ - /* gsa interval */ - /* gsv interval */ - /* gll interval */ - /* rmc interval */ - /* vtg interval */ - /* zda interval */ - /* attributes (0 = update to sram, 1 = update flash too) */ - - SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ - /* 0 = car, 1 = pedestrian */ - /* 0 = update to sram, 1 = update sram + flash */ -}; - -static void -ao_gps_lexchar(void) -{ - if (ao_gps_error) - ao_gps_char = '\n'; - else - ao_gps_char = ao_serial_getchar(); - ao_gps_cksum ^= ao_gps_char; -} - -void -ao_gps_skip_field(void) -{ - while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') - ao_gps_lexchar(); -} - -void -ao_gps_skip_sep(void) -{ - if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') - ao_gps_lexchar(); -} - -__pdata static uint8_t ao_gps_num_width; - -static int16_t -ao_gps_decimal(uint8_t max_width) -{ - int16_t v; - __pdata uint8_t neg = 0; - - ao_gps_skip_sep(); - if (ao_gps_char == '-') { - neg = 1; - ao_gps_lexchar(); - } - v = 0; - ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if (ao_gps_char < '0' || '9' < ao_gps_char) - break; - v = v * (int16_t) 10 + ao_gps_char - '0'; - ao_gps_num_width++; - ao_gps_lexchar(); - } - if (neg) - v = -v; - return v; -} - -static uint8_t -ao_gps_hex(uint8_t max_width) -{ - uint8_t v, d; - - ao_gps_skip_sep(); - v = 0; - ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if ('0' <= ao_gps_char && ao_gps_char <= '9') - d = ao_gps_char - '0'; - else if ('A' <= ao_gps_char && ao_gps_char <= 'F') - d = ao_gps_char - 'A' + 10; - else if ('a' <= ao_gps_char && ao_gps_char <= 'f') - d = ao_gps_char - 'a' + 10; - else - break; - v = (v << 4) | d; - ao_gps_num_width++; - ao_gps_lexchar(); - } - return v; -} - -static int32_t -ao_gps_parse_pos(uint8_t deg_width) __reentrant -{ - int32_t d; - int32_t m; - int32_t f; - - d = ao_gps_decimal(deg_width); - m = ao_gps_decimal(2); - if (ao_gps_char == '.') { - f = ao_gps_decimal(4); - while (ao_gps_num_width < 4) { - f *= 10; - ao_gps_num_width++; - } - } else { - f = 0; - if (ao_gps_char != ',') - ao_gps_error = 1; - } - d = d * 10000000l; - m = m * 10000l + f; - d = d + m * 50 / 3; - return d; -} - -static uint8_t -ao_gps_parse_flag(char no_c, char yes_c) __reentrant -{ - uint8_t ret = 0; - ao_gps_skip_sep(); - if (ao_gps_char == yes_c) - ret = 1; - else if (ao_gps_char == no_c) - ret = 0; - else - ao_gps_error = 1; - ao_gps_lexchar(); - return ret; -} - -static void -ao_nmea_gga() -{ - uint8_t i; - - /* Now read the data into the gps data record - * - * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 - * - * Essential fix data - * - * 025149.000 time (02:51:49.000 GMT) - * 4528.1723,N Latitude 45°28.1723' N - * 12244.2480,W Longitude 122°44.2480' W - * 1 Fix quality: - * 0 = invalid - * 1 = GPS fix (SPS) - * 2 = DGPS fix - * 3 = PPS fix - * 4 = Real Time Kinematic - * 5 = Float RTK - * 6 = estimated (dead reckoning) - * 7 = Manual input mode - * 8 = Simulation mode - * 05 Number of satellites (5) - * 2.0 Horizontal dilution - * 103.5,M Altitude, 103.5M above msl - * -19.5,M Height of geoid above WGS84 ellipsoid - * ? time in seconds since last DGPS update - * 0000 DGPS station ID - * *66 checksum - */ - - ao_gps_next_tick = ao_time(); - ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; - ao_gps_next.hour = ao_gps_decimal(2); - ao_gps_next.minute = ao_gps_decimal(2); - ao_gps_next.second = ao_gps_decimal(2); - ao_gps_skip_field(); /* skip seconds fraction */ - - ao_gps_next.latitude = ao_gps_parse_pos(2); - if (ao_gps_parse_flag('N', 'S')) - ao_gps_next.latitude = -ao_gps_next.latitude; - ao_gps_next.longitude = ao_gps_parse_pos(3); - if (ao_gps_parse_flag('E', 'W')) - ao_gps_next.longitude = -ao_gps_next.longitude; - - i = ao_gps_decimal(0xff); - if (i == 1) - ao_gps_next.flags |= AO_GPS_VALID; - - i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; - if (i > AO_GPS_NUM_SAT_MASK) - i = AO_GPS_NUM_SAT_MASK; - ao_gps_next.flags |= i; - - ao_gps_lexchar(); - i = ao_gps_decimal(0xff); - if (i <= 50) { - i = (uint8_t) 5 * i; - if (ao_gps_char == '.') - i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); - } else - i = 255; - ao_gps_next.hdop = i; - ao_gps_skip_field(); - - ao_gps_next.altitude = ao_gps_decimal(0xff); - ao_gps_skip_field(); /* skip any fractional portion */ - - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - } -} - -static void -ao_nmea_gsv(void) -{ - char c; - uint8_t i; - uint8_t done; - /* Now read the data into the GPS tracking data record - * - * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 - * - * Satellites in view data - * - * 3 Total number of GSV messages - * 1 Sequence number of current GSV message - * 12 Total sats in view (0-12) - * 05 SVID - * 54 Elevation - * 069 Azimuth - * 45 C/N0 in dB - * ... other SVIDs - * 72 checksum - */ - c = ao_gps_decimal(1); /* total messages */ - i = ao_gps_decimal(1); /* message sequence */ - if (i == 1) { - ao_gps_tracking_next.channels = 0; - } - done = (uint8_t) c == i; - ao_gps_lexchar(); - 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; - 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 */ - c = ao_gps_decimal(2); /* C/N0 */ - if (i < AO_MAX_GPS_TRACKING) { - if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0) - ao_gps_tracking_next.channels = i + 1; - } - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } - else - ao_gps_error = 1; - if (ao_gps_error) - ao_gps_tracking_next.channels = 0; - else if (done) { - ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - } -} - -static void -ao_nmea_rmc(void) -{ - char a, c; - uint8_t i; - /* Parse the RMC record to read out the current date */ - - /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 - * - * Recommended Minimum Specific GNSS Data - * - * 111636.932 UTC time 11:16:36.932 - * A Data Valid (V = receiver warning) - * 2447.0949 Latitude - * N North/south indicator - * 12100.5223 Longitude - * E East/west indicator - * 000.0 Speed over ground - * 000.0 Course over ground - * 030407 UTC date (ddmmyy format) - * A Mode indicator: - * N = data not valid - * A = autonomous mode - * D = differential mode - * E = estimated (dead reckoning) mode - * M = manual input mode - * S = simulator mode - * 61 checksum - */ - ao_gps_skip_field(); - for (i = 0; i < 8; i++) { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - a = ao_gps_decimal(2); - c = ao_gps_decimal(2); - i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_gps_next.year = i; - ao_gps_next.month = c; - ao_gps_next.day = a; - ao_gps_date_flags = AO_GPS_DATE_VALID; - } -} - -#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) - -static void -ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) -{ - while (l--) { - uint8_t c = *b++; - if (c == 0xa0) - ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(c); - } -} - -static void -ao_gps_nmea_parse(void) -{ - uint8_t a, b, c; - - ao_gps_cksum = 0; - ao_gps_error = 0; - - for (a = 0; a < AO_GPS_LEADER; a++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[a]) - return; - } - - ao_gps_lexchar(); - a = ao_gps_char; - ao_gps_lexchar(); - b = ao_gps_char; - ao_gps_lexchar(); - c = ao_gps_char; - ao_gps_lexchar(); - - if (ao_gps_char != ',') - return; - - if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { - ao_nmea_gga(); - } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { - ao_nmea_gsv(); - } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { - ao_nmea_rmc(); - } -} - -void -ao_gps(void) __reentrant -{ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); - - /* give skytraq time to boot in case of cold start */ - ao_delay(AO_MS_TO_TICKS(2000)); - - ao_skytraq_sendstruct(ao_gps_config); - - for (;;) { - /* Locate the begining of the next record */ - if (ao_serial_getchar() == '$') { - ao_gps_nmea_parse(); - } - - } -} - -__xdata struct ao_task ao_gps_task; - -static void -gps_dump(void) __reentrant -{ - uint8_t i; - ao_mutex_get(&ao_gps_mutex); - printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); - printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", 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); - printf ("Sats: %d", ao_gps_tracking_data.channels); - for (i = 0; i < ao_gps_tracking_data.channels; i++) - printf (" %d %d", - ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].c_n_1); - printf ("\ndone\n"); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { gps_dump, "g\0Display GPS" }, - { 0, NULL }, -}; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); -} diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c deleted file mode 100644 index 93d7a9ab..00000000 --- a/src/ao_gps_test.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define AO_GPS_TEST -#include "ao_host.h" -#include -#include -#include -#include -#include -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10â· */ - int32_t longitude; /* degrees * 10â· */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -#define ao_telemetry_location ao_gps_orig -#define ao_telemetry_satellite ao_gps_tracking_orig -#define ao_telemetry_satellite_info ao_gps_sat_orig - -void -ao_mutex_get(uint8_t *mutex) -{ -} - -void -ao_mutex_put(uint8_t *mutex) -{ -} - -static int -ao_gps_fd; - -static void -ao_dbg_char(char c) -{ - char line[128]; - line[0] = '\0'; - if (c < ' ') { - if (c == '\n') - sprintf (line, "\n"); - else - sprintf (line, "\\%02x", ((int) c) & 0xff); - } else { - sprintf (line, "%c", c); - } - write(1, line, strlen(line)); -} - -#define QUEUE_LEN 4096 - -static char input_queue[QUEUE_LEN]; -int input_head, input_tail; - -#include - -int -get_millis(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -check_sirf_message(char *from, uint8_t *msg, int len) -{ - uint16_t encoded_len, encoded_cksum; - uint16_t cksum; - uint8_t id; - int i; - - if (msg[0] != 0xa0 || msg[1] != 0xa2) { - printf ("bad header\n"); - return; - } - if (len < 7) { - printf("short\n"); - return; - } - if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { - printf ("bad trailer\n"); - return; - } - encoded_len = (msg[2] << 8) | msg[3]; - id = msg[4]; -/* printf ("%9d: %3d\n", get_millis(), id); */ - if (encoded_len != len - 8) { - if (id != 52) - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); - return; - } - encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; - cksum = 0; - for (i = 4; i < len - 4; i++) - cksum = (cksum + msg[i]) & 0x7fff; - if (encoded_cksum != cksum) { - printf ("cksum mismatch (got %04x wanted %04x)\n", - cksum, encoded_cksum); - return; - } - id = msg[4]; - switch (id) { - case 41:{ - int off = 4; - - uint8_t id; - uint16_t nav_valid; - uint16_t nav_type; - uint16_t week; - uint32_t tow; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint16_t second; - uint32_t sat_list; - int32_t lat; - int32_t lon; - int32_t alt_ell; - int32_t alt_msl; - int8_t datum; - uint16_t sog; - uint16_t cog; - int16_t mag_var; - int16_t climb_rate; - int16_t heading_rate; - uint32_t h_error; - uint32_t v_error; - uint32_t t_error; - uint16_t h_v_error; - -#define get_u8(u) u = (msg[off]); off+= 1 -#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 -#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 - - get_u8(id); - get_u16(nav_valid); - get_u16(nav_type); - get_u16(week); - get_u32(tow); - get_u16(year); - get_u8(month); - get_u8(day); - get_u8(hour); - get_u8(minute); - get_u16(second); - get_u32(sat_list); - get_u32(lat); - get_u32(lon); - get_u32(alt_ell); - get_u32(alt_msl); - get_u8(datum); - get_u16(sog); - get_u16(cog); - get_u16(mag_var); - get_u16(climb_rate); - get_u16(heading_rate); - get_u32(h_error); - get_u32(v_error); - get_u32(t_error); - get_u16(h_v_error); - - - printf ("Geodetic Navigation Data (41):\n"); - printf ("\tNav valid %04x\n", nav_valid); - printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %5d", week); - printf (" TOW %9d", tow); - printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", - year, month, day, - hour, minute, second / 1000.0); - printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g", lat / 1.0e7); - printf (" lon: %g", lon / 1.0e7); - printf (" alt_ell: %g", alt_ell / 100.0); - printf (" alt_msll: %g", alt_msl / 100.0); - printf (" datum: %d\n", datum); - printf ("\tground speed: %g", sog / 100.0); - printf (" course: %g", cog / 100.0); - printf (" climb: %g", climb_rate / 100.0); - printf (" heading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g", h_error / 100.0); - printf (" v error: %g", v_error / 100.0); - printf (" t error: %g", t_error / 100.0); - printf (" h vel error: %g\n", h_v_error / 100.0); - break; - } - case 4: { - int off = 4; - uint8_t id; - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - int j, k; - - get_u8(id); - get_u16(gps_week); - get_u32(gps_tow); - get_u8(channels); - - printf ("Measured Tracker Data (4):\n"); - printf ("GPS week: %d\n", gps_week); - printf ("GPS time of week: %d\n", gps_tow); - printf ("channels: %d\n", channels); - for (j = 0; j < 12; j++) { - uint8_t svid, azimuth, elevation; - uint16_t state; - uint8_t c_n[10]; - get_u8(svid); - get_u8(azimuth); - get_u8(elevation); - get_u16(state); - for (k = 0; k < 10; k++) { - get_u8(c_n[k]); - } - printf ("Sat %3d:", svid); - printf (" aziumuth: %6.1f", azimuth * 1.5); - printf (" elevation: %6.1f", elevation * 0.5); - printf (" state: 0x%02x", state); - printf (" c_n:"); - for (k = 0; k < 10; k++) - printf(" %3d", c_n[k]); - if (state & SIRF_SAT_STATE_ACQUIRED) - printf(" acq,"); - if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) - printf(" car,"); - if (state & SIRF_SAT_BIT_SYNC_COMPLETE) - printf(" bit,"); - if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) - printf(" sub,"); - if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) - printf(" pullin,"); - if (state & SIRF_SAT_CODE_LOCKED) - printf(" code,"); - if (state & SIRF_SAT_ACQUISITION_FAILED) - printf(" fail,"); - if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) - printf(" ephem,"); - printf ("\n"); - } - break; - } - default: - return; - printf ("%s %4d:", from, encoded_len); - for (i = 4; i < len - 4; i++) { - if (((i - 4) & 0xf) == 0) - printf("\n "); - printf (" %3d", msg[i]); - } - printf ("\n"); - } -} - -static uint8_t sirf_message[4096]; -static int sirf_message_len; -static uint8_t sirf_in_message[4096]; -static int sirf_in_len; - -char -ao_serial_getchar(void) -{ - char c; - uint8_t uc; - - while (input_head == input_tail) { - for (;;) { - input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); - if (input_tail < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("getchar"); - exit (1); - } - input_head = 0; - break; - } - } - c = input_queue[input_head]; - input_head = (input_head + 1) % QUEUE_LEN; - uc = c; - if (sirf_in_len || uc == 0xa0) { - if (sirf_in_len < 4096) - sirf_in_message[sirf_in_len++] = uc; - if (uc == 0xb3) { - check_sirf_message("recv", sirf_in_message, sirf_in_len); - sirf_in_len = 0; - } - } - return c; -} - - -void -ao_serial_putchar(char c) -{ - int i; - uint8_t uc = (uint8_t) c; - - if (sirf_message_len || uc == 0xa0) { - if (sirf_message_len < 4096) - sirf_message[sirf_message_len++] = uc; - if (uc == 0xb3) { - check_sirf_message("send", sirf_message, sirf_message_len); - sirf_message_len = 0; - } - } - for (;;) { - i = write(ao_gps_fd, &c, 1); - if (i == 1) { - if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { - .tv_sec = 0, - .tv_nsec = 100 * 1000 * 1000 - }; - tcdrain(ao_gps_fd); -// nanosleep(&delay, NULL); - } - break; - } - if (i < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - perror("putchar"); - exit(1); - } -} - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_57600 1 - -static void -ao_serial_set_speed(uint8_t speed) -{ - int fd = ao_gps_fd; - struct termios termios; - - tcdrain(fd); - tcgetattr(fd, &termios); - switch (speed) { - case AO_SERIAL_SPEED_4800: - cfsetspeed(&termios, B4800); - break; - case AO_SERIAL_SPEED_57600: - cfsetspeed(&termios, B57600); - break; - } - tcsetattr(fd, TCSAFLUSH, &termios); - tcflush(fd, TCIFLUSH); -} - -#define ao_time() 0 - -#include "ao_gps_print.c" -#include "ao_gps_sirf.c" - -void -ao_dump_state(void *wchan) -{ - double lat, lon; - int i; - if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - return; - printf ("%02d:%02d:%02d", - ao_gps_data.hour, ao_gps_data.minute, - ao_gps_data.second); - printf (" nsat %d %svalid", - ao_gps_data.flags & AO_GPS_NUM_SAT_MASK, - ao_gps_data.flags & AO_GPS_VALID ? "" : "not "); - printf (" lat %g lon %g alt %d", - ao_gps_data.latitude / 1.0e7, - ao_gps_data.longitude / 1.0e7, - ao_gps_data.altitude); - printf (" speed %g climb %g course %d", - ao_gps_data.ground_speed / 100.0, - ao_gps_data.climb_rate / 100.0, - ao_gps_data.course * 2); - printf (" hdop %g h_error %d v_error %d", - ao_gps_data.hdop / 5.0, - ao_gps_data.h_error, ao_gps_data.v_error); - printf("\n"); - printf ("\t"); - for (i = 0; i < 12; i++) - printf (" %2d(%02d)", - ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].c_n_1); - printf ("\n"); -} - -int -ao_gps_open(const char *tty) -{ - struct termios termios; - int fd; - - fd = open (tty, O_RDWR); - if (fd < 0) - return -1; - - tcgetattr(fd, &termios); - cfmakeraw(&termios); - cfsetspeed(&termios, B4800); - tcsetattr(fd, TCSAFLUSH, &termios); - - tcdrain(fd); - tcflush(fd, TCIFLUSH); - return fd; -} - -#include - -static const struct option options[] = { - { .name = "tty", .has_arg = 1, .val = 'T' }, - { 0, 0, 0, 0}, -}; - -static void usage(char *program) -{ - fprintf(stderr, "usage: %s [--tty ]\n", program); - exit(1); -} - -int -main (int argc, char **argv) -{ - char *tty = "/dev/ttyUSB0"; - int c; - - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { - switch (c) { - case 'T': - tty = optarg; - break; - default: - usage(argv[0]); - break; - } - } - ao_gps_fd = ao_gps_open(tty); - if (ao_gps_fd < 0) { - perror (tty); - exit (1); - } - ao_gps_setup(); - ao_gps(); -} diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c deleted file mode 100644 index a78fae0f..00000000 --- a/src/ao_gps_test_skytraq.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define AO_GPS_TEST -#include "ao_host.h" -#include -#include -#include -#include -#include -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10â· */ - int32_t longitude; /* degrees * 10â· */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -#define ao_telemetry_location ao_gps_orig -#define ao_telemetry_satellite ao_gps_tracking_orig -#define ao_telemetry_satellite_info ao_gps_sat_orig - -void -ao_mutex_get(uint8_t *mutex) -{ -} - -void -ao_mutex_put(uint8_t *mutex) -{ -} - -static int -ao_gps_fd; - -static void -ao_dbg_char(char c) -{ - char line[128]; - line[0] = '\0'; - if (c < ' ') { - if (c == '\n') - sprintf (line, "\n"); - else - sprintf (line, "\\%02x", ((int) c) & 0xff); - } else { - sprintf (line, "%c", c); - } - write(1, line, strlen(line)); -} - -#define QUEUE_LEN 4096 - -static char input_queue[QUEUE_LEN]; -int input_head, input_tail; - -#include - -int -get_millis(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -check_skytraq_message(char *from, uint8_t *msg, int len) -{ - uint16_t encoded_len, encoded_cksum; - uint16_t cksum; - uint8_t id; - int i; - -// fwrite(msg, 1, len, stdout); - return; - if (msg[0] != 0xa0 || msg[1] != 0xa2) { - printf ("bad header\n"); - return; - } - if (len < 7) { - printf("short\n"); - return; - } - if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { - printf ("bad trailer\n"); - return; - } - encoded_len = (msg[2] << 8) | msg[3]; - id = msg[4]; -/* printf ("%9d: %3d\n", get_millis(), id); */ - if (encoded_len != len - 8) { - if (id != 52) - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); - return; - } - encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; - cksum = 0; - for (i = 4; i < len - 4; i++) - cksum = (cksum + msg[i]) & 0x7fff; - if (encoded_cksum != cksum) { - printf ("cksum mismatch (got %04x wanted %04x)\n", - cksum, encoded_cksum); - return; - } - id = msg[4]; - switch (id) { - case 41:{ - int off = 4; - - uint8_t id; - uint16_t nav_valid; - uint16_t nav_type; - uint16_t week; - uint32_t tow; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint16_t second; - uint32_t sat_list; - int32_t lat; - int32_t lon; - int32_t alt_ell; - int32_t alt_msl; - int8_t datum; - uint16_t sog; - uint16_t cog; - int16_t mag_var; - int16_t climb_rate; - int16_t heading_rate; - uint32_t h_error; - uint32_t v_error; - uint32_t t_error; - uint16_t h_v_error; - -#define get_u8(u) u = (msg[off]); off+= 1 -#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 -#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 - - get_u8(id); - get_u16(nav_valid); - get_u16(nav_type); - get_u16(week); - get_u32(tow); - get_u16(year); - get_u8(month); - get_u8(day); - get_u8(hour); - get_u8(minute); - get_u16(second); - get_u32(sat_list); - get_u32(lat); - get_u32(lon); - get_u32(alt_ell); - get_u32(alt_msl); - get_u8(datum); - get_u16(sog); - get_u16(cog); - get_u16(mag_var); - get_u16(climb_rate); - get_u16(heading_rate); - get_u32(h_error); - get_u32(v_error); - get_u32(t_error); - get_u16(h_v_error); - - - printf ("Geodetic Navigation Data (41):\n"); - printf ("\tNav valid %04x\n", nav_valid); - printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %5d", week); - printf (" TOW %9d", tow); - printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", - year, month, day, - hour, minute, second / 1000.0); - printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g", lat / 1.0e7); - printf (" lon: %g", lon / 1.0e7); - printf (" alt_ell: %g", alt_ell / 100.0); - printf (" alt_msll: %g", alt_msl / 100.0); - printf (" datum: %d\n", datum); - printf ("\tground speed: %g", sog / 100.0); - printf (" course: %g", cog / 100.0); - printf (" climb: %g", climb_rate / 100.0); - printf (" heading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g", h_error / 100.0); - printf (" v error: %g", v_error / 100.0); - printf (" t error: %g", t_error / 100.0); - printf (" h vel error: %g\n", h_v_error / 100.0); - break; - } - case 4: { - int off = 4; - uint8_t id; - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - int j, k; - - get_u8(id); - get_u16(gps_week); - get_u32(gps_tow); - get_u8(channels); - - printf ("Measured Tracker Data (4):\n"); - printf ("GPS week: %d\n", gps_week); - printf ("GPS time of week: %d\n", gps_tow); - printf ("channels: %d\n", channels); - for (j = 0; j < 12; j++) { - uint8_t svid, azimuth, elevation; - uint16_t state; - uint8_t c_n[10]; - get_u8(svid); - get_u8(azimuth); - get_u8(elevation); - get_u16(state); - for (k = 0; k < 10; k++) { - get_u8(c_n[k]); - } - printf ("Sat %3d:", svid); - printf (" aziumuth: %6.1f", azimuth * 1.5); - printf (" elevation: %6.1f", elevation * 0.5); - printf (" state: 0x%02x", state); - printf (" c_n:"); - for (k = 0; k < 10; k++) - printf(" %3d", c_n[k]); - if (state & SIRF_SAT_STATE_ACQUIRED) - printf(" acq,"); - if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) - printf(" car,"); - if (state & SIRF_SAT_BIT_SYNC_COMPLETE) - printf(" bit,"); - if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) - printf(" sub,"); - if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) - printf(" pullin,"); - if (state & SIRF_SAT_CODE_LOCKED) - printf(" code,"); - if (state & SIRF_SAT_ACQUISITION_FAILED) - printf(" fail,"); - if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) - printf(" ephem,"); - printf ("\n"); - } - break; - } - default: - return; - printf ("%s %4d:", from, encoded_len); - for (i = 4; i < len - 4; i++) { - if (((i - 4) & 0xf) == 0) - printf("\n "); - printf (" %3d", msg[i]); - } - printf ("\n"); - } -} - -static uint8_t skytraq_message[4096]; -static int skytraq_message_len; -static uint8_t skytraq_in_message[4096]; -static int skytraq_in_len; - -char -ao_serial_getchar(void) -{ - char c; - uint8_t uc; - - while (input_head == input_tail) { - for (;;) { - input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); - if (input_tail < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("getchar"); - exit (1); - } - input_head = 0; - break; - } - } - c = input_queue[input_head]; - input_head = (input_head + 1) % QUEUE_LEN; - uc = c; -// printf ("c: %02x %c\n", uc, uc); - if (skytraq_in_len || uc == '$') { - if (skytraq_in_len < 4096) - skytraq_in_message[skytraq_in_len++] = uc; - if (uc == 0x0a) { - check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); - skytraq_in_len = 0; - } - } - return c; -} - - -void -ao_serial_putchar(char c) -{ - int i; - uint8_t uc = (uint8_t) c; - - if (skytraq_message_len || uc == 0xa0) { - if (skytraq_message_len < 4096) - skytraq_message[skytraq_message_len++] = uc; - if (uc == 0x0a) { - check_skytraq_message("send", skytraq_message, skytraq_message_len); - skytraq_message_len = 0; - } - } - for (;;) { - i = write(ao_gps_fd, &c, 1); - if (i == 1) { - if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { - .tv_sec = 0, - .tv_nsec = 100 * 1000 * 1000 - }; - tcdrain(ao_gps_fd); -// nanosleep(&delay, NULL); - } - break; - } - if (i < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - perror("putchar"); - exit(1); - } -} - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_57600 2 - -static void -ao_serial_set_speed(uint8_t speed) -{ - int fd = ao_gps_fd; - struct termios termios; - - tcdrain(fd); - tcgetattr(fd, &termios); - switch (speed) { - case AO_SERIAL_SPEED_4800: - cfsetspeed(&termios, B4800); - break; - case AO_SERIAL_SPEED_9600: - cfsetspeed(&termios, B38400); - break; - case AO_SERIAL_SPEED_57600: - cfsetspeed(&termios, B57600); - break; - } - tcsetattr(fd, TCSAFLUSH, &termios); - tcflush(fd, TCIFLUSH); -} - -#define ao_time() 0 - -#include "ao_gps_print.c" -#include "ao_gps_skytraq.c" - -void -ao_dump_state(void *wchan) -{ - double lat, lon; - int i; - if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - return; -} - -int -ao_gps_open(const char *tty) -{ - struct termios termios; - int fd; - - fd = open (tty, O_RDWR); - if (fd < 0) - return -1; - - tcgetattr(fd, &termios); - cfmakeraw(&termios); - cfsetspeed(&termios, B4800); - tcsetattr(fd, TCSAFLUSH, &termios); - - tcdrain(fd); - tcflush(fd, TCIFLUSH); - return fd; -} - -#include - -static const struct option options[] = { - { .name = "tty", .has_arg = 1, .val = 'T' }, - { 0, 0, 0, 0}, -}; - -static void usage(char *program) -{ - fprintf(stderr, "usage: %s [--tty ]\n", program); - exit(1); -} - -int -main (int argc, char **argv) -{ - char *tty = "/dev/ttyUSB0"; - int c; - - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { - switch (c) { - case 'T': - tty = optarg; - break; - default: - usage(argv[0]); - break; - } - } - ao_gps_fd = ao_gps_open(tty); - if (ao_gps_fd < 0) { - perror (tty); - exit (1); - } - ao_gps(); -} diff --git a/src/ao_host.h b/src/ao_host.h deleted file mode 100644 index 65c25fe5..00000000 --- a/src/ao_host.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define _GNU_SOURCE - -#include -#include -#include -#include -#include - -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -/* - * One set of samples read from the A/D converter - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#define __pdata -#define __data -#define __xdata -#define __code -#define __reentrant - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; - -#define ao_led_on(l) -#define ao_led_off(l) -#define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state(wchan) -#define ao_cmd_register(c) -#define ao_usb_disable() -#define ao_telemetry_set_interval(x) -#define ao_delay(x) - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -void -ao_ignite(enum ao_igniter igniter) -{ - printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); -} - -struct ao_task { - int dummy; -}; - -#define ao_add_task(t,f,n) - -#define ao_log_start() -#define ao_log_stop() - -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) - -#define AO_FLIGHT_TEST - -struct ao_adc ao_adc_static; - -FILE *emulator_in; - -void -ao_dump_state(void *wchan); - -void -ao_sleep(void *wchan); - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; - -struct ao_cmds { - void (*func)(void); - const char *help; -}; - - -struct ao_config { - uint16_t main_deploy; - int16_t accel_zero_g; -}; - -#define ao_config_get() - -struct ao_config ao_config = { 250, 16000 }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c deleted file mode 100644 index 5238beb4..00000000 --- a/src/ao_ignite.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -#if IGNITE_ON_P2 -#define AO_IGNITER_DROGUE P2_3 -#define AO_IGNITER_MAIN P2_4 -#define AO_IGNITER_DIR P2DIR -#define AO_IGNITER_DROGUE_BIT (1 << 3) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -#if IGNITE_ON_P0 -#define AO_IGNITER_DROGUE P0_5 -#define AO_IGNITER_MAIN P0_4 -#define AO_IGNITER_DIR P0DIR -#define AO_IGNITER_DROGUE_BIT (1 << 5) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -/* test these values with real igniters */ -#define AO_IGNITER_OPEN 1000 -#define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) -#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) - -struct ao_ignition { - uint8_t request; - uint8_t fired; - uint8_t firing; -}; - -__xdata struct ao_ignition ao_ignition[2]; - -void -ao_ignite(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); -} - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter) -{ - __xdata struct ao_adc adc; - __pdata int16_t value; - __pdata uint8_t request, firing, fired; - - __critical { - ao_adc_get(&adc); - request = ao_ignition[igniter].request; - fired = ao_ignition[igniter].fired; - firing = ao_ignition[igniter].firing; - } - if (firing || (request && !fired)) - return ao_igniter_active; - - value = (AO_IGNITER_CLOSED>>1); - switch (igniter) { - case ao_igniter_drogue: - value = adc.sense_d; - break; - case ao_igniter_main: - value = adc.sense_m; - break; - } - if (value < AO_IGNITER_OPEN) - return ao_igniter_open; - else if (value > AO_IGNITER_CLOSED) - return ao_igniter_ready; - else - return ao_igniter_unknown; -} - -void -ao_igniter_fire(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - } - ao_ignition[igniter].firing = 0; -} - -void -ao_igniter(void) -{ - __xdata enum ao_ignter igniter; - - ao_config_get(); - for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; - } - } - } -} - -void -ao_ignite_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); - } -} - -static __code char * __code igniter_status_names[] = { - "unknown", "ready", "active", "open" -}; - -void -ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant -{ - enum ao_igniter_status status = ao_igniter_status(igniter); - printf("Igniter: %6s Status: %s\n", - name, - igniter_status_names[status]); -} - -void -ao_ignite_test(void) -{ - ao_ignite_print_status(ao_igniter_drogue, "drogue"); - ao_ignite_print_status(ao_igniter_main, "main"); -} - -__code struct ao_cmds ao_ignite_cmds[] = { - { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter" }, - { 0, NULL }, -}; - -__xdata struct ao_task ao_igniter_task; - -void -ao_ignite_set_pins(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; -} - -void -ao_igniter_init(void) -{ - ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); - ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); -} diff --git a/src/ao_intflash.c b/src/ao_intflash.c deleted file mode 100644 index d76d954e..00000000 --- a/src/ao_intflash.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "cc1111.h" - -#define ENDOFCODE (CODESIZE) -#define AO_INTFLASH_BLOCK 1024 -#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) -#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) -#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) - -/* - * 21000 * 24e6 - * FWT = ------------ - * 16e9 - * - * = 31.5 - * - * Round up and use 32 - */ - -#define FLASH_TIMING 0x20 - -#if AO_INTFLASH_BLOCKS < 2 -#error "Too few pages" -#endif - -#if AO_INFTLASH_LOCATION % 1024 != 0 -#error "Pages aren't aligned properly" -#endif - -__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total = sizeof(ao_intflash); - -/* Block size - device is erased in these units. */ -__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; - -/* Storage unit size - device reads and writes must be within blocks of this size. */ -__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; - -__xdata static uint8_t ao_intflash_dma_done; -static uint8_t ao_intflash_dma; - -/* - * The internal flash chip is arranged in 1kB sectors; the - * chip cannot erase in units smaller than that. - * - * Writing happens in units of 2 bytes and - * can only change bits from 1 to 0. So, you can rewrite - * the same contents, or append to an existing page easily enough - */ - -/* - * Erase the specified sector - */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - uint16_t addr; - - if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) - return 0; - - addr = ((uint16_t)(ao_intflash + pos) >> 1); - - FADDRH = addr >> 8; - FADDRL = addr; - - __critical { - _asm - .even - orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE - nop ; Required, see datasheet. - _endasm; - } - - return 1; -} - -/* - * Write to flash - */ - -static void -ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant -{ - pos = ((uint16_t) ao_intflash + pos) >> 1; - - ao_dma_set_transfer(ao_intflash_dma, - d, - &FWDATAXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_FLASH, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - - FADDRH = pos >> 8; - FADDRL = pos; - - ao_dma_start(ao_intflash_dma); - - __critical { - _asm - .even - orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE - nop - _endasm; - } -} - -static void -ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant -{ - static __xdata uint8_t b[2]; - - if (pos & 1) { - b[0] = 0xff; - b[1] = byte; - } else { - b[0] = byte; - b[1] = 0xff; - } - ao_intflash_write_aligned(pos, b, 2); -} - -uint8_t -ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant -{ - uint16_t pos = pos32; - __xdata uint8_t *d = v; - uint8_t oddlen; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - if (len == 0) - return 1; - - if (pos & 1) { - ao_intflash_write_byte(pos++, *d++); - len--; - } - oddlen = len & 1; - len -= oddlen; - if (len) - ao_intflash_write_aligned(pos, d, len); - if (oddlen) - ao_intflash_write_byte(pos + len, d[len]); - - return 1; -} - -/* - * Read from flash - */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - memcpy(d, ao_intflash+pos, len); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ -} - -void -ao_storage_device_info(void) __reentrant -{ - printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); -} - -void -ao_storage_device_init(void) -{ - ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); - - FWT = FLASH_TIMING; -} diff --git a/src/ao_kalman.c b/src/ao_kalman.c deleted file mode 100644 index ee01949e..00000000 --- a/src/ao_kalman.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#include "ao_kalman.h" - -static __pdata int32_t ao_k_height; -static __pdata int32_t ao_k_speed; -static __pdata int32_t ao_k_accel; - -#define AO_K_STEP_100 to_fix16(0.01) -#define AO_K_STEP_2_2_100 to_fix16(0.00005) - -#define AO_K_STEP_10 to_fix16(0.1) -#define AO_K_STEP_2_2_10 to_fix16(0.005) - -#define AO_K_STEP_1 to_fix16(1) -#define AO_K_STEP_2_2_1 to_fix16(0.5) - -__pdata int16_t ao_height; -__pdata int16_t ao_speed; -__pdata int16_t ao_accel; -__pdata int16_t ao_max_height; -static __pdata int32_t ao_avg_height_scaled; -__pdata int16_t ao_avg_height; - -__pdata int16_t ao_error_h; -__pdata int16_t ao_error_h_sq_avg; - -#if HAS_ACCEL -__pdata int16_t ao_error_a; -#endif - -static void -ao_kalman_predict(void) -{ -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + - (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; - - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + - (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; - - return; - } - if (ao_flight_debug) { - printf ("predict speed %g + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, - (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); - } -#endif - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + - (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; -} - -static void -ao_kalman_err_height(void) -{ - int16_t e; - int16_t height_distrust; -#if HAS_ACCEL - int16_t speed_distrust; -#endif - - ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); - - e = ao_error_h; - if (e < 0) - e = -e; - if (e > 127) - e = 127; -#if HAS_ACCEL - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; - ao_error_h_sq_avg += (e * e) >> 2; -#else - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; - ao_error_h_sq_avg += (e * e) >> 4; -#endif - - if (ao_flight_state >= ao_flight_drogue) - return; - height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; -#if HAS_ACCEL - /* speed is stored * 16, but we need to ramp between 200 and 328, so - * we want to multiply by 2. The result is a shift by 3. - */ - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); - if (speed_distrust <= 0) - speed_distrust = 0; - else if (speed_distrust > height_distrust) - height_distrust = speed_distrust; -#endif - if (height_distrust > 0) { -#ifdef AO_FLIGHT_TEST - int old_ao_error_h = ao_error_h; -#endif - if (height_distrust > 0x100) - height_distrust = 0x100; - ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); -#ifdef AO_FLIGHT_TEST - if (ao_flight_debug) { - printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), - (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, - height_distrust / 256.0, - old_ao_error_h, ao_error_h); - } -#endif - } -} - -static void -ao_kalman_correct_baro(void) -{ - ao_kalman_err_height(); -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; - return; - } -#endif - ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; -} - -#if HAS_ACCEL - -static void -ao_kalman_err_accel(void) -{ - int32_t accel; - - accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; - - /* Can't use ao_accel here as it is the pre-prediction value still */ - ao_error_a = (accel - ao_k_accel) >> 16; -} - -static void -ao_kalman_correct_both(void) -{ - ao_kalman_err_height(); - ao_kalman_err_accel(); - -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_1 * ao_error_h + - (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_1 * ao_error_h + - (int32_t) AO_BOTH_K01_1 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_1 * ao_error_h + - (int32_t) AO_BOTH_K11_1 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_1 * ao_error_h + - (int32_t) AO_BOTH_K21_1 * ao_error_a; - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) AO_BOTH_K01_10 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_10 * ao_error_h + - (int32_t) AO_BOTH_K21_10 * ao_error_a; - return; - } - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); - } -#endif - ao_k_height += - (int32_t) AO_BOTH_K00_100 * ao_error_h + - (int32_t) AO_BOTH_K01_100 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_100 * ao_error_h + - (int32_t) AO_BOTH_K21_100 * ao_error_a; -} - -#ifdef FORCE_ACCEL -static void -ao_kalman_correct_accel(void) -{ - ao_kalman_err_accel(); - - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; - return; - } - ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; -} -#endif -#endif /* HAS_ACCEL */ - -void -ao_kalman(void) -{ - ao_kalman_predict(); -#if HAS_ACCEL - if (ao_flight_state <= ao_flight_coast) { -#ifdef FORCE_ACCEL - ao_kalman_correct_accel(); -#else - ao_kalman_correct_both(); -#endif - } else -#endif - ao_kalman_correct_baro(); - ao_height = from_fix(ao_k_height); - ao_speed = from_fix(ao_k_speed); - ao_accel = from_fix(ao_k_accel); - if (ao_height > ao_max_height) - ao_max_height = ao_height; - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) - ao_avg_height = (ao_avg_height_scaled + 1) >> 1; - else if (ao_sample_tick - ao_sample_prev_tick > 5) - ao_avg_height = (ao_avg_height_scaled + 7) >> 4; - else -#endif - ao_avg_height = (ao_avg_height_scaled + 63) >> 7; -#ifdef AO_FLIGHT_TEST - ao_sample_prev_tick = ao_sample_tick; -#endif -} diff --git a/src/ao_led.c b/src/ao_led.c deleted file mode 100644 index 5beed58d..00000000 --- a/src/ao_led.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__pdata uint8_t ao_led_enable; - -void -ao_led_on(uint8_t colors) -{ - P1 |= (colors & ao_led_enable); -} - -void -ao_led_off(uint8_t colors) -{ - P1 &= ~(colors & ao_led_enable); -} - -void -ao_led_set(uint8_t colors) -{ - P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable); -} - -void -ao_led_toggle(uint8_t colors) -{ - P1 ^= (colors & ao_led_enable); -} - -void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant -{ - ao_led_on(colors); - ao_delay(ticks); - ao_led_off(colors); -} - -void -ao_led_init(uint8_t enable) -{ - ao_led_enable = enable; - P1SEL &= ~enable; - P1 &= ~enable; - P1DIR |= enable; -} diff --git a/src/ao_log.c b/src/ao_log.c deleted file mode 100644 index 6d3ad535..00000000 --- a/src/ao_log.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__pdata uint32_t ao_log_current_pos; -__pdata uint32_t ao_log_end_pos; -__pdata uint32_t ao_log_start_pos; -__xdata uint8_t ao_log_running; -__pdata enum flight_state ao_log_state; -__xdata uint16_t ao_flight_number; - -__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; - -void -ao_log_flush(void) -{ - ao_storage_flush(); -} - -/* - * When erasing a flight log, make sure the config block - * has an up-to-date version of the current flight number - */ - -struct ao_log_erase { - uint8_t unused; - uint16_t flight; -}; - -static __xdata struct ao_log_erase erase; - -#define LOG_MAX_ERASE 16 - -static uint32_t -ao_log_erase_pos(uint8_t i) -{ - return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; -} - -void -ao_log_write_erase(uint8_t pos) -{ - erase.unused = 0x00; - erase.flight = ao_flight_number; - ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); - ao_storage_flush(); -} - -static void -ao_log_read_erase(uint8_t pos) -{ - ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); -} - - -static void -ao_log_erase_mark(void) -{ - uint8_t i; - - for (i = 0; i < LOG_MAX_ERASE; i++) { - ao_log_read_erase(i); - if (erase.unused == 0 && erase.flight == ao_flight_number) - return; - if (erase.unused == 0xff) { - ao_log_write_erase(i); - return; - } - } - ao_config_put(); -} - -static uint8_t -ao_log_slots() -{ - return (uint8_t) (ao_storage_config / ao_config.flight_log_max); -} - -uint32_t -ao_log_pos(uint8_t slot) -{ - return ((slot) * ao_config.flight_log_max); -} - -static uint16_t -ao_log_max_flight(void) -{ - uint8_t log_slot; - uint8_t log_slots; - uint16_t log_flight; - uint16_t max_flight = 0; - - /* Scan the log space looking for the biggest flight number */ - log_slots = ao_log_slots(); - for (log_slot = 0; log_slot < log_slots; log_slot++) { - log_flight = ao_log_flight(log_slot); - if (!log_flight) - continue; - if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) - max_flight = log_flight; - } - return max_flight; -} - -void -ao_log_scan(void) __reentrant -{ - uint8_t log_slot; - uint8_t log_slots; - uint8_t log_want; - - ao_config_get(); - - ao_flight_number = ao_log_max_flight(); - if (ao_flight_number) - if (++ao_flight_number == 0) - ao_flight_number = 1; - - /* Now look through the log of flight numbers from erase operations and - * see if the last one is bigger than what we found above - */ - for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { - ao_log_read_erase(log_slot); - if (erase.unused == 0) { - if (ao_flight_number == 0 || - (int16_t) (erase.flight - ao_flight_number) > 0) - ao_flight_number = erase.flight; - break; - } - } - if (ao_flight_number == 0) - ao_flight_number = 1; - - /* With a flight number in hand, find a place to write a new log, - * use the target flight number to index the available log slots so - * that we write logs to each spot about the same number of times. - */ - - /* Find a log slot for the next flight, if available */ - ao_log_current_pos = ao_log_end_pos = 0; - log_slots = ao_log_slots(); - log_want = (ao_flight_number - 1) % log_slots; - log_slot = log_want; - do { - if (ao_log_flight(log_slot) == 0) { - ao_log_current_pos = ao_log_pos(log_slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - break; - } - if (++log_slot >= log_slots) - log_slot = 0; - } while (log_slot != log_want); - - ao_wakeup(&ao_flight_number); -} - -void -ao_log_start(void) -{ - /* start logging */ - ao_log_running = 1; - ao_wakeup(&ao_log_running); -} - -void -ao_log_stop(void) -{ - ao_log_running = 0; - ao_log_flush(); -} - -uint8_t -ao_log_present(void) -{ - return ao_log_max_flight() != 0; -} - -uint8_t -ao_log_full(void) -{ - return ao_log_current_pos == ao_log_end_pos; -} - -static __xdata struct ao_task ao_log_task; - -void -ao_log_list(void) __reentrant -{ - uint8_t slot; - uint8_t slots; - uint16_t flight; - - slots = ao_log_slots(); - for (slot = 0; slot < slots; slot++) - { - flight = ao_log_flight(slot); - if (flight) - printf ("flight %d start %x end %x\n", - flight, - (uint16_t) (ao_log_pos(slot) >> 8), - (uint16_t) (ao_log_pos(slot+1) >> 8)); - } - printf ("done\n"); -} - -void -ao_log_delete(void) __reentrant -{ - uint8_t slot; - uint8_t slots; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - - slots = ao_log_slots(); - /* Look for the flight log matching the requested flight */ - if (ao_cmd_lex_i) { - for (slot = 0; slot < slots; slot++) { - if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_erase_mark(); - ao_log_current_pos = ao_log_pos(slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - while (ao_log_current_pos < ao_log_end_pos) { - uint8_t i; - static __xdata uint8_t b; - - /* - * Check to see if we've reached the end of - * the used memory to avoid re-erasing the same - * memory over and over again - */ - for (i = 0; i < 16; i++) { - if (ao_storage_read(ao_log_current_pos + i, &b, 1)) - if (b != 0xff) - break; - } - if (i == 16) - break; - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; - } - puts("Erased"); - return; - } - } - } - printf("No such flight: %d\n", ao_cmd_lex_i); -} - -__code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List flight logs" }, - { ao_log_delete, "d \0Delete flight" }, - { 0, NULL }, -}; - -void -ao_log_init(void) -{ - ao_log_running = 0; - - /* For now, just log the flight starting at the begining of eeprom */ - ao_log_state = ao_flight_invalid; - - ao_cmd_register(&ao_log_cmds[0]); - - /* Create a task to log events to eeprom */ - ao_add_task(&ao_log_task, ao_log, "log"); -} diff --git a/src/ao_log_big.c b/src/ao_log_big.c deleted file mode 100644 index 74d94c4b..00000000 --- a/src/ao_log_big.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static __xdata uint8_t ao_log_mutex; -static __xdata struct ao_log_record log; - -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant -{ - uint8_t sum = 0x5a; - uint8_t i; - - for (i = 0; i < sizeof (struct ao_log_record); i++) - sum += *b++; - return -sum; -} - -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_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - log, - sizeof (struct ao_log_record)); - ao_log_current_pos += sizeof (struct ao_log_record); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} - -static uint8_t -ao_log_dump_check_data(void) -{ - if (ao_log_csum((uint8_t *) &log) != 0) - return 0; - return 1; -} - -static __data uint8_t ao_log_adc_pos; - -/* a hack to make sure that ao_log_records fill the eeprom block in even units */ -typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; - -#define AO_SENSOR_INTERVAL_ASCENT 1 -#define AO_SENSOR_INTERVAL_DESCENT 10 -#define AO_OTHER_INTERVAL 32 - -void -ao_log(void) -{ - __pdata uint16_t next_sensor, next_other; - - ao_storage_setup(); - - ao_log_scan(); - - while (!ao_log_running) - ao_sleep(&ao_log_running); - - log.type = AO_LOG_FLIGHT; - log.tick = ao_sample_tick; -#if HAS_ACCEL - log.u.flight.ground_accel = ao_ground_accel; -#endif - log.u.flight.flight = ao_flight_number; - ao_log_data(&log); - - /* Write the whole contents of the ring to the log - * when starting up. - */ - ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); - next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; - ao_log_state = ao_flight_startup; - for (;;) { - /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_sample_adc) { - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - if ((int16_t) (log.tick - next_sensor) >= 0) { - log.type = AO_LOG_SENSOR; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if (ao_log_state <= ao_flight_coast) - next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; - else - next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; - } - if ((int16_t) (log.tick - next_other) >= 0) { - log.type = AO_LOG_TEMP_VOLT; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; - ao_log_data(&log); - log.type = AO_LOG_DEPLOY; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; - ao_log_data(&log); - next_other = log.tick + AO_OTHER_INTERVAL; - } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_sample_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } - - /* Wait for a while */ - ao_delay(AO_MS_TO_TICKS(100)); - - /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); - } -} - -uint16_t -ao_log_flight(uint8_t slot) -{ - if (!ao_storage_read(ao_log_pos(slot), - &log, - sizeof (struct ao_log_record))) - return 0; - - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) - return log.u.flight.flight; - return 0; -} diff --git a/src/ao_log_telem.c b/src/ao_log_telem.c deleted file mode 100644 index 1b472efe..00000000 --- a/src/ao_log_telem.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -void -ao_log_write_erase(uint8_t pos) -{ - (void) pos; -} - -uint8_t -ao_log_present(void) -{ - return 0; -} diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c deleted file mode 100644 index d5a3b99f..00000000 --- a/src/ao_log_tiny.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static __data uint16_t ao_log_tiny_interval; - -#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) -#if USE_FAST_ASCENT_LOG -#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) -#define AO_PAD_RING 8 -#else -#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT -#define AO_PAD_RING 2 -#endif - -__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; - -void -ao_log_tiny_set_interval(uint16_t ticks) -{ - ao_log_tiny_interval = ticks; -} - - -static void ao_log_tiny_data(uint16_t d) -{ - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); - ao_log_current_pos += 2; - } -} - -static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; -static __pdata uint8_t ao_log_pad_ring_pos; - -#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) - -static void ao_log_tiny_queue(uint16_t d) -{ - ao_log_pad_ring[ao_log_pad_ring_pos] = d; - ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); -} - -static void ao_log_tiny_start(void) -{ - uint8_t p; - uint16_t d; - - ao_log_tiny_data(ao_flight_number); - ao_log_tiny_data(ao_ground_pres); - p = ao_log_pad_ring_pos; - do { - d = ao_log_pad_ring[p]; - /* - * ignore unwritten slots - */ - if (d) - ao_log_tiny_data(d); - p = ao_pad_ring_next(p); - } while (p != ao_log_pad_ring_pos); -} - -void -ao_log(void) -{ - uint16_t last_time; - uint16_t now; - enum ao_flight_state ao_log_tiny_state; - int32_t sum; - int16_t count; - uint8_t ao_log_adc; - uint8_t ao_log_started = 0; - - ao_storage_setup(); - - ao_log_scan(); - - ao_log_tiny_state = ao_flight_invalid; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; - sum = 0; - count = 0; - ao_log_adc = ao_sample_adc; - last_time = ao_time(); - for (;;) { - - /* - * Add in pending sample data - */ - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (ao_log_adc != ao_sample_adc) { - sum += ao_adc_ring[ao_log_adc].pres; - count++; - ao_log_adc = ao_adc_ring_next(ao_log_adc); - } - if (ao_log_running) { - if (!ao_log_started) { - ao_log_tiny_start(); - ao_log_started = 1; - } - if (ao_flight_state != ao_log_tiny_state) { - ao_log_tiny_data(ao_flight_state | 0x8000); - ao_log_tiny_state = ao_flight_state; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; -#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT - if (ao_log_tiny_state <= ao_flight_coast) - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; -#endif - if (ao_log_tiny_state == ao_flight_landed) - ao_log_stop(); - } - } - - /* Stop logging when told to */ - if (!ao_log_running && ao_log_started) - ao_exit(); - - /* - * Write out the sample when finished - */ - now = ao_time(); - if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { - count = sum / count; - if (ao_log_started) - ao_log_tiny_data(count); - else - ao_log_tiny_queue(count); - sum = 0; - count = 0; - last_time = now; - } - } -} - -uint16_t -ao_log_flight(uint8_t slot) -{ - static __xdata uint16_t flight; - - (void) slot; - ao_storage_read(0, &flight, 2); - if (flight == 0xffff) - flight = 0; - return flight; -} diff --git a/src/ao_m25.c b/src/ao_m25.c deleted file mode 100644 index d7208273..00000000 --- a/src/ao_m25.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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" - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -/* - * Each flash chip is arranged in 64kB sectors; the - * chip cannot erase in units smaller than that. - * - * Writing happens in units of 256 byte pages and - * can only change bits from 1 to 0. So, you can rewrite - * the same contents, or append to an existing page easily enough - */ - -#define M25_WREN 0x06 /* Write Enable */ -#define M25_WRDI 0x04 /* Write Disable */ -#define M25_RDID 0x9f /* Read Identification */ -#define M25_RDSR 0x05 /* Read Status Register */ -#define M25_WRSR 0x01 /* Write Status Register */ -#define M25_READ 0x03 /* Read Data Bytes */ -#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ -#define M25_PP 0x02 /* Page Program */ -#define M25_SE 0xd8 /* Sector Erase */ -#define M25_BE 0xc7 /* Bulk Erase */ -#define M25_DP 0xb9 /* Deep Power-down */ - -/* RDID response */ -#define M25_MANUF_OFFSET 0 -#define M25_MEMORY_TYPE_OFFSET 1 -#define M25_CAPACITY_OFFSET 2 -#define M25_UID_OFFSET 3 -#define M25_CFI_OFFSET 4 -#define M25_RDID_LEN 4 /* that's all we need */ - -#define M25_CAPACITY_128KB 0x11 -#define M25_CAPACITY_256KB 0x12 -#define M25_CAPACITY_512KB 0x13 -#define M25_CAPACITY_1MB 0x14 -#define M25_CAPACITY_2MB 0x15 - -/* - * Status register bits - */ - -#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ -#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ -#define M25_STATUS_BP_SHIFT (2) -#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ -#define M25_STATUS_WIP (1 << 0) /* Write in progress */ - -/* - * On teleterra, the m25 chip select pins are - * wired on P0_0 through P0_3. - */ - -#if M25_MAX_CHIPS > 1 -static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ -static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ -static uint8_t ao_m25_numchips; /* number of chips detected */ -#endif -static uint8_t ao_m25_total; /* total sectors available */ -static uint8_t ao_m25_wip; /* write in progress */ - -static __xdata uint8_t ao_m25_mutex; - -/* - * This little array is abused to send and receive data. A particular - * caution -- the read and write addresses are written into the last - * three bytes of the array by ao_m25_set_page_address and then the - * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither - * of which touch those last three bytes. - */ - -static __xdata uint8_t ao_m25_instruction[4]; - -#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) -#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) - -#define M25_BLOCK_SHIFT 16 -#define M25_BLOCK 65536L -#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) -#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) - -/* - * Block until the specified chip is done writing - */ -static void -ao_m25_wait_wip(uint8_t cs) -{ - if (ao_m25_wip & cs) { - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDSR; - ao_spi_send(ao_m25_instruction, 1); - do { - ao_spi_recv(ao_m25_instruction, 1); - } while (ao_m25_instruction[0] & M25_STATUS_WIP); - M25_DESELECT(cs); - ao_m25_wip &= ~cs; - } -} - -/* - * Set the write enable latch so that page program and sector - * erase commands will work. Also mark the chip as busy writing - * so that future operations will block until the WIP bit goes off - */ -static void -ao_m25_write_enable(uint8_t cs) -{ - M25_SELECT(cs); - ao_m25_instruction[0] = M25_WREN; - ao_spi_send(&ao_m25_instruction, 1); - M25_DESELECT(cs); - ao_m25_wip |= cs; -} - - -/* - * Returns the number of 64kB sectors - */ -static uint8_t -ao_m25_read_capacity(uint8_t cs) -{ - uint8_t capacity; - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); - M25_DESELECT(cs); - - /* Check to see if the chip is present */ - if (ao_m25_instruction[0] == 0xff) - return 0; - capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; - - /* Sanity check capacity number */ - if (capacity < 0x11 || 0x1f < capacity) - return 0; - return 1 << (capacity - 0x10); -} - -static uint8_t -ao_m25_set_address(uint32_t pos) -{ - uint8_t chip; -#if M25_MAX_CHIPS > 1 - uint8_t size; - - for (chip = 0; chip < ao_m25_numchips; chip++) { - size = ao_m25_size[chip]; - if (M25_POS_TO_SECTOR(pos) < size) - break; - pos -= M25_SECTOR_TO_POS(size); - } - if (chip == ao_m25_numchips) - return 0xff; - - chip = ao_m25_pin[chip]; -#else - chip = M25_CS_MASK; -#endif - ao_m25_wait_wip(chip); - - ao_m25_instruction[1] = pos >> 16; - ao_m25_instruction[2] = pos >> 8; - ao_m25_instruction[3] = pos; - return chip; -} - -/* - * Scan the possible chip select lines - * to see which flash chips are connected - */ -static uint8_t -ao_m25_scan(void) -{ -#if M25_MAX_CHIPS > 1 - uint8_t pin, size; -#endif - - if (ao_m25_total) - return 1; - -#if M25_MAX_CHIPS > 1 - ao_m25_numchips = 0; - for (pin = 1; pin != 0; pin <<= 1) { - if (M25_CS_MASK & pin) { - size = ao_m25_read_capacity(pin); - if (size != 0) { - ao_m25_size[ao_m25_numchips] = size; - ao_m25_pin[ao_m25_numchips] = pin; - ao_m25_total += size; - ao_m25_numchips++; - } - } - } -#else - ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); -#endif - if (!ao_m25_total) - return 0; - ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); - ao_storage_block = M25_BLOCK; - ao_storage_config = ao_storage_total - M25_BLOCK; - ao_storage_unit = 256; - return 1; -} - -/* - * Erase the specified sector - */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) - return 0; - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - - ao_m25_wait_wip(cs); - ao_m25_write_enable(cs); - - ao_m25_instruction[0] = M25_SE; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - M25_DESELECT(cs); - ao_m25_wip |= cs; - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -/* - * Write to flash - */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - ao_m25_write_enable(cs); - - ao_m25_instruction[0] = M25_PP; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_send(d, len); - M25_DESELECT(cs); - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -/* - * Read from flash - */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - - /* No need to use the FAST_READ as we're running at only 8MHz */ - ao_m25_instruction[0] = M25_READ; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_recv(d, len); - M25_DESELECT(cs); - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - ao_mutex_put(&ao_m25_mutex); -} - -void -ao_storage_device_info(void) __reentrant -{ - uint8_t cs; -#if M25_MAX_CHIPS > 1 - uint8_t chip; -#endif - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - ao_mutex_put(&ao_m25_mutex); - -#if M25_MAX_CHIPS > 1 - printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); - for (chip = 0; chip < ao_m25_numchips; chip++) - printf ("Flash chip %d select %02x size %d\n", - chip, ao_m25_pin[chip], ao_m25_size[chip]); -#else - printf ("Detected chips 1 size %d\n", ao_m25_total); -#endif - - printf ("Available chips:\n"); - for (cs = 1; cs != 0; cs <<= 1) { - if ((M25_CS_MASK & cs) == 0) - continue; - - ao_mutex_get(&ao_m25_mutex); - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); - M25_DESELECT(cs); - - printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", - cs, - ao_m25_instruction[M25_MANUF_OFFSET], - ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], - ao_m25_instruction[M25_CAPACITY_OFFSET], - ao_m25_instruction[M25_UID_OFFSET]); - ao_mutex_put(&ao_m25_mutex); - } -} - -void -ao_storage_device_init(void) -{ - /* Set up chip select wires */ - SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ - SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ - SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ -} diff --git a/src/ao_main.c b/src/ao_main.c deleted file mode 100644 index 25acccfc..00000000 --- a/src/ao_main.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_cmd_init(); - ao_ee_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); - ao_usb_init(); - ao_serial_init(); - ao_gps_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_start_scheduler(); -} diff --git a/src/ao_monitor.c b/src/ao_monitor.c deleted file mode 100644 index 69eb58e8..00000000 --- a/src/ao_monitor.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_telem.h" - -#if !HAS_MONITOR -#error Must define HAS_MONITOR to 1 -#endif - -__xdata uint8_t ao_monitoring; -__pdata uint8_t ao_monitor_led; - -#define AO_MONITOR_RING 8 - -__xdata union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) - -__data uint8_t ao_monitor_head; - -void -ao_monitor_get(void) -{ - uint8_t size; - - for (;;) { - switch (ao_monitoring) { - case 0: - ao_sleep(&ao_monitoring); - continue; - case AO_MONITORING_ORIG: - size = sizeof (struct ao_telemetry_orig_recv); - break; - case AO_MONITORING_TINY: - size = sizeof (struct ao_telemetry_tiny_recv); - break; - default: - if (ao_monitoring > AO_MAX_TELEMETRY) - ao_monitoring = AO_MAX_TELEMETRY; - size = ao_monitoring; - break; - } - if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) - continue; - ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); - ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_toggle(ao_monitor_led); - } -} - -void -ao_monitor_put(void) -{ - __xdata char callsign[AO_MAX_CALLSIGN+1]; - - uint8_t ao_monitor_tail; - uint8_t state; - uint8_t sum, byte; - int16_t rssi; - __xdata union ao_monitor *m; - -#define recv_raw ((m->raw)) -#define recv_orig ((m->orig)) -#define recv_tiny ((m->tiny)) - - ao_monitor_tail = ao_monitor_head; - for (;;) { - while (ao_monitor_tail == ao_monitor_head) - ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - m = &ao_monitor_ring[ao_monitor_tail]; - ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); - switch (ao_monitoring) { - case AO_MONITORING_ORIG: - state = recv_orig.telemetry_orig.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_orig.rssi >> 1) - 74; - memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { - - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_orig.telemetry_orig.serial, - recv_orig.telemetry_orig.flight, - rssi, - ao_state_names[state], - recv_orig.telemetry_orig.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_ACCEL " %d " - AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_orig.telemetry_orig.adc.accel, - recv_orig.telemetry_orig.adc.pres, - recv_orig.telemetry_orig.adc.temp, - recv_orig.telemetry_orig.adc.v_batt, - recv_orig.telemetry_orig.adc.sense_d, - recv_orig.telemetry_orig.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_ACCEL_GROUND " %d " - AO_TELEM_CAL_BARO_GROUND " %d " - AO_TELEM_CAL_ACCEL_PLUS " %d " - AO_TELEM_CAL_ACCEL_MINUS " %d ", - recv_orig.telemetry_orig.ground_accel, - recv_orig.telemetry_orig.ground_pres, - recv_orig.telemetry_orig.accel_plus_g, - recv_orig.telemetry_orig.accel_minus_g); - - if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d ", - recv_orig.telemetry_orig.height, - recv_orig.telemetry_orig.u.k.speed, - recv_orig.telemetry_orig.accel); - } else { - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d ", - recv_orig.telemetry_orig.accel, - recv_orig.telemetry_orig.u.flight_vel, - recv_orig.telemetry_orig.height); - } - ao_gps_print(&recv_orig.telemetry_orig.gps); - ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); - putchar('\n'); - ao_rssi_set(rssi); - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - case AO_MONITORING_TINY: - state = recv_tiny.telemetry_tiny.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_tiny.telemetry_tiny.serial, - recv_tiny.telemetry_tiny.flight, - rssi, - ao_state_names[state], - recv_tiny.telemetry_tiny.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_tiny.telemetry_tiny.adc.pres, - recv_tiny.telemetry_tiny.adc.temp, - recv_tiny.telemetry_tiny.adc.v_batt, - recv_tiny.telemetry_tiny.adc.sense_d, - recv_tiny.telemetry_tiny.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_BARO_GROUND " %d ", - recv_tiny.telemetry_tiny.ground_pres); - -#if 1 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d\n", - recv_tiny.telemetry_tiny.height, - recv_tiny.telemetry_tiny.speed, - recv_tiny.telemetry_tiny.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d\n", - recv_tiny.telemetry_tiny.flight_accel, - recv_tiny.telemetry_tiny.flight_vel, - recv_tiny.telemetry_tiny.flight_pres); -#endif - ao_rssi_set(rssi); - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - default: - printf ("TELEM %02x", ao_monitoring + 2); - sum = 0x5a; - for (state = 0; state < ao_monitoring + 2; state++) { - byte = recv_raw.packet[state]; - sum += byte; - printf("%02x", byte); - } - printf("%02x\n", sum); - break; - } - ao_usb_flush(); - } -} - -__xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_put_task; - -void -ao_set_monitor(uint8_t monitoring) -{ - if (ao_monitoring) - ao_radio_recv_abort(); - ao_monitoring = monitoring; - ao_wakeup(&ao_monitoring); -} - -static void -set_monitor(void) -{ - ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i); -} - -__code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, - { 0, NULL }, -}; - -void -ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant -{ - ao_monitor_led = monitor_led; - ao_monitoring = monitoring; - ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); - ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); -} diff --git a/src/ao_mutex.c b/src/ao_mutex.c deleted file mode 100644 index c82a7d57..00000000 --- a/src/ao_mutex.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -ao_mutex_get(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex == ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - while (*mutex) - ao_sleep(mutex); - *mutex = ao_cur_task->task_id; - } -} - -void -ao_mutex_put(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex != ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - *mutex = 0; - ao_wakeup(mutex); - } -} diff --git a/src/ao_packet.c b/src/ao_packet.c deleted file mode 100644 index f627e02b..00000000 --- a/src/ao_packet.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata struct ao_packet_recv ao_rx_packet; -__xdata struct ao_packet ao_tx_packet; -__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_seq; - -__xdata struct ao_task ao_packet_task; -__xdata uint8_t ao_packet_enable; -__xdata uint8_t ao_packet_master_sleeping; - -void -ao_packet_send(void) -{ - ao_led_on(AO_LED_RED); - /* If any tx data is pending then copy it into the tx packet */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) { - memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); - ao_tx_packet.len = ao_packet_tx_used; - ao_tx_packet.seq++; - ao_packet_tx_used = 0; - ao_wakeup(&tx_data); - } - ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); - ao_led_off(AO_LED_RED); -} - -uint8_t -ao_packet_recv(void) -{ - uint8_t dma_done; - -#ifdef AO_LED_GREEN - ao_led_on(AO_LED_GREEN); -#endif - dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); -#ifdef AO_LED_GREEN - ao_led_off(AO_LED_GREEN); -#endif - - /* Check to see if we got a valid packet */ - if (!dma_done) - return 0; - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return 0; - - /* SYN packets carry no data */ - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; - ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - - /* Check for incoming data at the next sequence and - * for an empty data buffer - */ - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && - ao_packet_rx_used == ao_packet_rx_len) { - - /* Copy data to the receive data buffer and set up the - * offsets - */ - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - - /* Mark the sequence that we've received to - * let the sender know when we return a packet - */ - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - - /* Poke anyone looking for received data */ - ao_wakeup(&ao_stdin_ready); - } - } - - /* If the other side has seen the latest data we queued, - * wake up any task waiting to send data and let them go again - */ - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); - } - return 1; -} - -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - -#if PACKET_HAS_MASTER -void -ao_packet_flush(void) -{ - /* If there is data to send, and this is the master, - * then poke the master to send all queued data - */ - if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); -} -#endif /* PACKET_HAS_MASTER */ - -void -ao_packet_putchar(char c) __reentrant -{ - while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { -#if PACKET_HAS_MASTER - ao_packet_flush(); -#endif - ao_sleep(&tx_data); - } - - if (ao_packet_enable) - tx_data[ao_packet_tx_used++] = c; -} - -char -ao_packet_pollchar(void) __critical -{ - if (!ao_packet_enable) - return AO_READ_AGAIN; - - if (ao_packet_rx_used == ao_packet_rx_len) - return AO_READ_AGAIN; - - return rx_data[ao_packet_rx_used++]; -} diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c deleted file mode 100644 index b0fdf5a8..00000000 --- a/src/ao_packet_master.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static char -ao_packet_getchar(void) __critical -{ - char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { - if (!ao_packet_enable) - break; - if (ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); - flush(); - ao_sleep(&ao_stdin_ready); - } - return c; -} - -static void -ao_packet_echo(void) __reentrant -{ - char c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (c != AO_READ_AGAIN) - putchar(c); - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; -static __xdata uint16_t ao_packet_master_delay; -static __xdata uint16_t ao_packet_master_time; - -#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) -#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) -#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) - -static void -ao_packet_master_busy(void) -{ - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - ao_packet_master_time = ao_time(); -} - -static void -ao_packet_master_check_busy(void) -{ - int16_t idle; - if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) - return; - idle = (int16_t) (ao_time() - ao_packet_master_time); - - if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; -} - -void -ao_packet_master(void) -{ - ao_config_get(); - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - ao_packet_master_time = ao_time(); - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - while (ao_packet_enable) { - memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - ao_packet_send(); - if (ao_tx_packet.len) - ao_packet_master_busy(); - ao_packet_master_check_busy(); - ao_alarm(ao_packet_master_delay); - if (ao_packet_recv()) { - /* if we can transmit data, do so */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) - continue; - if (ao_rx_packet.packet.len) - ao_packet_master_busy(); - ao_packet_master_sleeping = 1; - ao_alarm(ao_packet_master_delay); - ao_sleep(&ao_packet_master_sleeping); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - flush(); -#if HAS_MONITOR - ao_set_monitor(0); -#endif - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { - 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; - while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_wakeup(&ao_stdin_ready); - ao_delay(AO_MS_TO_TICKS(10)); - } -} - - - -__code struct ao_cmds ao_packet_master_cmds[] = { - { ao_packet_forward, "p\0Remote packet link." }, - { 0, NULL }, -}; - -void -ao_packet_master_init(void) -{ - ao_cmd_register(&ao_packet_master_cmds[0]); -} diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c deleted file mode 100644 index 9f14052a..00000000 --- a/src/ao_packet_slave.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -ao_packet_slave(void) -{ - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - if (ao_packet_recv()) { - memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); -#if HAS_FLIGHT - ao_flight_force_idle = TRUE; -#endif - ao_packet_send(); - } - } - ao_exit(); -} - -void -ao_packet_slave_start(void) -{ - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); -} - -void -ao_packet_slave_stop(void) -{ - if (ao_packet_enable) { - ao_packet_enable = 0; - while (ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_delay(AO_MS_TO_TICKS(10)); - } - } -} - -void -ao_packet_slave_init(uint8_t enable) -{ - ao_add_stdio(ao_packet_pollchar, - ao_packet_putchar, - NULL); - if (enable) - ao_packet_slave_start(); -} diff --git a/src/ao_panic.c b/src/ao_panic.c deleted file mode 100644 index fdada201..00000000 --- a/src/ao_panic.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -#ifndef HAS_BEEP -#error Please define HAS_BEEP -#endif - -#if !HAS_BEEP -#define ao_beep(x) -#endif - -static void -ao_panic_delay(uint8_t n) -{ - uint8_t i = 0, j = 0; - - while (n--) - while (--j) - while (--i) - _asm nop _endasm; -} - -void -ao_panic(uint8_t reason) -{ - uint8_t n; - - __critical for (;;) { - ao_panic_delay(20); - for (n = 0; n < 5; n++) { - ao_led_on(AO_LED_RED); - ao_beep(AO_BEEP_HIGH); - ao_panic_delay(1); - ao_led_off(AO_LED_RED); - ao_beep(AO_BEEP_LOW); - ao_panic_delay(1); - } - ao_beep(AO_BEEP_OFF); - ao_panic_delay(2); -#pragma disable_warning 126 - for (n = 0; n < reason; n++) { - ao_led_on(AO_LED_RED); - ao_beep(AO_BEEP_MID); - ao_panic_delay(10); - ao_led_off(AO_LED_RED); - ao_beep(AO_BEEP_OFF); - ao_panic_delay(10); - } - } -} diff --git a/src/ao_pins.h b/src/ao_pins.h deleted file mode 100644 index e1f5459f..00000000 --- a/src/ao_pins.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#if defined(TELEMETRUM_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_1_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 1 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_2) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEMINI_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define USE_FAST_ASCENT_LOG 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELENANO_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_DBG 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 1 - #define HAS_ACCEL_REF 0 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 0 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TIDONGLE) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_0) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define HAS_BTM 1 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 1 - #define BT_LINK_ON_P1 0 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P2_1 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_SERIAL_1 1 - #define HAS_SERIAL_1_ALT_1 1 - #define HAS_SERIAL_1_ALT_2 0 - #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_BTM 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 0 - #define BT_LINK_ON_P1 1 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P1_7 - #define HAS_MONITOR 1 -#endif - -#if DBG_ON_P1 - - #define DBG_CLOCK (1 << 4) /* mi0 */ - #define DBG_DATA (1 << 5) /* mo0 */ - #define DBG_RESET_N (1 << 3) /* c0 */ - - #define DBG_CLOCK_PIN (P1_4) - #define DBG_DATA_PIN (P1_5) - #define DBG_RESET_N_PIN (P1_3) - - #define DBG_PORT_NUM 1 - #define DBG_PORT P1 - #define DBG_PORT_SEL P1SEL - #define DBG_PORT_INP P1INP - #define DBG_PORT_DIR P1DIR - -#endif /* DBG_ON_P1 */ - -#if DBG_ON_P0 - - #define DBG_CLOCK (1 << 3) - #define DBG_DATA (1 << 4) - #define DBG_RESET_N (1 << 5) - - #define DBG_CLOCK_PIN (P0_3) - #define DBG_DATA_PIN (P0_4) - #define DBG_RESET_N_PIN (P0_5) - - #define DBG_PORT_NUM 0 - #define DBG_PORT P0 - #define DBG_PORT_SEL P0SEL - #define DBG_PORT_INP P0INP - #define DBG_PORT_DIR P0DIR - -#endif /* DBG_ON_P0 */ - -#if COMPANION_CS_ON_P1 - #define COMPANION_CS_PORT P1 - #define COMPANION_CS_SEL P1SEL - #define COMPANION_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P1 - #define SPI_CS_PORT P1 - #define SPI_CS_SEL P1SEL - #define SPI_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P0 - #define SPI_CS_PORT P0 - #define SPI_CS_SEL P0SEL - #define SPI_CS_DIR P0DIR -#endif - -#ifndef IGNITE_ON_P2 -#error Please define IGNITE_ON_P2 -#endif - -#ifndef IGNITE_ON_P0 -#error Please define IGNITE_ON_P0 -#endif - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#ifndef HAS_EEPROM -#error Please define HAS_EEPROM -#endif - -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif - -#ifndef HAS_DBG -#error Please define HAS_DBG -#endif - -#ifndef HAS_IGNITE -#error Please define HAS_IGNITE -#endif - -#ifndef PACKET_HAS_MASTER -#error Please define PACKET_HAS_MASTER -#endif - -#ifndef PACKET_HAS_SLAVE -#error Please define PACKET_HAS_SLAVE -#endif - -#ifndef HAS_MONITOR -#error Please define HAS_MONITOR -#endif -#endif /* _AO_PINS_H_ */ diff --git a/src/ao_product.c b/src/ao_product.c deleted file mode 100644 index fb59580b..00000000 --- a/src/ao_product.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_product.h" - -/* Defines which mark this particular AltOS product */ - -const char ao_version[AO_MAX_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)) - -#if HAS_USB -#include "ao_usb.h" -/* USB descriptors in one giant block of bytes */ -__code __at(0x00aa) uint8_t ao_usb_descriptors [] = -{ - /* Device descriptor */ - 0x12, - AO_USB_DESC_DEVICE, - LE_WORD(0x0110), /* bcdUSB */ - 0x02, /* bDeviceClass */ - 0x00, /* bDeviceSubClass */ - 0x00, /* bDeviceProtocol */ - AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ - LE_WORD(0xFFFE), /* idVendor */ - LE_WORD(AO_idProduct_NUMBER), /* idProduct */ - LE_WORD(0x0100), /* bcdDevice */ - 0x01, /* iManufacturer */ - 0x02, /* iProduct */ - 0x03, /* iSerialNumber */ - 0x01, /* bNumConfigurations */ - - /* Configuration descriptor */ - 0x09, - AO_USB_DESC_CONFIGURATION, - LE_WORD(67), /* wTotalLength */ - 0x02, /* bNumInterfaces */ - 0x01, /* bConfigurationValue */ - 0x00, /* iConfiguration */ - 0xC0, /* bmAttributes */ - 0x32, /* bMaxPower */ - - /* Control class interface */ - 0x09, - AO_USB_DESC_INTERFACE, - 0x00, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x01, /* bNumEndPoints */ - 0x02, /* bInterfaceClass */ - 0x02, /* bInterfaceSubClass */ - 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ - 0x00, /* iInterface */ - - /* Header functional descriptor */ - 0x05, - CS_INTERFACE, - 0x00, /* bDescriptor SubType Header */ - LE_WORD(0x0110), /* CDC version 1.1 */ - - /* Call management functional descriptor */ - 0x05, - CS_INTERFACE, - 0x01, /* bDescriptor SubType Call Management */ - 0x01, /* bmCapabilities = device handles call management */ - 0x01, /* bDataInterface call management interface number */ - - /* ACM functional descriptor */ - 0x04, - CS_INTERFACE, - 0x02, /* bDescriptor SubType Abstract Control Management */ - 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ - - /* Union functional descriptor */ - 0x05, - CS_INTERFACE, - 0x06, /* bDescriptor SubType Union Functional descriptor */ - 0x00, /* bMasterInterface */ - 0x01, /* bSlaveInterface0 */ - - /* Notification EP */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_INT_EP|0x80, /* bEndpointAddress */ - 0x03, /* bmAttributes = intr */ - LE_WORD(8), /* wMaxPacketSize */ - 0x0A, /* bInterval */ - - /* Data class interface descriptor */ - 0x09, - AO_USB_DESC_INTERFACE, - 0x01, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x02, /* bNumEndPoints */ - 0x0A, /* bInterfaceClass = data */ - 0x00, /* bInterfaceSubClass */ - 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface */ - - /* Data EP OUT */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_OUT_EP, /* bEndpointAddress */ - 0x02, /* bmAttributes = bulk */ - LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ - 0x00, /* bInterval */ - - /* Data EP in */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_IN_EP|0x80, /* bEndpointAddress */ - 0x02, /* bmAttributes = bulk */ - LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ - 0x00, /* bInterval */ - - /* String descriptors */ - 0x04, - AO_USB_DESC_STRING, - LE_WORD(0x0409), - - /* iManufacturer */ - AO_iManufacturer_LEN, - AO_USB_DESC_STRING, - AO_iManufacturer_UCS2, - - /* iProduct */ - AO_iProduct_LEN, - AO_USB_DESC_STRING, - AO_iProduct_UCS2, - - /* iSerial */ - AO_iSerial_LEN, - AO_USB_DESC_STRING, - AO_iSerial_UCS2, - - /* Terminating zero */ - 0 -}; -#endif diff --git a/src/ao_radio.c b/src/ao_radio.c deleted file mode 100644 index 00816b33..00000000 --- a/src/ao_radio.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -/* Values from SmartRF® Studio for: - * - * Deviation: 20.507812 kHz - * Datarate: 38.360596 kBaud - * Modulation: GFSK - * RF Freq: 434.549927 MHz - * Channel: 99.975586 kHz - * Channel: 0 - * RX filter: 93.75 kHz - */ - -/* - * For IF freq of 140.62kHz, the IF value is: - * - * 140.62e3 / (24e6 / 2**10) = 6 - */ - -#define IF_FREQ_CONTROL 6 - -/* - * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are - * - * BW = 24e6 / (8 * (4 + M) * 2 ** E) - * - * So, M = 0 and E = 3 - */ - -#define CHANBW_M 0 -#define CHANBW_E 3 - -/* - * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are: - * - * R = (256 + M) * 2** E * 24e6 / 2**28 - * - * So M is 163 and E is 10 - */ - -#define DRATE_E 10 -#define DRATE_M 163 - -/* - * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are: - * - * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E - * - * So M is 6 and E is 3 - */ - -#define DEVIATION_M 6 -#define DEVIATION_E 3 - -/* - * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), - * so the DRATE_E and DRATE_M values are: - * - * M is 94 and E is 6 - * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes - */ - -#define RDF_DRATE_E 6 -#define RDF_DRATE_M 94 -#define RDF_PACKET_LEN 50 - -/* - * RDF deviation should match the normal NFM value of 5kHz - * - * M is 6 and E is 1 - * - */ - -#define RDF_DEVIATION_M 6 -#define RDF_DEVIATION_E 1 - -/* This are from the table for 433MHz */ - -#define RF_POWER_M30_DBM 0x12 -#define RF_POWER_M20_DBM 0x0e -#define RF_POWER_M15_DBM 0x1d -#define RF_POWER_M10_DBM 0x34 -#define RF_POWER_M5_DBM 0x2c -#define RF_POWER_0_DBM 0x60 -#define RF_POWER_5_DBM 0x84 -#define RF_POWER_7_DBM 0xc8 -#define RF_POWER_10_DBM 0xc0 - -#define RF_POWER RF_POWER_10_DBM - -static __code uint8_t radio_setup[] = { - RF_PA_TABLE7_OFF, RF_POWER, - RF_PA_TABLE6_OFF, RF_POWER, - RF_PA_TABLE5_OFF, RF_POWER, - RF_PA_TABLE4_OFF, RF_POWER, - RF_PA_TABLE3_OFF, RF_POWER, - RF_PA_TABLE2_OFF, RF_POWER, - RF_PA_TABLE1_OFF, RF_POWER, - RF_PA_TABLE0_OFF, RF_POWER, - - RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), - RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), - - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), - RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | - RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), - RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | - RF_MDMCFG1_NUM_PREAMBLE_4 | - (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - RF_MDMCFG0_OFF, (17 << RF_MDMCFG0_CHANSPC_M_SHIFT), - - RF_CHANNR_OFF, 0, - - RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* SmartRF says set LODIV_BUF_CURRENT_TX to 0 - * And, we're not using power ramping, so use PA_POWER 0 - */ - RF_FREND0_OFF, ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) | - (0 << RF_FREND0_PA_POWER_SHIFT)), - - RF_FREND1_OFF, ((1 << RF_FREND1_LNA_CURRENT_SHIFT) | - (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) | - (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) | - (2 << RF_FREND1_MIX_CURRENT_SHIFT)), - - RF_FSCAL3_OFF, 0xE9, - RF_FSCAL2_OFF, 0x0A, - RF_FSCAL1_OFF, 0x00, - RF_FSCAL0_OFF, 0x1F, - - RF_TEST2_OFF, 0x88, - RF_TEST1_OFF, 0x31, - RF_TEST0_OFF, 0x09, - - /* default sync values */ - RF_SYNC1_OFF, 0xD3, - RF_SYNC0_OFF, 0x91, - - /* max packet length */ - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| - PKTCTRL1_APPEND_STATUS| - PKTCTRL1_ADR_CHK_NONE), - RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| - RF_PKTCTRL0_PKT_FORMAT_NORMAL| - RF_PKTCTRL0_CRC_EN| - RF_PKTCTRL0_LENGTH_CONFIG_FIXED), - RF_ADDR_OFF, 0x00, - RF_MCSM2_OFF, (RF_MCSM2_RX_TIME_END_OF_PACKET), - RF_MCSM1_OFF, (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING| - RF_MCSM1_RXOFF_MODE_IDLE| - RF_MCSM1_TXOFF_MODE_IDLE), - RF_MCSM0_OFF, (RF_MCSM0_FS_AUTOCAL_FROM_IDLE| - RF_MCSM0_MAGIC_3| - RF_MCSM0_CLOSE_IN_RX_0DB), - RF_FOCCFG_OFF, (RF_FOCCFG_FOC_PRE_K_3K, - RF_FOCCFG_FOC_POST_K_PRE_K, - RF_FOCCFG_FOC_LIMIT_BW_OVER_4), - RF_BSCFG_OFF, (RF_BSCFG_BS_PRE_K_2K| - RF_BSCFG_BS_PRE_KP_3KP| - RF_BSCFG_BS_POST_KI_PRE_KI| - RF_BSCFG_BS_POST_KP_PRE_KP| - RF_BSCFG_BS_LIMIT_0), - RF_AGCCTRL2_OFF, 0x43, - RF_AGCCTRL1_OFF, 0x40, - RF_AGCCTRL0_OFF, 0x91, - - RF_IOCFG2_OFF, 0x00, - RF_IOCFG1_OFF, 0x00, - RF_IOCFG0_OFF, 0x00, -}; - -static __code uint8_t rdf_setup[] = { - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), - RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | - RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), - RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | - RF_MDMCFG1_NUM_PREAMBLE_2 | - (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - - RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* packet length is set in-line */ - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| - PKTCTRL1_ADR_CHK_NONE), - RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| - RF_PKTCTRL0_LENGTH_CONFIG_FIXED), -}; - -static __code uint8_t fixed_pkt_setup[] = { - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), - RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), - RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | - RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), - RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | - RF_MDMCFG1_NUM_PREAMBLE_4 | - (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - - RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* max packet length -- now set inline */ - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| - PKTCTRL1_APPEND_STATUS| - PKTCTRL1_ADR_CHK_NONE), - RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| - RF_PKTCTRL0_PKT_FORMAT_NORMAL| - RF_PKTCTRL0_CRC_EN| - RF_PKTCTRL0_LENGTH_CONFIG_FIXED), -}; - -__xdata uint8_t ao_radio_dma; -__xdata uint8_t ao_radio_dma_done; -__xdata uint8_t ao_radio_done; -__xdata uint8_t ao_radio_abort; -__xdata uint8_t ao_radio_mutex; - -void -ao_radio_general_isr(void) __interrupt 16 -{ - S1CON &= ~0x03; - if (RFIF & RFIF_IM_TIMEOUT) { - ao_radio_recv_abort(); - RFIF &= ~ RFIF_IM_TIMEOUT; - } else if (RFIF & RFIF_IM_DONE) { - ao_radio_done = 1; - ao_wakeup(&ao_radio_done); - RFIF &= ~RFIF_IM_DONE; - } -} - -void -ao_radio_set_packet(void) -{ - uint8_t i; - for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) - RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; -} - -void -ao_radio_idle(void) -{ - if (RF_MARCSTATE != RF_MARCSTATE_IDLE) - { - do { - RFST = RFST_SIDLE; - ao_yield(); - } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); - } -} - -void -ao_radio_get(uint8_t len) -{ - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_setting); - RF_PKTLEN = len; -} - - -void -ao_radio_send(__xdata void *packet, uint8_t size) __reentrant -{ - ao_radio_get(size); - ao_radio_done = 0; - ao_dma_set_transfer(ao_radio_dma, - packet, - &RFDXADDR, - size, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_STX; - __critical while (!ao_radio_done) - ao_sleep(&ao_radio_done); - ao_radio_put(); -} - -uint8_t -ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant -{ - ao_radio_abort = 0; - ao_radio_get(size - 2); - ao_dma_set_transfer(ao_radio_dma, - &RFDXADDR, - packet, - size, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_SRX; - - /* Wait for DMA to be done, for the radio receive process to - * get aborted or for a receive timeout to fire - */ - __critical while (!ao_radio_dma_done && !ao_radio_abort) - if (ao_sleep(&ao_radio_dma_done)) - break; - - /* If recv was aborted, clean up by stopping the DMA engine - * and idling the radio - */ - if (!ao_radio_dma_done) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } - ao_radio_put(); - return ao_radio_dma_done; -} - -/* - * Wake up a task waiting to receive a radio packet - * and tell them to abort the transfer - */ - -void -ao_radio_recv_abort(void) -{ - ao_radio_abort = 1; - ao_wakeup(&ao_radio_dma_done); -} - -__xdata ao_radio_rdf_value = 0x55; - -void -ao_radio_rdf(int ms) -{ - uint8_t i; - uint8_t pkt_len; - - /* - * Compute the packet length as follows: - * - * 2000 bps (for a 1kHz tone) - * so, for 'ms' milliseconds, we need - * 2 * ms bits, or ms / 4 bytes - */ - if (ms > (255 * 4)) - ms = 255 * 4; - pkt_len = ms >> 2; - - ao_radio_abort = 0; - ao_radio_get(pkt_len); - ao_radio_done = 0; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; - - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_STX; - __critical while (!ao_radio_done && !ao_radio_abort) - ao_sleep(&ao_radio_done); - if (!ao_radio_done) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } - ao_radio_set_packet(); - ao_radio_put(); -} - -void -ao_radio_rdf_abort(void) -{ - ao_radio_abort = 1; - ao_wakeup(&ao_radio_done); -} - - -/* Output carrier */ -void -ao_radio_test(void) -{ - uint8_t mode = 2; - static __xdata radio_on; - ao_cmd_white(); - if (ao_cmd_lex_c != '\n') { - ao_cmd_decimal(); - mode = (uint8_t) ao_cmd_lex_u32; - } - mode++; - if ((mode & 2) && !radio_on) { -#if HAS_MONITOR - ao_set_monitor(0); -#endif -#if PACKET_HAS_SLAVE - ao_packet_slave_stop(); -#endif - ao_radio_get(0xff); - RFST = RFST_STX; - radio_on = 1; - } - if (mode == 3) { - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - } - if ((mode & 1) && radio_on) { - ao_radio_idle(); - ao_radio_put(); - radio_on = 0; - } -} - -__code struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, - { 0, NULL }, -}; - -void -ao_radio_init(void) -{ - uint8_t i; - for (i = 0; i < sizeof (radio_setup); i += 2) - RF[radio_setup[i]] = radio_setup[i+1]; - ao_radio_set_packet(); - ao_radio_dma_done = 1; - ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); - RFIF = 0; - RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; - IEN2 |= IEN2_RFIE; - ao_cmd_register(&ao_radio_cmds[0]); -} diff --git a/src/ao_reboot.c b/src/ao_reboot.c deleted file mode 100644 index 8c47b893..00000000 --- a/src/ao_reboot.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -/* Use the watchdog timer to force a complete reboot - */ -void -ao_reboot(void) -{ - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; - ao_delay(AO_SEC_TO_TICKS(2)); - ao_panic(AO_PANIC_REBOOT); -} diff --git a/src/ao_report.c b/src/ao_report.c deleted file mode 100644 index 3cf558e1..00000000 --- a/src/ao_report.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -#define BIT(i,x) ((x) ? (1 << (i)) : 0) -#define MORSE1(a) (1 | BIT(3,a)) -#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) -#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) -#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) -#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) - -static const uint8_t flight_reports[] = { - MORSE3(0,0,0), /* startup, 'S' */ - MORSE2(0,0), /* idle 'I' */ - MORSE4(0,1,1,0), /* pad 'P' */ - MORSE4(1,0,0,0), /* boost 'B' */ - MORSE4(0,0,1,0), /* fast 'F' */ - MORSE4(1,0,1,0), /* coast 'C' */ - MORSE3(1,0,0), /* drogue 'D' */ - MORSE2(1,1), /* main 'M' */ - MORSE4(0,1,0,0), /* landed 'L' */ - MORSE4(1,0,0,1), /* invalid 'X' */ -}; - -#if HAS_BEEP -#define low(time) ao_beep_for(AO_BEEP_LOW, time) -#define mid(time) ao_beep_for(AO_BEEP_MID, time) -#define high(time) ao_beep_for(AO_BEEP_HIGH, time) -#else -#define low(time) ao_led_for(AO_LED_GREEN, time) -#define mid(time) ao_led_for(AO_LED_RED, time) -#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) -#endif -#define pause(time) ao_delay(time) - -static __pdata enum ao_flight_state ao_report_state; - -static void -ao_report_beep(void) __reentrant -{ - uint8_t r = flight_reports[ao_flight_state]; - uint8_t l = r & 7; - - if (!r) - return; - while (l--) { - if (r & 8) - mid(AO_MS_TO_TICKS(600)); - else - mid(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); - r >>= 1; - } - pause(AO_MS_TO_TICKS(400)); -} - -static void -ao_report_digit(uint8_t digit) __reentrant -{ - if (!digit) { - mid(AO_MS_TO_TICKS(500)); - pause(AO_MS_TO_TICKS(200)); - } else { - while (digit--) { - mid(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); - } - } - pause(AO_MS_TO_TICKS(300)); -} - -static void -ao_report_altitude(void) -{ - __pdata int16_t agl = ao_max_height; - __xdata uint8_t digits[10]; - __pdata uint8_t ndigits, i; - - if (agl < 0) - agl = 0; - ndigits = 0; - do { - digits[ndigits++] = agl % 10; - agl /= 10; - } while (agl); - - for (;;) { - ao_report_beep(); - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); - pause(AO_SEC_TO_TICKS(5)); - } -} - -#if HAS_IGNITE -static uint8_t -ao_report_igniter_ready(enum ao_igniter igniter) -{ - return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; -} - -static void -ao_report_continuity(void) __reentrant -{ - uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | - (ao_report_igniter_ready(ao_igniter_main) << 1)); - if (c) { - while (c--) { - high(AO_MS_TO_TICKS(25)); - pause(AO_MS_TO_TICKS(100)); - } - } else { - c = 10; - while (c--) { - high(AO_MS_TO_TICKS(20)); - low(AO_MS_TO_TICKS(20)); - } - } - if (ao_log_full()) { - pause(AO_MS_TO_TICKS(100)); - c = 2; - while (c--) { - low(AO_MS_TO_TICKS(100)); - mid(AO_MS_TO_TICKS(100)); - high(AO_MS_TO_TICKS(100)); - mid(AO_MS_TO_TICKS(100)); - } - } - c = 50; - while (c-- && ao_flight_state == ao_flight_pad) - pause(AO_MS_TO_TICKS(100)); -} -#endif - -void -ao_report(void) -{ - ao_report_state = ao_flight_state; - for(;;) { - if (ao_flight_state == ao_flight_landed) - ao_report_altitude(); - ao_report_beep(); -#if HAS_IGNITE - if (ao_flight_state == ao_flight_idle) - ao_report_continuity(); - while (ao_flight_state == ao_flight_pad) - ao_report_continuity(); -#endif - __critical { - while (ao_report_state == ao_flight_state) - ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; - } - } -} - -static __xdata struct ao_task ao_report_task; - -void -ao_report_init(void) -{ - ao_add_task(&ao_report_task, ao_report, "report"); -} diff --git a/src/ao_romconfig.c b/src/ao_romconfig.c deleted file mode 100644 index f3fe61b1..00000000 --- a/src/ao_romconfig.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; diff --git a/src/ao_rssi.c b/src/ao_rssi.c deleted file mode 100644 index e3964d2d..00000000 --- a/src/ao_rssi.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static __xdata volatile uint16_t ao_rssi_time; -static __pdata volatile uint16_t ao_rssi_delay; -static __pdata uint8_t ao_rssi_led; - -void -ao_rssi(void) -{ - for (;;) { - while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3)) - ao_sleep(&ao_rssi_time); - ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100)); - ao_delay(ao_rssi_delay); - } -} - -void -ao_rssi_set(int rssi_value) -{ - if (rssi_value > 0) - rssi_value = 0; - ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5); - ao_rssi_time = ao_time(); - ao_wakeup(&ao_rssi_time); -} - -__xdata struct ao_task ao_rssi_task; - -void -ao_rssi_init(uint8_t rssi_led) -{ - ao_rssi_led = rssi_led; - ao_rssi_delay = 0; - ao_add_task(&ao_rssi_task, ao_rssi, "rssi"); -} diff --git a/src/ao_sample.c b/src/ao_sample.c deleted file mode 100644 index b2b8e9f6..00000000 --- a/src/ao_sample.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -/* - * Current sensor values - */ - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata int16_t ao_sample_pres; -__pdata int16_t ao_sample_alt; -__pdata int16_t ao_sample_height; -#if HAS_ACCEL -__pdata int16_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_adc; - -/* - * Sensor calibration values - */ - -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -__pdata int16_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - -uint8_t -ao_sample(void) -{ - ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_sample_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_sample_adc]; - ao_sample_tick = ao_adc->tick; - ao_sample_pres = ao_adc->pres; - ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; -#if HAS_ACCEL - ao_sample_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_sample_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_sample_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_sample_accel 32767 - * = ------------ * ------------ - * 32767 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_sample_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; -#endif -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_adc = ao_adc_ring_next(ao_sample_adc); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_adc = ao_adc_head; - ao_preflight = TRUE; -} diff --git a/src/ao_serial.c b/src/ao_serial.c deleted file mode 100644 index 82370c64..00000000 --- a/src/ao_serial.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -volatile __xdata struct ao_fifo ao_usart1_rx_fifo; -volatile __xdata struct ao_fifo ao_usart1_tx_fifo; - -void -ao_serial_rx1_isr(void) __interrupt 3 -{ - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN - ao_wakeup(&ao_stdin_ready); -#endif -} - -static __xdata uint8_t ao_serial_tx1_started; - -static void -ao_serial_tx1_start(void) -{ - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) - { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); - } -} - -void -ao_serial_tx1_isr(void) __interrupt 14 -{ - UTX1IF = 0; - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); -} - -char -ao_serial_getchar(void) __critical -{ - char c; - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); - return c; -} - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical -{ - char c; - if (ao_fifo_empty(ao_usart1_rx_fifo)) - return AO_READ_AGAIN; - ao_fifo_remove(ao_usart1_rx_fifo,c); - return c; -} -#endif - -void -ao_serial_putchar(char c) __critical -{ - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); -} - -void -ao_serial_drain(void) __critical -{ - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); -} - -static __code struct { - uint8_t baud; - uint8_t gcr; -} ao_serial_speeds[] = { - /* [AO_SERIAL_SPEED_4800] = */ { - /* .baud = */ 163, - /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_9600] = */ { - /* .baud = */ 163, - /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_19200] = */ { - /* .baud = */ 163, - /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_57600] = */ { - /* .baud = */ 59, - /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, -}; - -void -ao_serial_set_speed(uint8_t speed) -{ - ao_serial_drain(); - if (speed > AO_SERIAL_SPEED_57600) - return; - U1UCR |= UxUCR_FLUSH; - U1BAUD = ao_serial_speeds[speed].baud; - U1GCR = ao_serial_speeds[speed].gcr; -} - -void -ao_serial_init(void) -{ -#if HAS_SERIAL_1_ALT_1 - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; - - P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; - - /* Make the USART pins be controlled by the USART */ - P0SEL |= (1 << 5) | (1 << 4); -#if HAS_SERIAL_1_HW_FLOW - P0SEL |= (1 << 3) | (1 << 2); -#endif -#else - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; - - P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | - (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); - - /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 6) | (1 << 7); - P1SEL |= (1 << 5) | (1 << 4); -#endif - - /* UART mode with receiver enabled */ - U1CSR = (UxCSR_MODE_UART | UxCSR_RE); - - /* Pick a 4800 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - - /* Reasonable serial parameters */ - U1UCR = (UxUCR_FLUSH | -#if HAS_SERIAL_1_HW_FLOW - UxUCR_FLOW_ENABLE | -#else - UxUCR_FLOW_DISABLE | -#endif - UxUCR_D9_EVEN_PARITY | - UxUCR_BIT9_8_BITS | - UxUCR_PARITY_DISABLE | - UxUCR_SPB_1_STOP_BIT | - UxUCR_STOP_HIGH | - UxUCR_START_LOW); - - IEN0 |= IEN0_URX1IE; - IEN2 |= IEN2_UTX1IE; -} diff --git a/src/ao_spi.c b/src/ao_spi.c deleted file mode 100644 index fbe613c7..00000000 --- a/src/ao_spi.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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" - -/* Shared mutex to protect SPI bus, must cover the entire - * operation, from CS low to CS high. This means that any SPI - * user must protect the SPI bus with this mutex - */ -__xdata uint8_t ao_spi_mutex; -__xdata uint8_t ao_spi_dma_in_done; -__xdata uint8_t ao_spi_dma_out_done; - -uint8_t ao_spi_dma_out_id; -uint8_t ao_spi_dma_in_id; - -static __xdata uint8_t ao_spi_const = 0xff; - -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant -{ - ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, - &ao_spi_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_spi_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_spi_dma_in_id); - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant -{ - ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_spi_dma_out_id, - &ao_spi_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_spi_dma_in_id); - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); -} - -/* - * Initialize USART0 for SPI using config alt 2 - * - * MO P1_5 - * MI P1_4 - * CLK P1_3 - * - * Chip select is the responsibility of the caller - */ - -void -ao_spi_init(void) -{ - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); - - /* Set up IN DMA */ - ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock. - * Every peripheral I've ever seen goes faster than that, - * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); -} diff --git a/src/ao_state.c b/src/ao_state.c deleted file mode 100644 index ed197aa5..00000000 --- a/src/ao_state.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; diff --git a/src/ao_stdio.c b/src/ao_stdio.c deleted file mode 100644 index c0138a30..00000000 --- a/src/ao_stdio.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -/* - * Basic I/O functions to support SDCC stdio package - */ - -#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) - -__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; -__pdata int8_t ao_cur_stdio; -__pdata int8_t ao_num_stdios; - -void -putchar(char c) -{ - if (c == '\n') - (*ao_stdios[ao_cur_stdio].putchar)('\r'); - (*ao_stdios[ao_cur_stdio].putchar)(c); -} - -void -flush(void) -{ - if (ao_stdios[ao_cur_stdio].flush) - ao_stdios[ao_cur_stdio].flush(); -} - -__xdata uint8_t ao_stdin_ready; - -char -getchar(void) __reentrant __critical -{ - char c; - int8_t stdio = ao_cur_stdio; - - for (;;) { - c = ao_stdios[stdio].pollchar(); - if (c != AO_READ_AGAIN) - break; - if (++stdio == ao_num_stdios) - stdio = 0; - if (stdio == ao_cur_stdio) - ao_sleep(&ao_stdin_ready); - } - ao_cur_stdio = stdio; - return c; -} - -uint8_t -ao_echo(void) -{ - return ao_stdios[ao_cur_stdio].echo; -} - -int8_t -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char), - void (*flush)(void)) __reentrant -{ - if (ao_num_stdios == AO_NUM_STDIOS) - ao_panic(AO_PANIC_STDIO); - ao_stdios[ao_num_stdios].pollchar = pollchar; - ao_stdios[ao_num_stdios].putchar = putchar; - ao_stdios[ao_num_stdios].flush = flush; - ao_stdios[ao_num_stdios].echo = 1; - return ao_num_stdios++; -} diff --git a/src/ao_storage.c b/src/ao_storage.c deleted file mode 100644 index 6ffca0e5..00000000 --- a/src/ao_storage.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t this_len; - uint16_t this_off; - - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & (ao_storage_unit - 1); - this_len = ao_storage_unit - this_off; - if (this_len > len) - this_len = len; - - if (!ao_storage_device_read(pos, buf, this_len)) - return 0; - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } - return 1; -} - -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t this_len; - uint16_t this_off; - - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & (ao_storage_unit - 1); - this_len = ao_storage_unit - this_off; - if (this_len > len) - this_len = len; - - if (!ao_storage_device_write(pos, buf, this_len)) - return 0; - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } - return 1; -} - -static __xdata uint8_t storage_data[8]; - -static void -ao_storage_dump(void) __reentrant -{ - uint8_t i, j; - - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - for (i = 0; ; i += 8) { - if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, - storage_data, - 8)) { - ao_cmd_put16((uint16_t) i); - for (j = 0; j < 8; j++) { - putchar(' '); - ao_cmd_put8(storage_data[j]); - } - putchar ('\n'); - } - if (i == 248) - break; - } -} - -#if 0 - -/* not enough space for this today - */ -static void -ao_storage_store(void) __reentrant -{ - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - uint32_t addr; - - ao_cmd_hex(); - block = ao_cmd_lex_i; - ao_cmd_hex(); - i = ao_cmd_lex_i; - addr = ((uint32_t) block << 8) | i; - ao_cmd_hex(); - len = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - while (len--) { - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - b = ao_cmd_lex_i; - ao_storage_write(addr, &b, 1); - addr++; - } -} -#endif - -void -ao_storage_zap(void) __reentrant -{ - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); -} - -void -ao_storage_zapall(void) __reentrant -{ - uint32_t pos; - - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) - ao_storage_erase(pos); -} - -void -ao_storage_info(void) __reentrant -{ - printf("Storage size: %ld\n", ao_storage_total); - printf("Storage erase unit: %ld\n", ao_storage_block); - ao_storage_device_info(); -} - -__code struct ao_cmds ao_storage_cmds[] = { - { ao_storage_info, "f\0Show storage" }, - { ao_storage_dump, "e \0Dump flash" }, -#ifdef HAS_STORAGE_DBG - { ao_storage_store, "w ...\0Write data to flash" }, -#endif - { ao_storage_zap, "z \0Erase " }, - { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, - { 0, NULL }, -}; - -void -ao_storage_init(void) -{ - ao_storage_device_init(); - ao_cmd_register(&ao_storage_cmds[0]); -} diff --git a/src/ao_task.c b/src/ao_task.c deleted file mode 100644 index f5850fa4..00000000 --- a/src/ao_task.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -#define AO_NO_TASK_INDEX 0xff - -__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; -__data uint8_t ao_num_tasks; -__data uint8_t ao_cur_task_index; -__xdata struct ao_task *__data ao_cur_task; - -void -ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant -{ - uint8_t __xdata *stack; - uint8_t task_id; - uint8_t t; - if (ao_num_tasks == AO_NUM_TASKS) - ao_panic(AO_PANIC_NO_TASK); - for (task_id = 1; task_id != 0; task_id++) { - for (t = 0; t < ao_num_tasks; t++) - if (ao_tasks[t]->task_id == task_id) - break; - if (t == ao_num_tasks) - break; - } - ao_tasks[ao_num_tasks++] = task; - task->task_id = task_id; - task->name = name; - /* - * Construct a stack frame so that it will 'return' - * to the start of the task - */ - stack = task->stack; - - *stack++ = ((uint16_t) start); /* 0 */ - *stack++ = ((uint16_t) start) >> 8; /* 1 */ - - /* and the stuff saved by ao_switch */ - *stack++ = 0; /* 2 acc */ - *stack++ = 0x80; /* 3 IE */ - - /* 4 DPL - * 5 DPH - * 6 B - * 7 R2 - * 8 R3 - * 9 R4 - * 10 R5 - * 11 R6 - * 12 R7 - * 13 R0 - * 14 R1 - * 15 PSW - * 16 BP - */ - for (t = 0; t < 13; t++) - *stack++ = 0; - - task->stack_count = 17; - task->wchan = NULL; -} - -/* Task switching function. This must not use any stack variables */ -void -ao_yield(void) __naked -{ - - /* Save current context */ - _asm - /* Push ACC first, as when restoring the context it must be restored - * last (it is used to set the IE register). */ - push ACC - /* Store the IE register then enable interrupts. */ - push _IEN0 - setb _EA - push DPL - push DPH - push b - push ar2 - push ar3 - push ar4 - push ar5 - push ar6 - push ar7 - push ar0 - push ar1 - push PSW - _endasm; - PSW = 0; - _asm - push _bp - _endasm; - - if (ao_cur_task_index == AO_NO_TASK_INDEX) - ao_cur_task_index = ao_num_tasks-1; - else - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - /* Save the current stack */ - stack_len = SP - (AO_STACK_START - 1); - ao_cur_task->stack_count = stack_len; - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *save_ptr++ = *stack_ptr++; - while (--stack_len); - } - - /* Empty the stack; might as well let interrupts have the whole thing */ - SP = AO_STACK_START - 1; - - /* Find a task to run. If there isn't any runnable task, - * this loop will run forever, which is just fine - */ - { - __pdata uint8_t ao_next_task_index = ao_cur_task_index; - for (;;) { - ++ao_next_task_index; - if (ao_next_task_index == ao_num_tasks) - ao_next_task_index = 0; - - ao_cur_task = ao_tasks[ao_next_task_index]; - if (ao_cur_task->wchan == NULL) { - ao_cur_task_index = ao_next_task_index; - break; - } - - /* Check if the alarm is set for a time which has passed */ - if (ao_cur_task->alarm && - (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { - ao_cur_task_index = ao_next_task_index; - break; - } - - /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) - PCON = PCON_IDLE; - } - } - - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - - /* Restore the old stack */ - stack_len = ao_cur_task->stack_count; - SP = AO_STACK_START - 1 + stack_len; - - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *stack_ptr++ = *save_ptr++; - while (--stack_len); - } - - _asm - pop _bp - pop PSW - pop ar1 - pop ar0 - pop ar7 - pop ar6 - pop ar5 - pop ar4 - pop ar3 - pop ar2 - pop b - pop DPH - pop DPL - /* The next byte of the stack is the IE register. Only the global - enable bit forms part of the task context. Pop off the IE then set - the global enable bit to match that of the stored IE register. */ - pop ACC - JB ACC.7,0098$ - CLR _EA - LJMP 0099$ - 0098$: - SETB _EA - 0099$: - /* Finally pop off the ACC, which was the first register saved. */ - pop ACC - ret - _endasm; -} - -uint8_t -ao_sleep(__xdata void *wchan) -{ - __critical { - ao_cur_task->wchan = wchan; - } - ao_yield(); - ao_cur_task->alarm = 0; - if (ao_cur_task->wchan) { - ao_cur_task->wchan = NULL; - return 1; - } - return 0; -} - -void -ao_wakeup(__xdata void *wchan) -{ - uint8_t i; - - for (i = 0; i < ao_num_tasks; i++) - if (ao_tasks[i]->wchan == wchan) - ao_tasks[i]->wchan = NULL; -} - -void -ao_alarm(uint16_t delay) -{ - /* Make sure we sleep *at least* delay ticks, which means adding - * one to account for the fact that we may be close to the next tick - */ - if (!(ao_cur_task->alarm = ao_time() + delay + 1)) - ao_cur_task->alarm = 1; -} - -void -ao_exit(void) __critical -{ - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); - /* we'll never get back here */ -} - -void -ao_task_info(void) -{ - uint8_t i; - uint8_t pc_loc; - __xdata struct ao_task *task; - - for (i = 0; i < ao_num_tasks; i++) { - task = ao_tasks[i]; - pc_loc = task->stack_count - 17; - printf("%12s: wchan %04x pc %04x\n", - task->name, - (int16_t) task->wchan, - (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); - } -} - -void -ao_start_scheduler(void) -{ - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_cur_task = NULL; - ao_yield(); -} diff --git a/src/ao_telebt.c b/src/ao_telebt.c deleted file mode 100644 index 85565172..00000000 --- a/src/ao_telebt.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); -#if HAS_BEEP - ao_beep_init(); -#endif - ao_cmd_init(); -#if HAS_EEPROM - ao_spi_init(); - ao_storage_init(); -#endif - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_master_init(); - ao_btm_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c deleted file mode 100644 index 008b200a..00000000 --- a/src/ao_teledongle.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_master_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telem.h b/src/ao_telem.h deleted file mode 100644 index 1a8da291..00000000 --- a/src/ao_telem.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_TELEM_H_ -#define _AO_TELEM_H_ - -#define AO_TELEMETRY_VERSION 4 - -/* - * Telemetry version 4 and higher format: - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - -#define AO_TELEM_VERSION "VERSION" -#define AO_TELEM_CALL "c" -#define AO_TELEM_SERIAL "n" -#define AO_TELEM_FLIGHT "f" -#define AO_TELEM_RSSI "r" -#define AO_TELEM_STATE "s" -#define AO_TELEM_TICK "t" - -/* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - -#define AO_TELEM_RAW_ACCEL "r_a" -#define AO_TELEM_RAW_BARO "r_b" -#define AO_TELEM_RAW_THERMO "r_t" -#define AO_TELEM_RAW_BATT "r_v" -#define AO_TELEM_RAW_DROGUE "r_d" -#define AO_TELEM_RAW_MAIN "r_m" - -/* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - -#define AO_TELEM_CAL_ACCEL_GROUND "c_a" -#define AO_TELEM_CAL_BARO_GROUND "c_b" -#define AO_TELEM_CAL_ACCEL_PLUS "c_p" -#define AO_TELEM_CAL_ACCEL_MINUS "c_m" - -/* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - -#define AO_TELEM_KALMAN_HEIGHT "k_h" -#define AO_TELEM_KALMAN_SPEED "k_s" -#define AO_TELEM_KALMAN_ACCEL "k_a" - -/* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - -#define AO_TELEM_ADHOC_ACCEL "a_a" -#define AO_TELEM_ADHOC_SPEED "a_s" -#define AO_TELEM_ADHOC_BARO "a_b" - -/* - * GPS values - * - * Name Value - * g GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_g GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - -#define AO_TELEM_GPS_STATE "g" -#define AO_TELEM_GPS_STATE_LOCKED 'l' -#define AO_TELEM_GPS_STATE_UNLOCKED 'u' -#define AO_TELEM_GPS_STATE_ERROR 'e' -#define AO_TELEM_GPS_NUM_SAT "g_n" -#define AO_TELEM_GPS_LATITUDE "g_ns" -#define AO_TELEM_GPS_LONGITUDE "g_ew" -#define AO_TELEM_GPS_ALTITUDE "g_a" -#define AO_TELEM_GPS_YEAR "g_Y" -#define AO_TELEM_GPS_MONTH "g_M" -#define AO_TELEM_GPS_DAY "g_D" -#define AO_TELEM_GPS_HOUR "g_h" -#define AO_TELEM_GPS_MINUTE "g_m" -#define AO_TELEM_GPS_SECOND "g_s" -#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" -#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" -#define AO_TELEM_GPS_COURSE "g_c" -#define AO_TELEM_GPS_HDOP "g_hd" -#define AO_TELEM_GPS_VDOP "g_vd" -#define AO_TELEM_GPS_HERROR "g_he" -#define AO_TELEM_GPS_VERROR "g_ve" - -/* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - -#define AO_TELEM_SAT_NUM "s_n" -#define AO_TELEM_SAT_SVID "s_v" -#define AO_TELEM_SAT_C_N_0 "s_c" - -#endif /* _AO_TELEM_H_ */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c deleted file mode 100644 index f560740a..00000000 --- a/src/ao_telemetrum.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - /* - * Reduce the transient on the ignite pins at startup by - * pulling the pins low as soon as possible at power up - */ - ao_ignite_set_pins(); - - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - /* A hack -- look at the SPI clock pin, if it's sitting at - * ground, then we force the computer to idle mode instead of - * flight mode - */ - if (P1_3 == 0) { - ao_flight_force_idle = 1; - while (P1_3 == 0) - ; - } - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_cmd_init(); - ao_spi_init(); - ao_storage_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); - ao_usb_init(); - ao_serial_init(); - ao_gps_init(); - ao_gps_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_igniter_init(); -#if HAS_DBG - ao_dbg_init(); -#endif -#if HAS_COMPANION - ao_companion_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c deleted file mode 100644 index c7338a58..00000000 --- a/src/ao_telemetry.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_product.h" - -static __pdata uint16_t ao_telemetry_interval; -static __pdata int8_t ao_telemetry_config_max; -static __pdata int8_t ao_telemetry_config_cur; -#if HAS_GPS -static __pdata int8_t ao_telemetry_loc_cur; -static __pdata int8_t ao_telemetry_sat_cur; -#endif -#if HAS_COMPANION -static __pdata int8_t ao_telemetry_companion_max; -static __pdata int8_t ao_telemetry_companion_cur; -#endif -static __pdata uint8_t ao_rdf = 0; -static __pdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM -#endif - -#if defined(TELEMINI_V_1_0) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI -#endif - -#if defined(TELENANO_V_0_1) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO -#endif - -static __xdata union ao_telemetry_all telemetry; - -/* Send sensor packet */ -static void -ao_send_sensor(void) -{ - uint8_t sample; - sample = ao_sample_adc; - - telemetry.generic.tick = ao_adc_ring[sample].tick; - telemetry.generic.type = AO_TELEMETRY_SENSOR; - - telemetry.sensor.state = ao_flight_state; -#if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; -#else - telemetry.sensor.accel = 0; -#endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; -#if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; -#else - telemetry.sensor.sense_d = 0; - telemetry.sensor.sense_m = 0; -#endif - - telemetry.sensor.acceleration = ao_accel; - telemetry.sensor.speed = ao_speed; - telemetry.sensor.height = ao_height; - - telemetry.sensor.ground_pres = ao_ground_pres; -#if HAS_ACCEL - telemetry.sensor.ground_accel = ao_ground_accel; - telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; - telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; -#else - telemetry.sensor.ground_accel = 0; - telemetry.sensor.accel_plus_g = 0; - telemetry.sensor.accel_minus_g = 0; -#endif - - ao_radio_send(&telemetry, sizeof (telemetry)); -} - -static void -ao_send_configuration(void) -{ - if (--ao_telemetry_config_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; - telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.configuration.config_major = AO_CONFIG_MAJOR; - telemetry.configuration.config_minor = AO_CONFIG_MINOR; - telemetry.configuration.apogee_delay = ao_config.apogee_delay; - telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; - memcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_config_cur = ao_telemetry_config_max; - } -} - -#if HAS_GPS -static void -ao_send_location(void) -{ - if (--ao_telemetry_loc_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_LOCATION; - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.location.flags, - &ao_gps_data.flags, - 26); - ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_loc_cur = ao_telemetry_config_max; - } -} - -static void -ao_send_satellite(void) -{ - if (--ao_telemetry_sat_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_SATELLITE; - ao_mutex_get(&ao_gps_mutex); - telemetry.satellite.channels = ao_gps_tracking_data.channels; - memcpy(&telemetry.satellite.sats, - &ao_gps_tracking_data.sats, - AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); - ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_sat_cur = ao_telemetry_config_max; - } -} -#endif - -#if HAS_COMPANION -static void -ao_send_companion(void) -{ - if (--ao_telemetry_companion_cur <= 0) { - telemetry.generic.type = AO_TELEMETRY_COMPANION; - telemetry.companion.board_id = ao_companion_setup.board_id; - telemetry.companion.update_period = ao_companion_setup.update_period; - telemetry.companion.channels = ao_companion_setup.channels; - ao_mutex_get(&ao_companion_mutex); - memcpy(&telemetry.companion.companion_data, - ao_companion_data, - ao_companion_setup.channels * 2); - ao_mutex_put(&ao_companion_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_companion_cur = ao_telemetry_companion_max; - } -} -#endif - -void -ao_telemetry(void) -{ - uint16_t time; - int16_t delay; - - ao_config_get(); - if (!ao_config.radio_enable) - ao_exit(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - - telemetry.generic.serial = ao_serial_number; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&telemetry); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - - - ao_send_sensor(); -#if HAS_COMPANION - if (ao_companion_running) - ao_send_companion(); -#endif - ao_send_configuration(); -#if HAS_GPS - ao_send_location(); - ao_send_satellite(); -#endif - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - -#if HAS_COMPANION - if (!ao_companion_setup.update_period) - ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); - ao_telemetry_companion_max = ao_companion_setup.update_period / interval; - ao_telemetry_companion_cur = 1; -#endif - - ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; -#if HAS_COMPANION - ao_telemetry_config_cur = ao_telemetry_companion_cur; - if (ao_telemetry_config_max > ao_telemetry_config_cur) - ao_telemetry_config_cur++; -#else - ao_telemetry_config_cur = 1; -#endif - -#if HAS_GPS - ao_telemetry_loc_cur = ao_telemetry_config_cur; - if (ao_telemetry_config_max > ao_telemetry_loc_cur) - ao_telemetry_loc_cur++; - ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max > ao_telemetry_sat_cur) - ao_telemetry_sat_cur++; -#endif - ao_wakeup(&telemetry); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_task; - -void -ao_telemetry_init() -{ - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); -} diff --git a/src/ao_telemini.c b/src/ao_telemini.c deleted file mode 100644 index fa23de01..00000000 --- a/src/ao_telemini.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - /* - * Reduce the transient on the ignite pins at startup by - * pulling the pins low as soon as possible at power up - */ - ao_ignite_set_pins(); - - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_cmd_init(); - ao_storage_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_igniter_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telenano.c b/src/ao_telenano.c deleted file mode 100644 index d91983d0..00000000 --- a/src/ao_telenano.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - ao_clock_init(); - - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_cmd_init(); - ao_storage_init(); - ao_flight_nano_init(); - ao_log_init(); - ao_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c deleted file mode 100644 index d696b914..00000000 --- a/src/ao_teleterra.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define AO_NO_ADC_ISR 1 -#include "ao.h" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_beep_init(); - ao_cmd_init(); - ao_usb_init(); - ao_serial_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_radio_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_test.c b/src/ao_test.c deleted file mode 100644 index 14c2eb75..00000000 --- a/src/ao_test.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -struct ao_task __xdata blink_0_task; -struct ao_task __xdata blink_1_task; -struct ao_task __xdata wakeup_task; -struct ao_task __xdata beep_task; -struct ao_task __xdata echo_task; - -void delay(int n) __reentrant -{ - uint8_t j = 0; - while (--n) - while (--j) - ao_yield(); -} - -static __xdata uint8_t blink_chan; - -void -blink_0(void) -{ - uint8_t b = 0; - for (;;) { - b = 1 - b; - if (b) - ao_led_on(AO_LED_GREEN); - else - ao_led_off(AO_LED_GREEN); - ao_sleep(&blink_chan); - } -} - -void -blink_1(void) -{ - static __xdata struct ao_adc adc; - - for (;;) { - ao_sleep(&ao_adc_head); - ao_adc_get(&adc); - if (adc.accel < 15900) - ao_led_on(AO_LED_RED); - else - ao_led_off(AO_LED_RED); - } -} - -void -wakeup(void) -{ - for (;;) { - ao_delay(AO_MS_TO_TICKS(100)); - ao_wakeup(&blink_chan); - } -} - -void -beep(void) -{ - static __xdata struct ao_adc adc; - - for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); - ao_adc_get(&adc); - if (adc.temp > 7400) - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50)); - } -} - -void -echo(void) -{ - char c; - for (;;) { - ao_usb_flush(); - c = ao_usb_getchar(); - ao_usb_putchar(c); - if (c == '\r') - ao_usb_putchar('\n'); - } -} - -void -main(void) -{ - ao_clock_init(); - -// ao_add_task(&blink_0_task, blink_0); -// ao_add_task(&blink_1_task, blink_1); -// ao_add_task(&wakeup_task, wakeup); -// ao_add_task(&beep_task, beep); - ao_add_task(&echo_task, echo); - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_led_init(); - ao_usb_init(); - - ao_start_scheduler(); -} diff --git a/src/ao_tidongle.c b/src/ao_tidongle.c deleted file mode 100644 index 3b7c2733..00000000 --- a/src/ao_tidongle.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define AO_NO_SERIAL_ISR 1 -#define AO_NO_ADC_ISR 1 -#include "ao.h" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(AO_LED_RED); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_dbg_init(); - ao_config_init(); - /* Bring up the USB link */ - P1DIR |= 1; - P1 |= 1; - ao_start_scheduler(); -} diff --git a/src/ao_timer.c b/src/ao_timer.c deleted file mode 100644 index c977fbc8..00000000 --- a/src/ao_timer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static volatile __data uint16_t ao_tick_count; - -uint16_t ao_time(void) __critical -{ - return ao_tick_count; -} - -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - -#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ - -#if HAS_ADC -volatile __data uint8_t ao_adc_interval = 1; -volatile __data uint8_t ao_adc_count; -#endif - -void ao_timer_isr(void) __interrupt 9 -{ - ++ao_tick_count; -#if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; - ao_adc_poll(); - } -#endif -} - -#if HAS_ADC -void -ao_timer_set_adc_interval(uint8_t interval) __critical -{ - ao_adc_interval = interval; - ao_adc_count = 0; -} -#endif - -void -ao_timer_init(void) -{ - /* NOTE: This uses a timer only present on cc1111 architecture. */ - - /* disable timer 1 */ - T1CTL = 0; - - /* set the sample rate */ - T1CC0H = T1_SAMPLE_TIME >> 8; - T1CC0L = (uint8_t) T1_SAMPLE_TIME; - - T1CCTL0 = T1CCTL_MODE_COMPARE; - T1CCTL1 = 0; - T1CCTL2 = 0; - - /* clear timer value */ - T1CNTL = 0; - - /* enable overflow interrupt */ - OVFIM = 1; - /* enable timer 1 interrupt */ - T1IE = 1; - - /* enable timer 1 in module mode, dividing by 8 */ - T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8; -} - -/* - * AltOS always cranks the clock to the max frequency - */ -void -ao_clock_init(void) -{ - /* Switch system clock to crystal oscilator */ - CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL); - - while (!(SLEEP & SLEEP_XOSC_STB)) - ; - - /* Crank up the timer tick and system clock speed */ - CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) | - (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)); - - while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) != - (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)) - ; -} diff --git a/src/ao_usb.c b/src/ao_usb.c deleted file mode 100644 index 08cb7390..00000000 --- a/src/ao_usb.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_usb.h" - -struct ao_task __xdata ao_usb_task; - -static __xdata uint16_t ao_usb_in_bytes; -static __pdata uint16_t ao_usb_in_bytes_last; -static __xdata uint16_t ao_usb_out_bytes; -static __pdata uint8_t ao_usb_iif; -static __pdata uint8_t ao_usb_running; - -static void -ao_usb_set_interrupts(void) -{ - /* IN interrupts on the control an IN endpoints */ - USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP); - - /* OUT interrupts on the OUT endpoint */ - USBOIE = (1 << AO_USB_OUT_EP); - - /* Only care about reset */ - USBCIE = USBCIE_RSTIE; -} - -/* This interrupt is shared with port 2, - * so when we hook that up, fix this - */ -void -ao_usb_isr(void) __interrupt 6 -{ - USBIF = 0; - ao_usb_iif |= USBIIF; - if (ao_usb_iif & 1) - ao_wakeup(&ao_usb_task); - if (ao_usb_iif & (1 << AO_USB_IN_EP)) - ao_wakeup(&ao_usb_in_bytes); - - if (USBOIF & (1 << AO_USB_OUT_EP)) - ao_wakeup(&ao_stdin_ready); - - if (USBCIF & USBCIF_RSTIF) - ao_usb_set_interrupts(); -#if HAS_BTM -#if BT_LINK_ON_P2 - ao_btm_isr(); -#endif -#endif -} - -struct ao_usb_setup { - uint8_t dir_type_recip; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -} __xdata ao_usb_setup; - -__pdata uint8_t ao_usb_ep0_state; -uint8_t * __pdata ao_usb_ep0_in_data; -__pdata uint8_t ao_usb_ep0_in_len; -__pdata uint8_t ao_usb_ep0_in_buf[2]; -__pdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__pdata ao_usb_ep0_out_data; -__pdata uint8_t ao_usb_configuration; - -/* Send an IN data packet */ -static void -ao_usb_ep0_flush(void) -{ - __pdata uint8_t this_len; - __pdata uint8_t cs0; - - /* If the IN packet hasn't been picked up, just return */ - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_INPKT_RDY) - return; - - this_len = ao_usb_ep0_in_len; - if (this_len > AO_USB_CONTROL_SIZE) - this_len = AO_USB_CONTROL_SIZE; - cs0 = USBCS0_INPKT_RDY; - if (this_len != AO_USB_CONTROL_SIZE) { - cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } - ao_usb_ep0_in_len -= this_len; - while (this_len--) - USBFIFO[0] = *ao_usb_ep0_in_data++; - USBINDEX = 0; - USBCS0 = cs0; -} - -__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; - -/* Walk through the list of descriptors and find a match - */ -static void -ao_usb_get_descriptor(uint16_t value) -{ - __code uint8_t *__pdata descriptor; - __pdata uint8_t type = value >> 8; - __pdata uint8_t index = value; - - descriptor = ao_usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == AO_USB_DESC_CONFIGURATION) - ao_usb_ep0_in_len = descriptor[2]; - else - ao_usb_ep0_in_len = descriptor[0]; - ao_usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -/* Read data from the ep0 OUT fifo - */ -static void -ao_usb_ep0_fill(void) -{ - __pdata uint8_t len; - - USBINDEX = 0; - len = USBCNT0; - if (len > ao_usb_ep0_out_len) - len = ao_usb_ep0_out_len; - ao_usb_ep0_out_len -= len; - while (len--) - *ao_usb_ep0_out_data++ = USBFIFO[0]; -} - -void -ao_usb_ep0_queue_byte(uint8_t a) -{ - ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; -} - -void -ao_usb_set_address(uint8_t address) -{ - ao_usb_running = 1; - USBADDR = address | 0x80; - while (USBADDR & 0x80) - ; -} - -static void -ao_usb_set_configuration(void) -{ - /* Set the IN max packet size, double buffered */ - USBINDEX = AO_USB_IN_EP; - USBMAXI = AO_USB_IN_SIZE >> 3; - USBCSIH |= USBCSIH_IN_DBL_BUF; - - /* Set the OUT max packet size, double buffered */ - USBINDEX = AO_USB_OUT_EP; - USBMAXO = AO_USB_OUT_SIZE >> 3; - USBCSOH = USBCSOH_OUT_DBL_BUF; -} - -static void -ao_usb_ep0_setup(void) -{ - /* Pull the setup packet out of the fifo */ - ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; - ao_usb_ep0_out_len = 8; - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len != 0) - return; - - /* Figure out how to ACK the setup packet */ - if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } else { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } - USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - - ao_usb_ep0_in_data = ao_usb_ep0_in_buf; - ao_usb_ep0_in_len = 0; - switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { - case AO_USB_TYPE_STANDARD: - switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { - case AO_USB_RECIP_DEVICE: - switch(ao_usb_setup.request) { - case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_SET_ADDRESS: - ao_usb_set_address(ao_usb_setup.value); - break; - case AO_USB_REQ_GET_DESCRIPTOR: - ao_usb_get_descriptor(ao_usb_setup.value); - break; - case AO_USB_REQ_GET_CONFIGURATION: - ao_usb_ep0_queue_byte(ao_usb_configuration); - break; - case AO_USB_REQ_SET_CONFIGURATION: - ao_usb_configuration = ao_usb_setup.value; - ao_usb_set_configuration(); - break; - } - break; - case AO_USB_RECIP_INTERFACE: - #pragma disable_warning 110 - switch(ao_usb_setup.request) { - case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_GET_INTERFACE: - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_SET_INTERFACE: - break; - } - break; - case AO_USB_RECIP_ENDPOINT: - switch(ao_usb_setup.request) { - case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); - break; - } - break; - } - break; - case AO_USB_TYPE_CLASS: - switch (ao_usb_setup.request) { - case SET_LINE_CODING: - ao_usb_ep0_out_len = 7; - ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; - break; - case GET_LINE_CODING: - ao_usb_ep0_in_len = 7; - ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; - break; - case SET_CONTROL_LINE_STATE: - break; - } - break; - } - if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { - if (ao_usb_setup.length < ao_usb_ep0_in_len) - ao_usb_ep0_in_len = ao_usb_setup.length; - ao_usb_ep0_flush(); - } -} - -/* End point 0 receives all of the control messages. */ -static void -ao_usb_ep0(void) -{ - __pdata uint8_t cs0; - - ao_usb_ep0_state = AO_USB_EP0_IDLE; - for (;;) { - __critical for (;;) { - if (ao_usb_iif & 1) { - ao_usb_iif &= ~1; - break; - } - ao_sleep(&ao_usb_task); - } - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_SETUP_END) { - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBCS0 = USBCS0_CLR_SETUP_END; - } - if (cs0 & USBCS0_SENT_STALL) { - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBCS0 &= ~USBCS0_SENT_STALL; - } - if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN && - (cs0 & USBCS0_INPKT_RDY) == 0) - { - ao_usb_ep0_flush(); - } - if (cs0 & USBCS0_OUTPKT_RDY) { - switch (ao_usb_ep0_state) { - case AO_USB_EP0_IDLE: - ao_usb_ep0_setup(); - break; - case AO_USB_EP0_DATA_OUT: - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - break; - } - } - } -} - -/* Wait for a free IN buffer */ -static void -ao_usb_in_wait(void) -{ - for (;;) { - USBINDEX = AO_USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - ao_sleep(&ao_usb_in_bytes); - } -} - -/* Send the current IN packet */ -static void -ao_usb_in_send(void) -{ - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes_last = ao_usb_in_bytes; - ao_usb_in_bytes = 0; -} - -void -ao_usb_flush(void) __critical -{ - if (!ao_usb_running) - return; - - /* If there are pending bytes, or if the last packet was full, - * send another IN packet - */ - if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { - ao_usb_in_wait(); - ao_usb_in_send(); - } -} - -void -ao_usb_putchar(char c) __critical __reentrant -{ - if (!ao_usb_running) - return; - - ao_usb_in_wait(); - - /* Queue a byte, sending the packet when full */ - USBFIFO[AO_USB_IN_EP << 1] = c; - if (++ao_usb_in_bytes == AO_USB_IN_SIZE) - ao_usb_in_send(); -} - -char -ao_usb_pollchar(void) __critical -{ - char c; - if (ao_usb_out_bytes == 0) { - USBINDEX = AO_USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return AO_READ_AGAIN; - ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; - 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]; - if (ao_usb_out_bytes == 0) { - USBINDEX = AO_USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - } - return c; -} - -char -ao_usb_getchar(void) __critical -{ - char c; - - while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); - return c; -} - -void -ao_usb_enable(void) -{ - /* Turn on the USB controller */ - SLEEP |= SLEEP_USB_EN; - - ao_usb_set_configuration(); - - ao_usb_set_interrupts(); - - /* enable USB interrupts */ - IEN2 |= IEN2_USBIE; - - /* Clear any pending interrupts */ - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; -} - -void -ao_usb_disable(void) -{ - /* Disable USB interrupts */ - USBIIE = 0; - USBOIE = 0; - USBCIE = 0; - IEN2 &= ~IEN2_USBIE; - - /* Clear any pending interrupts */ - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - - /* Turn off the USB controller */ - SLEEP &= ~SLEEP_USB_EN; -} - -void -ao_usb_init(void) -{ - ao_usb_enable(); - - ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); -} diff --git a/src/ao_usb.h b/src/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/at45db161d.h b/src/at45db161d.h deleted file mode 100644 index 9ee6f1b6..00000000 --- a/src/at45db161d.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ - -#ifndef _AT45DB161D_H_ -#define _AT45DB161D_H_ - -/* - * We reserve the last block on the device for - * configuration space. Writes and reads in this - * area return errors. - */ - - -#define FLASH_READ 0x03 -#define FLASH_WRITE 0x82 -#define FLASH_PAGE_ERASE 0x81 -#define FLASH_READ_STATUS 0xd7 -#define FLASH_SET_CONFIG 0x3d - -#define FLASH_SET_512_BYTE_0 0x2a -#define FLASH_SET_512_BYTE_1 0x80 -#define FLASH_SET_512_BYTE_2 0xa6 - -#define FLASH_STATUS_RDY (1 << 7) -#define FLASH_STATUS_COMP (1 << 6) -#define FLASH_STATUS_PROTECT (1 << 1) -#define FLASH_STATUS_PAGESIZE_512 (1 << 0) - -#endif /* _AT45DB161D_H_ */ diff --git a/src/cc1111.h b/src/cc1111.h deleted file mode 100644 index e52aa79f..00000000 --- a/src/cc1111.h +++ /dev/null @@ -1,1306 +0,0 @@ -/*------------------------------------------------------------------------- - Register Declarations for the ChipCon CC1111 Processor Range - - Copyright © 2008 Keith Packard - - 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. - - Adapted from the Cygnal C8051F12x config file which is: - - Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ - -#ifndef _CC1111_H_ -#define _CC1111_H_ -#include -#include - -__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 */ - -#define IEN0_EA (1 << 7) -#define IEN0_STIE (1 << 5) -#define IEN0_ENCIE (1 << 4) -#define IEN0_URX1IE (1 << 3) -#define IEN0_I2SRXIE (1 << 3) -#define IEN0_URX0IE (1 << 2) -#define IEN0_ADCIE (1 << 1) -#define IEN0_RFTXRXIE (1 << 0) - -__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_T3IE (1 << 3) /* Timer 3 interrupt enable */ -#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ -#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ -#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ - -/* IEN2 */ -__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_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ -#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ -#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ -#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ -#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ -#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ - -/* CLKCON 0xC6 */ -__sfr __at 0xC6 CLKCON; /* Clock Control */ - -#define CLKCON_OSC32K_RC (1 << 7) -#define CLKCON_OSC32K_XTAL (0 << 7) -#define CLKCON_OSC32K_MASK (1 << 7) -#define CLKCON_OSC_RC (1 << 6) -#define CLKCON_OSC_XTAL (0 << 6) -#define CLKCON_OSC_MASK (1 << 6) -#define CLKCON_TICKSPD_MASK (7 << 3) -# define CLKCON_TICKSPD_1 (0 << 3) -# define CLKCON_TICKSPD_1_2 (1 << 3) -# define CLKCON_TICKSPD_1_4 (2 << 3) -# define CLKCON_TICKSPD_1_8 (3 << 3) -# define CLKCON_TICKSPD_1_16 (4 << 3) -# define CLKCON_TICKSPD_1_32 (5 << 3) -# define CLKCON_TICKSPD_1_64 (6 << 3) -# define CLKCON_TICKSPD_1_128 (7 << 3) - -#define CLKCON_CLKSPD_MASK (7 << 0) -# define CLKCON_CLKSPD_1 (0 << 0) -# define CLKCON_CLKSPD_1_2 (1 << 0) -# define CLKCON_CLKSPD_1_4 (2 << 0) -# define CLKCON_CLKSPD_1_8 (3 << 0) -# define CLKCON_CLKSPD_1_16 (4 << 0) -# define CLKCON_CLKSPD_1_32 (5 << 0) -# define CLKCON_CLKSPD_1_64 (6 << 0) -# define CLKCON_CLKSPD_1_128 (7 << 0) - -/* SLEEP 0xBE */ -#define SLEEP_USB_EN (1 << 7) -#define SLEEP_XOSC_STB (1 << 6) -#define SLEEP_HFRC_STB (1 << 5) -#define SLEEP_RST_POWER (0 << 3) -#define SLEEP_RST_EXTERNAL (1 << 3) -#define SLEEP_RST_WATCHDOG (2 << 3) -#define SLEEP_RST_MASK (3 << 3) -#define SLEEP_OSC_PD (1 << 2) -#define SLEEP_MODE_PM0 (0 << 0) -#define SLEEP_MODE_PM1 (1 << 0) -#define SLEEP_MODE_PM2 (2 << 0) -#define SLEEP_MODE_PM3 (3 << 0) -#define SLEEP_MODE_MASK (3 << 0) - -/* PCON 0x87 */ -__sfr __at 0x87 PCON; /* Power Mode Control Register */ - -#define PCON_IDLE (1 << 0) - -/* - * TCON - */ -__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 */ - -#define TCON_URX1IF (1 << 7) -#define TCON_I2SRXIF (1 << 7) -#define TCON_ADCIF (1 << 5) -#define TCON_URX0IF (1 << 3) -#define TCON_RFTXRXIF (1 << 1) - -/* - * S0CON - */ -__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ - -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 */ - -#define S1CON_RFIF_1 (1 << 1) -#define S1CON_RFIF_0 (1 << 0) - -/* - * IRCON - */ -__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 */ - -#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ -#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ -#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ -#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ -#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ -#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ -#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ - -/* - * IRCON2 - */ -__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 */ - -#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ -#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ -#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ -#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ -#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ -#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ -#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ - -/* - * IP1 - Interrupt Priority 1 - */ - -/* - * Interrupt priority groups: - * - * IPG0 RFTXRX RF DMA - * IPG1 ADC T1 P2INT/USB - * IPG2 URX0 T2 UTX0 - * IPG3 URX1/I2SRX T3 UTX1 / I2STX - * IPG4 ENC T4 P1INT - * IPG5 ST P0INT WDT - * - * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first - */ - -__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ -__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ - -#define IP1_IPG5 (1 << 5) -#define IP1_IPG4 (1 << 4) -#define IP1_IPG3 (1 << 3) -#define IP1_IPG2 (1 << 2) -#define IP1_IPG1 (1 << 1) -#define IP1_IPG0 (1 << 0) - -#define IP0_IPG5 (1 << 5) -#define IP0_IPG4 (1 << 4) -#define IP0_IPG3 (1 << 3) -#define IP0_IPG2 (1 << 2) -#define IP0_IPG1 (1 << 1) -#define IP0_IPG0 (1 << 0) - -/* - * Timer 1 - */ -#define T1CTL_MODE_SUSPENDED (0 << 0) -#define T1CTL_MODE_FREE (1 << 0) -#define T1CTL_MODE_MODULO (2 << 0) -#define T1CTL_MODE_UP_DOWN (3 << 0) -#define T1CTL_MODE_MASK (3 << 0) -#define T1CTL_DIV_1 (0 << 2) -#define T1CTL_DIV_8 (1 << 2) -#define T1CTL_DIV_32 (2 << 2) -#define T1CTL_DIV_128 (3 << 2) -#define T1CTL_DIV_MASK (3 << 2) -#define T1CTL_OVFIF (1 << 4) -#define T1CTL_CH0IF (1 << 5) -#define T1CTL_CH1IF (1 << 6) -#define T1CTL_CH2IF (1 << 7) - -#define T1CCTL_NO_CAPTURE (0 << 0) -#define T1CCTL_CAPTURE_RISING (1 << 0) -#define T1CCTL_CAPTURE_FALLING (2 << 0) -#define T1CCTL_CAPTURE_BOTH (3 << 0) -#define T1CCTL_CAPTURE_MASK (3 << 0) - -#define T1CCTL_MODE_CAPTURE (0 << 2) -#define T1CCTL_MODE_COMPARE (1 << 2) - -#define T1CTL_CMP_SET (0 << 3) -#define T1CTL_CMP_CLEAR (1 << 3) -#define T1CTL_CMP_TOGGLE (2 << 3) -#define T1CTL_CMP_SET_CLEAR (3 << 3) -#define T1CTL_CMP_CLEAR_SET (4 << 3) - -#define T1CTL_IM_DISABLED (0 << 6) -#define T1CTL_IM_ENABLED (1 << 6) - -#define T1CTL_CPSEL_NORMAL (0 << 7) -#define T1CTL_CPSEL_RF (1 << 7) - -/* - * Timer 3 and Timer 4 - */ - -/* Timer count */ -__sfr __at 0xCA T3CNT; -__sfr __at 0xEA T4CNT; - -/* Timer control */ - -__sfr __at 0xCB T3CTL; -__sfr __at 0xEB T4CTL; - -#define TxCTL_DIV_1 (0 << 5) -#define TxCTL_DIV_2 (1 << 5) -#define TxCTL_DIV_4 (2 << 5) -#define TxCTL_DIV_8 (3 << 5) -#define TxCTL_DIV_16 (4 << 5) -#define TxCTL_DIV_32 (5 << 5) -#define TxCTL_DIV_64 (6 << 5) -#define TxCTL_DIV_128 (7 << 5) -#define TxCTL_START (1 << 4) -#define TxCTL_OVFIM (1 << 3) -#define TxCTL_CLR (1 << 2) -#define TxCTL_MODE_FREE (0 << 0) -#define TxCTL_MODE_DOWN (1 << 0) -#define TxCTL_MODE_MODULO (2 << 0) -#define TxCTL_MODE_UP_DOWN (3 << 0) - -/* Timer 4 channel 0 compare control */ - -__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_CLEAR (1 << 3) -#define TxCCTLy_CMP_TOGGLE (2 << 3) -#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) -#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) -#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) -#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 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; - -/* - * Peripheral control - */ - -__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) - -#define PERCFG_T3CFG_ALT_1 (0 << 5) -#define PERCFG_T3CFG_ALT_2 (1 << 5) -#define PERCFG_T3CFG_ALT_MASK (1 << 5) - -#define PERCFG_T4CFG_ALT_1 (0 << 4) -#define PERCFG_T4CFG_ALT_2 (1 << 4) -#define PERCFG_T4CFG_ALT_MASK (1 << 4) - -#define PERCFG_U1CFG_ALT_1 (0 << 1) -#define PERCFG_U1CFG_ALT_2 (1 << 1) -#define PERCFG_U1CFG_ALT_MASK (1 << 1) - -#define PERCFG_U0CFG_ALT_1 (0 << 0) -#define PERCFG_U0CFG_ALT_2 (1 << 0) -#define PERCFG_U0CFG_ALT_MASK (1 << 0) - -/* directly addressed USB registers */ -__xdata __at (0xde00) volatile uint8_t USBADDR; -__xdata __at (0xde01) volatile uint8_t USBPOW; -__xdata __at (0xde02) volatile uint8_t USBIIF; - -__xdata __at (0xde04) volatile uint8_t USBOIF; - -__xdata __at (0xde06) volatile uint8_t USBCIF; - -# define USBCIF_SOFIF (1 << 3) -# define USBCIF_RSTIF (1 << 2) -# define USBCIF_RESUMEIF (1 << 1) -# define USBCIF_SUSPENDIF (1 << 0) - -__xdata __at (0xde07) volatile uint8_t USBIIE; - -__xdata __at (0xde09) volatile uint8_t USBOIE; - -__xdata __at (0xde0b) volatile uint8_t USBCIE; - -# define USBCIE_SOFIE (1 << 3) -# define USBCIE_RSTIE (1 << 2) -# define USBCIE_RESUMEIE (1 << 1) -# define USBCIE_SUSPENDIE (1 << 0) - -__xdata __at (0xde0c) volatile uint8_t USBFRML; -__xdata __at (0xde0d) volatile uint8_t USBFRMH; -__xdata __at (0xde0e) volatile uint8_t USBINDEX; - -/* indexed USB registers, must set USBINDEX to 0-5 */ -__xdata __at (0xde10) volatile uint8_t USBMAXI; -__xdata __at (0xde11) volatile uint8_t USBCS0; - -# define USBCS0_CLR_SETUP_END (1 << 7) -# define USBCS0_CLR_OUTPKT_RDY (1 << 6) -# define USBCS0_SEND_STALL (1 << 5) -# define USBCS0_SETUP_END (1 << 4) -# define USBCS0_DATA_END (1 << 3) -# define USBCS0_SENT_STALL (1 << 2) -# define USBCS0_INPKT_RDY (1 << 1) -# define USBCS0_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde11) volatile uint8_t USBCSIL; - -# define USBCSIL_CLR_DATA_TOG (1 << 6) -# define USBCSIL_SENT_STALL (1 << 5) -# define USBCSIL_SEND_STALL (1 << 4) -# define USBCSIL_FLUSH_PACKET (1 << 3) -# define USBCSIL_UNDERRUN (1 << 2) -# define USBCSIL_PKT_PRESENT (1 << 1) -# define USBCSIL_INPKT_RDY (1 << 0) - -__xdata __at (0xde12) volatile uint8_t USBCSIH; - -# define USBCSIH_AUTOSET (1 << 7) -# define USBCSIH_ISO (1 << 6) -# define USBCSIH_FORCE_DATA_TOG (1 << 3) -# define USBCSIH_IN_DBL_BUF (1 << 0) - -__xdata __at (0xde13) volatile uint8_t USBMAXO; -__xdata __at (0xde14) volatile uint8_t USBCSOL; - -# define USBCSOL_CLR_DATA_TOG (1 << 7) -# define USBCSOL_SENT_STALL (1 << 6) -# define USBCSOL_SEND_STALL (1 << 5) -# define USBCSOL_FLUSH_PACKET (1 << 4) -# define USBCSOL_DATA_ERROR (1 << 3) -# define USBCSOL_OVERRUN (1 << 2) -# define USBCSOL_FIFO_FULL (1 << 1) -# define USBCSOL_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde15) volatile uint8_t USBCSOH; - -# define USBCSOH_AUTOCLEAR (1 << 7) -# define USBCSOH_ISO (1 << 6) -# define USBCSOH_OUT_DBL_BUF (1 << 0) - -__xdata __at (0xde16) volatile uint8_t USBCNT0; -__xdata __at (0xde16) volatile uint8_t USBCNTL; -__xdata __at (0xde17) volatile uint8_t USBCNTH; - -__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; - -/* ADC Data register, low and high */ -__sfr at 0xBA ADCL; -__sfr at 0xBB ADCH; -__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; - -/* ADC Control Register 1 */ -__sfr at 0xB4 ADCCON1; - -# define ADCCON1_EOC (1 << 7) /* conversion complete */ -# define ADCCON1_ST (1 << 6) /* start conversion */ - -# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ -# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ -# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ -# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ -# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ - -# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ -# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ -# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ - -/* ADC Control Register 2 */ -__sfr at 0xB5 ADCCON2; - -# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ -# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ -# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ -# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ - -# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ -# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ - -# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON2_SCH_SHIFT 0 -# define ADCCON2_SCH_AIN0 (0 << 0) -# define ADCCON2_SCH_AIN1 (1 << 0) -# define ADCCON2_SCH_AIN2 (2 << 0) -# define ADCCON2_SCH_AIN3 (3 << 0) -# define ADCCON2_SCH_AIN4 (4 << 0) -# define ADCCON2_SCH_AIN5 (5 << 0) -# define ADCCON2_SCH_AIN6 (6 << 0) -# define ADCCON2_SCH_AIN7 (7 << 0) -# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) -# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) -# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) -# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) -# define ADCCON2_SCH_GND (0xc << 0) -# define ADCCON2_SCH_VREF (0xd << 0) -# define ADCCON2_SCH_TEMP (0xe << 0) -# define ADCCON2_SCH_VDD_3 (0xf << 0) - - -/* ADC Control Register 3 */ -__sfr at 0xB6 ADCCON3; - -# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ -# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ -# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ -# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ -# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ -# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ -# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON3_ECH_SHIFT 0 -# define ADCCON3_ECH_AIN0 (0 << 0) -# define ADCCON3_ECH_AIN1 (1 << 0) -# define ADCCON3_ECH_AIN2 (2 << 0) -# define ADCCON3_ECH_AIN3 (3 << 0) -# define ADCCON3_ECH_AIN4 (4 << 0) -# define ADCCON3_ECH_AIN5 (5 << 0) -# define ADCCON3_ECH_AIN6 (6 << 0) -# define ADCCON3_ECH_AIN7 (7 << 0) -# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) -# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) -# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) -# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) -# define ADCCON3_ECH_GND (0xc << 0) -# define ADCCON3_ECH_VREF (0xd << 0) -# define ADCCON3_ECH_TEMP (0xe << 0) -# define ADCCON3_ECH_VDD_3 (0xf << 0) - -/* - * ADC configuration register, this selects which - * GPIO pins are to be used as ADC inputs - */ -__sfr at 0xF2 ADCCFG; - -/* - * Watchdog timer - */ - -__sfr at 0xc9 WDCTL; - -#define WDCTL_CLEAR_FIRST (0xa << 4) -#define WDCTL_CLEAR_SECOND (0x5 << 4) -#define WDCTL_EN (1 << 3) -#define WDCTL_MODE_WATCHDOG (0 << 2) -#define WDCTL_MODE_TIMER (1 << 2) -#define WDCTL_MODE_MASK (1 << 2) -#define WDCTL_INT_32768 (0 << 0) -#define WDCTL_INT_8192 (1 << 0) -#define WDCTL_INT_512 (2 << 0) -#define WDCTL_INT_64 (3 << 0) - -/* - * Pin selectors, these set which pins are - * using their peripheral function - */ -__sfr at 0xF3 P0SEL; -__sfr at 0xF4 P1SEL; -__sfr at 0xF5 P2SEL; - -#define P2SEL_PRI3P1_USART0 (0 << 6) -#define P2SEL_PRI3P1_USART1 (1 << 6) -#define P2SEL_PRI3P1_MASK (1 << 6) -#define P2SEL_PRI2P1_USART1 (0 << 5) -#define P2SEL_PRI2P1_TIMER3 (1 << 5) -#define P2SEL_PRI2P1_MASK (1 << 5) -#define P2SEL_PRI1P1_TIMER1 (0 << 4) -#define P2SEL_PRI1P1_TIMER4 (1 << 4) -#define P2SEL_PRI1P1_MASK (1 << 4) -#define P2SEL_PRI0P1_USART0 (0 << 3) -#define P2SEL_PRI0P1_TIMER1 (1 << 3) -#define P2SEL_PRI0P1_MASK (1 << 3) -#define P2SEL_SELP2_4_GPIO (0 << 2) -#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) -#define P2SEL_SELP2_4_MASK (1 << 2) -#define P2SEL_SELP2_3_GPIO (0 << 1) -#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) -#define P2SEL_SELP2_3_MASK (1 << 1) -#define P2SEL_SELP2_0_GPIO (0 << 0) -#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) -#define P2SEL_SELP2_0_MASK (1 << 0) - -/* - * For pins used as GPIOs, these set which are used as outputs - */ -__sfr at 0xFD P0DIR; -__sfr at 0xFE P1DIR; -__sfr at 0xFF P2DIR; - -#define P2DIR_PRIP0_USART0_USART1 (0 << 6) -#define P2DIR_PRIP0_USART1_USART0 (1 << 6) -#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) -#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) -#define P2DIR_PRIP0_MASK (3 << 6) - -__sfr at 0x8F P0INP; - -/* Select between tri-state and pull up/down - * for pins P0_0 - P0_7. - */ -#define P0INP_MDP0_7_PULL (0 << 7) -#define P0INP_MDP0_7_TRISTATE (1 << 7) -#define P0INP_MDP0_6_PULL (0 << 6) -#define P0INP_MDP0_6_TRISTATE (1 << 6) -#define P0INP_MDP0_5_PULL (0 << 5) -#define P0INP_MDP0_5_TRISTATE (1 << 5) -#define P0INP_MDP0_4_PULL (0 << 4) -#define P0INP_MDP0_4_TRISTATE (1 << 4) -#define P0INP_MDP0_3_PULL (0 << 3) -#define P0INP_MDP0_3_TRISTATE (1 << 3) -#define P0INP_MDP0_2_PULL (0 << 2) -#define P0INP_MDP0_2_TRISTATE (1 << 2) -#define P0INP_MDP0_1_PULL (0 << 1) -#define P0INP_MDP0_1_TRISTATE (1 << 1) -#define P0INP_MDP0_0_PULL (0 << 0) -#define P0INP_MDP0_0_TRISTATE (1 << 0) - -__sfr at 0xF6 P1INP; - -/* Select between tri-state and pull up/down - * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are - * always tri-stated - */ -#define P1INP_MDP1_7_PULL (0 << 7) -#define P1INP_MDP1_7_TRISTATE (1 << 7) -#define P1INP_MDP1_6_PULL (0 << 6) -#define P1INP_MDP1_6_TRISTATE (1 << 6) -#define P1INP_MDP1_5_PULL (0 << 5) -#define P1INP_MDP1_5_TRISTATE (1 << 5) -#define P1INP_MDP1_4_PULL (0 << 4) -#define P1INP_MDP1_4_TRISTATE (1 << 4) -#define P1INP_MDP1_3_PULL (0 << 3) -#define P1INP_MDP1_3_TRISTATE (1 << 3) -#define P1INP_MDP1_2_PULL (0 << 2) -#define P1INP_MDP1_2_TRISTATE (1 << 2) - -__sfr at 0xF7 P2INP; -/* P2INP has three extra bits which are used to choose - * between pull-up and pull-down when they are not tri-stated - */ -#define P2INP_PDUP2_PULL_UP (0 << 7) -#define P2INP_PDUP2_PULL_DOWN (1 << 7) -#define P2INP_PDUP1_PULL_UP (0 << 6) -#define P2INP_PDUP1_PULL_DOWN (1 << 6) -#define P2INP_PDUP0_PULL_UP (0 << 5) -#define P2INP_PDUP0_PULL_DOWN (1 << 5) - -/* For the P2 pins, choose between tri-state and pull up/down - * mode - */ -#define P2INP_MDP2_4_PULL (0 << 4) -#define P2INP_MDP2_4_TRISTATE (1 << 4) -#define P2INP_MDP2_3_PULL (0 << 3) -#define P2INP_MDP2_3_TRISTATE (1 << 3) -#define P2INP_MDP2_2_PULL (0 << 2) -#define P2INP_MDP2_2_TRISTATE (1 << 2) -#define P2INP_MDP2_1_PULL (0 << 1) -#define P2INP_MDP2_1_TRISTATE (1 << 1) -#define P2INP_MDP2_0_PULL (0 << 0) -#define P2INP_MDP2_0_TRISTATE (1 << 0) - -/* GPIO interrupt status flags */ -__sfr at 0x89 P0IFG; -__sfr at 0x8A P1IFG; -__sfr at 0x8B P2IFG; - -#define P0IFG_USB_RESUME (1 << 7) - -__sfr at 0x8C PICTL; -#define PICTL_P2IEN (1 << 5) -#define PICTL_P0IENH (1 << 4) -#define PICTL_P0IENL (1 << 3) -#define PICTL_P2ICON (1 << 2) -#define PICTL_P1ICON (1 << 1) -#define PICTL_P0ICON (1 << 0) - -/* GPIO pins */ -__sfr at 0x80 P0; - -sbit at 0x80 P0_0; -sbit at 0x81 P0_1; -sbit at 0x82 P0_2; -sbit at 0x83 P0_3; -sbit at 0x84 P0_4; -sbit at 0x85 P0_5; -sbit at 0x86 P0_6; -sbit at 0x87 P0_7; - -__sfr at 0x90 P1; - -sbit at 0x90 P1_0; -sbit at 0x91 P1_1; -sbit at 0x92 P1_2; -sbit at 0x93 P1_3; -sbit at 0x94 P1_4; -sbit at 0x95 P1_5; -sbit at 0x96 P1_6; -sbit at 0x97 P1_7; - -__sfr at 0xa0 P2; - -sbit at 0xa0 P2_0; -sbit at 0xa1 P2_1; -sbit at 0xa2 P2_2; -sbit at 0xa3 P2_3; -sbit at 0xa4 P2_4; - -/* DMA controller */ -struct cc_dma_channel { - uint8_t src_high; - uint8_t src_low; - uint8_t dst_high; - uint8_t dst_low; - uint8_t len_high; - uint8_t len_low; - uint8_t cfg0; - uint8_t cfg1; -}; - -# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) -# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) -# define DMA_LEN_HIGH_VLEN (2 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) -# define DMA_LEN_HIGH_MASK (0x1f) - -# define DMA_CFG0_WORDSIZE_8 (0 << 7) -# define DMA_CFG0_WORDSIZE_16 (1 << 7) -# define DMA_CFG0_TMODE_MASK (3 << 5) -# define DMA_CFG0_TMODE_SINGLE (0 << 5) -# define DMA_CFG0_TMODE_BLOCK (1 << 5) -# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) -# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) - -/* - * DMA triggers - */ -# define DMA_CFG0_TRIGGER_NONE 0 -# define DMA_CFG0_TRIGGER_PREV 1 -# define DMA_CFG0_TRIGGER_T1_CH0 2 -# define DMA_CFG0_TRIGGER_T1_CH1 3 -# define DMA_CFG0_TRIGGER_T1_CH2 4 -# define DMA_CFG0_TRIGGER_T2_OVFL 6 -# define DMA_CFG0_TRIGGER_T3_CH0 7 -# define DMA_CFG0_TRIGGER_T3_CH1 8 -# define DMA_CFG0_TRIGGER_T4_CH0 9 -# define DMA_CFG0_TRIGGER_T4_CH1 10 -# define DMA_CFG0_TRIGGER_IOC_0 12 -# define DMA_CFG0_TRIGGER_IOC_1 13 -# define DMA_CFG0_TRIGGER_URX0 14 -# define DMA_CFG0_TRIGGER_UTX0 15 -# define DMA_CFG0_TRIGGER_URX1 16 -# define DMA_CFG0_TRIGGER_UTX1 17 -# define DMA_CFG0_TRIGGER_FLASH 18 -# define DMA_CFG0_TRIGGER_RADIO 19 -# define DMA_CFG0_TRIGGER_ADC_CHALL 20 -# define DMA_CFG0_TRIGGER_ADC_CH0 21 -# define DMA_CFG0_TRIGGER_ADC_CH1 22 -# define DMA_CFG0_TRIGGER_ADC_CH2 23 -# define DMA_CFG0_TRIGGER_ADC_CH3 24 -# define DMA_CFG0_TRIGGER_ADC_CH4 25 -# define DMA_CFG0_TRIGGER_ADC_CH5 26 -# define DMA_CFG0_TRIGGER_ADC_CH6 27 -# define DMA_CFG0_TRIGGER_I2SRX 27 -# define DMA_CFG0_TRIGGER_ADC_CH7 28 -# define DMA_CFG0_TRIGGER_I2STX 28 -# define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_DNC_UP 30 - -# define DMA_CFG1_SRCINC_MASK (3 << 6) -# define DMA_CFG1_SRCINC_0 (0 << 6) -# define DMA_CFG1_SRCINC_1 (1 << 6) -# define DMA_CFG1_SRCINC_2 (2 << 6) -# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) - -# define DMA_CFG1_DESTINC_MASK (3 << 4) -# define DMA_CFG1_DESTINC_0 (0 << 4) -# define DMA_CFG1_DESTINC_1 (1 << 4) -# define DMA_CFG1_DESTINC_2 (2 << 4) -# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) - -# define DMA_CFG1_IRQMASK (1 << 3) -# define DMA_CFG1_M8 (1 << 2) - -# define DMA_CFG1_PRIORITY_MASK (3 << 0) -# define DMA_CFG1_PRIORITY_LOW (0 << 0) -# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) -# define DMA_CFG1_PRIORITY_HIGH (2 << 0) - -/* - * DMAARM - DMA Channel Arm - */ - -__sfr at 0xD6 DMAARM; - -# define DMAARM_ABORT (1 << 7) -# define DMAARM_DMAARM4 (1 << 4) -# define DMAARM_DMAARM3 (1 << 3) -# define DMAARM_DMAARM2 (1 << 2) -# define DMAARM_DMAARM1 (1 << 1) -# define DMAARM_DMAARM0 (1 << 0) - -/* - * DMAREQ - DMA Channel Start Request and Status - */ - -__sfr at 0xD7 DMAREQ; - -# define DMAREQ_DMAREQ4 (1 << 4) -# define DMAREQ_DMAREQ3 (1 << 3) -# define DMAREQ_DMAREQ2 (1 << 2) -# define DMAREQ_DMAREQ1 (1 << 1) -# define DMAREQ_DMAREQ0 (1 << 0) - -/* - * DMA configuration 0 address - */ - -__sfr at 0xD5 DMA0CFGH; -__sfr at 0xD4 DMA0CFGL; - -/* - * DMA configuration 1-4 address - */ - -__sfr at 0xD3 DMA1CFGH; -__sfr at 0xD2 DMA1CFGL; - -/* - * DMAIRQ - DMA Interrupt Flag - */ - -__sfr at 0xD1 DMAIRQ; - -# define DMAIRQ_DMAIF4 (1 << 4) -# define DMAIRQ_DMAIF3 (1 << 3) -# define DMAIRQ_DMAIF2 (1 << 2) -# define DMAIRQ_DMAIF1 (1 << 1) -# define DMAIRQ_DMAIF0 (1 << 0) - -/* - * UART registers - */ - -/* USART config/status registers */ -__sfr at 0x86 U0CSR; -__sfr at 0xF8 U1CSR; - -# define UxCSR_MODE_UART (1 << 7) -# define UxCSR_MODE_SPI (0 << 7) -# define UxCSR_RE (1 << 6) -# define UxCSR_SLAVE (1 << 5) -# define UxCSR_MASTER (0 << 5) -# define UxCSR_FE (1 << 4) -# define UxCSR_ERR (1 << 3) -# define UxCSR_RX_BYTE (1 << 2) -# define UxCSR_TX_BYTE (1 << 1) -# define UxCSR_ACTIVE (1 << 0) - -/* UART configuration registers */ -__sfr at 0xc4 U0UCR; -__sfr at 0xfb U1UCR; - -# define UxUCR_FLUSH (1 << 7) -# define UxUCR_FLOW_DISABLE (0 << 6) -# define UxUCR_FLOW_ENABLE (1 << 6) -# define UxUCR_D9_EVEN_PARITY (0 << 5) -# define UxUCR_D9_ODD_PARITY (1 << 5) -# define UxUCR_BIT9_8_BITS (0 << 4) -# define UxUCR_BIT9_9_BITS (1 << 4) -# define UxUCR_PARITY_DISABLE (0 << 3) -# define UxUCR_PARITY_ENABLE (1 << 3) -# define UxUCR_SPB_1_STOP_BIT (0 << 2) -# define UxUCR_SPB_2_STOP_BITS (1 << 2) -# define UxUCR_STOP_LOW (0 << 1) -# define UxUCR_STOP_HIGH (1 << 1) -# define UxUCR_START_LOW (0 << 0) -# define UxUCR_START_HIGH (1 << 0) - -/* USART General configuration registers (mostly SPI) */ -__sfr at 0xc5 U0GCR; -__sfr at 0xfc U1GCR; - -# define UxGCR_CPOL_NEGATIVE (0 << 7) -# define UxGCR_CPOL_POSITIVE (1 << 7) -# define UxGCR_CPHA_FIRST_EDGE (0 << 6) -# define UxGCR_CPHA_SECOND_EDGE (1 << 6) -# define UxGCR_ORDER_LSB (0 << 5) -# define UxGCR_ORDER_MSB (1 << 5) -# define UxGCR_BAUD_E_MASK (0x1f) -# define UxGCR_BAUD_E_SHIFT 0 - -/* USART data registers */ -__sfr at 0xc1 U0DBUF; -__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr at 0xf9 U1DBUF; -__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; - -/* USART baud rate registers, M value */ -__sfr at 0xc2 U0BAUD; -__sfr at 0xfa U1BAUD; - -/* Flash controller */ - -__sfr at 0xAE FCTL; -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - -/* Flash write data. Write two bytes here */ -__sfr at 0xAF FWDATA; -__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; - -/* Flash write/erase address */ -__sfr at 0xAD FADDRH; -__sfr at 0xAC FADDRL; - -/* Flash timing */ -__sfr at 0xAB FWT; - -/* Radio */ - -__sfr at 0xD9 RFD; -__xdata at (0xDFD9) volatile uint8_t RFDXADDR; - -__sfr at 0xE9 RFIF; -#define RFIF_IM_TXUNF (1 << 7) -#define RFIF_IM_RXOVF (1 << 6) -#define RFIF_IM_TIMEOUT (1 << 5) -#define RFIF_IM_DONE (1 << 4) -#define RFIF_IM_CS (1 << 3) -#define RFIF_IM_PQT (1 << 2) -#define RFIF_IM_CCA (1 << 1) -#define RFIF_IM_SFD (1 << 0) - -__sfr at 0x91 RFIM; -#define RFIM_IM_TXUNF (1 << 7) -#define RFIM_IM_RXOVF (1 << 6) -#define RFIM_IM_TIMEOUT (1 << 5) -#define RFIM_IM_DONE (1 << 4) -#define RFIM_IM_CS (1 << 3) -#define RFIM_IM_PQT (1 << 2) -#define RFIM_IM_CCA (1 << 1) -#define RFIM_IM_SFD (1 << 0) - -__sfr at 0xE1 RFST; - -#define RFST_SFSTXON 0x00 -#define RFST_SCAL 0x01 -#define RFST_SRX 0x02 -#define RFST_STX 0x03 -#define RFST_SIDLE 0x04 - -__xdata __at (0xdf00) uint8_t RF[0x3c]; - -__xdata __at (0xdf2f) uint8_t RF_IOCFG2; -#define RF_IOCFG2_OFF 0x2f - -__xdata __at (0xdf30) uint8_t RF_IOCFG1; -#define RF_IOCFG1_OFF 0x30 - -__xdata __at (0xdf31) uint8_t RF_IOCFG0; -#define RF_IOCFG0_OFF 0x31 - -__xdata __at (0xdf00) uint8_t RF_SYNC1; -#define RF_SYNC1_OFF 0x00 - -__xdata __at (0xdf01) uint8_t RF_SYNC0; -#define RF_SYNC0_OFF 0x01 - -__xdata __at (0xdf02) uint8_t RF_PKTLEN; -#define RF_PKTLEN_OFF 0x02 - -__xdata __at (0xdf03) uint8_t RF_PKTCTRL1; -#define RF_PKTCTRL1_OFF 0x03 -#define PKTCTRL1_PQT_MASK (0x7 << 5) -#define PKTCTRL1_PQT_SHIFT 5 -#define PKTCTRL1_APPEND_STATUS (1 << 2) -#define PKTCTRL1_ADR_CHK_NONE (0 << 0) -#define PKTCTRL1_ADR_CHK_NO_BROADCAST (1 << 0) -#define PKTCTRL1_ADR_CHK_00_BROADCAST (2 << 0) -#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST (3 << 0) - -/* If APPEND_STATUS is used, two bytes will be added to the packet data */ -#define PKT_APPEND_STATUS_0_RSSI_MASK (0xff) -#define PKT_APPEND_STATUS_0_RSSI_SHIFT 0 -#define PKT_APPEND_STATUS_1_CRC_OK (1 << 7) -#define PKT_APPEND_STATUS_1_LQI_MASK (0x7f) -#define PKT_APPEND_STATUS_1_LQI_SHIFT 0 - -__xdata __at (0xdf04) uint8_t RF_PKTCTRL0; -#define RF_PKTCTRL0_OFF 0x04 -#define RF_PKTCTRL0_WHITE_DATA (1 << 6) -#define RF_PKTCTRL0_PKT_FORMAT_NORMAL (0 << 4) -#define RF_PKTCTRL0_PKT_FORMAT_RANDOM (2 << 4) -#define RF_PKTCTRL0_CRC_EN (1 << 2) -#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED (0 << 0) -#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE (1 << 0) - -__xdata __at (0xdf05) uint8_t RF_ADDR; -#define RF_ADDR_OFF 0x05 - -__xdata __at (0xdf06) uint8_t RF_CHANNR; -#define RF_CHANNR_OFF 0x06 - -__xdata __at (0xdf07) uint8_t RF_FSCTRL1; -#define RF_FSCTRL1_OFF 0x07 - -#define RF_FSCTRL1_FREQ_IF_SHIFT (0) - -__xdata __at (0xdf08) uint8_t RF_FSCTRL0; -#define RF_FSCTRL0_OFF 0x08 - -#define RF_FSCTRL0_FREQOFF_SHIFT (0) - -__xdata __at (0xdf09) uint8_t RF_FREQ2; -#define RF_FREQ2_OFF 0x09 - -__xdata __at (0xdf0a) uint8_t RF_FREQ1; -#define RF_FREQ1_OFF 0x0a - -__xdata __at (0xdf0b) uint8_t RF_FREQ0; -#define RF_FREQ0_OFF 0x0b - -__xdata __at (0xdf0c) uint8_t RF_MDMCFG4; -#define RF_MDMCFG4_OFF 0x0c - -#define RF_MDMCFG4_CHANBW_E_SHIFT 6 -#define RF_MDMCFG4_CHANBW_M_SHIFT 4 -#define RF_MDMCFG4_DRATE_E_SHIFT 0 - -__xdata __at (0xdf0d) uint8_t RF_MDMCFG3; -#define RF_MDMCFG3_OFF 0x0d - -#define RF_MDMCFG3_DRATE_M_SHIFT 0 - -__xdata __at (0xdf0e) uint8_t RF_MDMCFG2; -#define RF_MDMCFG2_OFF 0x0e - -#define RF_MDMCFG2_DEM_DCFILT_OFF (1 << 7) -#define RF_MDMCFG2_DEM_DCFILT_ON (0 << 7) - -#define RF_MDMCFG2_MOD_FORMAT_MASK (7 << 4) -#define RF_MDMCFG2_MOD_FORMAT_2_FSK (0 << 4) -#define RF_MDMCFG2_MOD_FORMAT_GFSK (1 << 4) -#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK (3 << 4) -#define RF_MDMCFG2_MOD_FORMAT_MSK (7 << 4) - -#define RF_MDMCFG2_MANCHESTER_EN (1 << 3) - -#define RF_MDMCFG2_SYNC_MODE_MASK (0x7 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE (0x0 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16 (0x1 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16 (0x2 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32 (0x3 << 0) -#define RF_MDMCFG2_SYNC_MODE_NONE_THRES (0x4 << 0) -#define RF_MDMCFG2_SYNC_MODE_15_16_THRES (0x5 << 0) -#define RF_MDMCFG2_SYNC_MODE_16_16_THRES (0x6 << 0) -#define RF_MDMCFG2_SYNC_MODE_30_32_THRES (0x7 << 0) - -__xdata __at (0xdf0f) uint8_t RF_MDMCFG1; -#define RF_MDMCFG1_OFF 0x0f - -#define RF_MDMCFG1_FEC_EN (1 << 7) -#define RF_MDMCFG1_FEC_DIS (0 << 7) - -#define RF_MDMCFG1_NUM_PREAMBLE_MASK (7 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_2 (0 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_3 (1 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_4 (2 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_6 (3 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_8 (4 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_12 (5 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_16 (6 << 4) -#define RF_MDMCFG1_NUM_PREAMBLE_24 (7 << 4) - -#define RF_MDMCFG1_CHANSPC_E_MASK (3 << 0) -#define RF_MDMCFG1_CHANSPC_E_SHIFT (0) - -__xdata __at (0xdf10) uint8_t RF_MDMCFG0; -#define RF_MDMCFG0_OFF 0x10 - -#define RF_MDMCFG0_CHANSPC_M_SHIFT (0) - -__xdata __at (0xdf11) uint8_t RF_DEVIATN; -#define RF_DEVIATN_OFF 0x11 - -#define RF_DEVIATN_DEVIATION_E_SHIFT 4 -#define RF_DEVIATN_DEVIATION_M_SHIFT 0 - -__xdata __at (0xdf12) uint8_t RF_MCSM2; -#define RF_MCSM2_OFF 0x12 -#define RF_MCSM2_RX_TIME_RSSI (1 << 4) -#define RF_MCSM2_RX_TIME_QUAL (1 << 3) -#define RF_MCSM2_RX_TIME_MASK (0x7) -#define RF_MCSM2_RX_TIME_SHIFT 0 -#define RF_MCSM2_RX_TIME_END_OF_PACKET (7) - -__xdata __at (0xdf13) uint8_t RF_MCSM1; -#define RF_MCSM1_OFF 0x13 -#define RF_MCSM1_CCA_MODE_ALWAYS (0 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW (1 << 4) -#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING (2 << 4) -#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING (3 << 4) -#define RF_MCSM1_RXOFF_MODE_IDLE (0 << 2) -#define RF_MCSM1_RXOFF_MODE_FSTXON (1 << 2) -#define RF_MCSM1_RXOFF_MODE_TX (2 << 2) -#define RF_MCSM1_RXOFF_MODE_RX (3 << 2) -#define RF_MCSM1_TXOFF_MODE_IDLE (0 << 0) -#define RF_MCSM1_TXOFF_MODE_FSTXON (1 << 0) -#define RF_MCSM1_TXOFF_MODE_TX (2 << 0) -#define RF_MCSM1_TXOFF_MODE_RX (3 << 0) - -__xdata __at (0xdf14) uint8_t RF_MCSM0; -#define RF_MCSM0_OFF 0x14 -#define RF_MCSM0_FS_AUTOCAL_NEVER (0 << 4) -#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE (1 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE (2 << 4) -#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4 (3 << 4) -#define RF_MCSM0_MAGIC_3 (1 << 3) -#define RF_MCSM0_MAGIC_2 (1 << 2) -#define RF_MCSM0_CLOSE_IN_RX_0DB (0 << 0) -#define RF_MCSM0_CLOSE_IN_RX_6DB (1 << 0) -#define RF_MCSM0_CLOSE_IN_RX_12DB (2 << 0) -#define RF_MCSM0_CLOSE_IN_RX_18DB (3 << 0) - -__xdata __at (0xdf15) uint8_t RF_FOCCFG; -#define RF_FOCCFG_OFF 0x15 -#define RF_FOCCFG_FOC_BS_CS_GATE (1 << 5) -#define RF_FOCCFG_FOC_PRE_K_1K (0 << 3) -#define RF_FOCCFG_FOC_PRE_K_2K (1 << 3) -#define RF_FOCCFG_FOC_PRE_K_3K (2 << 3) -#define RF_FOCCFG_FOC_PRE_K_4K (3 << 3) -#define RF_FOCCFG_FOC_POST_K_PRE_K (0 << 2) -#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2 (1 << 2) -#define RF_FOCCFG_FOC_LIMIT_0 (0 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8 (1 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4 (2 << 0) -#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2 (3 << 0) - -__xdata __at (0xdf16) uint8_t RF_BSCFG; -#define RF_BSCFG_OFF 0x16 -#define RF_BSCFG_BS_PRE_K_1K (0 << 6) -#define RF_BSCFG_BS_PRE_K_2K (1 << 6) -#define RF_BSCFG_BS_PRE_K_3K (2 << 6) -#define RF_BSCFG_BS_PRE_K_4K (3 << 6) -#define RF_BSCFG_BS_PRE_KP_1KP (0 << 4) -#define RF_BSCFG_BS_PRE_KP_2KP (1 << 4) -#define RF_BSCFG_BS_PRE_KP_3KP (2 << 4) -#define RF_BSCFG_BS_PRE_KP_4KP (3 << 4) -#define RF_BSCFG_BS_POST_KI_PRE_KI (0 << 3) -#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2 (1 << 3) -#define RF_BSCFG_BS_POST_KP_PRE_KP (0 << 2) -#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2 (1 << 2) -#define RF_BSCFG_BS_LIMIT_0 (0 << 0) -#define RF_BSCFG_BS_LIMIT_3_125 (1 << 0) -#define RF_BSCFG_BS_LIMIT_6_25 (2 << 0) -#define RF_BSCFG_BS_LIMIT_12_5 (3 << 0) - -__xdata __at (0xdf17) uint8_t RF_AGCCTRL2; -#define RF_AGCCTRL2_OFF 0x17 - -__xdata __at (0xdf18) uint8_t RF_AGCCTRL1; -#define RF_AGCCTRL1_OFF 0x18 - -__xdata __at (0xdf19) uint8_t RF_AGCCTRL0; -#define RF_AGCCTRL0_OFF 0x19 - -__xdata __at (0xdf1a) uint8_t RF_FREND1; -#define RF_FREND1_OFF 0x1a - -#define RF_FREND1_LNA_CURRENT_SHIFT 6 -#define RF_FREND1_LNA2MIX_CURRENT_SHIFT 4 -#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT 2 -#define RF_FREND1_MIX_CURRENT_SHIFT 0 - -__xdata __at (0xdf1b) uint8_t RF_FREND0; -#define RF_FREND0_OFF 0x1b - -#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK (0x3 << 4) -#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT 4 -#define RF_FREND0_PA_POWER_MASK (0x7) -#define RF_FREND0_PA_POWER_SHIFT 0 - -__xdata __at (0xdf1c) uint8_t RF_FSCAL3; -#define RF_FSCAL3_OFF 0x1c - -__xdata __at (0xdf1d) uint8_t RF_FSCAL2; -#define RF_FSCAL2_OFF 0x1d - -__xdata __at (0xdf1e) uint8_t RF_FSCAL1; -#define RF_FSCAL1_OFF 0x1e - -__xdata __at (0xdf1f) uint8_t RF_FSCAL0; -#define RF_FSCAL0_OFF 0x1f - -__xdata __at (0xdf23) uint8_t RF_TEST2; -#define RF_TEST2_OFF 0x23 - -#define RF_TEST2_NORMAL_MAGIC 0x88 -#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC 0x81 - -__xdata __at (0xdf24) uint8_t RF_TEST1; -#define RF_TEST1_OFF 0x24 - -#define RF_TEST1_TX_MAGIC 0x31 -#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC 0x35 - -__xdata __at (0xdf25) uint8_t RF_TEST0; -#define RF_TEST0_OFF 0x25 - -#define RF_TEST0_7_2_MASK (0xfc) -#define RF_TEST0_VCO_SEL_CAL_EN (1 << 1) -#define RF_TEST0_0_MASK (1) - -/* These are undocumented, and must be computed - * using the provided tool. - */ -__xdata __at (0xdf27) uint8_t RF_PA_TABLE7; -#define RF_PA_TABLE7_OFF 0x27 - -__xdata __at (0xdf28) uint8_t RF_PA_TABLE6; -#define RF_PA_TABLE6_OFF 0x28 - -__xdata __at (0xdf29) uint8_t RF_PA_TABLE5; -#define RF_PA_TABLE5_OFF 0x29 - -__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4; -#define RF_PA_TABLE4_OFF 0x2a - -__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3; -#define RF_PA_TABLE3_OFF 0x2b - -__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2; -#define RF_PA_TABLE2_OFF 0x2c - -__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1; -#define RF_PA_TABLE1_OFF 0x2d - -__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0; -#define RF_PA_TABLE0_OFF 0x2e - -__xdata __at (0xdf36) uint8_t RF_PARTNUM; -#define RF_PARTNUM_OFF 0x36 - -__xdata __at (0xdf37) uint8_t RF_VERSION; -#define RF_VERSION_OFF 0x37 - -__xdata __at (0xdf38) uint8_t RF_FREQEST; -#define RF_FREQEST_OFF 0x38 - -__xdata __at (0xdf39) uint8_t RF_LQI; -#define RF_LQI_OFF 0x39 - -#define RF_LQI_CRC_OK (1 << 7) -#define RF_LQI_LQI_EST_MASK (0x7f) - -__xdata __at (0xdf3a) uint8_t RF_RSSI; -#define RF_RSSI_OFF 0x3a - -__xdata __at (0xdf3b) uint8_t RF_MARCSTATE; -#define RF_MARCSTATE_OFF 0x3b - -#define RF_MARCSTATE_MASK 0x1f -#define RF_MARCSTATE_SLEEP 0x00 -#define RF_MARCSTATE_IDLE 0x01 -#define RF_MARCSTATE_VCOON_MC 0x03 -#define RF_MARCSTATE_REGON_MC 0x04 -#define RF_MARCSTATE_MANCAL 0x05 -#define RF_MARCSTATE_VCOON 0x06 -#define RF_MARCSTATE_REGON 0x07 -#define RF_MARCSTATE_STARTCAL 0x08 -#define RF_MARCSTATE_BWBOOST 0x09 -#define RF_MARCSTATE_FS_LOCK 0x0a -#define RF_MARCSTATE_IFADCON 0x0b -#define RF_MARCSTATE_ENDCAL 0x0c -#define RF_MARCSTATE_RX 0x0d -#define RF_MARCSTATE_RX_END 0x0e -#define RF_MARCSTATE_RX_RST 0x0f -#define RF_MARCSTATE_TXRX_SWITCH 0x10 -#define RF_MARCSTATE_RX_OVERFLOW 0x11 -#define RF_MARCSTATE_FSTXON 0x12 -#define RF_MARCSTATE_TX 0x13 -#define RF_MARCSTATE_TX_END 0x14 -#define RF_MARCSTATE_RXTX_SWITCH 0x15 -#define RF_MARCSTATE_TX_UNDERFLOW 0x16 - - -__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; -#define RF_PKTSTATUS_OFF 0x3c - -#define RF_PKTSTATUS_CRC_OK (1 << 7) -#define RF_PKTSTATUS_CS (1 << 6) -#define RF_PKTSTATUS_PQT_REACHED (1 << 5) -#define RF_PKTSTATUS_CCA (1 << 4) -#define RF_PKTSTATUS_SFD (1 << 3) - -__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; -#define RF_VCO_VC_DAC_OFF 0x3d - -#endif diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 new file mode 100644 index 00000000..8de4a9b2 --- /dev/null +++ b/src/cc1111/Makefile.cc1111 @@ -0,0 +1,27 @@ +CC=sdcc + +CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) + +CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product + +CODESIZE ?= 0x8000 + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ + --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff + +REL=$(SRC:.c=.rel) ao_product.rel +ADB=$(REL:.rel=.adb) +ASM=$(REL:.rel=.asm) +LNK=$(REL:.rel=.lnk) +LST=$(REL:.rel=.lst) +RST=$(REL:.rel=.rst) +SYM=$(REL:.rel=.sym) + +PCDB=$(PROG:.ihx=.cdb) +PLNK=$(PROG:.ihx=.lnk) +PMAP=$(PROG:.ihx=.map) +PMEM=$(PROG:.ihx=.mem) +PAOM=$(PROG:.ihx=) + +%.rel : %.c $(INC) + $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< diff --git a/src/cc1111/_bp.c b/src/cc1111/_bp.c new file mode 100644 index 00000000..6bf135bc --- /dev/null +++ b/src/cc1111/_bp.c @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + + _bp.c :- just declares bp as a variable + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +__data unsigned char bp ; diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c new file mode 100644 index 00000000..786dfd11 --- /dev/null +++ b/src/cc1111/ao_adc.c @@ -0,0 +1,196 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +#if HAS_ACCEL_REF +volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif +volatile __data uint8_t ao_adc_head; + +void +ao_adc_poll(void) +{ +#if HAS_ACCEL_REF + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; +#else +# ifdef TELENANO_V_0_1 + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; +# else + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +# endif +#endif +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_sample_adc); + memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +void +ao_adc_isr(void) __interrupt 1 +{ + uint8_t sequence; + uint8_t __xdata *a; + + sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; +#if IGNITE_ON_P2 + /* TeleMetrum readings */ +#if HAS_ACCEL_REF + if (sequence == 2) { + a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + sequence = 0; + } else +#endif + { + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + sequence++; + } +#define GOT_ADC + a[0] = ADCL; + a[1] = ADCH; + if (sequence < 6) { +#if HAS_EXTERNAL_TEMP == 0 + /* start next channel conversion */ + /* v0.2 replaces external temp sensor with internal one */ + if (sequence == 2) + ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + else +#endif + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; + } +#endif + +#if IGNITE_ON_P0 + /* TeleMini readings */ + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); +#ifdef TELEMINI_V_1_0 + switch (sequence) { + case 0: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; + break; + case 1: + /* drogue sense */ + a += 6; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; + break; + case 2: + /* main sense */ + a += 8; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif +#ifdef TELENANO_V_0_1 + switch (sequence) { + case 1: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif + a[0] = ADCL; + a[1] = ADCH; + if (sequence) { + /* Start next conversion */ + ADCCON3 = sequence; + } +#endif +#ifndef GOT_ADC +#error No known ADC configuration set +#endif + + else { + /* record this conversion series */ + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); + } +} + +static void +ao_adc_dump(void) __reentrant +{ + static __xdata struct ao_adc packet; + ao_adc_get(&packet); + printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", + packet.tick, packet.accel, packet.pres, packet.temp, + packet.v_batt, packet.sense_d, packet.sense_m); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Current ADC" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ +#if IGNITE_ON_P2 + /* TeleMetrum configuration */ + ADCCFG = ((1 << 0) | /* acceleration */ + (1 << 1) | /* pressure */ +#if HAS_EXTERNAL_TEMP + (1 << 2) | /* v0.1 temperature */ +#endif + (1 << 3) | /* battery voltage */ + (1 << 4) | /* drogue sense */ + (1 << 5)); /* main sense */ +#endif + +#if IGNITE_ON_P0 + /* TeleMini configuration */ + ADCCFG = ((1 << 0) | /* pressure */ + (1 << 1) | /* drogue sense */ + (1 << 2) | /* main sense */ + (1 << 3)); /* battery voltage */ +#endif + + /* enable interrupts */ + ADCIF = 0; + IEN0 |= IEN0_ADCIE; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/cc1111/ao_beep.c b/src/cc1111/ao_beep.c new file mode 100644 index 00000000..3642f4c6 --- /dev/null +++ b/src/cc1111/ao_beep.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + T4CTL = 0; + } else { + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; + T4CC0 = beep; + T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on P2_0, which is hooked to timer 4 using + * configuration alternative 2 + */ + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; + T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; +} diff --git a/src/cc1111/ao_dbg.c b/src/cc1111/ao_dbg.c new file mode 100644 index 00000000..d4c9567f --- /dev/null +++ b/src/cc1111/ao_dbg.c @@ -0,0 +1,364 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +static void +ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant +{ + DBG_PORT = (DBG_PORT & ~msk) | (val & msk); + _asm + nop + nop + _endasm; +} + +void +ao_dbg_send_byte(uint8_t byte) +{ + __pdata uint8_t b, d; + + DBG_PORT |= DBG_DATA; + DBG_PORT_DIR |= DBG_DATA; + for (b = 0; b < 8; b++) { + d = 0; + if (byte & 0x80) + d = DBG_DATA; + byte <<= 1; + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); + } + DBG_PORT_DIR &= ~DBG_DATA; +} + +uint8_t +ao_dbg_recv_byte(void) +{ + __pdata uint8_t byte, b; + + byte = 0; + for (b = 0; b < 8; b++) { + byte = byte << 1; + ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK); + if (DBG_DATA_PIN) + byte |= 1; + ao_dbg_send_bits(DBG_CLOCK, 0); + } + return byte; +} + +/* 8051 instructions + */ +#define NOP 0x00 +#define MOV_direct_data 0x75 +#define LJMP 0x02 +#define MOV_Rn_data(n) (0x78 | (n)) +#define DJNZ_Rn_rel(n) (0xd8 | (n)) +#define MOV_A_direct 0xe5 +#define MOV_direct1_direct2 0x85 +#define MOV_direct_A 0xf5 +#define MOV_DPTR_data16 0x90 +#define MOV_A_data 0x74 +#define MOVX_atDPTR_A 0xf0 +#define MOVX_A_atDPTR 0xe0 +#define INC_DPTR 0xa3 +#define TRAP 0xa5 +#define SJMP 0x80 +#define JB 0x20 + +#define DEBUG_INSTR(l) (0x54 | (l)) + +#define SFR_PSW 0xD0 +#define SFR_DPL0 0x82 +#define SFR_DPH0 0x83 +#define SFR_DPL1 0x84 +#define SFR_DPH1 0x85 + +__pdata uint8_t save_acc; +__pdata uint8_t save_psw; +__pdata uint8_t save_dpl0; +__pdata uint8_t save_dph0; +__pdata uint8_t save_dpl1; +__pdata uint8_t save_dph1; + +static uint8_t +ao_dbg_inst1(uint8_t a) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(1)); + ao_dbg_send_byte(a); + return ao_dbg_recv_byte(); +} + +static uint8_t +ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(2)); + ao_dbg_send_byte(a); + ao_dbg_send_byte(b); + return ao_dbg_recv_byte(); +} + +static uint8_t +ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(3)); + ao_dbg_send_byte(a); + ao_dbg_send_byte(b); + ao_dbg_send_byte(c); + return ao_dbg_recv_byte(); +} + +void +ao_dbg_start_transfer(uint16_t addr) +{ + save_acc = ao_dbg_inst1(NOP); + save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW); + save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0); + save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0); + save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1); + save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1); + ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr); +} + +void +ao_dbg_end_transfer(void) +{ + ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0); + ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0); + ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1); + ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1); + ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw); + ao_dbg_inst2(MOV_A_data, save_acc); +} + +void +ao_dbg_write_byte(uint8_t byte) +{ + ao_dbg_inst2(MOV_A_data, byte); + ao_dbg_inst1(MOVX_atDPTR_A); + ao_dbg_inst1(INC_DPTR); +} + +uint8_t +ao_dbg_read_byte(void) +{ + ao_dbg_inst1(MOVX_A_atDPTR); + return ao_dbg_inst1(INC_DPTR); +} + +static void +ao_dbg_set_pins(void) +{ + /* Make the DBG pins GPIOs. On TeleMetrum, this will + * disable the SPI link, so don't expect SPI to work after + * using the debugger. + */ + DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); + + /* make DBG_DATA tri-state */ + DBG_PORT_INP |= DBG_DATA; + + /* Raise RESET_N and CLOCK */ + DBG_PORT |= DBG_RESET_N | DBG_CLOCK; + + /* RESET_N and CLOCK are outputs now */ + DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR &= ~DBG_DATA; +} + +static void +ao_dbg_long_delay(void) +{ + uint8_t n; + + for (n = 0; n < 20; n++) + _asm nop _endasm; +} + +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) + +void +ao_dbg_debug_mode(void) +{ + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); +} + +void +ao_dbg_reset(void) +{ + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); +} + +static void +debug_enable(void) +{ + ao_dbg_debug_mode(); +} + +static void +debug_reset(void) +{ + ao_dbg_reset(); +} + +static void +debug_put(void) +{ + for (;;) { + ao_cmd_white (); + if (ao_cmd_lex_c == '\n') + break; + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + break; + ao_dbg_send_byte(ao_cmd_lex_i); + } +} + +static void +debug_get(void) +{ + __pdata uint16_t count; + __pdata uint16_t i; + __pdata uint8_t byte; + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + count = ao_cmd_lex_i; + if (count > 256) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < count; i++) { + if (i && (i & 7) == 0) + putchar('\n'); + byte = ao_dbg_recv_byte(); + ao_cmd_put8(byte); + putchar(' '); + } + putchar('\n'); +} + +static uint8_t +getnibble(void) +{ + __pdata char c; + + c = getchar(); + 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); + ao_cmd_status = ao_cmd_lex_error; + return 0; +} + +static void +debug_input(void) +{ + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; + __pdata uint8_t i; + + ao_cmd_hex(); + count = ao_cmd_lex_i; + ao_cmd_hex(); + addr = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + ao_dbg_start_transfer(addr); + i = 0; + while (count--) { + if (!(i++ & 7)) + putchar('\n'); + b = ao_dbg_read_byte(); + ao_cmd_put8(b); + } + ao_dbg_end_transfer(); + putchar('\n'); +} + +static void +debug_output(void) +{ + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; + + ao_cmd_hex(); + count = ao_cmd_lex_i; + ao_cmd_hex(); + addr = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + ao_dbg_start_transfer(addr); + while (count--) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_dbg_write_byte(b); + } + ao_dbg_end_transfer(); +} + +__code struct ao_cmds ao_dbg_cmds[7] = { + { debug_enable, "D\0Enable debug" }, + { debug_get, "G \0Get data" }, + { debug_input, "I \0Input at " }, + { debug_output, "O \0Output at " }, + { debug_put, "P ...\0Put data" }, + { debug_reset, "R\0Reset" }, + { 0, NULL }, +}; + +void +ao_dbg_init(void) +{ + ao_cmd_register(&ao_dbg_cmds[0]); +} diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c new file mode 100644 index 00000000..6052964a --- /dev/null +++ b/src/cc1111/ao_dma.c @@ -0,0 +1,131 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +#define NUM_DMA 5 + +/* + * The config address for DMA0 is programmed + * separately from that of DMA1-4, but for simplicity, + * we make them all contiguous. + */ + +static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; +static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; +static __data uint8_t ao_next_dma; + +uint8_t +ao_dma_alloc(__xdata uint8_t *done) +{ + uint8_t id; + + if (ao_next_dma == NUM_DMA) + ao_panic(AO_PANIC_DMA); + id = ao_next_dma++; + ao_dma_done[id] = done; + + /* When the first dma object is allocated, set up the DMA + * controller + */ + if (id == 0) { + DMAIRQ = 0; + DMAIF = 0; + IEN1 |= IEN1_DMAIE; + } + + return id; +} + +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) +{ + if (DMAARM & (1 << id)) + ao_panic(AO_PANIC_DMA); + ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; + ao_dma_config[id].src_low = ((uint16_t) srcaddr); + ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; + ao_dma_config[id].dst_low = ((uint16_t) dstaddr); + ao_dma_config[id].len_high = count >> 8; + ao_dma_config[id].len_low = count; + ao_dma_config[id].cfg0 = cfg0; + ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; + if (id == 0) { + DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; + DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); + } else { + DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; + DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); + } +} + +#define nop() _asm nop _endasm; + +void +ao_dma_start(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAIRQ &= ~mask; + DMAARM = 0x80 | mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + *(ao_dma_done[id]) = 0; + DMAARM = mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + nop(); +} + +void +ao_dma_trigger(uint8_t id) +{ + DMAREQ |= (1 << id); +} + +void +ao_dma_abort(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAARM = 0x80 | mask; + DMAIRQ &= ~mask; +} + +void +ao_dma_isr(void) __interrupt 8 +{ + uint8_t id, mask; + + /* Find the first DMA channel which is done */ + mask = 1; + for (id = 0; id < ao_next_dma; id++) { + if (DMAIRQ & mask) { + /* Clear CPU interrupt flag */ + DMAIF = 0; + /* Clear the completed ID */ + DMAIRQ = ~mask; + *(ao_dma_done[id]) = 1; + ao_wakeup(ao_dma_done[id]); + break; + } + mask <<= 1; + } +} diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c new file mode 100644 index 00000000..5238beb4 --- /dev/null +++ b/src/cc1111/ao_ignite.c @@ -0,0 +1,218 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +struct ao_ignition { + uint8_t request; + uint8_t fired; + uint8_t firing; +}; + +__xdata struct ao_ignition ao_ignition[2]; + +void +ao_ignite(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].request = 1; + ao_wakeup(&ao_ignition); +} + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + __xdata struct ao_adc adc; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; + + __critical { + ao_adc_get(&adc); + request = ao_ignition[igniter].request; + fired = ao_ignition[igniter].fired; + firing = ao_ignition[igniter].firing; + } + if (firing || (request && !fired)) + return ao_igniter_active; + + value = (AO_IGNITER_CLOSED>>1); + switch (igniter) { + case ao_igniter_drogue: + value = adc.sense_d; + break; + case ao_igniter_main: + value = adc.sense_m; + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +void +ao_igniter_fire(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].firing = 1; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + break; + case ao_igniter_main: + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + } + ao_ignition[igniter].firing = 0; +} + +void +ao_igniter(void) +{ + __xdata enum ao_ignter igniter; + + ao_config_get(); + for (;;) { + ao_sleep(&ao_ignition); + for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { + if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + + ao_igniter_fire(igniter); + ao_delay(AO_IGNITER_CHARGE_TIME); + ao_ignition[igniter].fired = 1; + } + } + } +} + +void +ao_ignite_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + if (ao_cmd_lex_c == 'm') { + if(ao_match_word("main")) + ao_igniter_fire(ao_igniter_main); + } else { + if(ao_match_word("drogue")) + ao_igniter_fire(ao_igniter_drogue); + } +} + +static __code char * __code igniter_status_names[] = { + "unknown", "ready", "active", "open" +}; + +void +ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant +{ + enum ao_igniter_status status = ao_igniter_status(igniter); + printf("Igniter: %6s Status: %s\n", + name, + igniter_status_names[status]); +} + +void +ao_ignite_test(void) +{ + ao_ignite_print_status(ao_igniter_drogue, "drogue"); + ao_ignite_print_status(ao_igniter_main, "main"); +} + +__code struct ao_cmds ao_ignite_cmds[] = { + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter" }, + { 0, NULL }, +}; + +__xdata struct ao_task ao_igniter_task; + +void +ao_ignite_set_pins(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); + ao_cmd_register(&ao_ignite_cmds[0]); + ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +} diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c new file mode 100644 index 00000000..d76d954e --- /dev/null +++ b/src/cc1111/ao_intflash.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "cc1111.h" + +#define ENDOFCODE (CODESIZE) +#define AO_INTFLASH_BLOCK 1024 +#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) +#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) +#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) + +/* + * 21000 * 24e6 + * FWT = ------------ + * 16e9 + * + * = 31.5 + * + * Round up and use 32 + */ + +#define FLASH_TIMING 0x20 + +#if AO_INTFLASH_BLOCKS < 2 +#error "Too few pages" +#endif + +#if AO_INFTLASH_LOCATION % 1024 != 0 +#error "Pages aren't aligned properly" +#endif + +__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total = sizeof(ao_intflash); + +/* Block size - device is erased in these units. */ +__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; + +__xdata static uint8_t ao_intflash_dma_done; +static uint8_t ao_intflash_dma; + +/* + * The internal flash chip is arranged in 1kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint16_t addr; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + FADDRH = addr >> 8; + FADDRL = addr; + + __critical { + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop ; Required, see datasheet. + _endasm; + } + + return 1; +} + +/* + * Write to flash + */ + +static void +ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant +{ + pos = ((uint16_t) ao_intflash + pos) >> 1; + + ao_dma_set_transfer(ao_intflash_dma, + d, + &FWDATAXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + + FADDRH = pos >> 8; + FADDRL = pos; + + ao_dma_start(ao_intflash_dma); + + __critical { + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + nop + _endasm; + } +} + +static void +ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant +{ + static __xdata uint8_t b[2]; + + if (pos & 1) { + b[0] = 0xff; + b[1] = byte; + } else { + b[0] = byte; + b[1] = 0xff; + } + ao_intflash_write_aligned(pos, b, 2); +} + +uint8_t +ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + uint8_t oddlen; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + if (len == 0) + return 1; + + if (pos & 1) { + ao_intflash_write_byte(pos++, *d++); + len--; + } + oddlen = len & 1; + len -= oddlen; + if (len) + ao_intflash_write_aligned(pos, d, len); + if (oddlen) + ao_intflash_write_byte(pos + len, d[len]); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + memcpy(d, ao_intflash+pos, len); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); +} + +void +ao_storage_device_init(void) +{ + ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); + + FWT = FLASH_TIMING; +} diff --git a/src/cc1111/ao_led.c b/src/cc1111/ao_led.c new file mode 100644 index 00000000..5beed58d --- /dev/null +++ b/src/cc1111/ao_led.c @@ -0,0 +1,61 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint8_t ao_led_enable; + +void +ao_led_on(uint8_t colors) +{ + P1 |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + P1 &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + P1 ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_led_enable = enable; + P1SEL &= ~enable; + P1 &= ~enable; + P1DIR |= enable; +} diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c new file mode 100644 index 00000000..f627e02b --- /dev/null +++ b/src/cc1111/ao_packet.c @@ -0,0 +1,148 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_seq; + +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_send(void) +{ + ao_led_on(AO_LED_RED); + /* If any tx data is pending then copy it into the tx packet */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; + ao_wakeup(&tx_data); + } + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); + ao_led_off(AO_LED_RED); +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + +#ifdef AO_LED_GREEN + ao_led_on(AO_LED_GREEN); +#endif + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); +#ifdef AO_LED_GREEN + ao_led_off(AO_LED_GREEN); +#endif + + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); + } + } + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; +} + +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER +void +ao_packet_flush(void) +{ + /* If there is data to send, and this is the master, + * then poke the master to send all queued data + */ + if (ao_packet_tx_used && ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); +} +#endif /* PACKET_HAS_MASTER */ + +void +ao_packet_putchar(char c) __reentrant +{ + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER + ao_packet_flush(); +#endif + ao_sleep(&tx_data); + } + + if (ao_packet_enable) + tx_data[ao_packet_tx_used++] = c; +} + +char +ao_packet_pollchar(void) __critical +{ + if (!ao_packet_enable) + return AO_READ_AGAIN; + + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; + + return rx_data[ao_packet_rx_used++]; +} diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c new file mode 100644 index 00000000..b0fdf5a8 --- /dev/null +++ b/src/cc1111/ao_packet_master.c @@ -0,0 +1,144 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static char +ao_packet_getchar(void) __critical +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); + flush(); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + char c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (c != AO_READ_AGAIN) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + ao_config_get(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + if (ao_packet_recv()) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + ao_packet_master_sleeping = 1; + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); +#if HAS_MONITOR + ao_set_monitor(0); +#endif + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + 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; + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); + ao_delay(AO_MS_TO_TICKS(10)); + } +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c new file mode 100644 index 00000000..9f14052a --- /dev/null +++ b/src/cc1111/ao_packet_slave.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_packet_slave(void) +{ + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + if (ao_packet_recv()) { + memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif + ao_packet_send(); + } + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); +} + +void +ao_packet_slave_stop(void) +{ + if (ao_packet_enable) { + ao_packet_enable = 0; + while (ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); + } + } +} + +void +ao_packet_slave_init(uint8_t enable) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + NULL); + if (enable) + ao_packet_slave_start(); +} diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c new file mode 100644 index 00000000..00816b33 --- /dev/null +++ b/src/cc1111/ao_radio.c @@ -0,0 +1,475 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +/* Values from SmartRF® Studio for: + * + * Deviation: 20.507812 kHz + * Datarate: 38.360596 kBaud + * Modulation: GFSK + * RF Freq: 434.549927 MHz + * Channel: 99.975586 kHz + * Channel: 0 + * RX filter: 93.75 kHz + */ + +/* + * For IF freq of 140.62kHz, the IF value is: + * + * 140.62e3 / (24e6 / 2**10) = 6 + */ + +#define IF_FREQ_CONTROL 6 + +/* + * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are + * + * BW = 24e6 / (8 * (4 + M) * 2 ** E) + * + * So, M = 0 and E = 3 + */ + +#define CHANBW_M 0 +#define CHANBW_E 3 + +/* + * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are: + * + * R = (256 + M) * 2** E * 24e6 / 2**28 + * + * So M is 163 and E is 10 + */ + +#define DRATE_E 10 +#define DRATE_M 163 + +/* + * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are: + * + * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E + * + * So M is 6 and E is 3 + */ + +#define DEVIATION_M 6 +#define DEVIATION_E 3 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), + * so the DRATE_E and DRATE_M values are: + * + * M is 94 and E is 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ + +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 94 +#define RDF_PACKET_LEN 50 + +/* + * RDF deviation should match the normal NFM value of 5kHz + * + * M is 6 and E is 1 + * + */ + +#define RDF_DEVIATION_M 6 +#define RDF_DEVIATION_E 1 + +/* This are from the table for 433MHz */ + +#define RF_POWER_M30_DBM 0x12 +#define RF_POWER_M20_DBM 0x0e +#define RF_POWER_M15_DBM 0x1d +#define RF_POWER_M10_DBM 0x34 +#define RF_POWER_M5_DBM 0x2c +#define RF_POWER_0_DBM 0x60 +#define RF_POWER_5_DBM 0x84 +#define RF_POWER_7_DBM 0xc8 +#define RF_POWER_10_DBM 0xc0 + +#define RF_POWER RF_POWER_10_DBM + +static __code uint8_t radio_setup[] = { + RF_PA_TABLE7_OFF, RF_POWER, + RF_PA_TABLE6_OFF, RF_POWER, + RF_PA_TABLE5_OFF, RF_POWER, + RF_PA_TABLE4_OFF, RF_POWER, + RF_PA_TABLE3_OFF, RF_POWER, + RF_PA_TABLE2_OFF, RF_POWER, + RF_PA_TABLE1_OFF, RF_POWER, + RF_PA_TABLE0_OFF, RF_POWER, + + RF_FSCTRL1_OFF, (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT), + RF_FSCTRL0_OFF, (0 << RF_FSCTRL0_FREQOFF_SHIFT), + + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + RF_MDMCFG0_OFF, (17 << RF_MDMCFG0_CHANSPC_M_SHIFT), + + RF_CHANNR_OFF, 0, + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* SmartRF says set LODIV_BUF_CURRENT_TX to 0 + * And, we're not using power ramping, so use PA_POWER 0 + */ + RF_FREND0_OFF, ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) | + (0 << RF_FREND0_PA_POWER_SHIFT)), + + RF_FREND1_OFF, ((1 << RF_FREND1_LNA_CURRENT_SHIFT) | + (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) | + (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) | + (2 << RF_FREND1_MIX_CURRENT_SHIFT)), + + RF_FSCAL3_OFF, 0xE9, + RF_FSCAL2_OFF, 0x0A, + RF_FSCAL1_OFF, 0x00, + RF_FSCAL0_OFF, 0x1F, + + RF_TEST2_OFF, 0x88, + RF_TEST1_OFF, 0x31, + RF_TEST0_OFF, 0x09, + + /* default sync values */ + RF_SYNC1_OFF, 0xD3, + RF_SYNC0_OFF, 0x91, + + /* max packet length */ + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), + RF_ADDR_OFF, 0x00, + RF_MCSM2_OFF, (RF_MCSM2_RX_TIME_END_OF_PACKET), + RF_MCSM1_OFF, (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING| + RF_MCSM1_RXOFF_MODE_IDLE| + RF_MCSM1_TXOFF_MODE_IDLE), + RF_MCSM0_OFF, (RF_MCSM0_FS_AUTOCAL_FROM_IDLE| + RF_MCSM0_MAGIC_3| + RF_MCSM0_CLOSE_IN_RX_0DB), + RF_FOCCFG_OFF, (RF_FOCCFG_FOC_PRE_K_3K, + RF_FOCCFG_FOC_POST_K_PRE_K, + RF_FOCCFG_FOC_LIMIT_BW_OVER_4), + RF_BSCFG_OFF, (RF_BSCFG_BS_PRE_K_2K| + RF_BSCFG_BS_PRE_KP_3KP| + RF_BSCFG_BS_POST_KI_PRE_KI| + RF_BSCFG_BS_POST_KP_PRE_KP| + RF_BSCFG_BS_LIMIT_0), + RF_AGCCTRL2_OFF, 0x43, + RF_AGCCTRL1_OFF, 0x40, + RF_AGCCTRL0_OFF, 0x91, + + RF_IOCFG2_OFF, 0x00, + RF_IOCFG1_OFF, 0x00, + RF_IOCFG0_OFF, 0x00, +}; + +static __code uint8_t rdf_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | + RF_MDMCFG1_NUM_PREAMBLE_2 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* packet length is set in-line */ + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; + +static __code uint8_t fixed_pkt_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), + RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | + RF_MDMCFG2_MOD_FORMAT_GFSK | + RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_EN | + RF_MDMCFG1_NUM_PREAMBLE_4 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* max packet length -- now set inline */ + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_APPEND_STATUS| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_WHITE_DATA| + RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_CRC_EN| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; + +__xdata uint8_t ao_radio_dma; +__xdata uint8_t ao_radio_dma_done; +__xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_abort; +__xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) __interrupt 16 +{ + S1CON &= ~0x03; + if (RFIF & RFIF_IM_TIMEOUT) { + ao_radio_recv_abort(); + RFIF &= ~ RFIF_IM_TIMEOUT; + } else if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } +} + +void +ao_radio_set_packet(void) +{ + uint8_t i; + for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) + RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; +} + +void +ao_radio_idle(void) +{ + if (RF_MARCSTATE != RF_MARCSTATE_IDLE) + { + do { + RFST = RFST_SIDLE; + ao_yield(); + } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); + } +} + +void +ao_radio_get(uint8_t len) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_setting); + RF_PKTLEN = len; +} + + +void +ao_radio_send(__xdata void *packet, uint8_t size) __reentrant +{ + ao_radio_get(size); + ao_radio_done = 0; + ao_dma_set_transfer(ao_radio_dma, + packet, + &RFDXADDR, + size, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant +{ + ao_radio_abort = 0; + ao_radio_get(size - 2); + ao_dma_set_transfer(ao_radio_dma, + &RFDXADDR, + packet, + size, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_SRX; + + /* Wait for DMA to be done, for the radio receive process to + * get aborted or for a receive timeout to fire + */ + __critical while (!ao_radio_dma_done && !ao_radio_abort) + if (ao_sleep(&ao_radio_dma_done)) + break; + + /* If recv was aborted, clean up by stopping the DMA engine + * and idling the radio + */ + if (!ao_radio_dma_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } + ao_radio_put(); + return ao_radio_dma_done; +} + +/* + * Wake up a task waiting to receive a radio packet + * and tell them to abort the transfer + */ + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_dma_done); +} + +__xdata ao_radio_rdf_value = 0x55; + +void +ao_radio_rdf(int ms) +{ + uint8_t i; + uint8_t pkt_len; + + /* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + if (ms > (255 * 4)) + ms = 255 * 4; + pkt_len = ms >> 2; + + ao_radio_abort = 0; + ao_radio_get(pkt_len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; + + ao_dma_set_transfer(ao_radio_dma, + &ao_radio_rdf_value, + &RFDXADDR, + pkt_len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + __critical while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + if (!ao_radio_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } + ao_radio_set_packet(); + ao_radio_put(); +} + +void +ao_radio_rdf_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); +} + + +/* Output carrier */ +void +ao_radio_test(void) +{ + uint8_t mode = 2; + static __xdata radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_set_monitor(0); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + RFST = RFST_STX; + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; + } +} + +__code struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, +}; + +void +ao_radio_init(void) +{ + uint8_t i; + for (i = 0; i < sizeof (radio_setup); i += 2) + RF[radio_setup[i]] = radio_setup[i+1]; + ao_radio_set_packet(); + ao_radio_dma_done = 1; + ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + RFIF = 0; + RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; + IEN2 |= IEN2_RFIE; + ao_cmd_register(&ao_radio_cmds[0]); +} diff --git a/src/cc1111/ao_reboot.c b/src/cc1111/ao_reboot.c new file mode 100644 index 00000000..8c47b893 --- /dev/null +++ b/src/cc1111/ao_reboot.c @@ -0,0 +1,28 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +/* Use the watchdog timer to force a complete reboot + */ +void +ao_reboot(void) +{ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; + ao_delay(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} diff --git a/src/cc1111/ao_romconfig.c b/src/cc1111/ao_romconfig.c new file mode 100644 index 00000000..f3fe61b1 --- /dev/null +++ b/src/cc1111/ao_romconfig.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c new file mode 100644 index 00000000..82370c64 --- /dev/null +++ b/src/cc1111/ao_serial.c @@ -0,0 +1,175 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +volatile __xdata struct ao_fifo ao_usart1_rx_fifo; +volatile __xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_serial_rx1_isr(void) __interrupt 3 +{ + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); + } +} + +void +ao_serial_tx1_isr(void) __interrupt 14 +{ + UTX1IF = 0; + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_usart1_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart1_rx_fifo,c); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); +} + +void +ao_serial_drain(void) __critical +{ + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); +} + +static __code struct { + uint8_t baud; + uint8_t gcr; +} ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + /* .baud = */ 163, + /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_9600] = */ { + /* .baud = */ 163, + /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_19200] = */ { + /* .baud = */ 163, + /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_57600] = */ { + /* .baud = */ 59, + /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ + ao_serial_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U1UCR |= UxUCR_FLUSH; + U1BAUD = ao_serial_speeds[speed].baud; + U1GCR = ao_serial_speeds[speed].gcr; +} + +void +ao_serial_init(void) +{ +#if HAS_SERIAL_1_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_1_HW_FLOW + P0SEL |= (1 << 3) | (1 << 2); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | + (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 6) | (1 << 7); + P1SEL |= (1 << 5) | (1 << 4); +#endif + + /* UART mode with receiver enabled */ + U1CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 4800 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + + /* Reasonable serial parameters */ + U1UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_1_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX1IE; + IEN2 |= IEN2_UTX1IE; +} diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c new file mode 100644 index 00000000..fbe613c7 --- /dev/null +++ b/src/cc1111/ao_spi.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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" + +/* Shared mutex to protect SPI bus, must cover the entire + * operation, from CS low to CS high. This means that any SPI + * user must protect the SPI bus with this mutex + */ +__xdata uint8_t ao_spi_mutex; +__xdata uint8_t ao_spi_dma_in_done; +__xdata uint8_t ao_spi_dma_out_done; + +uint8_t ao_spi_dma_out_id; +uint8_t ao_spi_dma_in_id; + +static __xdata uint8_t ao_spi_const = 0xff; + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + &ao_spi_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + &ao_spi_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +void +ao_spi_init(void) +{ + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); + + /* Set up IN DMA */ + ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); +} diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c new file mode 100644 index 00000000..c977fbc8 --- /dev/null +++ b/src/cc1111/ao_timer.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) __critical +{ + return ao_tick_count; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void ao_timer_isr(void) __interrupt 9 +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ + /* NOTE: This uses a timer only present on cc1111 architecture. */ + + /* disable timer 1 */ + T1CTL = 0; + + /* set the sample rate */ + T1CC0H = T1_SAMPLE_TIME >> 8; + T1CC0L = (uint8_t) T1_SAMPLE_TIME; + + T1CCTL0 = T1CCTL_MODE_COMPARE; + T1CCTL1 = 0; + T1CCTL2 = 0; + + /* clear timer value */ + T1CNTL = 0; + + /* enable overflow interrupt */ + OVFIM = 1; + /* enable timer 1 interrupt */ + T1IE = 1; + + /* enable timer 1 in module mode, dividing by 8 */ + T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8; +} + +/* + * AltOS always cranks the clock to the max frequency + */ +void +ao_clock_init(void) +{ + /* Switch system clock to crystal oscilator */ + CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL); + + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + + /* Crank up the timer tick and system clock speed */ + CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) | + (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)); + + while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) != + (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)) + ; +} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c new file mode 100644 index 00000000..08cb7390 --- /dev/null +++ b/src/cc1111/ao_usb.c @@ -0,0 +1,460 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" + +struct ao_task __xdata ao_usb_task; + +static __xdata uint16_t ao_usb_in_bytes; +static __pdata uint16_t ao_usb_in_bytes_last; +static __xdata uint16_t ao_usb_out_bytes; +static __pdata uint8_t ao_usb_iif; +static __pdata uint8_t ao_usb_running; + +static void +ao_usb_set_interrupts(void) +{ + /* IN interrupts on the control an IN endpoints */ + USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP); + + /* OUT interrupts on the OUT endpoint */ + USBOIE = (1 << AO_USB_OUT_EP); + + /* Only care about reset */ + USBCIE = USBCIE_RSTIE; +} + +/* This interrupt is shared with port 2, + * so when we hook that up, fix this + */ +void +ao_usb_isr(void) __interrupt 6 +{ + USBIF = 0; + ao_usb_iif |= USBIIF; + if (ao_usb_iif & 1) + ao_wakeup(&ao_usb_task); + if (ao_usb_iif & (1 << AO_USB_IN_EP)) + ao_wakeup(&ao_usb_in_bytes); + + if (USBOIF & (1 << AO_USB_OUT_EP)) + ao_wakeup(&ao_stdin_ready); + + if (USBCIF & USBCIF_RSTIF) + ao_usb_set_interrupts(); +#if HAS_BTM +#if BT_LINK_ON_P2 + ao_btm_isr(); +#endif +#endif +} + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} __xdata ao_usb_setup; + +__pdata uint8_t ao_usb_ep0_state; +uint8_t * __pdata ao_usb_ep0_in_data; +__pdata uint8_t ao_usb_ep0_in_len; +__pdata uint8_t ao_usb_ep0_in_buf[2]; +__pdata uint8_t ao_usb_ep0_out_len; +__xdata uint8_t *__pdata ao_usb_ep0_out_data; +__pdata uint8_t ao_usb_configuration; + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + __pdata uint8_t this_len; + __pdata uint8_t cs0; + + /* If the IN packet hasn't been picked up, just return */ + USBINDEX = 0; + cs0 = USBCS0; + if (cs0 & USBCS0_INPKT_RDY) + return; + + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + cs0 = USBCS0_INPKT_RDY; + if (this_len != AO_USB_CONTROL_SIZE) { + cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + ao_usb_ep0_in_len -= this_len; + while (this_len--) + USBFIFO[0] = *ao_usb_ep0_in_data++; + USBINDEX = 0; + USBCS0 = cs0; +} + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + __code uint8_t *__pdata descriptor; + __pdata uint8_t type = value >> 8; + __pdata uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +/* Read data from the ep0 OUT fifo + */ +static void +ao_usb_ep0_fill(void) +{ + __pdata uint8_t len; + + USBINDEX = 0; + len = USBCNT0; + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + while (len--) + *ao_usb_ep0_out_data++ = USBFIFO[0]; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +void +ao_usb_set_address(uint8_t address) +{ + ao_usb_running = 1; + USBADDR = address | 0x80; + while (USBADDR & 0x80) + ; +} + +static void +ao_usb_set_configuration(void) +{ + /* Set the IN max packet size, double buffered */ + USBINDEX = AO_USB_IN_EP; + USBMAXI = AO_USB_IN_SIZE >> 3; + USBCSIH |= USBCSIH_IN_DBL_BUF; + + /* Set the OUT max packet size, double buffered */ + USBINDEX = AO_USB_OUT_EP; + USBMAXO = AO_USB_OUT_SIZE >> 3; + USBCSOH = USBCSOH_OUT_DBL_BUF; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) + return; + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + USBINDEX = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + ao_usb_set_address(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_DESCRIPTOR: + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + #pragma disable_warning 110 + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + ao_usb_ep0_flush(); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + __pdata uint8_t cs0; + + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + __critical for (;;) { + if (ao_usb_iif & 1) { + ao_usb_iif &= ~1; + break; + } + ao_sleep(&ao_usb_task); + } + USBINDEX = 0; + cs0 = USBCS0; + if (cs0 & USBCS0_SETUP_END) { + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBCS0 = USBCS0_CLR_SETUP_END; + } + if (cs0 & USBCS0_SENT_STALL) { + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBCS0 &= ~USBCS0_SENT_STALL; + } + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN && + (cs0 & USBCS0_INPKT_RDY) == 0) + { + ao_usb_ep0_flush(); + } + if (cs0 & USBCS0_OUTPKT_RDY) { + switch (ao_usb_ep0_state) { + case AO_USB_EP0_IDLE: + ao_usb_ep0_setup(); + break; + case AO_USB_EP0_DATA_OUT: + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBINDEX = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; + break; + } + } + } +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + USBINDEX = AO_USB_IN_EP; + if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) + break; + ao_sleep(&ao_usb_in_bytes); + } +} + +/* Send the current IN packet */ +static void +ao_usb_in_send(void) +{ + USBINDEX = AO_USB_IN_EP; + USBCSIL |= USBCSIL_INPKT_RDY; + ao_usb_in_bytes_last = ao_usb_in_bytes; + ao_usb_in_bytes = 0; +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* If there are pending bytes, or if the last packet was full, + * send another IN packet + */ + if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { + ao_usb_in_wait(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + /* Queue a byte, sending the packet when full */ + USBFIFO[AO_USB_IN_EP << 1] = c; + if (++ao_usb_in_bytes == AO_USB_IN_SIZE) + ao_usb_in_send(); +} + +char +ao_usb_pollchar(void) __critical +{ + char c; + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) + return AO_READ_AGAIN; + ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; + 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]; + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + USBCSOL &= ~USBCSOL_OUTPKT_RDY; + } + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + return c; +} + +void +ao_usb_enable(void) +{ + /* Turn on the USB controller */ + SLEEP |= SLEEP_USB_EN; + + ao_usb_set_configuration(); + + ao_usb_set_interrupts(); + + /* enable USB interrupts */ + IEN2 |= IEN2_USBIE; + + /* Clear any pending interrupts */ + USBCIF = 0; + USBOIF = 0; + USBIIF = 0; +} + +void +ao_usb_disable(void) +{ + /* Disable USB interrupts */ + USBIIE = 0; + USBOIE = 0; + USBCIE = 0; + IEN2 &= ~IEN2_USBIE; + + /* Clear any pending interrupts */ + USBCIF = 0; + USBOIF = 0; + USBIIF = 0; + + /* Turn off the USB controller */ + SLEEP &= ~SLEEP_USB_EN; +} + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +} diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/cc1111/ao_usb.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h new file mode 100644 index 00000000..e52aa79f --- /dev/null +++ b/src/cc1111/cc1111.h @@ -0,0 +1,1306 @@ +/*------------------------------------------------------------------------- + Register Declarations for the ChipCon CC1111 Processor Range + + Copyright © 2008 Keith Packard + + 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. + + Adapted from the Cygnal C8051F12x config file which is: + + Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------*/ + +#ifndef _CC1111_H_ +#define _CC1111_H_ +#include +#include + +__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 */ + +#define IEN0_EA (1 << 7) +#define IEN0_STIE (1 << 5) +#define IEN0_ENCIE (1 << 4) +#define IEN0_URX1IE (1 << 3) +#define IEN0_I2SRXIE (1 << 3) +#define IEN0_URX0IE (1 << 2) +#define IEN0_ADCIE (1 << 1) +#define IEN0_RFTXRXIE (1 << 0) + +__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_T3IE (1 << 3) /* Timer 3 interrupt enable */ +#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ +#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ +#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ + +/* IEN2 */ +__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_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ +#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ +#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ +#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ +#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ +#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ + +/* CLKCON 0xC6 */ +__sfr __at 0xC6 CLKCON; /* Clock Control */ + +#define CLKCON_OSC32K_RC (1 << 7) +#define CLKCON_OSC32K_XTAL (0 << 7) +#define CLKCON_OSC32K_MASK (1 << 7) +#define CLKCON_OSC_RC (1 << 6) +#define CLKCON_OSC_XTAL (0 << 6) +#define CLKCON_OSC_MASK (1 << 6) +#define CLKCON_TICKSPD_MASK (7 << 3) +# define CLKCON_TICKSPD_1 (0 << 3) +# define CLKCON_TICKSPD_1_2 (1 << 3) +# define CLKCON_TICKSPD_1_4 (2 << 3) +# define CLKCON_TICKSPD_1_8 (3 << 3) +# define CLKCON_TICKSPD_1_16 (4 << 3) +# define CLKCON_TICKSPD_1_32 (5 << 3) +# define CLKCON_TICKSPD_1_64 (6 << 3) +# define CLKCON_TICKSPD_1_128 (7 << 3) + +#define CLKCON_CLKSPD_MASK (7 << 0) +# define CLKCON_CLKSPD_1 (0 << 0) +# define CLKCON_CLKSPD_1_2 (1 << 0) +# define CLKCON_CLKSPD_1_4 (2 << 0) +# define CLKCON_CLKSPD_1_8 (3 << 0) +# define CLKCON_CLKSPD_1_16 (4 << 0) +# define CLKCON_CLKSPD_1_32 (5 << 0) +# define CLKCON_CLKSPD_1_64 (6 << 0) +# define CLKCON_CLKSPD_1_128 (7 << 0) + +/* SLEEP 0xBE */ +#define SLEEP_USB_EN (1 << 7) +#define SLEEP_XOSC_STB (1 << 6) +#define SLEEP_HFRC_STB (1 << 5) +#define SLEEP_RST_POWER (0 << 3) +#define SLEEP_RST_EXTERNAL (1 << 3) +#define SLEEP_RST_WATCHDOG (2 << 3) +#define SLEEP_RST_MASK (3 << 3) +#define SLEEP_OSC_PD (1 << 2) +#define SLEEP_MODE_PM0 (0 << 0) +#define SLEEP_MODE_PM1 (1 << 0) +#define SLEEP_MODE_PM2 (2 << 0) +#define SLEEP_MODE_PM3 (3 << 0) +#define SLEEP_MODE_MASK (3 << 0) + +/* PCON 0x87 */ +__sfr __at 0x87 PCON; /* Power Mode Control Register */ + +#define PCON_IDLE (1 << 0) + +/* + * TCON + */ +__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 */ + +#define TCON_URX1IF (1 << 7) +#define TCON_I2SRXIF (1 << 7) +#define TCON_ADCIF (1 << 5) +#define TCON_URX0IF (1 << 3) +#define TCON_RFTXRXIF (1 << 1) + +/* + * S0CON + */ +__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ + +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 */ + +#define S1CON_RFIF_1 (1 << 1) +#define S1CON_RFIF_0 (1 << 0) + +/* + * IRCON + */ +__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 */ + +#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ +#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ +#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ +#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ +#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ +#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ +#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ + +/* + * IRCON2 + */ +__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 */ + +#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ +#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ +#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ +#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ +#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ +#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ +#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ + +/* + * IP1 - Interrupt Priority 1 + */ + +/* + * Interrupt priority groups: + * + * IPG0 RFTXRX RF DMA + * IPG1 ADC T1 P2INT/USB + * IPG2 URX0 T2 UTX0 + * IPG3 URX1/I2SRX T3 UTX1 / I2STX + * IPG4 ENC T4 P1INT + * IPG5 ST P0INT WDT + * + * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first + */ + +__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ +__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ + +#define IP1_IPG5 (1 << 5) +#define IP1_IPG4 (1 << 4) +#define IP1_IPG3 (1 << 3) +#define IP1_IPG2 (1 << 2) +#define IP1_IPG1 (1 << 1) +#define IP1_IPG0 (1 << 0) + +#define IP0_IPG5 (1 << 5) +#define IP0_IPG4 (1 << 4) +#define IP0_IPG3 (1 << 3) +#define IP0_IPG2 (1 << 2) +#define IP0_IPG1 (1 << 1) +#define IP0_IPG0 (1 << 0) + +/* + * Timer 1 + */ +#define T1CTL_MODE_SUSPENDED (0 << 0) +#define T1CTL_MODE_FREE (1 << 0) +#define T1CTL_MODE_MODULO (2 << 0) +#define T1CTL_MODE_UP_DOWN (3 << 0) +#define T1CTL_MODE_MASK (3 << 0) +#define T1CTL_DIV_1 (0 << 2) +#define T1CTL_DIV_8 (1 << 2) +#define T1CTL_DIV_32 (2 << 2) +#define T1CTL_DIV_128 (3 << 2) +#define T1CTL_DIV_MASK (3 << 2) +#define T1CTL_OVFIF (1 << 4) +#define T1CTL_CH0IF (1 << 5) +#define T1CTL_CH1IF (1 << 6) +#define T1CTL_CH2IF (1 << 7) + +#define T1CCTL_NO_CAPTURE (0 << 0) +#define T1CCTL_CAPTURE_RISING (1 << 0) +#define T1CCTL_CAPTURE_FALLING (2 << 0) +#define T1CCTL_CAPTURE_BOTH (3 << 0) +#define T1CCTL_CAPTURE_MASK (3 << 0) + +#define T1CCTL_MODE_CAPTURE (0 << 2) +#define T1CCTL_MODE_COMPARE (1 << 2) + +#define T1CTL_CMP_SET (0 << 3) +#define T1CTL_CMP_CLEAR (1 << 3) +#define T1CTL_CMP_TOGGLE (2 << 3) +#define T1CTL_CMP_SET_CLEAR (3 << 3) +#define T1CTL_CMP_CLEAR_SET (4 << 3) + +#define T1CTL_IM_DISABLED (0 << 6) +#define T1CTL_IM_ENABLED (1 << 6) + +#define T1CTL_CPSEL_NORMAL (0 << 7) +#define T1CTL_CPSEL_RF (1 << 7) + +/* + * Timer 3 and Timer 4 + */ + +/* Timer count */ +__sfr __at 0xCA T3CNT; +__sfr __at 0xEA T4CNT; + +/* Timer control */ + +__sfr __at 0xCB T3CTL; +__sfr __at 0xEB T4CTL; + +#define TxCTL_DIV_1 (0 << 5) +#define TxCTL_DIV_2 (1 << 5) +#define TxCTL_DIV_4 (2 << 5) +#define TxCTL_DIV_8 (3 << 5) +#define TxCTL_DIV_16 (4 << 5) +#define TxCTL_DIV_32 (5 << 5) +#define TxCTL_DIV_64 (6 << 5) +#define TxCTL_DIV_128 (7 << 5) +#define TxCTL_START (1 << 4) +#define TxCTL_OVFIM (1 << 3) +#define TxCTL_CLR (1 << 2) +#define TxCTL_MODE_FREE (0 << 0) +#define TxCTL_MODE_DOWN (1 << 0) +#define TxCTL_MODE_MODULO (2 << 0) +#define TxCTL_MODE_UP_DOWN (3 << 0) + +/* Timer 4 channel 0 compare control */ + +__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_CLEAR (1 << 3) +#define TxCCTLy_CMP_TOGGLE (2 << 3) +#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) +#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) +#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) +#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 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; + +/* + * Peripheral control + */ + +__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) + +#define PERCFG_T3CFG_ALT_1 (0 << 5) +#define PERCFG_T3CFG_ALT_2 (1 << 5) +#define PERCFG_T3CFG_ALT_MASK (1 << 5) + +#define PERCFG_T4CFG_ALT_1 (0 << 4) +#define PERCFG_T4CFG_ALT_2 (1 << 4) +#define PERCFG_T4CFG_ALT_MASK (1 << 4) + +#define PERCFG_U1CFG_ALT_1 (0 << 1) +#define PERCFG_U1CFG_ALT_2 (1 << 1) +#define PERCFG_U1CFG_ALT_MASK (1 << 1) + +#define PERCFG_U0CFG_ALT_1 (0 << 0) +#define PERCFG_U0CFG_ALT_2 (1 << 0) +#define PERCFG_U0CFG_ALT_MASK (1 << 0) + +/* directly addressed USB registers */ +__xdata __at (0xde00) volatile uint8_t USBADDR; +__xdata __at (0xde01) volatile uint8_t USBPOW; +__xdata __at (0xde02) volatile uint8_t USBIIF; + +__xdata __at (0xde04) volatile uint8_t USBOIF; + +__xdata __at (0xde06) volatile uint8_t USBCIF; + +# define USBCIF_SOFIF (1 << 3) +# define USBCIF_RSTIF (1 << 2) +# define USBCIF_RESUMEIF (1 << 1) +# define USBCIF_SUSPENDIF (1 << 0) + +__xdata __at (0xde07) volatile uint8_t USBIIE; + +__xdata __at (0xde09) volatile uint8_t USBOIE; + +__xdata __at (0xde0b) volatile uint8_t USBCIE; + +# define USBCIE_SOFIE (1 << 3) +# define USBCIE_RSTIE (1 << 2) +# define USBCIE_RESUMEIE (1 << 1) +# define USBCIE_SUSPENDIE (1 << 0) + +__xdata __at (0xde0c) volatile uint8_t USBFRML; +__xdata __at (0xde0d) volatile uint8_t USBFRMH; +__xdata __at (0xde0e) volatile uint8_t USBINDEX; + +/* indexed USB registers, must set USBINDEX to 0-5 */ +__xdata __at (0xde10) volatile uint8_t USBMAXI; +__xdata __at (0xde11) volatile uint8_t USBCS0; + +# define USBCS0_CLR_SETUP_END (1 << 7) +# define USBCS0_CLR_OUTPKT_RDY (1 << 6) +# define USBCS0_SEND_STALL (1 << 5) +# define USBCS0_SETUP_END (1 << 4) +# define USBCS0_DATA_END (1 << 3) +# define USBCS0_SENT_STALL (1 << 2) +# define USBCS0_INPKT_RDY (1 << 1) +# define USBCS0_OUTPKT_RDY (1 << 0) + +__xdata __at (0xde11) volatile uint8_t USBCSIL; + +# define USBCSIL_CLR_DATA_TOG (1 << 6) +# define USBCSIL_SENT_STALL (1 << 5) +# define USBCSIL_SEND_STALL (1 << 4) +# define USBCSIL_FLUSH_PACKET (1 << 3) +# define USBCSIL_UNDERRUN (1 << 2) +# define USBCSIL_PKT_PRESENT (1 << 1) +# define USBCSIL_INPKT_RDY (1 << 0) + +__xdata __at (0xde12) volatile uint8_t USBCSIH; + +# define USBCSIH_AUTOSET (1 << 7) +# define USBCSIH_ISO (1 << 6) +# define USBCSIH_FORCE_DATA_TOG (1 << 3) +# define USBCSIH_IN_DBL_BUF (1 << 0) + +__xdata __at (0xde13) volatile uint8_t USBMAXO; +__xdata __at (0xde14) volatile uint8_t USBCSOL; + +# define USBCSOL_CLR_DATA_TOG (1 << 7) +# define USBCSOL_SENT_STALL (1 << 6) +# define USBCSOL_SEND_STALL (1 << 5) +# define USBCSOL_FLUSH_PACKET (1 << 4) +# define USBCSOL_DATA_ERROR (1 << 3) +# define USBCSOL_OVERRUN (1 << 2) +# define USBCSOL_FIFO_FULL (1 << 1) +# define USBCSOL_OUTPKT_RDY (1 << 0) + +__xdata __at (0xde15) volatile uint8_t USBCSOH; + +# define USBCSOH_AUTOCLEAR (1 << 7) +# define USBCSOH_ISO (1 << 6) +# define USBCSOH_OUT_DBL_BUF (1 << 0) + +__xdata __at (0xde16) volatile uint8_t USBCNT0; +__xdata __at (0xde16) volatile uint8_t USBCNTL; +__xdata __at (0xde17) volatile uint8_t USBCNTH; + +__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; + +/* ADC Data register, low and high */ +__sfr at 0xBA ADCL; +__sfr at 0xBB ADCH; +__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; + +/* ADC Control Register 1 */ +__sfr at 0xB4 ADCCON1; + +# define ADCCON1_EOC (1 << 7) /* conversion complete */ +# define ADCCON1_ST (1 << 6) /* start conversion */ + +# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ +# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ +# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ +# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ +# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ + +# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ +# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ +# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ + +/* ADC Control Register 2 */ +__sfr at 0xB5 ADCCON2; + +# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ +# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ +# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ +# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ +# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ + +# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ +# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ +# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ +# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ +# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ + +# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ +# define ADCCON2_SCH_SHIFT 0 +# define ADCCON2_SCH_AIN0 (0 << 0) +# define ADCCON2_SCH_AIN1 (1 << 0) +# define ADCCON2_SCH_AIN2 (2 << 0) +# define ADCCON2_SCH_AIN3 (3 << 0) +# define ADCCON2_SCH_AIN4 (4 << 0) +# define ADCCON2_SCH_AIN5 (5 << 0) +# define ADCCON2_SCH_AIN6 (6 << 0) +# define ADCCON2_SCH_AIN7 (7 << 0) +# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) +# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) +# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) +# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) +# define ADCCON2_SCH_GND (0xc << 0) +# define ADCCON2_SCH_VREF (0xd << 0) +# define ADCCON2_SCH_TEMP (0xe << 0) +# define ADCCON2_SCH_VDD_3 (0xf << 0) + + +/* ADC Control Register 3 */ +__sfr at 0xB6 ADCCON3; + +# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ +# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ +# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ +# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ +# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ +# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ +# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ +# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ +# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ +# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ +# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ +# define ADCCON3_ECH_SHIFT 0 +# define ADCCON3_ECH_AIN0 (0 << 0) +# define ADCCON3_ECH_AIN1 (1 << 0) +# define ADCCON3_ECH_AIN2 (2 << 0) +# define ADCCON3_ECH_AIN3 (3 << 0) +# define ADCCON3_ECH_AIN4 (4 << 0) +# define ADCCON3_ECH_AIN5 (5 << 0) +# define ADCCON3_ECH_AIN6 (6 << 0) +# define ADCCON3_ECH_AIN7 (7 << 0) +# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) +# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) +# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) +# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) +# define ADCCON3_ECH_GND (0xc << 0) +# define ADCCON3_ECH_VREF (0xd << 0) +# define ADCCON3_ECH_TEMP (0xe << 0) +# define ADCCON3_ECH_VDD_3 (0xf << 0) + +/* + * ADC configuration register, this selects which + * GPIO pins are to be used as ADC inputs + */ +__sfr at 0xF2 ADCCFG; + +/* + * Watchdog timer + */ + +__sfr at 0xc9 WDCTL; + +#define WDCTL_CLEAR_FIRST (0xa << 4) +#define WDCTL_CLEAR_SECOND (0x5 << 4) +#define WDCTL_EN (1 << 3) +#define WDCTL_MODE_WATCHDOG (0 << 2) +#define WDCTL_MODE_TIMER (1 << 2) +#define WDCTL_MODE_MASK (1 << 2) +#define WDCTL_INT_32768 (0 << 0) +#define WDCTL_INT_8192 (1 << 0) +#define WDCTL_INT_512 (2 << 0) +#define WDCTL_INT_64 (3 << 0) + +/* + * Pin selectors, these set which pins are + * using their peripheral function + */ +__sfr at 0xF3 P0SEL; +__sfr at 0xF4 P1SEL; +__sfr at 0xF5 P2SEL; + +#define P2SEL_PRI3P1_USART0 (0 << 6) +#define P2SEL_PRI3P1_USART1 (1 << 6) +#define P2SEL_PRI3P1_MASK (1 << 6) +#define P2SEL_PRI2P1_USART1 (0 << 5) +#define P2SEL_PRI2P1_TIMER3 (1 << 5) +#define P2SEL_PRI2P1_MASK (1 << 5) +#define P2SEL_PRI1P1_TIMER1 (0 << 4) +#define P2SEL_PRI1P1_TIMER4 (1 << 4) +#define P2SEL_PRI1P1_MASK (1 << 4) +#define P2SEL_PRI0P1_USART0 (0 << 3) +#define P2SEL_PRI0P1_TIMER1 (1 << 3) +#define P2SEL_PRI0P1_MASK (1 << 3) +#define P2SEL_SELP2_4_GPIO (0 << 2) +#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) +#define P2SEL_SELP2_4_MASK (1 << 2) +#define P2SEL_SELP2_3_GPIO (0 << 1) +#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) +#define P2SEL_SELP2_3_MASK (1 << 1) +#define P2SEL_SELP2_0_GPIO (0 << 0) +#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) +#define P2SEL_SELP2_0_MASK (1 << 0) + +/* + * For pins used as GPIOs, these set which are used as outputs + */ +__sfr at 0xFD P0DIR; +__sfr at 0xFE P1DIR; +__sfr at 0xFF P2DIR; + +#define P2DIR_PRIP0_USART0_USART1 (0 << 6) +#define P2DIR_PRIP0_USART1_USART0 (1 << 6) +#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) +#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) +#define P2DIR_PRIP0_MASK (3 << 6) + +__sfr at 0x8F P0INP; + +/* Select between tri-state and pull up/down + * for pins P0_0 - P0_7. + */ +#define P0INP_MDP0_7_PULL (0 << 7) +#define P0INP_MDP0_7_TRISTATE (1 << 7) +#define P0INP_MDP0_6_PULL (0 << 6) +#define P0INP_MDP0_6_TRISTATE (1 << 6) +#define P0INP_MDP0_5_PULL (0 << 5) +#define P0INP_MDP0_5_TRISTATE (1 << 5) +#define P0INP_MDP0_4_PULL (0 << 4) +#define P0INP_MDP0_4_TRISTATE (1 << 4) +#define P0INP_MDP0_3_PULL (0 << 3) +#define P0INP_MDP0_3_TRISTATE (1 << 3) +#define P0INP_MDP0_2_PULL (0 << 2) +#define P0INP_MDP0_2_TRISTATE (1 << 2) +#define P0INP_MDP0_1_PULL (0 << 1) +#define P0INP_MDP0_1_TRISTATE (1 << 1) +#define P0INP_MDP0_0_PULL (0 << 0) +#define P0INP_MDP0_0_TRISTATE (1 << 0) + +__sfr at 0xF6 P1INP; + +/* Select between tri-state and pull up/down + * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are + * always tri-stated + */ +#define P1INP_MDP1_7_PULL (0 << 7) +#define P1INP_MDP1_7_TRISTATE (1 << 7) +#define P1INP_MDP1_6_PULL (0 << 6) +#define P1INP_MDP1_6_TRISTATE (1 << 6) +#define P1INP_MDP1_5_PULL (0 << 5) +#define P1INP_MDP1_5_TRISTATE (1 << 5) +#define P1INP_MDP1_4_PULL (0 << 4) +#define P1INP_MDP1_4_TRISTATE (1 << 4) +#define P1INP_MDP1_3_PULL (0 << 3) +#define P1INP_MDP1_3_TRISTATE (1 << 3) +#define P1INP_MDP1_2_PULL (0 << 2) +#define P1INP_MDP1_2_TRISTATE (1 << 2) + +__sfr at 0xF7 P2INP; +/* P2INP has three extra bits which are used to choose + * between pull-up and pull-down when they are not tri-stated + */ +#define P2INP_PDUP2_PULL_UP (0 << 7) +#define P2INP_PDUP2_PULL_DOWN (1 << 7) +#define P2INP_PDUP1_PULL_UP (0 << 6) +#define P2INP_PDUP1_PULL_DOWN (1 << 6) +#define P2INP_PDUP0_PULL_UP (0 << 5) +#define P2INP_PDUP0_PULL_DOWN (1 << 5) + +/* For the P2 pins, choose between tri-state and pull up/down + * mode + */ +#define P2INP_MDP2_4_PULL (0 << 4) +#define P2INP_MDP2_4_TRISTATE (1 << 4) +#define P2INP_MDP2_3_PULL (0 << 3) +#define P2INP_MDP2_3_TRISTATE (1 << 3) +#define P2INP_MDP2_2_PULL (0 << 2) +#define P2INP_MDP2_2_TRISTATE (1 << 2) +#define P2INP_MDP2_1_PULL (0 << 1) +#define P2INP_MDP2_1_TRISTATE (1 << 1) +#define P2INP_MDP2_0_PULL (0 << 0) +#define P2INP_MDP2_0_TRISTATE (1 << 0) + +/* GPIO interrupt status flags */ +__sfr at 0x89 P0IFG; +__sfr at 0x8A P1IFG; +__sfr at 0x8B P2IFG; + +#define P0IFG_USB_RESUME (1 << 7) + +__sfr at 0x8C PICTL; +#define PICTL_P2IEN (1 << 5) +#define PICTL_P0IENH (1 << 4) +#define PICTL_P0IENL (1 << 3) +#define PICTL_P2ICON (1 << 2) +#define PICTL_P1ICON (1 << 1) +#define PICTL_P0ICON (1 << 0) + +/* GPIO pins */ +__sfr at 0x80 P0; + +sbit at 0x80 P0_0; +sbit at 0x81 P0_1; +sbit at 0x82 P0_2; +sbit at 0x83 P0_3; +sbit at 0x84 P0_4; +sbit at 0x85 P0_5; +sbit at 0x86 P0_6; +sbit at 0x87 P0_7; + +__sfr at 0x90 P1; + +sbit at 0x90 P1_0; +sbit at 0x91 P1_1; +sbit at 0x92 P1_2; +sbit at 0x93 P1_3; +sbit at 0x94 P1_4; +sbit at 0x95 P1_5; +sbit at 0x96 P1_6; +sbit at 0x97 P1_7; + +__sfr at 0xa0 P2; + +sbit at 0xa0 P2_0; +sbit at 0xa1 P2_1; +sbit at 0xa2 P2_2; +sbit at 0xa3 P2_3; +sbit at 0xa4 P2_4; + +/* DMA controller */ +struct cc_dma_channel { + uint8_t src_high; + uint8_t src_low; + uint8_t dst_high; + uint8_t dst_low; + uint8_t len_high; + uint8_t len_low; + uint8_t cfg0; + uint8_t cfg1; +}; + +# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) +# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) +# define DMA_LEN_HIGH_VLEN (2 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) +# define DMA_LEN_HIGH_MASK (0x1f) + +# define DMA_CFG0_WORDSIZE_8 (0 << 7) +# define DMA_CFG0_WORDSIZE_16 (1 << 7) +# define DMA_CFG0_TMODE_MASK (3 << 5) +# define DMA_CFG0_TMODE_SINGLE (0 << 5) +# define DMA_CFG0_TMODE_BLOCK (1 << 5) +# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) +# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) + +/* + * DMA triggers + */ +# define DMA_CFG0_TRIGGER_NONE 0 +# define DMA_CFG0_TRIGGER_PREV 1 +# define DMA_CFG0_TRIGGER_T1_CH0 2 +# define DMA_CFG0_TRIGGER_T1_CH1 3 +# define DMA_CFG0_TRIGGER_T1_CH2 4 +# define DMA_CFG0_TRIGGER_T2_OVFL 6 +# define DMA_CFG0_TRIGGER_T3_CH0 7 +# define DMA_CFG0_TRIGGER_T3_CH1 8 +# define DMA_CFG0_TRIGGER_T4_CH0 9 +# define DMA_CFG0_TRIGGER_T4_CH1 10 +# define DMA_CFG0_TRIGGER_IOC_0 12 +# define DMA_CFG0_TRIGGER_IOC_1 13 +# define DMA_CFG0_TRIGGER_URX0 14 +# define DMA_CFG0_TRIGGER_UTX0 15 +# define DMA_CFG0_TRIGGER_URX1 16 +# define DMA_CFG0_TRIGGER_UTX1 17 +# define DMA_CFG0_TRIGGER_FLASH 18 +# define DMA_CFG0_TRIGGER_RADIO 19 +# define DMA_CFG0_TRIGGER_ADC_CHALL 20 +# define DMA_CFG0_TRIGGER_ADC_CH0 21 +# define DMA_CFG0_TRIGGER_ADC_CH1 22 +# define DMA_CFG0_TRIGGER_ADC_CH2 23 +# define DMA_CFG0_TRIGGER_ADC_CH3 24 +# define DMA_CFG0_TRIGGER_ADC_CH4 25 +# define DMA_CFG0_TRIGGER_ADC_CH5 26 +# define DMA_CFG0_TRIGGER_ADC_CH6 27 +# define DMA_CFG0_TRIGGER_I2SRX 27 +# define DMA_CFG0_TRIGGER_ADC_CH7 28 +# define DMA_CFG0_TRIGGER_I2STX 28 +# define DMA_CFG0_TRIGGER_ENC_DW 29 +# define DMA_CFG0_TRIGGER_DNC_UP 30 + +# define DMA_CFG1_SRCINC_MASK (3 << 6) +# define DMA_CFG1_SRCINC_0 (0 << 6) +# define DMA_CFG1_SRCINC_1 (1 << 6) +# define DMA_CFG1_SRCINC_2 (2 << 6) +# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) + +# define DMA_CFG1_DESTINC_MASK (3 << 4) +# define DMA_CFG1_DESTINC_0 (0 << 4) +# define DMA_CFG1_DESTINC_1 (1 << 4) +# define DMA_CFG1_DESTINC_2 (2 << 4) +# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) + +# define DMA_CFG1_IRQMASK (1 << 3) +# define DMA_CFG1_M8 (1 << 2) + +# define DMA_CFG1_PRIORITY_MASK (3 << 0) +# define DMA_CFG1_PRIORITY_LOW (0 << 0) +# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) +# define DMA_CFG1_PRIORITY_HIGH (2 << 0) + +/* + * DMAARM - DMA Channel Arm + */ + +__sfr at 0xD6 DMAARM; + +# define DMAARM_ABORT (1 << 7) +# define DMAARM_DMAARM4 (1 << 4) +# define DMAARM_DMAARM3 (1 << 3) +# define DMAARM_DMAARM2 (1 << 2) +# define DMAARM_DMAARM1 (1 << 1) +# define DMAARM_DMAARM0 (1 << 0) + +/* + * DMAREQ - DMA Channel Start Request and Status + */ + +__sfr at 0xD7 DMAREQ; + +# define DMAREQ_DMAREQ4 (1 << 4) +# define DMAREQ_DMAREQ3 (1 << 3) +# define DMAREQ_DMAREQ2 (1 << 2) +# define DMAREQ_DMAREQ1 (1 << 1) +# define DMAREQ_DMAREQ0 (1 << 0) + +/* + * DMA configuration 0 address + */ + +__sfr at 0xD5 DMA0CFGH; +__sfr at 0xD4 DMA0CFGL; + +/* + * DMA configuration 1-4 address + */ + +__sfr at 0xD3 DMA1CFGH; +__sfr at 0xD2 DMA1CFGL; + +/* + * DMAIRQ - DMA Interrupt Flag + */ + +__sfr at 0xD1 DMAIRQ; + +# define DMAIRQ_DMAIF4 (1 << 4) +# define DMAIRQ_DMAIF3 (1 << 3) +# define DMAIRQ_DMAIF2 (1 << 2) +# define DMAIRQ_DMAIF1 (1 << 1) +# define DMAIRQ_DMAIF0 (1 << 0) + +/* + * UART registers + */ + +/* USART config/status registers */ +__sfr at 0x86 U0CSR; +__sfr at 0xF8 U1CSR; + +# define UxCSR_MODE_UART (1 << 7) +# define UxCSR_MODE_SPI (0 << 7) +# define UxCSR_RE (1 << 6) +# define UxCSR_SLAVE (1 << 5) +# define UxCSR_MASTER (0 << 5) +# define UxCSR_FE (1 << 4) +# define UxCSR_ERR (1 << 3) +# define UxCSR_RX_BYTE (1 << 2) +# define UxCSR_TX_BYTE (1 << 1) +# define UxCSR_ACTIVE (1 << 0) + +/* UART configuration registers */ +__sfr at 0xc4 U0UCR; +__sfr at 0xfb U1UCR; + +# define UxUCR_FLUSH (1 << 7) +# define UxUCR_FLOW_DISABLE (0 << 6) +# define UxUCR_FLOW_ENABLE (1 << 6) +# define UxUCR_D9_EVEN_PARITY (0 << 5) +# define UxUCR_D9_ODD_PARITY (1 << 5) +# define UxUCR_BIT9_8_BITS (0 << 4) +# define UxUCR_BIT9_9_BITS (1 << 4) +# define UxUCR_PARITY_DISABLE (0 << 3) +# define UxUCR_PARITY_ENABLE (1 << 3) +# define UxUCR_SPB_1_STOP_BIT (0 << 2) +# define UxUCR_SPB_2_STOP_BITS (1 << 2) +# define UxUCR_STOP_LOW (0 << 1) +# define UxUCR_STOP_HIGH (1 << 1) +# define UxUCR_START_LOW (0 << 0) +# define UxUCR_START_HIGH (1 << 0) + +/* USART General configuration registers (mostly SPI) */ +__sfr at 0xc5 U0GCR; +__sfr at 0xfc U1GCR; + +# define UxGCR_CPOL_NEGATIVE (0 << 7) +# define UxGCR_CPOL_POSITIVE (1 << 7) +# define UxGCR_CPHA_FIRST_EDGE (0 << 6) +# define UxGCR_CPHA_SECOND_EDGE (1 << 6) +# define UxGCR_ORDER_LSB (0 << 5) +# define UxGCR_ORDER_MSB (1 << 5) +# define UxGCR_BAUD_E_MASK (0x1f) +# define UxGCR_BAUD_E_SHIFT 0 + +/* USART data registers */ +__sfr at 0xc1 U0DBUF; +__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; +__sfr at 0xf9 U1DBUF; +__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; + +/* USART baud rate registers, M value */ +__sfr at 0xc2 U0BAUD; +__sfr at 0xfa U1BAUD; + +/* Flash controller */ + +__sfr at 0xAE FCTL; +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +/* Flash write data. Write two bytes here */ +__sfr at 0xAF FWDATA; +__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; + +/* Flash write/erase address */ +__sfr at 0xAD FADDRH; +__sfr at 0xAC FADDRL; + +/* Flash timing */ +__sfr at 0xAB FWT; + +/* Radio */ + +__sfr at 0xD9 RFD; +__xdata at (0xDFD9) volatile uint8_t RFDXADDR; + +__sfr at 0xE9 RFIF; +#define RFIF_IM_TXUNF (1 << 7) +#define RFIF_IM_RXOVF (1 << 6) +#define RFIF_IM_TIMEOUT (1 << 5) +#define RFIF_IM_DONE (1 << 4) +#define RFIF_IM_CS (1 << 3) +#define RFIF_IM_PQT (1 << 2) +#define RFIF_IM_CCA (1 << 1) +#define RFIF_IM_SFD (1 << 0) + +__sfr at 0x91 RFIM; +#define RFIM_IM_TXUNF (1 << 7) +#define RFIM_IM_RXOVF (1 << 6) +#define RFIM_IM_TIMEOUT (1 << 5) +#define RFIM_IM_DONE (1 << 4) +#define RFIM_IM_CS (1 << 3) +#define RFIM_IM_PQT (1 << 2) +#define RFIM_IM_CCA (1 << 1) +#define RFIM_IM_SFD (1 << 0) + +__sfr at 0xE1 RFST; + +#define RFST_SFSTXON 0x00 +#define RFST_SCAL 0x01 +#define RFST_SRX 0x02 +#define RFST_STX 0x03 +#define RFST_SIDLE 0x04 + +__xdata __at (0xdf00) uint8_t RF[0x3c]; + +__xdata __at (0xdf2f) uint8_t RF_IOCFG2; +#define RF_IOCFG2_OFF 0x2f + +__xdata __at (0xdf30) uint8_t RF_IOCFG1; +#define RF_IOCFG1_OFF 0x30 + +__xdata __at (0xdf31) uint8_t RF_IOCFG0; +#define RF_IOCFG0_OFF 0x31 + +__xdata __at (0xdf00) uint8_t RF_SYNC1; +#define RF_SYNC1_OFF 0x00 + +__xdata __at (0xdf01) uint8_t RF_SYNC0; +#define RF_SYNC0_OFF 0x01 + +__xdata __at (0xdf02) uint8_t RF_PKTLEN; +#define RF_PKTLEN_OFF 0x02 + +__xdata __at (0xdf03) uint8_t RF_PKTCTRL1; +#define RF_PKTCTRL1_OFF 0x03 +#define PKTCTRL1_PQT_MASK (0x7 << 5) +#define PKTCTRL1_PQT_SHIFT 5 +#define PKTCTRL1_APPEND_STATUS (1 << 2) +#define PKTCTRL1_ADR_CHK_NONE (0 << 0) +#define PKTCTRL1_ADR_CHK_NO_BROADCAST (1 << 0) +#define PKTCTRL1_ADR_CHK_00_BROADCAST (2 << 0) +#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST (3 << 0) + +/* If APPEND_STATUS is used, two bytes will be added to the packet data */ +#define PKT_APPEND_STATUS_0_RSSI_MASK (0xff) +#define PKT_APPEND_STATUS_0_RSSI_SHIFT 0 +#define PKT_APPEND_STATUS_1_CRC_OK (1 << 7) +#define PKT_APPEND_STATUS_1_LQI_MASK (0x7f) +#define PKT_APPEND_STATUS_1_LQI_SHIFT 0 + +__xdata __at (0xdf04) uint8_t RF_PKTCTRL0; +#define RF_PKTCTRL0_OFF 0x04 +#define RF_PKTCTRL0_WHITE_DATA (1 << 6) +#define RF_PKTCTRL0_PKT_FORMAT_NORMAL (0 << 4) +#define RF_PKTCTRL0_PKT_FORMAT_RANDOM (2 << 4) +#define RF_PKTCTRL0_CRC_EN (1 << 2) +#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED (0 << 0) +#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE (1 << 0) + +__xdata __at (0xdf05) uint8_t RF_ADDR; +#define RF_ADDR_OFF 0x05 + +__xdata __at (0xdf06) uint8_t RF_CHANNR; +#define RF_CHANNR_OFF 0x06 + +__xdata __at (0xdf07) uint8_t RF_FSCTRL1; +#define RF_FSCTRL1_OFF 0x07 + +#define RF_FSCTRL1_FREQ_IF_SHIFT (0) + +__xdata __at (0xdf08) uint8_t RF_FSCTRL0; +#define RF_FSCTRL0_OFF 0x08 + +#define RF_FSCTRL0_FREQOFF_SHIFT (0) + +__xdata __at (0xdf09) uint8_t RF_FREQ2; +#define RF_FREQ2_OFF 0x09 + +__xdata __at (0xdf0a) uint8_t RF_FREQ1; +#define RF_FREQ1_OFF 0x0a + +__xdata __at (0xdf0b) uint8_t RF_FREQ0; +#define RF_FREQ0_OFF 0x0b + +__xdata __at (0xdf0c) uint8_t RF_MDMCFG4; +#define RF_MDMCFG4_OFF 0x0c + +#define RF_MDMCFG4_CHANBW_E_SHIFT 6 +#define RF_MDMCFG4_CHANBW_M_SHIFT 4 +#define RF_MDMCFG4_DRATE_E_SHIFT 0 + +__xdata __at (0xdf0d) uint8_t RF_MDMCFG3; +#define RF_MDMCFG3_OFF 0x0d + +#define RF_MDMCFG3_DRATE_M_SHIFT 0 + +__xdata __at (0xdf0e) uint8_t RF_MDMCFG2; +#define RF_MDMCFG2_OFF 0x0e + +#define RF_MDMCFG2_DEM_DCFILT_OFF (1 << 7) +#define RF_MDMCFG2_DEM_DCFILT_ON (0 << 7) + +#define RF_MDMCFG2_MOD_FORMAT_MASK (7 << 4) +#define RF_MDMCFG2_MOD_FORMAT_2_FSK (0 << 4) +#define RF_MDMCFG2_MOD_FORMAT_GFSK (1 << 4) +#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK (3 << 4) +#define RF_MDMCFG2_MOD_FORMAT_MSK (7 << 4) + +#define RF_MDMCFG2_MANCHESTER_EN (1 << 3) + +#define RF_MDMCFG2_SYNC_MODE_MASK (0x7 << 0) +#define RF_MDMCFG2_SYNC_MODE_NONE (0x0 << 0) +#define RF_MDMCFG2_SYNC_MODE_15_16 (0x1 << 0) +#define RF_MDMCFG2_SYNC_MODE_16_16 (0x2 << 0) +#define RF_MDMCFG2_SYNC_MODE_30_32 (0x3 << 0) +#define RF_MDMCFG2_SYNC_MODE_NONE_THRES (0x4 << 0) +#define RF_MDMCFG2_SYNC_MODE_15_16_THRES (0x5 << 0) +#define RF_MDMCFG2_SYNC_MODE_16_16_THRES (0x6 << 0) +#define RF_MDMCFG2_SYNC_MODE_30_32_THRES (0x7 << 0) + +__xdata __at (0xdf0f) uint8_t RF_MDMCFG1; +#define RF_MDMCFG1_OFF 0x0f + +#define RF_MDMCFG1_FEC_EN (1 << 7) +#define RF_MDMCFG1_FEC_DIS (0 << 7) + +#define RF_MDMCFG1_NUM_PREAMBLE_MASK (7 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_2 (0 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_3 (1 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_4 (2 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_6 (3 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_8 (4 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_12 (5 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_16 (6 << 4) +#define RF_MDMCFG1_NUM_PREAMBLE_24 (7 << 4) + +#define RF_MDMCFG1_CHANSPC_E_MASK (3 << 0) +#define RF_MDMCFG1_CHANSPC_E_SHIFT (0) + +__xdata __at (0xdf10) uint8_t RF_MDMCFG0; +#define RF_MDMCFG0_OFF 0x10 + +#define RF_MDMCFG0_CHANSPC_M_SHIFT (0) + +__xdata __at (0xdf11) uint8_t RF_DEVIATN; +#define RF_DEVIATN_OFF 0x11 + +#define RF_DEVIATN_DEVIATION_E_SHIFT 4 +#define RF_DEVIATN_DEVIATION_M_SHIFT 0 + +__xdata __at (0xdf12) uint8_t RF_MCSM2; +#define RF_MCSM2_OFF 0x12 +#define RF_MCSM2_RX_TIME_RSSI (1 << 4) +#define RF_MCSM2_RX_TIME_QUAL (1 << 3) +#define RF_MCSM2_RX_TIME_MASK (0x7) +#define RF_MCSM2_RX_TIME_SHIFT 0 +#define RF_MCSM2_RX_TIME_END_OF_PACKET (7) + +__xdata __at (0xdf13) uint8_t RF_MCSM1; +#define RF_MCSM1_OFF 0x13 +#define RF_MCSM1_CCA_MODE_ALWAYS (0 << 4) +#define RF_MCSM1_CCA_MODE_RSSI_BELOW (1 << 4) +#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING (2 << 4) +#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING (3 << 4) +#define RF_MCSM1_RXOFF_MODE_IDLE (0 << 2) +#define RF_MCSM1_RXOFF_MODE_FSTXON (1 << 2) +#define RF_MCSM1_RXOFF_MODE_TX (2 << 2) +#define RF_MCSM1_RXOFF_MODE_RX (3 << 2) +#define RF_MCSM1_TXOFF_MODE_IDLE (0 << 0) +#define RF_MCSM1_TXOFF_MODE_FSTXON (1 << 0) +#define RF_MCSM1_TXOFF_MODE_TX (2 << 0) +#define RF_MCSM1_TXOFF_MODE_RX (3 << 0) + +__xdata __at (0xdf14) uint8_t RF_MCSM0; +#define RF_MCSM0_OFF 0x14 +#define RF_MCSM0_FS_AUTOCAL_NEVER (0 << 4) +#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE (1 << 4) +#define RF_MCSM0_FS_AUTOCAL_TO_IDLE (2 << 4) +#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4 (3 << 4) +#define RF_MCSM0_MAGIC_3 (1 << 3) +#define RF_MCSM0_MAGIC_2 (1 << 2) +#define RF_MCSM0_CLOSE_IN_RX_0DB (0 << 0) +#define RF_MCSM0_CLOSE_IN_RX_6DB (1 << 0) +#define RF_MCSM0_CLOSE_IN_RX_12DB (2 << 0) +#define RF_MCSM0_CLOSE_IN_RX_18DB (3 << 0) + +__xdata __at (0xdf15) uint8_t RF_FOCCFG; +#define RF_FOCCFG_OFF 0x15 +#define RF_FOCCFG_FOC_BS_CS_GATE (1 << 5) +#define RF_FOCCFG_FOC_PRE_K_1K (0 << 3) +#define RF_FOCCFG_FOC_PRE_K_2K (1 << 3) +#define RF_FOCCFG_FOC_PRE_K_3K (2 << 3) +#define RF_FOCCFG_FOC_PRE_K_4K (3 << 3) +#define RF_FOCCFG_FOC_POST_K_PRE_K (0 << 2) +#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2 (1 << 2) +#define RF_FOCCFG_FOC_LIMIT_0 (0 << 0) +#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8 (1 << 0) +#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4 (2 << 0) +#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2 (3 << 0) + +__xdata __at (0xdf16) uint8_t RF_BSCFG; +#define RF_BSCFG_OFF 0x16 +#define RF_BSCFG_BS_PRE_K_1K (0 << 6) +#define RF_BSCFG_BS_PRE_K_2K (1 << 6) +#define RF_BSCFG_BS_PRE_K_3K (2 << 6) +#define RF_BSCFG_BS_PRE_K_4K (3 << 6) +#define RF_BSCFG_BS_PRE_KP_1KP (0 << 4) +#define RF_BSCFG_BS_PRE_KP_2KP (1 << 4) +#define RF_BSCFG_BS_PRE_KP_3KP (2 << 4) +#define RF_BSCFG_BS_PRE_KP_4KP (3 << 4) +#define RF_BSCFG_BS_POST_KI_PRE_KI (0 << 3) +#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2 (1 << 3) +#define RF_BSCFG_BS_POST_KP_PRE_KP (0 << 2) +#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2 (1 << 2) +#define RF_BSCFG_BS_LIMIT_0 (0 << 0) +#define RF_BSCFG_BS_LIMIT_3_125 (1 << 0) +#define RF_BSCFG_BS_LIMIT_6_25 (2 << 0) +#define RF_BSCFG_BS_LIMIT_12_5 (3 << 0) + +__xdata __at (0xdf17) uint8_t RF_AGCCTRL2; +#define RF_AGCCTRL2_OFF 0x17 + +__xdata __at (0xdf18) uint8_t RF_AGCCTRL1; +#define RF_AGCCTRL1_OFF 0x18 + +__xdata __at (0xdf19) uint8_t RF_AGCCTRL0; +#define RF_AGCCTRL0_OFF 0x19 + +__xdata __at (0xdf1a) uint8_t RF_FREND1; +#define RF_FREND1_OFF 0x1a + +#define RF_FREND1_LNA_CURRENT_SHIFT 6 +#define RF_FREND1_LNA2MIX_CURRENT_SHIFT 4 +#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT 2 +#define RF_FREND1_MIX_CURRENT_SHIFT 0 + +__xdata __at (0xdf1b) uint8_t RF_FREND0; +#define RF_FREND0_OFF 0x1b + +#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK (0x3 << 4) +#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT 4 +#define RF_FREND0_PA_POWER_MASK (0x7) +#define RF_FREND0_PA_POWER_SHIFT 0 + +__xdata __at (0xdf1c) uint8_t RF_FSCAL3; +#define RF_FSCAL3_OFF 0x1c + +__xdata __at (0xdf1d) uint8_t RF_FSCAL2; +#define RF_FSCAL2_OFF 0x1d + +__xdata __at (0xdf1e) uint8_t RF_FSCAL1; +#define RF_FSCAL1_OFF 0x1e + +__xdata __at (0xdf1f) uint8_t RF_FSCAL0; +#define RF_FSCAL0_OFF 0x1f + +__xdata __at (0xdf23) uint8_t RF_TEST2; +#define RF_TEST2_OFF 0x23 + +#define RF_TEST2_NORMAL_MAGIC 0x88 +#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC 0x81 + +__xdata __at (0xdf24) uint8_t RF_TEST1; +#define RF_TEST1_OFF 0x24 + +#define RF_TEST1_TX_MAGIC 0x31 +#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC 0x35 + +__xdata __at (0xdf25) uint8_t RF_TEST0; +#define RF_TEST0_OFF 0x25 + +#define RF_TEST0_7_2_MASK (0xfc) +#define RF_TEST0_VCO_SEL_CAL_EN (1 << 1) +#define RF_TEST0_0_MASK (1) + +/* These are undocumented, and must be computed + * using the provided tool. + */ +__xdata __at (0xdf27) uint8_t RF_PA_TABLE7; +#define RF_PA_TABLE7_OFF 0x27 + +__xdata __at (0xdf28) uint8_t RF_PA_TABLE6; +#define RF_PA_TABLE6_OFF 0x28 + +__xdata __at (0xdf29) uint8_t RF_PA_TABLE5; +#define RF_PA_TABLE5_OFF 0x29 + +__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4; +#define RF_PA_TABLE4_OFF 0x2a + +__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3; +#define RF_PA_TABLE3_OFF 0x2b + +__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2; +#define RF_PA_TABLE2_OFF 0x2c + +__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1; +#define RF_PA_TABLE1_OFF 0x2d + +__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0; +#define RF_PA_TABLE0_OFF 0x2e + +__xdata __at (0xdf36) uint8_t RF_PARTNUM; +#define RF_PARTNUM_OFF 0x36 + +__xdata __at (0xdf37) uint8_t RF_VERSION; +#define RF_VERSION_OFF 0x37 + +__xdata __at (0xdf38) uint8_t RF_FREQEST; +#define RF_FREQEST_OFF 0x38 + +__xdata __at (0xdf39) uint8_t RF_LQI; +#define RF_LQI_OFF 0x39 + +#define RF_LQI_CRC_OK (1 << 7) +#define RF_LQI_LQI_EST_MASK (0x7f) + +__xdata __at (0xdf3a) uint8_t RF_RSSI; +#define RF_RSSI_OFF 0x3a + +__xdata __at (0xdf3b) uint8_t RF_MARCSTATE; +#define RF_MARCSTATE_OFF 0x3b + +#define RF_MARCSTATE_MASK 0x1f +#define RF_MARCSTATE_SLEEP 0x00 +#define RF_MARCSTATE_IDLE 0x01 +#define RF_MARCSTATE_VCOON_MC 0x03 +#define RF_MARCSTATE_REGON_MC 0x04 +#define RF_MARCSTATE_MANCAL 0x05 +#define RF_MARCSTATE_VCOON 0x06 +#define RF_MARCSTATE_REGON 0x07 +#define RF_MARCSTATE_STARTCAL 0x08 +#define RF_MARCSTATE_BWBOOST 0x09 +#define RF_MARCSTATE_FS_LOCK 0x0a +#define RF_MARCSTATE_IFADCON 0x0b +#define RF_MARCSTATE_ENDCAL 0x0c +#define RF_MARCSTATE_RX 0x0d +#define RF_MARCSTATE_RX_END 0x0e +#define RF_MARCSTATE_RX_RST 0x0f +#define RF_MARCSTATE_TXRX_SWITCH 0x10 +#define RF_MARCSTATE_RX_OVERFLOW 0x11 +#define RF_MARCSTATE_FSTXON 0x12 +#define RF_MARCSTATE_TX 0x13 +#define RF_MARCSTATE_TX_END 0x14 +#define RF_MARCSTATE_RXTX_SWITCH 0x15 +#define RF_MARCSTATE_TX_UNDERFLOW 0x16 + + +__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; +#define RF_PKTSTATUS_OFF 0x3c + +#define RF_PKTSTATUS_CRC_OK (1 << 7) +#define RF_PKTSTATUS_CS (1 << 6) +#define RF_PKTSTATUS_PQT_REACHED (1 << 5) +#define RF_PKTSTATUS_CCA (1 << 4) +#define RF_PKTSTATUS_SFD (1 << 3) + +__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; +#define RF_VCO_VC_DAC_OFF 0x3d + +#endif diff --git a/src/check-stack b/src/check-stack deleted file mode 100755 index 1e8044e0..00000000 --- a/src/check-stack +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -HEADER=$1 -MEM=$2 - -HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` -MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` - -if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then - echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' - exit 1 -else - exit 0 -fi diff --git a/src/core/altitude.h b/src/core/altitude.h new file mode 100644 index 00000000..a278bbc6 --- /dev/null +++ b/src/core/altitude.h @@ -0,0 +1,132 @@ +/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ +#define NALT 129 +#define ALT_FRAC_BITS 8 + 15835, /* 10.56 kPa 0.000% */ + 15332, /* 11.42 kPa 0.781% */ + 14868, /* 12.29 kPa 1.563% */ + 14435, /* 13.16 kPa 2.344% */ + 14030, /* 14.02 kPa 3.125% */ + 13649, /* 14.90 kPa 3.906% */ + 13290, /* 15.76 kPa 4.688% */ + 12950, /* 16.63 kPa 5.469% */ + 12627, /* 17.50 kPa 6.250% */ + 12320, /* 18.37 kPa 7.031% */ + 12027, /* 19.24 kPa 7.813% */ + 11747, /* 20.10 kPa 8.594% */ + 11479, /* 20.97 kPa 9.375% */ + 11222, /* 21.84 kPa 10.156% */ + 10975, /* 22.71 kPa 10.938% */ + 10736, /* 23.58 kPa 11.719% */ + 10504, /* 24.44 kPa 12.500% */ + 10278, /* 25.31 kPa 13.281% */ + 10059, /* 26.18 kPa 14.063% */ + 9846, /* 27.05 kPa 14.844% */ + 9638, /* 27.91 kPa 15.625% */ + 9435, /* 28.78 kPa 16.406% */ + 9237, /* 29.65 kPa 17.188% */ + 9044, /* 30.52 kPa 17.969% */ + 8855, /* 31.39 kPa 18.750% */ + 8670, /* 32.26 kPa 19.531% */ + 8490, /* 33.13 kPa 20.313% */ + 8313, /* 33.99 kPa 21.094% */ + 8140, /* 34.86 kPa 21.875% */ + 7970, /* 35.73 kPa 22.656% */ + 7803, /* 36.60 kPa 23.438% */ + 7640, /* 37.47 kPa 24.219% */ + 7480, /* 38.33 kPa 25.000% */ + 7322, /* 39.20 kPa 25.781% */ + 7168, /* 40.07 kPa 26.563% */ + 7016, /* 40.94 kPa 27.344% */ + 6867, /* 41.80 kPa 28.125% */ + 6720, /* 42.67 kPa 28.906% */ + 6575, /* 43.54 kPa 29.688% */ + 6433, /* 44.41 kPa 30.469% */ + 6294, /* 45.28 kPa 31.250% */ + 6156, /* 46.15 kPa 32.031% */ + 6020, /* 47.01 kPa 32.813% */ + 5887, /* 47.88 kPa 33.594% */ + 5755, /* 48.75 kPa 34.375% */ + 5625, /* 49.62 kPa 35.156% */ + 5497, /* 50.49 kPa 35.938% */ + 5371, /* 51.35 kPa 36.719% */ + 5247, /* 52.22 kPa 37.500% */ + 5124, /* 53.09 kPa 38.281% */ + 5003, /* 53.96 kPa 39.063% */ + 4883, /* 54.83 kPa 39.844% */ + 4765, /* 55.69 kPa 40.625% */ + 4648, /* 56.56 kPa 41.406% */ + 4533, /* 57.43 kPa 42.188% */ + 4419, /* 58.30 kPa 42.969% */ + 4307, /* 59.17 kPa 43.750% */ + 4196, /* 60.03 kPa 44.531% */ + 4086, /* 60.90 kPa 45.313% */ + 3977, /* 61.77 kPa 46.094% */ + 3870, /* 62.63 kPa 46.875% */ + 3764, /* 63.51 kPa 47.656% */ + 3659, /* 64.38 kPa 48.438% */ + 3555, /* 65.24 kPa 49.219% */ + 3453, /* 66.11 kPa 50.000% */ + 3351, /* 66.98 kPa 50.781% */ + 3250, /* 67.85 kPa 51.563% */ + 3151, /* 68.72 kPa 52.344% */ + 3052, /* 69.58 kPa 53.125% */ + 2955, /* 70.45 kPa 53.906% */ + 2858, /* 71.32 kPa 54.688% */ + 2763, /* 72.19 kPa 55.469% */ + 2668, /* 73.06 kPa 56.250% */ + 2574, /* 73.92 kPa 57.031% */ + 2482, /* 74.79 kPa 57.813% */ + 2390, /* 75.66 kPa 58.594% */ + 2298, /* 76.52 kPa 59.375% */ + 2208, /* 77.40 kPa 60.156% */ + 2119, /* 78.26 kPa 60.938% */ + 2030, /* 79.13 kPa 61.719% */ + 1942, /* 80.00 kPa 62.500% */ + 1855, /* 80.87 kPa 63.281% */ + 1769, /* 81.74 kPa 64.063% */ + 1683, /* 82.60 kPa 64.844% */ + 1598, /* 83.47 kPa 65.625% */ + 1514, /* 84.34 kPa 66.406% */ + 1430, /* 85.21 kPa 67.188% */ + 1347, /* 86.08 kPa 67.969% */ + 1265, /* 86.94 kPa 68.750% */ + 1184, /* 87.81 kPa 69.531% */ + 1103, /* 88.68 kPa 70.313% */ + 1023, /* 89.55 kPa 71.094% */ + 943, /* 90.41 kPa 71.875% */ + 864, /* 91.28 kPa 72.656% */ + 786, /* 92.15 kPa 73.438% */ + 708, /* 93.02 kPa 74.219% */ + 631, /* 93.89 kPa 75.000% */ + 554, /* 94.76 kPa 75.781% */ + 478, /* 95.63 kPa 76.563% */ + 403, /* 96.49 kPa 77.344% */ + 328, /* 97.36 kPa 78.125% */ + 254, /* 98.23 kPa 78.906% */ + 180, /* 99.10 kPa 79.688% */ + 106, /* 99.97 kPa 80.469% */ + 34, /* 100.83 kPa 81.250% */ + -39, /* 101.70 kPa 82.031% */ + -111, /* 102.57 kPa 82.813% */ + -182, /* 103.44 kPa 83.594% */ + -253, /* 104.30 kPa 84.375% */ + -323, /* 105.17 kPa 85.156% */ + -393, /* 106.04 kPa 85.938% */ + -462, /* 106.91 kPa 86.719% */ + -531, /* 107.78 kPa 87.500% */ + -600, /* 108.65 kPa 88.281% */ + -668, /* 109.51 kPa 89.063% */ + -736, /* 110.38 kPa 89.844% */ + -803, /* 111.25 kPa 90.625% */ + -870, /* 112.12 kPa 91.406% */ + -936, /* 112.99 kPa 92.188% */ + -1002, /* 113.85 kPa 92.969% */ + -1068, /* 114.72 kPa 93.750% */ + -1133, /* 115.59 kPa 94.531% */ + -1198, /* 116.46 kPa 95.313% */ + -1262, /* 117.33 kPa 96.094% */ + -1326, /* 118.19 kPa 96.875% */ + -1389, /* 119.06 kPa 97.656% */ + -1453, /* 119.93 kPa 98.438% */ + -1516, /* 120.80 kPa 99.219% */ + -1578, /* 121.67 kPa 100.000% */ diff --git a/src/core/ao.h b/src/core/ao.h new file mode 100644 index 00000000..8ac9ac3d --- /dev/null +++ b/src/core/ao.h @@ -0,0 +1,1610 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_H_ +#define _AO_H_ + +#include +#include +#include +#include +#include "cc1111.h" +#include "ao_pins.h" + +#define TRUE 1 +#define FALSE 0 + +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + +/* An AltOS task */ +struct ao_task { + __xdata void *wchan; /* current wait channel (NULL if running) */ + uint16_t alarm; /* abort ao_sleep time */ + uint8_t stack_count; /* amount of saved stack */ + uint8_t task_id; /* unique id */ + __code char *name; /* task name */ + uint8_t stack[AO_STACK_SIZE]; /* saved stack */ +}; + +extern __xdata struct ao_task *__data ao_cur_task; + +#define AO_NUM_TASKS 16 /* maximum number of tasks */ +#define AO_NO_TASK 0 /* no task id */ + +/* + ao_task.c + */ + +/* Suspend the current task until wchan is awoken. + * returns: + * 0 on normal wake + * 1 on alarm + */ +uint8_t +ao_sleep(__xdata void *wchan); + +/* Wake all tasks sleeping on wchan */ +void +ao_wakeup(__xdata void *wchan); + +/* set an alarm to go off in 'delay' ticks */ +void +ao_alarm(uint16_t delay); + +/* Yield the processor to another task */ +void +ao_yield(void) __naked; + +/* Add a task to the run queue */ +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; + +/* Terminate the current task */ +void +ao_exit(void); + +/* Dump task info to console */ +void +ao_task_info(void); + +/* Start the scheduler. This will not return */ +void +ao_start_scheduler(void); + +/* + * ao_panic.c + */ + +#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */ +#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */ +#define AO_PANIC_MUTEX 3 /* Mis-using mutex API */ +#define AO_PANIC_EE 4 /* Mis-using eeprom API */ +#define AO_PANIC_LOG 5 /* Failing to read/write log data */ +#define AO_PANIC_CMD 6 /* Too many command sets registered */ +#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ +#define AO_PANIC_REBOOT 8 /* Reboot failed */ +#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ +#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ +#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ + +/* Stop the operating system, beeping and blinking the reason */ +void +ao_panic(uint8_t reason); + +/* + * ao_timer.c + */ + +/* Our timer runs at 100Hz */ +#define AO_HERTZ 100 +#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) +#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) + +/* Returns the current time in ticks */ +uint16_t +ao_time(void); + +/* Suspend the current task until ticks time has passed */ +void +ao_delay(uint16_t ticks); + +/* Set the ADC interval */ +void +ao_timer_set_adc_interval(uint8_t interval) __critical; + +/* Timer interrupt */ +void +ao_timer_isr(void) __interrupt 9; + +/* Initialize the timer */ +void +ao_timer_init(void); + +/* Initialize the hardware clock. Must be called first */ +void +ao_clock_init(void); + +/* + * One set of samples read from the A/D converter or telemetry + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +/* + * ao_adc.c + */ + +#define AO_ADC_RING 32 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* The A/D interrupt handler */ + +void +ao_adc_isr(void) __interrupt 1; + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* HAS_ADC */ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +/* Turn on the specified LEDs */ +void +ao_led_on(uint8_t colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(uint8_t colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(uint8_t colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(uint8_t colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +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; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) __interrupt 6; +#endif + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +ao_usb_init(void); + +/* + * ao_cmd.c + */ + +enum ao_cmd_status { + ao_cmd_success = 0, + ao_cmd_lex_error = 1, + ao_cmd_syntax_error = 2, +}; + +extern __pdata uint16_t ao_cmd_lex_i; +extern __pdata uint32_t ao_cmd_lex_u32; +extern __pdata char ao_cmd_lex_c; +extern __pdata enum ao_cmd_status ao_cmd_status; + +void +ao_cmd_lex(void); + +void +ao_cmd_put8(uint8_t v); + +void +ao_cmd_put16(uint16_t v); + +void +ao_cmd_white(void); + +void +ao_cmd_hex(void); + +void +ao_cmd_decimal(void); + +uint8_t +ao_match_word(__code char *word); + +struct ao_cmds { + void (*func)(void); + __code char *help; +}; + +void +ao_cmd_register(__code struct ao_cmds *cmds); + +void +ao_cmd_init(void); + +#if HAS_CMD_FILTER +/* + * Provided by an external module to filter raw command lines + */ +uint8_t +ao_cmd_filter(void); +#endif + +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) __interrupt 8; + +/* + * ao_mutex.c + */ + +void +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; + +void +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +/* + * ao_report.c + */ + +void +ao_report_init(void); + +/* + * ao_convert.c + * + * Given raw data, convert to SI units + */ + +/* pressure from the sensor to altitude in meters */ +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant; + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant; + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant; + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +/* + * ao_serial.c + */ + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_1 +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +void +ao_serial_rx1_isr(void) __interrupt 3; + +void +ao_serial_tx1_isr(void) __interrupt 14; + +char +ao_serial_getchar(void) __critical; + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical; + +void +ao_serial_set_stdin(uint8_t stdin); +#endif + +void +ao_serial_putchar(char c) __critical; + +void +ao_serial_drain(void) __critical; + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +void +ao_serial_set_speed(uint8_t speed); + +void +ao_serial_init(void); +#endif + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; +}; + +/* + * ao_gps.c + */ + +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +extern __pdata uint16_t ao_gps_tick; +extern __xdata uint8_t ao_gps_mutex; +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10â· */ + int32_t longitude; /* degrees * 10â· */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +void +ao_gps(void); + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data); + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); + +void +ao_gps_init(void); + +/* + * ao_gps_report.c + */ + +void +ao_gps_report(void); + +void +ao_gps_report_init(void); + +/* + * ao_telemetry_orig.c + */ + +struct ao_telemetry_orig { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t accel; + int16_t ground_accel; + union { + struct { + int16_t speed; + int16_t unused; + } k; + int32_t flight_vel; + } u; + int16_t height; + int16_t ground_pres; + int16_t accel_plus_g; + int16_t accel_minus_g; + struct ao_adc adc; + struct ao_gps_orig gps; + char callsign[AO_MAX_CALLSIGN]; + struct ao_gps_tracking_orig gps_tracking; +}; + +struct ao_telemetry_tiny { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t height; /* AGL in meters */ + int16_t speed; /* in m/s * 16 */ + int16_t accel; /* in m/s² * 16 */ + int16_t ground_pres; /* sensor units */ + struct ao_adc adc; /* raw ADC readings */ + char callsign[AO_MAX_CALLSIGN]; +}; + +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + +struct ao_telemetry_orig_recv { + struct ao_telemetry_orig telemetry_orig; + int8_t rssi; + uint8_t status; +}; + +struct ao_telemetry_tiny_recv { + struct ao_telemetry_tiny telemetry_tiny; + int8_t rssi; + uint8_t status; +}; + +/* Set delay between telemetry reports (0 to disable) */ + +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) + +void +ao_telemetry_set_interval(uint16_t interval); + +void +ao_rdf_set(uint8_t rdf); + +void +ao_telemetry_init(void); + +void +ao_telemetry_orig_init(void); + +void +ao_telemetry_tiny_init(void); + +/* + * ao_radio.c + */ + +extern __xdata uint8_t ao_radio_dma; +extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_done; +extern __xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) __interrupt 16; + +void +ao_radio_get(uint8_t len); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +void +ao_radio_set_packet(void); + +void +ao_radio_send(__xdata void *data, uint8_t size) __reentrant; + +uint8_t +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; + +void +ao_radio_recv_abort(void); + +void +ao_radio_rdf(int ms); + +void +ao_radio_rdf_abort(void); + +void +ao_radio_idle(void); + +void +ao_radio_init(void); + +/* + * ao_monitor.c + */ + +extern const char const * const ao_state_names[]; + +void +ao_monitor(void); + +#define AO_MONITORING_OFF 0 +#define AO_MONITORING_ORIG 1 +#define AO_MONITORING_TINY 2 + +void +ao_set_monitor(uint8_t monitoring); + +void +ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; + +/* + * ao_stdio.c + */ + +#define AO_READ_AGAIN ((char) -1) + +struct ao_stdio { + char (*pollchar)(void); + void (*putchar)(char c) __reentrant; + void (*flush)(void); + uint8_t echo; +}; + +extern __xdata struct ao_stdio ao_stdios[]; +extern __pdata int8_t ao_cur_stdio; +extern __pdata int8_t ao_num_stdios; + +void +flush(void); + +extern __xdata uint8_t ao_stdin_ready; + +uint8_t +ao_echo(void); + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char) __reentrant, + void (*flush)(void)) __reentrant; + +/* + * ao_ignite.c + */ + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter); + +enum ao_igniter_status { + ao_igniter_unknown, /* unknown status (ambiguous voltage) */ + ao_igniter_ready, /* continuity detected */ + ao_igniter_active, /* igniter firing */ + ao_igniter_open, /* open circuit detected */ +}; + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter); + +void +ao_ignite_set_pins(void); + +void +ao_igniter_init(void); + +/* + * ao_config.c + */ + +#define AO_CONFIG_MAJOR 1 +#define AO_CONFIG_MINOR 8 + +struct ao_config { + uint8_t major; + uint8_t minor; + uint16_t main_deploy; + int16_t accel_plus_g; /* changed for minor version 2 */ + uint8_t radio_channel; + char callsign[AO_MAX_CALLSIGN + 1]; + uint8_t apogee_delay; /* minor version 1 */ + int16_t accel_minus_g; /* minor version 2 */ + uint32_t radio_cal; /* minor version 3 */ + uint32_t flight_log_max; /* minor version 4 */ + uint8_t ignite_mode; /* minor version 5 */ + uint8_t pad_orientation; /* minor version 6 */ + uint32_t radio_setting; /* minor version 7 */ + uint8_t radio_enable; /* minor version 8 */ +}; + +#define AO_IGNITE_MODE_DUAL 0 +#define AO_IGNITE_MODE_APOGEE 1 +#define AO_IGNITE_MODE_MAIN 2 + +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + +extern __xdata struct ao_config ao_config; + +#define AO_CONFIG_MAX_SIZE 128 + +void +ao_config_get(void); + +void +ao_config_put(void); + +void +ao_config_init(void); + +/* + * ao_rssi.c + */ + +void +ao_rssi_set(int rssi_value); + +void +ao_rssi_init(uint8_t rssi_led); + +/* + * ao_product.c + * + * values which need to be defined for + * each instance of a product + */ + +extern const char ao_version[]; +extern const char ao_manufacturer[]; +extern const char ao_product[]; + +/* + * Fifos + */ + +#define AO_FIFO_SIZE 32 + +struct ao_fifo { + uint8_t insert; + uint8_t remove; + char fifo[AO_FIFO_SIZE]; +}; + +#define ao_fifo_insert(f,c) do { \ + (f).fifo[(f).insert] = (c); \ + (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_remove(f,c) do {\ + c = (f).fifo[(f).remove]; \ + (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) +#define ao_fifo_empty(f) ((f).insert == (f).remove) + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); + +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; + +void +ao_btm_init(void); + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + +#endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c new file mode 100644 index 00000000..1442ebea --- /dev/null +++ b/src/core/ao_cmd.c @@ -0,0 +1,320 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint16_t ao_cmd_lex_i; +__pdata uint32_t ao_cmd_lex_u32; +__pdata char ao_cmd_lex_c; +__pdata enum ao_cmd_status ao_cmd_status; + +#define CMD_LEN 32 + +static __xdata char cmd_line[CMD_LEN]; +static __pdata uint8_t cmd_len; +static __pdata uint8_t cmd_i; + +static void +put_string(__code char *s) +{ + char c; + while (c = *s++) + putchar(c); +} + +static void +readline(void) +{ + __pdata char c; + if (ao_echo()) + put_string("> "); + cmd_len = 0; + for (;;) { + flush(); + c = getchar(); + /* backspace/delete */ + if (c == '\010' || c == '\177') { + if (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* ^U */ + if (c == '\025') { + while (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* map CR to NL */ + if (c == '\r') + c = '\n'; + + if (c == '\n') { + if (ao_echo()) + putchar('\n'); + break; + } + + if (cmd_len >= CMD_LEN - 2) { + if (ao_echo()) + putchar('\007'); + continue; + } + cmd_line[cmd_len++] = c; + if (ao_echo()) + putchar(c); + } + cmd_line[cmd_len++] = '\n'; + cmd_line[cmd_len++] = '\0'; + cmd_i = 0; +} + +void +ao_cmd_lex(void) +{ + ao_cmd_lex_c = '\n'; + if (cmd_i < cmd_len) + ao_cmd_lex_c = cmd_line[cmd_i++]; +} + +static void +putnibble(uint8_t v) +{ + if (v < 10) + putchar(v + '0'); + else + putchar(v + ('a' - 10)); +} + +void +ao_cmd_put16(uint16_t v) +{ + ao_cmd_put8(v >> 8); + ao_cmd_put8(v); +} + +void +ao_cmd_put8(uint8_t v) +{ + putnibble((v >> 4) & 0xf); + putnibble(v & 0xf); +} + +void +ao_cmd_white(void) +{ + while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + ao_cmd_lex(); +} + +void +ao_cmd_hex(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + uint8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + n = (ao_cmd_lex_c - '0'); + else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + n = (ao_cmd_lex_c - 'a' + 10); + else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + n = (ao_cmd_lex_c - 'A' + 10); + else + break; + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; +} + +void +ao_cmd_decimal(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + + ao_cmd_lex_u32 = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); + else + break; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; + ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; +} + +uint8_t +ao_match_word(__code char *word) +{ + while (*word) { + if (ao_cmd_lex_c != *word) { + ao_cmd_status = ao_cmd_syntax_error; + return 0; + } + word++; + ao_cmd_lex(); + } + return 1; +} + +static void +eol(void) +{ + while (ao_cmd_lex_c != '\n') + ao_cmd_lex(); +} + +static void +echo(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) + ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; +} + +static void +ao_reboot(void) +{ + ao_cmd_white(); + if (!ao_match_word("eboot")) + return; + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; + ao_delay(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} + +static void +version(void) +{ + printf("manufacturer %s\n", ao_manufacturer); + printf("product %s\n", ao_product); + printf("serial-number %u\n", ao_serial_number); +#if HAS_EEPROM + printf("log-format %u\n", ao_log_format); +#endif + printf("software-version %s\n", ao_version); +} + +#define NUM_CMDS 11 + +static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); +static __pdata uint8_t ao_ncmds; + +static void +help(void) +{ + register uint8_t cmds; + register uint8_t cmd; + register __code struct ao_cmds * cs; + + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + printf("%-45s %s\n", + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); + } +} + +static void +report(void) +{ + switch(ao_cmd_status) { + case ao_cmd_lex_error: + case ao_cmd_syntax_error: + puts("Syntax error"); + ao_cmd_status = 0; + break; + } +} + +void +ao_cmd_register(__code struct ao_cmds *cmds) +{ + if (ao_ncmds >= NUM_CMDS) + ao_panic(AO_PANIC_CMD); + ao_cmds[ao_ncmds++] = cmds; +} + +void +ao_cmd(void) +{ + char c; + uint8_t cmd, cmds; + __code struct ao_cmds * __xdata cs; + void (*__xdata func)(void); + + for (;;) { + readline(); + ao_cmd_lex(); + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + if (c == '\r' || c == '\n') + continue; + func = (void (*)(void)) NULL; + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + if (cs[cmd].help[0] == c) { + func = cs[cmd].func; + break; + } + if (func) + break; + } + if (func) + (*func)(); + else + ao_cmd_status = ao_cmd_syntax_error; + report(); + } +} + +__xdata struct ao_task ao_cmd_task; + +__code struct ao_cmds ao_base_cmds[] = { + { help, "?\0Help" }, + { ao_task_info, "T\0Show tasks" }, + { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_reboot, "r eboot\0Reboot" }, + { version, "v\0Version" }, + { 0, NULL }, +}; + +void +ao_cmd_init(void) +{ + ao_cmd_register(&ao_base_cmds[0]); + ao_add_task(&ao_cmd_task, ao_cmd, "cmd"); +} diff --git a/src/core/ao_config.c b/src/core/ao_config.c new file mode 100644 index 00000000..0c10e608 --- /dev/null +++ b/src/core/ao_config.c @@ -0,0 +1,542 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +__xdata struct ao_config ao_config; +__pdata uint8_t ao_config_loaded; +__pdata uint8_t ao_config_dirty; +__xdata uint8_t ao_config_mutex; + +#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 +#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 +#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" +#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 +#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL +#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif +#if USE_INTERNAL_FLASH +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config +#else +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) +#endif + +#if HAS_EEPROM +static void +_ao_config_put(void) +{ + ao_storage_setup(); + ao_storage_erase(ao_storage_config); + ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_log_write_erase(0); + ao_storage_flush(); +} + +void +ao_config_put(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_put(); + ao_mutex_put(&ao_config_mutex); +} +#endif + +static void +_ao_config_get(void) +{ + if (ao_config_loaded) + return; +#if HAS_EEPROM + ao_storage_setup(); + ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); +#endif + if (ao_config.major != AO_CONFIG_MAJOR) { + ao_config.major = AO_CONFIG_MAJOR; + ao_config.minor = 0; + ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; + ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; + memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + } + if (ao_config.minor < AO_CONFIG_MINOR) { + /* Fixups for minor version 1 */ + if (ao_config.minor < 1) + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + /* Fixups for minor version 2 */ + if (ao_config.minor < 2) { + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } + /* Fixups for minor version 3 */ + if (ao_config.minor < 3) + ao_config.radio_cal = ao_radio_cal; + /* Fixups for minor version 4 */ + if (ao_config.minor < 4) + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + /* Fixupes for minor version 5 */ + if (ao_config.minor < 5) + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + if (ao_config.minor < 6) + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + if (ao_config.minor < 7) + ao_config.radio_setting = ao_config.radio_cal; + if (ao_config.minor < 8) + ao_config.radio_enable = TRUE; + ao_config.minor = AO_CONFIG_MINOR; + ao_config_dirty = 1; + } + ao_config_loaded = 1; +} + +static void +_ao_config_edit_start(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); +} + +static void +_ao_config_edit_finish(void) +{ + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_get(void) +{ + _ao_config_edit_start(); + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_callsign_show(void) +{ + printf ("Callsign: \"%s\"\n", ao_config.callsign); +} + +void +ao_config_callsign_set(void) __reentrant +{ + uint8_t c; + static __xdata char callsign[AO_MAX_CALLSIGN + 1]; + + memset(callsign, '\0', sizeof callsign); + ao_cmd_white(); + c = 0; + while (ao_cmd_lex_c != '\n') { + if (c < AO_MAX_CALLSIGN) + callsign[c++] = ao_cmd_lex_c; + else + ao_cmd_status = ao_cmd_lex_error; + ao_cmd_lex(); + } + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + memcpy(&ao_config.callsign, &callsign, + AO_MAX_CALLSIGN + 1); + _ao_config_edit_finish(); +} + +void +ao_config_radio_channel_show(void) __reentrant +{ + printf("Radio channel: %d\n", + ao_config.radio_channel); +} + +void +ao_config_radio_channel_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_channel = ao_cmd_lex_i; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +#if HAS_ADC + +void +ao_config_main_deploy_show(void) __reentrant +{ + printf("Main deploy: %d meters\n", + ao_config.main_deploy); +} + +void +ao_config_main_deploy_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.main_deploy = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#if HAS_ACCEL +void +ao_config_accel_calibrate_show(void) __reentrant +{ + printf("Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); +} + +#define ACCEL_CALIBRATE_SAMPLES 1024 +#define ACCEL_CALIBRATE_SHIFT 10 + +static int16_t +ao_config_accel_calibrate_auto(char *orientation) __reentrant +{ + uint16_t i; + int32_t accel_total; + uint8_t cal_adc_ring; + + printf("Orient antenna %s and press a key...", orientation); + flush(); + (void) getchar(); + puts("\r\n"); flush(); + puts("Calibrating..."); flush(); + i = ACCEL_CALIBRATE_SAMPLES; + accel_total = 0; + cal_adc_ring = ao_sample_adc; + while (i) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (i && cal_adc_ring != ao_sample_adc) { + accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; + cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + i--; + } + } + return accel_total >> ACCEL_CALIBRATE_SHIFT; +} + +void +ao_config_accel_calibrate_set(void) __reentrant +{ + int16_t up, down; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i == 0) { + up = ao_config_accel_calibrate_auto("up"); + down = ao_config_accel_calibrate_auto("down"); + } else { + up = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + down = ao_cmd_lex_i; + } + if (up >= down) { + printf("Invalid accel: up (%d) down (%d)\n", + up, down); + return; + } + _ao_config_edit_start(); + ao_config.accel_plus_g = up; + ao_config.accel_minus_g = down; + _ao_config_edit_finish(); +} +#endif /* HAS_ACCEL */ + +void +ao_config_apogee_delay_show(void) __reentrant +{ + printf("Apogee delay: %d seconds\n", + ao_config.apogee_delay); +} + +void +ao_config_apogee_delay_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_delay = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_ADC */ + +void +ao_config_radio_cal_show(void) __reentrant +{ + printf("Radio cal: %ld\n", ao_config.radio_cal); +} + +void +ao_config_radio_cal_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} + +#if HAS_EEPROM +void +ao_config_log_show(void) __reentrant +{ + printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +} + +void +ao_config_log_set(void) __reentrant +{ + uint16_t block = (uint16_t) (ao_storage_block >> 10); + uint16_t config = (uint16_t) (ao_storage_config >> 10); + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_log_present()) + printf("Storage must be empty before changing log size\n"); + else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) + printf("Flight log size must be multiple of %d kB\n", block); + else if (ao_cmd_lex_i > config) + printf("Flight log max %d kB\n", config); + else { + _ao_config_edit_start(); + ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; + _ao_config_edit_finish(); + } +} +#endif /* HAS_EEPROM */ + +#if HAS_IGNITE +void +ao_config_ignite_mode_show(void) __reentrant +{ + printf("Ignite mode: %d\n", ao_config.ignite_mode); +} + +void +ao_config_ignite_mode_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.ignite_mode = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +#if HAS_ACCEL +void +ao_config_pad_orientation_show(void) __reentrant +{ + printf("Pad orientation: %d\n", ao_config.pad_orientation); +} + +void +ao_config_pad_orientation_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_cmd_lex_i &= 1; + if (ao_config.pad_orientation != ao_cmd_lex_i) { + uint16_t t; + t = ao_config.accel_plus_g; + ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; + ao_config.accel_minus_g = 0x7fff - t; + } + ao_config.pad_orientation = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +void +ao_config_radio_setting_show(void) __reentrant +{ + printf("Radio setting: %ld\n", ao_config.radio_setting); +} + +void +ao_config_radio_setting_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_cmd_lex_u32; + ao_config.radio_channel = 0; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +void +ao_config_radio_enable_show(void) __reentrant +{ + printf("Radio enable: %d\n", ao_config.radio_enable); +} + +void +ao_config_radio_enable_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_enable = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +struct ao_config_var { + __code char *str; + void (*set)(void) __reentrant; + void (*show)(void) __reentrant; +}; + +static void +ao_config_help(void) __reentrant; + +static void +ao_config_show(void) __reentrant; + +static void +ao_config_write(void) __reentrant; + +__code struct ao_config_var ao_config_vars[] = { +#if HAS_ADC + { "m \0Main deploy (in meters)", + ao_config_main_deploy_set, ao_config_main_deploy_show, }, + { "d \0Apogee delay (in seconds)", + ao_config_apogee_delay_set, ao_config_apogee_delay_show }, +#endif /* HAS_ADC */ + { "r \0Radio channel (freq = 434.550 + chan * .1)", + ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "c \0Callsign (8 char max)", + ao_config_callsign_set, ao_config_callsign_show }, + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, + { "e <0 disable, 1 enable>\0Enable telemetry and RDF", + ao_config_radio_enable_set, ao_config_radio_enable_show }, +#if HAS_ACCEL + { "a <+g> <-g>\0Accel calib (0 for auto)", + ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, +#endif /* HAS_ACCEL */ + { "f \0Radio calib (cal = rf/(xtal/2^16))", + ao_config_radio_cal_set, ao_config_radio_cal_show }, +#if HAS_EEPROM + { "l \0Flight log size in kB", + ao_config_log_set, ao_config_log_show }, +#endif +#if HAS_IGNITE + { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", + ao_config_ignite_mode_set, ao_config_ignite_mode_show }, +#endif +#if HAS_ACCEL + { "o <0 antenna up, 1 antenna down>\0Set pad orientation", + ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif + { "s\0Show", + ao_config_show, 0 }, +#if HAS_EEPROM + { "w\0Write to eeprom", + ao_config_write, 0 }, +#endif + { "?\0Help", + ao_config_help, 0 }, + { 0, 0, 0 } +}; + +void +ao_config_set(void) +{ + char c; + uint8_t cmd; + void (*__xdata func)(void) __reentrant; + + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + func = 0; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].str[0] == c) { + (*ao_config_vars[cmd].set)(); + return; + } + ao_cmd_status = ao_cmd_syntax_error; +} + +static void +ao_config_help(void) __reentrant +{ + uint8_t cmd; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + printf("%-20s %s\n", + ao_config_vars[cmd].str, + ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); +} + +static void +ao_config_show(void) __reentrant +{ + uint8_t cmd; + printf("Config version: %d.%d\n", + ao_config.major, ao_config.minor); + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].show) + (*ao_config_vars[cmd].show)(); +} + +#if HAS_EEPROM +static void +ao_config_write(void) __reentrant +{ + uint8_t saved = 0; + ao_mutex_get(&ao_config_mutex); + if (ao_config_dirty) { + _ao_config_put(); + ao_config_dirty = 0; + saved = 1; + } + ao_mutex_put(&ao_config_mutex); + if (saved) + puts("Saved"); + else + puts("Nothing to save"); +} +#endif + +__code struct ao_cmds ao_config_cmds[] = { + { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { 0, NULL }, +}; + +void +ao_config_init(void) +{ + ao_cmd_register(&ao_config_cmds[0]); +} diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c new file mode 100644 index 00000000..0969f107 --- /dev/null +++ b/src/core/ao_convert.c @@ -0,0 +1,85 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int16_t altitude_table[] = { +#include "altitude.h" +}; + +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant +{ + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; +} + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant +{ + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; +} + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant +{ + int16_t ret; + + /* Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + * ≃ (value - 19791) * 1012 / 65536 + */ + ret = ((temp - 19791) * 1012L) >> 16; + return ret; +} diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c new file mode 100644 index 00000000..e2c28b73 --- /dev/null +++ b/src/core/ao_convert_test.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert.c" + +#define STEP 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int16_t p_to_a, p_to_a_to_p; + int16_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 32767 + STEP; i += STEP) { + if (i > 32767) + i = 32767; + p_to_a = ao_pres_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pres(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pres %d alt %d pres %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1578; i < 15835 + STEP; i += STEP) { + if (i > 15835) + i = 15835; + a_to_p = ao_altitude_to_pres(i); + a_to_p_to_a = ao_pres_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pres %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c new file mode 100644 index 00000000..b0c1d61e --- /dev/null +++ b/src/core/ao_ee_fake.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +/* + * For hardware without eeprom, the config code still + * wants to call these functions + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + (void) buf; + (void) len; + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + memset(buf, '\0', len); + return 1; +} diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..85c1825b --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,315 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#endif + case ao_flight_coast: + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); + + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { + ao_ignite(ao_igniter_main); + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c new file mode 100644 index 00000000..2e332b12 --- /dev/null +++ b/src/core/ao_flight_nano.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; + +__pdata uint8_t ao_flight_force_idle; + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) + +static void +ao_flight_nano(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + + for (;;) { + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + if (ao_flight_force_idle) { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + } else { + ao_flight_state = ao_flight_pad; + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + } + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; + case ao_flight_pad: + if (ao_height> AO_M_TO_HEIGHT(20)) { + ao_flight_state = ao_flight_drogue; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + /* drogue/main to land: + * + * barometer: altitude stable + */ + + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_nano_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight_nano, "flight"); +} diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c new file mode 100644 index 00000000..fcdedd30 --- /dev/null +++ b/src/core/ao_gps_print.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif +#include "ao_telem.h" + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant +{ + char state; + + if (gps_data->flags & AO_GPS_VALID) + state = AO_TELEM_GPS_STATE_LOCKED; + else if (gps_data->flags & AO_GPS_RUNNING) + state = AO_TELEM_GPS_STATE_UNLOCKED; + else + state = AO_TELEM_GPS_STATE_ERROR; + printf(AO_TELEM_GPS_STATE " %c " + AO_TELEM_GPS_NUM_SAT " %d ", + state, + (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); + if (!(gps_data->flags & AO_GPS_VALID)) + return; + printf(AO_TELEM_GPS_LATITUDE " %ld " + AO_TELEM_GPS_LONGITUDE " %ld " + AO_TELEM_GPS_ALTITUDE " %d ", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); + + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(AO_TELEM_GPS_YEAR " %d " + AO_TELEM_GPS_MONTH " %d " + AO_TELEM_GPS_DAY " %d ", + gps_data->year, + gps_data->month, + gps_data->day); + + printf(AO_TELEM_GPS_HOUR " %d " + AO_TELEM_GPS_MINUTE " %d " + AO_TELEM_GPS_SECOND " %d ", + gps_data->hour, + gps_data->minute, + gps_data->second); + + printf(AO_TELEM_GPS_HDOP " %d ", + gps_data->hdop * 2); + + if (gps_data->flags & AO_GPS_COURSE_VALID) { + printf(AO_TELEM_GPS_HERROR " %d " + AO_TELEM_GPS_VERROR " %d " + AO_TELEM_GPS_VERTICAL_SPEED " %d " + AO_TELEM_GPS_HORIZONTAL_SPEED " %d " + AO_TELEM_GPS_COURSE " %d ", + gps_data->h_error, + gps_data->v_error, + gps_data->climb_rate, + gps_data->ground_speed, + (int) gps_data->course * 2); + } +} + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant +{ + uint8_t c, n, v; + __xdata struct ao_gps_sat_orig *sat; + + n = gps_tracking_data->channels; + if (n == 0) + return; + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) + v++; + sat++; + } + + printf (AO_TELEM_SAT_NUM " %d ", + v); + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) { + printf (AO_TELEM_SAT_SVID "%d %d " + AO_TELEM_SAT_C_N_0 "%d %d ", + v, sat->svid, + v, sat->c_n_1); + v++; + } + sat++; + } +} diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c new file mode 100644 index 00000000..e57f8744 --- /dev/null +++ b/src/core/ao_gps_report.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_gps_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LAT; + gps_log.u.gps_latitude = gps_data.latitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LON; + gps_log.u.gps_longitude = gps_data.longitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_ALT; + gps_log.u.gps_altitude.altitude = gps_data.altitude; + gps_log.u.gps_altitude.unused = 0xffff; + ao_log_data(&gps_log); + if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { + 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; + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); + } + } +} + +void +ao_gps_tracking_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + gps_log.tick = ao_gps_tick; + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + ao_log_data(&gps_log); + } + } +} + +__xdata struct ao_task ao_gps_report_task; +__xdata struct ao_task ao_gps_tracking_report_task; + +void +ao_gps_report_init(void) +{ + ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); + ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); +} diff --git a/src/core/ao_host.h b/src/core/ao_host.h new file mode 100644 index 00000000..65c25fe5 --- /dev/null +++ b/src/core/ao_host.h @@ -0,0 +1,127 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#define AO_ADC_RING 64 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + +/* + * One set of samples read from the A/D converter + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define __pdata +#define __data +#define __xdata +#define __code +#define __reentrant + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +struct ao_adc ao_adc_ring[AO_ADC_RING]; +uint8_t ao_adc_head; + +#define ao_led_on(l) +#define ao_led_off(l) +#define ao_timer_set_adc_interval(i) +#define ao_wakeup(wchan) ao_dump_state(wchan) +#define ao_cmd_register(c) +#define ao_usb_disable() +#define ao_telemetry_set_interval(x) +#define ao_delay(x) + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter) +{ + printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); +} + +struct ao_task { + int dummy; +}; + +#define ao_add_task(t,f,n) + +#define ao_log_start() +#define ao_log_stop() + +#define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_SEC_TO_TICKS(s) ((s) * 100) + +#define AO_FLIGHT_TEST + +struct ao_adc ao_adc_static; + +FILE *emulator_in; + +void +ao_dump_state(void *wchan); + +void +ao_sleep(void *wchan); + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + + +struct ao_config { + uint16_t main_deploy; + int16_t accel_zero_g; +}; + +#define ao_config_get() + +struct ao_config ao_config = { 250, 16000 }; diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c new file mode 100644 index 00000000..ee01949e --- /dev/null +++ b/src/core/ao_kalman.c @@ -0,0 +1,292 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#include "ao_kalman.h" + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +#define AO_K_STEP_1 to_fix16(1) +#define AO_K_STEP_2_2_1 to_fix16(0.5) + +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; +static __pdata int32_t ao_avg_height_scaled; +__pdata int16_t ao_avg_height; + +__pdata int16_t ao_error_h; +__pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +__pdata int16_t ao_error_a; +#endif + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + + (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; + + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static void +ao_kalman_err_height(void) +{ + int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + + ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +#endif + + if (ao_flight_state >= ao_flight_drogue) + return; + height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; +#if HAS_ACCEL + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust > 0) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif + } +} + +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; + return; + } +#endif + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; +} + +#if HAS_ACCEL + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_1 * ao_error_h + + (int32_t) AO_BOTH_K01_1 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_1 * ao_error_h + + (int32_t) AO_BOTH_K21_1 * ao_error_a; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) AO_BOTH_K01_10 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_10 * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +#ifdef FORCE_ACCEL +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif +#endif /* HAS_ACCEL */ + +void +ao_kalman(void) +{ + ao_kalman_predict(); +#if HAS_ACCEL + if (ao_flight_state <= ao_flight_coast) { +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); +#endif + } else +#endif + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) + ao_avg_height = (ao_avg_height_scaled + 1) >> 1; + else if (ao_sample_tick - ao_sample_prev_tick > 5) + ao_avg_height = (ao_avg_height_scaled + 7) >> 4; + else +#endif + ao_avg_height = (ao_avg_height_scaled + 63) >> 7; +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif +} diff --git a/src/core/ao_log.c b/src/core/ao_log.c new file mode 100644 index 00000000..6d3ad535 --- /dev/null +++ b/src/core/ao_log.c @@ -0,0 +1,284 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint32_t ao_log_current_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__pdata enum flight_state ao_log_state; +__xdata uint16_t ao_flight_number; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + +void +ao_log_flush(void) +{ + ao_storage_flush(); +} + +/* + * When erasing a flight log, make sure the config block + * has an up-to-date version of the current flight number + */ + +struct ao_log_erase { + uint8_t unused; + uint16_t flight; +}; + +static __xdata struct ao_log_erase erase; + +#define LOG_MAX_ERASE 16 + +static uint32_t +ao_log_erase_pos(uint8_t i) +{ + return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; +} + +void +ao_log_write_erase(uint8_t pos) +{ + erase.unused = 0x00; + erase.flight = ao_flight_number; + ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_storage_flush(); +} + +static void +ao_log_read_erase(uint8_t pos) +{ + ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + + +static void +ao_log_erase_mark(void) +{ + uint8_t i; + + for (i = 0; i < LOG_MAX_ERASE; i++) { + ao_log_read_erase(i); + if (erase.unused == 0 && erase.flight == ao_flight_number) + return; + if (erase.unused == 0xff) { + ao_log_write_erase(i); + return; + } + } + ao_config_put(); +} + +static uint8_t +ao_log_slots() +{ + return (uint8_t) (ao_storage_config / ao_config.flight_log_max); +} + +uint32_t +ao_log_pos(uint8_t slot) +{ + return ((slot) * ao_config.flight_log_max); +} + +static uint16_t +ao_log_max_flight(void) +{ + uint8_t log_slot; + uint8_t log_slots; + uint16_t log_flight; + uint16_t max_flight = 0; + + /* Scan the log space looking for the biggest flight number */ + log_slots = ao_log_slots(); + for (log_slot = 0; log_slot < log_slots; log_slot++) { + log_flight = ao_log_flight(log_slot); + if (!log_flight) + continue; + if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) + max_flight = log_flight; + } + return max_flight; +} + +void +ao_log_scan(void) __reentrant +{ + uint8_t log_slot; + uint8_t log_slots; + uint8_t log_want; + + ao_config_get(); + + ao_flight_number = ao_log_max_flight(); + if (ao_flight_number) + if (++ao_flight_number == 0) + ao_flight_number = 1; + + /* Now look through the log of flight numbers from erase operations and + * see if the last one is bigger than what we found above + */ + for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { + ao_log_read_erase(log_slot); + if (erase.unused == 0) { + if (ao_flight_number == 0 || + (int16_t) (erase.flight - ao_flight_number) > 0) + ao_flight_number = erase.flight; + break; + } + } + if (ao_flight_number == 0) + ao_flight_number = 1; + + /* With a flight number in hand, find a place to write a new log, + * use the target flight number to index the available log slots so + * that we write logs to each spot about the same number of times. + */ + + /* Find a log slot for the next flight, if available */ + ao_log_current_pos = ao_log_end_pos = 0; + log_slots = ao_log_slots(); + log_want = (ao_flight_number - 1) % log_slots; + log_slot = log_want; + do { + if (ao_log_flight(log_slot) == 0) { + ao_log_current_pos = ao_log_pos(log_slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + break; + } + if (++log_slot >= log_slots) + log_slot = 0; + } while (log_slot != log_want); + + ao_wakeup(&ao_flight_number); +} + +void +ao_log_start(void) +{ + /* start logging */ + ao_log_running = 1; + ao_wakeup(&ao_log_running); +} + +void +ao_log_stop(void) +{ + ao_log_running = 0; + ao_log_flush(); +} + +uint8_t +ao_log_present(void) +{ + return ao_log_max_flight() != 0; +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos == ao_log_end_pos; +} + +static __xdata struct ao_task ao_log_task; + +void +ao_log_list(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + uint16_t flight; + + slots = ao_log_slots(); + for (slot = 0; slot < slots; slot++) + { + flight = ao_log_flight(slot); + if (flight) + printf ("flight %d start %x end %x\n", + flight, + (uint16_t) (ao_log_pos(slot) >> 8), + (uint16_t) (ao_log_pos(slot+1) >> 8)); + } + printf ("done\n"); +} + +void +ao_log_delete(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + + slots = ao_log_slots(); + /* Look for the flight log matching the requested flight */ + if (ao_cmd_lex_i) { + for (slot = 0; slot < slots; slot++) { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + while (ao_log_current_pos < ao_log_end_pos) { + uint8_t i; + static __xdata uint8_t b; + + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + for (i = 0; i < 16; i++) { + if (ao_storage_read(ao_log_current_pos + i, &b, 1)) + if (b != 0xff) + break; + } + if (i == 16) + break; + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } + puts("Erased"); + return; + } + } + } + printf("No such flight: %d\n", ao_cmd_lex_i); +} + +__code struct ao_cmds ao_log_cmds[] = { + { ao_log_list, "l\0List flight logs" }, + { ao_log_delete, "d \0Delete flight" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + /* For now, just log the flight starting at the begining of eeprom */ + ao_log_state = ao_flight_invalid; + + ao_cmd_register(&ao_log_cmds[0]); + + /* Create a task to log events to eeprom */ + ao_add_task(&ao_log_task, ao_log, "log"); +} diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c new file mode 100644 index 00000000..74d94c4b --- /dev/null +++ b/src/core/ao_log_big.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_record log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +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_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); + ao_log_current_pos += sizeof (struct ao_log_record); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_adc_pos; + +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.flight = ao_flight_number; + ao_log_data(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); + next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_sample_adc) { + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; + log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + ao_log_data(&log); + log.type = AO_LOG_DEPLOY; + log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; + log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + ao_log_data(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_sample_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_record))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c new file mode 100644 index 00000000..1b472efe --- /dev/null +++ b/src/core/ao_log_telem.c @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +ao_log_write_erase(uint8_t pos) +{ + (void) pos; +} + +uint8_t +ao_log_present(void) +{ + return 0; +} diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c new file mode 100644 index 00000000..d5a3b99f --- /dev/null +++ b/src/core/ao_log_tiny.c @@ -0,0 +1,161 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __data uint16_t ao_log_tiny_interval; + +#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) +#if USE_FAST_ASCENT_LOG +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_PAD_RING 8 +#else +#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT +#define AO_PAD_RING 2 +#endif + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; + +void +ao_log_tiny_set_interval(uint16_t ticks) +{ + ao_log_tiny_interval = ticks; +} + + +static void ao_log_tiny_data(uint16_t d) +{ + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); + ao_log_current_pos += 2; + } +} + +static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; +static __pdata uint8_t ao_log_pad_ring_pos; + +#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) + +static void ao_log_tiny_queue(uint16_t d) +{ + ao_log_pad_ring[ao_log_pad_ring_pos] = d; + ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); +} + +static void ao_log_tiny_start(void) +{ + uint8_t p; + uint16_t d; + + ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + p = ao_log_pad_ring_pos; + do { + d = ao_log_pad_ring[p]; + /* + * ignore unwritten slots + */ + if (d) + ao_log_tiny_data(d); + p = ao_pad_ring_next(p); + } while (p != ao_log_pad_ring_pos); +} + +void +ao_log(void) +{ + uint16_t last_time; + uint16_t now; + enum ao_flight_state ao_log_tiny_state; + int32_t sum; + int16_t count; + uint8_t ao_log_adc; + uint8_t ao_log_started = 0; + + ao_storage_setup(); + + ao_log_scan(); + + ao_log_tiny_state = ao_flight_invalid; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + sum = 0; + count = 0; + ao_log_adc = ao_sample_adc; + last_time = ao_time(); + for (;;) { + + /* + * Add in pending sample data + */ + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (ao_log_adc != ao_sample_adc) { + sum += ao_adc_ring[ao_log_adc].pres; + count++; + ao_log_adc = ao_adc_ring_next(ao_log_adc); + } + if (ao_log_running) { + if (!ao_log_started) { + ao_log_tiny_start(); + ao_log_started = 1; + } + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; +#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; +#endif + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); + } + } + + /* Stop logging when told to */ + if (!ao_log_running && ao_log_started) + ao_exit(); + + /* + * Write out the sample when finished + */ + now = ao_time(); + if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { + count = sum / count; + if (ao_log_started) + ao_log_tiny_data(count); + else + ao_log_tiny_queue(count); + sum = 0; + count = 0; + last_time = now; + } + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + static __xdata uint16_t flight; + + (void) slot; + ao_storage_read(0, &flight, 2); + if (flight == 0xffff) + flight = 0; + return flight; +} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c new file mode 100644 index 00000000..69eb58e8 --- /dev/null +++ b/src/core/ao_monitor.c @@ -0,0 +1,277 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_telem.h" + +#if !HAS_MONITOR +#error Must define HAS_MONITOR to 1 +#endif + +__xdata uint8_t ao_monitoring; +__pdata uint8_t ao_monitor_led; + +#define AO_MONITOR_RING 8 + +__xdata union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +} ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +__data uint8_t ao_monitor_head; + +void +ao_monitor_get(void) +{ + uint8_t size; + + for (;;) { + switch (ao_monitoring) { + case 0: + ao_sleep(&ao_monitoring); + continue; + case AO_MONITORING_ORIG: + size = sizeof (struct ao_telemetry_orig_recv); + break; + case AO_MONITORING_TINY: + size = sizeof (struct ao_telemetry_tiny_recv); + break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + size = ao_monitoring; + break; + } + if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) + continue; + ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_put(void) +{ + __xdata char callsign[AO_MAX_CALLSIGN+1]; + + uint8_t ao_monitor_tail; + uint8_t state; + uint8_t sum, byte; + int16_t rssi; + __xdata union ao_monitor *m; + +#define recv_raw ((m->raw)) +#define recv_orig ((m->orig)) +#define recv_tiny ((m->tiny)) + + ao_monitor_tail = ao_monitor_head; + for (;;) { + while (ao_monitor_tail == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + m = &ao_monitor_ring[ao_monitor_tail]; + ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); + switch (ao_monitoring) { + case AO_MONITORING_ORIG: + state = recv_orig.telemetry_orig.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { + + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_orig.telemetry_orig.serial, + recv_orig.telemetry_orig.flight, + rssi, + ao_state_names[state], + recv_orig.telemetry_orig.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_ACCEL " %d " + AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_orig.telemetry_orig.adc.accel, + recv_orig.telemetry_orig.adc.pres, + recv_orig.telemetry_orig.adc.temp, + recv_orig.telemetry_orig.adc.v_batt, + recv_orig.telemetry_orig.adc.sense_d, + recv_orig.telemetry_orig.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_ACCEL_GROUND " %d " + AO_TELEM_CAL_BARO_GROUND " %d " + AO_TELEM_CAL_ACCEL_PLUS " %d " + AO_TELEM_CAL_ACCEL_MINUS " %d ", + recv_orig.telemetry_orig.ground_accel, + recv_orig.telemetry_orig.ground_pres, + recv_orig.telemetry_orig.accel_plus_g, + recv_orig.telemetry_orig.accel_minus_g); + + if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv_orig.telemetry_orig.height, + recv_orig.telemetry_orig.u.k.speed, + recv_orig.telemetry_orig.accel); + } else { + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv_orig.telemetry_orig.accel, + recv_orig.telemetry_orig.u.flight_vel, + recv_orig.telemetry_orig.height); + } + ao_gps_print(&recv_orig.telemetry_orig.gps); + ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); + putchar('\n'); + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + case AO_MONITORING_TINY: + state = recv_tiny.telemetry_tiny.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; + memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_tiny.telemetry_tiny.serial, + recv_tiny.telemetry_tiny.flight, + rssi, + ao_state_names[state], + recv_tiny.telemetry_tiny.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_tiny.telemetry_tiny.adc.pres, + recv_tiny.telemetry_tiny.adc.temp, + recv_tiny.telemetry_tiny.adc.v_batt, + recv_tiny.telemetry_tiny.adc.sense_d, + recv_tiny.telemetry_tiny.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_BARO_GROUND " %d ", + recv_tiny.telemetry_tiny.ground_pres); + +#if 1 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d\n", + recv_tiny.telemetry_tiny.height, + recv_tiny.telemetry_tiny.speed, + recv_tiny.telemetry_tiny.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d\n", + recv_tiny.telemetry_tiny.flight_accel, + recv_tiny.telemetry_tiny.flight_vel, + recv_tiny.telemetry_tiny.flight_pres); +#endif + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + default: + printf ("TELEM %02x", ao_monitoring + 2); + sum = 0x5a; + for (state = 0; state < ao_monitoring + 2; state++) { + byte = recv_raw.packet[state]; + sum += byte; + printf("%02x", byte); + } + printf("%02x\n", sum); + break; + } + ao_usb_flush(); + } +} + +__xdata struct ao_task ao_monitor_get_task; +__xdata struct ao_task ao_monitor_put_task; + +void +ao_set_monitor(uint8_t monitoring) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + ao_monitoring = monitoring; + ao_wakeup(&ao_monitoring); +} + +static void +set_monitor(void) +{ + ao_cmd_hex(); + ao_set_monitor(ao_cmd_lex_i); +} + +__code struct ao_cmds ao_monitor_cmds[] = { + { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { 0, NULL }, +}; + +void +ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +{ + ao_monitor_led = monitor_led; + ao_monitoring = monitoring; + ao_cmd_register(&ao_monitor_cmds[0]); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); + ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +} diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c new file mode 100644 index 00000000..c82a7d57 --- /dev/null +++ b/src/core/ao_mutex.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_mutex_get(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex == ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + while (*mutex) + ao_sleep(mutex); + *mutex = ao_cur_task->task_id; + } +} + +void +ao_mutex_put(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex != ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + *mutex = 0; + ao_wakeup(mutex); + } +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c new file mode 100644 index 00000000..fdada201 --- /dev/null +++ b/src/core/ao_panic.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +#ifndef HAS_BEEP +#error Please define HAS_BEEP +#endif + +#if !HAS_BEEP +#define ao_beep(x) +#endif + +static void +ao_panic_delay(uint8_t n) +{ + uint8_t i = 0, j = 0; + + while (n--) + while (--j) + while (--i) + _asm nop _endasm; +} + +void +ao_panic(uint8_t reason) +{ + uint8_t n; + + __critical for (;;) { + ao_panic_delay(20); + for (n = 0; n < 5; n++) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_HIGH); + ao_panic_delay(1); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_LOW); + ao_panic_delay(1); + } + ao_beep(AO_BEEP_OFF); + ao_panic_delay(2); +#pragma disable_warning 126 + for (n = 0; n < reason; n++) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_MID); + ao_panic_delay(10); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_OFF); + ao_panic_delay(10); + } + } +} diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h new file mode 100644 index 00000000..e1f5459f --- /dev/null +++ b/src/core/ao_pins.h @@ -0,0 +1,408 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_product.c b/src/core/ao_product.c new file mode 100644 index 00000000..fb59580b --- /dev/null +++ b/src/core/ao_product.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +/* Defines which mark this particular AltOS product */ + +const char ao_version[AO_MAX_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)) + +#if HAS_USB +#include "ao_usb.h" +/* USB descriptors in one giant block of bytes */ +__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +{ + /* Device descriptor */ + 0x12, + AO_USB_DESC_DEVICE, + LE_WORD(0x0110), /* bcdUSB */ + 0x02, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ + LE_WORD(0xFFFE), /* idVendor */ + LE_WORD(AO_idProduct_NUMBER), /* idProduct */ + LE_WORD(0x0100), /* bcdDevice */ + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x03, /* iSerialNumber */ + 0x01, /* bNumConfigurations */ + + /* Configuration descriptor */ + 0x09, + AO_USB_DESC_CONFIGURATION, + LE_WORD(67), /* wTotalLength */ + 0x02, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ + 0xC0, /* bmAttributes */ + 0x32, /* bMaxPower */ + + /* Control class interface */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x01, /* bNumEndPoints */ + 0x02, /* bInterfaceClass */ + 0x02, /* bInterfaceSubClass */ + 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ + 0x00, /* iInterface */ + + /* Header functional descriptor */ + 0x05, + CS_INTERFACE, + 0x00, /* bDescriptor SubType Header */ + LE_WORD(0x0110), /* CDC version 1.1 */ + + /* Call management functional descriptor */ + 0x05, + CS_INTERFACE, + 0x01, /* bDescriptor SubType Call Management */ + 0x01, /* bmCapabilities = device handles call management */ + 0x01, /* bDataInterface call management interface number */ + + /* ACM functional descriptor */ + 0x04, + CS_INTERFACE, + 0x02, /* bDescriptor SubType Abstract Control Management */ + 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ + + /* Union functional descriptor */ + 0x05, + CS_INTERFACE, + 0x06, /* bDescriptor SubType Union Functional descriptor */ + 0x00, /* bMasterInterface */ + 0x01, /* bSlaveInterface0 */ + + /* Notification EP */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_INT_EP|0x80, /* bEndpointAddress */ + 0x03, /* bmAttributes = intr */ + LE_WORD(8), /* wMaxPacketSize */ + 0x0A, /* bInterval */ + + /* Data class interface descriptor */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x01, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndPoints */ + 0x0A, /* bInterfaceClass = data */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Data EP OUT */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* Data EP in */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_IN_EP|0x80, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* String descriptors */ + 0x04, + AO_USB_DESC_STRING, + LE_WORD(0x0409), + + /* iManufacturer */ + AO_iManufacturer_LEN, + AO_USB_DESC_STRING, + AO_iManufacturer_UCS2, + + /* iProduct */ + AO_iProduct_LEN, + AO_USB_DESC_STRING, + AO_iProduct_UCS2, + + /* iSerial */ + AO_iSerial_LEN, + AO_USB_DESC_STRING, + AO_iSerial_UCS2, + + /* Terminating zero */ + 0 +}; +#endif diff --git a/src/core/ao_report.c b/src/core/ao_report.c new file mode 100644 index 00000000..3cf558e1 --- /dev/null +++ b/src/core/ao_report.c @@ -0,0 +1,180 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +#define BIT(i,x) ((x) ? (1 << (i)) : 0) +#define MORSE1(a) (1 | BIT(3,a)) +#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) +#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) +#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) +#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) + +static const uint8_t flight_reports[] = { + MORSE3(0,0,0), /* startup, 'S' */ + MORSE2(0,0), /* idle 'I' */ + MORSE4(0,1,1,0), /* pad 'P' */ + MORSE4(1,0,0,0), /* boost 'B' */ + MORSE4(0,0,1,0), /* fast 'F' */ + MORSE4(1,0,1,0), /* coast 'C' */ + MORSE3(1,0,0), /* drogue 'D' */ + MORSE2(1,1), /* main 'M' */ + MORSE4(0,1,0,0), /* landed 'L' */ + MORSE4(1,0,0,1), /* invalid 'X' */ +}; + +#if HAS_BEEP +#define low(time) ao_beep_for(AO_BEEP_LOW, time) +#define mid(time) ao_beep_for(AO_BEEP_MID, time) +#define high(time) ao_beep_for(AO_BEEP_HIGH, time) +#else +#define low(time) ao_led_for(AO_LED_GREEN, time) +#define mid(time) ao_led_for(AO_LED_RED, time) +#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) +#endif +#define pause(time) ao_delay(time) + +static __pdata enum ao_flight_state ao_report_state; + +static void +ao_report_beep(void) __reentrant +{ + uint8_t r = flight_reports[ao_flight_state]; + uint8_t l = r & 7; + + if (!r) + return; + while (l--) { + if (r & 8) + mid(AO_MS_TO_TICKS(600)); + else + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + r >>= 1; + } + pause(AO_MS_TO_TICKS(400)); +} + +static void +ao_report_digit(uint8_t digit) __reentrant +{ + if (!digit) { + mid(AO_MS_TO_TICKS(500)); + pause(AO_MS_TO_TICKS(200)); + } else { + while (digit--) { + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + } + } + pause(AO_MS_TO_TICKS(300)); +} + +static void +ao_report_altitude(void) +{ + __pdata int16_t agl = ao_max_height; + __xdata uint8_t digits[10]; + __pdata uint8_t ndigits, i; + + if (agl < 0) + agl = 0; + ndigits = 0; + do { + digits[ndigits++] = agl % 10; + agl /= 10; + } while (agl); + + for (;;) { + ao_report_beep(); + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); + pause(AO_SEC_TO_TICKS(5)); + } +} + +#if HAS_IGNITE +static uint8_t +ao_report_igniter_ready(enum ao_igniter igniter) +{ + return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; +} + +static void +ao_report_continuity(void) __reentrant +{ + uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); + if (c) { + while (c--) { + high(AO_MS_TO_TICKS(25)); + pause(AO_MS_TO_TICKS(100)); + } + } else { + c = 10; + while (c--) { + high(AO_MS_TO_TICKS(20)); + low(AO_MS_TO_TICKS(20)); + } + } + if (ao_log_full()) { + pause(AO_MS_TO_TICKS(100)); + c = 2; + while (c--) { + low(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + high(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + } + } + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); +} +#endif + +void +ao_report(void) +{ + ao_report_state = ao_flight_state; + for(;;) { + if (ao_flight_state == ao_flight_landed) + ao_report_altitude(); + ao_report_beep(); +#if HAS_IGNITE + if (ao_flight_state == ao_flight_idle) + ao_report_continuity(); + while (ao_flight_state == ao_flight_pad) + ao_report_continuity(); +#endif + __critical { + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; + } + } +} + +static __xdata struct ao_task ao_report_task; + +void +ao_report_init(void) +{ + ao_add_task(&ao_report_task, ao_report, "report"); +} diff --git a/src/core/ao_rssi.c b/src/core/ao_rssi.c new file mode 100644 index 00000000..e3964d2d --- /dev/null +++ b/src/core/ao_rssi.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata volatile uint16_t ao_rssi_time; +static __pdata volatile uint16_t ao_rssi_delay; +static __pdata uint8_t ao_rssi_led; + +void +ao_rssi(void) +{ + for (;;) { + while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3)) + ao_sleep(&ao_rssi_time); + ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100)); + ao_delay(ao_rssi_delay); + } +} + +void +ao_rssi_set(int rssi_value) +{ + if (rssi_value > 0) + rssi_value = 0; + ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5); + ao_rssi_time = ao_time(); + ao_wakeup(&ao_rssi_time); +} + +__xdata struct ao_task ao_rssi_task; + +void +ao_rssi_init(uint8_t rssi_led) +{ + ao_rssi_led = rssi_led; + ao_rssi_delay = 0; + ao_add_task(&ao_rssi_task, ao_rssi, "rssi"); +} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..b2b8e9f6 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +/* + * Current sensor values + */ + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata int16_t ao_sample_pres; +__pdata int16_t ao_sample_alt; +__pdata int16_t ao_sample_height; +#if HAS_ACCEL +__pdata int16_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_adc; + +/* + * Sensor calibration values + */ + +__pdata int16_t ao_ground_pres; /* startup pressure */ +__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata int16_t ao_ground_accel; /* startup acceleration */ +__pdata int16_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + +uint8_t +ao_sample(void) +{ + ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); + while (ao_sample_adc != ao_adc_head) { + __xdata struct ao_adc *ao_adc; + + /* Capture a sample */ + ao_adc = &ao_adc_ring[ao_sample_adc]; + ao_sample_tick = ao_adc->tick; + ao_sample_pres = ao_adc->pres; + ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; +#endif +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_adc = ao_adc_ring_next(ao_sample_adc); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_adc = ao_adc_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_state.c b/src/core/ao_state.c new file mode 100644 index 00000000..ed197aa5 --- /dev/null +++ b/src/core/ao_state.c @@ -0,0 +1,23 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c new file mode 100644 index 00000000..c0138a30 --- /dev/null +++ b/src/core/ao_stdio.c @@ -0,0 +1,84 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +/* + * Basic I/O functions to support SDCC stdio package + */ + +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) + +__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; +__pdata int8_t ao_cur_stdio; +__pdata int8_t ao_num_stdios; + +void +putchar(char c) +{ + if (c == '\n') + (*ao_stdios[ao_cur_stdio].putchar)('\r'); + (*ao_stdios[ao_cur_stdio].putchar)(c); +} + +void +flush(void) +{ + if (ao_stdios[ao_cur_stdio].flush) + ao_stdios[ao_cur_stdio].flush(); +} + +__xdata uint8_t ao_stdin_ready; + +char +getchar(void) __reentrant __critical +{ + char c; + int8_t stdio = ao_cur_stdio; + + for (;;) { + c = ao_stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + return c; +} + +uint8_t +ao_echo(void) +{ + return ao_stdios[ao_cur_stdio].echo; +} + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) __reentrant +{ + if (ao_num_stdios == AO_NUM_STDIOS) + ao_panic(AO_PANIC_STDIO); + ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios].putchar = putchar; + ao_stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].echo = 1; + return ao_num_stdios++; +} diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c new file mode 100644 index 00000000..6ffca0e5 --- /dev/null +++ b/src/core/ao_storage.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_read(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_write(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +static __xdata uint8_t storage_data[8]; + +static void +ao_storage_dump(void) __reentrant +{ + uint8_t i, j; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + for (i = 0; ; i += 8) { + if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, + storage_data, + 8)) { + ao_cmd_put16((uint16_t) i); + for (j = 0; j < 8; j++) { + putchar(' '); + ao_cmd_put8(storage_data[j]); + } + putchar ('\n'); + } + if (i == 248) + break; + } +} + +#if 0 + +/* not enough space for this today + */ +static void +ao_storage_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + static __xdata uint8_t b; + uint32_t addr; + + ao_cmd_hex(); + block = ao_cmd_lex_i; + ao_cmd_hex(); + i = ao_cmd_lex_i; + addr = ((uint32_t) block << 8) | i; + ao_cmd_hex(); + len = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + while (len--) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + b = ao_cmd_lex_i; + ao_storage_write(addr, &b, 1); + addr++; + } +} +#endif + +void +ao_storage_zap(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); +} + +void +ao_storage_zapall(void) __reentrant +{ + uint32_t pos; + + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + ao_storage_erase(pos); +} + +void +ao_storage_info(void) __reentrant +{ + printf("Storage size: %ld\n", ao_storage_total); + printf("Storage erase unit: %ld\n", ao_storage_block); + ao_storage_device_info(); +} + +__code struct ao_cmds ao_storage_cmds[] = { + { ao_storage_info, "f\0Show storage" }, + { ao_storage_dump, "e \0Dump flash" }, +#ifdef HAS_STORAGE_DBG + { ao_storage_store, "w ...\0Write data to flash" }, +#endif + { ao_storage_zap, "z \0Erase " }, + { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, + { 0, NULL }, +}; + +void +ao_storage_init(void) +{ + ao_storage_device_init(); + ao_cmd_register(&ao_storage_cmds[0]); +} diff --git a/src/core/ao_task.c b/src/core/ao_task.c new file mode 100644 index 00000000..f5850fa4 --- /dev/null +++ b/src/core/ao_task.c @@ -0,0 +1,275 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +#define AO_NO_TASK_INDEX 0xff + +__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; +__data uint8_t ao_num_tasks; +__data uint8_t ao_cur_task_index; +__xdata struct ao_task *__data ao_cur_task; + +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant +{ + uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; + if (ao_num_tasks == AO_NUM_TASKS) + ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } + ao_tasks[ao_num_tasks++] = task; + task->task_id = task_id; + task->name = name; + /* + * Construct a stack frame so that it will 'return' + * to the start of the task + */ + stack = task->stack; + + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ + + /* and the stuff saved by ao_switch */ + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; + task->wchan = NULL; +} + +/* Task switching function. This must not use any stack variables */ +void +ao_yield(void) __naked +{ + + /* Save current context */ + _asm + /* Push ACC first, as when restoring the context it must be restored + * last (it is used to set the IE register). */ + push ACC + /* Store the IE register then enable interrupts. */ + push _IEN0 + setb _EA + push DPL + push DPH + push b + push ar2 + push ar3 + push ar4 + push ar5 + push ar6 + push ar7 + push ar0 + push ar1 + push PSW + _endasm; + PSW = 0; + _asm + push _bp + _endasm; + + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + /* Save the current stack */ + stack_len = SP - (AO_STACK_START - 1); + ao_cur_task->stack_count = stack_len; + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *save_ptr++ = *stack_ptr++; + while (--stack_len); + } + + /* Empty the stack; might as well let interrupts have the whole thing */ + SP = AO_STACK_START - 1; + + /* Find a task to run. If there isn't any runnable task, + * this loop will run forever, which is just fine + */ + { + __pdata uint8_t ao_next_task_index = ao_cur_task_index; + for (;;) { + ++ao_next_task_index; + if (ao_next_task_index == ao_num_tasks) + ao_next_task_index = 0; + + ao_cur_task = ao_tasks[ao_next_task_index]; + if (ao_cur_task->wchan == NULL) { + ao_cur_task_index = ao_next_task_index; + break; + } + + /* Check if the alarm is set for a time which has passed */ + if (ao_cur_task->alarm && + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { + ao_cur_task_index = ao_next_task_index; + break; + } + + /* Enter lower power mode when there isn't anything to do */ + if (ao_next_task_index == ao_cur_task_index) + PCON = PCON_IDLE; + } + } + + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + + /* Restore the old stack */ + stack_len = ao_cur_task->stack_count; + SP = AO_STACK_START - 1 + stack_len; + + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *stack_ptr++ = *save_ptr++; + while (--stack_len); + } + + _asm + pop _bp + pop PSW + pop ar1 + pop ar0 + pop ar7 + pop ar6 + pop ar5 + pop ar4 + pop ar3 + pop ar2 + pop b + pop DPH + pop DPL + /* The next byte of the stack is the IE register. Only the global + enable bit forms part of the task context. Pop off the IE then set + the global enable bit to match that of the stored IE register. */ + pop ACC + JB ACC.7,0098$ + CLR _EA + LJMP 0099$ + 0098$: + SETB _EA + 0099$: + /* Finally pop off the ACC, which was the first register saved. */ + pop ACC + ret + _endasm; +} + +uint8_t +ao_sleep(__xdata void *wchan) +{ + __critical { + ao_cur_task->wchan = wchan; + } + ao_yield(); + ao_cur_task->alarm = 0; + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + return 1; + } + return 0; +} + +void +ao_wakeup(__xdata void *wchan) +{ + uint8_t i; + + for (i = 0; i < ao_num_tasks; i++) + if (ao_tasks[i]->wchan == wchan) + ao_tasks[i]->wchan = NULL; +} + +void +ao_alarm(uint16_t delay) +{ + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) + ao_cur_task->alarm = 1; +} + +void +ao_exit(void) __critical +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + +void +ao_task_info(void) +{ + uint8_t i; + uint8_t pc_loc; + __xdata struct ao_task *task; + + for (i = 0; i < ao_num_tasks; i++) { + task = ao_tasks[i]; + pc_loc = task->stack_count - 17; + printf("%12s: wchan %04x pc %04x\n", + task->name, + (int16_t) task->wchan, + (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + } +} + +void +ao_start_scheduler(void) +{ + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_cur_task = NULL; + ao_yield(); +} diff --git a/src/core/ao_telem.h b/src/core/ao_telem.h new file mode 100644 index 00000000..1a8da291 --- /dev/null +++ b/src/core/ao_telem.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEM_H_ +#define _AO_TELEM_H_ + +#define AO_TELEMETRY_VERSION 4 + +/* + * Telemetry version 4 and higher format: + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + +#define AO_TELEM_VERSION "VERSION" +#define AO_TELEM_CALL "c" +#define AO_TELEM_SERIAL "n" +#define AO_TELEM_FLIGHT "f" +#define AO_TELEM_RSSI "r" +#define AO_TELEM_STATE "s" +#define AO_TELEM_TICK "t" + +/* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + +#define AO_TELEM_RAW_ACCEL "r_a" +#define AO_TELEM_RAW_BARO "r_b" +#define AO_TELEM_RAW_THERMO "r_t" +#define AO_TELEM_RAW_BATT "r_v" +#define AO_TELEM_RAW_DROGUE "r_d" +#define AO_TELEM_RAW_MAIN "r_m" + +/* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + +#define AO_TELEM_CAL_ACCEL_GROUND "c_a" +#define AO_TELEM_CAL_BARO_GROUND "c_b" +#define AO_TELEM_CAL_ACCEL_PLUS "c_p" +#define AO_TELEM_CAL_ACCEL_MINUS "c_m" + +/* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + +#define AO_TELEM_KALMAN_HEIGHT "k_h" +#define AO_TELEM_KALMAN_SPEED "k_s" +#define AO_TELEM_KALMAN_ACCEL "k_a" + +/* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + +#define AO_TELEM_ADHOC_ACCEL "a_a" +#define AO_TELEM_ADHOC_SPEED "a_s" +#define AO_TELEM_ADHOC_BARO "a_b" + +/* + * GPS values + * + * Name Value + * g GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_g GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + +#define AO_TELEM_GPS_STATE "g" +#define AO_TELEM_GPS_STATE_LOCKED 'l' +#define AO_TELEM_GPS_STATE_UNLOCKED 'u' +#define AO_TELEM_GPS_STATE_ERROR 'e' +#define AO_TELEM_GPS_NUM_SAT "g_n" +#define AO_TELEM_GPS_LATITUDE "g_ns" +#define AO_TELEM_GPS_LONGITUDE "g_ew" +#define AO_TELEM_GPS_ALTITUDE "g_a" +#define AO_TELEM_GPS_YEAR "g_Y" +#define AO_TELEM_GPS_MONTH "g_M" +#define AO_TELEM_GPS_DAY "g_D" +#define AO_TELEM_GPS_HOUR "g_h" +#define AO_TELEM_GPS_MINUTE "g_m" +#define AO_TELEM_GPS_SECOND "g_s" +#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" +#define AO_TELEM_GPS_COURSE "g_c" +#define AO_TELEM_GPS_HDOP "g_hd" +#define AO_TELEM_GPS_VDOP "g_vd" +#define AO_TELEM_GPS_HERROR "g_he" +#define AO_TELEM_GPS_VERROR "g_ve" + +/* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + +#define AO_TELEM_SAT_NUM "s_n" +#define AO_TELEM_SAT_SVID "s_v" +#define AO_TELEM_SAT_C_N_0 "s_c" + +#endif /* _AO_TELEM_H_ */ diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c new file mode 100644 index 00000000..c7338a58 --- /dev/null +++ b/src/core/ao_telemetry.c @@ -0,0 +1,270 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +static __pdata uint16_t ao_telemetry_interval; +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; +#if HAS_GPS +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; +#endif +#if HAS_COMPANION +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; +#endif +static __pdata uint8_t ao_rdf = 0; +static __pdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM +#endif + +#if defined(TELEMINI_V_1_0) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI +#endif + +#if defined(TELENANO_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO +#endif + +static __xdata union ao_telemetry_all telemetry; + +/* Send sensor packet */ +static void +ao_send_sensor(void) +{ + uint8_t sample; + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; +#if HAS_ACCEL + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; +#else + telemetry.sensor.ground_accel = 0; + telemetry.sensor.accel_plus_g = 0; + telemetry.sensor.accel_minus_g = 0; +#endif + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static void +ao_send_configuration(void) +{ + if (--ao_telemetry_config_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.apogee_delay = ao_config.apogee_delay; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_config_cur = ao_telemetry_config_max; + } +} + +#if HAS_GPS +static void +ao_send_location(void) +{ + if (--ao_telemetry_loc_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_LOCATION; + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.location.flags, + &ao_gps_data.flags, + 26); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_loc_cur = ao_telemetry_config_max; + } +} + +static void +ao_send_satellite(void) +{ + if (--ao_telemetry_sat_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_SATELLITE; + ao_mutex_get(&ao_gps_mutex); + telemetry.satellite.channels = ao_gps_tracking_data.channels; + memcpy(&telemetry.satellite.sats, + &ao_gps_tracking_data.sats, + AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_sat_cur = ao_telemetry_config_max; + } +} +#endif + +#if HAS_COMPANION +static void +ao_send_companion(void) +{ + if (--ao_telemetry_companion_cur <= 0) { + telemetry.generic.type = AO_TELEMETRY_COMPANION; + telemetry.companion.board_id = ao_companion_setup.board_id; + telemetry.companion.update_period = ao_companion_setup.update_period; + telemetry.companion.channels = ao_companion_setup.channels; + ao_mutex_get(&ao_companion_mutex); + memcpy(&telemetry.companion.companion_data, + ao_companion_data, + ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_companion_cur = ao_telemetry_companion_max; + } +} +#endif + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + + ao_config_get(); + if (!ao_config.radio_enable) + ao_exit(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + + telemetry.generic.serial = ao_serial_number; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&telemetry); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + + + ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif + ao_send_configuration(); +#if HAS_GPS + ao_send_location(); + ao_send_satellite(); +#endif + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + +#if HAS_COMPANION + if (!ao_companion_setup.update_period) + ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); + ao_telemetry_companion_max = ao_companion_setup.update_period / interval; + ao_telemetry_companion_cur = 1; +#endif + + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +#if HAS_COMPANION + ao_telemetry_config_cur = ao_telemetry_companion_cur; + if (ao_telemetry_config_max > ao_telemetry_config_cur) + ao_telemetry_config_cur++; +#else + ao_telemetry_config_cur = 1; +#endif + +#if HAS_GPS + ao_telemetry_loc_cur = ao_telemetry_config_cur; + if (ao_telemetry_config_max > ao_telemetry_loc_cur) + ao_telemetry_loc_cur++; + ao_telemetry_sat_cur = ao_telemetry_loc_cur; + if (ao_telemetry_config_max > ao_telemetry_sat_cur) + ao_telemetry_sat_cur++; +#endif + ao_wakeup(&telemetry); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c new file mode 100644 index 00000000..738f8ce6 --- /dev/null +++ b/src/drivers/ao_25lc1024.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_25lc1024.h" + +#define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_BLOCK_SHIFT 8 +#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +/* + * Using SPI on USART 0, with P1_2 as the chip select + */ + +#define EE_CS P1_2 +#define EE_CS_INDEX 2 + +static __xdata uint8_t ao_ee_mutex; + +#define ao_ee_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) + +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) + +struct ao_ee_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_ee_instruction; + +static void +ao_ee_write_enable(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WREN; + ao_spi_send(&ao_ee_instruction, 1); + ao_ee_cs_high(); +} + +static uint8_t +ao_ee_rdsr(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_RDSR; + ao_spi_send(&ao_ee_instruction, 1); + ao_spi_recv(&ao_ee_instruction, 1); + ao_ee_cs_high(); + return ao_ee_instruction.instruction; +} + +static void +ao_ee_wrsr(uint8_t status) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WRSR; + ao_ee_instruction.address[0] = status; + ao_spi_send(&ao_ee_instruction, 2); + ao_ee_cs_high(); +} + +#define EE_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; +static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; +static __pdata uint8_t ao_ee_block_dirty; + +/* Write the current block to the EEPROM */ +static void +ao_ee_write_block(void) +{ + uint8_t status; + + status = ao_ee_rdsr(); + if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) { + status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN); + ao_ee_wrsr(status); + } + ao_ee_write_enable(); + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WRITE; + ao_ee_instruction.address[0] = ao_ee_block >> 8; + ao_ee_instruction.address[1] = ao_ee_block; + ao_ee_instruction.address[2] = 0; + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); + ao_ee_cs_high(); + for (;;) { + uint8_t status = ao_ee_rdsr(); + if ((status & EE_STATUS_WIP) == 0) + break; + } +} + +/* Read the current block from the EEPROM */ +static void +ao_ee_read_block(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_READ; + ao_ee_instruction.address[0] = ao_ee_block >> 8; + ao_ee_instruction.address[1] = ao_ee_block; + ao_ee_instruction.address[2] = 0; + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); + ao_ee_cs_high(); +} + +static void +ao_ee_flush_internal(void) +{ + if (ao_ee_block_dirty) { + ao_ee_write_block(); + ao_ee_block_dirty = 0; + } +} + +static void +ao_ee_fill(uint16_t block) +{ + if (block != ao_ee_block) { + ao_ee_flush_internal(); + ao_ee_block = block; + ao_ee_read_block(); + } +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + if (len != EE_BLOCK_SIZE) + ao_ee_fill(block); + else { + ao_ee_flush_internal(); + ao_ee_block = block; + } + memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_fill(block); + memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_flush_internal(); + } ao_mutex_put(&ao_ee_mutex); +} + +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_flush_internal(); + ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +static void +ee_store(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + if (ao_storage_total == 0) { + ao_storage_total = EE_DEVICE_SIZE; + ao_storage_block = EE_BLOCK_SIZE; + ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + ao_storage_unit = EE_BLOCK_SIZE; + } +} + +void +ao_storage_device_info(void) __reentrant +{ +} + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_storage_device_init(void) +{ + /* set up CS */ + EE_CS = 1; + P1DIR |= (1 << EE_CS_INDEX); + P1SEL &= ~(1 << EE_CS_INDEX); +} diff --git a/src/drivers/ao_25lc1024.h b/src/drivers/ao_25lc1024.h new file mode 100644 index 00000000..44e52387 --- /dev/null +++ b/src/drivers/ao_25lc1024.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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. + */ + +/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ + +#ifndef _25LC1024_H_ +#define _25LC1024_H_ + +#define EE_READ 0x03 +#define EE_WRITE 0x02 +#define EE_WREN 0x06 +#define EE_WRDI 0x04 +#define EE_RDSR 0x05 +#define EE_WRSR 0x01 +#define EE_PE 0x42 +#define EE_SE 0xd8 +#define EE_CE 0xc7 +#define EE_RDID 0xab +#define EE_DPD 0xb9 + +#define EE_STATUS_WIP (1 << 0) +#define EE_STATUS_WEL (1 << 1) +#define EE_STATUS_BP0 (1 << 2) +#define EE_STATUS_BP1 (1 << 3) +#define EE_STATUS_WPEN (1 << 7) + +#endif /* _25LC1024_H_ */ diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c new file mode 100644 index 00000000..aee9877a --- /dev/null +++ b/src/drivers/ao_at45db161d.c @@ -0,0 +1,318 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_at45db161d.h" + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +#define FLASH_CS P1_1 +#define FLASH_CS_INDEX 1 + +#define FLASH_BLOCK_SIZE_MAX 512 + +__xdata uint8_t ao_flash_mutex; + +#define ao_flash_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) + +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) + +struct ao_flash_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_flash_instruction; + +static void +ao_flash_set_pagesize_512(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_SET_CONFIG; + ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; + ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; + ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; + ao_spi_send(&ao_flash_instruction, 4); + ao_flash_cs_high(); +} + + +static uint8_t +ao_flash_read_status(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ_STATUS; + ao_spi_send(&ao_flash_instruction, 1); + ao_spi_recv(&ao_flash_instruction, 1); + ao_flash_cs_high(); + return ao_flash_instruction.instruction; +} + +#define FLASH_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; +static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; +static __pdata uint8_t ao_flash_block_dirty; +static __pdata uint8_t ao_flash_write_pending; +static __pdata uint8_t ao_flash_setup_done; +static __pdata uint8_t ao_flash_block_shift; +static __pdata uint16_t ao_flash_block_size; +static __pdata uint16_t ao_flash_block_mask; + +void +ao_storage_setup(void) __reentrant +{ + uint8_t status; + + if (ao_flash_setup_done) + return; + + ao_mutex_get(&ao_flash_mutex); + if (ao_flash_setup_done) { + ao_mutex_put(&ao_flash_mutex); + return; + } + + /* On first use, check to see if the flash chip has + * been programmed to use 512 byte pages. If not, do so. + * And then, because the flash part must be power cycled + * for that change to take effect, panic. + */ + status = ao_flash_read_status(); + + if (!(status & FLASH_STATUS_PAGESIZE_512)) { + ao_flash_set_pagesize_512(); + ao_panic(AO_PANIC_FLASH); + } + + switch (status & 0x3c) { + + /* AT45DB321D */ + case 0x34: + ao_flash_block_shift = 9; + ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB161D */ + case 0x2c: + ao_flash_block_shift = 9; + ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB081D */ + case 0x24: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB041D */ + case 0x1c: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); + break; + + /* AT45DB021D */ + case 0x14: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); + break; + + /* AT45DB011D */ + case 0x0c: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); + break; + + default: + ao_panic(AO_PANIC_FLASH); + } + ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_block_mask = ao_flash_block_size - 1; + + ao_storage_block = ao_flash_block_size; + ao_storage_config = ao_storage_total - ao_storage_block; + ao_storage_unit = ao_flash_block_size; + + ao_flash_setup_done = 1; + ao_mutex_put(&ao_flash_mutex); +} + +static void +ao_flash_wait_write(void) +{ + if (ao_flash_write_pending) { + for (;;) { + uint8_t status = ao_flash_read_status(); + if ((status & FLASH_STATUS_RDY)) + break; + } + ao_flash_write_pending = 0; + } +} + +/* Write the current block to the FLASHPROM */ +static void +ao_flash_write_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_WRITE; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(ao_flash_data, ao_storage_block); + ao_flash_cs_high(); + ao_flash_write_pending = 1; +} + +/* Read the current block from the FLASHPROM */ +static void +ao_flash_read_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_recv(ao_flash_data, ao_flash_block_size); + ao_flash_cs_high(); +} + +static void +ao_flash_flush_internal(void) +{ + if (ao_flash_block_dirty) { + ao_flash_write_block(); + ao_flash_block_dirty = 0; + } +} + +static void +ao_flash_fill(uint16_t block) +{ + if (block != ao_flash_block) { + ao_flash_flush_internal(); + ao_flash_block = block; + ao_flash_read_block(); + } +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (len != ao_flash_block_size) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + buf, + len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, + ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + len); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); +} + +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); + memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t status; + + ao_storage_setup(); + ao_mutex_get(&ao_flash_mutex); { + status = ao_flash_read_status(); + printf ("Flash status: 0x%02x\n", status); + printf ("Flash block shift: %d\n", ao_flash_block_shift); + printf ("Flash block size: %d\n", ao_flash_block_size); + printf ("Flash block mask: %d\n", ao_flash_block_mask); + printf ("Flash device size: %ld\n", ao_storage_total); + } ao_mutex_put(&ao_flash_mutex); +} + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_storage_device_init(void) +{ + /* set up CS */ + FLASH_CS = 1; + P1DIR |= (1 << FLASH_CS_INDEX); + P1SEL &= ~(1 << FLASH_CS_INDEX); +} diff --git a/src/drivers/ao_at45db161d.h b/src/drivers/ao_at45db161d.h new file mode 100644 index 00000000..9ee6f1b6 --- /dev/null +++ b/src/drivers/ao_at45db161d.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ + +#ifndef _AT45DB161D_H_ +#define _AT45DB161D_H_ + +/* + * We reserve the last block on the device for + * configuration space. Writes and reads in this + * area return errors. + */ + + +#define FLASH_READ 0x03 +#define FLASH_WRITE 0x82 +#define FLASH_PAGE_ERASE 0x81 +#define FLASH_READ_STATUS 0xd7 +#define FLASH_SET_CONFIG 0x3d + +#define FLASH_SET_512_BYTE_0 0x2a +#define FLASH_SET_512_BYTE_1 0x80 +#define FLASH_SET_512_BYTE_2 0xa6 + +#define FLASH_STATUS_RDY (1 << 7) +#define FLASH_STATUS_COMP (1 << 6) +#define FLASH_STATUS_PROTECT (1 << 1) +#define FLASH_STATUS_PAGESIZE_512 (1 << 0) + +#endif /* _AT45DB161D_H_ */ diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c new file mode 100644 index 00000000..44155ec1 --- /dev/null +++ b/src/drivers/ao_btm.c @@ -0,0 +1,302 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +int8_t ao_btm_stdio; +__xdata uint8_t ao_btm_connected; + +#define AO_BTM_MAX_REPLY 16 +__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; + +extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; + +/* + * Read a line of data from the serial port, truncating + * it after a few characters. + */ + +uint8_t +ao_btm_get_line(void) +{ + uint8_t ao_btm_reply_len = 0; + char c; + + for (;;) { + + while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (c == '\r' || c == '\n') + goto done; + } + for (c = 0; c < 10; c++) { + ao_delay(AO_MS_TO_TICKS(10)); + if (!ao_fifo_empty(ao_usart1_rx_fifo)) + break; + } + if (c == 10) + goto done; + } +done: + for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) + ao_btm_reply[c++] = '\0'; + return ao_btm_reply_len; +} + +/* + * Drain the serial port completely + */ +void +ao_btm_drain() +{ + while (ao_btm_get_line()) + ; +} + +/* + * Set the stdio echo for the bluetooth link + */ +void +ao_btm_echo(uint8_t echo) +{ + ao_stdios[ao_btm_stdio].echo = echo; +} + +/* + * Delay between command charaters; the BT module + * can't keep up with 57600 baud + */ + +void +ao_btm_putchar(char c) +{ + ao_serial_putchar(c); + ao_delay(1); +} + +/* + * Wait for the bluetooth device to return + * status from the previously executed command + */ +uint8_t +ao_btm_wait_reply(void) +{ + for (;;) { + ao_btm_get_line(); + if (!strncmp(ao_btm_reply, "OK", 2)) + return 1; + if (!strncmp(ao_btm_reply, "ERROR", 5)) + return -1; + if (ao_btm_reply[0] == '\0') + return 0; + } +} + +void +ao_btm_string(__code char *cmd) +{ + char c; + + while (c = *cmd++) + ao_btm_putchar(c); +} + +uint8_t +ao_btm_cmd(__code char *cmd) +{ + ao_btm_drain(); + ao_btm_string(cmd); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_set_name(void) +{ + char sn[8]; + char *s = sn + 8; + char c; + int n; + ao_btm_string("ATN=TeleBT-"); + *--s = '\0'; + *--s = '\r'; + n = ao_serial_number; + do { + *--s = '0' + n % 10; + } while (n /= 10); + while ((c = *s++)) + ao_btm_putchar(c); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_try_speed(uint8_t speed) +{ + ao_serial_set_speed(speed); + ao_btm_drain(); + (void) ao_btm_cmd("\rATE0\rATQ0\r"); + if (ao_btm_cmd("AT\r") == 1) + return 1; + return 0; +} + +/* + * A thread to initialize the bluetooth device and + * hang around to blink the LED when connected + */ +void +ao_btm(void) +{ + /* + * Wait for the bluetooth device to boot + */ + ao_delay(AO_SEC_TO_TICKS(3)); + +#if HAS_BEEP + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +#endif + + /* + * The first time we connect, the BTM-180 comes up at 19200 baud. + * After that, it will remember and come up at 57600 baud. So, see + * if it is already running at 57600 baud, and if that doesn't work + * then tell it to switch to 57600 from 19200 baud. + */ + while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) + ao_btm_cmd("ATL4\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + } + + /* Disable echo */ + ao_btm_cmd("ATE0\r"); + + /* Enable flow control */ + ao_btm_cmd("ATC1\r"); + + /* Set the reported name to something we can find on the host */ + ao_btm_set_name(); + + /* Turn off status reporting */ + ao_btm_cmd("ATQ1\r"); + + ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); + ao_btm_echo(0); + + for (;;) { + while (!ao_btm_connected) + ao_sleep(&ao_btm_connected); + while (ao_btm_connected) { + ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); + ao_delay(AO_SEC_TO_TICKS(3)); + } + } +} + +__xdata struct ao_task ao_btm_task; + +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + +void +ao_btm_check_link() __critical +{ + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } +} + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif +{ +#if BT_LINK_ON_P1 + P1IF = 0; +#endif + if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); + } + BT_PIFG = 0; +} + +void +ao_btm_init (void) +{ + ao_serial_init(); + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + +#if BT_LINK_ON_P1 + /* + * Configure ser reset line + */ + + P1_6 = 0; + P1DIR |= (1 << 6); +#endif + + /* + * Configure link status line + */ + + /* Set pin to input */ + BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); + + /* Set pin to tri-state */ + BT_PINP |= (1 << BT_LINK_PIN_INDEX); + + /* Enable interrupts */ + IEN2 |= BT_IEN2_PIE; + + /* Check current pin state */ + ao_btm_check_link(); + +#if BT_LINK_ON_P2 + /* Eable the pin interrupt */ + PICTL |= PICTL_P2IEN; +#endif +#if BT_LINK_ON_P1 + /* Enable pin interrupt */ + P1IEN |= (1 << BT_LINK_PIN_INDEX); +#endif + + ao_add_task(&ao_btm_task, ao_btm, "bt"); +} diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c new file mode 100644 index 00000000..4c8f4269 --- /dev/null +++ b/src/drivers/ao_companion.c @@ -0,0 +1,132 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) + +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) + +static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_setup ao_companion_setup; + +__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; +__pdata uint8_t ao_companion_running; +__xdata uint8_t ao_companion_mutex; + +static void +ao_companion_send_command(uint8_t command) +{ + ao_companion_command.command = command; + ao_companion_command.flight_state = ao_flight_state; + ao_companion_command.tick = ao_time(); + ao_companion_command.serial = ao_serial_number; + ao_companion_command.flight = ao_flight_number; + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); +} + +static uint8_t +ao_companion_get_setup(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_SETUP); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + COMPANION_DESELECT(); + return (ao_companion_setup.board_id == + ~ao_companion_setup.board_id_inverse); +} + +static void +ao_companion_get_data(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_FETCH); + ao_mutex_get(&ao_companion_mutex); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + COMPANION_DESELECT(); +} + +static void +ao_companion_notify(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_NOTIFY); + COMPANION_DESELECT(); +} + +void +ao_companion(void) +{ + uint8_t i; + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + for (i = 0; i < 10; i++) { + ao_delay(AO_SEC_TO_TICKS(1)); + if ((ao_companion_running = ao_companion_get_setup())) + break; + } + while (ao_companion_running) { + ao_alarm(ao_companion_setup.update_period); + if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) + ao_companion_get_data(); + else + ao_companion_notify(); + } + ao_exit(); +} + +void +ao_companion_status(void) __reentrant +{ + uint8_t i; + printf("Companion running: %d\n", ao_companion_running); + printf("device: %d\n", ao_companion_setup.board_id); + printf("update period: %d\n", ao_companion_setup.update_period); + printf("channels: %d\n", ao_companion_setup.channels); + printf("data:"); + for(i = 0; i < ao_companion_setup.channels; i++) + printf(" %5u", ao_companion_data[i]); + printf("\n"); +} + +__code struct ao_cmds ao_companion_cmds[] = { + { ao_companion_status, "L\0Companion link status" }, + { 0, NULL }, +}; + +static __xdata struct ao_task ao_companion_task; + +void +ao_companion_init(void) +{ + COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ + COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ + COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ + + ao_cmd_register(&ao_companion_cmds[0]); + ao_add_task(&ao_companion_task, ao_companion, "companion"); +} diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c new file mode 100644 index 00000000..f2abbf84 --- /dev/null +++ b/src/drivers/ao_gps_sirf.c @@ -0,0 +1,442 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +__xdata uint8_t ao_gps_mutex; +__pdata uint16_t ao_gps_tick; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; + +const char ao_gps_config[] = { + + 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ + 136, /* mode control */ + 0, 0, /* reserved */ + 0, /* degraded mode (allow 1-SV navigation) */ + 0, 0, /* reserved */ + 0, 0, /* user specified altitude */ + 2, /* alt hold mode (disabled, require 3d fixes) */ + 0, /* alt hold source (use last computed altitude) */ + 0, /* reserved */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ + 0, /* Track smoothing (disabled) */ + 0x00, 0x8e, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ + 166, /* Set message rate */ + 2, /* enable/disable all messages */ + 0, /* message id (ignored) */ + 0, /* update rate (0 = disable) */ + 0, 0, 0, 0, /* reserved */ + 0x00, 0xa8, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ + 143, /* static navigation */ + 0, /* disable */ + 0x00, 0x8f, 0xb0, 0xb3, +}; + +#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) +#define NAV_TYPE_NO_FIX (0 << 0) +#define NAV_TYPE_SV_KF (1 << 0) +#define NAV_TYPE_2_SV_KF (2 << 0) +#define NAV_TYPE_3_SV_KF (3 << 0) +#define NAV_TYPE_4_SV_KF (4 << 0) +#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) +#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) +#define NAV_TYPE_DR (7 << 0) +#define NAV_TYPE_TRICKLE_POWER (1 << 3) +#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) +#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) +#define NAV_TYPE_DGPS_APPLIED (1 << 7) +#define NAV_TYPE_SENSOR_DR (1 << 8) +#define NAV_TYPE_OVERDETERMINED (1 << 9) +#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) +#define NAV_TYPE_FIX_MI_EDIT (1 << 11) +#define NAV_TYPE_INVALID_VELOCITY (1 << 12) +#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) +#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) + +struct sirf_geodetic_nav_data { + uint16_t nav_type; + uint16_t utc_year; + uint8_t utc_month; + uint8_t utc_day; + uint8_t utc_hour; + uint8_t utc_minute; + uint16_t utc_second; + int32_t lat; + int32_t lon; + int32_t alt_msl; + uint16_t ground_speed; + uint16_t course; + int16_t climb_rate; + uint32_t h_error; + uint32_t v_error; + uint8_t num_sv; + uint8_t hdop; +}; + +static __xdata struct sirf_geodetic_nav_data ao_sirf_data; + +struct sirf_measured_sat_data { + uint8_t svid; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + +static __pdata uint16_t ao_sirf_cksum; +static __pdata uint16_t ao_sirf_len; + +#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) + +static uint8_t data_byte(void) +{ + uint8_t c = ao_sirf_byte(); + --ao_sirf_len; + ao_sirf_cksum += c; + return c; +} + +static char __xdata *sirf_target; + +static void sirf_u16(uint8_t offset) +{ + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); + uint16_t val; + + val = data_byte() << 8; + val |= data_byte (); + *ptr = val; +} + +static void sirf_u8(uint8_t offset) +{ + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); + uint8_t val; + + val = data_byte (); + *ptr = val; +} + +static void sirf_u32(uint8_t offset) __reentrant +{ + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); + uint32_t val; + + val = ((uint32_t) data_byte ()) << 24; + val |= ((uint32_t) data_byte ()) << 16; + val |= ((uint32_t) data_byte ()) << 8; + val |= ((uint32_t) data_byte ()); + *ptr = val; +} + +static void sirf_discard(uint8_t len) +{ + while (len--) + data_byte(); +} + +#define SIRF_END 0 +#define SIRF_DISCARD 1 +#define SIRF_U8 2 +#define SIRF_U16 3 +#define SIRF_U32 4 +#define SIRF_U8X10 5 + +struct sirf_packet_parse { + uint8_t type; + uint8_t offset; +}; + +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + +static const struct sirf_packet_parse geodetic_nav_data_packet[] = { + { SIRF_DISCARD, 2 }, /* 1 nav valid */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ + { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ + { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ + { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ + { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ + { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ + { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ + { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, + clock bias error, clock drift, + clock drift error, distance, + distance error, heading error */ /* 58 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ + { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ + { SIRF_END, 0 }, /* 91 */ +}; + +static void +ao_sirf_parse_41(void) __reentrant +{ + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} + +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); +} + +static void +ao_gps_setup(void) __reentrant +{ + uint8_t i, k; + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); + for (k = 0; k < 3; k++) + for (i = 0; i < sizeof (ao_gps_set_nmea); i++) + ao_serial_putchar(ao_gps_set_nmea[i]); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); +} + +static const char ao_gps_set_message_rate[] = { + 0xa0, 0xa2, 0x00, 0x08, + 166, + 0, +}; + +void +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant +{ + uint16_t cksum = 0x00a6; + uint8_t i; + + for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) + ao_serial_putchar(ao_gps_set_message_rate[i]); + ao_serial_putchar(msg); + ao_serial_putchar(rate); + cksum = 0xa6 + msg + rate; + for (i = 0; i < 4; i++) + ao_serial_putchar(0); + ao_serial_putchar((cksum >> 8) & 0x7f); + ao_serial_putchar(cksum & 0xff); + ao_serial_putchar(0xb0); + ao_serial_putchar(0xb3); +} + +static const uint8_t sirf_disable[] = { + 2, + 9, + 10, + 27, + 50, + 52, +}; + +void +ao_gps(void) __reentrant +{ + uint8_t i, k; + uint16_t cksum; + + ao_gps_setup(); + for (k = 0; k < 5; k++) + { + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (i = 0; i < sizeof (sirf_disable); i++) + ao_sirf_set_message_rate(sirf_disable[i], 0); + ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); + } + for (;;) { + /* Locate the begining of the next record */ + while (ao_sirf_byte() != (uint8_t) 0xa0) + ; + if (ao_sirf_byte() != (uint8_t) 0xa2) + continue; + + /* Length */ + ao_sirf_len = ao_sirf_byte() << 8; + ao_sirf_len |= ao_sirf_byte(); + if (ao_sirf_len > 1023) + continue; + + ao_sirf_cksum = 0; + + /* message ID */ + i = data_byte (); /* 0 */ + + switch (i) { + case 41: + if (ao_sirf_len < 90) + break; + ao_sirf_parse_41(); + break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; + } + if (ao_sirf_len != 0) + continue; + + /* verify checksum and end sequence */ + ao_sirf_cksum &= 0x7fff; + cksum = ao_sirf_byte() << 8; + cksum |= ao_sirf_byte(); + if (ao_sirf_cksum != cksum) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb0) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb3) + continue; + + switch (i) { + case 41: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_time(); + ao_gps_data.hour = ao_sirf_data.utc_hour; + ao_gps_data.minute = ao_sirf_data.utc_minute; + ao_gps_data.second = ao_sirf_data.utc_second / 1000; + ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; + if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) + ao_gps_data.flags |= AO_GPS_VALID; + ao_gps_data.latitude = ao_sirf_data.lat; + ao_gps_data.longitude = ao_sirf_data.lon; + ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; + ao_gps_data.ground_speed = ao_sirf_data.ground_speed; + ao_gps_data.course = ao_sirf_data.course / 200; + ao_gps_data.hdop = ao_sirf_data.hdop; + ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + ao_gps_data.flags |= AO_GPS_COURSE_VALID; +#if 0 + if (ao_sirf_data.h_error > 6553500) + ao_gps_data.h_error = 65535; + else + ao_gps_data.h_error = ao_sirf_data.h_error / 100; + if (ao_sirf_data.v_error > 6553500) + ao_gps_data.v_error = 65535; + else + ao_gps_data.v_error = ao_sirf_data.v_error / 100; +#endif + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; + } + } +} + +__xdata struct ao_task ao_gps_task; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); +} diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c new file mode 100644 index 00000000..7ac26946 --- /dev/null +++ b/src/drivers/ao_gps_skytraq.c @@ -0,0 +1,490 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +#define AO_GPS_LEADER 2 + +static __code char ao_gps_header[] = "GP"; + +__xdata uint8_t ao_gps_mutex; +static __data char ao_gps_char; +static __pdata uint8_t ao_gps_cksum; +static __pdata uint8_t ao_gps_error; + +__pdata uint16_t ao_gps_tick; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +static __pdata uint16_t ao_gps_next_tick; +static __xdata struct ao_telemetry_location ao_gps_next; +static __pdata uint8_t ao_gps_date_flags; +static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; + +#define STQ_S 0xa0, 0xa1 +#define STQ_E 0x0d, 0x0a +#define SKYTRAQ_MSG_2(id,a,b) \ + STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E +#define SKYTRAQ_MSG_3(id,a,b,c) \ + STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E +#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ + STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E +#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ + STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ + (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E + +static __code uint8_t ao_gps_config[] = { + SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + /* gga interval */ + /* gsa interval */ + /* gsv interval */ + /* gll interval */ + /* rmc interval */ + /* vtg interval */ + /* zda interval */ + /* attributes (0 = update to sram, 1 = update flash too) */ + + SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ + /* 0 = car, 1 = pedestrian */ + /* 0 = update to sram, 1 = update sram + flash */ +}; + +static void +ao_gps_lexchar(void) +{ + if (ao_gps_error) + ao_gps_char = '\n'; + else + ao_gps_char = ao_serial_getchar(); + ao_gps_cksum ^= ao_gps_char; +} + +void +ao_gps_skip_field(void) +{ + while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + ao_gps_lexchar(); +} + +void +ao_gps_skip_sep(void) +{ + if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + ao_gps_lexchar(); +} + +__pdata static uint8_t ao_gps_num_width; + +static int16_t +ao_gps_decimal(uint8_t max_width) +{ + int16_t v; + __pdata uint8_t neg = 0; + + ao_gps_skip_sep(); + if (ao_gps_char == '-') { + neg = 1; + ao_gps_lexchar(); + } + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if (ao_gps_char < '0' || '9' < ao_gps_char) + break; + v = v * (int16_t) 10 + ao_gps_char - '0'; + ao_gps_num_width++; + ao_gps_lexchar(); + } + if (neg) + v = -v; + return v; +} + +static uint8_t +ao_gps_hex(uint8_t max_width) +{ + uint8_t v, d; + + ao_gps_skip_sep(); + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if ('0' <= ao_gps_char && ao_gps_char <= '9') + d = ao_gps_char - '0'; + else if ('A' <= ao_gps_char && ao_gps_char <= 'F') + d = ao_gps_char - 'A' + 10; + else if ('a' <= ao_gps_char && ao_gps_char <= 'f') + d = ao_gps_char - 'a' + 10; + else + break; + v = (v << 4) | d; + ao_gps_num_width++; + ao_gps_lexchar(); + } + return v; +} + +static int32_t +ao_gps_parse_pos(uint8_t deg_width) __reentrant +{ + int32_t d; + int32_t m; + int32_t f; + + d = ao_gps_decimal(deg_width); + m = ao_gps_decimal(2); + if (ao_gps_char == '.') { + f = ao_gps_decimal(4); + while (ao_gps_num_width < 4) { + f *= 10; + ao_gps_num_width++; + } + } else { + f = 0; + if (ao_gps_char != ',') + ao_gps_error = 1; + } + d = d * 10000000l; + m = m * 10000l + f; + d = d + m * 50 / 3; + return d; +} + +static uint8_t +ao_gps_parse_flag(char no_c, char yes_c) __reentrant +{ + uint8_t ret = 0; + ao_gps_skip_sep(); + if (ao_gps_char == yes_c) + ret = 1; + else if (ao_gps_char == no_c) + ret = 0; + else + ao_gps_error = 1; + ao_gps_lexchar(); + return ret; +} + +static void +ao_nmea_gga() +{ + uint8_t i; + + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next_tick = ao_time(); + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + i = ao_gps_decimal(0xff); + if (i <= 50) { + i = (uint8_t) 5 * i; + if (ao_gps_char == '.') + i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + i = 255; + ao_gps_next.hdop = i; + ao_gps_skip_field(); + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; + memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } +} + +static void +ao_nmea_gsv(void) +{ + char c; + uint8_t i; + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + 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; + 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 */ + c = ao_gps_decimal(2); /* C/N0 */ + if (i < AO_MAX_GPS_TRACKING) { + if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0) + ao_gps_tracking_next.channels = i + 1; + } + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } +} + +static void +ao_nmea_rmc(void) +{ + char a, c; + uint8_t i; + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } +} + +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) + +static void +ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) +{ + while (l--) { + uint8_t c = *b++; + if (c == 0xa0) + ao_delay(AO_MS_TO_TICKS(500)); + ao_serial_putchar(c); + } +} + +static void +ao_gps_nmea_parse(void) +{ + uint8_t a, b, c; + + ao_gps_cksum = 0; + ao_gps_error = 0; + + for (a = 0; a < AO_GPS_LEADER; a++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[a]) + return; + } + + ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); + b = ao_gps_char; + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + + if (ao_gps_char != ',') + return; + + if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { + ao_nmea_gga(); + } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { + ao_nmea_gsv(); + } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { + ao_nmea_rmc(); + } +} + +void +ao_gps(void) __reentrant +{ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + /* give skytraq time to boot in case of cold start */ + ao_delay(AO_MS_TO_TICKS(2000)); + + ao_skytraq_sendstruct(ao_gps_config); + + for (;;) { + /* Locate the begining of the next record */ + if (ao_serial_getchar() == '$') { + ao_gps_nmea_parse(); + } + + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + uint8_t i; + ao_mutex_get(&ao_gps_mutex); + printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); + printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); + printf ("Lat/Lon: %ld %ld\n", 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); + printf ("Sats: %d", ao_gps_tracking_data.channels); + for (i = 0; i < ao_gps_tracking_data.channels; i++) + printf (" %d %d", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\ndone\n"); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { gps_dump, "g\0Display GPS" }, + { 0, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c new file mode 100644 index 00000000..d7208273 --- /dev/null +++ b/src/drivers/ao_m25.c @@ -0,0 +1,380 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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" + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +/* + * Each flash chip is arranged in 64kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 256 byte pages and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +#define M25_WREN 0x06 /* Write Enable */ +#define M25_WRDI 0x04 /* Write Disable */ +#define M25_RDID 0x9f /* Read Identification */ +#define M25_RDSR 0x05 /* Read Status Register */ +#define M25_WRSR 0x01 /* Write Status Register */ +#define M25_READ 0x03 /* Read Data Bytes */ +#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define M25_PP 0x02 /* Page Program */ +#define M25_SE 0xd8 /* Sector Erase */ +#define M25_BE 0xc7 /* Bulk Erase */ +#define M25_DP 0xb9 /* Deep Power-down */ + +/* RDID response */ +#define M25_MANUF_OFFSET 0 +#define M25_MEMORY_TYPE_OFFSET 1 +#define M25_CAPACITY_OFFSET 2 +#define M25_UID_OFFSET 3 +#define M25_CFI_OFFSET 4 +#define M25_RDID_LEN 4 /* that's all we need */ + +#define M25_CAPACITY_128KB 0x11 +#define M25_CAPACITY_256KB 0x12 +#define M25_CAPACITY_512KB 0x13 +#define M25_CAPACITY_1MB 0x14 +#define M25_CAPACITY_2MB 0x15 + +/* + * Status register bits + */ + +#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ +#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ +#define M25_STATUS_BP_SHIFT (2) +#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ +#define M25_STATUS_WIP (1 << 0) /* Write in progress */ + +/* + * On teleterra, the m25 chip select pins are + * wired on P0_0 through P0_3. + */ + +#if M25_MAX_CHIPS > 1 +static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ +static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ +static uint8_t ao_m25_numchips; /* number of chips detected */ +#endif +static uint8_t ao_m25_total; /* total sectors available */ +static uint8_t ao_m25_wip; /* write in progress */ + +static __xdata uint8_t ao_m25_mutex; + +/* + * This little array is abused to send and receive data. A particular + * caution -- the read and write addresses are written into the last + * three bytes of the array by ao_m25_set_page_address and then the + * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither + * of which touch those last three bytes. + */ + +static __xdata uint8_t ao_m25_instruction[4]; + +#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) +#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) + +#define M25_BLOCK_SHIFT 16 +#define M25_BLOCK 65536L +#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) +#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) + +/* + * Block until the specified chip is done writing + */ +static void +ao_m25_wait_wip(uint8_t cs) +{ + if (ao_m25_wip & cs) { + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDSR; + ao_spi_send(ao_m25_instruction, 1); + do { + ao_spi_recv(ao_m25_instruction, 1); + } while (ao_m25_instruction[0] & M25_STATUS_WIP); + M25_DESELECT(cs); + ao_m25_wip &= ~cs; + } +} + +/* + * Set the write enable latch so that page program and sector + * erase commands will work. Also mark the chip as busy writing + * so that future operations will block until the WIP bit goes off + */ +static void +ao_m25_write_enable(uint8_t cs) +{ + M25_SELECT(cs); + ao_m25_instruction[0] = M25_WREN; + ao_spi_send(&ao_m25_instruction, 1); + M25_DESELECT(cs); + ao_m25_wip |= cs; +} + + +/* + * Returns the number of 64kB sectors + */ +static uint8_t +ao_m25_read_capacity(uint8_t cs) +{ + uint8_t capacity; + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + /* Check to see if the chip is present */ + if (ao_m25_instruction[0] == 0xff) + return 0; + capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; + + /* Sanity check capacity number */ + if (capacity < 0x11 || 0x1f < capacity) + return 0; + return 1 << (capacity - 0x10); +} + +static uint8_t +ao_m25_set_address(uint32_t pos) +{ + uint8_t chip; +#if M25_MAX_CHIPS > 1 + uint8_t size; + + for (chip = 0; chip < ao_m25_numchips; chip++) { + size = ao_m25_size[chip]; + if (M25_POS_TO_SECTOR(pos) < size) + break; + pos -= M25_SECTOR_TO_POS(size); + } + if (chip == ao_m25_numchips) + return 0xff; + + chip = ao_m25_pin[chip]; +#else + chip = M25_CS_MASK; +#endif + ao_m25_wait_wip(chip); + + ao_m25_instruction[1] = pos >> 16; + ao_m25_instruction[2] = pos >> 8; + ao_m25_instruction[3] = pos; + return chip; +} + +/* + * Scan the possible chip select lines + * to see which flash chips are connected + */ +static uint8_t +ao_m25_scan(void) +{ +#if M25_MAX_CHIPS > 1 + uint8_t pin, size; +#endif + + if (ao_m25_total) + return 1; + +#if M25_MAX_CHIPS > 1 + ao_m25_numchips = 0; + for (pin = 1; pin != 0; pin <<= 1) { + if (M25_CS_MASK & pin) { + size = ao_m25_read_capacity(pin); + if (size != 0) { + ao_m25_size[ao_m25_numchips] = size; + ao_m25_pin[ao_m25_numchips] = pin; + ao_m25_total += size; + ao_m25_numchips++; + } + } + } +#else + ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); +#endif + if (!ao_m25_total) + return 0; + ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); + ao_storage_block = M25_BLOCK; + ao_storage_config = ao_storage_total - M25_BLOCK; + ao_storage_unit = 256; + return 1; +} + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + ao_m25_wait_wip(cs); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_SE; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + M25_DESELECT(cs); + ao_m25_wip |= cs; + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_PP; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + /* No need to use the FAST_READ as we're running at only 8MHz */ + ao_m25_instruction[0] = M25_READ; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_recv(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t cs; +#if M25_MAX_CHIPS > 1 + uint8_t chip; +#endif + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); + +#if M25_MAX_CHIPS > 1 + printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); + for (chip = 0; chip < ao_m25_numchips; chip++) + printf ("Flash chip %d select %02x size %d\n", + chip, ao_m25_pin[chip], ao_m25_size[chip]); +#else + printf ("Detected chips 1 size %d\n", ao_m25_total); +#endif + + printf ("Available chips:\n"); + for (cs = 1; cs != 0; cs <<= 1) { + if ((M25_CS_MASK & cs) == 0) + continue; + + ao_mutex_get(&ao_m25_mutex); + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", + cs, + ao_m25_instruction[M25_MANUF_OFFSET], + ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], + ao_m25_instruction[M25_CAPACITY_OFFSET], + ao_m25_instruction[M25_UID_OFFSET]); + ao_mutex_put(&ao_m25_mutex); + } +} + +void +ao_storage_device_init(void) +{ + /* Set up chip select wires */ + SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ + SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ + SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +} diff --git a/src/gps-cksum b/src/gps-cksum deleted file mode 100755 index a08153bf..00000000 --- a/src/gps-cksum +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(string a) -{ - int c = 0; - for (int i = 0; i < String::length(a); i++) - c ^= a[i]; - return c; -} - -void main() -{ - for (int i = 1; i < dim(argv); i++) - printf ("$%s*%02x\n", argv[i], checksum(argv[i])); -} - -main(); diff --git a/src/make-altitude b/src/make-altitude deleted file mode 100644 index 716aa8a8..00000000 --- a/src/make-altitude +++ /dev/null @@ -1,283 +0,0 @@ -#!/usr/bin/nickle -f -/* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ - return 0; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted altitude */ - for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - base_pressure *= exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - base_pressure *= pow(base, exponent); - } - base_temperature += delta_z * lapse_rate[layer_number]; - } - - /* calculate the pressure at the inputted altitude */ - delta_z = altitude - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - pressure = base_pressure * exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - pressure = base_pressure * pow(base, exponent); - } - - return pressure; -} - - -/* outputs the altitude associated with the given pressure. the altitude - returned is measured with respect to the mean sea level */ -real pressure_to_altitude(real pressure) { - - real next_base_temperature = LAYER0_BASE_TEMPERATURE; - real next_base_pressure = LAYER0_BASE_PRESSURE; - - real altitude; - real base_pressure; - real base_temperature; - real base; /* base for function to determine base pressure of next layer */ - real exponent; /* exponent for function to determine base pressure - of next layer */ - real coefficient; - int layer_number; /* identifies layer in the atmosphere */ - int delta_z; /* difference between two altitudes */ - - if (pressure < 0) /* illegal pressure */ - return -1; - if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ - return MAXIMUM_ALTITUDE; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted pressure. */ - layer_number = -1; - do { - layer_number++; - base_pressure = next_base_pressure; - base_temperature = next_base_temperature; - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - next_base_pressure *= exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - next_base_pressure *= pow(base, exponent); - } - next_base_temperature += delta_z * lapse_rate[layer_number]; - } - while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); - - /* calculate the altitude associated with the inputted pressure */ - if (lapse_rate[layer_number] == 0.0) { - coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) - * base_temperature; - altitude = base_altitude[layer_number] - + coefficient * log(pressure / base_pressure); - } - else { - base = pressure / base_pressure; - exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] - / GRAVITATIONAL_ACCELERATION; - coefficient = base_temperature / lapse_rate[layer_number]; - altitude = base_altitude[layer_number] - + coefficient * (pow(base, exponent) - 1); - } - - return altitude; -} - -real feet_to_meters(real feet) -{ - return feet * (12 * 2.54 / 100); -} - -real meters_to_feet(real meters) -{ - return meters / (12 * 2.54 / 100); -} - -/* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - -real counts_per_kPa = 27 * 2047 / 3300; -real counts_at_101_3kPa = 1674; - -real fraction_to_kPa(real fraction) -{ - return (fraction + 0.095) / 0.009; -} - - -real count_to_kPa(real count) = fraction_to_kPa(count / 2047); - -typedef struct { - real m, b; - int m_i, b_i; -} line_t; - -line_t best_fit(real[] values, int first, int last) { - real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; - int n = last - first + 1; - real m, b; - int m_i, b_i; - - for (int i = first; i <= last; i++) { - sum_x += i; - sum_x2 += i**2; - sum_y += values[i]; - sum_xy += values[i] * i; - } - m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); - b = sum_y/n - m*(sum_x/n); - return (line_t) { m = m, b = b }; -} - -real count_to_altitude(real count) { - return pressure_to_altitude(count_to_kPa(count) * 1000); -} - -real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); - -int num_samples = 1024; - -real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; - -int num_part = 128; -int seg_len = num_samples / num_part; - -line_t [dim(alt) / seg_len] fit = { - [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) -}; - -int[num_samples/seg_len + 1] alt_part; - -alt_part[0] = floor (fit[0].b + 0.5); -alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); - -for (int i = 0; i < dim(fit) - 1; i++) { - real here, there; - here = fit[i].m * (i+1) * seg_len + fit[i].b; - there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; - alt_part[i+1] = floor ((here + there) / 2 + 0.5); -} - -real count_to_fit_altitude(int count) { - int sub = count // seg_len; - int off = count % seg_len; - line_t l = fit[sub]; - real r_v; - real i_v; - - r_v = count * l.m + l.b; - i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; - return i_v; -} - -real max_error = 0; -int max_error_count = 0; -real total_error = 0; - -for (int count = 0; count < num_samples; count++) { - real kPa = fraction_to_kPa(count / (num_samples - 1)); - real meters = pressure_to_altitude(kPa * 1000); - - real meters_approx = count_to_fit_altitude(count); - real error = abs(meters - meters_approx); - - total_error += error; - if (error > max_error) { - max_error = error; - max_error_count = count; - } -# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", -# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); -} - -printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); - -printf ("#define NALT %d\n", dim(alt_part)); -printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); - -for (int i = 0; i < dim(alt_part); i++) { - real fraction = i / (dim(alt_part) - 1); - real kPa = fraction_to_kPa(fraction); - printf ("%9d, /* %6.2f kPa %7.3f%% */\n", - alt_part[i], kPa, fraction * 100); -} diff --git a/src/make-kalman b/src/make-kalman deleted file mode 100644 index 9ac35134..00000000 --- a/src/make-kalman +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -cd ../kalman - -SIGMA_BOTH="-M 2 -H 6 -A 2" -SIGMA_BARO="-M 2 -H 6 -A 2" -SIGMA_ACCEL="-M 2 -H 4 -A 4" - -nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH - -nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL - -nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO -nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO -nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt new file mode 100644 index 00000000..99730b9f --- /dev/null +++ b/src/product/Makefile.telebt @@ -0,0 +1,97 @@ +# +# TeleBT build file +# +# Define TELEBT_VER, TELEBT_DEF, TELEBT_INC and TELEBT_SRC +# and include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h \ + $(TELEBT_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_btm.c + +PRODUCT_SRC = \ + ao_telebt.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) \ + $(TELEBT_SRC) + +PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx +PRODUCT=TeleBT-v$(TELEBT_VER) +PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF) +IDPRODUCT=0x000e + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle new file mode 100644 index 00000000..f32c037f --- /dev/null +++ b/src/product/Makefile.teledongle @@ -0,0 +1,96 @@ +# +# TeleDongle build file +# +# The various teledongle versions differ only +# in minor pin variations +# so the per-board makefiles simply define +# TD_VER, TD_DEF and include +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_teledongle.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teledongle-v$(TD_VER)-$(VERSION).ihx +PRODUCT=TeleDongle-v$(TD_VER) +PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF) +IDPRODUCT=0x000c + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum new file mode 100644 index 00000000..fd958aea --- /dev/null +++ b/src/product/Makefile.telemetrum @@ -0,0 +1,111 @@ +# +# TeleMetrum build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h \ + $(TM_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_gps_report.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_big.c \ + ao_report.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_ignite.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TM_SRC) + +PRODUCT_SRC = \ + ao_telemetrum.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PRODUCT=TeleMetrum-v$(TM_VER) +PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) +IDPRODUCT=0x000b + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini new file mode 100644 index 00000000..3bd14226 --- /dev/null +++ b/src/product/Makefile.telemini @@ -0,0 +1,100 @@ +# +# TeleMini build file +# +# Define TELEMINI_VER and TELEMINI_DEF and then +# include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_flight.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_mutex.c \ + ao_panic.c \ + ao_report.c \ + ao_sample.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_dma.c \ + ao_ignite.c \ + ao_intflash.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telemini.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx +PRODUCT=TeleMini-v$(TELEMINI_VER) +PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) +IDPRODUCT=0x000a +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano new file mode 100644 index 00000000..72043044 --- /dev/null +++ b/src/product/Makefile.telenano @@ -0,0 +1,99 @@ +# +# TeleNano build file +# +# Define TELENANO_VER and TELENANO_DEF and then +# include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_flight_nano.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_mutex.c \ + ao_panic.c \ + ao_report.c \ + ao_sample.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_dma.c \ + ao_intflash.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telenano.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx +PRODUCT=TeleNano-v$(TELENANO_VER) +PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF) +IDPRODUCT=0x000a +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c new file mode 100644 index 00000000..85565172 --- /dev/null +++ b/src/product/ao_telebt.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); +#if HAS_BEEP + ao_beep_init(); +#endif + ao_cmd_init(); +#if HAS_EEPROM + ao_spi_init(); + ao_storage_init(); +#endif + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c new file mode 100644 index 00000000..008b200a --- /dev/null +++ b/src/product/ao_teledongle.c @@ -0,0 +1,40 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telemetrum.c b/src/product/ao_telemetrum.c new file mode 100644 index 00000000..f560740a --- /dev/null +++ b/src/product/ao_telemetrum.c @@ -0,0 +1,70 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_gps_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c new file mode 100644 index 00000000..fa23de01 --- /dev/null +++ b/src/product/ao_telemini.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telenano.c b/src/product/ao_telenano.c new file mode 100644 index 00000000..d91983d0 --- /dev/null +++ b/src/product/ao_telenano.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_nano_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_teleterra.c b/src/product/ao_teleterra.c new file mode 100644 index 00000000..d696b914 --- /dev/null +++ b/src/product/ao_teleterra.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_NO_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_beep_init(); + ao_cmd_init(); + ao_usb_init(); + ao_serial_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_radio_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_test.c b/src/product/ao_test.c new file mode 100644 index 00000000..14c2eb75 --- /dev/null +++ b/src/product/ao_test.c @@ -0,0 +1,117 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +struct ao_task __xdata blink_0_task; +struct ao_task __xdata blink_1_task; +struct ao_task __xdata wakeup_task; +struct ao_task __xdata beep_task; +struct ao_task __xdata echo_task; + +void delay(int n) __reentrant +{ + uint8_t j = 0; + while (--n) + while (--j) + ao_yield(); +} + +static __xdata uint8_t blink_chan; + +void +blink_0(void) +{ + uint8_t b = 0; + for (;;) { + b = 1 - b; + if (b) + ao_led_on(AO_LED_GREEN); + else + ao_led_off(AO_LED_GREEN); + ao_sleep(&blink_chan); + } +} + +void +blink_1(void) +{ + static __xdata struct ao_adc adc; + + for (;;) { + ao_sleep(&ao_adc_head); + ao_adc_get(&adc); + if (adc.accel < 15900) + ao_led_on(AO_LED_RED); + else + ao_led_off(AO_LED_RED); + } +} + +void +wakeup(void) +{ + for (;;) { + ao_delay(AO_MS_TO_TICKS(100)); + ao_wakeup(&blink_chan); + } +} + +void +beep(void) +{ + static __xdata struct ao_adc adc; + + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + ao_adc_get(&adc); + if (adc.temp > 7400) + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50)); + } +} + +void +echo(void) +{ + char c; + for (;;) { + ao_usb_flush(); + c = ao_usb_getchar(); + ao_usb_putchar(c); + if (c == '\r') + ao_usb_putchar('\n'); + } +} + +void +main(void) +{ + ao_clock_init(); + +// ao_add_task(&blink_0_task, blink_0); +// ao_add_task(&blink_1_task, blink_1); +// ao_add_task(&wakeup_task, wakeup); +// ao_add_task(&beep_task, beep); + ao_add_task(&echo_task, echo); + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_led_init(); + ao_usb_init(); + + ao_start_scheduler(); +} diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c new file mode 100644 index 00000000..3b7c2733 --- /dev/null +++ b/src/product/ao_tidongle.c @@ -0,0 +1,42 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_NO_SERIAL_ISR 1 +#define AO_NO_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(AO_LED_RED); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_RED, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_dbg_init(); + ao_config_init(); + /* Bring up the USB link */ + P1DIR |= 1; + P1 |= 1; + ao_start_scheduler(); +} diff --git a/src/sirf-cksum b/src/sirf-cksum deleted file mode 100755 index b905f318..00000000 --- a/src/sirf-cksum +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(int[] msg) -{ - int sum = 0; - for (int i = 0; i < dim(msg); i++) { - sum += msg[i]; - sum &= 0x7fff; - } - return sum; -} - -void main() -{ - string[...] input; - int[...] msg; - - setdim(input, 0); - while (!File::end(stdin)) { - input[dim(input)] = gets(); - } - - setdim(msg, 0); - for (int i = 0; i < dim(input); i++) { - string[*] words = String::wordsplit(input[i], " ,\t"); - for (int j = 0; j < dim(words); j++) { - if (words[j] == "/" + "*") - break; - if (String::length(words[j]) > 0 && - Ctype::isdigit(words[j][0])) { - msg[dim(msg)] = string_to_integer(words[j]); - } - } - } - printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n", - dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); - for (int i = 0; i < dim(input); i++) - printf("%s\n", input[i]); - int csum = checksum(msg); - printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n", - csum >> 8, csum & 0xff); -} - -main(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum deleted file mode 100644 index ab0464a7..00000000 --- a/src/skytraq-cksum +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(int[] msg) -{ - int sum = 0; - for (int i = 0; i < dim(msg); i++) { - sum ^= msg[i]; - sum &= 0xff; - } - return sum; -} - -void main() -{ - string[...] input; - int[...] msg; - - setdim(input, 0); - while (!File::end(stdin)) { - input[dim(input)] = gets(); - } - - setdim(msg, 0); - for (int i = 0; i < dim(input); i++) { - string[*] words = String::wordsplit(input[i], " ,\t"); - for (int j = 0; j < dim(words); j++) { - if (words[j] == "/" + "*") - break; - if (String::length(words[j]) > 0 && - Ctype::isdigit(words[j][0])) { - msg[dim(msg)] = string_to_integer(words[j]); - } - } - } - printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", - dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); - for (int i = 0; i < dim(input); i++) - printf("%s\n", input[i]); - int csum = checksum(msg); - printf ("\t0x%02x, 0x0d, 0x0a,\n", - csum); -} - -main(); diff --git a/src/telebt-v0.0/Makefile b/src/telebt-v0.0/Makefile index d8867b19..e89639ab 100644 --- a/src/telebt-v0.0/Makefile +++ b/src/telebt-v0.0/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleBT v0.0 build +# + +TELEBT_VER=0.0 +TELEBT_DEF=0_0 + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs deleted file mode 100644 index f0bb5e0c..00000000 --- a/src/telebt-v0.0/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.0-$(VERSION).ihx - -SRC = \ - $(TBT_BASE_SRC) - -PRODUCT=TeleBT-v0.0 -PRODUCT_DEF=-DTELEBT_V_0_0 -IDPRODUCT=0x000e diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index d8867b19..a34e8912 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -1 +1,19 @@ -include ../Makefile.proto +# +# TeleBT v0.1 build +# + +TELEBT_VER=0.1 +TELEBT_DEF=0_1 + +TELEBT_INC = \ + ao_25lc1024.h + +TELEBT_SRC = \ + ao_beep.c \ + ao_log_telem.c \ + ao_spi.c \ + ao_storage.c \ + ao_m25.c + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs deleted file mode 100644 index 50657c83..00000000 --- a/src/telebt-v0.1/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.1-$(VERSION).ihx - -SRC = \ - $(TBT_V_0_1_SRC) - -PRODUCT=TeleBT-v0.1 -PRODUCT_DEF=-DTELEBT_V_0_1 -IDPRODUCT=0x000e diff --git a/src/teledongle-v0.1/Makefile b/src/teledongle-v0.1/Makefile index d8867b19..48425107 100644 --- a/src/teledongle-v0.1/Makefile +++ b/src/teledongle-v0.1/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.1 +TD_DEF=0_1 + +include ../product/Makefile.teledongle diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs deleted file mode 100644 index ceb80b7a..00000000 --- a/src/teledongle-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.1-$(VERSION).ihx - -SRC = \ - $(TD_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleDongle-v0.1 -PRODUCT_DEF=-DTELEDONGLE_V_0_1 -IDPRODUCT=0x000c diff --git a/src/teledongle-v0.2/Makefile b/src/teledongle-v0.2/Makefile index d8867b19..ce4ab437 100644 --- a/src/teledongle-v0.2/Makefile +++ b/src/teledongle-v0.2/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.2 +TD_DEF=0_2 + +include ../product/Makefile.teledongle \ No newline at end of file diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs deleted file mode 100644 index ea9713b6..00000000 --- a/src/teledongle-v0.2/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.2-$(VERSION).ihx - -SRC = \ - $(TD_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleDongle-v0.2 -PRODUCT_DEF=-DTELEDONGLE_V_0_2 -IDPRODUCT=0x000c diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index d8867b19..00cdc9c5 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ + ao_25lc1024.h + +TM_SRC = \ + ao_gps_sirf.c \ + ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs deleted file mode 100644 index ac8dcdb9..00000000 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sirf-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(EE_DRIVER_SRC) \ - $(SIRF_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1-SiRF -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index d8867b19..e3c61db6 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ + ao_25lc1024.h + +TM_SRC = \ + ao_gps_skytraq.c \ + ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs deleted file mode 100644 index e032d1eb..00000000 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sky-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(EE_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1 -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile index d8867b19..4aae84c8 100644 --- a/src/telemetrum-v1.0/Makefile +++ b/src/telemetrum-v1.0/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v1.0 build +# + +TM_VER=1.0 +TM_DEF=1_0 + +TM_INC = \ + ao_at45db161d.h + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_at45db161d.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs deleted file mode 100644 index 5eefc392..00000000 --- a/src/telemetrum-v1.0/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.0-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(FLASH_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(COMPANION_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v1.0 -PRODUCT_DEF=-DTELEMETRUM_V_1_0 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile index d8867b19..4bea03db 100644 --- a/src/telemetrum-v1.1/Makefile +++ b/src/telemetrum-v1.1/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# AltOS build +# +# + +TM_VER=1.1 +TM_DEF=1_1 + +TM_INC = + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs deleted file mode 100644 index 3c8b8793..00000000 --- a/src/telemetrum-v1.1/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.1-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(M25_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(COMPANION_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v1.1 -PRODUCT_DEF=-DTELEMETRUM_V_1_1 -IDPRODUCT=0x000b diff --git a/src/telemini-v1.0/Makefile b/src/telemini-v1.0/Makefile index d8867b19..4f1c8b51 100644 --- a/src/telemini-v1.0/Makefile +++ b/src/telemini-v1.0/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleMini build file +# + +TELEMINI_VER=1.0 +TELEMINI_DEF=1_0 + +include ../product/Makefile.telemini diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs deleted file mode 100644 index 0e91f2fc..00000000 --- a/src/telemini-v1.0/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telemini-v1.0-$(VERSION).ihx - -SRC = \ - $(TMINI_BASE_SRC) - -PRODUCT=TeleMini-v1.0 -PRODUCT_DEF=-DTELEMINI_V_1_0 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telenano-v0.1/Makefile b/src/telenano-v0.1/Makefile index d8867b19..2714c1e9 100644 --- a/src/telenano-v0.1/Makefile +++ b/src/telenano-v0.1/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleNano build file +# + +TELENANO_VER=0.1 +TELENANO_DEF=0_1 + +include ../product/Makefile.telenano + diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs deleted file mode 100644 index 34cf69d1..00000000 --- a/src/telenano-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telenano-v0.1-$(VERSION).ihx - -SRC = \ - $(TNANO_BASE_SRC) - -PRODUCT=TeleNano-v0.1 -PRODUCT_DEF=-DTELENANO_V_0_1 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/test/Makefile b/src/test/Makefile index 33203ffd..333850e4 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,9 +1,8 @@ -vpath % .. -vpath % ../kalman +vpath % ..:../core:../drivers PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test -CFLAGS=-I.. -I. +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g all: $(PROGS) @@ -13,22 +12,19 @@ clean: install: ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c + cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c + cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_convert_test: ao_convert_test.c ao_convert.c altitude.h - cc -g -o $@ $< - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< > $@ + cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c new file mode 100644 index 00000000..56733c89 --- /dev/null +++ b/src/test/ao_flight_test.c @@ -0,0 +1,716 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#define AO_HERTZ 100 + +#define AO_ADC_RING 64 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +/* + * One set of samples read from the A/D converter + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t pres_real; /* unclipped */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define __pdata +#define __data +#define __xdata +#define __code +#define __reentrant + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 +#define AO_BARO_SATURATE 13000 +#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern enum ao_flight_state ao_flight_state; + +#define FALSE 0 +#define TRUE 1 + +struct ao_adc ao_adc_ring[AO_ADC_RING]; +uint8_t ao_adc_head; +int ao_summary = 0; + +#define ao_led_on(l) +#define ao_led_off(l) +#define ao_timer_set_adc_interval(i) +#define ao_wakeup(wchan) ao_dump_state() +#define ao_cmd_register(c) +#define ao_usb_disable() +#define ao_telemetry_set_interval(x) +#define ao_rdf_set(rdf) +#define ao_packet_slave_start() +#define ao_packet_slave_stop() + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +struct ao_adc ao_adc_static; + +int drogue_height; +double drogue_time; +int main_height; +double main_time; + +int tick_offset; + +static int32_t ao_k_height; + +void +ao_ignite(enum ao_igniter igniter) +{ + double time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (igniter == ao_igniter_drogue) { + drogue_time = time; + drogue_height = ao_k_height >> 16; + } else { + main_time = time; + main_height = ao_k_height >> 16; + } +} + +struct ao_task { + int dummy; +}; + +#define ao_add_task(t,f,n) + +#define ao_log_start() +#define ao_log_stop() + +#define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_SEC_TO_TICKS(s) ((s) * 100) + +#define AO_FLIGHT_TEST + +int ao_flight_debug; + +FILE *emulator_in; +char *emulator_app; +char *emulator_name; +double emulator_error_max = 4; +double emulator_height_error_max = 20; /* noise in the baro sensor */ + +void +ao_dump_state(void); + +void +ao_sleep(void *wchan); + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + +#include "ao_convert.c" + +struct ao_config { + uint16_t main_deploy; + int16_t accel_plus_g; + int16_t accel_minus_g; + uint8_t pad_orientation; +}; + +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + +#define ao_config_get() + +struct ao_config ao_config; + +#define DATA_TO_XDATA(x) (x) + +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#define HAS_ACCEL_REF 0 +#endif + +#define GRAVITY 9.80665 +extern int16_t ao_ground_accel, ao_flight_accel; +extern int16_t ao_accel_2g; + +extern uint16_t ao_sample_tick; + +extern int16_t ao_sample_height; +extern int16_t ao_sample_accel; +extern int32_t ao_accel_scale; +extern int16_t ao_ground_height; +extern int16_t ao_sample_alt; + +int ao_sample_prev_tick; +uint16_t prev_tick; + +#include "ao_kalman.c" +#include "ao_sample.c" +#include "ao_flight.c" + +#define to_double(f) ((f) / 65536.0) + +static int ao_records_read = 0; +static int ao_eof_read = 0; +static int ao_flight_ground_accel; +static int ao_flight_started = 0; +static int ao_test_max_height; +static double ao_test_max_height_time; +static int ao_test_main_height; +static double ao_test_main_height_time; +static double ao_test_landed_time; +static double ao_test_landed_height; +static double ao_test_landed_time; +static int landed_set; +static double landed_time; +static double landed_height; + +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + double landed_error; + double landed_time_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + landed_error = fabs(ao_test_landed_height - landed_height); + landed_time_error = ao_test_landed_time - landed_time; + if (drogue_error > emulator_error_max || main_error > emulator_error_max || + landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tLanded height error %g\n", landed_error); + printf ("\tLanded time error %g\n", landed_time_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time, + ao_test_landed_height, ao_test_landed_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + drogue_height, drogue_time, main_height, main_time, + landed_height, landed_time); + exit (1); + } + exit(0); +} + +void +ao_insert(void) +{ + double time; + + ao_adc_ring[ao_adc_head] = ao_adc_static; + ao_adc_head = ao_adc_ring_next(ao_adc_head); + if (ao_flight_state != ao_flight_startup) { + double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + (ao_config.accel_minus_g - ao_config.accel_plus_g); + + if (!tick_offset) + tick_offset = -ao_adc_static.tick; + if ((prev_tick - ao_adc_static.tick) > 0x400) + tick_offset += 65536; + prev_tick = ao_adc_static.tick; + time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + ao_test_landed_height = height; + ao_test_landed_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + + if (ao_test_landed_height > height) { + ao_test_landed_height = height; + ao_test_landed_time = time; + } + + if (ao_flight_state == ao_flight_landed && !landed_set) { + landed_set = 1; + landed_time = time; + landed_height = height; + } + + if (!ao_summary) { + printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", + time, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + ao_avg_height, + drogue_height, + main_height, + ao_error_h_sq_avg); + +// if (ao_flight_state == ao_flight_landed) +// ao_test_exit(); + } + } +} + +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; +}; + +uint16_t +uint16(uint8_t *bytes, int off) +{ + off++; + return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); +} + +int16_t +int16(uint8_t *bytes, int off) +{ + return (int16_t) uint16(bytes, off); +} + +void +ao_sleep(void *wchan) +{ + if (wchan == &ao_adc_head) { + char type; + uint16_t tick; + uint16_t a, b; + int ret; + uint8_t bytes[1024]; + union ao_telemetry_all telem; + char line[1024]; + char *saveptr; + char *l; + char *words[64]; + int nword; + + for (;;) { + if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) + { + ao_adc_static.accel = ao_flight_ground_accel; + ao_insert(); + return; + } + + if (!fgets(line, sizeof (line), emulator_in)) { + if (++ao_eof_read >= 1000) { + if (!ao_summary) + printf ("no more data, exiting simulation\n"); + ao_test_exit(); + } + ao_adc_static.tick += 10; + ao_insert(); + return; + } + l = line; + for (nword = 0; nword < 64; nword++) { + words[nword] = strtok_r(l, " \t\n", &saveptr); + l = NULL; + if (words[nword] == NULL) + break; + } + if (nword == 4) { + type = words[0][0]; + tick = strtoul(words[1], NULL, 16); + a = strtoul(words[2], NULL, 16); + b = strtoul(words[3], NULL, 16); + if (type == 'P') + type = 'A'; + } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { + ao_config.accel_plus_g = atoi(words[3]); + ao_config.accel_minus_g = atoi(words[5]); + } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { + ao_config.main_deploy = atoi(words[2]); + } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { + tick = atoi(words[10]); + if (!ao_flight_started) { + type = 'F'; + a = atoi(words[26]); + ao_flight_started = 1; + } else { + type = 'A'; + a = atoi(words[12]); + b = atoi(words[14]); + } + } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { + tick = strtol(words[1], NULL, 16); + a = 16384 - 328; + b = strtol(words[2], NULL, 10); + type = 'A'; + if (!ao_flight_started) { + ao_flight_ground_accel = 16384 - 328; + ao_config.accel_plus_g = 16384 - 328; + ao_config.accel_minus_g = 16384 + 328; + ao_flight_started = 1; + } + } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { + char *hex = words[1]; + char elt[3]; + int i, len; + uint8_t sum; + + len = strlen(hex); + if (len > sizeof (bytes) * 2) { + len = sizeof (bytes)*2; + hex[len] = '\0'; + } + for (i = 0; i < len; i += 2) { + elt[0] = hex[i]; + elt[1] = hex[i+1]; + elt[2] = '\0'; + bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); + } + len = i/2; + if (bytes[0] != len - 2) { + printf ("bad length %d != %d\n", bytes[0], len - 2); + continue; + } + sum = 0x5a; + for (i = 1; i < len-1; i++) + sum += bytes[i]; + if (sum != bytes[len-1]) { + printf ("bad checksum\n"); + continue; + } + if ((bytes[len-2] & 0x80) == 0) { + continue; + } + if (len == 36) { + memcpy(&telem, bytes + 1, 32); + tick = telem.generic.tick; + switch (telem.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (!ao_flight_started) { + ao_flight_ground_accel = telem.sensor.ground_accel; + ao_config.accel_plus_g = telem.sensor.accel_plus_g; + ao_config.accel_minus_g = telem.sensor.accel_minus_g; + ao_flight_started = 1; + } + type = 'A'; + a = telem.sensor.accel; + b = telem.sensor.pres; + break; + } + } else if (len == 99) { + ao_flight_started = 1; + tick = uint16(bytes, 21); + ao_flight_ground_accel = int16(bytes, 7); + ao_config.accel_plus_g = int16(bytes, 17); + ao_config.accel_minus_g = int16(bytes, 19); + type = 'A'; + a = int16(bytes, 23); + b = int16(bytes, 25); + } else if (len == 98) { + ao_flight_started = 1; + tick = uint16(bytes, 20); + ao_flight_ground_accel = int16(bytes, 6); + ao_config.accel_plus_g = int16(bytes, 16); + ao_config.accel_minus_g = int16(bytes, 18); + type = 'A'; + a = int16(bytes, 22); + b = int16(bytes, 24); + } else { + printf("unknown len %d\n", len); + continue; + } + } + if (type != 'F' && !ao_flight_started) + continue; + + switch (type) { + case 'F': + ao_flight_ground_accel = a; + if (ao_config.accel_plus_g == 0) { + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; + } + if (ao_config.main_deploy == 0) + ao_config.main_deploy = 250; + ao_flight_started = 1; + break; + case 'S': + break; + case 'A': + ao_adc_static.tick = tick; + ao_adc_static.accel = a; + ao_adc_static.pres_real = b; + if (b < AO_MIN_BARO_VALUE) + b = AO_MIN_BARO_VALUE; + ao_adc_static.pres = b; + ao_records_read++; + ao_insert(); + return; + case 'T': + ao_adc_static.tick = tick; + ao_adc_static.temp = a; + ao_adc_static.v_batt = b; + break; + case 'D': + case 'G': + case 'N': + case 'W': + case 'H': + break; + } + } + + } +} +#define COUNTS_PER_G 264.8 + +void +ao_dump_state(void) +{ +} + +static const struct option options[] = { + { .name = "summary", .has_arg = 0, .val = 's' }, + { .name = "debug", .has_arg = 0, .val = 'd' }, + { 0, 0, 0, 0}, +}; + +void run_flight_fixed(char *name, FILE *f, int summary) +{ + emulator_name = name; + emulator_in = f; + ao_summary = summary; + ao_flight_init(); + ao_flight(); +} + +int +main (int argc, char **argv) +{ + int summary = 0; + int c; + int i; + +#if HAS_ACCEL + emulator_app="full"; +#else + emulator_app="baro"; +#endif + while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { + switch (c) { + case 's': + summary = 1; + break; + case 'd': + ao_flight_debug = 1; + break; + } + } + + if (optind == argc) + run_flight_fixed("", stdin, summary); + else + for (i = optind; i < argc; i++) { + FILE *f = fopen(argv[i], "r"); + if (!f) { + perror(argv[i]); + continue; + } + run_flight_fixed(argv[i], f, summary); + fclose(f); + } +} diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c new file mode 100644 index 00000000..93d7a9ab --- /dev/null +++ b/src/test/ao_gps_test.c @@ -0,0 +1,508 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10â· */ + int32_t longitude; /* degrees * 10â· */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_sirf_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t sirf_message[4096]; +static int sirf_message_len; +static uint8_t sirf_in_message[4096]; +static int sirf_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; + if (sirf_in_len || uc == 0xa0) { + if (sirf_in_len < 4096) + sirf_in_message[sirf_in_len++] = uc; + if (uc == 0xb3) { + check_sirf_message("recv", sirf_in_message, sirf_in_len); + sirf_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (sirf_message_len || uc == 0xa0) { + if (sirf_message_len < 4096) + sirf_message[sirf_message_len++] = uc; + if (uc == 0xb3) { + check_sirf_message("send", sirf_message, sirf_message_len); + sirf_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_57600 1 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#define ao_time() 0 + +#include "ao_gps_print.c" +#include "ao_gps_sirf.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; + printf ("%02d:%02d:%02d", + ao_gps_data.hour, ao_gps_data.minute, + ao_gps_data.second); + printf (" nsat %d %svalid", + ao_gps_data.flags & AO_GPS_NUM_SAT_MASK, + ao_gps_data.flags & AO_GPS_VALID ? "" : "not "); + printf (" lat %g lon %g alt %d", + ao_gps_data.latitude / 1.0e7, + ao_gps_data.longitude / 1.0e7, + ao_gps_data.altitude); + printf (" speed %g climb %g course %d", + ao_gps_data.ground_speed / 100.0, + ao_gps_data.climb_rate / 100.0, + ao_gps_data.course * 2); + printf (" hdop %g h_error %d v_error %d", + ao_gps_data.hdop / 5.0, + ao_gps_data.h_error, ao_gps_data.v_error); + printf("\n"); + printf ("\t"); + for (i = 0; i < 12; i++) + printf (" %2d(%02d)", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\n"); +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps_setup(); + ao_gps(); +} diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c new file mode 100644 index 00000000..a78fae0f --- /dev/null +++ b/src/test/ao_gps_test_skytraq.c @@ -0,0 +1,490 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10â· */ + int32_t longitude; /* degrees * 10â· */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_skytraq_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + +// fwrite(msg, 1, len, stdout); + return; + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t skytraq_message[4096]; +static int skytraq_message_len; +static uint8_t skytraq_in_message[4096]; +static int skytraq_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; +// printf ("c: %02x %c\n", uc, uc); + if (skytraq_in_len || uc == '$') { + if (skytraq_in_len < 4096) + skytraq_in_message[skytraq_in_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); + skytraq_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (skytraq_message_len || uc == 0xa0) { + if (skytraq_message_len < 4096) + skytraq_message[skytraq_message_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("send", skytraq_message, skytraq_message_len); + skytraq_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_9600: + cfsetspeed(&termios, B38400); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#define ao_time() 0 + +#include "ao_gps_print.c" +#include "ao_gps_skytraq.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps(); +} diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index d8867b19..fc8df1f4 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -1 +1,92 @@ -include ../Makefile.proto +# +# TIDongle build file +# + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_tidongle.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = tidongle-$(VERSION).ihx +PRODUCT=TIDongle +PRODUCT_DEF=-DTIDONGLE +IDPRODUCT=0x000a + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs deleted file mode 100644 index 0e13cb20..00000000 --- a/src/tidongle/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = tidongle-$(VERSION).ihx - -SRC = \ - $(TI_SRC) - -PRODUCT=TIDongle - -PRODUCT_DEF=-DTIDONGLE -IDPRODUCT=0x000a diff --git a/src/util/ao-make-product.5c b/src/util/ao-make-product.5c new file mode 100644 index 00000000..5f2eb8e8 --- /dev/null +++ b/src/util/ao-make-product.5c @@ -0,0 +1,103 @@ +#!/bin/sh + +autoimport ParseArgs; + +void +write_ucs2(string a, string description) +{ + int len = String::length(a); + + printf("/* %s */\n", description); + printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2); + printf("#define AO_%s_STRING \"%s\"\n", description, a); + printf("#define AO_%s_UCS2", description); + for (int i = 0; i < len; i++) { + int c = a[i]; + if (i > 0) + printf(","); + if (0x20 <= c && c < 128) + printf(" '%c', 0", c); + else + printf(" LE_WORD(0x%04x),", c); + } + printf("\n\n"); +} + +void +write_string(string a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_STRING \"%s\"\n", description, a); +} + +void +write_int(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER %d\n\n", description, a); +} + +void +write_hex(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); +} + +string manufacturer = "altusmetrum.org"; +string product = "TeleMetrum"; +string version = "0.0"; +int serial = 1; +int user_argind = 0; +int id_product = 0x000a; + +argdesc argd = { + .args = { + { + .var = { .arg_string = &manufacturer }, + .abbr = 'm', + .name = "manufacturer", + .expr_name = "manf", + .desc = "Manufacturer name." }, + { + .var = { .arg_string = &product }, + .abbr = 'p', + .name = "product", + .expr_name = "prod", + .desc = "Product name." }, + { + .var = { .arg_int = &id_product }, + .abbr = 'i', + .name = "id_product", + .expr_name = "id_p", + .desc = "Product ID." }, + { + .var = { .arg_int = &serial }, + .abbr = 's', + .name = "serial", + .expr_name = "number", + .desc = "Serial number." }, + { + .var = { .arg_string = &version }, + .abbr = 'v', + .name = "version", + .expr_name = "string", + .desc = "Program version." }, + }, + .prog_name = "usb descriptors", +}; + +void +main() +{ + string[dim(argv)-1] nargv = {[n] = argv[n+1]}; + parseargs(&argd, &nargv); + write_ucs2(manufacturer, "iManufacturer"); + write_ucs2(product, "iProduct"); + write_ucs2(sprintf("%06d", serial), "iSerial"); + write_int(serial, "iSerial"); + write_hex(id_product, "idProduct"); + write_string(version, "iVersion"); +} + +main(); diff --git a/src/util/check-stack b/src/util/check-stack new file mode 100755 index 00000000..1e8044e0 --- /dev/null +++ b/src/util/check-stack @@ -0,0 +1,13 @@ +#!/bin/sh +HEADER=$1 +MEM=$2 + +HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` +MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` + +if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then + echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' + exit 1 +else + exit 0 +fi diff --git a/src/util/gps-cksum b/src/util/gps-cksum new file mode 100755 index 00000000..a08153bf --- /dev/null +++ b/src/util/gps-cksum @@ -0,0 +1,17 @@ +#!/usr/bin/env nickle + +int checksum(string a) +{ + int c = 0; + for (int i = 0; i < String::length(a); i++) + c ^= a[i]; + return c; +} + +void main() +{ + for (int i = 1; i < dim(argv); i++) + printf ("$%s*%02x\n", argv[i], checksum(argv[i])); +} + +main(); diff --git a/src/util/make-altitude b/src/util/make-altitude new file mode 100644 index 00000000..716aa8a8 --- /dev/null +++ b/src/util/make-altitude @@ -0,0 +1,283 @@ +#!/usr/bin/nickle -f +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +real pressure_to_altitude(real pressure) { + + real next_base_temperature = LAYER0_BASE_TEMPERATURE; + real next_base_pressure = LAYER0_BASE_PRESSURE; + + real altitude; + real base_pressure; + real base_temperature; + real base; /* base for function to determine base pressure of next layer */ + real exponent; /* exponent for function to determine base pressure + of next layer */ + real coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +real feet_to_meters(real feet) +{ + return feet * (12 * 2.54 / 100); +} + +real meters_to_feet(real meters) +{ + return meters / (12 * 2.54 / 100); +} + +/* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + +real counts_per_kPa = 27 * 2047 / 3300; +real counts_at_101_3kPa = 1674; + +real fraction_to_kPa(real fraction) +{ + return (fraction + 0.095) / 0.009; +} + + +real count_to_kPa(real count) = fraction_to_kPa(count / 2047); + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real count_to_altitude(real count) { + return pressure_to_altitude(count_to_kPa(count) * 1000); +} + +real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); + +int num_samples = 1024; + +real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; + +int num_part = 128; +int seg_len = num_samples / num_part; + +line_t [dim(alt) / seg_len] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real count_to_fit_altitude(int count) { + int sub = count // seg_len; + int off = count % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = count * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_count = 0; +real total_error = 0; + +for (int count = 0; count < num_samples; count++) { + real kPa = fraction_to_kPa(count / (num_samples - 1)); + real meters = pressure_to_altitude(kPa * 1000); + + real meters_approx = count_to_fit_altitude(count); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_count = count; + } +# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", +# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); + +for (int i = 0; i < dim(alt_part); i++) { + real fraction = i / (dim(alt_part) - 1); + real kPa = fraction_to_kPa(fraction); + printf ("%9d, /* %6.2f kPa %7.3f%% */\n", + alt_part[i], kPa, fraction * 100); +} diff --git a/src/util/make-kalman b/src/util/make-kalman new file mode 100644 index 00000000..f78f30a9 --- /dev/null +++ b/src/util/make-kalman @@ -0,0 +1,19 @@ +#!/bin/sh + +cd $1 >&/dev/null + +SIGMA_BOTH="-M 2 -H 6 -A 2" +SIGMA_BARO="-M 2 -H 6 -A 2" +SIGMA_ACCEL="-M 2 -H 4 -A 4" + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH + +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL + +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO diff --git a/src/util/sirf-cksum b/src/util/sirf-cksum new file mode 100755 index 00000000..b905f318 --- /dev/null +++ b/src/util/sirf-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum += msg[i]; + sum &= 0x7fff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n", + csum >> 8, csum & 0xff); +} + +main(); diff --git a/src/util/skytraq-cksum b/src/util/skytraq-cksum new file mode 100644 index 00000000..ab0464a7 --- /dev/null +++ b/src/util/skytraq-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum ^= msg[i]; + sum &= 0xff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x0d, 0x0a,\n", + csum); +} + +main(); -- cgit v1.2.3 From a588092a7d76dab92e4ab11e0fdb457d2ddc9025 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 21:10:56 -0700 Subject: altos: AVR changes - create ao_arch.h files, define ao_arch_reboot Start pulling changes needed for avr port; architecture-specific code will live in /ao_arch.h. This first change defines the ao_arch_reboot macro to reboot the microcontroller. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 32 ++++++++++++++++++++++++++++++++ src/core/ao.h | 2 +- src/core/ao_cmd.c | 13 +++---------- 4 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 src/avr/ao_arch.h create mode 100644 src/cc1111/ao_arch.h diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h new file mode 100644 index 00000000..2b566814 --- /dev/null +++ b/src/avr/ao_arch.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "avr.h" + + +/* + * AVR definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 128 + +/* Various definitions to make GCC look more like SDCC */ + +#define __naked __attribute__((naked)) + +#define ao_arch_reboot() /* XXX */ + +#endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h new file mode 100644 index 00000000..585fffe5 --- /dev/null +++ b/src/cc1111/ao_arch.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +/* + * CC1111 definitions and code fragments for AltOS + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "cc1111.h" + +#define ao_arch_reboot() do { \ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ + ao_delay(AO_SEC_TO_TICKS(2)); \ + } while (0) + +#endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 8ac9ac3d..0f1a24ad 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,7 +22,7 @@ #include #include #include -#include "cc1111.h" +#include #include "ao_pins.h" #define TRUE 1 diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 1442ebea..7663d875 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -32,7 +32,7 @@ static void put_string(__code char *s) { char c; - while (c = *s++) + while ((c = *s++)) putchar(c); } @@ -187,13 +187,6 @@ ao_match_word(__code char *word) return 1; } -static void -eol(void) -{ - while (ao_cmd_lex_c != '\n') - ao_cmd_lex(); -} - static void echo(void) { @@ -208,8 +201,7 @@ ao_reboot(void) ao_cmd_white(); if (!ao_match_word("eboot")) return; - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_delay(AO_SEC_TO_TICKS(2)); + ao_arch_reboot(); ao_panic(AO_PANIC_REBOOT); } @@ -254,6 +246,7 @@ report(void) case ao_cmd_syntax_error: puts("Syntax error"); ao_cmd_status = 0; + default: break; } } -- cgit v1.2.3 From e9fab7dc99a0e7c22b511c5919adf7df85213252 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:04:36 -0700 Subject: altos: add GCC/SDCC compat macros, init_stack, save_context and GCC stdio hooks More arch-indepdency bits. GCC stdio is different from SDCC, so create suitable code in avr/ao_avr_stdio.c Create macros to initialize the task stack frame and save the task context. Add GCC/SDCC type definition compatibility macros Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 102 ++++++++++ src/avr/ao_arch.h | 67 ++++++- src/avr/ao_avr_stdio.c | 52 +++++ src/avr/ao_pins.h | 31 +++ src/cc1111/ao_arch.h | 99 ++++++++++ src/cc1111/ao_pins.h | 425 ++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 76 ++----- src/core/ao_panic.c | 2 +- src/core/ao_pins.h | 408 -------------------------------------- src/core/ao_task.c | 60 +----- src/product/Makefile.telebt | 2 +- src/product/Makefile.teledongle | 2 +- src/product/Makefile.telemetrum | 2 +- src/product/Makefile.telemini | 2 +- src/product/Makefile.telenano | 2 +- src/tidongle/Makefile | 2 +- 16 files changed, 805 insertions(+), 529 deletions(-) create mode 100644 src/avr-demo/Makefile create mode 100644 src/avr/ao_avr_stdio.c create mode 100644 src/avr/ao_pins.h create mode 100644 src/cc1111/ao_pins.h delete mode 100644 src/core/ao_pins.h diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile new file mode 100644 index 00000000..ea356654 --- /dev/null +++ b/src/avr-demo/Makefile @@ -0,0 +1,102 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../driver +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_serial_avr.c \ + ao_avr_stdio.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c + +PRODUCT=AvrDemo-v0.0 +MCU=atmega32u4 +PRODUCT_DEF=-DAVR_DEMO +IDPRODUCT=0x000a +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues + +NICKLE=nickle + +PROG=avr-demo + +SRC=$(ALTOS_SRC) ao_demo.c ao_debug_avr.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +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 + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h \ No newline at end of file diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 2b566814..51a65880 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,18 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ -#include "avr.h" +#include +#include +#ifdef AVR_DEMO +#define TEENSY 1 +#endif + +#if TEENSY +#define F_CPU 16000000UL // 16 MHz +#else +#define F_CPU 8000000UL // 8 MHz +#endif /* * AVR definitions and code fragments for AltOS @@ -29,8 +39,61 @@ /* Various definitions to make GCC look more like SDCC */ -#define __naked __attribute__((naked)) +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) #define ao_arch_reboot() /* XXX */ +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); + +extern int ao_serial_number; + +#define ao_arch_init_stack(task, start) do { \ + uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + PUSH8(sp, a); \ + PUSH8(sp, (a >> 8)); \ + \ + /* Clear register values */ \ + i = 32; \ + while (i--) \ + PUSH8(sp, 0); \ + \ + /* SREG with interrupts enabled */ \ + PUSH8(sp, 0x80); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_context() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c new file mode 100644 index 00000000..2f358eb5 --- /dev/null +++ b/src/avr/ao_avr_stdio.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +int +stdio_put(char c, FILE *stream) +{ + if (ao_cur_task && ao_num_stdios) + putchar(c); + else + { + if (c == '\n') + stdio_put('\r', stream); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; + } + + return 0; +} + +int +stdio_get(FILE *stream) +{ + return (int) getchar() & 0xff; +} + +static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); + +void +ao_stdio_init(void) +{ + stdout = &mystdout; + stdin = &mystdin; + printf("%d stdios registered\n", ao_num_stdios); +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h new file mode 100644 index 00000000..ef41b59c --- /dev/null +++ b/src/avr/ao_pins.h @@ -0,0 +1,31 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef AVR_DEMO + #define AO_LED_RED (1<<7) + #define LEDS_AVAILABLE (AO_LED_RED) + #define USE_SERIAL_STDIN 1 + #define HAS_USB 0 + #define PACKET_HAS_SLAVE 0 + #define HAS_SERIAL_1 1 + #define HAS_BEEP 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 585fffe5..35fd66f8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -24,9 +24,108 @@ #include "cc1111.h" +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* Stack runs from above the allocated __data space to 0xfe, which avoids + * writing to 0xff as that triggers the stack overflow indicator + */ +#define AO_STACK_START 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + #define ao_arch_reboot() do { \ WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) +#define ao_arch_nop() _asm nop _endasm +#define ao_arch_interrupt(n) __interrupt n + +#define ao_arch_naked_declare __naked +#define ao_arch_naked_define __naked + +/* CC1111-specific drivers */ + +/* + * 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; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* Initialize stack */ +#define ao_arch_init_stack(task, start) { \ + uint8_t __xdata *stack = task->stack; \ + uint8_t t; \ + *stack++ = ((uint16_t) start); /* 0 */ \ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ \ + \ + /* and the stuff saved by ao_switch */ \ + *stack++ = 0; /* 2 acc */ \ + *stack++ = 0x80; /* 3 IE */ \ + \ + /* 4 DPL \ + * 5 DPH \ + * 6 B \ + * 7 R2 \ + * 8 R3 \ + * 9 R4 \ + * 10 R5 \ + * 11 R6 \ + * 12 R7 \ + * 13 R0 \ + * 14 R1 \ + * 15 PSW \ + * 16 BP \ + */ \ + for (t = 0; t < 13; t++) \ + *stack++ = 0; \ + task->stack_count = 17; \ + } + + + +/* Save current context */ + +#define ao_arch_save_context() \ + _asm \ + /* Push ACC first, as when restoring the context it must be restored \ + * last (it is used to set the IE register). */ \ + push ACC \ + /* Store the IE register then enable interrupts. */ \ + push _IEN0 \ + setb _EA \ + push DPL \ + push DPH \ + push b \ + push ar2 \ + push ar3 \ + push ar4 \ + push ar5 \ + push ar6 \ + push ar7 \ + push ar0 \ + push ar1 \ + push PSW \ + _endasm; \ + PSW = 0; \ + _asm \ + push _bp \ + _endasm + + + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h new file mode 100644 index 00000000..4ac6a84b --- /dev/null +++ b/src/cc1111/ao_pins.h @@ -0,0 +1,425 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 0f1a24ad..9b0bb545 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,21 +22,16 @@ #include #include #include -#include #include "ao_pins.h" +#include #define TRUE 1 #define FALSE 0 /* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* Stack runs from above the allocated __data space to 0xfe, which avoids - * writing to 0xff as that triggers the stack overflow indicator - */ -#define AO_STACK_START 0x90 -#define AO_STACK_END 0xfe -#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) +#ifndef DATA_TO_XDATA +#define DATA_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { @@ -75,7 +70,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) __naked; +ao_yield(void) ao_arch_naked_declare; /* Add a task to the run queue */ void @@ -136,7 +131,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) __interrupt 9; +ao_timer_isr(void) ao_arch_interrupt(9); /* Initialize the timer */ void @@ -159,20 +154,8 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - #if HAS_ADC -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif - /* * ao_adc.c */ @@ -207,7 +190,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) __interrupt 1; +ao_adc_isr(void) ao_arch_interrupt(1); /* Initialize the A/D converter */ void @@ -298,25 +281,6 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; 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; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - /* * ao_usb.c */ @@ -342,7 +306,7 @@ ao_usb_flush(void); #if HAS_USB /* USB interrupt handler */ void -ao_usb_isr(void) __interrupt 6; +ao_usb_isr(void) ao_arch_interrupt(6); #endif /* Enable the USB controller */ @@ -446,7 +410,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) __interrupt 8; +ao_dma_isr(void) ao_arch_interrupt(8); /* * ao_mutex.c @@ -927,10 +891,10 @@ ao_dbg_init(void); #endif void -ao_serial_rx1_isr(void) __interrupt 3; +ao_serial_rx1_isr(void) ao_arch_interrupt(3); void -ao_serial_tx1_isr(void) __interrupt 14; +ao_serial_tx1_isr(void) ao_arch_interrupt(14); char ao_serial_getchar(void) __critical; @@ -1251,14 +1215,6 @@ struct ao_telemetry_tiny { char callsign[AO_MAX_CALLSIGN]; }; -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { - uint8_t packet[AO_MAX_TELEMETRY + 2]; -}; - struct ao_telemetry_orig_recv { struct ao_telemetry_orig telemetry_orig; int8_t rssi; @@ -1271,6 +1227,14 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -1302,7 +1266,7 @@ extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) __interrupt 16; +ao_radio_general_isr(void) ao_arch_interrupt(16); void ao_radio_get(uint8_t len); diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index fdada201..cbfdf399 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -33,7 +33,7 @@ ao_panic_delay(uint8_t n) while (n--) while (--j) while (--i) - _asm nop _endasm; + ao_arch_nop(); } void diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h deleted file mode 100644 index e1f5459f..00000000 --- a/src/core/ao_pins.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#if defined(TELEMETRUM_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_1_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 1 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_2) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEMINI_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define USE_FAST_ASCENT_LOG 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELENANO_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_DBG 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 1 - #define HAS_ACCEL_REF 0 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 0 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TIDONGLE) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_0) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define HAS_BTM 1 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 1 - #define BT_LINK_ON_P1 0 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P2_1 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_SERIAL_1 1 - #define HAS_SERIAL_1_ALT_1 1 - #define HAS_SERIAL_1_ALT_2 0 - #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_BTM 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 0 - #define BT_LINK_ON_P1 1 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P1_7 - #define HAS_MONITOR 1 -#endif - -#if DBG_ON_P1 - - #define DBG_CLOCK (1 << 4) /* mi0 */ - #define DBG_DATA (1 << 5) /* mo0 */ - #define DBG_RESET_N (1 << 3) /* c0 */ - - #define DBG_CLOCK_PIN (P1_4) - #define DBG_DATA_PIN (P1_5) - #define DBG_RESET_N_PIN (P1_3) - - #define DBG_PORT_NUM 1 - #define DBG_PORT P1 - #define DBG_PORT_SEL P1SEL - #define DBG_PORT_INP P1INP - #define DBG_PORT_DIR P1DIR - -#endif /* DBG_ON_P1 */ - -#if DBG_ON_P0 - - #define DBG_CLOCK (1 << 3) - #define DBG_DATA (1 << 4) - #define DBG_RESET_N (1 << 5) - - #define DBG_CLOCK_PIN (P0_3) - #define DBG_DATA_PIN (P0_4) - #define DBG_RESET_N_PIN (P0_5) - - #define DBG_PORT_NUM 0 - #define DBG_PORT P0 - #define DBG_PORT_SEL P0SEL - #define DBG_PORT_INP P0INP - #define DBG_PORT_DIR P0DIR - -#endif /* DBG_ON_P0 */ - -#if COMPANION_CS_ON_P1 - #define COMPANION_CS_PORT P1 - #define COMPANION_CS_SEL P1SEL - #define COMPANION_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P1 - #define SPI_CS_PORT P1 - #define SPI_CS_SEL P1SEL - #define SPI_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P0 - #define SPI_CS_PORT P0 - #define SPI_CS_SEL P0SEL - #define SPI_CS_DIR P0DIR -#endif - -#ifndef IGNITE_ON_P2 -#error Please define IGNITE_ON_P2 -#endif - -#ifndef IGNITE_ON_P0 -#error Please define IGNITE_ON_P0 -#endif - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#ifndef HAS_EEPROM -#error Please define HAS_EEPROM -#endif - -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif - -#ifndef HAS_DBG -#error Please define HAS_DBG -#endif - -#ifndef HAS_IGNITE -#error Please define HAS_IGNITE -#endif - -#ifndef PACKET_HAS_MASTER -#error Please define PACKET_HAS_MASTER -#endif - -#ifndef PACKET_HAS_SLAVE -#error Please define PACKET_HAS_SLAVE -#endif - -#ifndef HAS_MONITOR -#error Please define HAS_MONITOR -#endif -#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index f5850fa4..41520476 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -27,7 +27,6 @@ __xdata struct ao_task *__data ao_cur_task; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { - uint8_t __xdata *stack; uint8_t task_id; uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) @@ -42,70 +41,19 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam ao_tasks[ao_num_tasks++] = task; task->task_id = task_id; task->name = name; + task->wchan = NULL; /* * Construct a stack frame so that it will 'return' * to the start of the task */ - stack = task->stack; - - *stack++ = ((uint16_t) start); /* 0 */ - *stack++ = ((uint16_t) start) >> 8; /* 1 */ - - /* and the stuff saved by ao_switch */ - *stack++ = 0; /* 2 acc */ - *stack++ = 0x80; /* 3 IE */ - - /* 4 DPL - * 5 DPH - * 6 B - * 7 R2 - * 8 R3 - * 9 R4 - * 10 R5 - * 11 R6 - * 12 R7 - * 13 R0 - * 14 R1 - * 15 PSW - * 16 BP - */ - for (t = 0; t < 13; t++) - *stack++ = 0; - - task->stack_count = 17; - task->wchan = NULL; + ao_arch_init_stack(task, start); } /* Task switching function. This must not use any stack variables */ void -ao_yield(void) __naked +ao_yield(void) ao_arch_naked_define { - - /* Save current context */ - _asm - /* Push ACC first, as when restoring the context it must be restored - * last (it is used to set the IE register). */ - push ACC - /* Store the IE register then enable interrupts. */ - push _IEN0 - setb _EA - push DPL - push DPH - push b - push ar2 - push ar3 - push ar4 - push ar5 - push ar6 - push ar7 - push ar0 - push ar1 - push PSW - _endasm; - PSW = 0; - _asm - push _bp - _endasm; + ao_arch_save_context(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 99730b9f..d9ef1ea7 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -79,7 +79,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index f32c037f..cfd9b806 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -78,7 +78,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fd958aea..2759ac52 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -93,7 +93,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 3bd14226..7f251897 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -82,7 +82,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 72043044..c47e95ff 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index fc8df1f4..247f4fe0 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -73,7 +73,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -- cgit v1.2.3 From 8125acc030574afed6f23aa8aa302d9c768bb04e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:55:33 -0700 Subject: altos: get avr-demo to build. Pull in AVR drivers and LCD driver This completes the basic task of making an AVR version of altos by getting the Teensy 'avr-demo' program to build. Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 7 +- src/avr-demo/ao_demo.c | 52 ++++ src/avr/ao_arch.h | 80 ++++-- src/avr/ao_avr_stdio.c | 2 +- src/avr/ao_debug_avr.c | 78 ++++++ src/avr/ao_led.c | 67 +++++ src/avr/ao_pins.h | 28 +- src/avr/ao_romconfig.c | 20 ++ src/avr/ao_serial_avr.c | 166 ++++++++++++ src/avr/ao_timer.c | 147 +++++++++++ src/avr/ao_usb.h | 100 +++++++ src/avr/ao_usb_avr.c | 688 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 118 +++++++-- src/core/ao.h | 11 +- src/core/ao_panic.c | 2 +- src/core/ao_task.c | 99 ++----- 16 files changed, 1542 insertions(+), 123 deletions(-) create mode 100644 src/avr-demo/ao_demo.c create mode 100644 src/avr/ao_debug_avr.c create mode 100644 src/avr/ao_led.c create mode 100644 src/avr/ao_romconfig.c create mode 100644 src/avr/ao_serial_avr.c create mode 100644 src/avr/ao_timer.c create mode 100644 src/avr/ao_usb.h create mode 100644 src/avr/ao_usb_avr.c diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile index ea356654..93295166 100644 --- a/src/avr-demo/Makefile +++ b/src/avr-demo/Makefile @@ -2,7 +2,7 @@ # AltOS build # # -vpath % ..:../core:../product:../driver +vpath % ..:../core:../product:../drivers:../avr vpath make-altitude .. vpath make-kalman .. vpath kalman.5c ../kalman @@ -38,12 +38,15 @@ ALTOS_SRC = \ ao_mutex.c \ ao_panic.c \ ao_product.c \ + ao_romconfig.c \ ao_serial_avr.c \ ao_avr_stdio.c \ ao_stdio.c \ ao_task.c \ ao_timer.c \ - ao_led.c + ao_led.c \ + ao_usb_avr.c \ + ao_lcd.c PRODUCT=AvrDemo-v0.0 MCU=atmega32u4 diff --git a/src/avr-demo/ao_demo.c b/src/avr-demo/ao_demo.c new file mode 100644 index 00000000..756dd0d4 --- /dev/null +++ b/src/avr-demo/ao_demo.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +struct ao_task demo_task; + +void +ao_demo(void) +{ + for (;;) { + ao_led_toggle(AO_LED_RED); + printf ("hello %d\n", ao_time()); + ao_delay(AO_MS_TO_TICKS(200)); + } +} + +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_avr_stdio_init(); + printf ("stdio initialized\n"); +// ao_debug_init(); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_lcd_init(); + +// ao_add_task(&demo_task, ao_demo, "demo"); + /* Turn on the LED until the system is stable */ + ao_start_scheduler(); + return 0; +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 51a65880..0ed97361 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,10 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ +#include #include #include +#include #ifdef AVR_DEMO #define TEENSY 1 @@ -48,6 +50,7 @@ #define __reentrant #define __critical #define __interrupt(n) +#define __at(n) #define ao_arch_reboot() /* XXX */ @@ -62,8 +65,18 @@ extern void putchar(char c); extern char getchar(void); +extern void ao_avr_stdio_init(void); -extern int ao_serial_number; +extern const uint16_t ao_serial_number; + +#define AVR_PUSH8(stack, val) (*((stack)--) = (val)) + +extern uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_globals uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_members\ + uint8_t *sp; /* saved stack pointer */ #define ao_arch_init_stack(task, start) do { \ uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ @@ -71,29 +84,66 @@ extern int ao_serial_number; int i; \ \ /* Return address */ \ - PUSH8(sp, a); \ - PUSH8(sp, (a >> 8)); \ + AVR_PUSH8(sp, a); \ + AVR_PUSH8(sp, (a >> 8)); \ \ /* Clear register values */ \ i = 32; \ while (i--) \ - PUSH8(sp, 0); \ + AVR_PUSH8(sp, 0); \ \ /* SREG with interrupts enabled */ \ - PUSH8(sp, 0x80); \ + AVR_PUSH8(sp, 0x80); \ task->sp = sp; \ } while (0); -#define ao_arch_save_context() do { \ - asm("push r31" "\n\t" "push r30"); \ - asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ - asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ - asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ - asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ - asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ - asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ - asm("in r0, __SREG__" "\n\t" "push r0"); \ - sei(); \ +#define ao_arch_save_regs() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + cli(); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint8_t sp_l, sp_h; \ + asm("in %0,__SP_L__" : "=&r" (sp_l) ); \ + asm("in %0,__SP_H__" : "=&r" (sp_h) ); \ + ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \ } while (0) +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + if (!ao_cpu_sleep_disable) \ + sleep_cpu(); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint8_t sp_l, sp_h; \ + sp_l = (uint16_t) ao_cur_task->sp; \ + sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \ + cli(); \ + asm("out __SP_H__,%0" : : "r" (sp_h) ); \ + asm("out __SP_L__,%0" : : "r" (sp_l) ); \ + asm("pop r0" "\n\t" \ + "out __SREG__, r0"); \ + asm("pop r0" "\n\t" "pop r1" "\n\t" "pop r2" "\n\t" "pop r3" "\n\t" "pop r4"); \ + asm("pop r5" "\n\t" "pop r6" "\n\t" "pop r7" "\n\t" "pop r8" "\n\t" "pop r9"); \ + asm("pop r10" "\n\t" "pop r11" "\n\t" "pop r12" "\n\t" "pop r13" "\n\t" "pop r14"); \ + asm("pop r15" "\n\t" "pop r16" "\n\t" "pop r17" "\n\t" "pop r18" "\n\t" "pop r19"); \ + asm("pop r20" "\n\t" "pop r21" "\n\t" "pop r22" "\n\t" "pop r23" "\n\t" "pop r24"); \ + asm("pop r25" "\n\t" "pop r26" "\n\t" "pop r27" "\n\t" "pop r28" "\n\t" "pop r29"); \ + asm("pop r30" "\n\t" "pop r31"); \ + asm("ret"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) + #endif /* _AO_ARCH_H_ */ + diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index 2f358eb5..ba562dbf 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -44,7 +44,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); void -ao_stdio_init(void) +ao_avr_stdio_init(void) { stdout = &mystdout; stdin = &mystdin; diff --git a/src/avr/ao_debug_avr.c b/src/avr/ao_debug_avr.c new file mode 100644 index 00000000..2e41e15a --- /dev/null +++ b/src/avr/ao_debug_avr.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +uart_send(char c) +{ + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +int +uart_put(char c, FILE *stream) +{ + if (c == '\n') + uart_send('\r'); + uart_send(c); + return 0; +} + +int +uart_get(FILE *stream) +{ + loop_until_bit_is_set(UCSR1A, RXC1); + return (int) UDR1 & 0xff; +} + +void +uart_init(uint16_t baud) +{ + PRR1 &= ~(1 << PRUSART1); + UBRR1L = baud; + UBRR1H = baud >> 8; + UCSR1A = 0; + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1)); /* Enable transmitter */ + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ +} + +static FILE mystdout = FDEV_SETUP_STREAM(uart_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, uart_get, _FDEV_SETUP_READ); + +void ao_debug_init(void) +{ + uart_init(F_CPU / (16UL * 9600UL) - 1); + + stdout = &mystdout; + stdin = &mystdin; + + if (DDRB & AO_LED_RED) { + printf ("oops, starting all over\n"); + for (;;) + ; + } + DDRB |= (1 << 7); + PORTB |= (1 << 7); + printf ("debug initialized\n"); +} diff --git a/src/avr/ao_led.c b/src/avr/ao_led.c new file mode 100644 index 00000000..91dfb85e --- /dev/null +++ b/src/avr/ao_led.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT PORTB +#define LED_DDR DDRB + +void +ao_led_on(uint8_t colors) +{ + LED_PORT |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT = (LED_PORT & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_led_enable = enable; + if ((LED_DDR & enable)) { + printf ("oops! restarted\n"); + ao_panic(AO_PANIC_REBOOT); + } + LED_PORT &= ~enable; + LED_DDR |= enable; +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index ef41b59c..56435f18 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -22,10 +22,36 @@ #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) #define USE_SERIAL_STDIN 1 - #define HAS_USB 0 + #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 + #define TEENSY 1 + #define AVR_VCC_5V 1 + #define AVR_VCC_3V3 0 + #define AVR_CLOCK 16000000UL #define HAS_BEEP 0 #endif +#ifdef TELESCIENCE + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 1 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_CS_PORT PORTE + #define SPI_CS_DIR DDRE + #define M25_CS_MASK (1 << PORTE6) + #define M25_MAX_CHIPS 1 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c new file mode 100644 index 00000000..bbb677e2 --- /dev/null +++ b/src/avr/ao_romconfig.c @@ -0,0 +1,20 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +const uint16_t ao_serial_number = 0; diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c new file mode 100644 index 00000000..2fe39755 --- /dev/null +++ b/src/avr/ao_serial_avr.c @@ -0,0 +1,166 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +ISR(USART1_RX_vect) +{ + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, UDR1); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + } +} + +ISR(USART1_UDRE_vect) +{ + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +static const struct { + uint16_t ubrr; +} ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + F_CPU / (16UL * 4800UL) - 1 + }, + /* [AO_SERIAL_SPEED_9600] = */ { + F_CPU / (16UL * 9600UL) - 1 + }, + /* [AO_SERIAL_SPEED_19200] = */ { + F_CPU / (16UL * 19200UL) - 1 + }, + /* [AO_SERIAL_SPEED_57600] = */ { + F_CPU / (16UL * 57600UL) - 1 + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ + ao_serial_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + UBRR1L = ao_serial_speeds[speed].ubrr; + UBRR1H = ao_serial_speeds[speed].ubrr >> 8; +} + +void +ao_serial_init(void) +{ + /* Ensure the uart is powered up */ + + PRR1 &= ~(1 << PRUSART1); + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + UCSR1A = 0; + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1) | /* Enable transmitter */ + (1 << RXCIE1) | /* Enable receive interrupts */ + (1 << UDRIE1)); /* Enable transmit empty interrupts */ +#if 0 +#if USE_SERIAL_STDIN + int8_t i; + i = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); + printf("Register serial stdio as %d\n", i); +#endif +#endif +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c new file mode 100644 index 00000000..1e374c75 --- /dev/null +++ b/src/avr/ao_timer.c @@ -0,0 +1,147 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + +ISR(TIMER1_COMPA_vect) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ + TCCR1A = ((0 << WGM11) | /* CTC mode, OCR1A */ + (0 << WGM10)); /* CTC mode, OCR1A */ + TCCR1B = ((0 << ICNC1) | /* no input capture noise canceler */ + (0 << ICES1) | /* input capture on falling edge (don't care) */ + (0 << WGM13) | /* CTC mode, OCR1A */ + (1 << WGM12) | /* CTC mode, OCR1A */ + (3 << CS10)); /* clk/64 from prescaler */ + +#if TEENSY + OCR1A = 2500; /* 16MHz clock */ +#else + OCR1A = 1250; /* 8MHz clock */ +#endif + + TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ +} + +/* + * AltOS always cranks the clock to the max frequency + */ +void +ao_clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + + /* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL + CLKPR = 1; +#else + CLKPR = 0; +#endif + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; + + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_enable(); +} diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/avr/ao_usb.h @@ -0,0 +1,100 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c new file mode 100644 index 00000000..74bdea23 --- /dev/null +++ b/src/avr/ao_usb_avr.c @@ -0,0 +1,688 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" + +#define USB_DEBUG 0 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args) +#else +#define debug(format, args...) +#endif + +struct ao_task __xdata ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} __xdata ao_usb_setup; + +static __xdata uint8_t ao_usb_ep0_state; +static const uint8_t * __xdata ao_usb_ep0_in_data; +static __xdata uint8_t ao_usb_ep0_in_len; +static __xdata uint8_t ao_usb_ep0_in_pending; +static __xdata uint8_t ao_usb_addr_pending; +static __xdata uint8_t ao_usb_ep0_in_buf[2]; +static __xdata uint8_t ao_usb_ep0_out_len; +static __xdata uint8_t *__xdata ao_usb_ep0_out_data; + +static __xdata uint8_t ao_usb_in_flushed; +static __xdata uint8_t ao_usb_running; +static __xdata uint8_t ao_usb_configuration; +static __xdata uint8_t ueienx_0; + +void +ao_usb_set_address(uint8_t address) +{ + UDADDR = (0 << ADDEN) | address; + ao_usb_addr_pending = 1; +} + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +static void +ao_usb_dump_ep(uint8_t ep) +{ + UENUM = ep; + debug ("EP %d: UECONX %02x UECFG0X %02x UECFG1X %02x UEIENX %02x UESTA0X %02x UESTA1X %02X\n", + ep, UECONX, UECFG0X, UECFG1X, UEIENX, UESTA0X, UESTA1X); +} + +static void +ao_usb_set_ep0(void) +{ + debug ("set_ep0\n"); + /* Set the CONTROL max packet size, single buffered */ + UENUM = 0; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((0 << EPTYPE0) | /* Control */ + (0 << EPDIR)); /* Out (ish) */ + + UECFG1X = (EP_SIZE(AO_USB_CONTROL_SIZE) | /* Size */ + (0 << EPBK0) | /* Single bank */ + (1 << ALLOC)); + + ueienx_0 = ((1 << RXSTPE) | /* Enable SETUP interrupt */ + (1 << RXOUTE)); /* Enable OUT interrupt */ + +// ao_usb_dump_ep(0); + ao_usb_addr_pending = 0; +} + +static void +ao_usb_set_configuration(void) +{ + /* Set the IN max packet size, double buffered */ + UENUM = AO_USB_IN_EP; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (1 << EPDIR)); /* In */ + + UECFG1X = (EP_SIZE(AO_USB_IN_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + +#if 0 + UEIENX = ((1 << TXINE)); /* Enable IN complete interrupt */ +#endif + + ao_usb_dump_ep(AO_USB_IN_EP); + + /* Set the OUT max packet size, double buffered */ + UENUM = AO_USB_OUT_EP; + UECONX |= (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (0 << EPDIR)); /* Out */ + + UECFG1X = (EP_SIZE(AO_USB_OUT_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + + UEIENX = ((1 << RXOUTE)); /* Enable OUT complete interrupt */ + + ao_usb_dump_ep(AO_USB_OUT_EP); + ao_usb_running = 1; +} + +ISR(USB_GEN_vect) +{ + ao_wakeup(&ao_usb_task); +} + + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *__xdata descriptor; + __xdata uint8_t type = value >> 8; + __xdata uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ + ao_usb_ep0_in_pending = in_pending; + + if (in_pending) + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + __xdata uint8_t this_len; + + cli(); + UENUM = 0; + if (!(UEINTX & (1 << TXINI))) { + debug("EP0 not accepting IN data\n"); + ao_usb_ep0_set_in_pending(1); + } else { + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + ao_usb_ep0_in_len -= this_len; + + /* Set IN interrupt enable */ + if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) + ao_usb_ep0_set_in_pending(0); + else + ao_usb_ep0_set_in_pending(1); + + debug ("Flush EP0 len %d:", this_len); + while (this_len--) { + uint8_t c = *ao_usb_ep0_in_data++; + debug(" %02x", c); + UEDATX = c; + } + debug ("\n"); + + /* Clear the TXINI bit to send the packet */ + UEINTX &= ~(1 << TXINI); + } + sei(); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(uint8_t len, uint8_t ack) +{ + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + +// debug ("EP0 UEINTX %02x UEBCLX %d UEBCHX %d\n", +// UEINTX, UEBCLX, UEBCHX); + /* Pull all of the data out of the packet */ + debug ("Fill EP0 len %d:", len); + UENUM = 0; + while (len--) { + uint8_t c = UEDATX; + *ao_usb_ep0_out_data++ = c; + debug (" %02x", c); + } + debug ("\n"); + + /* ACK the packet */ + UEINTX &= ~ack; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(8, (1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI)); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } +/* + UENUM = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; +*/ + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_set_address(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: +#ifndef AVR + #pragma disable_warning 110 +#endif + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + debug ("Start ep0 in delivery %d\n", ao_usb_ep0_in_len); + ao_usb_ep0_set_in_pending(1); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + cli(); + for (;;) { + udint = UDINT; + UDINT = 0; +// debug ("UDINT %02x\n", udint); + if (udint & (1 << EORSTI)) { + ao_usb_configuration = 0; + ao_usb_set_ep0(); + } + UENUM = 0; + intx = UEINTX; +// debug ("UEINTX %02x\n", intx); + if (intx & ((1 << RXSTPI) | (1 << RXOUTI))) + break; + if ((intx & (1 << TXINI))) { + if (ao_usb_ep0_in_pending) + break; + else + { + if (ao_usb_addr_pending) { + UDADDR |= (1 << ADDEN); + ao_usb_addr_pending = 0; + } + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE)); /* Disable IN interrupt */ + } + } +// debug ("usb task sleeping...\n"); + UENUM = 0; + UEIENX = ueienx_0; + ao_sleep(&ao_usb_task); + } + sei(); +// debug ("UEINTX for ep0 is %02x\n", intx); + if (intx & (1 << RXSTPI)) { + ao_usb_ep0_setup(); + } + if (intx & (1 << RXOUTI)) { + ao_usb_ep0_fill(UEBCLX, (1 << RXOUTI)); + ao_usb_ep0_set_in_pending(1); + } + if (intx & (1 << TXINI) && ao_usb_ep0_in_pending) { + debug ("continue sending ep0 IN data\n"); + ao_usb_ep0_flush(); + } + } +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + UENUM = AO_USB_IN_EP; + if (UEINTX & (1 << RWAL)) + break; + + cli(); + /* Wait for an IN buffer to be ready */ + for (;;) { + UENUM = AO_USB_IN_EP; + if ((UEINTX & (1 << TXINI))) + break; + UEIENX = (1 << TXINE); + ao_sleep(&ao_usb_in_flushed); + } + /* Ack the interrupt */ + UEINTX &= ~(1 << TXINI); + sei(); + } +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ + UENUM = AO_USB_IN_EP; + UEINTX &= ~(1 << FIFOCON); +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + if (!ao_usb_in_flushed) { + ao_usb_in_flushed = 1; + ao_usb_in_wait(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + /* Queue a byte */ + UENUM = AO_USB_IN_EP; + UEDATX = c; + + /* Send the packet when full */ + if ((UEINTX & (1 << RWAL)) == 0) + ao_usb_in_send(); + ao_usb_in_flushed = 0; +} + +static char +_ao_usb_pollchar(void) +{ + char c; + uint8_t intx; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + UENUM = AO_USB_OUT_EP; + intx = UEINTX; + debug("usb_pollchar UEINTX %02d\n", intx); + if (intx & (1 << RWAL)) + break; + + if (intx & (1 << FIFOCON)) { + /* Ack the last packet */ + UEINTX = (uint8_t) ~(1 << FIFOCON); + } + + /* Check to see if a packet has arrived */ + if ((intx & (1 << RXOUTI)) == 0) { + UENUM = AO_USB_OUT_EP; + UEIENX = (1 << RXOUTE); + return AO_READ_AGAIN; + } + + /* Ack the interrupt */ + UEINTX = ~(1 << RXOUTI); + } + + /* Pull a character out of the fifo */ + c = UEDATX; + return c; +} + +char +ao_usb_pollchar(void) +{ + char c; + cli(); + c = _ao_usb_pollchar(); + sei(); + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + cli(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + sei(); + return c; +} + +uint16_t control_count; +uint16_t in_count; +uint16_t out_count; + +/* Endpoint interrupt */ +ISR(USB_COM_vect) +{ + uint8_t old_num = UENUM; + uint8_t i = UEINT; + +#ifdef AO_LED_RED + ao_led_toggle(AO_LED_RED); +#endif + UEINT = 0; + if (i & (1 << 0)) { + UENUM = 0; + UEIENX = 0; + ao_wakeup(&ao_usb_task); + ++control_count; + } + if (i & (1 << AO_USB_IN_EP)) { + UENUM = AO_USB_IN_EP; + UEIENX = 0; + ao_wakeup(&ao_usb_in_flushed); + in_count++; + } + if (i & (1 << AO_USB_OUT_EP)) { + UENUM = AO_USB_OUT_EP; + UEIENX = 0; + ao_wakeup(&ao_stdin_ready); + ++out_count; + } + UENUM = old_num; +} + +#if AVR_VCC_5V +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn on pad regulator */ +#endif +#if AVR_VCC_3V3 +/* TeleScience V0.1 has a hardware bug -- UVcc is hooked up, but UCap is not + * Make this work by running power through UVcc to the USB system + */ +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn off pad regulator */ +#endif + +#if AVR_CLOCK == 16000000UL +#define AO_USB_PLL_INPUT_PRESCALER (1 << PINDIV) /* Divide 16MHz clock by 2 */ +#endif +#if AVR_CLOCK == 8000000UL +#define AO_USB_PLL_INPUT_PRESCALER 0 /* Don't divide clock */ +#endif + +void +ao_usb_disable(void) +{ + /* Unplug from the bus */ + UDCON = (1 << DETACH); + + /* Disable the interface */ + USBCON = 0; + + /* Disable the PLL */ + PLLCSR = 0; + + /* Turn off the pad regulator */ + UHWCON = 0; +} + +#define AO_USB_CON ((1 << USBE) | /* USB enable */ \ + (0 << RSTCPU) | /* do not reset CPU */ \ + (0 << LSM) | /* Full speed mode */ \ + (0 << RMWKUP)) /* no remote wake-up */ \ + +void +ao_usb_enable(void) +{ + /* Configure pad regulator */ + UHWCON = AO_PAD_REGULATOR_INIT; + + /* Enable USB device, but freeze the clocks until initialized */ + USBCON = AO_USB_CON | (1 <stack_count = stack_len; \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *save_ptr++ = *stack_ptr++; \ + while (--stack_len); \ + } +#define ao_arch_isr_stack() \ + /* Empty the stack; might as well let interrupts have the whole thing */ \ + (SP = AO_STACK_START - 1) + +#define ao_arch_cpu_idle() (PCON = PCON_IDLE) + +#define ao_arch_restore_stack() { \ + uint8_t stack_len; \ + __data uint8_t *stack_ptr; \ + __xdata uint8_t *save_ptr; \ + \ + /* Restore the old stack */ \ + stack_len = ao_cur_task->stack_count; \ + SP = AO_STACK_START - 1 + stack_len; \ + \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *stack_ptr++ = *save_ptr++; \ + while (--stack_len); \ + \ + _asm \ + pop _bp \ + pop PSW \ + pop ar1 \ + pop ar0 \ + pop ar7 \ + pop ar6 \ + pop ar5 \ + pop ar4 \ + pop ar3 \ + pop ar2 \ + pop b \ + pop DPH \ + pop DPL \ + /* The next byte of the stack is the IE register. Only the global \ + enable bit forms part of the task context. Pop off the IE then set \ + the global enable bit to match that of the stored IE register. */ \ + pop ACC \ + JB ACC.7,0098$ \ + CLR _EA \ + LJMP 0099$ \ + 0098$: \ + SETB _EA \ + 0099$: \ + /* Finally pop off the ACC, which was the first register saved. */ \ + pop ACC \ + ret \ + _endasm; \ +} + +#define ao_arch_critical(b) __critical { b } #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9b0bb545..98a01a4a 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ - uint8_t stack_count; /* amount of saved stack */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; @@ -321,6 +321,10 @@ ao_usb_disable(void); void ao_usb_init(void); +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + /* * ao_cmd.c */ @@ -1571,4 +1575,9 @@ extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void ao_companion_init(void); +/* ao_lcd.c */ + +void +ao_lcd_init(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index cbfdf399..0668dad2 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -53,7 +53,7 @@ ao_panic(uint8_t reason) } ao_beep(AO_BEEP_OFF); ao_panic_delay(2); -#pragma disable_warning 126 + for (n = 0; n < reason; n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 41520476..32826114 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -24,6 +24,10 @@ __data uint8_t ao_num_tasks; __data uint8_t ao_cur_task_index; __xdata struct ao_task *__data ao_cur_task; +#ifdef ao_arch_task_globals +ao_arch_task_globals +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -53,27 +57,16 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam void ao_yield(void) ao_arch_naked_define { - ao_arch_save_context(); + ao_arch_save_regs(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; else { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - /* Save the current stack */ - stack_len = SP - (AO_STACK_START - 1); - ao_cur_task->stack_count = stack_len; - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *save_ptr++ = *stack_ptr++; - while (--stack_len); + ao_arch_save_stack(); } - /* Empty the stack; might as well let interrupts have the whole thing */ - SP = AO_STACK_START - 1; + ao_arch_isr_stack(); /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine @@ -99,63 +92,20 @@ ao_yield(void) ao_arch_naked_define } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) - PCON = PCON_IDLE; + if (ao_next_task_index == ao_cur_task_index) { + ao_arch_cpu_idle(); + } } } - - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - - /* Restore the old stack */ - stack_len = ao_cur_task->stack_count; - SP = AO_STACK_START - 1 + stack_len; - - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *stack_ptr++ = *save_ptr++; - while (--stack_len); - } - - _asm - pop _bp - pop PSW - pop ar1 - pop ar0 - pop ar7 - pop ar6 - pop ar5 - pop ar4 - pop ar3 - pop ar2 - pop b - pop DPH - pop DPL - /* The next byte of the stack is the IE register. Only the global - enable bit forms part of the task context. Pop off the IE then set - the global enable bit to match that of the stored IE register. */ - pop ACC - JB ACC.7,0098$ - CLR _EA - LJMP 0099$ - 0098$: - SETB _EA - 0099$: - /* Finally pop off the ACC, which was the first register saved. */ - pop ACC - ret - _endasm; + ao_arch_restore_stack(); } uint8_t ao_sleep(__xdata void *wchan) { - __critical { + ao_arch_critical( ao_cur_task->wchan = wchan; - } + ); ao_yield(); ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { @@ -186,14 +136,16 @@ ao_alarm(uint16_t delay) } void -ao_exit(void) __critical +ao_exit(void) { - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); + ao_arch_critical( + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + ); /* we'll never get back here */ } @@ -201,16 +153,13 @@ void ao_task_info(void) { uint8_t i; - uint8_t pc_loc; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; - pc_loc = task->stack_count - 17; - printf("%12s: wchan %04x pc %04x\n", + printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan, - (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + (int16_t) task->wchan); } } -- cgit v1.2.3 From 08e3d54bacf8b38a7c33e420a0bc19bcc7acedd4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 09:35:54 -0600 Subject: moving git-buildpackage config into .git/ since it is fairly specific to Bdale's build environment, and doesn't need to be in the source package --- debian/gbp.conf | 46 ---------------------------------------------- 1 file changed, 46 deletions(-) delete mode 100644 debian/gbp.conf diff --git a/debian/gbp.conf b/debian/gbp.conf deleted file mode 100644 index 9561fdfe..00000000 --- a/debian/gbp.conf +++ /dev/null @@ -1,46 +0,0 @@ -# Configuration file for git-buildpackage and friends - -[DEFAULT] -# the default build command: -#builder = debuild -i\.git/ -I.git -# the default clean command: -cleaner = debian/rules prebuild && debuild clean -# the default branch for upstream sources: -upstream-branch = upstream -# the default branch for the debian patch: -debian-branch = master -# the default tag formats used: -#upstream-tag = upstream/%(version)s -#debian-tag = debian/%(version)s -# use pristine-tar: -pristine-tar = True - -# Options only affecting git-buildpackage -[git-buildpackage] -#upstream-branch = dfsgclean -# uncomment this to automatically GPG sign tags -#sign-tags = True -# keyid to GPG sign tags with -#keyid = 0xdeadbeef -# push to a remote repository after a successful tag: -posttag = git push --mirror -# use this for more svn-buildpackage like behaviour: -export-dir = ../build-area/altos/ -#tarball-dir = ../tarballs/ - -# Options only affecting git-import-orig -[git-import-orig] -#upstream-branch = newupstream -#debian-branch = dfsgclean -#filter = .svn - -# Options only affecting git-import-dsc -[git-import-dsc] -#upstream-branch = svn-upstream -#filter = [ 'CVS', '.cvsignore' ] - -# Options only affecting git-dch -[git-dch] -#git-log = --no-merges -#snapshot-number = snapshot + 1 - -- cgit v1.2.3 From 3cea033ec928c21b9f7b810898ed3c3cc536d2ce Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 09:41:46 -0600 Subject: get ready for a 1.0.1 release --- Releasing | 4 ++++ configure.ac | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Releasing b/Releasing index 3307b535..edfb5eb4 100644 --- a/Releasing +++ b/Releasing @@ -26,6 +26,10 @@ These are Bdale's notes on how to do a release. this pushes fresh documents to the web site + sudo debian/rules clean + + leave the build tree in an unclutterd state + Testing before a release To verify that a build works, the following need to be checked diff --git a/configure.ac b/configure.ac index f9002508..27d56751 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0) +AC_INIT([altos], 1.0.1) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 0a92eb2fa6b213533691288d8f99d72b80312983 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 09:43:06 -0600 Subject: update changelogs for Debian build --- ChangeLog | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ debian/changelog | 14 ++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/ChangeLog b/ChangeLog index 87d7951f..70d0c357 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,54 @@ +commit 3cea033ec928c21b9f7b810898ed3c3cc536d2ce +Author: Bdale Garbee +Date: Fri Aug 26 09:41:46 2011 -0600 + + get ready for a 1.0.1 release + +commit 674231773256bacd7acb4b5718c47412e47b813f +Merge: 08e3d54 3bfe8df +Author: Bdale Garbee +Date: Fri Aug 26 09:37:01 2011 -0600 + + Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos + +commit 08e3d54bacf8b38a7c33e420a0bc19bcc7acedd4 +Author: Bdale Garbee +Date: Fri Aug 26 09:35:54 2011 -0600 + + moving git-buildpackage config into .git/ since it is fairly specific to + Bdale's build environment, and doesn't need to be in the source package + +commit 3bfe8df44b575ca430ffaa051e20faa955a06c03 +Author: Keith Packard +Date: Thu Aug 25 18:02:45 2011 -0700 + + altos: Clear callsign on initial config load + + Before being written the first time, ao_config will get set to 0xff + when the config storage is read. This leaves the tail of the callsign + filled with invalid bytes. Zero the whole thing before loading the + default callsign to make sure any extra bytes are set correctly. + + Signed-off-by: Keith Packard + +commit 93ecaf7f18f8f4c15953c2e80dc9e1b20d04fdfa +Author: Bdale Garbee +Date: Thu Aug 25 15:46:30 2011 -0600 + + update TeleMini turnon script now that we've made a stable firmware release + +commit c3314dae2d3df82e188daf6ba8520cce833592c6 +Author: Bdale Garbee +Date: Thu Aug 25 03:36:25 2011 -0600 + + use multimaint-merge to make Debian changelogs less ugly + +commit f9d87de0e2681c2ec5753f4fffef0e61a3a9e144 +Author: Bdale Garbee +Date: Thu Aug 25 02:22:53 2011 -0600 + + update changelogs for Debian build + commit 41998645c04a2ee856dec272b40c2dc5913291d3 Author: Bdale Garbee Date: Thu Aug 25 02:16:17 2011 -0600 diff --git a/debian/changelog b/debian/changelog index 906c0ded..7eb0ab87 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,17 @@ +altos (1.0.1) unstable; urgency=low + + [ Bdale Garbee ] + * use multimaint-merge to make Debian changelogs less ugly + * update TeleMini turnon script now that we've made a stable firmware release + * moving git-buildpackage config into .git/ since it is fairly specific to + Bdale's build environment, and doesn't need to be in the source package + * get ready for a 1.0.1 release + + [ Keith Packard ] + * altos: Clear callsign on initial config load + + -- Bdale Garbee Fri, 26 Aug 2011 09:42:35 -0600 + altos (1.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 58a74c3c3dcd01509224326cffeb67a3e809e4e6 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:07:15 -0600 Subject: fix telemini firmware path name --- ao-bringup/turnon_telemini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 0cb3d029..4450d6f6 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -42,7 +42,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v0.1*.ihx $SERIAL +$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/stable/telemini-v1.0*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 1d15c841ad276127edae0345bd316c30731fffbf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:24:35 -0600 Subject: ignore generated log file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 0d36192c..1773096d 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,4 @@ tags doc/telemetrum.fo doc/telemetrum.html doc/telemetrum.pdf +altosui/altos-windows.log -- cgit v1.2.3 From 13e6e799070a1469cbc2ff990379ee520b8f0e6a Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:29:58 -0600 Subject: roll release notes version from 1.0 to 1.0.1 --- doc/Makefile | 2 +- doc/release-notes-1.0.1.xsl | 103 ++++++++++++++++++++++++++++++++++++++++++++ doc/release-notes-1.0.xsl | 103 -------------------------------------------- 3 files changed, 104 insertions(+), 104 deletions(-) create mode 100644 doc/release-notes-1.0.1.xsl delete mode 100644 doc/release-notes-1.0.xsl diff --git a/doc/Makefile b/doc/Makefile index 35858b15..14bce5c9 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -7,7 +7,7 @@ RELNOTES=\ release-notes-0.8.html \ release-notes-0.9.html \ release-notes-0.9.2.html \ - release-notes-1.0.html + release-notes-1.0.1.html RELNOTES_XSL=$(RELNOTES:.html=.xsl) HTML=altusmetrum.html altos.html telemetry.html $(RELNOTES) diff --git a/doc/release-notes-1.0.1.xsl b/doc/release-notes-1.0.1.xsl new file mode 100644 index 00000000..1e9fcabc --- /dev/null +++ b/doc/release-notes-1.0.1.xsl @@ -0,0 +1,103 @@ + + + +
+ + Version 1.0.1 is a major release, adding support for the TeleMini + device and lots of new AltosUI features + + + AltOS Firmware Changes + + + Add TeleMini v1.0 support. Firmware images for TeleMini are + included in AltOS releases. + + + Change telemetry to be encoded in multiple 32-byte packets. This + enables support for TeleMini and other devices without requiring + further updates to the TeleDongle firmware. + + + Support operation of TeleMetrum with the antenna pointing + aft. Previous firmware versions required the antenna to be + pointing upwards, now there is a configuration option allowing + the antenna to point aft, to aid installation in some airframes. + + + Ability to disable telemetry. For airframes where an antenna + just isn't possible, or where radio transmissions might cause + trouble with other electronics, there's a configuration option + to disable all telemetry. Note that the board will still + enable the radio link in idle mode. + + + Arbitrary frequency selection. The radios in Altus Metrum + devices can be programmed to a wide range of frequencies, so + instead of limiting devices to 10 pre-selected 'channels', the + new firmware allows the user to choose any frequency in the + 70cm band. Note that the RF matching circuit on the boards is + tuned for around 435MHz, so frequencies far from that may + reduce the available range. + + + Kalman-filter based flight-tracking. The model based sensor + fusion approach of a Kalman filter means that AltOS now + computes apogee much more accurately than before, generally + within a fraction of a second. In addition, this approach + allows the baro-only TeleMini device to correctly identify + Mach transitions, avoiding the error-prone selection of a Mach + delay. + + + + + AltosUI Changes + + + Wait for altimeter when using packet mode. Instead of quicly + timing out when trying to initialize a packet mode + configuration connection, AltosUI now waits indefinitely for + the remote device to appear, providing a cancel button should + the user get bored. This is necessary as the TeleMini can only + be placed in "Idle" mode if AltosUI is polling it. + + + Add main/apogee voltage graphs to the data plot. This provides + a visual indication if the igniters fail before being fired. + + + Scan for altimeter devices by watching the defined telemetry + frequencies. This avoids the problem of remembering what + frequency a device was configured to use, which is especially + important with TeleMini which does not include a USB connection. + + + Monitor altimeter state in "Idle" mode. This provides much of + the information presented in the "Pad" dialog from the Monitor + Flight command, monitoring the igniters, battery and GPS + status withing requiring the flight computer to be armed and + ready for flight. + + + Pre-load map images from home. For those launch sites which + don't provide free Wi-Fi, this allows you to download the + necessary satellite images given the location of the launch + site. A list of known launch sites is maintained at + altusmetrum.org which AltosUI downloads to populate a menu; if + you've got a launch site not on that list, please send the + name of it, latitude and longitude along with a link to the + web site of the controlling club to the altusmetrum mailing list. + + + Flight statistics are now displayed in the Graph data + window. These include max height/speed/accel, average descent + rates and a few other bits of information. The Graph Data + window can now be reached from the 'Landed' tab in the Monitor + Flight window so you can immediately see the results of a + flight. + + + +
diff --git a/doc/release-notes-1.0.xsl b/doc/release-notes-1.0.xsl deleted file mode 100644 index 1a06a43d..00000000 --- a/doc/release-notes-1.0.xsl +++ /dev/null @@ -1,103 +0,0 @@ - - - -
- - Version 1.0 is a major release, adding support for the TeleMini - device and lots of new AltosUI features - - - AltOS Firmware Changes - - - Add TeleMini v1.0 support. Firmware images for TeleMini are - included in AltOS releases. - - - Change telemetry to be encoded in multiple 32-byte packets. This - enables support for TeleMini and other devices without requiring - further updates to the TeleDongle firmware. - - - Support operation of TeleMetrum with the antenna pointing - aft. Previous firmware versions required the antenna to be - pointing upwards, now there is a configuration option allowing - the antenna to point aft, to aid installation in some airframes. - - - Ability to disable telemetry. For airframes where an antenna - just isn't possible, or where radio transmissions might cause - trouble with other electronics, there's a configuration option - to disable all telemetry. Note that the board will still - enable the radio link in idle mode. - - - Arbitrary frequency selection. The radios in Altus Metrum - devices can be programmed to a wide range of frequencies, so - instead of limiting devices to 10 pre-selected 'channels', the - new firmware allows the user to choose any frequency in the - 70cm band. Note that the RF matching circuit on the boards is - tuned for around 435MHz, so frequencies far from that may - reduce the available range. - - - Kalman-filter based flight-tracking. The model based sensor - fusion approach of a Kalman filter means that AltOS now - computes apogee much more accurately than before, generally - within a fraction of a second. In addition, this approach - allows the baro-only TeleMini device to correctly identify - Mach transitions, avoiding the error-prone selection of a Mach - delay. - - - - - AltosUI Changes - - - Wait for altimeter when using packet mode. Instead of quicly - timing out when trying to initialize a packet mode - configuration connection, AltosUI now waits indefinitely for - the remote device to appear, providing a cancel button should - the user get bored. This is necessary as the TeleMini can only - be placed in "Idle" mode if AltosUI is polling it. - - - Add main/apogee voltage graphs to the data plot. This provides - a visual indication if the igniters fail before being fired. - - - Scan for altimeter devices by watching the defined telemetry - frequencies. This avoids the problem of remembering what - frequency a device was configured to use, which is especially - important with TeleMini which does not include a USB connection. - - - Monitor altimeter state in "Idle" mode. This provides much of - the information presented in the "Pad" dialog from the Monitor - Flight command, monitoring the igniters, battery and GPS - status withing requiring the flight computer to be armed and - ready for flight. - - - Pre-load map images from home. For those launch sites which - don't provide free Wi-Fi, this allows you to download the - necessary satellite images given the location of the launch - site. A list of known launch sites is maintained at - altusmetrum.org which AltosUI downloads to populate a menu; if - you've got a launch site not on that list, please send the - name of it, latitude and longitude along with a link to the - web site of the controlling club to the altusmetrum mailing list. - - - Flight statistics are now displayed in the Graph data - window. These include max height/speed/accel, average descent - rates and a few other bits of information. The Graph Data - window can now be reached from the 'Landed' tab in the Monitor - Flight window so you can immediately see the results of a - flight. - - - -
-- cgit v1.2.3 From bc399d97a8424a5262f66a03e3bc403f793bb337 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:38:44 -0600 Subject: roll back packaging changelog for rebuild --- debian/changelog | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/debian/changelog b/debian/changelog index 7eb0ab87..906c0ded 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,17 +1,3 @@ -altos (1.0.1) unstable; urgency=low - - [ Bdale Garbee ] - * use multimaint-merge to make Debian changelogs less ugly - * update TeleMini turnon script now that we've made a stable firmware release - * moving git-buildpackage config into .git/ since it is fairly specific to - Bdale's build environment, and doesn't need to be in the source package - * get ready for a 1.0.1 release - - [ Keith Packard ] - * altos: Clear callsign on initial config load - - -- Bdale Garbee Fri, 26 Aug 2011 09:42:35 -0600 - altos (1.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 01aee9ebe517ed657692e0a39a31ae0ddfb5b8b0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:39:45 -0600 Subject: update changelogs for Debian build --- ChangeLog | 30 ++++++++++++++++++++++++++++++ debian/changelog | 19 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/ChangeLog b/ChangeLog index 70d0c357..bcb4d6eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,33 @@ +commit bc399d97a8424a5262f66a03e3bc403f793bb337 +Author: Bdale Garbee +Date: Fri Aug 26 10:38:44 2011 -0600 + + roll back packaging changelog for rebuild + +commit 13e6e799070a1469cbc2ff990379ee520b8f0e6a +Author: Bdale Garbee +Date: Fri Aug 26 10:29:58 2011 -0600 + + roll release notes version from 1.0 to 1.0.1 + +commit 1d15c841ad276127edae0345bd316c30731fffbf +Author: Bdale Garbee +Date: Fri Aug 26 10:24:35 2011 -0600 + + ignore generated log file + +commit 58a74c3c3dcd01509224326cffeb67a3e809e4e6 +Author: Bdale Garbee +Date: Fri Aug 26 10:07:15 2011 -0600 + + fix telemini firmware path name + +commit 0a92eb2fa6b213533691288d8f99d72b80312983 +Author: Bdale Garbee +Date: Fri Aug 26 09:43:06 2011 -0600 + + update changelogs for Debian build + commit 3cea033ec928c21b9f7b810898ed3c3cc536d2ce Author: Bdale Garbee Date: Fri Aug 26 09:41:46 2011 -0600 diff --git a/debian/changelog b/debian/changelog index 906c0ded..a662e1c3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,22 @@ +altos (1.0.1) unstable; urgency=low + + [ Bdale Garbee ] + * use multimaint-merge to make Debian changelogs less ugly + * update TeleMini turnon script now that we've made a stable firmware release + * moving git-buildpackage config into .git/ since it is fairly specific to + Bdale's build environment, and doesn't need to be in the source package + * get ready for a 1.0.1 release + * update changelogs for Debian build + * fix telemini firmware path name + * ignore generated log file + * roll release notes version from 1.0 to 1.0.1 + * roll back packaging changelog for rebuild + + [ Keith Packard ] + * altos: Clear callsign on initial config load + + -- Bdale Garbee Fri, 26 Aug 2011 10:39:29 -0600 + altos (1.0) unstable; urgency=low [ Keith Packard ] -- cgit v1.2.3 From 9451ae5e4ea6ecfa512ba93197351682d4d043dc Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:51:18 -0600 Subject: update release process docs --- Releasing | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Releasing b/Releasing index edfb5eb4..80d39f6a 100644 --- a/Releasing +++ b/Releasing @@ -4,10 +4,9 @@ These are Bdale's notes on how to do a release. git tag -a - git-buildpackage --git-ignore-new + - make sure checked-out tree is "clean" so git won't complain - use --git-ignore-new so trash in checked-out tree doesn't - cause the build to fail! + git-buildpackage at this point, we have Debian packages @@ -18,6 +17,9 @@ These are Bdale's notes on how to do a release. this pushes packages for each platform to web site + - copy the relevant release notes file from doc/ to + /home/bdale/web/altusmetrum/AltOS/releases/ + - go edit ~/web/altusmetrum/AltOS/releases/.mdwn to include release date and explicit ref to dir contents so the AltOS page shows versioned links, commit and push -- cgit v1.2.3 From 93b8f40bb451c9ec152490d1f431ab18f8ecb7d1 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 26 Aug 2011 10:52:55 -0600 Subject: more release process doc updates --- Releasing | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Releasing b/Releasing index 80d39f6a..4d2f8e71 100644 --- a/Releasing +++ b/Releasing @@ -10,6 +10,8 @@ These are Bdale's notes on how to do a release. at this point, we have Debian packages + git tag debian/ + make distclean ./autogen.sh --with-fat-dir=/home/bdale/web/altusmetrum/AltOS/releases @@ -29,8 +31,10 @@ These are Bdale's notes on how to do a release. this pushes fresh documents to the web site sudo debian/rules clean + git push + git push --tags - leave the build tree in an unclutterd state + push commits and leave the build tree in an uncluttered state Testing before a release -- cgit v1.2.3 From c32893ce79835a8f861d6ef414644c2ff9769ff6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 15:02:43 -0700 Subject: altos: Integrate telescience support Adds a few drivers including an LCD driver Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 129 +++++++++++++++++++ src/avr/ao_arch.h | 9 ++ src/avr/ao_spi_slave.c | 142 +++++++++++++++++++++ src/avr/ao_spi_usart.c | 112 +++++++++++++++++ src/cc1111/ao_arch.h | 12 ++ src/core/ao.h | 40 ++++-- src/core/ao_log_telescience.c | 274 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_panic.c | 4 + src/drivers/ao_companion.c | 2 +- src/drivers/ao_lcd.c | 281 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_m25.c | 2 + src/product/ao_telescience.c | 39 ++++++ src/telescience-v0.1/Makefile | 109 ++++++++++++++++ src/util/check-avr-mem | 9 ++ 15 files changed, 1153 insertions(+), 13 deletions(-) create mode 100644 src/avr/ao_adc_avr.c create mode 100644 src/avr/ao_spi_slave.c create mode 100644 src/avr/ao_spi_usart.c create mode 100644 src/core/ao_log_telescience.c create mode 100644 src/drivers/ao_lcd.c create mode 100644 src/product/ao_telescience.c create mode 100644 src/telescience-v0.1/Makefile create mode 100644 src/util/check-avr-mem diff --git a/src/Makefile b/src/Makefile index 4e40c2bf..caa91e83 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - tidongle test + tidongle test telescience-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c new file mode 100644 index 00000000..5afced74 --- /dev/null +++ b/src/avr/ao_adc_avr.c @@ -0,0 +1,129 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; + +const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { + 0x00, + 0x01, + 0x04, + 0x05, + 0x06, + 0x07, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, +}; + +static uint8_t ao_adc_channel; + +#define ADC_CHANNEL_LOW(c) (((c) & 0x1f) << MUX0) +#define ADC_CHANNEL_HIGH(c) ((((c) & 0x20) >> 5) << MUX5) + +#define ADCSRA_INIT ((1 << ADEN) | /* Enable ADC */ \ + (0 << ADATE) | /* No auto ADC trigger */ \ + (1 << ADIF) | /* Clear interrupt */ \ + (0 << ADIE) | /* Enable interrupt */ \ + (6 << ADPS0)) /* Prescale clock by 64 */ + +#define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ + (0 << ACME) | /* Some comparitor thing */ \ + (2 << ADTS0)) /* Free running mode (don't care) */ + +static void +ao_adc_start(void) +{ + uint8_t channel = adc_channels[ao_adc_channel]; + ADMUX = ((0 << REFS1) | /* AVcc reference */ + (1 << REFS0) | /* AVcc reference */ + (1 << ADLAR) | /* Left-shift results */ + (ADC_CHANNEL_LOW(channel))); /* Select channel */ + + ADCSRB = (ADCSRB_INIT | + ADC_CHANNEL_HIGH(channel)); /* High channel bit */ + + ADCSRA = (ADCSRA_INIT | + (1 << ADSC) | + (1 << ADIE)); /* Start conversion */ +} + +ISR(ADC_vect) +{ + uint16_t value; + + /* Must read ADCL first or the value there will be lost */ + value = ADCL; + value |= (ADCH << 8); + ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + ao_adc_start(); + else { + ADCSRA = ADCSRA_INIT; + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup((void *) &ao_adc_head); + ao_cpu_sleep_disable = 0; + } +} + +void +ao_adc_poll(void) +{ + ao_cpu_sleep_disable = 1; + ao_adc_channel = 0; + ao_adc_start(); +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_adc_head); + memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ + static __xdata struct ao_adc packet; + uint8_t i; + ao_adc_get(&packet); + printf("tick: %5u", packet.tick); + for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + printf (" %2d: %5u", i, packet.adc[i]); + printf ("\n"); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + DIDR0 = 0xf3; + DIDR2 = 0x3f; + ADCSRB = ADCSRB_INIT; + ADCSRA = ADCSRA_INIT; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 0ed97361..c695a725 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -145,5 +145,14 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_critical(b) do { cli(); b; sei(); } while (0) +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c new file mode 100644 index 00000000..4dde09f3 --- /dev/null +++ b/src/avr/ao_spi_slave.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +static uint8_t +ao_spi_read(uint8_t *buf, uint8_t len) +{ + while (len--) { + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return 0; + *buf++ = SPDR; + } + return 1; +} + +static void +ao_spi_write(uint8_t *buf, uint8_t len) +{ + while (len--) { + SPDR = *buf++; + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return; + } + /* Clear pending SPIF bit by reading */ + (void) SPDR; +} + +static uint8_t ao_spi_slave_recv(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return 0; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return 0; + } + + ao_log_store.tm_tick = ao_companion_command.tick; + if (ao_log_store.tm_state != ao_companion_command.flight_state) { + ao_log_store.tm_state = ao_companion_command.flight_state; + return 1; + } + return 0; +} + +static uint8_t ao_spi_slave_running; + +ISR(PCINT0_vect) +{ + if ((PINB & (1 << PINB0)) == 0) { + if (!ao_spi_slave_running) { + uint8_t changed; + ao_spi_slave_running = 1; + cli(); + changed = ao_spi_slave_recv(); + sei(); + if (changed && ao_flight_boost <= ao_log_store.tm_state) { + if (ao_log_store.tm_state < ao_flight_landed) + ao_log_start(); + else + ao_log_stop(); + } + } + } else { + ao_spi_slave_running = 0; + } +} + +void ao_spi_slave_debug(void) { + printf ("slave running %d\n", ao_spi_slave_running); +} + +void +ao_spi_slave_init(void) +{ + PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, input */ + (0 << 1) | /* SCK, input */ + (0 << 0)); /* SS, input */ + + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ + PORTB = ((PORTB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, no pull-up */ + (0 << 1) | /* SCK, no pull-up */ + (0 << 0)); /* SS, no pull-up */ + + SPCR = (0 << SPIE) | /* Disable SPI interrupts */ + (1 << SPE) | /* Enable SPI */ + (0 << DORD) | /* MSB first */ + (0 << MSTR) | /* Slave mode */ + (0 << CPOL) | /* Clock low when idle */ + (0 << CPHA); /* Sample at leading clock edge */ +} diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c new file mode 100644 index 00000000..6ed708ff --- /dev/null +++ b/src/avr/ao_spi_usart.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* + * Atmega32u4 USART in MSPIM (master SPI mode) + */ + +__xdata uint8_t ao_spi_mutex; + +/* Send bytes over SPI. + * + * This just polls; the SPI is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = *d++; + while (!(UCSR1A & (1 << RXC1))); + (void) UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = 0; + while (!(UCSR1A & (1 << RXC1))); + *d++ = UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +#define XCK1_DDR DDRD +#define XCK1_PORT PORTD +#define XCK1 PORTD5 +#define XMS1_DDR DDRE +#define XMS1_PORT PORTE +#define XMS1 PORTE6 + +void +ao_spi_init(void) +{ + /* Ensure the USART is powered */ + PRR1 &= ~(1 << PRUSART1); + + /* + * Set pin directions + */ + XCK1_DDR |= (1 << XCK1); + + /* Clear chip select (which is negated) */ + XMS1_PORT |= (1 < XMS1); + XMS1_DDR |= (1 << XMS1); + + /* Set baud register to zero (required before turning transmitter on) */ + UBRR1 = 0; + + UCSR1C = ((0x3 << UMSEL10) | /* Master SPI mode */ + (0 << UCSZ10) | /* SPI mode 0 */ + (0 << UCPOL1)); /* SPI mode 0 */ + + /* Enable transmitter and receiver */ + UCSR1B = ((1 << RXEN1) | + (1 << TXEN1)); + + /* It says that 0 is a legal value; we'll see... */ + UBRR1 = 0; +} diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index c4972819..8a41791f 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -192,4 +192,16 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define AO_ADC_RING 32 + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 98a01a4a..05f056fd 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -144,15 +144,6 @@ ao_clock_init(void); /* * One set of samples read from the A/D converter or telemetry */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; #if HAS_ADC @@ -160,7 +151,6 @@ struct ao_adc { * ao_adc.c */ -#define AO_ADC_RING 32 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -505,6 +495,23 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +extern struct ao_log_telescience ao_log_store; + /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -970,6 +977,16 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; void ao_spi_init(void); +/* + * ao_spi_slave.c + */ + +void +ao_spi_slave_debug(void); + +void +ao_spi_slave_init(void); + /* * ao_telemetry.c */ @@ -1568,8 +1585,9 @@ struct ao_companion_setup { }; extern __pdata uint8_t ao_companion_running; -extern __xdata struct ao_companion_setup ao_companion_setup; extern __xdata uint8_t ao_companion_mutex; +extern __xdata struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c new file mode 100644 index 00000000..aac780fa --- /dev/null +++ b/src/core/ao_log_telescience.c @@ -0,0 +1,274 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +static struct ao_task ao_log_task; +//static struct ao_task ao_spi_task; + +uint8_t ao_log_running; +uint8_t ao_log_mutex; +uint32_t ao_log_start_pos; +uint32_t ao_log_end_pos; +uint32_t ao_log_current_pos; + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +struct ao_log_telescience ao_log_store; +struct ao_log_telescience ao_log_fetch; + +static uint8_t ao_log_adc_pos; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + sum += *b++; + return -sum; +} + +static uint8_t +ao_log_telescience_write(void) +{ + uint8_t wrote = 0; + + ao_log_store.csum = 0; + ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + (__xdata uint8_t *) &ao_log_store, + sizeof (struct ao_log_telescience)); + ao_log_current_pos += sizeof (struct ao_log_telescience); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_valid(struct ao_log_telescience *log) +{ + uint8_t *d; + uint8_t i; + d = (uint8_t *) log; + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + if (d[i] != 0xff) + return 1; + return 0; +} + +static uint8_t +ao_log_telescience_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) + return 0; + return ao_log_valid(&ao_log_fetch); +} + +void +ao_log_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_telescience(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(10)); + + ao_log_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_start_pos = ao_log_current_pos; + ao_log_store.type = AO_LOG_TELESCIENCE_START; + ao_log_store.tick = ao_time(); + ao_log_store.adc[0] = ao_companion_command.serial; + ao_log_store.adc[1] = ao_companion_command.flight; + ao_log_telescience_write(); + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_adc_head) { + ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_log_telescience_write(); + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep((void *) &ao_adc_head); + } + memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + } +} + +void +ao_log_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_list(void) +{ + uint32_t pos; + uint32_t start = 0; + uint8_t flight = 0; + + for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { + if (pos >= ao_storage_config || + !ao_log_telescience_read(pos) || + ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + { + if (pos != start) { + printf("flight %d start %x end %x\n", + flight, + (uint16_t) (start >> 8), + (uint16_t) ((pos + 0xff) >> 8)); flush(); + } + if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + break; + start = pos; + flight++; + } + } + printf ("done\n"); +} + +void +ao_log_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_telescience_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +static void +ao_log_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + printf("log data tick: %04x\n", ao_log_store.tick); + printf("TM data tick: %04x\n", ao_log_store.tm_tick); + printf("TM state: %d\n", ao_log_store.tm_state); + printf("TM serial: %d\n", ao_companion_command.serial); + printf("TM flight: %d\n", ao_companion_command.flight); +} + +const struct ao_cmds ao_log_cmds[] = { + { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_list, "l\0List stored flight logs" }, + { ao_log_delete, "d 1\0Delete all stored flights" }, + { ao_log_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_cmds[0]); + + ao_add_task(&ao_log_task, ao_log_telescience, "log"); +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 0668dad2..b6ff65cc 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -24,6 +24,10 @@ #if !HAS_BEEP #define ao_beep(x) #endif +#if !LEDS_AVAILABLE +#define ao_led_on(x) +#define ao_led_off(x) +#endif static void ao_panic_delay(uint8_t n) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 4c8f4269..2e587f8e 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -30,7 +30,7 @@ #define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) #define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) -static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c new file mode 100644 index 00000000..5bc89bbd --- /dev/null +++ b/src/drivers/ao_lcd.c @@ -0,0 +1,281 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +void +ao_lcd_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_set_bits(data); + return n; +} + +uint8_t +ao_lcd_get_status(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(0); + low = ao_lcd_get_nibble(0); + data = (high << 4) | low; + printf ("\tLCD status %02x\n", data); + return data; +} + +uint8_t +ao_lcd_get_data(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(1); + low = ao_lcd_get_nibble(1); + data = (high << 4) | low; + printf ("\tLCD data %02x\n", data); + return data; +} + +void +ao_lcd_wait_idle(void) +{ + uint8_t status; + uint8_t count = 0; + + do { + status = ao_lcd_get_status(); + count++; + if (count > 100) { + printf("idle timeout\n"); + break; + } + } while (0); /* status & 0x80); */ +} + +void +ao_lcd_send_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + ao_lcd_set_bits(data); +} + +static uint16_t ao_lcd_time = 3; + +void +ao_lcd_delay(void) +{ + volatile uint16_t count; + + for (count = 0; count < ao_lcd_time; count++) + ; +} + +void +ao_lcd_send_ins(uint8_t data) +{ +// printf("send ins %02x\n", data); +// ao_lcd_wait_idle(); +// ao_delay(1); + ao_lcd_delay(); + ao_lcd_send_nibble(0, data >> 4); + ao_lcd_send_nibble(0, data & 0xf); +} + +void +ao_lcd_send_data(uint8_t data) +{ +// printf ("send data %02x\n", data); +// ao_lcd_wait_idle(); + ao_lcd_delay(); + ao_lcd_send_nibble(1, data >> 4); + ao_lcd_send_nibble(1, data & 0x0f); +} + +void +ao_lcd_send_string(char *string) +{ + uint8_t c; + + while ((c = (uint8_t) *string++)) + ao_lcd_send_data(c); +} + +#define AO_LCD_POWER_CONTROL 0x54 + +void +ao_lcd_contrast_set(uint8_t contrast) +{ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); + ao_lcd_send_ins(0x70 | (contrast & 0xf)); +} + +void +ao_lcd_clear(void) +{ + ao_lcd_send_ins(0x01); + ao_delay(1); + /* Entry mode */ + ao_lcd_send_ins(0x04 | 0x02); +} + +void +ao_lcd_start(void) +{ + /* get to 4bit mode */ + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x2); + + /* function set */ + ao_lcd_send_ins(0x28); + /* function set, instruction table 1 */ + ao_lcd_send_ins(0x29); + + /* freq set */ + ao_lcd_send_ins(0x14); + + /* Power/icon/contrast control*/ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL); + + /* Follower control */ + ao_lcd_send_ins(0x6d); + ao_delay(AO_MS_TO_TICKS(200)); + + /* contrast set */ + ao_lcd_contrast_set(0x18); + + /* Display on */ + ao_lcd_send_ins(0x08 | 0x04); + + /* Clear */ + ao_lcd_clear(); + +} + +void +ao_lcd_contrast(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting contrast to %02x\n", ao_cmd_lex_i); + ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); + } +} + +static uint8_t +ao_cmd_hex_nibble(void) +{ + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + return ao_cmd_lex_c - '0'; + if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + return ao_cmd_lex_c - ('a' - 10); + if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + return ao_cmd_lex_c - ('A' - 10); + ao_cmd_status = ao_cmd_syntax_error; + return 0; +} + +void +ao_lcd_string(void) +{ + uint8_t col = 0; + uint8_t c; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); + ao_cmd_white(); + while (ao_cmd_lex_c != '\n') { + c = ao_cmd_lex_c; + if (c == '\\') { + ao_cmd_lex(); + c = ao_cmd_hex_nibble() << 4; + ao_cmd_lex(); + c |= ao_cmd_hex_nibble(); + } + ao_lcd_send_data(c); + ao_cmd_lex(); + col++; + } + while (col < 16) { + ao_lcd_send_data(' '); + col++; + } +} + +void +ao_lcd_delay_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting LCD delay to %d\n", ao_cmd_lex_i); + ao_lcd_time = ao_cmd_lex_i; + } +} + +__code struct ao_cmds ao_lcd_cmds[] = { + { ao_lcd_start, "S\0Start LCD" }, + { ao_lcd_contrast, "C \0Set LCD contrast" }, + { ao_lcd_string, "s \0Send string to LCD" }, + { ao_lcd_delay_set, "t \0Set LCD delay" }, + { 0, NULL }, +}; + +void +ao_lcd_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; + ao_cmd_register(&ao_lcd_cmds[0]); +} diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index d7208273..28cb1dd7 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -376,5 +376,7 @@ ao_storage_device_init(void) /* Set up chip select wires */ SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ +#ifdef SPI_CS_SEL SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +#endif } diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c new file mode 100644 index 00000000..4dec3a18 --- /dev/null +++ b/src/product/ao_telescience.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_spi_slave_init(); + ao_storage_init(); + ao_usb_init(); + ao_adc_init(); + ao_log_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile new file mode 100644 index 00000000..3ccbb787 --- /dev/null +++ b/src/telescience-v0.1/Makefile @@ -0,0 +1,109 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +# +# Common AltOS sources +# +TELESCIENCE_STORAGE= \ + ao_m25.c \ + ao_spi_usart.c \ + ao_storage.c \ + +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_spi_slave.c \ + ao_log_telescience.c \ + $(TELESCIENCE_STORAGE) + +PRODUCT=TeleScience-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELESCIENCE +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telescience-v0.1 + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +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 + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem new file mode 100644 index 00000000..c73edbd1 --- /dev/null +++ b/src/util/check-avr-mem @@ -0,0 +1,9 @@ +#!/bin/sh +nm "$@" | +grep ' N _end' | +awk '{ iram = strtonum("0x" $1) % 0x10000; +if ( iram > 0xaff) { + printf ("%d bytes of ram more than %d available\n", iram, 0xaff); + exit(1); +} else + exit(0); }' -- cgit v1.2.3 From 1c46c419704f661064d200432eb7efeeb11b3859 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 20:46:47 -0700 Subject: altos: re-order ao_task to match single-arch code This is just for testing to make the new build match the old build exactly. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index 05f056fd..c926c001 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ - ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; -- cgit v1.2.3 From b10fbbf0830053a39e4640a53598b1c027615c63 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:44:13 -0700 Subject: altos: Add 'send all baro' compile-time option This option creates a new packet type that delivers full sensor-rate barometer telemetry data to allow for off-line analysis of flight algorithms using all of the data, rather than the slower rate provided either over telemetry or stored in the eeprom file. Define AO_SEND_ALL_BARO and this will get built in. Perhaps this could be a run-time option... Signed-off-by: Keith Packard --- src/core/ao.h | 31 +++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/src/core/ao.h b/src/core/ao.h index c926c001..0cff0436 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1118,6 +1118,30 @@ struct ao_telemetry_companion { /* 32 */ }; +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; @@ -1125,6 +1149,7 @@ union ao_telemetry_all { struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; struct ao_telemetry_companion companion; + struct ao_telemetry_baro baro; }; /* @@ -1258,9 +1283,15 @@ struct ao_telemetry_raw_recv { /* Set delay between telemetry reports (0 to disable) */ +#ifdef AO_SEND_ALL_BARO +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100) +#else #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) #define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) +#endif void ao_telemetry_set_interval(uint16_t interval); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c7338a58..de669ce1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -94,6 +94,30 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +static uint8_t ao_baro_sample; + +#ifdef AO_SEND_ALL_BARO +static void +ao_send_baro(void) +{ + uint8_t sample = ao_sample_adc; + uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + + if (samples > 12) { + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + samples = 12; + } + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_BARO; + telemetry.baro.samples = samples; + for (sample = 0; sample < samples; sample++) { + telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; + ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + } + ao_radio_send(&telemetry, sizeof (telemetry)); +} +#endif + static void ao_send_configuration(void) { @@ -193,6 +217,9 @@ ao_telemetry(void) while (ao_telemetry_interval) { +#ifdef AO_SEND_ALL_BARO + ao_send_baro(); +#endif ao_send_sensor(); #if HAS_COMPANION if (ao_companion_running) @@ -203,12 +230,14 @@ ao_telemetry(void) ao_send_location(); ao_send_satellite(); #endif +#ifndef AO_SEND_ALL_BARO if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; ao_radio_rdf(AO_RDF_LENGTH_MS); } +#endif time += ao_telemetry_interval; delay = time - ao_time(); if (delay > 0) -- cgit v1.2.3 -- cgit v1.2.3 From f145be3fc4ee94fdb5c1e2406b6c11d38bdbbd9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Jul 2011 20:01:47 -0700 Subject: altos: Start telelaunch product Looks a lot like TM, but without the flight code. Signed-off-by: Keith Packard --- src/Makefile | 3 ++- src/cc1111/ao_adc.c | 4 ++++ src/cc1111/ao_pins.h | 29 +++++++++++++++++++++++++++++ src/core/ao_config.c | 8 +++++--- src/telelaunch-v0.1/.gitignore | 2 ++ src/telelaunch-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile | 1 + src/telelaunch-v0.1/Makefile.defs | 11 +++++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/telelaunch-v0.1/.gitignore create mode 100644 src/telelaunch-v0.1/.sdcdbrc create mode 100644 src/telelaunch-v0.1/Makefile create mode 100644 src/telelaunch-v0.1/Makefile.defs diff --git a/src/Makefile b/src/Makefile index caa91e83..9ef5ae0a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,6 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ + telelaunch-v0.1 \ tidongle test telescience-v0.1 all: all-local all-recursive @@ -50,4 +51,4 @@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c sh $< kalman > $@ clean-local: - rm -f altitude.h ao_kalman.h \ No newline at end of file + rm -f altitude.h ao_kalman.h diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 786dfd11..6aa6e018 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -41,7 +41,11 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { +#if HAS_FLIGHT uint8_t i = ao_adc_ring_prev(ao_sample_adc); +#else + uint8_t i = ao_adc_ring_prev(ao_adc_head); +#endif memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 4ac6a84b..19ea0cfd 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -302,6 +302,35 @@ #define HAS_MONITOR 1 #endif +#if defined(TELELAUNCH_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 0c10e608..ec2b61f6 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -47,7 +47,9 @@ _ao_config_put(void) ao_storage_setup(); ao_storage_erase(ao_storage_config); ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); +#if HAS_FLIGHT ao_log_write_erase(0); +#endif ao_storage_flush(); } @@ -301,7 +303,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT void ao_config_log_show(void) __reentrant { @@ -329,7 +331,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM */ +#endif /* HAS_EEPROM && HAS_FLIGHT */ #if HAS_IGNITE void @@ -448,7 +450,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore new file mode 100644 index 00000000..d25d7ad9 --- /dev/null +++ b/src/telelaunch-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky* +ao_product.h diff --git a/src/telelaunch-v0.1/.sdcdbrc b/src/telelaunch-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telelaunch-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs new file mode 100644 index 00000000..0c7efb52 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telelaunch-v0.1-$(VERSION).ihx + +SRC = \ + $(TLAUNCH_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(EE_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleLaunch-v0.1 +PRODUCT_DEF=-DTELELAUNCH_V_0_1 +IDPRODUCT=0x000f -- cgit v1.2.3 From a731d240f802d37524ce84c3c6acf22bcda4d522 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jul 2011 18:51:33 -0700 Subject: altos: Start work on AES and raw radio interfaces. We probably don't want this raw radio interface, but it's a start. Signed-off-by: Keith Packard --- src/ao_aes.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_radio_cmac.c | 100 +++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_pins.h | 4 ++ src/cc1111/cc1111.h | 24 +++++++++- src/core/ao.h | 26 +++++++++++ 5 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/ao_aes.c create mode 100644 src/ao_radio_cmac.c diff --git a/src/ao_aes.c b/src/ao_aes.c new file mode 100644 index 00000000..649eda06 --- /dev/null +++ b/src/ao_aes.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t ao_aes_done; +__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ + S0CON = 0; + if (ENCCCS & ENCCCS_RDY) { + ao_aes_done = 1; + ao_wakeup(&ao_aes_done); + } +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + ao_aes_done = 0; + ENCCCS = ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_LOAD_KEY | + ENCCCS_START; + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t b; + if (in) { + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + } + if (out) { + ao_dma_set_transfer(ao_aes_dma_out, + &ENCDOXADDR, + out, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_UP, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_LOW); + } + switch (ao_aes_current_mode) { + case ao_aes_mode_cbc_mac: + if (out) + b = (ENCCCS_MODE_CBC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + else + b = (ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + break; + default: + return; + } + ao_aes_done = 0; + ENCCCS = b; + if (out) + while (!ao_aes_dma_out_done) + ao_sleep(&ao_aes_dma_out_done); + else + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_init(void) +{ + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + ENCIE = 1; +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c new file mode 100644 index 00000000..4b118d02 --- /dev/null +++ b/src/ao_radio_cmac.c @@ -0,0 +1,100 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define AO_CMAC_KEY_LEN 16 +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; + +static uint8_t +getnibble(void) +{ + __pdata char c; + + c = getchar(); + 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); + ao_cmd_status = ao_cmd_lex_error; + return 0; +} + +static void +ao_radio_cmac_key(void) __reentrant +{ + uint8_t i; + + for (i = 0; i < AO_CMAC_KEY_LEN; i++) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_key[i] = ao_cmd_lex_i; + } +} + +static void +ao_radio_cmac_send(void) __reentrant +{ + uint8_t i, b; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < ao_cmd_lex_i; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_data[i] = b; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_key); + for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); + } + ao_mutex_put(&ao_aes_mutex); + ao_set_monitor(0); + ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +} + +__code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, + { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); + +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 19ea0cfd..9e9b3bf6 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -108,6 +108,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEMINI_V_1_0) @@ -212,6 +213,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TIDONGLE) @@ -235,6 +237,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_0) @@ -300,6 +303,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELELAUNCH_V_0_1) diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index e52aa79f..11ea8bbb 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -768,7 +768,7 @@ struct cc_dma_channel { # define DMA_CFG0_TRIGGER_ADC_CH7 28 # define DMA_CFG0_TRIGGER_I2STX 28 # define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_DNC_UP 30 +# define DMA_CFG0_TRIGGER_ENC_UP 30 # define DMA_CFG1_SRCINC_MASK (3 << 6) # define DMA_CFG1_SRCINC_0 (0 << 6) @@ -1303,4 +1303,26 @@ __xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; #define RF_VCO_VC_DAC_OFF 0x3d +/* AES engine */ + +__sfr at 0xB1 ENCDI; +__sfr at 0xB2 ENCDO; +__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; + +__sfr at 0xB3 ENCCCS; + +#define ENCCCS_MODE_CBC (0 << 4) +#define ENCCCS_MODE_CFB (1 << 4) +#define ENCCCS_MODE_OFB (2 << 4) +#define ENCCCS_MODE_CTR (3 << 4) +#define ENCCCS_MODE_ECB (4 << 4) +#define ENCCCS_MODE_CBC_MAC (5 << 4) +#define ENCCCS_RDY (1 << 3) +#define ENCCCS_CMD_ENCRYPT (0 << 1) +#define ENCCCS_CMD_DECRYPT (1 << 1) +#define ENCCCS_CMD_LOAD_KEY (2 << 1) +#define ENCCCS_CMD_LOAD_IV (3 << 1) +#define ENCCCS_START (1 << 0) + #endif diff --git a/src/core/ao.h b/src/core/ao.h index 0cff0436..0275cad1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1629,4 +1629,30 @@ ao_companion_init(void); void ao_lcd_init(void); +/* ao_aes.c */ + +__xdata uint8_t ao_aes_mutex; + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +void +ao_aes_init(void); + #endif /* _AO_H_ */ -- cgit v1.2.3 From bd0bf00081bb24af5cd67a9351b0b0c1a041d0d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:25:01 -0700 Subject: altos: More work on AES bits Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 9 +++++++++ src/core/ao.h | 4 ++++ src/telelaunch-v0.1/Makefile.defs | 1 + 3 files changed, 14 insertions(+) diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 4b118d02..9b406a21 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -22,6 +22,7 @@ static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; +static __pdata uint8_t ao_radio_cmac_len; static uint8_t getnibble(void) @@ -85,6 +86,14 @@ ao_radio_cmac_send(void) __reentrant ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); } +static void +ao_radio_cmac_recv(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; +} + __code struct ao_cmds ao_radio_cmac_cmds[] = { { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, diff --git a/src/core/ao.h b/src/core/ao.h index 0275cad1..2394d401 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1655,4 +1655,8 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_launch.c */ +void +ao_launch_init(void); + #endif /* _AO_H_ */ diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index 0c7efb52..e4934ffa 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -4,6 +4,7 @@ SRC = \ $(TLAUNCH_BASE_SRC) \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ + ao_launch.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 776df9ce2e7b4fa5cedda326988e66c614299af4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 20 Jul 2011 23:46:04 -0700 Subject: altos: Get AES CBC-MAC packet transfers running This just has simple command-line based packet transfers for testing. This also adds special ao_telelaunch bits where the launch control code will live. Signed-off-by: Keith Packard --- src/ao_aes.c | 48 +++++++++++++++------ src/ao_launch.c | 59 +++++++++++++++++++++++++ src/ao_radio_cmac.c | 90 +++++++++++++++++++++++++++++++-------- src/ao_telelaunch.c | 47 ++++++++++++++++++++ src/cc1111/ao_pins.h | 4 +- src/core/ao.h | 12 ++++++ src/product/ao_telebt.c | 4 ++ src/product/ao_teledongle.c | 2 + src/teledongle-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile.defs | 2 + 10 files changed, 237 insertions(+), 32 deletions(-) create mode 100644 src/ao_launch.c create mode 100644 src/ao_telelaunch.c create mode 100644 src/teledongle-v0.1/.sdcdbrc diff --git a/src/ao_aes.c b/src/ao_aes.c index 649eda06..d50fecfb 100644 --- a/src/ao_aes.c +++ b/src/ao_aes.c @@ -17,6 +17,10 @@ #include "ao.h" +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + __xdata uint8_t ao_aes_mutex; __xdata uint8_t ao_aes_done; __xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; @@ -45,21 +49,32 @@ ao_aes_set_key(__xdata uint8_t *in) ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_LOW); + ao_dma_start(ao_aes_dma_in); ao_aes_done = 0; ENCCCS = ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_LOAD_KEY | - ENCCCS_START; - while (!ao_aes_done) + ENCCCS_CMD_LOAD_KEY; + ENCCCS |= ENCCCS_START; + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); } +void +ao_aes_zero_iv(void) +{ + uint8_t b; + + ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; + for (b = 0; b < AO_AES_LEN; b++) + ENCDI = 0; +} + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out) @@ -69,7 +84,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, @@ -81,7 +96,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_out, &ENCDOXADDR, out, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_UP, @@ -93,24 +108,28 @@ ao_aes_run(__xdata uint8_t *in, case ao_aes_mode_cbc_mac: if (out) b = (ENCCCS_MODE_CBC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); else b = (ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); break; default: return; } ao_aes_done = 0; - ENCCCS = b; + if (in) + ao_dma_start(ao_aes_dma_in); if (out) - while (!ao_aes_dma_out_done) + ao_dma_start(ao_aes_dma_out); + ENCCCS = b; + ENCCCS |= ENCCCS_START; + if (out) { + __critical while (!ao_aes_dma_out_done) ao_sleep(&ao_aes_dma_out_done); - else - while (!ao_aes_done) + } else { + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); + } } void @@ -118,5 +137,6 @@ ao_aes_init(void) { ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + S0CON = 0; ENCIE = 1; } diff --git a/src/ao_launch.c b/src/ao_launch.c new file mode 100644 index 00000000..4870869e --- /dev/null +++ b/src/ao_launch.c @@ -0,0 +1,59 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_launch(void) +{ + enum ao_igniter_status arm_status, ignite_status; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + arm_status = ao_igniter_status(ao_igniter_drogue); + + switch (arm_status) { + case ao_igniter_unknown: + break; + case ao_igniter_active: + case ao_igniter_open: + break; + case ao_igniter_ready: + ignite_status = ao_igniter_status(ao_igniter_main); + switch (ignite_status) { + case ao_igniter_unknown: + /* some kind of failure signal here */ + break; + case ao_igniter_active: + break; + case ao_igniter_open: + break; + } + break; + } + ao_delay(AO_SEC_TO_TICKS(1)); + } +} + +static __xdata struct ao_task ao_launch_task; + +void +ao_launch_init(void) +{ + ao_add_task(&ao_launch_task, ao_launch, "launch status"); +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9b406a21..7648a2f5 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -40,62 +40,119 @@ getnibble(void) return 0; } +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + static void ao_radio_cmac_key(void) __reentrant { uint8_t i; for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - ao_cmd_hex(); + cmac_key[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_key[i] = ao_cmd_lex_i; } } static void ao_radio_cmac_send(void) __reentrant { - uint8_t i, b; + uint8_t i; + uint8_t len; - ao_cmd_hex(); + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { ao_cmd_status = ao_cmd_syntax_error; return; } - for (i = 0; i < ao_cmd_lex_i; i++) { - b = getnibble() << 4; - b |= getnibble(); + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_data[i] = b; } ao_mutex_get(&ao_aes_mutex); ao_aes_set_mode(ao_aes_mode_cbc_mac); ao_aes_set_key(cmac_key); - for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) ao_aes_run(&cmac_data[i], NULL); else - ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); + ao_aes_run(&cmac_data[i], &cmac_data[len]); } ao_mutex_put(&ao_aes_mutex); +#if HAS_MONITOR ao_set_monitor(0); - ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +#endif + printf("send:"); + for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) + printf(" %02x", cmac_data[i]); + printf("\n"); flush(); + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); } static void ao_radio_cmac_recv(void) __reentrant { - ao_cmd_hex(); + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + len = ao_cmd_lex_i; + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; + timeout = ao_cmd_lex_i; +#if HAS_MONITOR + ao_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { + printf("timeout\n"); + return; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + printf ("PACKET "); + for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) + printf("%02x", cmac_data[i]); + printf ("\n"); } -__code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, { 0, NULL }, @@ -105,5 +162,4 @@ void ao_radio_cmac_init(void) { ao_cmd_register(&ao_radio_cmac_cmds[0]); - } diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c new file mode 100644 index 00000000..b5404710 --- /dev/null +++ b/src/ao_telelaunch.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_aes_init(); + ao_radio_cmac_init(); + ao_launch_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 9e9b3bf6..819dc7df 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -267,6 +267,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_1) @@ -322,7 +323,7 @@ #define IGNITE_ON_P2 1 #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 + #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) @@ -333,6 +334,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define HAS_AES 1 #endif #if DBG_ON_P1 diff --git a/src/core/ao.h b/src/core/ao.h index 2394d401..2898852b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1633,6 +1633,10 @@ ao_lcd_init(void); __xdata uint8_t ao_aes_mutex; +/* AES keys and blocks are 128 bits */ + +#define AO_AES_LEN 16 + enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1648,6 +1652,9 @@ ao_aes_set_mode(enum ao_aes_mode mode); void ao_aes_set_key(__xdata uint8_t *in); +void +ao_aes_zero_iv(void); + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out); @@ -1655,6 +1662,11 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_radio_cmac.c */ + +void +ao_radio_cmac_init(void); + /* ao_launch.c */ void ao_launch_init(void); diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 85565172..5bbbf71b 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -44,6 +44,10 @@ main(void) ao_btm_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_AES + ao_aes_init(); + ao_radio_cmac_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 008b200a..b8be9f45 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,6 +35,8 @@ main(void) #if HAS_DBG ao_dbg_init(); #endif + ao_aes_init(); + ao_radio_cmac_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/teledongle-v0.1/.sdcdbrc b/src/teledongle-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index e4934ffa..56f5730b 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -5,6 +5,8 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ ao_launch.c \ + ao_aes.c \ + ao_radio_cmac.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 4299b5a36a2f6f9f7bbbc3a1b935dd2357c1fb0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 20:04:05 -0700 Subject: altos: Implement remote launch protocol Uses the radio_cmac module to provide secure communication. Keeps igniter closed for 500ms. Provides remote status for arming and ignition. Signed-off-by: Keith Packard --- src/ao_launch.c | 170 +++++++++++++++++++++++--- src/ao_radio_cmac.c | 278 ++++++++++++++++++++++++++++++------------ src/ao_telelaunch.c | 1 - src/cc1111/ao_ignite.c | 6 - src/cc1111/ao_packet_master.c | 6 +- src/cc1111/ao_timer.c | 1 + src/core/ao.h | 59 ++++++++- src/core/ao_cmd.c | 44 +++++-- src/core/ao_config.c | 36 ++++++ src/core/ao_task.c | 7 +- 10 files changed, 497 insertions(+), 111 deletions(-) diff --git a/src/ao_launch.c b/src/ao_launch.c index 4870869e..6c154719 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -17,43 +17,183 @@ #include "ao.h" +__xdata uint16_t ao_launch_ignite; + +static void +ao_launch_run(void) +{ + for (;;) { + while (!ao_launch_ignite) + ao_sleep(&ao_launch_ignite); + while (ao_launch_ignite) { + ao_launch_ignite = 0; + + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DROGUE = 1; + ao_delay(AO_MS_TO_TICKS(500)); + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; + } + } +} + +static void +ao_launch_status(void) +{ + uint8_t i; + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } + } +} + +static __pdata uint8_t ao_launch_armed; +static __pdata uint16_t ao_launch_arm_time; + static void ao_launch(void) { - enum ao_igniter_status arm_status, ignite_status; + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + int16_t time_difference; ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { - arm_status = ao_igniter_status(ao_igniter_drogue); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + printf ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + if (command.serial != ao_serial_number) { + printf ("serial number mismatch\n"); + continue; + } - switch (arm_status) { - case ao_igniter_unknown: + switch (command.cmd) { + case AO_LAUNCH_QUERY: + if (command.channel == 0) { + query.valid = 1; + query.arm_status = ao_igniter_status(ao_igniter_drogue); + query.igniter_status = ao_igniter_status(ao_igniter_main); + } else { + query.valid = 0; + } + query.tick = ao_time(); + query.serial = ao_serial_number; + query.channel = command.channel; + printf ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); break; - case ao_igniter_active: - case ao_igniter_open: + case AO_LAUNCH_ARM: + if (command.channel != 0) + break; + time_difference = command.tick - ao_time(); + printf ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time difference too large %d\n", time_difference); + break; + } + printf ("armed\n"); + ao_launch_armed = 1; + ao_launch_arm_time = ao_time(); break; - case ao_igniter_ready: - ignite_status = ao_igniter_status(ao_igniter_main); - switch (ignite_status) { - case ao_igniter_unknown: - /* some kind of failure signal here */ + case AO_LAUNCH_FIRE: + if (command.channel != 0) break; - case ao_igniter_active: + if (!ao_launch_armed) { + printf ("not armed\n"); break; - case ao_igniter_open: + } + if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { + printf ("late launch arm_time %d time %d\n", + ao_launch_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time different too large %d\n", time_difference); break; } + printf ("ignite\n"); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); break; } - ao_delay(AO_SEC_TO_TICKS(1)); } } +void +ao_launch_test(void) +{ + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +} + +void +ao_launch_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); +} + static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { + { ao_launch_test, "t\0Test launch continuity" }, + { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; void ao_launch_init(void) { - ao_add_task(&ao_launch_task, ao_launch, "launch status"); + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + ao_cmd_register(&ao_launch_cmds[0]); + ao_add_task(&ao_launch_task, ao_launch, "launch listener"); + ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); + ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); } diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 7648a2f5..9694b5b3 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -17,27 +17,24 @@ #include "ao.h" -#define AO_CMAC_KEY_LEN 16 +#define AO_CMAC_KEY_LEN AO_AES_LEN #define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) -static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t ao_radio_cmac_mutex; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; static uint8_t getnibble(void) { - __pdata char c; - - c = getchar(); - 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); - ao_cmd_status = ao_cmd_lex_error; - return 0; + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; } static uint8_t @@ -49,20 +46,137 @@ getbyte(void) return b; } +static uint8_t +round_len(uint8_t len) +{ + uint8_t rem; + + /* Make sure we transfer at least one packet, and + * then make sure every packet is full. Note that + * there is no length encoded, and that the receiver + * must deal with any extra bytes in the packet + */ + if (len < AO_CMAC_KEY_LEN) + len = AO_CMAC_KEY_LEN; + rem = len % AO_CMAC_KEY_LEN; + if (rem != 0) + len += (AO_CMAC_KEY_LEN - rem); + return len; +} + +/* + * Sign and deliver the data sitting in the cmac buffer + */ static void -ao_radio_cmac_key(void) __reentrant +radio_cmac_send(uint8_t len) __reentrant { uint8_t i; - for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - cmac_key[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_set_monitor(0); +#endif + + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len]); } + ao_mutex_put(&ao_aes_mutex); + + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); +} + +/* + * Receive and validate an incoming packet + */ + +static int8_t +radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + + len = round_len(len); +#if HAS_MONITOR + ao_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) + return AO_RADIO_CMAC_TIMEOUT; + + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + return AO_RADIO_CMAC_CRC_ERROR; + + ao_config_get(); + + /* Compute the packet signature + */ + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + ao_mutex_put(&ao_aes_mutex); + + /* Check the packet signature against the signature provided + * over the link + */ + + if (memcmp(&cmac_data[len], + &cmac_data[len + AO_CMAC_KEY_LEN + 2], + AO_CMAC_KEY_LEN) != 0) { + return AO_RADIO_CMAC_MAC_ERROR; + } + + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; } static void -ao_radio_cmac_send(void) __reentrant +radio_cmac_send_cmd(void) __reentrant { uint8_t i; uint8_t len; @@ -70,43 +184,25 @@ ao_radio_cmac_send(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { ao_cmd_status = ao_cmd_syntax_error; return; } flush(); + ao_mutex_get(&ao_radio_cmac_mutex); len = ao_cmd_lex_i; for (i = 0; i < len; i++) { cmac_data[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len]); - } - ao_mutex_put(&ao_aes_mutex); -#if HAS_MONITOR - ao_set_monitor(0); -#endif - printf("send:"); - for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) - printf(" %02x", cmac_data[i]); - printf("\n"); flush(); - ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); } static void -ao_radio_cmac_recv(void) __reentrant +radio_cmac_recv_cmd(void) __reentrant { uint8_t len, i; uint16_t timeout; @@ -114,47 +210,79 @@ ao_radio_cmac_recv(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { - ao_cmd_status = ao_cmd_syntax_error; - return; - } len = ao_cmd_lex_i; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - timeout = ao_cmd_lex_i; -#if HAS_MONITOR - ao_set_monitor(0); -#endif - if (timeout) - ao_alarm(timeout); - if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { - printf("timeout\n"); + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf ("\n"); + } else + printf ("ERROR %d\n", i); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static void +launch_report_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + uint8_t channel; + uint16_t serial; + uint8_t i; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) return; + flush(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = 0; + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { + case AO_RADIO_CMAC_OK: + printf("\n"); + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (query.igniter_status) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + default: + printf("Disarmed\n"); + } + return; + default: + continue; + } } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); - } - printf ("PACKET "); - for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) - printf("%02x", cmac_data[i]); - printf ("\n"); + printf ("Timeout\n"); } static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, - { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, { 0, NULL }, }; diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c index b5404710..506431de 100644 --- a/src/ao_telelaunch.c +++ b/src/ao_telelaunch.c @@ -35,7 +35,6 @@ main(void) ao_storage_init(); ao_usb_init(); ao_radio_init(); - ao_igniter_init(); #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index 5238beb4..0fd2b4bf 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -39,12 +39,6 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) -struct ao_ignition { - uint8_t request; - uint8_t fired; - uint8_t firing; -}; - __xdata struct ao_ignition ao_ignition[2]; void diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index b0fdf5a8..0d0be30e 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -80,13 +80,16 @@ ao_packet_master(void) ao_packet_master_time = ao_time(); ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { + uint8_t r; memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); ao_packet_master_check_busy(); ao_alarm(ao_packet_master_delay); - if (ao_packet_recv()) { + r = ao_packet_recv(); + ao_clear_alarm(); + if (r) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) continue; @@ -95,6 +98,7 @@ ao_packet_master(void) ao_packet_master_sleeping = 1; ao_alarm(ao_packet_master_delay); ao_sleep(&ao_packet_master_sleeping); + ao_clear_alarm(); ao_packet_master_sleeping = 0; } } diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index c977fbc8..aadee71e 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -31,6 +31,7 @@ ao_delay(uint16_t ticks) { ao_alarm(ticks); ao_sleep(&ao_forever); + ao_clear_alarm(); } #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ diff --git a/src/core/ao.h b/src/core/ao.h index 2898852b..a5bbb6f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -68,6 +68,10 @@ ao_wakeup(__xdata void *wchan); void ao_alarm(uint16_t delay); +/* Clear any pending alarm */ +void +ao_clear_alarm(void); + /* Yield the processor to another task */ void ao_yield(void) ao_arch_naked_declare; @@ -342,6 +346,12 @@ ao_cmd_put16(uint16_t v); void ao_cmd_white(void); +int8_t +ao_cmd_hexchar(char c); + +void +ao_cmd_hexbyte(void); + void ao_cmd_hex(void); @@ -1417,6 +1427,14 @@ enum ao_igniter_status { ao_igniter_open, /* open circuit detected */ }; +struct ao_ignition { + uint8_t request; + uint8_t fired; + uint8_t firing; +}; + +extern __xdata struct ao_ignition ao_ignition[2]; + enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); @@ -1431,7 +1449,8 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 8 +#define AO_CONFIG_MINOR 9 +#define AO_AES_LEN 16 struct ao_config { uint8_t major; @@ -1448,6 +1467,7 @@ struct ao_config { uint8_t pad_orientation; /* minor version 6 */ uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ + uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ }; #define AO_IGNITE_MODE_DUAL 0 @@ -1635,8 +1655,6 @@ __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -#define AO_AES_LEN 16 - enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1664,10 +1682,45 @@ ao_aes_init(void); /* ao_radio_cmac.c */ +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + void ao_radio_cmac_init(void); /* ao_launch.c */ + +struct ao_launch_command { + uint16_t tick; + uint16_t serial; + uint8_t cmd; + uint8_t channel; + uint16_t unused; +}; + +#define AO_LAUNCH_QUERY 1 + +struct ao_launch_query { + uint16_t tick; + uint16_t serial; + uint8_t channel; + uint8_t valid; + uint8_t arm_status; + uint8_t igniter_status; +}; + +#define AO_LAUNCH_ARM 2 +#define AO_LAUNCH_FIRE 3 + void ao_launch_init(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 7663d875..9e14c221 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -22,7 +22,7 @@ __pdata uint32_t ao_cmd_lex_u32; __pdata char ao_cmd_lex_c; __pdata enum ao_cmd_status ao_cmd_status; -#define CMD_LEN 32 +#define CMD_LEN 48 static __xdata char cmd_line[CMD_LEN]; static __pdata uint8_t cmd_len; @@ -128,22 +128,48 @@ ao_cmd_white(void) ao_cmd_lex(); } +int8_t +ao_cmd_hexchar(char 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; +} + +void +ao_cmd_hexbyte(void) +{ + uint8_t i; + int8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for (i = 0; i < 2; i++) { + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) { + ao_cmd_status = ao_cmd_syntax_error; + break; + } + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + ao_cmd_lex(); + } +} + void ao_cmd_hex(void) { __pdata uint8_t r = ao_cmd_lex_error; - uint8_t n; + int8_t n; ao_cmd_lex_i = 0; ao_cmd_white(); for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - n = (ao_cmd_lex_c - '0'); - else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - n = (ao_cmd_lex_c - 'a' + 10); - else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - n = (ao_cmd_lex_c - 'A' + 10); - else + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) break; ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; r = ao_cmd_success; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ec2b61f6..7f999feb 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -74,11 +74,14 @@ _ao_config_get(void) if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; ao_config.minor = 0; + + /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ @@ -104,6 +107,8 @@ _ao_config_get(void) ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; + if (ao_config.minor < 9) + memset(&ao_config.aes_key, '\0', AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -414,6 +419,33 @@ ao_config_radio_enable_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_AES +void +ao_config_key_show(void) __reentrant +{ + uint8_t i; + printf("AES key: "); + for (i = 0; i < AO_AES_LEN; i++) + printf ("%02x", ao_config.aes_key[i]); + printf("\n"); +} + +void +ao_config_key_set(void) __reentrant +{ + uint8_t i; + + _ao_config_edit_start(); + for (i = 0; i < AO_AES_LEN; i++) { + ao_cmd_hexbyte(); + if (ao_cmd_status != ao_cmd_success) + break; + ao_config.aes_key[i] = ao_cmd_lex_i; + } + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -461,6 +493,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_ACCEL { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif +#if HAS_AES + { "k <32 hex digits>\0Set AES encryption key", + ao_config_key_set, ao_config_key_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 32826114..a19a6a6f 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -107,7 +107,6 @@ ao_sleep(__xdata void *wchan) ao_cur_task->wchan = wchan; ); ao_yield(); - ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; return 1; @@ -135,6 +134,12 @@ ao_alarm(uint16_t delay) ao_cur_task->alarm = 1; } +void +ao_clear_alarm(void) +{ + ao_cur_task->alarm = 0; +} + void ao_exit(void) { -- cgit v1.2.3 From bc1b94df4d6b92e794ec93d9c1682ae5f61efa61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 22:25:45 -0700 Subject: altos: Finish up primitive telelaunch protocol This adds two commands to teledongle, one to query and one to actually fire the igniter. These will (eventually) want to be replaced with something nicer. Signed-off-by: Keith Packard --- src/ao_launch.c | 44 +++++++++++++--------- src/ao_radio_cmac.c | 101 ++++++++++++++++++++++++++++++++++++++++++--------- src/core/ao_config.c | 2 +- 3 files changed, 111 insertions(+), 36 deletions(-) diff --git a/src/ao_launch.c b/src/ao_launch.c index 6c154719..35afbda8 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -19,6 +19,12 @@ __xdata uint16_t ao_launch_ignite; +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + static void ao_launch_run(void) { @@ -71,19 +77,20 @@ ao_launch(void) ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { + flush(); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) continue; - printf ("tick %d serial %d cmd %d channel %d\n", + PRINTD ("tick %d serial %d cmd %d channel %d\n", command.tick, command.serial, command.cmd, command.channel); - if (command.serial != ao_serial_number) { - printf ("serial number mismatch\n"); - continue; - } - switch (command.cmd) { case AO_LAUNCH_QUERY: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel == 0) { query.valid = 1; query.arm_status = ao_igniter_status(ao_igniter_drogue); @@ -94,35 +101,38 @@ ao_launch(void) query.tick = ao_time(); query.serial = ao_serial_number; query.channel = command.channel; - printf ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", query.tick, query.serial, query.channel, query.valid, query.arm_status, query.igniter_status); ao_radio_cmac_send(&query, sizeof (query)); break; case AO_LAUNCH_ARM: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel != 0) break; time_difference = command.tick - ao_time(); - printf ("arm tick %d local tick %d\n", command.tick, ao_time()); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); if (time_difference < 0) time_difference = -time_difference; if (time_difference > 10) { - printf ("time difference too large %d\n", time_difference); + PRINTD ("time difference too large %d\n", time_difference); break; } - printf ("armed\n"); + PRINTD ("armed\n"); ao_launch_armed = 1; ao_launch_arm_time = ao_time(); break; case AO_LAUNCH_FIRE: - if (command.channel != 0) - break; if (!ao_launch_armed) { - printf ("not armed\n"); + PRINTD ("not armed\n"); break; } - if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { - printf ("late launch arm_time %d time %d\n", + if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late launch arm_time %d time %d\n", ao_launch_arm_time, ao_time()); break; } @@ -130,10 +140,10 @@ ao_launch(void) if (time_difference < 0) time_difference = -time_difference; if (time_difference > 10) { - printf ("time different too large %d\n", time_difference); + PRINTD ("time different too large %d\n", time_difference); break; } - printf ("ignite\n"); + PRINTD ("ignite\n"); ao_launch_ignite = 1; ao_wakeup(&ao_launch_ignite); break; diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9694b5b3..c2757b16 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -227,14 +227,37 @@ radio_cmac_recv_cmd(void) __reentrant ao_mutex_put(&ao_radio_cmac_mutex); } +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; + + +static int8_t +launch_query(uint16_t serial, uint8_t channel) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + printf("\n"); flush(); + return r; +} + static void launch_report_cmd(void) __reentrant { - static __xdata struct ao_launch_command command; - static __xdata struct ao_launch_query query; uint8_t channel; uint16_t serial; - uint8_t i; + int8_t r; ao_cmd_decimal(); serial = ao_cmd_lex_i; @@ -242,17 +265,10 @@ launch_report_cmd(void) __reentrant channel = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - flush(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = 0; - command.serial = serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = channel; - ao_radio_cmac_send(&command, sizeof (command)); - switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { - case AO_RADIO_CMAC_OK: - printf("\n"); + r = launch_query(serial, channel); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { switch (query.arm_status) { case ao_igniter_ready: case ao_igniter_active: @@ -268,21 +284,70 @@ launch_report_cmd(void) __reentrant printf("igniter bad\n"); break; } + break; default: printf("Disarmed\n"); } - return; - default: - continue; + } else { + printf("Invalid channel %d\n", channel); } + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t channel; + uint16_t serial; + uint8_t secs; + uint8_t i; + int8_t r; + uint16_t tick_offset; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + tick_offset = ao_time(); + r = launch_query(serial, channel); + tick_offset -= query.tick; + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + } + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); + ao_delay(AO_MS_TO_TICKS(100)); } - printf ("Timeout\n"); } static __code struct ao_cmds ao_radio_cmac_cmds[] = { { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, { 0, NULL }, }; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 7f999feb..28854ab5 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -108,7 +108,7 @@ _ao_config_get(void) if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) - memset(&ao_config.aes_key, '\0', AO_AES_LEN); + memset(&ao_config.aes_key, 0, AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } -- cgit v1.2.3 From be117376179126824439d98379079025ca0b245a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 17:06:49 -0700 Subject: altos: Keep relay closed while firing launcher Instead of opening the relay while checking the desired state, keep it closed until the state goes off. Signed-off-by: Keith Packard --- src/ao_launch.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ao_launch.c b/src/ao_launch.c index 35afbda8..a593d0b2 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -31,17 +31,17 @@ ao_launch_run(void) for (;;) { while (!ao_launch_ignite) ao_sleep(&ao_launch_ignite); + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + AO_IGNITER_DROGUE = 1; while (ao_launch_ignite) { ao_launch_ignite = 0; - - ao_ignition[ao_igniter_drogue].firing = 1; - ao_ignition[ao_igniter_main].firing = 1; - AO_IGNITER_DROGUE = 1; ao_delay(AO_MS_TO_TICKS(500)); - AO_IGNITER_DROGUE = 0; - ao_ignition[ao_igniter_drogue].firing = 0; - ao_ignition[ao_igniter_main].firing = 0; } + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; } } -- cgit v1.2.3 From 4568bc796a6c362ebf7f72ee9a5fa4a9a3c4ba6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 17:08:24 -0700 Subject: altosui: Add primitive UI for TeleLaunch Display status along with arm and fire buttons. Signed-off-by: Keith Packard --- altosui/AltosLaunch.java | 201 ++++++++++++++++ altosui/AltosLaunchUI.java | 518 ++++++++++++++++++++++++++++++++++++++++++ altosui/AltosPreferences.java | 39 ++++ altosui/Makefile.am | 2 + src/ao_radio_cmac.c | 140 ++++++++---- 5 files changed, 854 insertions(+), 46 deletions(-) create mode 100644 altosui/AltosLaunch.java create mode 100644 altosui/AltosLaunchUI.java diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java new file mode 100644 index 00000000..77f681b8 --- /dev/null +++ b/altosui/AltosLaunch.java @@ -0,0 +1,201 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; + +public class AltosLaunch { + AltosDevice device; + AltosSerial serial; + boolean serial_started; + int launcher_serial; + int launcher_channel; + int rssi; + + final static int Unknown = -1; + final static int Good = 0; + final static int Bad = 1; + + int armed; + int igniter; + + private void start_serial() throws InterruptedException { + serial_started = true; + } + + private void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + if (serial == null) + return; + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + public boolean status() throws InterruptedException, TimeoutException { + boolean ok = false; + if (serial == null) + return false; + string_ref status_name = new string_ref(); + start_serial(); + serial.printf("l %d %d\n", launcher_serial, launcher_channel); + for (;;) { + String line = serial.get_reply(20000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Rssi: ", status_name)) { + try { + rssi = Altos.fromdec(status_name.get()); + } catch (NumberFormatException ne) { + } + break; + } else if (get_string(line, "Armed: ", status_name)) { + armed = Good; + String status = status_name.get(); + if (status.startsWith("igniter good")) + igniter = Good; + else if (status.startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Disarmed: ", status_name)) { + armed = Bad; + if (status_name.get().startsWith("igniter good")) + igniter = Good; + else if (status_name.get().startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Error ", status_name)) { + armed = Unknown; + igniter = Unknown; + ok = false; + break; + } + } + stop_serial(); + if (!ok) { + armed = Unknown; + igniter = Unknown; + } + return ok; + } + + public static String status_string(int status) { + switch (status) { + case Good: + return "good"; + case Bad: + return "open"; + } + return "unknown"; + } + + public void arm() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("a %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void fire() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("i %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void close() { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial.close(); + serial = null; + } + + public void set_frame(Frame frame) { + serial.set_frame(frame); + } + + public void set_remote(int in_serial, int in_channel) { + launcher_serial = in_serial; + launcher_channel = in_channel; + } + + public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + + device = in_device; + serial = new AltosSerial(device); + } +} \ No newline at end of file diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java new file mode 100644 index 00000000..4e630afb --- /dev/null +++ b/altosui/AltosLaunchUI.java @@ -0,0 +1,518 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.*; + +class FireButton extends JButton { + protected void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + switch (e.getID()) { + case MouseEvent.MOUSE_PRESSED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down")); + break; + case MouseEvent.MOUSE_RELEASED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up")); + break; + } + } + + public FireButton(String s) { + super(s); + } +} + +public class AltosLaunchUI + extends JDialog + implements ActionListener +{ + AltosDevice device; + JFrame owner; + JLabel label; + + int radio_channel; + JLabel radio_channel_label; + JTextField radio_channel_text; + + int launcher_serial; + JLabel launcher_serial_label; + JTextField launcher_serial_text; + + int launcher_channel; + JLabel launcher_channel_label; + JTextField launcher_channel_text; + + JLabel armed_label; + JLabel armed_status_label; + JLabel igniter; + JLabel igniter_status_label; + JToggleButton arm; + FireButton fire; + javax.swing.Timer arm_timer; + javax.swing.Timer fire_timer; + + boolean firing; + boolean armed; + int armed_status; + int igniter_status; + int rssi; + + final static int arm_timeout = 1 * 1000; + final static int fire_timeout = 250; + + int armed_count; + + LinkedBlockingQueue command_queue; + + class LaunchHandler implements Runnable { + AltosLaunch launch; + JFrame owner; + + void send_exception(Exception e) { + final Exception f_e = e; + Runnable r = new Runnable() { + public void run() { + launch_exception(f_e); + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + try { + launch = new AltosLaunch(device); + } catch (Exception e) { + send_exception(e); + return; + } + launch.set_frame(owner); + launch.set_remote(launcher_serial, launcher_channel); + + for (;;) { + Runnable r; + + try { + String command = command_queue.take(); + String reply = null; + + if (command.equals("get_status")) { + launch.status(); + reply = "status"; + armed_status = launch.armed; + igniter_status = launch.igniter; + rssi = launch.rssi; + } else if (command.equals("set_remote")) { + launch.set_remote(launcher_serial, launcher_channel); + reply = "remote set"; + } else if (command.equals("arm")) { + launch.arm(); + reply = "armed"; + } else if (command.equals("fire")) { + launch.fire(); + reply = "fired"; + } else if (command.equals("quit")) { + launch.close(); + break; + } else { + throw new ParseException(String.format("invalid command %s", command), 0); + } + final String f_reply = reply; + r = new Runnable() { + public void run() { + launch_reply(f_reply); + } + }; + SwingUtilities.invokeLater(r); + } catch (Exception e) { + send_exception(e); + } + } + } + + public LaunchHandler(JFrame in_owner) { + owner = in_owner; + } + } + + void launch_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); + } + + void launch_reply(String reply) { + if (reply == null) + return; + if (reply.equals("remote set")) + poll_launch_status(); + if (reply.equals("status")) { + set_launch_status(); + } + } + + void set_arm_text() { + if (arm.isSelected()) + arm.setText(String.format("%d", armed_count)); + else + arm.setText("Arm"); + } + + void start_arm_timer() { + armed_count = 30; + set_arm_text(); + } + + void stop_arm_timer() { + armed_count = 0; + armed = false; + arm.setSelected(false); + fire.setEnabled(false); + set_arm_text(); + } + + void cancel () { + fire.setEnabled(false); + firing = false; + stop_arm_timer(); + } + + void send_command(String command) { + try { + command_queue.put(command); + } catch (Exception ex) { + launch_exception(ex); + } + } + + boolean getting_status = false; + + void set_launch_status() { + getting_status = false; + armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status))); + igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status))); + } + + void poll_launch_status() { + if (!getting_status && !firing && !armed) { + getting_status = true; + send_command("get_status"); + } + } + + void fired() { + firing = false; + cancel(); + } + + void close() { + send_command("quit"); + arm_timer.stop(); + setVisible(false); + dispose(); + } + + void tick_arm_timer() { + if (armed_count > 0) { + --armed_count; + if (armed_count <= 0) { + armed_count = 0; + cancel(); + } else { + if (!firing) { + send_command("arm"); + set_arm_text(); + } + } + } + poll_launch_status(); + } + + void arm() { + if (arm.isSelected()) { + fire.setEnabled(true); + start_arm_timer(); + if (!firing) + send_command("arm"); + armed = true; + } else + cancel(); + } + + void fire_more() { + if (firing) + send_command("fire"); + } + + void fire_down() { + if (arm.isEnabled() && arm.isSelected() && armed_count > 0) { + firing = true; + fire_more(); + fire_timer.restart(); + } + } + + void fire_up() { + firing = false; + fire_timer.stop(); + } + + void set_radio() { + try { + radio_channel = Integer.parseInt(radio_channel_text.getText()); + } catch (NumberFormatException ne) { + radio_channel_text.setText(String.format("%d", radio_channel)); + } + } + + void set_serial() { + try { + launcher_serial = Integer.parseInt(launcher_serial_text.getText()); + AltosPreferences.set_launcher_serial(launcher_serial); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_serial_text.setText(String.format("%d", launcher_serial)); + } + } + + void set_channel() { + try { + launcher_channel = Integer.parseInt(launcher_channel_text.getText()); + AltosPreferences.set_launcher_serial(launcher_channel); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_channel_text.setText(String.format("%d", launcher_channel)); + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + System.out.printf("cmd %s\n", cmd); + if (cmd.equals("armed") || cmd.equals("igniter")) { + stop_arm_timer(); + } + + if (cmd.equals("arm")) + arm(); + if (cmd.equals("tick_arm")) + tick_arm_timer(); + if (cmd.equals("close")) + close(); + if (cmd.equals("fire_down")) + fire_down(); + if (cmd.equals("fire_up")) + fire_up(); + if (cmd.equals("tick_fire")) + fire_more(); + if (cmd.equals("new_serial")) + set_serial(); + if (cmd.equals("new_channel")) + set_channel(); + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosLaunchUI ui; + + public ConfigListener(AltosLaunchUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + command_queue = new LinkedBlockingQueue(); + + device = AltosDeviceDialog.show(owner, Altos.product_any); + if (device != null) { + LaunchHandler handler = new LaunchHandler(owner); + Thread t = new Thread(handler); + t.start(); + return true; + } + return false; + } + + public AltosLaunchUI(JFrame in_owner) { + + launcher_channel = AltosPreferences.launcher_channel(); + launcher_serial = AltosPreferences.launcher_serial(); + owner = in_owner; + armed_status = AltosLaunch.Unknown; + igniter_status = AltosLaunch.Unknown; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + arm_timer = new javax.swing.Timer(arm_timeout, this); + arm_timer.setActionCommand("tick_arm"); + arm_timer.restart(); + + fire_timer = new javax.swing.Timer(fire_timeout, this); + fire_timer.setActionCommand("tick_fire"); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + label = new JLabel ("Launch Controller"); + pane.add(label, c); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_label = new JLabel("Launcher Serial"); + pane.add(launcher_serial_label, c); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_text = new JTextField(7); + launcher_serial_text.setText(String.format("%d", launcher_serial)); + launcher_serial_text.setActionCommand("new_serial"); + launcher_serial_text.addActionListener(this); + pane.add(launcher_serial_text, c); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_label = new JLabel("Launcher Channel"); + pane.add(launcher_channel_label, c); + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_text = new JTextField(7); + launcher_channel_text.setText(String.format("%d", launcher_channel)); + launcher_channel_text.setActionCommand("new_channel"); + launcher_channel_text.addActionListener(this); + pane.add(launcher_channel_text, c); + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_label = new JLabel ("Armed"); + pane.add(armed_label, c); + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_status_label = new JLabel(); + pane.add(armed_status_label, c); + + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter = new JLabel ("Igniter"); + pane.add(igniter, c); + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter_status_label = new JLabel(); + pane.add(igniter_status_label, c); + + c.gridx = 0; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + arm = new JToggleButton ("Arm"); + pane.add(arm, c); + arm.addActionListener(this); + arm.setActionCommand("arm"); + arm.setEnabled(true); + + c.gridx = 1; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + fire = new FireButton ("Fire"); + fire.setEnabled(false); + pane.add(fire, c); + fire.addActionListener(this); + fire.setActionCommand("fire"); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + + setVisible(true); + } +} \ No newline at end of file diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 716559ab..48aed441 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -58,6 +58,12 @@ class AltosPreferences { /* font size preferences name */ final static String fontSizePreference = "FONT-SIZE"; + /* Launcher serial preference name */ + final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + + /* Launcher channel prefernce name */ + final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -143,6 +149,9 @@ class AltosPreferences { node.put(String.format(description_format, i), frequencies[i].description); } } + static int launcher_serial; + + static int launcher_channel; public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -176,6 +185,10 @@ class AltosPreferences { font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); Altos.set_fonts(font_size); + launcher_serial = preferences.getInt(launcherSerialPreference, 0); + + launcher_channel = preferences.getInt(launcherChannelPreference, 0); + String firmwaredir_string = preferences.get(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); @@ -390,6 +403,32 @@ class AltosPreferences { return serial_debug; } + public static void set_launcher_serial(int new_launcher_serial) { + launcher_serial = new_launcher_serial; + System.out.printf("set launcher serial to %d\n", new_launcher_serial); + synchronized (preferences) { + preferences.putInt(launcherSerialPreference, launcher_serial); + flush_preferences(); + } + } + + public static int launcher_serial() { + return launcher_serial; + } + + public static void set_launcher_channel(int new_launcher_channel) { + launcher_channel = new_launcher_channel; + System.out.printf("set launcher channel to %d\n", new_launcher_channel); + synchronized (preferences) { + preferences.putInt(launcherChannelPreference, launcher_channel); + flush_preferences(); + } + } + + public static int launcher_channel() { + return launcher_channel; + } + public static Preferences bt_devices() { return preferences.node("bt_devices"); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index ba1c830c..e2e42d84 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -68,6 +68,8 @@ altosui_JAVA = \ AltosIdleMonitorUI.java \ AltosIgnite.java \ AltosIgniteUI.java \ + AltosLaunch.java \ + AltosLaunchUI.java \ AltosInfoTable.java \ AltosKML.java \ AltosLanded.java \ diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index c2757b16..41fbbe1f 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -21,6 +21,7 @@ #define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) static __xdata uint8_t ao_radio_cmac_mutex; +__pdata int16_t ao_radio_cmac_rssi; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; @@ -114,9 +115,12 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); ao_clear_alarm(); - if (!i) + if (!i) { + ao_radio_cmac_rssi = 0; return AO_RADIO_CMAC_TIMEOUT; + } + ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; @@ -221,33 +225,46 @@ radio_cmac_recv_cmd(void) __reentrant printf ("PACKET "); for (i = 0; i < len; i++) printf("%02x", cmac_data[i]); - printf ("\n"); + printf (" %d\n", ao_radio_cmac_rssi); } else - printf ("ERROR %d\n", i); + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); ao_mutex_put(&ao_radio_cmac_mutex); } static __xdata struct ao_launch_command command; static __xdata struct ao_launch_query query; +static pdata uint16_t launch_serial; +static pdata uint8_t launch_channel; +static pdata uint16_t tick_offset; +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} static int8_t -launch_query(uint16_t serial, uint8_t channel) +launch_query(void) { uint8_t i; int8_t r = AO_RADIO_CMAC_OK; + tick_offset = ao_time(); for (i = 0; i < 10; i++) { printf ("."); flush(); command.tick = ao_time(); - command.serial = serial; + command.serial = launch_serial; command.cmd = AO_LAUNCH_QUERY; - command.channel = channel; + command.channel = launch_channel; ao_radio_cmac_send(&command, sizeof (command)); r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); if (r == AO_RADIO_CMAC_OK) break; } + tick_offset -= query.tick; printf("\n"); flush(); return r; } @@ -255,17 +272,12 @@ launch_query(uint16_t serial, uint8_t channel) static void launch_report_cmd(void) __reentrant { - uint8_t channel; - uint16_t serial; int8_t r; - ao_cmd_decimal(); - serial = ao_cmd_lex_i; - ao_cmd_decimal(); - channel = ao_cmd_lex_i; + launch_args(); if (ao_cmd_status != ao_cmd_success) return; - r = launch_query(serial, channel); + r = launch_query(); switch (r) { case AO_RADIO_CMAC_OK: if (query.valid) { @@ -273,24 +285,25 @@ launch_report_cmd(void) __reentrant case ao_igniter_ready: case ao_igniter_active: printf ("Armed: "); - switch (query.igniter_status) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } break; default: - printf("Disarmed\n"); + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; } } else { - printf("Invalid channel %d\n", channel); + printf("Invalid channel %d\n", launch_channel); } + printf("Rssi: %d\n", ao_radio_cmac_rssi); break; default: printf("Error %d\n", r); @@ -298,56 +311,91 @@ launch_report_cmd(void) __reentrant } } +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + static void launch_fire_cmd(void) __reentrant { static __xdata struct ao_launch_command command; - uint8_t channel; - uint16_t serial; uint8_t secs; uint8_t i; int8_t r; - uint16_t tick_offset; - ao_cmd_decimal(); - serial = ao_cmd_lex_i; - ao_cmd_decimal(); - channel = ao_cmd_lex_i; + launch_args(); ao_cmd_decimal(); secs = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - tick_offset = ao_time(); - r = launch_query(serial, channel); - tick_offset -= query.tick; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } for (i = 0; i < 4; i++) { printf("arm %d\n", i); flush(); - command.tick = ao_time() - tick_offset; - command.serial = serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = channel; - ao_radio_cmac_send(&command, sizeof (command)); + launch_arm(); } + secs = secs * 10 - 5; if (secs > 100) secs = 100; for (i = 0; i < secs; i++) { printf("fire %d\n", i); flush(); - command.tick = ao_time() - tick_offset; - command.serial = serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); + launch_ignite(); ao_delay(AO_MS_TO_TICKS(100)); } } +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + static __code struct ao_cmds ao_radio_cmac_cmds[] = { { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, { launch_report_cmd, "l \0Get remote launch status" }, { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, }; -- cgit v1.2.3 From 02df2141e5a67afc16acd01a6c60f3cc61052b93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:45:43 -0700 Subject: altosui: Hook up the launch controller UI from the main button box Provide a button to start the launch controller UI. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 27c41838..8399b7c8 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -210,6 +210,13 @@ public class AltosUI extends JFrame { }); b.setToolTipText("Check flight readiness of altimeter in idle mode"); + b = addButton(2, 2, "Launch Controller"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + LaunchController(); + } + }); + setTitle("AltOS"); pane.doLayout(); @@ -272,6 +279,10 @@ public class AltosUI extends JFrame { new AltosSiteMapPreload(AltosUI.this); } + void LaunchController() { + new AltosLaunchUI(AltosUI.this); + } + /* * Replay a flight from telemetry data */ -- cgit v1.2.3 From 6b2db651a1dbc7ea97fce802b5f10b88be1ab42b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 12:42:10 -0700 Subject: altos: Add makefile for telelaunch Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 97 +++++++++++++++++++++++++++++++++++++++++ src/telelaunch-v0.1/Makefile | 5 ++- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/product/Makefile.telelaunch diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch new file mode 100644 index 00000000..71781bb1 --- /dev/null +++ b/src/product/Makefile.telelaunch @@ -0,0 +1,97 @@ +# +# TeleLaunch build file +# +# define TELELAUNCH_VER, TELELAUNCH_DEF +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_sample.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_ignite.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telelaunch.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx +PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) +PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) +IDPRODUCT=0x000f + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile index d8867b19..b0d9d165 100644 --- a/src/telelaunch-v0.1/Makefile +++ b/src/telelaunch-v0.1/Makefile @@ -1 +1,4 @@ -include ../Makefile.proto +TELELAUNCH_VER=0.1 +TELELAUNCH_DEF=0_1 + +include ../product/Makefile.telelaunch -- cgit v1.2.3 From b3c95582774355c991d0a9f27d0a86881e643e62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:24:41 -0700 Subject: altos: move igniter defines back to ao_pins.h so that ao_launch gets them too Signed-off-by: Keith Packard --- src/cc1111/ao_ignite.c | 22 ------ src/cc1111/ao_launch.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_pins.h | 39 ++++++++- 3 files changed, 247 insertions(+), 23 deletions(-) create mode 100644 src/cc1111/ao_launch.c diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index 0fd2b4bf..289263ab 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -17,28 +17,6 @@ #include "ao.h" -#if IGNITE_ON_P2 -#define AO_IGNITER_DROGUE P2_3 -#define AO_IGNITER_MAIN P2_4 -#define AO_IGNITER_DIR P2DIR -#define AO_IGNITER_DROGUE_BIT (1 << 3) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -#if IGNITE_ON_P0 -#define AO_IGNITER_DROGUE P0_5 -#define AO_IGNITER_MAIN P0_4 -#define AO_IGNITER_DIR P0DIR -#define AO_IGNITER_DROGUE_BIT (1 << 5) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -/* test these values with real igniters */ -#define AO_IGNITER_OPEN 1000 -#define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) -#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) - __xdata struct ao_ignition ao_ignition[2]; void diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c new file mode 100644 index 00000000..a593d0b2 --- /dev/null +++ b/src/cc1111/ao_launch.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +__xdata uint16_t ao_launch_ignite; + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +static void +ao_launch_run(void) +{ + for (;;) { + while (!ao_launch_ignite) + ao_sleep(&ao_launch_ignite); + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + AO_IGNITER_DROGUE = 1; + while (ao_launch_ignite) { + ao_launch_ignite = 0; + ao_delay(AO_MS_TO_TICKS(500)); + } + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; + } +} + +static void +ao_launch_status(void) +{ + uint8_t i; + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } + } +} + +static __pdata uint8_t ao_launch_armed; +static __pdata uint16_t ao_launch_arm_time; + +static void +ao_launch(void) +{ + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + int16_t time_difference; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + flush(); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + PRINTD ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + switch (command.cmd) { + case AO_LAUNCH_QUERY: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + + if (command.channel == 0) { + query.valid = 1; + query.arm_status = ao_igniter_status(ao_igniter_drogue); + query.igniter_status = ao_igniter_status(ao_igniter_main); + } else { + query.valid = 0; + } + query.tick = ao_time(); + query.serial = ao_serial_number; + query.channel = command.channel; + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); + break; + case AO_LAUNCH_ARM: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + + if (command.channel != 0) + break; + time_difference = command.tick - ao_time(); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time difference too large %d\n", time_difference); + break; + } + PRINTD ("armed\n"); + ao_launch_armed = 1; + ao_launch_arm_time = ao_time(); + break; + case AO_LAUNCH_FIRE: + if (!ao_launch_armed) { + PRINTD ("not armed\n"); + break; + } + if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late launch arm_time %d time %d\n", + ao_launch_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time different too large %d\n", time_difference); + break; + } + PRINTD ("ignite\n"); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); + break; + } + } +} + +void +ao_launch_test(void) +{ + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +} + +void +ao_launch_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); +} + +static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { + { ao_launch_test, "t\0Test launch continuity" }, + { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; + +void +ao_launch_init(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + ao_cmd_register(&ao_launch_cmds[0]); + ao_add_task(&ao_launch_task, ao_launch, "launch listener"); + ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); + ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 819dc7df..91719b54 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -27,6 +27,7 @@ #define HAS_ADC 1 #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define DBG_ON_P1 1 @@ -59,6 +60,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define DBG_ON_P1 1 @@ -95,6 +97,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 0 @@ -120,6 +123,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 @@ -146,6 +150,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 @@ -172,6 +177,7 @@ #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 @@ -200,6 +206,7 @@ #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 @@ -225,6 +232,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 @@ -249,6 +257,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define HAS_BTM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 @@ -282,6 +291,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_BTM 1 #define DBG_ON_P1 1 @@ -317,7 +327,8 @@ #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 + #define HAS_LOG 0 + #define USE_INTERNAL_FLASH 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 1 @@ -415,6 +426,10 @@ #error Please define HAS_EEPROM #endif +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + #if HAS_EEPROM #ifndef USE_INTERNAL_FLASH #error Please define USE_INTERNAL_FLASH @@ -457,4 +472,26 @@ #endif /* HAS_ADC */ +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 9adf2c9c40ea1da2637ed809dc0d004e47844440 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:25:23 -0700 Subject: altos: add ao_aes/radio_cmac to tidongle, teledongle and telebt All of these can do the telelco stuff at this point. Signed-off-by: Keith Packard --- src/product/Makefile.telebt | 2 ++ src/product/Makefile.teledongle | 2 ++ src/product/ao_tidongle.c | 2 ++ src/tidongle/Makefile | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index d9ef1ea7..ff0e1502 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -32,12 +32,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_timer.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index cfd9b806..56182b84 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -34,12 +34,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index 3b7c2733..5adbb05c 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -34,6 +34,8 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); + ao_aes_init(); + ao_radio_cmac_init(); ao_config_init(); /* Bring up the USB link */ P1DIR |= 1; diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 247f4fe0..057e420b 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -29,12 +29,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_timer.c \ ao_usb.c \ -- cgit v1.2.3 From 6afbc1876cd63f64e8975e300692f95a43866f5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:27:00 -0700 Subject: altos: ao_launch belongs in cc1111 Signed-off-by: Keith Packard --- src/ao_launch.c | 209 -------------------------------------------------------- 1 file changed, 209 deletions(-) delete mode 100644 src/ao_launch.c diff --git a/src/ao_launch.c b/src/ao_launch.c deleted file mode 100644 index a593d0b2..00000000 --- a/src/ao_launch.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -__xdata uint16_t ao_launch_ignite; - -#if 0 -#define PRINTD(...) printf(__VA_ARGS__) -#else -#define PRINTD(...) -#endif - -static void -ao_launch_run(void) -{ - for (;;) { - while (!ao_launch_ignite) - ao_sleep(&ao_launch_ignite); - ao_ignition[ao_igniter_drogue].firing = 1; - ao_ignition[ao_igniter_main].firing = 1; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; - AO_IGNITER_DROGUE = 1; - while (ao_launch_ignite) { - ao_launch_ignite = 0; - ao_delay(AO_MS_TO_TICKS(500)); - } - AO_IGNITER_DROGUE = 0; - ao_ignition[ao_igniter_drogue].firing = 0; - ao_ignition[ao_igniter_main].firing = 0; - } -} - -static void -ao_launch_status(void) -{ - uint8_t i; - for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); - if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { - if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { - for (i = 0; i < 5; i++) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); - ao_delay(AO_MS_TO_TICKS(100)); - } - } else { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - } - } - } -} - -static __pdata uint8_t ao_launch_armed; -static __pdata uint16_t ao_launch_arm_time; - -static void -ao_launch(void) -{ - static __xdata struct ao_launch_command command; - static __xdata struct ao_launch_query query; - int16_t time_difference; - - ao_led_off(AO_LED_RED); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - for (;;) { - flush(); - if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) - continue; - - PRINTD ("tick %d serial %d cmd %d channel %d\n", - command.tick, command.serial, command.cmd, command.channel); - - switch (command.cmd) { - case AO_LAUNCH_QUERY: - if (command.serial != ao_serial_number) { - PRINTD ("serial number mismatch\n"); - break; - } - - if (command.channel == 0) { - query.valid = 1; - query.arm_status = ao_igniter_status(ao_igniter_drogue); - query.igniter_status = ao_igniter_status(ao_igniter_main); - } else { - query.valid = 0; - } - query.tick = ao_time(); - query.serial = ao_serial_number; - query.channel = command.channel; - PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", - query.tick, query.serial, query.channel, query.valid, query.arm_status, - query.igniter_status); - ao_radio_cmac_send(&query, sizeof (query)); - break; - case AO_LAUNCH_ARM: - if (command.serial != ao_serial_number) { - PRINTD ("serial number mismatch\n"); - break; - } - - if (command.channel != 0) - break; - time_difference = command.tick - ao_time(); - PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); - if (time_difference < 0) - time_difference = -time_difference; - if (time_difference > 10) { - PRINTD ("time difference too large %d\n", time_difference); - break; - } - PRINTD ("armed\n"); - ao_launch_armed = 1; - ao_launch_arm_time = ao_time(); - break; - case AO_LAUNCH_FIRE: - if (!ao_launch_armed) { - PRINTD ("not armed\n"); - break; - } - if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { - PRINTD ("late launch arm_time %d time %d\n", - ao_launch_arm_time, ao_time()); - break; - } - time_difference = command.tick - ao_time(); - if (time_difference < 0) - time_difference = -time_difference; - if (time_difference > 10) { - PRINTD ("time different too large %d\n", time_difference); - break; - } - PRINTD ("ignite\n"); - ao_launch_ignite = 1; - ao_wakeup(&ao_launch_ignite); - break; - } - } -} - -void -ao_launch_test(void) -{ - switch (ao_igniter_status(ao_igniter_drogue)) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - switch (ao_igniter_status(ao_igniter_main)) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - break; - default: - printf("Disarmed\n"); - } -} - -void -ao_launch_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - ao_launch_ignite = 1; - ao_wakeup(&ao_launch_ignite); -} - -static __xdata struct ao_task ao_launch_task; -static __xdata struct ao_task ao_launch_ignite_task; -static __xdata struct ao_task ao_launch_status_task; - -__code struct ao_cmds ao_launch_cmds[] = { - { ao_launch_test, "t\0Test launch continuity" }, - { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, - { 0, NULL } -}; - -void -ao_launch_init(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; - ao_cmd_register(&ao_launch_cmds[0]); - ao_add_task(&ao_launch_task, ao_launch, "launch listener"); - ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); - ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); -} -- cgit v1.2.3 From 8a1cbef0e316e38c80b71d3bac15641fe56e0a99 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:27:28 -0700 Subject: altos: Add HAS_LOG for products that log to eeprom Some products have eeprom for config, but none for logging (like telelaunch) Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 +- src/core/ao_config.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 9e14c221..d0a46633 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -237,7 +237,7 @@ version(void) printf("manufacturer %s\n", ao_manufacturer); printf("product %s\n", ao_product); printf("serial-number %u\n", ao_serial_number); -#if HAS_EEPROM +#if HAS_LOG printf("log-format %u\n", ao_log_format); #endif printf("software-version %s\n", ao_version); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 28854ab5..a653bed2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -308,7 +308,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG void ao_config_log_show(void) __reentrant { @@ -336,7 +336,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM && HAS_FLIGHT */ +#endif /* HAS_LOG */ #if HAS_IGNITE void @@ -482,7 +482,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif -- cgit v1.2.3 From bc827699be4ed9ac60a7e862e6532791968bf685 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:28:01 -0700 Subject: altos: Fix up telelaunch Makefile Adding all of the mising sources Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 71781bb1..5da42e46 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -22,23 +22,26 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ + ao_launch.c \ ao_mutex.c \ ao_panic.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c \ - ao_sample.c + ao_task.c CC1111_SRC = \ ao_adc.c \ + ao_aes.c \ ao_beep.c \ ao_dbg.c \ ao_dma.c \ ao_ignite.c \ + ao_intflash.c \ ao_led.c \ ao_packet.c \ ao_packet_slave.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_spi.c \ @@ -61,6 +64,7 @@ PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) IDPRODUCT=0x000f +CODESIZE=0x6700 include ../cc1111/Makefile.cc1111 -- cgit v1.2.3 From 7e2b5e2957ddcb808723081ca7e046a28b7e70e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:30:34 -0700 Subject: altosui: launch controller button needs to move over monitor idle was inserted into position 2,2 Signed-off-by: Keith Packard --- altosui/AltosUI.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 8399b7c8..60adfc7c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -210,7 +210,7 @@ public class AltosUI extends JFrame { }); b.setToolTipText("Check flight readiness of altimeter in idle mode"); - b = addButton(2, 2, "Launch Controller"); + b = addButton(3, 2, "Launch Controller"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { LaunchController(); -- cgit v1.2.3 From b33a92e372327158ab21c1bb2d091c58761efe10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 15:19:43 -0700 Subject: altos: Share log code between telescience and telebt. Add telebt log Telescience and telebt both log data in 32-byte chunks, so share some code which manages that between the two products. Add simple telemetry logging to telebt. Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 14 +-- src/core/ao.h | 97 +++++++++++++++---- src/core/ao_log_telem.c | 48 +++++++++- src/core/ao_log_telescience.c | 211 ++++++------------------------------------ src/core/ao_monitor.c | 10 +- src/product/ao_telebt.c | 3 + src/product/ao_telescience.c | 2 +- src/telebt-v0.1/Makefile | 1 + src/telescience-v0.1/Makefile | 1 + 9 files changed, 164 insertions(+), 223 deletions(-) diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 4dde09f3..e4d866a8 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -74,9 +74,9 @@ static uint8_t ao_spi_slave_recv(void) return 0; } - ao_log_store.tm_tick = ao_companion_command.tick; - if (ao_log_store.tm_state != ao_companion_command.flight_state) { - ao_log_store.tm_state = ao_companion_command.flight_state; + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; return 1; } return 0; @@ -93,11 +93,11 @@ ISR(PCINT0_vect) cli(); changed = ao_spi_slave_recv(); sei(); - if (changed && ao_flight_boost <= ao_log_store.tm_state) { - if (ao_log_store.tm_state < ao_flight_landed) - ao_log_start(); + if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); else - ao_log_stop(); + ao_log_single_stop(); } } } else { diff --git a/src/core/ao.h b/src/core/ao.h index a5bbb6f1..8b978272 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,23 +505,6 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -#define AO_LOG_TELESCIENCE_NUM_ADC 12 - -struct ao_log_telescience { - uint8_t type; - uint8_t csum; - uint16_t tick; - uint16_t tm_tick; - uint8_t tm_state; - uint8_t unused; - uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; -}; - -extern struct ao_log_telescience ao_log_store; - /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -1365,6 +1348,20 @@ ao_radio_init(void); extern const char const * const ao_state_names[]; +#define AO_MONITOR_RING 8 + +union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +}; + +extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +extern __data uint8_t ao_monitor_head; + void ao_monitor(void); @@ -1724,4 +1721,70 @@ struct ao_launch_query { void ao_launch_init(void); +/* + * ao_log_single.c + */ + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +#define AO_LOG_SINGLE_SIZE 32 + +union ao_log_single { + struct ao_log_telescience telescience; + union ao_telemetry_all telemetry; + uint8_t bytes[AO_LOG_SINGLE_SIZE]; +}; + +extern __xdata union ao_log_single ao_log_single_write_data; +extern __xdata union ao_log_single ao_log_single_read_data; + +void +ao_log_single_extra_query(void); + +void +ao_log_single_list(void); + +void +ao_log_single_main(void); + +uint8_t +ao_log_single_write(void); + +uint8_t +ao_log_single_read(uint32_t pos); + +void +ao_log_single_start(void); + +void +ao_log_single_stop(void); + +void +ao_log_single_restart(void); + +void +ao_log_single_set(void); + +void +ao_log_single_delete(void); + +void +ao_log_single_init(void); + +void +ao_log_single(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 1b472efe..34abe879 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -17,14 +17,52 @@ #include "ao.h" +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; + +static __data uint8_t ao_log_monitor_pos; + +void +ao_log_single(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(2)); + + ao_log_single_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_monitor_pos = ao_monitor_head; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_monitor_pos != ao_monitor_head) { + memcpy(&ao_log_single_write_data.telemetry, + &ao_monitor_ring[ao_log_monitor_pos], + AO_LOG_SINGLE_SIZE); + ao_log_single_write(); + ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + } + } +} + void -ao_log_write_erase(uint8_t pos) +ao_log_single_list(void) { - (void) pos; + if (ao_log_current_pos != 0) + printf("flight 1 start %x end %x\n", + 0, + (uint16_t) ((ao_log_current_pos + 0xff) >> 8)); + printf ("done\n"); } -uint8_t -ao_log_present(void) +void +ao_log_single_extra_query(void) { - return 0; } diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index aac780fa..31eda381 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -18,119 +18,25 @@ #include "ao.h" #include "ao_product.h" -static struct ao_task ao_log_task; -//static struct ao_task ao_spi_task; - -uint8_t ao_log_running; -uint8_t ao_log_mutex; -uint32_t ao_log_start_pos; -uint32_t ao_log_end_pos; -uint32_t ao_log_current_pos; - -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -struct ao_log_telescience ao_log_store; -struct ao_log_telescience ao_log_fetch; - static uint8_t ao_log_adc_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant +static void +ao_log_telescience_csum(void) __reentrant { + __xdata uint8_t *b = ao_log_single_write_data.bytes; uint8_t sum = 0x5a; uint8_t i; + ao_log_single_write_data.telescience.csum = 0; for (i = 0; i < sizeof (struct ao_log_telescience); i++) sum += *b++; - return -sum; -} - -static uint8_t -ao_log_telescience_write(void) -{ - uint8_t wrote = 0; - - ao_log_store.csum = 0; - ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); - ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - (__xdata uint8_t *) &ao_log_store, - sizeof (struct ao_log_telescience)); - ao_log_current_pos += sizeof (struct ao_log_telescience); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} - -static uint8_t -ao_log_valid(struct ao_log_telescience *log) -{ - uint8_t *d; - uint8_t i; - d = (uint8_t *) log; - for (i = 0; i < sizeof (struct ao_log_telescience); i++) - if (d[i] != 0xff) - return 1; - return 0; -} - -static uint8_t -ao_log_telescience_read(uint32_t pos) -{ - if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) - return 0; - return ao_log_valid(&ao_log_fetch); -} - -void -ao_log_start(void) -{ - if (!ao_log_running) { - ao_log_running = 1; - ao_wakeup(&ao_log_running); - } -} - -void -ao_log_stop(void) -{ - if (ao_log_running) { - ao_log_running = 0; - } -} - -void -ao_log_restart(void) -{ - /* Find end of data */ - ao_log_end_pos = ao_storage_config; - for (ao_log_current_pos = 0; - ao_log_current_pos < ao_storage_config; - ao_log_current_pos += ao_storage_block) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - if (ao_log_current_pos > 0) { - ao_log_current_pos -= ao_storage_block; - for (; ao_log_current_pos < ao_storage_config; - ao_log_current_pos += sizeof (struct ao_log_telescience)) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - } + ao_log_single_write_data.telescience.csum = -sum; } void -ao_log_telescience(void) +ao_log_single(void) { ao_storage_setup(); @@ -139,57 +45,42 @@ ao_log_telescience(void) */ ao_delay(AO_SEC_TO_TICKS(10)); - ao_log_restart(); + ao_log_single_restart(); for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); ao_log_start_pos = ao_log_current_pos; - ao_log_store.type = AO_LOG_TELESCIENCE_START; - ao_log_store.tick = ao_time(); - ao_log_store.adc[0] = ao_companion_command.serial; - ao_log_store.adc[1] = ao_companion_command.flight; - ao_log_telescience_write(); + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_START; + ao_log_single_write_data.telescience.tick = ao_time(); + ao_log_single_write_data.telescience.adc[0] = ao_companion_command.serial; + ao_log_single_write_data.telescience.adc[1] = ao_companion_command.flight; + ao_log_telescience_csum(); + ao_log_single_write(); /* Write the whole contents of the ring to the log * when starting up. */ ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); - ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_adc_head) { - ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - ao_log_telescience_write(); + ao_log_telescience_csum(); + ao_log_single_write(); ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); } /* Wait for more ADC data to arrive */ ao_sleep((void *) &ao_adc_head); } - memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } } void -ao_log_set(void) -{ - printf("Logging currently %s\n", ao_log_running ? "on" : "off"); - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) { - if (ao_cmd_lex_i) { - printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); - ao_log_start(); - } else { - printf ("Log stopped at %ld\n", ao_log_current_pos); - ao_log_stop(); - } - } - ao_cmd_status = ao_cmd_success; -} - -void -ao_log_list(void) +ao_log_single_list(void) { uint32_t pos; uint32_t start = 0; @@ -197,8 +88,8 @@ ao_log_list(void) for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { if (pos >= ao_storage_config || - !ao_log_telescience_read(pos) || - ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + !ao_log_single_read(pos) || + ao_log_single_read_data.telescience.type == AO_LOG_TELESCIENCE_START) { if (pos != start) { printf("flight %d start %x end %x\n", @@ -206,7 +97,7 @@ ao_log_list(void) (uint16_t) (start >> 8), (uint16_t) ((pos + 0xff) >> 8)); flush(); } - if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + if (ao_log_single_read_data.telescience.type != AO_LOG_TELESCIENCE_START) break; start = pos; flight++; @@ -216,59 +107,11 @@ ao_log_list(void) } void -ao_log_delete(void) +ao_log_single_extra_query(void) { - uint32_t pos; - - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_cmd_lex_i != 1) { - ao_cmd_status = ao_cmd_syntax_error; - printf("No such flight: %d\n", ao_cmd_lex_i); - return; - } - ao_log_stop(); - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { - if (!ao_log_telescience_read(pos)) - break; - ao_storage_erase(pos); - } - ao_log_current_pos = ao_log_start_pos = 0; - if (pos == 0) - printf("No such flight: %d\n", ao_cmd_lex_i); - else - printf ("Erased\n"); -} - -static void -ao_log_query(void) -{ - printf("Logging enabled: %d\n", ao_log_running); - printf("Log start: %ld\n", ao_log_start_pos); - printf("Log cur: %ld\n", ao_log_current_pos); - printf("Log end: %ld\n", ao_log_end_pos); - printf("log data tick: %04x\n", ao_log_store.tick); - printf("TM data tick: %04x\n", ao_log_store.tm_tick); - printf("TM state: %d\n", ao_log_store.tm_state); + printf("log data tick: %04x\n", ao_log_single_write_data.telescience.tick); + printf("TM data tick: %04x\n", ao_log_single_write_data.telescience.tm_tick); + printf("TM state: %d\n", ao_log_single_write_data.telescience.tm_state); printf("TM serial: %d\n", ao_companion_command.serial); printf("TM flight: %d\n", ao_companion_command.flight); } - -const struct ao_cmds ao_log_cmds[] = { - { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_list, "l\0List stored flight logs" }, - { ao_log_delete, "d 1\0Delete all stored flights" }, - { ao_log_query, "q\0Query log status" }, - { 0, NULL }, -}; - -void -ao_log_init(void) -{ - ao_log_running = 0; - - ao_cmd_register(&ao_log_cmds[0]); - - ao_add_task(&ao_log_task, ao_log_telescience, "log"); -} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 69eb58e8..6f2d9dbb 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -25,15 +25,7 @@ __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; -#define AO_MONITOR_RING 8 - -__xdata union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +__xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 5bbbf71b..cb23f391 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -42,6 +42,9 @@ main(void) ao_radio_init(); ao_packet_master_init(); ao_btm_init(); +#if HAS_LOG + ao_log_single_init(); +#endif #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 4dec3a18..45b6d40e 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -33,7 +33,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_adc_init(); - ao_log_init(); + ao_log_single_init(); ao_start_scheduler(); return 0; } diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index a34e8912..01fbaf52 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -10,6 +10,7 @@ TELEBT_INC = \ TELEBT_SRC = \ ao_beep.c \ + ao_log_single.c \ ao_log_telem.c \ ao_spi.c \ ao_storage.c \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 3ccbb787..282829e7 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_usb_avr.c \ ao_adc_avr.c \ ao_spi_slave.c \ + ao_log_single.c \ ao_log_telescience.c \ $(TELESCIENCE_STORAGE) -- cgit v1.2.3 From 5c3a0263d292cb0675f608d0ef085d13e51ce6ba Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 28 Aug 2011 13:39:37 -0600 Subject: update changelogs for Debian build --- ChangeLog | 18 ++++++++++++++++++ debian/changelog | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/ChangeLog b/ChangeLog index bcb4d6eb..2711173f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +commit 93b8f40bb451c9ec152490d1f431ab18f8ecb7d1 +Author: Bdale Garbee +Date: Fri Aug 26 10:52:55 2011 -0600 + + more release process doc updates + +commit 9451ae5e4ea6ecfa512ba93197351682d4d043dc +Author: Bdale Garbee +Date: Fri Aug 26 10:51:18 2011 -0600 + + update release process docs + +commit 01aee9ebe517ed657692e0a39a31ae0ddfb5b8b0 +Author: Bdale Garbee +Date: Fri Aug 26 10:39:45 2011 -0600 + + update changelogs for Debian build + commit bc399d97a8424a5262f66a03e3bc403f793bb337 Author: Bdale Garbee Date: Fri Aug 26 10:38:44 2011 -0600 diff --git a/debian/changelog b/debian/changelog index a662e1c3..b9e78c8b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +altos (1.0.1+3+g93b8f40) unstable; urgency=low + + * update release process docs + * more release process doc updates + + -- Bdale Garbee Sun, 28 Aug 2011 13:39:31 -0600 + altos (1.0.1) unstable; urgency=low [ Bdale Garbee ] -- cgit v1.2.3 From e53557373e539d591a03d02db146b27d08c7eba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:18:29 -0700 Subject: altos: Start logging telemetry data right at boot time Anything logging telemetry data should just start logging packets as soon as they boot. Signed-off-by: Keith Packard --- src/core/ao_log_telem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 34abe879..af0e8e6b 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -31,6 +31,7 @@ ao_log_single(void) */ ao_delay(AO_SEC_TO_TICKS(2)); + ao_log_running = 1; ao_log_single_restart(); for (;;) { while (!ao_log_running) @@ -46,7 +47,7 @@ ao_log_single(void) ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); } - /* Wait for more ADC data to arrive */ + /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); } } -- cgit v1.2.3 From 6f231a3e512ff7fdd87a399a72c7c36f283394f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:20:41 -0700 Subject: Bump version to 1.0.9.0 Make it distinct from any production version Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index da9d9991..959f3b4d 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0) +AC_INIT([altos], 1.0.9.0) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 27835686648e14b030f6f7ec1fc0c0fd1c387ea4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:38:12 -0700 Subject: altos: Add RSSI blinking to new-style telemetry code Pull the RSSI data out locally and set the RSSI led blinking when using the variable-length TELEM output mechanism. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 6f2d9dbb..c167b861 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -228,6 +228,10 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); + if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { + rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + ao_rssi_set(rssi); + } break; } ao_usb_flush(); -- cgit v1.2.3 From cff737c290347b61ba16584880c2f4c436b95042 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:40:40 -0700 Subject: altos: Remove RSSI reporting from telebt Telebt uses one LED for bluetooth connection and the other for telem packet reception leaving none for RSSI. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 11 +++++++++++ src/core/ao_monitor.c | 6 ++++++ src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 3 +-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 91719b54..57de67b2 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -111,6 +111,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -220,6 +221,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -245,6 +247,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -276,6 +279,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -314,6 +318,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -456,6 +461,12 @@ #error Please define HAS_MONITOR #endif +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index c167b861..aaa6bb8b 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -151,7 +151,9 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -214,7 +216,9 @@ ao_monitor_put(void) recv_tiny.telemetry_tiny.flight_vel, recv_tiny.telemetry_tiny.flight_pres); #endif +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -228,10 +232,12 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); +#if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; ao_rssi_set(rssi); } +#endif break; } ao_usb_flush(); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ff0e1502..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_rssi.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index cb23f391..9154f4be 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,8 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); + ao_monitor_init(AO_LED_RED, TRUE); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 7c6a3195dec6ac68f5d7b3f883ccc2c316384e76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:42:25 -0700 Subject: altos: Blink on telem packet receive instead of toggle Toggling the LED was too confusing; just blink for 100ms each time a packet comes in. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index aaa6bb8b..382af8a2 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -55,7 +55,15 @@ ao_monitor_get(void) continue; ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_blink(void) +{ + for (;;) { + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); } } @@ -246,6 +254,7 @@ ao_monitor_put(void) __xdata struct ao_task ao_monitor_get_task; __xdata struct ao_task ao_monitor_put_task; +__xdata struct ao_task ao_monitor_blink_task; void ao_set_monitor(uint8_t monitoring) @@ -276,4 +285,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); + if (ao_monitor_led) + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } -- cgit v1.2.3 From 8eaa1c4697a3cfc2406e1adadc3094f7f712341a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:43:32 -0700 Subject: altos: Add pragma to eliminate unreachable code warning on SDCC This pragma was removed as GCC doesn't support it; make it conditional on SDCC so that we eliminate a warning message. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index b6ff65cc..244917a8 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -58,6 +58,9 @@ ao_panic(uint8_t reason) ao_beep(AO_BEEP_OFF); ao_panic_delay(2); +#ifdef SDCC +#pragma disable_warning 126 +#endif for (n = 0; n < reason; n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); -- cgit v1.2.3 From 3d478a39f2ede7b805bbe568cc1c8ecc176d7a04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:45:05 -0700 Subject: altos: Add the BT serial debug code back in, disabled This code is useful whenever the BT stuff is acting up, so just leave the source in place, turned off by default. Signed-off-by: Keith Packard --- src/drivers/ao_btm.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 44155ec1..e70e3048 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -20,6 +20,87 @@ int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; +#define BT_DEBUG 0 + +#if BT_DEBUG +__xdata char ao_btm_buffer[256]; +int ao_btm_ptr; +char ao_btm_dir; + +static void +ao_btm_add_char(char c) +{ + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ + if (dir != ao_btm_dir) { + ao_btm_add_char(dir); + ao_btm_dir = dir; + } + ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ + ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ + ao_btm_log_char(c, '<'); +} + +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ + int i; + char c; + + for (i = 0; i < ao_btm_ptr; i++) { + c = ao_btm_buffer[i]; + if (c < ' ' && c != '\n') + printf("\\%03o", ((int) c) & 0xff); + else + putchar(ao_btm_buffer[i]); + } + putchar('\n'); +} + +static void +ao_btm_speed(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_u32 == 57600) + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + else if (ao_cmd_lex_u32 == 19200) + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + else + ao_cmd_status = ao_cmd_syntax_error; +} + +__code struct ao_cmds ao_btm_cmds[] = { + { ao_btm_dump, "d\0Dump btm buffer." }, + { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, + { 0, NULL }, +}; + +#define ao_btm_log_init() ao_cmd_register(&ao_btm_cmds[0]) + +#else +#define ao_btm_log_in_char(c) +#define ao_btm_log_out_char(c) +#define ao_btm_log_init() +#endif + #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -39,6 +120,7 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; if (c == '\r' || c == '\n') @@ -85,6 +167,7 @@ ao_btm_echo(uint8_t echo) void ao_btm_putchar(char c) { + ao_btm_log_out_char(c); ao_serial_putchar(c); ao_delay(1); } @@ -299,4 +382,5 @@ ao_btm_init (void) #endif ao_add_task(&ao_btm_task, ao_btm, "bt"); + ao_btm_log_init(); } -- cgit v1.2.3 From cf72c2f5a69a736c28a9b63e124d510ef41a9f5d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:50:01 -0700 Subject: altosui: Add bluetooth bits back in Stub out functions on mac/windows for now. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosConfigureUI.java | 33 ++++++++---------- altosui/AltosDeviceDialog.java | 36 ++++++++----------- altosui/Makefile.am | 3 +- altosui/libaltos/libaltos.c | 78 ++++++++++++++++++++++++++++++++++++++++-- altosui/libaltos/libaltos.h | 5 --- 6 files changed, 109 insertions(+), 48 deletions(-) diff --git a/altosui/Altos.java b/altosui/Altos.java index e4f974f9..aa2fd77a 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -498,5 +498,5 @@ public class Altos { public final static String bt_product_telebt = bt_product_telebt(); -// public static AltosBTKnown bt_known = new AltosBTKnown(); + public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index bcb9636b..980068c0 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -52,8 +52,7 @@ public class AltosConfigureUI JRadioButton serial_debug; -// BLUETOOTH -// JButton manage_bluetooth; + JButton manage_bluetooth; JButton manage_frequencies; final static String[] font_size_names = { "Small", "Medium", "Large" }; @@ -241,19 +240,18 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(serial_debug, c); -// BLUETOOTH -// manage_bluetooth = new JButton("Manage Bluetooth"); -// manage_bluetooth.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// AltosBTManage.show(owner, Altos.bt_known); -// } -// }); -// c.gridx = 0; -// c.gridy = row++; -// c.gridwidth = 2; -// c.fill = GridBagConstraints.NONE; -// c.anchor = GridBagConstraints.WEST; -// pane.add(manage_bluetooth, c); + manage_bluetooth = new JButton("Manage Bluetooth"); + manage_bluetooth.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + AltosBTManage.show(owner, Altos.bt_known); + } + }); + c.gridx = 0; + c.gridy = row; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(manage_bluetooth, c); manage_frequencies = new JButton("Manage Frequencies"); manage_frequencies.addActionListener(new ActionListener() { @@ -262,9 +260,8 @@ public class AltosConfigureUI } }); manage_frequencies.setToolTipText("Configure which values are shown in frequency menus"); -// BLUETOOTH -// c.gridx = 2; - c.gridx = 1; + c.gridx = 2; + c.gridx = 2; c.gridy = row++; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index fa9587bc..610bb73e 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -30,8 +30,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private JList list; private JButton cancel_button; private JButton select_button; -// BLUETOOTH -// private JButton manage_bluetooth_button; + private JButton manage_bluetooth_button; private Frame frame; private int product; @@ -42,17 +41,15 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { private AltosDevice[] devices() { java.util.List usb_devices = AltosUSBDevice.list(product); int num_devices = usb_devices.size(); -// BLUETOOTH -// java.util.List bt_devices = Altos.bt_known.list(product); -// num_devices += bt_devices.size(); + java.util.List bt_devices = Altos.bt_known.list(product); + num_devices += bt_devices.size(); AltosDevice[] devices = new AltosDevice[num_devices]; for (int i = 0; i < usb_devices.size(); i++) devices[i] = usb_devices.get(i); -// BLUETOOTH -// int off = usb_devices.size(); -// for (int j = 0; j < bt_devices.size(); j++) -// devices[off + j] = bt_devices.get(j); + int off = usb_devices.size(); + for (int j = 0; j < bt_devices.size(); j++) + devices[off + j] = bt_devices.get(j); return devices; } @@ -75,10 +72,9 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { cancel_button.setActionCommand("cancel"); cancel_button.addActionListener(this); -// BLUETOOTH -// manage_bluetooth_button = new JButton("Manage Bluetooth"); -// manage_bluetooth_button.setActionCommand("manage"); -// manage_bluetooth_button.addActionListener(this); + manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); select_button = new JButton("Select"); select_button.setActionCommand("select"); @@ -152,8 +148,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(cancel_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); -// BLUETOOTH -// buttonPane.add(manage_bluetooth_button); + buttonPane.add(manage_bluetooth_button); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(select_button); @@ -173,12 +168,11 @@ public class AltosDeviceDialog extends JDialog implements ActionListener { public void actionPerformed(ActionEvent e) { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); -// BLUETOOTH -// if ("manage".equals(e.getActionCommand())) { -// AltosBTManage.show(frame, Altos.bt_known); -// update_devices(); -// return; -// } + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame, Altos.bt_known); + update_devices(); + return; + } setVisible(false); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index e2e42d84..c4d1e611 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -118,7 +118,8 @@ altosui_JAVA = \ AltosGraphUI.java \ AltosDataChooser.java \ AltosVersion.java \ - AltosVoice.java + AltosVoice.java \ + $(altosui_BT) JFREECHART_CLASS= \ jfreechart.jar diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index d1f445bd..a3796ee3 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -598,7 +598,6 @@ altos_list_finish(struct altos_list *usbdevs) free(usbdevs); } -#if HAS_BLUETOOTH struct altos_bt_list { inquiry_info *ii; int sock; @@ -730,7 +729,6 @@ no_sock: no_file: return NULL; } -#endif /* HAS_BLUETOOTH */ #endif @@ -844,6 +842,48 @@ altos_list_finish(struct altos_list *list) free(list); } +struct altos_bt_list { + int sock; + int dev_id; + int rsp; + int num_rsp; +}; + +#define INQUIRY_MAX_RSP 255 + +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ + strncpy(device->name, name, sizeof (device->name)); + device->name[sizeof(device->name)-1] = '\0'; + strncpy(device->addr, addr, sizeof (device->addr)); + device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + return NULL; +} + #endif @@ -1180,4 +1220,38 @@ altos_getchar(struct altos_file *file, int timeout) return file->in_data[file->in_read++]; } +struct altos_bt_list * +altos_bt_list_start(int inquiry_time) +{ + return NULL; +} + +int +altos_bt_list_next(struct altos_bt_list *bt_list, + struct altos_bt_device *device) +{ + return 0; +} + +void +altos_bt_list_finish(struct altos_bt_list *bt_list) +{ + free(bt_list); +} + +void +altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device) +{ + strncpy(device->name, name, sizeof (device->name)); + device->name[sizeof(device->name)-1] = '\0'; + strncpy(device->addr, addr, sizeof (device->addr)); + device->addr[sizeof(device->addr)-1] = '\0'; +} + +struct altos_file * +altos_bt_open(struct altos_bt_device *device) +{ + return NULL; +} + #endif diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index 363a84fd..a05bed4c 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -93,9 +93,6 @@ altos_flush(struct altos_file *file); PUBLIC int altos_getchar(struct altos_file *file, int timeout); -// #define HAS_BLUETOOTH 1 -#if HAS_BLUETOOTH - PUBLIC struct altos_bt_list * altos_bt_list_start(int inquiry_time); @@ -111,6 +108,4 @@ altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device); PUBLIC struct altos_file * altos_bt_open(struct altos_bt_device *device); -#endif - #endif /* _LIBALTOS_H_ */ -- cgit v1.2.3 From 31e3255b6cbfaf95c0e97e2d1ec8de72f845994c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:50:30 -0700 Subject: altosui: Report error message back from libaltos This includes changing all of the error dialogs to show the error message rather than just the file name. Signed-off-by: Keith Packard --- altosui/AltosBTDevice.java | 7 +++ altosui/AltosCSVUI.java | 2 +- altosui/AltosConfig.java | 3 +- altosui/AltosDataChooser.java | 2 +- altosui/AltosDevice.java | 1 + altosui/AltosEepromDownload.java | 12 +++-- altosui/AltosEepromManage.java | 3 +- altosui/AltosFlashUI.java | 4 +- altosui/AltosIgniteUI.java | 3 +- altosui/AltosLanded.java | 4 +- altosui/AltosLaunchUI.java | 3 +- altosui/AltosScanUI.java | 6 +-- altosui/AltosSerial.java | 4 +- altosui/AltosUI.java | 9 ++-- altosui/AltosUSBDevice.java | 7 +++ altosui/libaltos/libaltos.c | 97 +++++++++++++++++++++++++++++++++------- altosui/libaltos/libaltos.h | 8 ++++ 17 files changed, 131 insertions(+), 44 deletions(-) diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 7a876c25..55b8f8fc 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -42,6 +42,13 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { return getAddr(); } + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + public int getSerial() { String name = getName(); if (name == null) diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index e1b6002d..a212409e 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -99,7 +99,7 @@ public class AltosCSVUI writer.close(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, - file.getName(), + ee.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 122ebecc..93def70d 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -480,8 +480,7 @@ public class AltosConfig implements ActionListener { } } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 15de05c2..d81ca6d1 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -61,7 +61,7 @@ public class AltosDataChooser extends JFileChooser { } } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(frame, - filename, + fe.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosDevice.java b/altosui/AltosDevice.java index 3357c550..1b5c1a91 100644 --- a/altosui/AltosDevice.java +++ b/altosui/AltosDevice.java @@ -26,5 +26,6 @@ public interface AltosDevice { public abstract int getSerial(); public abstract String getPath(); public abstract boolean matchProduct(int product); + public abstract String getErrorString(); public SWIGTYPE_p_altos_file open(); } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 358ad337..e7e52466 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -248,6 +248,10 @@ public class AltosEepromDownload implements Runnable { done = true; } + void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { + + } + void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; int log_format = flights.config_data.log_format; @@ -300,10 +304,10 @@ public class AltosEepromDownload implements Runnable { extension = "eeprom"; CaptureTiny(eechunk); break; -// case Altos.AO_LOG_FORMAT_TELEMETRY: -// extension = "telem"; -// CaptureTelemetry(eechunk); -// break; + case Altos.AO_LOG_FORMAT_TELEMETRY: + extension = "telem"; + CaptureTelemetry(eechunk); + break; case Altos.AO_LOG_FORMAT_TELESCIENCE: extension = "science"; CaptureTeleScience(eechunk); diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 2e520628..083c7372 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -219,8 +219,7 @@ public class AltosEepromManage implements ActionListener { t.start(); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(frame, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3874b500..3956ff20 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -200,8 +200,8 @@ public class AltosFlashUI void exception (Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(frame, - "Cannot open image", - file.toString(), + ((FileNotFoundException) e).getMessage(), + "Cannot open file", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { JOptionPane.showMessageDialog(frame, diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index c11a8614..b215c228 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -122,8 +122,7 @@ public class AltosIgniteUI void ignite_exception(Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ((FileNotFoundException) e).getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 50e6b542..4dd9a2dd 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -250,7 +250,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio FileInputStream in = new FileInputStream(file); records = new AltosTelemetryIterable(in); } else { - throw new FileNotFoundException(); + throw new FileNotFoundException(filename); } try { new AltosGraphUI(records, filename); @@ -259,7 +259,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } } catch (FileNotFoundException fe) { JOptionPane.showMessageDialog(null, - filename, + fe.getMessage(), "Cannot open file", JOptionPane.ERROR_MESSAGE); } diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 4e630afb..47365e03 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -164,8 +164,7 @@ public class AltosLaunchUI void launch_exception(Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ((FileNotFoundException) e).getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index bce4b32c..df5c51d4 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -130,8 +130,7 @@ public class AltosScanUI void scan_exception(Exception e) { if (e instanceof FileNotFoundException) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ((FileNotFoundException) e).getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } else if (e instanceof AltosSerialInUseException) { @@ -326,8 +325,7 @@ public class AltosScanUI return true; } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(owner, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 0a531aa9..4cf306d0 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -323,8 +323,10 @@ public class AltosSerial implements Runnable { } altos = device.open(); if (altos == null) { + final String message = device.getErrorString(); close(); - throw new FileNotFoundException(device.toShortString()); + throw new FileNotFoundException(String.format("%s (%s)", + device.toShortString(), message)); } if (debug) System.out.printf("Open %s\n", device.getPath()); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 60adfc7c..3e5bcf43 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -52,8 +52,7 @@ public class AltosUI extends JFrame { new AltosFlightUI(voice, reader, device.getSerial()); } catch (FileNotFoundException ee) { JOptionPane.showMessageDialog(AltosUI.this, - String.format("Cannot open device \"%s\"", - device.toShortString()), + ee.getMessage(), "Cannot open target device", JOptionPane.ERROR_MESSAGE); } catch (AltosSerialInUseException si) { @@ -356,7 +355,7 @@ public class AltosUI extends JFrame { else return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } @@ -366,7 +365,7 @@ public class AltosUI extends JFrame { try { return new AltosCSV(file); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } @@ -376,7 +375,7 @@ public class AltosUI extends JFrame { try { return new AltosKML(file); } catch (FileNotFoundException fe) { - System.out.printf("Cannot open '%s'\n", filename); + System.out.printf("%s\n", fe.getMessage()); return null; } } diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index dc746a64..b11a3934 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -39,6 +39,13 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { } + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + public SWIGTYPE_p_altos_file open() { return libaltos.altos_open(this); } diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index a3796ee3..48e00a44 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -49,6 +49,22 @@ altos_fini(void) { } +static struct altos_error last_error; + +static void +altos_set_last_error(int code, char *string) +{ + last_error.code = code; + strncpy(last_error.string, string, sizeof (last_error.string) -1); + last_error.string[sizeof(last_error.string)-1] = '\0'; +} + +PUBLIC void +altos_get_last_error(struct altos_error *error) +{ + *error = last_error; +} + #ifdef DARWIN #undef USE_POLL @@ -96,6 +112,12 @@ struct altos_file { int in_read; }; +static void +altos_set_last_posix_error(void) +{ + altos_set_last_error(errno, strerror(errno)); +} + PUBLIC struct altos_file * altos_open(struct altos_device *device) { @@ -103,12 +125,18 @@ altos_open(struct altos_device *device) int ret; struct termios term; - if (!file) + if (!file) { + altos_set_last_posix_error(); return NULL; + } + +// altos_set_last_error(12, "yeah yeah, failed again"); +// free(file); +// return NULL; file->fd = open(device->path, O_RDWR | O_NOCTTY); if (file->fd < 0) { - perror(device->path); + altos_set_last_posix_error(); free(file); return NULL; } @@ -117,7 +145,7 @@ altos_open(struct altos_device *device) #else file->out_fd = open(device->path, O_RDWR | O_NOCTTY); if (file->out_fd < 0) { - perror(device->path); + altos_set_last_posix_error(); close(file->fd); free(file); return NULL; @@ -125,7 +153,7 @@ altos_open(struct altos_device *device) #endif ret = tcgetattr(file->fd, &term); if (ret < 0) { - perror("tcgetattr"); + altos_set_last_posix_error(); close(file->fd); #ifndef USE_POLL close(file->out_fd); @@ -143,7 +171,7 @@ altos_open(struct altos_device *device) #endif ret = tcsetattr(file->fd, TCSAFLUSH, &term); if (ret < 0) { - perror("tcsetattr"); + altos_set_last_posix_error(); close(file->fd); #ifndef USE_POLL close(file->out_fd); @@ -195,8 +223,10 @@ altos_flush(struct altos_file *file) #else ret = write (file->out_fd, file->out_data, file->out_used); #endif - if (ret < 0) + if (ret < 0) { + altos_set_last_posix_error(); return -errno; + } if (ret) { memmove(file->out_data, file->out_data + ret, file->out_used - ret); @@ -248,7 +278,7 @@ altos_fill(struct altos_file *file, int timeout) fd[1].events = POLLIN; ret = poll(fd, 2, timeout); if (ret < 0) { - perror("altos_getchar"); + altos_set_last_posix_error(); return LIBALTOS_ERROR; } if (ret == 0) @@ -261,7 +291,7 @@ altos_fill(struct altos_file *file, int timeout) { ret = read(file->fd, file->in_data, USB_BUF_SIZE); if (ret < 0) { - perror("altos_getchar"); + altos_set_last_posix_error(); return LIBALTOS_ERROR; } file->in_read = 0; @@ -700,8 +730,10 @@ altos_bt_open(struct altos_bt_device *device) if (!file) goto no_file; file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM); - if (file->fd < 0) + if (file->fd < 0) { + altos_set_last_posix_error(); goto no_sock; + } addr.rc_family = AF_BLUETOOTH; addr.rc_channel = 1; @@ -711,7 +743,7 @@ altos_bt_open(struct altos_bt_device *device) (struct sockaddr *)&addr, sizeof(addr)); if (status < 0) { - perror("connect"); + altos_set_last_posix_error(); goto no_link; } sleep(1); @@ -912,6 +944,21 @@ struct altos_file { OVERLAPPED ov_write; }; +static void +altos_set_last_windows_error(void) +{ + DWORD error = GetLastError(); + TCHAR message[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, + 0, + error, + 0, + message, + sizeof (message) / sizeof (TCHAR), + NULL); + altos_set_last_error(error, message); +} + PUBLIC struct altos_list * altos_list_start(void) { @@ -922,7 +969,7 @@ altos_list_start(void) list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL, DIGCF_ALLCLASSES|DIGCF_PRESENT); if (list->dev_info == INVALID_HANDLE_VALUE) { - printf("SetupDiGetClassDevs failed %ld\n", GetLastError()); + altos_set_last_windows_error(); free(list); return NULL; } @@ -956,6 +1003,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ); if (dev_key == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); printf("cannot open device registry key\n"); continue; } @@ -966,6 +1014,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL, symbolic, &symbolic_len); if (result != 0) { + altos_set_last_windows_error(); printf("cannot find SymbolicName value\n"); RegCloseKey(dev_key); continue; @@ -988,6 +1037,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) port, &port_len); RegCloseKey(dev_key); if (result != 0) { + altos_set_last_windows_error(); printf("failed to get PortName\n"); continue; } @@ -1003,6 +1053,7 @@ altos_list_next(struct altos_list *list, struct altos_device *device) sizeof(friendlyname), &friendlyname_len)) { + altos_set_last_windows_error(); printf("Failed to get friendlyname\n"); continue; } @@ -1015,8 +1066,10 @@ altos_list_next(struct altos_list *list, struct altos_device *device) return 1; } result = GetLastError(); - if (result != ERROR_NO_MORE_ITEMS) + if (result != ERROR_NO_MORE_ITEMS) { + altos_set_last_windows_error(); printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result); + } return 0; } @@ -1035,8 +1088,10 @@ altos_queue_read(struct altos_file *file) return LIBALTOS_SUCCESS; if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) { - if (GetLastError() != ERROR_IO_PENDING) + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } file->pend_read = TRUE; } else { file->pend_read = FALSE; @@ -1061,8 +1116,10 @@ altos_wait_read(struct altos_file *file, int timeout) ret = WaitForSingleObject(file->ov_read.hEvent, timeout); switch (ret) { case WAIT_OBJECT_0: - if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) + if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } file->pend_read = FALSE; file->in_read = 0; file->in_used = got; @@ -1106,15 +1163,20 @@ altos_flush(struct altos_file *file) while (used) { if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) { - if (GetLastError() != ERROR_IO_PENDING) + if (GetLastError() != ERROR_IO_PENDING) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE); switch (ret) { case WAIT_OBJECT_0: - if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) + if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) { + altos_set_last_windows_error(); return LIBALTOS_ERROR; + } break; default: + altos_set_last_windows_error(); return LIBALTOS_ERROR; } } @@ -1142,6 +1204,7 @@ altos_open(struct altos_device *device) 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (file->handle == INVALID_HANDLE_VALUE) { + altos_set_last_windows_error(); free(file); return NULL; } @@ -1157,6 +1220,7 @@ altos_open(struct altos_device *device) dcbSerialParams.DCBlength = sizeof(dcbSerialParams); if (!GetCommState(file->handle, &dcbSerialParams)) { + altos_set_last_windows_error(); CloseHandle(file->handle); free(file); return NULL; @@ -1166,6 +1230,7 @@ altos_open(struct altos_device *device) dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if (!SetCommState(file->handle, &dcbSerialParams)) { + altos_set_last_windows_error(); CloseHandle(file->handle); free(file); return NULL; diff --git a/altosui/libaltos/libaltos.h b/altosui/libaltos/libaltos.h index a05bed4c..f90fbb87 100644 --- a/altosui/libaltos/libaltos.h +++ b/altosui/libaltos/libaltos.h @@ -51,6 +51,11 @@ struct altos_bt_device { //%mutable; }; +struct altos_error { + int code; + char string[1024]; +}; + #define LIBALTOS_SUCCESS 0 #define LIBALTOS_ERROR -1 #define LIBALTOS_TIMEOUT -2 @@ -62,6 +67,9 @@ altos_init(void); PUBLIC void altos_fini(void); +PUBLIC void +altos_get_last_error(struct altos_error *error); + PUBLIC struct altos_list * altos_list_start(void); -- cgit v1.2.3 From 9b9568a637ffdbc67225271005f2b996ee08a0df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:39:41 -0700 Subject: altos: add 'report' to telebt This beeps out flight state changes and max altitude at landing, just like the altimeter. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_log_telem.c | 25 ++++++++++++++++++++++++- src/core/ao_monitor.c | 6 +++--- src/drivers/ao_btm.c | 4 ---- src/product/Makefile.telebt | 1 + src/product/ao_telebt.c | 3 ++- 6 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index 8b978272..f2e40fc6 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1360,6 +1360,7 @@ extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; #define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +extern __data uint8_t ao_monitoring; extern __data uint8_t ao_monitor_head; void diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index af0e8e6b..9afa13b2 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -19,8 +19,29 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; -static __data uint8_t ao_log_monitor_pos; +static __data uint8_t ao_log_monitor_pos; +__pdata enum ao_flight_state ao_flight_state; +__pdata int16_t ao_max_height; /* max of ao_height */ +static void +ao_log_telem_track() { + if (ao_monitoring == sizeof (union ao_telemetry_all)) { + switch (ao_log_single_write_data.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { + ao_max_height = ao_log_single_write_data.telemetry.sensor.height; + } + if (ao_log_single_write_data.telemetry.sensor.state != ao_flight_state) { + ao_flight_state = ao_log_single_write_data.telemetry.sensor.state; + if (ao_flight_state == ao_flight_pad) + ao_max_height = 0; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } + } +} void ao_log_single(void) { @@ -33,6 +54,7 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); + ao_flight_state = ao_flight_startup; for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); @@ -46,6 +68,7 @@ ao_log_single(void) AO_LOG_SINGLE_SIZE); ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + ao_log_telem_track(); } /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 382af8a2..56d7604d 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,7 +22,7 @@ #error Must define HAS_MONITOR to 1 #endif -__xdata uint8_t ao_monitoring; +__data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -37,7 +37,7 @@ ao_monitor_get(void) for (;;) { switch (ao_monitoring) { case 0: - ao_sleep(&ao_monitoring); + ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); @@ -262,7 +262,7 @@ ao_set_monitor(uint8_t monitoring) if (ao_monitoring) ao_radio_recv_abort(); ao_monitoring = monitoring; - ao_wakeup(&ao_monitoring); + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); } static void diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index e70e3048..5eb78815 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -249,10 +249,6 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..04dd044e 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,6 +26,7 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 9154f4be..6fe18a4d 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,8 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); + ao_report_init(); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 122c4101164d598e655fa9ad8473053d30ff4212 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:55:55 -0700 Subject: altos: Report continuity in telebt Report continuity values from remote altimeter Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 6 ++++++ src/core/ao_log_telem.c | 29 +++++++++++++++++++++++++++++ src/core/ao_report.c | 6 ++++-- src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 2 ++ src/telebt-v0.1/Makefile | 1 + 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 57de67b2..723f1500 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -274,6 +274,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 1 #define BT_LINK_ON_P1 0 #define BT_LINK_PIN_INDEX 7 @@ -313,6 +314,7 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 0 #define BT_LINK_ON_P1 1 #define BT_LINK_PIN_INDEX 7 @@ -449,6 +451,10 @@ #error Please define HAS_IGNITE #endif +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + #ifndef PACKET_HAS_MASTER #error Please define PACKET_HAS_MASTER #endif diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9afa13b2..193c11f3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -22,6 +22,7 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ +__pdata int16_t sense_d, sense_m; static void ao_log_telem_track() { @@ -29,6 +30,9 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; @@ -42,6 +46,31 @@ ao_log_telem_track() { } } } + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + int16_t value; + + switch (igniter) { + case ao_igniter_drogue: + value = sense_d; + break; + case ao_igniter_main: + value = sense_m; + break; + default: + value = 0; + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + void ao_log_single(void) { diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 3cf558e1..e0355d96 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -109,7 +109,7 @@ ao_report_altitude(void) } } -#if HAS_IGNITE +#if HAS_IGNITE_REPORT static uint8_t ao_report_igniter_ready(enum ao_igniter igniter) { @@ -133,6 +133,7 @@ ao_report_continuity(void) __reentrant low(AO_MS_TO_TICKS(20)); } } +#if HAS_LOG if (ao_log_full()) { pause(AO_MS_TO_TICKS(100)); c = 2; @@ -143,6 +144,7 @@ ao_report_continuity(void) __reentrant mid(AO_MS_TO_TICKS(100)); } } +#endif c = 50; while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); @@ -157,7 +159,7 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); -#if HAS_IGNITE +#if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 04dd044e..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 6fe18a4d..9e409db7 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -38,7 +38,9 @@ main(void) #endif ao_usb_init(); ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); +#if HAS_LOG ao_report_init(); +#endif ao_radio_init(); ao_packet_master_init(); ao_btm_init(); diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index 01fbaf52..90cd3cac 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -12,6 +12,7 @@ TELEBT_SRC = \ ao_beep.c \ ao_log_single.c \ ao_log_telem.c \ + ao_report.c \ ao_spi.c \ ao_storage.c \ ao_m25.c -- cgit v1.2.3 From e66fd72664aae7c000dce9c528803e28e7918fdf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 17:03:26 -0700 Subject: altos: don't beep igniter continuity for telenano Without any igniters, it's not nice to annoy people. Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ src/core/ao_log_telem.c | 10 ++++++++-- src/core/ao_report.c | 18 +++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index f2e40fc6..a541d8ac 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1436,6 +1436,8 @@ extern __xdata struct ao_ignition ao_ignition[2]; enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); +extern __pdata uint8_t ao_igniter_present; + void ao_ignite_set_pins(void); diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 193c11f3..096ad919 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -23,6 +23,7 @@ static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ __pdata int16_t sense_d, sense_m; +__pdata uint8_t ao_igniter_present; static void ao_log_telem_track() { @@ -30,10 +31,15 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: - sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; - sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.generic.type == AO_TELEMETRY_SENSOR_TELENANO) { + ao_igniter_present = 0; + } else { + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + ao_igniter_present = 1; + } if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; } diff --git a/src/core/ao_report.c b/src/core/ao_report.c index e0355d96..70f0b49d 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -119,7 +119,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) static void ao_report_continuity(void) __reentrant { - uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + uint8_t c; + +#if !HAS_IGNITE + if (!ao_igniter_present) + return; +#endif + c = (ao_report_igniter_ready(ao_igniter_drogue) | (ao_report_igniter_ready(ao_igniter_main) << 1)); if (c) { while (c--) { @@ -145,9 +151,6 @@ ao_report_continuity(void) __reentrant } } #endif - c = 50; - while (c-- && ao_flight_state == ao_flight_pad) - pause(AO_MS_TO_TICKS(100)); } #endif @@ -162,8 +165,13 @@ ao_report(void) #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); - while (ao_flight_state == ao_flight_pad) + while (ao_flight_state == ao_flight_pad) { + uint8_t c; ao_report_continuity(); + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); + } #endif __critical { while (ao_report_state == ao_flight_state) -- cgit v1.2.3 From b2d4e49bfe88aa61ca36fb1af8f3088c5754304c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Aug 2011 14:22:19 -0700 Subject: altos: Split avr clock initialization to ao_clock.c This will be shared with the attiny code for TeleTerra v0.1 Signed-off-by: Keith Packard --- src/avr/ao_clock.c | 77 +++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_timer.c | 58 -------------------------------- src/telescience-v0.1/Makefile | 1 + 3 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/avr/ao_clock.c diff --git a/src/avr/ao_clock.c b/src/avr/ao_clock.c new file mode 100644 index 00000000..0d42b6d5 --- /dev/null +++ b/src/avr/ao_clock.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* + * AltOS always cranks the clock to the max frequency + */ + +void +ao_clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + + /* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL + CLKPR = 1; +#else + CLKPR = 0; +#endif + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; + + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_enable(); +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index 1e374c75..eef14345 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -87,61 +87,3 @@ ao_timer_init(void) TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ } - -/* - * AltOS always cranks the clock to the max frequency - */ -void -ao_clock_init(void) -{ - /* disable RC clock */ - CLKSEL0 &= ~(1 << RCE); - - /* Disable PLL */ - PLLCSR &= ~(1 << PLLE); - - /* Enable external clock */ - CLKSEL0 |= (1 << EXTE); - - /* wait for external clock to be ready */ - while ((CLKSTA & (1 << EXTON)) == 0) - ; - - /* select external clock */ - CLKSEL0 |= (1 << CLKS); - - /* Disable the clock prescaler */ - cli(); - CLKPR = (1 << CLKPCE); - - /* Always run the system clock at 8MHz */ -#if AVR_CLOCK > 12000000UL - CLKPR = 1; -#else - CLKPR = 0; -#endif - sei(); - - /* Set up the PLL to use the crystal */ - - /* Use primary system clock as PLL source */ - PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ - (0 << PLLUSB) | /* No divide by 2 for USB */ - (0 << PLLTM0) | /* Disable high speed timer */ - (0x4 << PDIV0)); /* 48MHz PLL clock */ - - /* Set the frequency of the crystal */ -#if AVR_CLOCK > 12000000UL - PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ -#else - PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ -#endif - - /* Enable the PLL */ - PLLCSR |= (1 << PLLE); - while (!(PLLCSR & (1 << PLOCK))) - ; - - set_sleep_mode(SLEEP_MODE_IDLE); - sleep_enable(); -} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 282829e7..28620242 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -33,6 +33,7 @@ TELESCIENCE_STORAGE= \ ao_storage.c \ ALTOS_SRC = \ + ao_clock.c \ ao_cmd.c \ ao_mutex.c \ ao_panic.c \ -- cgit v1.2.3 From e44f1ffb7104d70f5c9b9a90529ddbe1b75da074 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Aug 2011 16:59:53 -0600 Subject: include 1.0.1 release notes in docs --- doc/altusmetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 5a60da7a..606c8b99 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -2480,7 +2480,7 @@ NAR #88757, TRA #12200 Release Notes - + -- cgit v1.2.3 From d1e81db87ce0f89fd0b7651ca00979498cd00b78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Sep 2011 08:48:05 -0700 Subject: altos: Delay restart of RDF at apogee Instead of immediately trying to send RDF at apogee, start it after the usual RDF interval to avoid doing RDF while firing the apogee igniter. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index c7338a58..d006aa59 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -258,7 +258,7 @@ ao_rdf_set(uint8_t rdf) if (rdf == 0) ao_radio_rdf_abort(); else - ao_rdf_time = ao_time(); + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; } __xdata struct ao_task ao_telemetry_task; -- cgit v1.2.3 From eaa7d7c7dd445ade7d8e3228306785f9a545b89a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Sep 2011 08:49:16 -0700 Subject: altos: Silence radio while firing igniters Hold the radio mutex while firing igniters to reduce potential interactions between the two. Signed-off-by: Keith Packard --- src/ao_ignite.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 5238beb4..ac1d28e7 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -90,6 +90,7 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { + ao_mutex_get(&ao_radio_mutex); ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -134,6 +135,7 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; + ao_mutex_put(&ao_radio_mutex); } void -- cgit v1.2.3 From 246864b0597ddd397aba39be1fe39df0df189433 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Sep 2011 18:27:56 -0700 Subject: Update to version 1.0.2 Bdale is planning to fly this version on 9/17. Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 27d56751..650aeffb 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.1) +AC_INIT([altos], 1.0.2) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From abf17522c206b465375b73a004a6d67bfa714ba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:36:11 -0700 Subject: altos: SPI slave code is now per-product We can't write general purpose SPI slave code as we must eliminate any latency because the SPI ports have no buffering. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 7 +++ src/avr/ao_spi_slave.c | 99 +++++++++++++++--------------------------- src/core/ao.h | 13 +++++- src/drivers/ao_science_slave.c | 62 ++++++++++++++++++++++++++ src/telescience-v0.1/Makefile | 1 + 5 files changed, 118 insertions(+), 64 deletions(-) create mode 100644 src/drivers/ao_science_slave.c diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 56435f18..88f03829 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -52,6 +52,13 @@ #define SPI_CS_DIR DDRE #define M25_CS_MASK (1 << PORTE6) #define M25_MAX_CHIPS 1 + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 #endif #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index e4d866a8..76f574c6 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -16,18 +16,8 @@ */ #include "ao.h" -#include "ao_product.h" -struct ao_companion_command ao_companion_command; - -static const struct ao_companion_setup ao_telescience_setup = { - .board_id = AO_idProduct_NUMBER, - .board_id_inverse = ~AO_idProduct_NUMBER, - .update_period = 50, - .channels = AO_LOG_TELESCIENCE_NUM_ADC, -}; - -static uint8_t +uint8_t ao_spi_read(uint8_t *buf, uint8_t len) { while (len--) { @@ -39,7 +29,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) return 1; } -static void +void ao_spi_write(uint8_t *buf, uint8_t len) { while (len--) { @@ -52,66 +42,38 @@ ao_spi_write(uint8_t *buf, uint8_t len) (void) SPDR; } -static uint8_t ao_spi_slave_recv(void) -{ - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) - return 0; - - /* Figure out the outbound data */ - switch (ao_companion_command.command) { - case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); - break; - case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - break; - case AO_COMPANION_NOTIFY: - break; - default: - return 0; - } - - ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; - if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { - ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; - return 1; - } - return 0; -} - static uint8_t ao_spi_slave_running; ISR(PCINT0_vect) { - if ((PINB & (1 << PINB0)) == 0) { + cli(); +#if SPI_SLAVE_PIN_0_3 + if ((PINB & (1 << PORTB0)) == 0) +#endif +#if SPI_SLAVE_PIN_2_5 + if ((PINB & (1 << PORTB2)) == 0) +#endif + { if (!ao_spi_slave_running) { - uint8_t changed; ao_spi_slave_running = 1; - cli(); - changed = ao_spi_slave_recv(); - sei(); - if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { - if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) - ao_log_single_start(); - else - ao_log_single_stop(); - } + ao_spi_slave(); } } else { ao_spi_slave_running = 0; } -} - -void ao_spi_slave_debug(void) { - printf ("slave running %d\n", ao_spi_slave_running); + sei(); } void ao_spi_slave_init(void) { + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ +#if SPI_SLAVE_PIN_0_3 PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ @@ -121,17 +83,28 @@ ao_spi_slave_init(void) (0 << 1) | /* SCK, input */ (0 << 0)); /* SS, input */ - /* We'd like to have a pull-up on SS so that disconnecting the - * TM would cause any SPI transaction to abort. However, when - * I tried that, SPI transactions would spontaneously abort, - * making me assume that we needed a less aggressive pull-up - * than is offered inside the AVR - */ PORTB = ((PORTB & 0xf0) | (1 << 3) | /* MISO, output */ (0 << 2) | /* MOSI, no pull-up */ (0 << 1) | /* SCK, no pull-up */ (0 << 0)); /* SS, no pull-up */ +#endif +#if SPI_SLAVE_PIN_2_5 + PCMSK0 |= (1 << PCINT2); /* Enable PCINT2 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (0 << 5) | /* SCK, input */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, input */ + (0 << 2)); /* SS, input */ + + PORTB = ((PORTB & 0xf0) | + (0 << 5) | /* SCK, no pull-up */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, no pull-up */ + (0 << 2)); /* SS, no pull-up */ +#endif SPCR = (0 << SPIE) | /* Disable SPI interrupts */ (1 << SPE) | /* Enable SPI */ diff --git a/src/core/ao.h b/src/core/ao.h index a541d8ac..1d5769cb 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -974,12 +974,23 @@ ao_spi_init(void); * ao_spi_slave.c */ +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len); + void -ao_spi_slave_debug(void); +ao_spi_write(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); +/* This must be defined by the product; it will get called when chip + * select goes low, at which point it should use ao_spi_read and + * ao_spi_write to deal with the request + */ + +void +ao_spi_slave(void); + /* * ao_telemetry.c */ diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c new file mode 100644 index 00000000..e902318f --- /dev/null +++ b/src/drivers/ao_science_slave.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } + + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; + if (ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); + else + ao_log_single_stop(); + } + } +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 28620242..a6797cbe 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_romconfig.c \ ao_usb_avr.c \ ao_adc_avr.c \ + ao_science_slave.c \ ao_spi_slave.c \ ao_log_single.c \ ao_log_telescience.c \ -- cgit v1.2.3 From c8a00bb9ccdf0d4257f037c2bf996ce5e6b0b0c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:39:24 -0700 Subject: altos: Pre-compute RDF packet len at compile time Instead of computing the RDF packet len at run time, which takes a pile of code space. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 14 +------------- src/core/ao.h | 12 +++++++++++- src/core/ao_telemetry.c | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 00816b33..75f241d4 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -367,21 +367,9 @@ ao_radio_recv_abort(void) __xdata ao_radio_rdf_value = 0x55; void -ao_radio_rdf(int ms) +ao_radio_rdf(uint8_t pkt_len) { uint8_t i; - uint8_t pkt_len; - - /* - * Compute the packet length as follows: - * - * 2000 bps (for a 1kHz tone) - * so, for 'ms' milliseconds, we need - * 2 * ms bits, or ms / 4 bytes - */ - if (ms > (255 * 4)) - ms = 255 * 4; - pkt_len = ms >> 2; ao_radio_abort = 0; ao_radio_get(pkt_len); diff --git a/src/core/ao.h b/src/core/ao.h index 1d5769cb..c28c4549 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1341,8 +1341,18 @@ ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; void ao_radio_recv_abort(void); +/* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + +#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) + void -ao_radio_rdf(int ms); +ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index de669ce1..c2707e7d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -235,7 +235,7 @@ ao_telemetry(void) (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); + ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); } #endif time += ao_telemetry_interval; -- cgit v1.2.3 From 0820f5c6dfe067590f36e8201a4049719dcf3d7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:40:56 -0700 Subject: altos: Support staging by going back to boost as needed Detect additional motor burns by looking for high positive acceleration in coast or fast modes. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 85c1825b..a5cf7468 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -34,7 +34,7 @@ /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ /* * track min/max data over a long interval to detect @@ -151,7 +151,7 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_sample_tick; + ao_boost_tick = ao_sample_tick; /* start logging data */ ao_log_start(); @@ -184,7 +184,7 @@ ao_flight(void) * (15 seconds) has past. */ if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; @@ -205,7 +205,8 @@ ao_flight(void) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } + } else + goto check_re_boost; break; #endif case ao_flight_coast: @@ -237,6 +238,16 @@ ao_flight(void) ao_flight_state = ao_flight_drogue; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } +#if HAS_ACCEL + else { + check_re_boost: + if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif break; case ao_flight_drogue: -- cgit v1.2.3 From 7a02d4bace05cc829522933b9df6b82a9e17336f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:30:43 -0700 Subject: altos: Add TelePyro v0.1 support Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 21 ++++++++- src/avr/ao_pins.h | 24 +++++++++++ src/core/ao.h | 6 +++ src/drivers/ao_pyro_slave.c | 51 ++++++++++++++++++++++ src/product/ao_telepyro.c | 36 ++++++++++++++++ src/telepyro-v0.1/Makefile | 101 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/drivers/ao_pyro_slave.c create mode 100644 src/product/ao_telepyro.c create mode 100644 src/telepyro-v0.1/Makefile diff --git a/src/Makefile b/src/Makefile index 9ef5ae0a..91d3f035 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ SUBDIRS=\ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ - tidongle test telescience-v0.1 + tidongle test telescience-v0.1 telepyro-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 5afced74..9f45acaf 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -20,6 +20,7 @@ volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; +#ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x00, 0x01, @@ -34,6 +35,22 @@ const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x24, 0x25, }; +#endif + +#ifdef TELEPYRO +const uint8_t adc_channels[AO_TELEPYRO_NUM_ADC] = { + 0x00, /* ADC0 v_batt */ + 0x04, /* ADC4 sense_a */ + 0x05, /* ADC5 sense_b */ + 0x06, /* ADC6 sense_c */ + 0x07, /* ADC7 sense_d */ + 0x23, /* ADC11 sense_e */ + 0x22, /* ADC10 sense_f */ + 0x21, /* ADC9 sense_g */ +}; +#endif + +#define NUM_ADC (sizeof (adc_channels) / sizeof (adc_channels[0])) static uint8_t ao_adc_channel; @@ -75,7 +92,7 @@ ISR(ADC_vect) value = ADCL; value |= (ADCH << 8); ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; - if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; @@ -108,7 +125,7 @@ ao_adc_dump(void) __reentrant uint8_t i; ao_adc_get(&packet); printf("tick: %5u", packet.tick); - for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); printf ("\n"); } diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 88f03829..6b72530b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -61,4 +61,28 @@ #define SPI_SLAVE_PIN_2_5 0 #endif +#ifdef TELEPYRO + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 0 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c28c4549..04610fea 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1811,4 +1811,10 @@ ao_log_single_init(void); void ao_log_single(void); +/* + * ao_pyro_slave.c + */ + +#define AO_TELEPYRO_NUM_ADC 9 + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c new file mode 100644 index 00000000..e6c73a3c --- /dev/null +++ b/src/drivers/ao_pyro_slave.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telepyro_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_TELEPYRO_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } +} diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c new file mode 100644 index 00000000..a2b8f83c --- /dev/null +++ b/src/product/ao_telepyro.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_slave_init(); + ao_usb_init(); + ao_adc_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile new file mode 100644 index 00000000..2f664fcb --- /dev/null +++ b/src/telepyro-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +ALTOS_SRC = \ + ao_clock.c \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_pyro_slave.c \ + ao_spi_slave.c + +PRODUCT=TelePyro-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELEPYRO +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telepyro-v0.1 + +SRC=$(ALTOS_SRC) ao_telepyro.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +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 + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h -- cgit v1.2.3 From 16aa67fc77b82a9d051f205037b27a5384e3e3b7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 14:24:30 -0700 Subject: altos: missing ao_log_single.c Neglected to add this file. Signed-off-by: Keith Packard --- src/core/ao_log_single.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/core/ao_log_single.c diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c new file mode 100644 index 00000000..9e90bd82 --- /dev/null +++ b/src/core/ao_log_single.c @@ -0,0 +1,198 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +/* + * ao_log_single.c + * + * Stores a sequence of fixed-size (32 byte) chunks + * without splitting memory up into separate flights + */ + +#include "ao.h" +#include "ao_product.h" + +static __xdata struct ao_task ao_log_single_task; + +__xdata uint8_t ao_log_running; +__xdata uint8_t ao_log_mutex; +__pdata uint32_t ao_log_start_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_current_pos; + +__xdata union ao_log_single ao_log_single_write_data; +__xdata union ao_log_single ao_log_single_read_data; + +uint8_t +ao_log_single_write(void) +{ + uint8_t wrote = 0; + + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_single_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + &ao_log_single_write_data, + AO_LOG_SINGLE_SIZE); + ao_log_current_pos += AO_LOG_SINGLE_SIZE; + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_single_valid(void) +{ + __xdata uint8_t *d = ao_log_single_read_data.bytes; + uint8_t i; + for (i = 0; i < AO_LOG_SINGLE_SIZE; i++) + if (*d++ != 0xff) + return 1; + return 0; +} + +uint8_t +ao_log_single_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_single_read_data, AO_LOG_SINGLE_SIZE)) + return 0; + return ao_log_single_valid(); +} + +void +ao_log_single_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_single_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_single_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_single_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_single_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_single_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_single_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_single_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_single_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos >= ao_log_end_pos; +} + +uint8_t +ao_log_present(void) +{ + return ao_log_single_read(0); +} + +static void +ao_log_single_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + ao_log_single_extra_query(); +} + +const struct ao_cmds ao_log_single_cmds[] = { + { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_single_list, "l\0List stored flight logs" }, + { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_single_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_single_cmds[0]); + + ao_add_task(&ao_log_single_task, ao_log_single, "log"); +} -- cgit v1.2.3 From f68f22f527104cdffa1f5e398a51a466a13ff1fb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 21 Sep 2011 16:42:22 -0600 Subject: add missing sense_h entry in TelePyro table --- src/avr/ao_adc_avr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 9f45acaf..4c4bcbda 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -47,6 +47,7 @@ const uint8_t adc_channels[AO_TELEPYRO_NUM_ADC] = { 0x23, /* ADC11 sense_e */ 0x22, /* ADC10 sense_f */ 0x21, /* ADC9 sense_g */ + 0x20, /* ADC8 sense_h */ }; #endif -- cgit v1.2.3 From 74d5dea5d5ef91db823018b631613d15c6da085d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 21 Sep 2011 16:42:52 -0600 Subject: fix bashism that prevents building with /bin/sh->/bin/dash --- src/Makefile | 2 +- src/util/make-kalman | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 91d3f035..5da7c855 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,7 +48,7 @@ altitude.h: make-altitude nickle $< > $@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< kalman > $@ + bash $< kalman > $@ clean-local: rm -f altitude.h ao_kalman.h diff --git a/src/util/make-kalman b/src/util/make-kalman index f78f30a9..b4e5d919 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash cd $1 >&/dev/null -- cgit v1.2.3 From 7bc007ed45af8fe9ef5daeb7844f183cd9a49035 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 18:13:55 -0700 Subject: altos: Fix make-kalman to run under dash Dash can't deal with >&, so use the old-school > file 2>&1 Signed-off-by: Keith Packard --- src/util/make-kalman | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/make-kalman b/src/util/make-kalman index b4e5d919..397d6020 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -1,6 +1,6 @@ #!/bin/bash -cd $1 >&/dev/null +cd $1 2> /dev/null 1>&2 SIGMA_BOTH="-M 2 -H 6 -A 2" SIGMA_BARO="-M 2 -H 6 -A 2" -- cgit v1.2.3 From 9b498a6b1327f543c73145e02ff16e76d09f2fe4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 22:54:56 -0700 Subject: Dump ADC registers --- src/avr/ao_adc_avr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 4c4bcbda..06284d68 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,6 +125,14 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_adc packet; uint8_t i; ao_adc_get(&packet); + printf("ADMUX: %02x\n", ADMUX); + printf("ADCSRA: %02x\n", ADCSRA); + printf("ADCSRB: %02x\n", ADCSRB); + printf("DIDR0: %02x\n", DIDR0); + printf("DIDR2: %02x\n", DIDR2); + printf("PORTF: %02x\n", PORTF); + printf("DDRF: %02x\n", DDRF); + printf("PINF: %02x\n", PINF); printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); -- cgit v1.2.3 From f1328d22aab4378c4fb6f0c24dbee95948ca836c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 23:21:04 -0700 Subject: Dump test conversion of ADC0 --- src/avr/ao_adc_avr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 06284d68..a47703e5 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -66,7 +66,7 @@ static uint8_t ao_adc_channel; #define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ (0 << ACME) | /* Some comparitor thing */ \ - (2 << ADTS0)) /* Free running mode (don't care) */ + (0 << ADTS0)) /* Free running mode (don't care) */ static void ao_adc_start(void) @@ -136,6 +136,15 @@ ao_adc_dump(void) __reentrant printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); + + + ADMUX = 0x60; + ADCSRB = 0x00; + ADCSRA = 0xc6; + while (ADCSRA & 0x40) + ; + printf ("ADCL: %02x\n", ADCL); + printf ("ADCH: %02x\n", ADCH); printf ("\n"); } -- cgit v1.2.3 From 4ed53ef838afd4e922deb1c721a311974527525a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Sep 2011 10:24:33 -0700 Subject: altos: Debug code for telepyro doesn't fit in telescience Just too many strings. Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index a47703e5..8c0cade0 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,6 +125,7 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_adc packet; uint8_t i; ao_adc_get(&packet); +#ifdef TELEPYRO printf("ADMUX: %02x\n", ADMUX); printf("ADCSRA: %02x\n", ADCSRA); printf("ADCSRB: %02x\n", ADCSRB); @@ -133,11 +134,13 @@ ao_adc_dump(void) __reentrant printf("PORTF: %02x\n", PORTF); printf("DDRF: %02x\n", DDRF); printf("PINF: %02x\n", PINF); +#endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); +#ifdef TELEPYRO ADMUX = 0x60; ADCSRB = 0x00; ADCSRA = 0xc6; @@ -146,6 +149,7 @@ ao_adc_dump(void) __reentrant printf ("ADCL: %02x\n", ADCL); printf ("ADCH: %02x\n", ADCH); printf ("\n"); +#endif } __code struct ao_cmds ao_adc_cmds[] = { -- cgit v1.2.3 From 0552fbed34c9698dac30c239df2a823a8502b3f3 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 30 Aug 2011 16:59:53 -0600 Subject: include 1.0.1 release notes in docs, closes: #642705 --- doc/altusmetrum.xsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 5a60da7a..606c8b99 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -2480,7 +2480,7 @@ NAR #88757, TRA #12200 Release Notes - + -- cgit v1.2.3 From fc4173ff882dd9718f34ed043276ef612783dfe0 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 27 Sep 2011 00:59:08 -0600 Subject: add run-time dependency on libjfreechart-java --- debian/control | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/control b/debian/control index 15176565..31daaf1b 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,7 @@ Vcs-Browser: http://git.gag.com/?p=fw/altos Package: altos Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends}, default-jre | java2-runtime, freetts, nickle +Depends: ${shlibs:Depends}, ${misc:Depends}, default-jre | java2-runtime, freetts, nickle, libjfreechart-java Suggests: slim | gdm Replaces: altusmetrum-themes, slim-altusmetrum Conflicts: altusmetrum-themes, slim-altusmetrum -- cgit v1.2.3 From fba1d605a627d03f9587ec060c45fb5d3e96aaeb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Sep 2011 11:50:28 -0700 Subject: altos: Delay reboot by a second to avoid re-entering idle mode TM and Tm go into idle mode if they receive a packet after boot time. When tebooting the device over the packet link, the packet master would be (rapidly) polling the device for additional data and so the device would invariably receive a packet during bootup and go into idle mode again. Delay the reboot by a second to give the controller time to disable the master end of the packet link. Signed-off-by: Keith Packard --- src/ao_cmd.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 1442ebea..8037195a 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -208,6 +208,13 @@ ao_reboot(void) ao_cmd_white(); if (!ao_match_word("eboot")) return; + + /* Delay waiting for the packet master to be turned off + * so that we don't end up back in idle mode because we + * received a packet after boot. + */ + flush(); + ao_delay(AO_SEC_TO_TICKS(1)); WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); -- cgit v1.2.3 From 0d10e25766b96f5660e213115cf27b71ff164405 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Sep 2011 21:06:54 -0700 Subject: altos: TM: Don't turn on packet slave mode until idle/invalid state Leave the packet link disabled until we've checked the accelerometer. That way, we cannot accidentally get to idle mode when the rocket is on the rail. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 ++++++++++- src/ao_packet_slave.c | 6 ++++-- src/ao_telemetrum.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/ao_flight.c b/src/ao_flight.c index 85c1825b..0a9cc046 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -91,6 +91,8 @@ ao_flight(void) */ ao_flight_state = ao_flight_invalid; + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); } else #endif if (!ao_flight_force_idle @@ -108,8 +110,10 @@ ao_flight(void) ao_usb_disable(); #endif - /* Disable packet mode in pad state */ +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ ao_packet_slave_stop(); +#endif /* Turn on telemetry system */ ao_rdf_set(1); @@ -121,6 +125,11 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; +#if HAS_ACCEL + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 9f14052a..d7cafa68 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -37,8 +37,10 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } } void diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index f560740a..ea77f5af 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(TRUE); + ao_packet_slave_init(FALSE); ao_igniter_init(); #if HAS_DBG ao_dbg_init(); -- cgit v1.2.3 From 258b75498916183ed250d3abb3282fe3d843e7a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Oct 2011 09:53:09 -0600 Subject: altos: Write xdata versions of memory functions These are significantly smaller than the general pointer versions from libc on the cc1111. Signed-off-by: Keith Packard Conflicts: src/Makefile.proto src/cc1111/ao_adc.c src/cc1111/ao_packet_master.c src/core/ao.h Fix up the new makefiles --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 17 +++++++++++++++++ src/cc1111/ao_intflash.c | 2 +- src/cc1111/ao_packet.c | 4 ++-- src/cc1111/ao_packet_master.c | 2 +- src/cc1111/ao_packet_slave.c | 2 +- src/core/ao.h | 6 ++++++ src/core/ao_cmd.c | 4 ++-- src/core/ao_config.c | 11 ++++++----- src/core/ao_ee_fake.c | 2 +- src/core/ao_gps_report.c | 4 ++-- src/core/ao_host.h | 4 ++++ src/core/ao_monitor.c | 4 ++-- src/core/ao_telemetry.c | 10 +++++----- src/drivers/ao_25lc1024.c | 6 +++--- src/drivers/ao_at45db161d.c | 6 +++--- src/drivers/ao_gps_skytraq.c | 4 ++-- src/product/Makefile.telebt | 1 + src/product/Makefile.teledongle | 1 + src/product/Makefile.telelaunch | 1 + src/product/Makefile.telemetrum | 1 + src/product/Makefile.telemini | 1 + src/product/Makefile.telenano | 1 + src/test/ao_flight_test.c | 8 ++++++-- src/tidongle/Makefile | 1 + 25 files changed, 72 insertions(+), 33 deletions(-) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 6aa6e018..1688eceb 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -46,7 +46,7 @@ ao_adc_get(__xdata struct ao_adc *packet) #else uint8_t i = ao_adc_ring_prev(ao_adc_head); #endif - memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } void diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8a41791f..02e36189 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,4 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_string.c */ + +void +_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); + +#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + +void +_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); + +#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) + +int8_t +_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); + +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c index d76d954e..632e2a85 100644 --- a/src/cc1111/ao_intflash.c +++ b/src/cc1111/ao_intflash.c @@ -180,7 +180,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant { if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; - memcpy(d, ao_intflash+pos, len); + ao_xmemcpy(d, ao_intflash+pos, len); return 1; } diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index f627e02b..37ba92e0 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -35,7 +35,7 @@ ao_packet_send(void) ao_led_on(AO_LED_RED); /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { - memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); ao_tx_packet.len = ao_packet_tx_used; ao_tx_packet.seq++; ao_packet_tx_used = 0; @@ -80,7 +80,7 @@ ao_packet_recv(void) /* Copy data to the receive data buffer and set up the * offsets */ - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); ao_packet_rx_used = 0; ao_packet_rx_len = ao_rx_packet.packet.len; diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index 0d0be30e..ab19f979 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -81,7 +81,7 @@ ao_packet_master(void) ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { uint8_t r; - memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c index d7cafa68..fd5d443e 100644 --- a/src/cc1111/ao_packet_slave.c +++ b/src/cc1111/ao_packet_slave.c @@ -24,7 +24,7 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { if (ao_packet_recv()) { - memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); #if HAS_FLIGHT ao_flight_force_idle = TRUE; #endif diff --git a/src/core/ao.h b/src/core/ao.h index 04610fea..c0474729 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1817,4 +1817,10 @@ ao_log_single(void); #define AO_TELEPYRO_NUM_ADC 9 +#ifndef ao_xmemcpy +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#endif + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 2b64b8ca..0c902f6b 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -265,8 +265,8 @@ help(void) cs = ao_cmds[cmds]; for (cmd = 0; cs[cmd].func; cmd++) printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a653bed2..08cc79b1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,8 +78,8 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } @@ -148,7 +148,7 @@ ao_config_callsign_set(void) __reentrant uint8_t c; static __xdata char callsign[AO_MAX_CALLSIGN + 1]; - memset(callsign, '\0', sizeof callsign); + ao_xmemset(callsign, '\0', sizeof callsign); ao_cmd_white(); c = 0; while (ao_cmd_lex_c != '\n') { @@ -161,7 +161,7 @@ ao_config_callsign_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - memcpy(&ao_config.callsign, &callsign, + ao_xmemcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); _ao_config_edit_finish(); } @@ -535,7 +535,8 @@ ao_config_help(void) __reentrant for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) printf("%-20s %s\n", ao_config_vars[cmd].str, - ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); + ao_config_vars[cmd].str+1+ + strlen(ao_config_vars[cmd].str)); } static void diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c index b0c1d61e..7fcfcab0 100644 --- a/src/core/ao_ee_fake.c +++ b/src/core/ao_ee_fake.c @@ -32,6 +32,6 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant uint8_t ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant { - memset(buf, '\0', len); + ao_xmemset(buf, '\0', len); return 1; } diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c index e57f8744..c52ef621 100644 --- a/src/core/ao_gps_report.c +++ b/src/core/ao_gps_report.c @@ -27,7 +27,7 @@ ao_gps_report(void) for (;;) { ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); if (!(gps_data.flags & AO_GPS_VALID)) @@ -72,7 +72,7 @@ ao_gps_tracking_report(void) ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) diff --git a/src/core/ao_host.h b/src/core/ao_host.h index 65c25fe5..f2b2f0c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -125,3 +125,7 @@ struct ao_config { #define ao_config_get() struct ao_config ao_config = { 250, 16000 }; + +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 56d7604d..1a8bb52a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -94,7 +94,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_orig.rssi >> 1) - 74; - memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { @@ -171,7 +171,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 26e4e2a0..95e53917 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -131,10 +131,10 @@ ao_send_configuration(void) telemetry.configuration.apogee_delay = ao_config.apogee_delay; telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; - memcpy (telemetry.configuration.callsign, + ao_xmemcpy (telemetry.configuration.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, + ao_xmemcpy (telemetry.configuration.version, ao_version, AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); @@ -150,7 +150,7 @@ ao_send_location(void) { telemetry.generic.type = AO_TELEMETRY_LOCATION; ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.location.flags, + ao_xmemcpy(&telemetry.location.flags, &ao_gps_data.flags, 26); ao_mutex_put(&ao_gps_mutex); @@ -167,7 +167,7 @@ ao_send_satellite(void) telemetry.generic.type = AO_TELEMETRY_SATELLITE; ao_mutex_get(&ao_gps_mutex); telemetry.satellite.channels = ao_gps_tracking_data.channels; - memcpy(&telemetry.satellite.sats, + ao_xmemcpy(&telemetry.satellite.sats, &ao_gps_tracking_data.sats, AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); ao_mutex_put(&ao_gps_mutex); @@ -187,7 +187,7 @@ ao_send_companion(void) telemetry.companion.update_period = ao_companion_setup.update_period; telemetry.companion.channels = ao_companion_setup.channels; ao_mutex_get(&ao_companion_mutex); - memcpy(&telemetry.companion.companion_data, + ao_xmemcpy(&telemetry.companion.companion_data, ao_companion_data, ao_companion_setup.channels * 2); ao_mutex_put(&ao_companion_mutex); diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index 738f8ce6..2d047a44 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -167,7 +167,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_ee_flush_internal(); ao_ee_block = block; } - memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_xmemcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; @@ -181,7 +181,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { ao_ee_fill(block); - memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + ao_xmemcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); } ao_mutex_put(&ao_ee_mutex); return 1; } @@ -200,7 +200,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_ee_mutex); { ao_ee_flush_internal(); ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_xmemset(ao_ee_data, 0xff, EE_BLOCK_SIZE); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index aee9877a..6cd689e5 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -245,7 +245,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_flash_flush_internal(); ao_flash_block = block; } - memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + ao_xmemcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), buf, len); ao_flash_block_dirty = 1; @@ -261,7 +261,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(block); - memcpy(buf, + ao_xmemcpy(buf, ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), len); } ao_mutex_put(&ao_flash_mutex); @@ -282,7 +282,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_flash_mutex); { ao_flash_flush_internal(); ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); - memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_xmemset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; } ao_mutex_put(&ao_flash_mutex); return 1; diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 7ac26946..6e65d651 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -265,7 +265,7 @@ ao_nmea_gga() if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -327,7 +327,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..8f7c7429 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -41,6 +41,7 @@ CC1111_SRC = \ ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 56182b84..c1b422c0 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 5da42e46..b40f61a2 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_romconfig.c \ ao_serial.c \ ao_spi.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 2759ac52..4f4195a9 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -54,6 +54,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_spi.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 7f251897..9f90b01f 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index c47e95ff..eff3ea97 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -44,6 +44,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 56733c89..921d44e7 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -173,6 +173,10 @@ struct ao_cmds { const char *help; }; +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) + #include "ao_convert.c" struct ao_config { @@ -542,7 +546,7 @@ ao_sleep(void *wchan) ao_flight_started = 1; } } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { - char *hex = words[1]; + __xdata char *hex = words[1]; char elt[3]; int i, len; uint8_t sum; @@ -574,7 +578,7 @@ ao_sleep(void *wchan) continue; } if (len == 36) { - memcpy(&telem, bytes + 1, 32); + ao_xmemcpy(&telem, bytes + 1, 32); tick = telem.generic.tick; switch (telem.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 057e420b..58b9d735 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -38,6 +38,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c -- cgit v1.2.3 From f9b0b7423c0640f729d61a91de6ff96ffe4b486e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:43:37 -0600 Subject: altosui: Max acceleration across boost instead of all ascent This ignores ejection bumps, making the max acceleration far more useful. Signed-off-by: Keith Packard --- altosui/AltosFlightStatsTable.java | 2 +- altosui/AltosState.java | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java index 3fecf921..2d34c6e2 100644 --- a/altosui/AltosFlightStatsTable.java +++ b/altosui/AltosFlightStatsTable.java @@ -86,7 +86,7 @@ public class AltosFlightStatsTable extends JComponent { String.format("%5.0f ft/s", AltosConvert.meters_to_feet(stats.max_speed)), String.format("Mach %5.3f", AltosConvert.meters_to_mach(stats.max_speed))); if (stats.max_acceleration != AltosRecord.MISSING) { - new FlightStat(layout, y++, "Maximum acceleration", + new FlightStat(layout, y++, "Maximum boost acceleration", String.format("%5.0f m/s²", stats.max_acceleration), String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)), String.format("%5.2f G", AltosConvert.meters_to_g(stats.max_acceleration))); diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 072cb790..3d8e5e12 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -35,6 +35,7 @@ public class AltosState { int state; boolean landed; boolean ascent; /* going up? */ + boolean boost; /* under power */ double ground_altitude; double height; @@ -166,13 +167,14 @@ public class AltosState { ascent = (Altos.ao_flight_boost <= state && state <= Altos.ao_flight_coast); + boost = (Altos.ao_flight_boost == state); - /* Only look at accelerometer data on the way up */ - if (ascent && acceleration > max_acceleration) + /* Only look at accelerometer data under boost */ + if (boost && acceleration > max_acceleration) max_acceleration = acceleration; - if (ascent && speed > max_speed) + if (boost && speed > max_speed) max_speed = speed; - if (ascent && baro_speed > max_baro_speed) + if (boost && baro_speed > max_baro_speed) max_baro_speed = baro_speed; if (height > max_height) -- cgit v1.2.3 From cbf5a649c8b7101bef9d57e48e42ac775e758c79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:46:38 -0600 Subject: altosui: Allow for multiple instances of each state in the graph With the new boost re-detect code, we can get multiple instances of boost/fast/coast, so make sure each are displayed in the graph. Signed-off-by: Keith Packard --- altosui/AltosGraphTime.java | 31 +++++++++++++++++-------------- altosui/AltosGraphUI.java | 6 ++++-- 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java index ada6ef13..6a084b2c 100644 --- a/altosui/AltosGraphTime.java +++ b/altosui/AltosGraphTime.java @@ -4,6 +4,11 @@ package altosui; +import java.lang.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import java.text.*; import java.awt.Color; import java.util.ArrayList; import java.util.HashMap; @@ -98,9 +103,10 @@ class AltosGraphTime extends AltosGraph { } static class StateMarker implements Element { - private double val = Double.NaN; + private LinkedList times = new LinkedList(); private String name; private int state; + private int prev_state = Altos.ao_flight_startup; StateMarker(int state, String name) { this.state = state; @@ -109,22 +115,19 @@ class AltosGraphTime extends AltosGraph { public void attachGraph(AltosGraphTime g) { return; } public void gotTimeData(double time, AltosDataPoint d) { - if (Double.isNaN(val) || time < val) { - if (d.state() == state) { - val = time; - } - } + if (prev_state != state && d.state() == state) + times.add(time); + prev_state = d.state(); } public void addToPlot(AltosGraphTime g, XYPlot plot) { - if (Double.isNaN(val)) - return; - - ValueMarker m = new ValueMarker(val); - m.setLabel(name); - m.setLabelAnchor(RectangleAnchor.TOP_RIGHT); - m.setLabelTextAnchor(TextAnchor.TOP_LEFT); - plot.addDomainMarker(m); + for (double time : times) { + ValueMarker m = new ValueMarker(time); + m.setLabel(name); + m.setLabelAnchor(RectangleAnchor.TOP_RIGHT); + m.setLabelTextAnchor(TextAnchor.TOP_LEFT); + plot.addDomainMarker(m); + } } } diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index be52bd4e..030bbc25 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -109,6 +109,8 @@ public class AltosGraphUI extends JFrame protected AltosGraphTime myAltosGraphTime(String suffix) { return (new AltosGraphTime("Overall " + suffix)) .addElement(e_boost) + .addElement(e_fast) + .addElement(e_coast) .addElement(e_drogue) .addElement(e_main) .addElement(e_landed); @@ -238,8 +240,8 @@ public class AltosGraphUI extends JFrame { ArrayList graph = new ArrayList(); graph.addAll((new OverallGraphs()).graphs()); - graph.addAll((new AscentGraphs()).graphs()); - graph.addAll((new DescentGraphs()).graphs()); +// graph.addAll((new AscentGraphs()).graphs()); +// graph.addAll((new DescentGraphs()).graphs()); if (which > 0) { if (which >= graph.size()) { -- cgit v1.2.3 From 82604193ed0c522c1fba0072b504fe88b027f1ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:50:24 -0600 Subject: ao-telem: Add new program to convert telem data to ascii This reads telem files and displays them in ascii form. It's not done, and it's not documented, but it's a start. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-telem/Makefile.am | 12 +++ ao-tools/ao-telem/ao-telem.1 | 61 ++++++++++++++ ao-tools/ao-telem/ao-telem.c | 112 +++++++++++++++++++++++++ ao-tools/lib/Makefile.am | 2 + ao-tools/lib/cc-telemetry.c | 62 ++++++++++++++ ao-tools/lib/cc-telemetry.h | 188 ++++++++++++++++++++++++++++++++++++++++++ ao-tools/lib/cc.h | 1 + configure.ac | 1 + 9 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 ao-tools/ao-telem/Makefile.am create mode 100644 ao-tools/ao-telem/ao-telem.1 create mode 100644 ao-tools/ao-telem/ao-telem.c create mode 100644 ao-tools/lib/cc-telemetry.c create mode 100644 ao-tools/lib/cc-telemetry.h diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 8144be1c..611bb7dc 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem diff --git a/ao-tools/ao-telem/Makefile.am b/ao-tools/ao-telem/Makefile.am new file mode 100644 index 00000000..3436443e --- /dev/null +++ b/ao-tools/ao-telem/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-telem + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_telem_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) + +ao_telem_SOURCES = ao-telem.c + +man_MANS = ao-telem.1 diff --git a/ao-tools/ao-telem/ao-telem.1 b/ao-tools/ao-telem/ao-telem.1 new file mode 100644 index 00000000..8e6699d5 --- /dev/null +++ b/ao-tools/ao-telem/ao-telem.1 @@ -0,0 +1,61 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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-TELEM 1 "ao-telem" "" +.SH NAME +ao-telem \- Analyse a flight log (either telemetry or eeprom) +.SH SYNOPSIS +.B "ao-telem" +[\-s ] +[\--summary=] +[\-d ] +[\--detail=] +[\-r ] +[\--raw=] +[\-p ] +[\--plot=] +[\-g + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cc.h" + +static const struct option options[] = { + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s\n" + "\t{flight-log} ...\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char line[80]; + int c, i, ret; + char *s; + FILE *file; + int serial; + while ((c = getopt_long(argc, argv, "", options, NULL)) != -1) { + switch (c) { + default: + usage(argv[0]); + break; + } + } + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + perror(argv[i]); + ret++; + continue; + } + s = strstr(argv[i], "-serial-"); + if (s) + serial = atoi(s + 8); + else + serial = 0; + while (fgets(line, sizeof (line), file)) { + union ao_telemetry_all telem; + char call[AO_MAX_CALLSIGN+1]; + char version[AO_MAX_VERSION+1]; + + if (cc_telemetry_parse(line, &telem)) { + printf ("serial %5d tick %5d type %3d ", + telem.generic.serial, telem.generic.tick, telem.generic.type); + switch (telem.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + printf ("state %1d accel %5d pres %5d ", + telem.sensor.state, telem.sensor.accel, telem.sensor.pres); + printf ("accel %5d speed %5d height %5d ", + telem.sensor.acceleration, + telem.sensor.speed, + telem.sensor.height); + printf ("ground_pres %5d ground_accel %5d accel_plus %5d accel_minus %5d\n", + telem.sensor.ground_pres, + telem.sensor.ground_accel, + telem.sensor.accel_plus_g, + telem.sensor.accel_minus_g); + break; + case AO_TELEMETRY_CONFIGURATION: + memcpy(call, telem.configuration.callsign, AO_MAX_CALLSIGN); + memcpy(version, telem.configuration.version, AO_MAX_VERSION); + call[AO_MAX_CALLSIGN] = '\0'; + version[AO_MAX_CALLSIGN] = '\0'; + printf ("device %3d flight %5d config %3d.%03d delay %2d main %4d", + telem.configuration.device, + telem.configuration.flight, + telem.configuration.config_major, + telem.configuration.config_minor, + telem.configuration.apogee_delay, + telem.configuration.main_deploy, + telem.configuration.flight_log_max); + printf (" call %8s version %8s\n", call, version); + break; + default: + printf("\n"); + } + } + } + fclose (file); + + } + return ret; +} diff --git a/ao-tools/lib/Makefile.am b/ao-tools/lib/Makefile.am index da355db5..1f8f2e42 100644 --- a/ao-tools/lib/Makefile.am +++ b/ao-tools/lib/Makefile.am @@ -32,6 +32,8 @@ libao_tools_a_SOURCES = \ cc-bitbang.h \ cc-logfile.c \ cc-telem.c \ + cc-telemetry.c \ + cc-telemetry.h \ cp-usb-async.c \ cp-usb-async.h \ i0.c \ diff --git a/ao-tools/lib/cc-telemetry.c b/ao-tools/lib/cc-telemetry.c new file mode 100644 index 00000000..2cdb9cac --- /dev/null +++ b/ao-tools/lib/cc-telemetry.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 "cc.h" +#include + +static int +parse_byte(char *data, uint8_t *byte) +{ + char d[3]; + int x; + d[0] = data[0]; + d[1] = data[1]; + d[2] = '\0'; + + if (sscanf(d, "%x", &x) != 1) + return FALSE; + *byte = x; + return TRUE; +} + +int +cc_telemetry_parse(const char *input_line, union ao_telemetry_all *telemetry) +{ + uint8_t *byte; + char *data; + uint8_t hex[35]; + int i; + + if (strncmp(input_line, "TELEM", 5) != 0) + return FALSE; + + data = strchr (input_line, ' '); + if (!data) + return FALSE; + data++; + byte = hex; + for (i = 0; i < 35; i++) { + if (!parse_byte(data, byte)) + return FALSE; + data += 2; + byte++; + } + if (hex[0] != 34) + return FALSE; + memcpy(telemetry, hex+1, 32); + return TRUE; +} diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h new file mode 100644 index 00000000..5a66b971 --- /dev/null +++ b/ao-tools/lib/cc-telemetry.h @@ -0,0 +1,188 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _CC_TELEMETRY_H_ +#define _CC_TELEMETRY_H_ +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; + struct ao_telemetry_baro baro; +}; + +int +cc_telemetry_parse(const char *input_line, union ao_telemetry_all *telemetry); + +#endif diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index ede46aa0..6257ee44 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -20,6 +20,7 @@ #include #include +#include "cc-telemetry.h" char * cc_fullname (char *dir, char *file); diff --git a/configure.ac b/configure.ac index 9f1921b9..1a2cc813 100644 --- a/configure.ac +++ b/configure.ac @@ -122,6 +122,7 @@ ao-tools/ao-bitbang/Makefile ao-tools/ao-eeprom/Makefile ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile +ao-tools/ao-telem/Makefile ao-utils/Makefile src/Version ]) -- cgit v1.2.3 From 6a7363b3ba99310bd44c9b66f6f5159e46762be4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:51:05 -0600 Subject: altos: Ignore ejection bumps when doing boost re-detect An ejection charge looks an awful lot like an extra (really small) motor burn. Ignore them by averaging the acceleration during fast/coast using a /64 exponential decay filter. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 433efeae..5e194638 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,11 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ * track min/max data over a long interval to detect * resting */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + __pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in @@ -197,6 +199,7 @@ ao_flight(void) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; #endif @@ -250,7 +253,8 @@ ao_flight(void) #if HAS_ACCEL else { check_re_boost: - if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { ao_boost_tick = ao_sample_tick; ao_flight_state = ao_flight_boost; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From aad03e3cab4c328e53d3df47b6dac1d3f7a49229 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 16:07:57 -0600 Subject: altosui: Remove igniter voltages from chart. These are just annoying; when we add the ability to turn stuff on/off on the fly, we can add them to the list of available items. Signed-off-by: Keith Packard --- altosui/AltosGraphUI.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 030bbc25..59e92499 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -122,9 +122,7 @@ public class AltosGraphUI extends JFrame graphs.add( myAltosGraphTime("Summary") .addElement(height) .addElement(speed) - .addElement(acceleration) - .addElement(drogue_voltage) - .addElement(main_voltage) ); + .addElement(acceleration) ); graphs.add( myAltosGraphTime("Summary") .addElement(height) -- cgit v1.2.3 From 26d7eb7149da8c797d7e704d75f73af2d2aa52c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 21:31:34 -0600 Subject: Bump to 1.0.9.2 (1.1 RC 2). Flown at Oktoberfest 2011 on 10/09/2011 (we hope) Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1a2cc813..57d2f196 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.1) +AC_INIT([altos], 1.0.9.2) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From ca036c5616c3e745c0b878ed90618d4ff710c0e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 22:19:52 -0600 Subject: altos: Improve TM v1.0 apogee estimate v1.0 boards have noisy accelerometer data caused by interactions between RF transmission and the accelerometer measurements; this noise generates a negative bias in the accelerometer readings. The net effect is that the estimated speed is lower than the actual speed, causing early an apogee estimate. By increasing the sigma value for accelerometer data, the kalman filter 'trusts' the acceleration data less, putting more weight on the barometer data. This causes the estimated time of apogee to be closer to the correct value. This reduces the response to changes in acceleration. This new value is applied solely to TeleMetrum v1.0 boards. v1.1 boards correct for this error, and hence can use the correct sigma value for the accelerometer. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/test/Makefile | 12 ++++++++++-- src/util/make-kalman | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 723f1500..d2fbb209 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -36,6 +36,7 @@ #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define NOISY_ACCEL 1 #define HAS_COMPANION 1 #define COMPANION_CS_ON_P1 1 diff --git a/src/test/Makefile b/src/test/Makefile index 333850e4..4e403da6 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,8 @@ -vpath % ..:../core:../drivers +vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test + +KALMAN=make-kalman CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g @@ -14,6 +16,9 @@ install: ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h + cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< + ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c @@ -28,3 +33,6 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc $(CFLAGS) -o $@ $< + +ao_kalman.h: $(KALMAN) + (cd .. && make ao_kalman.h) \ No newline at end of file diff --git a/src/util/make-kalman b/src/util/make-kalman index 397d6020..fd33bab0 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -5,11 +5,32 @@ cd $1 2> /dev/null 1>&2 SIGMA_BOTH="-M 2 -H 6 -A 2" SIGMA_BARO="-M 2 -H 6 -A 2" SIGMA_ACCEL="-M 2 -H 4 -A 4" +SIGMA_BOTH_NOISY_ACCEL="-M 2 -H 6 -A 3" + +echo '#if NOISY_ACCEL' +echo +echo '/* TeleMetrum v1.0 boards have noisy accelerometer values' +echo ' * increase the sigma value for accel data to compensate.' +echo ' * This improves the accuracy of apogee detection.' +echo ' */' +echo + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH_NOISY_ACCEL +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH_NOISY_ACCEL +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH_NOISY_ACCEL + +echo '#endif' +echo +echo '#ifndef AO_BOTH_K00_100' +echo nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH +echo '#endif' +echo + nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL @@ -17,3 +38,4 @@ nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO + -- cgit v1.2.3 From 636b7b368e67346b0796cd84fbfd71e10966d61f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Oct 2011 10:21:56 -0600 Subject: altos: Respond to telemetry rate changes immediately Instead of waiting for the previous telemetry interval to expire, immediately switch to the new telemetry rate. This will provide more telemetry data early in the boost. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 95e53917..d909bea5 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -240,8 +240,11 @@ ao_telemetry(void) #endif time += ao_telemetry_interval; delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); + if (delay > 0) { + ao_alarm(delay); + ao_sleep(&telemetry); + ao_clear_alarm(); + } else time = ao_time(); } -- cgit v1.2.3 From 5c82b07471f017171c58a6968adf79901f46a987 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Oct 2011 10:55:04 -0600 Subject: altosui: Deal with telem data that goes backwards in time The new telemetry stuff can send packets with older timestamps, so sort telem packets read from disk to create an in-order record of the flight. Signed-off-by: Keith Packard --- altosui/AltosRecord.java | 6 +++++- altosui/AltosTelemetryIterable.java | 8 ++++---- altosui/AltosTelemetryRecordRaw.java | 6 ++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index ce6d86ab..486c96b2 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -22,7 +22,7 @@ import java.text.*; import java.util.HashMap; import java.io.*; -public class AltosRecord { +public class AltosRecord implements Comparable { final static int MISSING = 0x7fffffff; static final int seen_flight = 1; @@ -243,6 +243,10 @@ public class AltosRecord { return null; } + public int compareTo(AltosRecord o) { + return tick - o.tick; + } + public AltosRecord(AltosRecord old) { version = old.version; seen = old.seen; diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index 1a31b365..278cbfb7 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -22,7 +22,7 @@ import java.util.*; import java.text.*; public class AltosTelemetryIterable extends AltosRecordIterable { - LinkedList records; + TreeSet records; public Iterator iterator () { return records.iterator(); @@ -41,7 +41,7 @@ public class AltosTelemetryIterable extends AltosRecordIterable { int boost_tick = 0; AltosRecord previous = null; - records = new LinkedList (); + records = new TreeSet (); try { for (;;) { @@ -56,8 +56,8 @@ public class AltosTelemetryIterable extends AltosRecordIterable { if (records.isEmpty()) { current_tick = record.tick; } else { - int tick = record.tick | (current_tick & ~ 0xffff); - if (tick < current_tick - 0x1000) + int tick = record.tick; + while (tick < current_tick - 0x1000) tick += 0x10000; current_tick = tick; record.tick = current_tick; diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index 39b2ba07..fb2b495c 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -143,11 +143,9 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { public AltosRecord update_state(AltosRecord previous) { AltosRecord next; - if (previous != null) { + if (previous != null) next = new AltosRecord(previous); - while (tick < previous.tick) - tick += 65536; - } else + else next = new AltosRecord(); next.serial = serial; next.tick = tick; -- cgit v1.2.3 From 5d1361c95f94125cda244b4cc5e55c2fb77b680b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Oct 2011 11:09:25 -0600 Subject: altosui: Deal with missing state transitions in FlightStats window Any missing start/end times are pinned to the end of the flight. Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index 2067951e..72d12600 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -47,7 +47,7 @@ public class AltosFlightStats { AltosState state = null; AltosState new_state = null; double boost_time = -1; - double start_time; + double end_time = 0; year = month = day = -1; hour = minute = second = -1; @@ -62,9 +62,7 @@ public class AltosFlightStats { if ((record.seen & AltosRecord.seen_flight) != 0 && flight < 0) flight = record.flight; new_state = new AltosState(record, state); - if (state == null) { - start_time = new_state.time; - } + end_time = new_state.time; state = new_state; if (0 <= state.state && state.state < Altos.ao_flight_invalid) { if (state.state >= Altos.ao_flight_boost) { @@ -107,6 +105,10 @@ public class AltosFlightStats { state_baro_speed[s] /= state_count[s]; state_accel[s] /= state_count[s]; } + if (state_start[s] == 0) + state_start[s] = end_time; + if (state_end[s] == 0) + state_end[s] = end_time; } } -- cgit v1.2.3 From 06b044629951b06c7ec9b0105b89f51b2880ebd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 16:03:04 -0600 Subject: altos/avr: SPI mutex is now held by the caller, not the SPI driver SPI transactions generally require a read followed by a write, with the chip select held the whole time. As a result, the SPI bus must be held across multiple transactions. To make this reliable, the caller must hold the SPI mutex, instead of the underlying SPI driver. Signed-off-by: Keith Packard --- src/avr/ao_spi_usart.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 6ed708ff..1996fcd9 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -33,14 +33,12 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; - ao_mutex_get(&ao_spi_mutex); while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = *d++; while (!(UCSR1A & (1 << RXC1))); (void) UDR1; } - ao_mutex_put(&ao_spi_mutex); } /* Receive bytes over SPI. @@ -54,14 +52,12 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; - ao_mutex_get(&ao_spi_mutex); while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = 0; while (!(UCSR1A & (1 << RXC1))); *d++ = UDR1; } - ao_mutex_put(&ao_spi_mutex); } /* -- cgit v1.2.3 From f3453068b0feb640b9d11dbeb021c535ce8b4a31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:39:06 -0600 Subject: altos/avr: Print newline after dumping ADC values Cleans up the formating a bit. Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 8c0cade0..4f6f0e60 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -138,6 +138,7 @@ ao_adc_dump(void) __reentrant printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); + printf("\n"); #ifdef TELEPYRO -- cgit v1.2.3 From 0a186e92c5773c5d908e9cee889d645a8172dcdc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:39:35 -0600 Subject: altos/avr: Make ao_arch_critical argument be a statement Wrap the argument to ao_arch_critical in do { } while (0); to make sure it gets correctly checked as a statement. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c695a725..2be4abee 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -143,7 +143,7 @@ extern uint8_t ao_cpu_sleep_disable; asm("ret"); \ } while(0) -#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) #define AO_TELESCIENCE_NUM_ADC 12 -- cgit v1.2.3 From 3bda859caf1501f8408703dca81412d70ba00e04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:42:24 -0600 Subject: altos/avr: telescience does not have a serial port The USART is used for SPI to talk to the flash part. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 6b72530b..ddd37a7b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -37,12 +37,12 @@ #define HAS_USB 1 #define HAS_LOG 1 #define TEENSY 0 - #define USE_SERIAL_STDIN 1 - #define HAS_SERIAL_1 1 - #define HAS_USB 1 + #define USE_SERIAL_STDIN 0 + #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_STORAGE_DEBUG 1 #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 -- cgit v1.2.3 From af4470f8025116179ef83726a8287e47c465907b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:44:02 -0600 Subject: altos/avr: Register stdio handler when using serial for stdin This code was left in a bit of a mess; just clean it up. Signed-off-by: Keith Packard --- src/avr/ao_serial_avr.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index 2fe39755..6885c339 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -154,13 +154,9 @@ ao_serial_init(void) (1 << TXEN1) | /* Enable transmitter */ (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ -#if 0 #if USE_SERIAL_STDIN - int8_t i; - i = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); - printf("Register serial stdio as %d\n", i); -#endif + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); #endif } -- cgit v1.2.3 From e60c470b426b7be08a33133e7d8c94201d7e96d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:44:40 -0600 Subject: altos/avr: Pull-up on the SPI slave select pin This makes the board work even when disconnected from TeleMetrum. Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 76f574c6..3aa0b97f 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -87,7 +87,7 @@ ao_spi_slave_init(void) (1 << 3) | /* MISO, output */ (0 << 2) | /* MOSI, no pull-up */ (0 << 1) | /* SCK, no pull-up */ - (0 << 0)); /* SS, no pull-up */ + (1 << 0)); /* SS, pull-up */ #endif #if SPI_SLAVE_PIN_2_5 PCMSK0 |= (1 << PCINT2); /* Enable PCINT2 pin change */ @@ -103,7 +103,7 @@ ao_spi_slave_init(void) (0 << 5) | /* SCK, no pull-up */ (1 << 4) | /* MISO, output */ (0 << 3) | /* MOSI, no pull-up */ - (0 << 2)); /* SS, no pull-up */ + (1 << 2)); /* SS, pull-up */ #endif SPCR = (0 << SPIE) | /* Disable SPI interrupts */ -- cgit v1.2.3 From 3a28846d3ff8f82b0e97c211b9debf6d67ee5af5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:10:45 -0600 Subject: altos/avr: Clear SPI receive buffer before clocking new data in I don't know why this is necessary, but the receive buffer gets 'extra' data added somehow. Signed-off-by: Keith Packard --- src/avr/ao_spi_usart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 1996fcd9..5ea11da6 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -43,15 +43,17 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant /* Receive bytes over SPI. * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. + * Poll, sending zeros and reading data back */ void ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; + /* Clear any pending data */ + while (UCSR1A & (1 << RXC1)) + (void) UDR1; + while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = 0; -- cgit v1.2.3 From ac0bebc44bc657b303db4c41fa0c9624f3df9f4f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:11:56 -0600 Subject: altos: Make HAS_STORAGE_DEBUG define consistent This allows products to include the 'w' command for testing flash writing as needed. Signed-off-by: Keith Packard --- src/core/ao_storage.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 6ffca0e5..ff4747d0 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -103,7 +103,7 @@ ao_storage_dump(void) __reentrant } } -#if 0 +#if HAS_STORAGE_DEBUG /* not enough space for this today */ @@ -160,6 +160,7 @@ ao_storage_zapall(void) __reentrant void ao_storage_info(void) __reentrant { + ao_storage_setup(); printf("Storage size: %ld\n", ao_storage_total); printf("Storage erase unit: %ld\n", ao_storage_block); ao_storage_device_info(); @@ -168,7 +169,7 @@ ao_storage_info(void) __reentrant __code struct ao_cmds ao_storage_cmds[] = { { ao_storage_info, "f\0Show storage" }, { ao_storage_dump, "e \0Dump flash" }, -#ifdef HAS_STORAGE_DBG +#if HAS_STORAGE_DEBUG { ao_storage_store, "w ...\0Write data to flash" }, #endif { ao_storage_zap, "z \0Erase " }, -- cgit v1.2.3 From cb837d9bb9e6736fcdfca7692b1f9490ea090838 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:13:00 -0600 Subject: altos: Allow ao_science_slave to not log data This is mostly for debugging with flash writes disabled. Signed-off-by: Keith Packard --- src/drivers/ao_science_slave.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index e902318f..78941255 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -49,6 +49,7 @@ void ao_spi_slave(void) return; } +#if HAS_LOG ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; @@ -59,4 +60,5 @@ void ao_spi_slave(void) ao_log_single_stop(); } } +#endif } -- cgit v1.2.3 From f1573a752425121d4c6a14285f1eb0fef3a8bea5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:44:48 -0600 Subject: altos/avr: Shrink default stack size to use less ram Not that we have any way of knowing how much stack we're using, but at least this seems to work. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 2be4abee..c189ccba 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -37,7 +37,7 @@ * AVR definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 128 +#define AO_STACK_SIZE 116 /* Various definitions to make GCC look more like SDCC */ -- cgit v1.2.3 From b80f8ffb61566cbd134c399ea6ccf9290075490b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:45:51 -0600 Subject: altos/avr: Must leave space for init stack in ram The stack used during system initialization lives at the top of RAM, so leave some space for that. Signed-off-by: Keith Packard --- src/util/check-avr-mem | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem index c73edbd1..7956f0aa 100644 --- a/src/util/check-avr-mem +++ b/src/util/check-avr-mem @@ -2,8 +2,10 @@ nm "$@" | grep ' N _end' | awk '{ iram = strtonum("0x" $1) % 0x10000; -if ( iram > 0xaff) { - printf ("%d bytes of ram more than %d available\n", iram, 0xaff); +if ( iram > 0xacf) { + printf ("%d bytes of ram more than %d available\n", iram, 0xacf); exit(1); -} else - exit(0); }' +} else { + printf("%d bytes of ram\n", iram); + exit(0); +} }' -- cgit v1.2.3 From 75960500d1f290fa9f82183431443ac122f12c19 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:48:11 -0600 Subject: altos/avr: telescience doesn't have room for the flash write code This is useful for debugging the SPI and flash drivers, but not necessary in production code. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index ddd37a7b..bf02db1b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -42,7 +42,7 @@ #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 - #define HAS_STORAGE_DEBUG 1 + #define HAS_STORAGE_DEBUG 0 #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 -- cgit v1.2.3 From 652c024ed37bfed5de17f45c772796d5cbe4599f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:48:55 -0600 Subject: altos/telescience: Add more header dependencies Signed-off-by: Keith Packard --- src/telescience-v0.1/Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index a6797cbe..be99f10d 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -20,9 +20,9 @@ endif INC = \ ao.h \ + ao_arch.h \ ao_usb.h \ - ao_pins.h \ - altitude.h + ao_pins.h # # Common AltOS sources @@ -30,7 +30,11 @@ INC = \ TELESCIENCE_STORAGE= \ ao_m25.c \ ao_spi_usart.c \ - ao_storage.c \ + ao_storage.c + +TELESCIENCE_LOG= \ + ao_log_single.c \ + ao_log_telescience.c ALTOS_SRC = \ ao_clock.c \ @@ -48,9 +52,8 @@ ALTOS_SRC = \ ao_adc_avr.c \ ao_science_slave.c \ ao_spi_slave.c \ - ao_log_single.c \ - ao_log_telescience.c \ - $(TELESCIENCE_STORAGE) + $(TELESCIENCE_STORAGE)\ + $(TELESCIENCE_LOG) PRODUCT=TeleScience-v0.1 MCU=atmega32u4 @@ -90,9 +93,6 @@ $(PROG).hex: $(PROG) load: $(PROG).hex $(LOADCMD) $(LOADARG)$(PROG).hex -../altitude.h: make-altitude - nickle $< > $@ - ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ @@ -109,4 +109,4 @@ install: uninstall: -$(OBJ): ao.h ao_product.h ao_usb.h +$(OBJ): ao_product.h $(INC) -- cgit v1.2.3 From 47c2c0b79dc516d2566ae149605b7d70ef2dca98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 20:58:04 -0600 Subject: Bump to 1.0.9.3 TeleScience and TelePyro now work. Signed-off-by: Keith Packard --- configure.ac | 2 +- src/avr/ao_spi_slave.c | 4 ++-- src/avr/ao_usb_avr.c | 3 --- src/core/ao.h | 4 ++-- src/drivers/ao_pyro_slave.c | 12 ++++++------ src/drivers/ao_science_slave.c | 12 ++++++------ 6 files changed, 17 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index 57d2f196..19db6d27 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.2) +AC_INIT([altos], 1.0.9.3) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 3aa0b97f..b742d29a 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -18,7 +18,7 @@ #include "ao.h" uint8_t -ao_spi_read(uint8_t *buf, uint8_t len) +ao_spi_slave_recv(uint8_t *buf, uint8_t len) { while (len--) { while (!(SPSR & (1 << SPIF))) @@ -30,7 +30,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) } void -ao_spi_write(uint8_t *buf, uint8_t len) +ao_spi_slave_send(uint8_t *buf, uint8_t len) { while (len--) { SPDR = *buf++; diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 74bdea23..fc8899d8 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -303,9 +303,6 @@ ao_usb_ep0_setup(void) } break; case AO_USB_RECIP_INTERFACE: -#ifndef AVR - #pragma disable_warning 110 -#endif debug ("Interface setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: diff --git a/src/core/ao.h b/src/core/ao.h index c0474729..94526bc3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -975,10 +975,10 @@ ao_spi_init(void); */ uint8_t -ao_spi_read(uint8_t *buf, uint8_t len); +ao_spi_slave_recv(uint8_t *buf, uint8_t len); void -ao_spi_write(uint8_t *buf, uint8_t len); +ao_spi_slave_send(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index e6c73a3c..5ef42b5a 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telepyro_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telepyro_setup, - sizeof (ao_telepyro_setup)); + ao_spi_slave_send((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 78941255..1ebb1480 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telescience_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); + ao_spi_slave_send((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; -- cgit v1.2.3 From badda0d910c56135401dce9adc9e6abebdba2ad7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:28:02 -0600 Subject: altos: Split out arch-specific bits of LCD driver The arch-specific section just puts a single nibble to the device. Signed-off-by: Keith Packard --- src/avr/ao_lcd_port.c | 74 ++++++++++++++++++++++++ src/cc1111/ao_lcd_port.c | 41 ++++++++++++++ src/cc1111/ao_packet.c | 4 ++ src/core/ao.h | 28 ++++++++++ src/core/ao_monitor.c | 13 ++++- src/drivers/ao_lcd.c | 142 ++++++++++------------------------------------- 6 files changed, 186 insertions(+), 116 deletions(-) create mode 100644 src/avr/ao_lcd_port.c create mode 100644 src/cc1111/ao_lcd_port.c diff --git a/src/avr/ao_lcd_port.c b/src/avr/ao_lcd_port.c new file mode 100644 index 00000000..b1e8aa17 --- /dev/null +++ b/src/avr/ao_lcd_port.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +static void +ao_lcd_port_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_port_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_port_set_bits(data); + return n; +} + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + ao_lcd_port_set_bits(data); +} + +void +ao_lcd_port_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; +} diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c new file mode 100644 index 00000000..324cc3d3 --- /dev/null +++ b/src/cc1111/ao_lcd_port.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) +{ + P0 = (P0 & 0xf0) | (nibble & 0x0f); + P1_1 = rs; + P1_0 = 1; + ao_delay(1); + P1_0 = 0; + ao_delay(1); +} + +void +ao_lcd_port_init(void) +{ + /* LCD_E and LCD_RS are GPIO outputs */ + P1DIR |= 0x03; + P1SEL &= ~0x03; + + /* LCD D4-D7 are GPIO outputs */ + P0DIR |= 0x0f; + P0SEL &= ~0x0f; +} diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index 37ba92e0..f502d67c 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -32,7 +32,9 @@ __xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) { +#ifdef AO_LED_RED ao_led_on(AO_LED_RED); +#endif /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -42,7 +44,9 @@ ao_packet_send(void) ao_wakeup(&tx_data); } ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED ao_led_off(AO_LED_RED); +#endif } uint8_t diff --git a/src/core/ao.h b/src/core/ao.h index 94526bc3..c800f1fc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1667,9 +1667,37 @@ ao_companion_init(void); /* ao_lcd.c */ +void +ao_lcd_putchar(uint8_t data); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + void ao_lcd_init(void); +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); + +void +ao_lcd_port_init(void); + /* ao_aes.c */ __xdata uint8_t ao_aes_mutex; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 1a8bb52a..5a6f61dd 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,6 +22,10 @@ #error Must define HAS_MONITOR to 1 #endif +#ifndef LEGACY_MONITOR +#error Must define LEGACY_MONITOR +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -39,12 +43,14 @@ ao_monitor_get(void) case 0: ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; +#if LEGACY_MONITOR case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; case AO_MONITORING_TINY: size = sizeof (struct ao_telemetry_tiny_recv); break; +#endif default: if (ao_monitoring > AO_MAX_TELEMETRY) ao_monitoring = AO_MAX_TELEMETRY; @@ -70,12 +76,13 @@ ao_monitor_blink(void) void ao_monitor_put(void) { +#if LEGACY_MONITOR __xdata char callsign[AO_MAX_CALLSIGN+1]; - + int16_t rssi; +#endif uint8_t ao_monitor_tail; uint8_t state; uint8_t sum, byte; - int16_t rssi; __xdata union ao_monitor *m; #define recv_raw ((m->raw)) @@ -89,6 +96,7 @@ ao_monitor_put(void) m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { +#if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -231,6 +239,7 @@ ao_monitor_put(void) printf("CRC INVALID RSSI %3d\n", rssi); } break; +#endif /* LEGACY_MONITOR */ default: printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 5bc89bbd..e62247ae 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -17,100 +17,9 @@ #include "ao.h" -#define LCD_PORT PORTB -#define LCD_DDR DDRB - -#define PIN_RS 4 -#define PIN_E 5 -#define PIN_RW 6 - -void -ao_lcd_set_bits(uint8_t bits) -{ -#if 0 - printf("\tLCD data %x RS %d R/W %d E %d\n", - bits & 0xf, - (bits & (1 << PIN_RS)) ? 1 : 0, - (bits & (1 << PIN_RW)) ? 1 : 0, - (bits & (1 << PIN_E)) ? 1 : 0); -#endif - LCD_PORT = bits; -#if 0 - ao_delay(1); - if (bits & (1 << PIN_RW)) - printf("\tLCD input %x\n", PINB); -#endif -} - -uint8_t -ao_lcd_get_nibble(uint8_t rs) -{ - uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); - uint8_t n; - - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - n = PINB & 0xf; - ao_lcd_set_bits(data); - return n; -} - -uint8_t -ao_lcd_get_status(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(0); - low = ao_lcd_get_nibble(0); - data = (high << 4) | low; - printf ("\tLCD status %02x\n", data); - return data; -} - -uint8_t -ao_lcd_get_data(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(1); - low = ao_lcd_get_nibble(1); - data = (high << 4) | low; - printf ("\tLCD data %02x\n", data); - return data; -} - -void -ao_lcd_wait_idle(void) -{ - uint8_t status; - uint8_t count = 0; - - do { - status = ao_lcd_get_status(); - count++; - if (count > 100) { - printf("idle timeout\n"); - break; - } - } while (0); /* status & 0x80); */ -} - -void -ao_lcd_send_nibble(uint8_t rs, uint8_t data) -{ - data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); - DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - ao_lcd_set_bits(data); -} - static uint16_t ao_lcd_time = 3; -void +static void ao_lcd_delay(void) { volatile uint16_t count; @@ -119,34 +28,34 @@ ao_lcd_delay(void) ; } -void -ao_lcd_send_ins(uint8_t data) +static void +ao_lcd_send_ins(uint8_t ins) { -// printf("send ins %02x\n", data); +// printf("send ins %02x\n", ins); // ao_lcd_wait_idle(); // ao_delay(1); ao_lcd_delay(); - ao_lcd_send_nibble(0, data >> 4); - ao_lcd_send_nibble(0, data & 0xf); + ao_lcd_port_put_nibble(0, ins >> 4); + ao_lcd_port_put_nibble(0, ins & 0xf); } void -ao_lcd_send_data(uint8_t data) +ao_lcd_put_byte(uint8_t c) { -// printf ("send data %02x\n", data); +// printf ("send data %02x\n", c); // ao_lcd_wait_idle(); ao_lcd_delay(); - ao_lcd_send_nibble(1, data >> 4); - ao_lcd_send_nibble(1, data & 0x0f); + ao_lcd_port_put_nibble(1, c >> 4); + ao_lcd_port_put_nibble(1, c & 0x0f); } void -ao_lcd_send_string(char *string) +ao_lcd_putstring(char *string) { - uint8_t c; + char c; while ((c = (uint8_t) *string++)) - ao_lcd_send_data(c); + ao_lcd_put_byte((uint8_t) c); } #define AO_LCD_POWER_CONTROL 0x54 @@ -167,14 +76,21 @@ ao_lcd_clear(void) ao_lcd_send_ins(0x04 | 0x02); } +void +ao_lcd_goto(uint8_t addr) +{ + ao_lcd_send_ins(0x80 | addr); + ao_lcd_send_ins(0x04 | 0x02); +} + void ao_lcd_start(void) { /* get to 4bit mode */ - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x2); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x2); /* function set */ ao_lcd_send_ins(0x28); @@ -199,7 +115,6 @@ ao_lcd_start(void) /* Clear */ ao_lcd_clear(); - } void @@ -229,7 +144,7 @@ void ao_lcd_string(void) { uint8_t col = 0; - uint8_t c; + char c; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) @@ -244,12 +159,12 @@ ao_lcd_string(void) ao_cmd_lex(); c |= ao_cmd_hex_nibble(); } - ao_lcd_send_data(c); + ao_lcd_put_byte(c); ao_cmd_lex(); col++; } while (col < 16) { - ao_lcd_send_data(' '); + ao_lcd_put_byte(' '); col++; } } @@ -275,7 +190,6 @@ __code struct ao_cmds ao_lcd_cmds[] = { void ao_lcd_init(void) { - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - PORTB = 0; + ao_lcd_port_init(); ao_cmd_register(&ao_lcd_cmds[0]); } -- cgit v1.2.3 From 65873a3ad1d8e8b5ec002be2576c6f496543306a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:29:24 -0600 Subject: altos: oops -- forgot to add the cc1111 string code This is required for all cc1111 builds now; it provides xdata string functions. Signed-off-by: Keith Packard --- src/cc1111/ao_string.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/cc1111/ao_string.c diff --git a/src/cc1111/ao_string.c b/src/cc1111/ao_string.c new file mode 100644 index 00000000..daa5c14b --- /dev/null +++ b/src/cc1111/ao_string.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +void +_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count) +{ + while (count--) + *dst++ = *src++; +} + +void +_ao_xmemset(__xdata uint8_t *dst, uint8_t v, uint8_t count) +{ + while (count--) + *dst++ = v; +} + +int8_t +_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count) +{ + while (count--) { + int8_t d = *a++ - *b++; + if (d) + return d; + } + return 0; +} -- cgit v1.2.3 From 0debe7ffc2aab2b4d08f42e488cb783ae91c36ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:30:53 -0600 Subject: altos: Add TeleTerra v0.2 product This includes most of the necessary drivers. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 36 +++++++ src/teleterra-v0.2/Makefile | 104 ++++++++++++++++++++ src/teleterra-v0.2/ao_pins.h | 214 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 src/product/ao_teleterra_0_2.c create mode 100644 src/teleterra-v0.2/Makefile create mode 100644 src/teleterra-v0.2/ao_pins.h diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c new file mode 100644 index 00000000..a6c10158 --- /dev/null +++ b/src/product/ao_teleterra_0_2.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define AO_NO_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + ao_timer_init(); + ao_beep_init(); + ao_cmd_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_monitor_init(0, TRUE); + ao_radio_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile new file mode 100644 index 00000000..892c37e2 --- /dev/null +++ b/src/teleterra-v0.2/Makefile @@ -0,0 +1,104 @@ +# +# TeleTerra build file +# + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_monitor.c \ + ao_log_single.c \ + ao_log_telem.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c + +CC1111_SRC = \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + ao_lcd_port.c \ + _bp.c + +DRIVER_SRC = \ + ao_m25.c \ + ao_lcd.c \ + ao_gps_skytraq.c + +PRODUCT_SRC = \ + ao_teleterra_0_2.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +TELETERRA_VER=0.2 +TELETERRA_DEF=0_2 +PROG = teleterra-v$(TELETERRA_VER)-$(VERSION).ihx +PRODUCT=TeleTerra-v$(TELETERRA_VER) +PRODUCT_DEF=-DTELETERRA_V_$(TELETERRA_DEF) +IDPRODUCT=0x000d + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h new file mode 100644 index 00000000..671d3876 --- /dev/null +++ b/src/teleterra-v0.2/ao_pins.h @@ -0,0 +1,214 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef TELETERRA_V_0_2 + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 0 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + + #define HAS_COMPANION 0 + + #define LEDS_AVAILABLE 0 + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 + #define LEGACY_MONITOR 0 + #define HAS_RSSI 0 + #define HAS_AES 0 + + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 + #define M25_MAX_CHIPS 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From aef732fc9cdf527a18f2959d6fb7903e832209da Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Oct 2011 22:54:02 -0700 Subject: ao-bringup: Make it build with source restructuring Source code all moved around, need to find the header files in new directories.x Signed-off-by: Keith Packard --- ao-bringup/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ao-bringup/Makefile b/ao-bringup/Makefile index cacbc161..7fdde985 100644 --- a/ao-bringup/Makefile +++ b/ao-bringup/Makefile @@ -1,7 +1,7 @@ CC=sdcc DEBUG=--debug -CFLAGS=--model-small --debug -I../src +CFLAGS=--model-small --debug -I../src/core -I../src/cc1111 LDFLAGS=--out-fmt-ihx --code-loc 0xf000 --xram-loc 0xf400 --xram-size 1024 --iram-size 0xff -- cgit v1.2.3 From a10aa835a06b71e2cefeb6b10daaf8cc394603b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Oct 2011 22:54:40 -0700 Subject: altos: Add LEGACY_MONITOR defines to more programs Make all monitoring programs define whether they want all of the old telemetry formats too. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index d2fbb209..7c5b4574 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -112,6 +112,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -222,6 +223,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -248,6 +250,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -281,6 +284,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -321,6 +325,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 0 #define HAS_AES 1 #endif -- cgit v1.2.3 From eb61f7aa2c8b692bd892b85e782f249187c80e5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Oct 2011 11:30:43 -0700 Subject: altos: Add teleballoon-v1.1 directory This is an alternate firmware load for telemetrum v1.1. Signed-off-by: Keith Packard --- src/core/ao_log_big.c | 2 + src/core/ao_telemetry.c | 2 +- src/teleballoon-v1.1/.gitignore | 2 + src/teleballoon-v1.1/Makefile | 122 +++++++++++++++++++ src/teleballoon-v1.1/ao_balloon.c | 155 ++++++++++++++++++++++++ src/teleballoon-v1.1/ao_pins.h | 220 ++++++++++++++++++++++++++++++++++ src/teleballoon-v1.1/ao_teleballoon.c | 77 ++++++++++++ 7 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 src/teleballoon-v1.1/.gitignore create mode 100644 src/teleballoon-v1.1/Makefile create mode 100644 src/teleballoon-v1.1/ao_balloon.c create mode 100644 src/teleballoon-v1.1/ao_pins.h create mode 100644 src/teleballoon-v1.1/ao_teleballoon.c diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 74d94c4b..43b3aa0c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -65,9 +65,11 @@ static __data uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; +#ifndef AO_SENSOR_INTERVAL_ASCENT #define AO_SENSOR_INTERVAL_ASCENT 1 #define AO_SENSOR_INTERVAL_DESCENT 10 #define AO_OTHER_INTERVAL 32 +#endif void ao_log(void) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index d909bea5..e66598d1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/teleballoon-v1.1/.gitignore b/src/teleballoon-v1.1/.gitignore new file mode 100644 index 00000000..21b236c0 --- /dev/null +++ b/src/teleballoon-v1.1/.gitignore @@ -0,0 +1,2 @@ +teleballoon-* +ao_product.h diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile new file mode 100644 index 00000000..89471cf4 --- /dev/null +++ b/src/teleballoon-v1.1/Makefile @@ -0,0 +1,122 @@ +# +# TeleBalloon build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +TELEBALLOON_VER=1.1 +TELEBALLOON_DEF=1_1 + +TELEBALLOON_INC = + +TELEBALLOON_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +vpath %.c ..:../core:../cc1111:../drivers:../product:. +vpath %.h ..:../core:../cc1111:../drivers:../product:. +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h \ + $(TELEBALLOON_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_gps_report.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_balloon.c \ + ao_sample.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_big.c \ + ao_report.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_string.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TELEBALLOON_SRC) + +PRODUCT_SRC = \ + ao_teleballoon.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teleballoon-v$(TELEBALLOON_VER)-$(VERSION).ihx +PRODUCT=TeleBalloon-v$(TELEBALLOON_VER) +PRODUCT_DEF=-DTELEBALLOON_V_$(TELEBALLOON_DEF) +IDPRODUCT=0x000b + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c new file mode 100644 index 00000000..08a3ae1e --- /dev/null +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ + +__pdata uint8_t ao_flight_force_idle; + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to coast: + * + * barometer: > 20m vertical motion + */ + if (ao_height > AO_M_TO_HEIGHT(20)) + { + ao_flight_state = ao_flight_drogue; + + /* start logging data */ + ao_log_start(); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + break; + + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h new file mode 100644 index 00000000..a96c6f2b --- /dev/null +++ b/src/teleballoon-v1.1/ao_pins.h @@ -0,0 +1,220 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEBALLOON_V_1_1) + + #define AO_SENSOR_INTERVAL_ASCENT AO_MS_TO_TICKS(1000) + #define AO_SENSOR_INTERVAL_DESCENT AO_MS_TO_TICKS(1000) + #define AO_OTHER_INTERVAL AO_MS_TO_TICKS(1000) + #define AO_TELEMETRY_INTERVAL_BALLOON AO_MS_TO_TICKS(1000) + + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/teleballoon-v1.1/ao_teleballoon.c b/src/teleballoon-v1.1/ao_teleballoon.c new file mode 100644 index 00000000..a48e21d2 --- /dev/null +++ b/src/teleballoon-v1.1/ao_teleballoon.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +ao_ignite_set_pins(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_gps_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 85b259c5bba7edbd2a79471bb1104bcf3904d536 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Oct 2011 14:58:26 -0700 Subject: src/teleballoon-v1.1: Use Tm style initial state stuff Come up in pad mode unless someone talks to us while in idle mode. Signed-off-by: Keith Packard --- src/teleballoon-v1.1/ao_balloon.c | 30 ++---------------------------- src/teleballoon-v1.1/ao_teleballoon.c | 2 +- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c index 08a3ae1e..e8972655 100644 --- a/src/teleballoon-v1.1/ao_balloon.c +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -59,26 +59,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) + if (!ao_flight_force_idle) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; @@ -89,10 +70,8 @@ ao_flight(void) ao_usb_disable(); #endif -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ + /* Disable packet mode in pad state */ ao_packet_slave_stop(); -#endif /* Turn on telemetry system */ ao_rdf_set(1); @@ -104,11 +83,6 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; -#if HAS_ACCEL - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/teleballoon-v1.1/ao_teleballoon.c b/src/teleballoon-v1.1/ao_teleballoon.c index a48e21d2..3f12a59c 100644 --- a/src/teleballoon-v1.1/ao_teleballoon.c +++ b/src/teleballoon-v1.1/ao_teleballoon.c @@ -65,7 +65,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(FALSE); + ao_packet_slave_init(TRUE); #if HAS_DBG ao_dbg_init(); #endif -- cgit v1.2.3 From 07d4477b2e8477e96a2f155a25f95e14a9a47efa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 12:51:05 -0700 Subject: altos/teleterra_0_2: Initialize LCD driver Initialize the LCD for testing. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index a6c10158..4019469b 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -32,5 +32,6 @@ main(void) ao_monitor_init(0, TRUE); ao_radio_init(); ao_config_init(); + ao_lcd_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 8e2736226fcd7c1ab1ba93a5ebac9b285ebf4733 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 12:55:35 -0700 Subject: src/teleterra-v0.2: Initialize more hardware Initialize the flash storage and flight state reporting beeper. Signed-off-by: Keith Packard --- src/product/ao_telebt.c | 2 +- src/product/ao_teleterra_0_2.c | 4 ++++ src/teleterra-v0.2/Makefile | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 9e409db7..c4b40dfc 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); + ao_monitor_init(AO_LED_RED, TRUE); #if HAS_LOG ao_report_init(); #endif diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 4019469b..05085860 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -26,10 +26,14 @@ main(void) ao_timer_init(); ao_beep_init(); ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); ao_usb_init(); ao_serial_init(); ao_gps_init(); ao_monitor_init(0, TRUE); + ao_report_init(); + ao_log_single_init(); ao_radio_init(); ao_config_init(); ao_lcd_init(); diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 892c37e2..eda67a2a 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -24,6 +24,7 @@ CORE_SRC = \ ao_log_telem.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ -- cgit v1.2.3 From 7e7a10c06a0486e9f869e361e46f2c98db9897b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:08:59 -0700 Subject: altos: Add button driver and sample user Hook up the teleterra buttons and have them beep Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 15 ++++++++ src/cc1111/ao_button.c | 86 ++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_usb.c | 3 ++ src/core/ao.h | 7 ++++ src/product/ao_teleterra_0_2.c | 1 + src/product/ao_terraui.c | 45 ++++++++++++++++++++++ src/teleterra-v0.2/Makefile | 4 +- src/teleterra-v0.2/ao_pins.h | 4 ++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/cc1111/ao_button.c create mode 100644 src/product/ao_terraui.c diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 02e36189..23589e66 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,6 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_button.c */ +void +ao_p2_isr(void); + +void +ao_button_init(void); + +#if HAS_BUTTON_P0 +void +ao_p0_isr(void) ao_arch_interrupt(13); +#endif + +char +ao_button_get(void) __critical; + /* ao_string.c */ void diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c new file mode 100644 index 00000000..547d71ac --- /dev/null +++ b/src/cc1111/ao_button.c @@ -0,0 +1,86 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +volatile __xdata struct ao_fifo ao_button_fifo; + +#define BUTTON_1_PIN (P0_4) +#define BUTTON_1_MASK (1 << 4) /* P0_4 */ + +#define BUTTON_2_PIN (P2_3) +#define BUTTON_2_MASK (1 << 3) /* P2_3 */ + +#define BUTTON_3_PIN (P2_4) +#define BUTTON_3_MASK (1 << 4) /* P2_4 */ + +static void +ao_button_insert(char n) +{ + ao_fifo_insert(ao_button_fifo, n); + ao_wakeup(&ao_button_fifo); +} + +char +ao_button_get(void) __critical +{ + char b; + + while (ao_fifo_empty(ao_button_fifo)) + ao_sleep(&ao_button_fifo); + ao_fifo_remove(ao_button_fifo, b); + return b; +} + +void +ao_p2_isr(void) +{ + if (P2IFG & BUTTON_2_MASK) + ao_button_insert(2); + if (P2IFG & BUTTON_3_MASK) + ao_button_insert(3); + P2IFG = 0; +} + +void +ao_p0_isr(void) ao_arch_interrupt(13) +{ + P0IF = 0; + if (P0IFG & BUTTON_1_MASK) + ao_button_insert(1); + P0IFG = 0; +} + +void +ao_button_init(void) +{ + /* Pins are configured as inputs with pull-up by default */ + + /* Enable interrupts for P2_0 - P2_4 + * Enable interrupts for P0_4 - P0_7 + * Set P2 interrupts to falling edge + * Set P0 interrupts to falling edge + */ + + PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + + /* Enable interrupts for P0 inputs */ + IEN1 |= IEN1_P0IE; + + /* Enable interrupts for P2 inputs */ + IEN2 |= IEN2_P2IE; +} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 08cb7390..35c9ac20 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -62,6 +62,9 @@ ao_usb_isr(void) __interrupt 6 ao_btm_isr(); #endif #endif +#if HAS_P2_ISR + ao_p2_isr(); +#endif } struct ao_usb_setup { diff --git a/src/core/ao.h b/src/core/ao.h index c800f1fc..43d4e0e3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1851,4 +1851,11 @@ ao_log_single(void); #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #endif +/* + * ao_terraui.c + */ + +void +ao_terraui_init(void); + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 05085860..b38f2907 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -37,5 +37,6 @@ main(void) ao_radio_init(); ao_config_init(); ao_lcd_init(); + ao_terraui_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c new file mode 100644 index 00000000..3885db4e --- /dev/null +++ b/src/product/ao_terraui.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_terraui(void) +{ + for (;;) { + char b = ao_button_get(); + switch (b) { + case 1: + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + break; + case 2: + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + break; + case 3: + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + break; + } + } +} + +__xdata static struct ao_task ao_terraui_task; + +void +ao_terraui_init(void) +{ + ao_add_task(&ao_terraui_task, ao_terraui, "ui"); +} diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index eda67a2a..8e4569a9 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -33,6 +33,7 @@ CORE_SRC = \ CC1111_SRC = \ ao_beep.c \ + ao_button.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ @@ -54,7 +55,8 @@ DRIVER_SRC = \ ao_gps_skytraq.c PRODUCT_SRC = \ - ao_teleterra_0_2.c + ao_teleterra_0_2.c \ + ao_terraui.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 671d3876..7b6f08b2 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -53,6 +53,10 @@ #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 + + #define HAS_P2_ISR 1 + #define HAS_BUTTON_P0 1 + #define HAS_BUTTON_P2 1 #endif #if DBG_ON_P1 -- cgit v1.2.3 From f70553106707e3496d07eecb83f0c0a1acad7f77 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:51:32 -0700 Subject: altos: Add battery voltage sampling driver For devices without a full ADC compliment, this just samples the battery pin and converts to mV. Signed-off-by: Keith Packard --- src/cc1111/ao_battery.c | 60 ++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 15 +++++++++++ src/product/ao_teleterra_0_2.c | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 2 ++ 5 files changed, 79 insertions(+) create mode 100644 src/cc1111/ao_battery.c diff --git a/src/cc1111/ao_battery.c b/src/cc1111/ao_battery.c new file mode 100644 index 00000000..070f682f --- /dev/null +++ b/src/cc1111/ao_battery.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +static __data union { + uint8_t d[2]; + int16_t v; +} ao_battery_value; + +void +ao_battery_isr(void) ao_arch_interrupt(1) +{ + ao_battery_value.d[0] = ADCL; + ao_battery_value.d[1] = ADCH; + ao_wakeup(DATA_TO_XDATA(&ao_battery_value)); +} + +uint16_t +ao_battery_get(void) +{ + ao_arch_critical( + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | BATTERY_PIN; + ao_sleep(DATA_TO_XDATA(&ao_battery_value)); + ); + return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 3333 >> 15); +} + +static void +ao_battery_show(void) +{ + printf("Battery: %u mV\n", ao_battery_get()); +} + +__code struct ao_cmds ao_battery_cmds[] = { + { ao_battery_show, "B\0Show battery voltage" }, + { 0, NULL }, +}; + +void +ao_battery_init(void) +{ + ADCCFG = (1 << BATTERY_PIN); + ADCIF = 0; + IEN0 |= IEN0_ADCIE; + ao_cmd_register(&ao_battery_cmds[0]); +} diff --git a/src/core/ao.h b/src/core/ao.h index 43d4e0e3..558d0e38 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1858,4 +1858,19 @@ ao_log_single(void); void ao_terraui_init(void); +/* + * ao_battery.c + */ + +#ifdef BATTERY_PIN +void +ao_battery_isr(void) ao_arch_interrupt(1); + +uint16_t +ao_battery_get(void); + +void +ao_battery_init(void); +#endif /* BATTERY_PIN */ + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index b38f2907..3272970f 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -38,5 +38,6 @@ main(void) ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_battery_init(); ao_start_scheduler(); } diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 8e4569a9..36f523a3 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -32,6 +32,7 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_battery.c \ ao_beep.c \ ao_button.c \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 7b6f08b2..36f3c199 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -57,6 +57,8 @@ #define HAS_P2_ISR 1 #define HAS_BUTTON_P0 1 #define HAS_BUTTON_P2 1 + + #define BATTERY_PIN 5 #endif #if DBG_ON_P1 -- cgit v1.2.3 From 90e738a3379d258a48a7c92f6708040fc39c373a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 15:20:50 -0700 Subject: altos: Fix battery voltage computation. Full scale is 4.95V, not 3.333V. Signed-off-by: Keith Packard --- src/cc1111/ao_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc1111/ao_battery.c b/src/cc1111/ao_battery.c index 070f682f..b9845fb3 100644 --- a/src/cc1111/ao_battery.c +++ b/src/cc1111/ao_battery.c @@ -36,7 +36,7 @@ ao_battery_get(void) ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | BATTERY_PIN; ao_sleep(DATA_TO_XDATA(&ao_battery_value)); ); - return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 3333 >> 15); + return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 4950 >> 15); } static void -- cgit v1.2.3 From 8e4cceedb5b758faae684978299e667c4bb06f4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 15:24:02 -0700 Subject: altos: Flip button IRQ initialization around This matches what the docs suggest Signed-off-by: Keith Packard --- src/cc1111/ao_button.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 547d71ac..3516d559 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -76,11 +76,11 @@ ao_button_init(void) * Set P0 interrupts to falling edge */ - PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; - /* Enable interrupts for P0 inputs */ IEN1 |= IEN1_P0IE; /* Enable interrupts for P2 inputs */ IEN2 |= IEN2_P2IE; + + PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; } -- cgit v1.2.3 From da330c5975b9f565d059ef8084dfdacc20f34246 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 26 Oct 2011 22:49:11 -0700 Subject: altos: Bring up basic TeleTerra v0.2 UI Lots of fun stuff here -- multiple panes of information. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 +- src/cc1111/ao_button.c | 115 ++++++--- src/cc1111/ao_lcd_port.c | 13 +- src/core/ao.h | 24 +- src/core/ao_monitor.c | 10 +- src/core/ao_sqrt.c | 46 ++++ src/drivers/ao_lcd.c | 12 +- src/product/Makefile.telemetrum | 6 +- src/product/ao_teleterra_0_2.c | 3 +- src/product/ao_terraui.c | 497 +++++++++++++++++++++++++++++++++++++- src/telelaunch-v0.1/.gitignore | 2 +- src/telemetrum-v0.1-sirf/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile | 1 + src/teleterra-v0.2/.gitignore | 2 + src/teleterra-v0.2/.sdcdbrc | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 14 +- 17 files changed, 710 insertions(+), 52 deletions(-) create mode 100644 src/core/ao_sqrt.c create mode 100644 src/teleterra-v0.2/.gitignore create mode 100644 src/teleterra-v0.2/.sdcdbrc diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 23589e66..f0f0daae 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,17 +205,23 @@ struct ao_adc { #define AO_ADC_RING 32 /* ao_button.c */ +#ifdef HAS_BUTTON void -ao_p2_isr(void); +ao_p0_isr(void) ao_arch_interrupt(13); void -ao_button_init(void); +ao_p1_isr(void) ao_arch_interrupt(15); -#if HAS_BUTTON_P0 void -ao_p0_isr(void) ao_arch_interrupt(13); +ao_p2_isr(void); + +#define HAS_P2_ISR 1 + #endif +void +ao_button_init(void); + char ao_button_get(void) __critical; diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 3516d559..77a8dde8 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -19,14 +19,22 @@ volatile __xdata struct ao_fifo ao_button_fifo; -#define BUTTON_1_PIN (P0_4) -#define BUTTON_1_MASK (1 << 4) /* P0_4 */ +static __code struct { + uint8_t mask; + uint8_t reg; +} ao_buttons[] = { +#ifdef BUTTON_1_MASK + { BUTTON_1_MASK, BUTTON_1_REG }, +#endif +#ifdef BUTTON_2_MASK + { BUTTON_2_MASK, BUTTON_2_REG }, +#endif +#ifdef BUTTON_3_MASK + { BUTTON_3_MASK, BUTTON_3_REG }, +#endif +}; -#define BUTTON_2_PIN (P2_3) -#define BUTTON_2_MASK (1 << 3) /* P2_3 */ - -#define BUTTON_3_PIN (P2_4) -#define BUTTON_3_MASK (1 << 4) /* P2_4 */ +#define NUM_BUTTONS ((sizeof ao_buttons) / sizeof (ao_buttons[0])) static void ao_button_insert(char n) @@ -35,52 +43,101 @@ ao_button_insert(char n) ao_wakeup(&ao_button_fifo); } +static void +ao_button_isr(uint8_t flag, uint8_t reg) +{ + uint8_t b; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg && (ao_buttons[b].mask & flag)) + ao_button_insert(b + 1); +} + +static uint8_t +ao_button_mask(uint8_t reg) +{ + uint8_t b; + uint8_t mask = 0; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg) + mask |= ao_buttons[b].mask; + return mask; +} + char ao_button_get(void) __critical { char b; while (ao_fifo_empty(ao_button_fifo)) - ao_sleep(&ao_button_fifo); + if (ao_sleep(&ao_button_fifo)) + return 0; ao_fifo_remove(ao_button_fifo, b); return b; } void -ao_p2_isr(void) +ao_p0_isr(void) ao_arch_interrupt(13) { - if (P2IFG & BUTTON_2_MASK) - ao_button_insert(2); - if (P2IFG & BUTTON_3_MASK) - ao_button_insert(3); - P2IFG = 0; + P0IF = 0; + ao_button_isr(P0IFG, 0); + P0IFG = 0; } void -ao_p0_isr(void) ao_arch_interrupt(13) +ao_p1_isr(void) ao_arch_interrupt(15) { - P0IF = 0; - if (P0IFG & BUTTON_1_MASK) - ao_button_insert(1); - P0IFG = 0; + P1IF = 0; + ao_button_isr(P1IFG, 1); + P1IFG = 0; +} + +/* Shared with USB */ +void +ao_p2_isr(void) +{ + ao_button_isr(P2IFG, 2); + P2IFG = 0; } void ao_button_init(void) { + uint8_t mask; + /* Pins are configured as inputs with pull-up by default */ - /* Enable interrupts for P2_0 - P2_4 - * Enable interrupts for P0_4 - P0_7 - * Set P2 interrupts to falling edge - * Set P0 interrupts to falling edge - */ - /* Enable interrupts for P0 inputs */ - IEN1 |= IEN1_P0IE; + mask = ao_button_mask(0); + if (mask) { + if (mask & 0x0f) + PICTL |= PICTL_P0IENL; + if (mask & 0xf0) + PICTL |= PICTL_P0IENH; + P0IFG = 0; + P0IF = 0; + IEN1 |= IEN1_P0IE; + PICTL |= PICTL_P0ICON; + } - /* Enable interrupts for P2 inputs */ - IEN2 |= IEN2_P2IE; + /* Enable interrupts for P1 inputs */ + mask = ao_button_mask(1); + if (mask) { + P1IEN |= mask; + P1IFG = 0; + P1IF = 0; + IEN2 |= IEN2_P1IE; + PICTL |= PICTL_P1ICON; + } - PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + /* Enable interrupts for P2 inputs */ + mask = ao_button_mask(2); + if (mask) { + PICTL |= PICTL_P2IEN; + P2IFG = 0; + P2IF = 0; + IEN2 |= IEN2_P2IE; + PICTL |= PICTL_P2ICON; + } } diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c index 324cc3d3..e61b1a60 100644 --- a/src/cc1111/ao_lcd_port.c +++ b/src/cc1111/ao_lcd_port.c @@ -17,15 +17,24 @@ #include "ao.h" +static void +ao_lcd_port_delay(void) +{ + uint8_t i; + + for (i = 0; i < 100; i++) + ao_arch_nop(); +} + void ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) { P0 = (P0 & 0xf0) | (nibble & 0x0f); P1_1 = rs; P1_0 = 1; - ao_delay(1); + ao_lcd_port_delay(); P1_0 = 0; - ao_delay(1); + ao_lcd_port_delay(); } void diff --git a/src/core/ao.h b/src/core/ao.h index 558d0e38..9b8d3270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -996,7 +996,11 @@ ao_spi_slave(void); */ #define AO_MAX_CALLSIGN 8 #define AO_MAX_VERSION 8 +#if LEGACY_MONITOR #define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif struct ao_telemetry_generic { uint16_t serial; /* 0 */ @@ -1156,6 +1160,12 @@ union ao_telemetry_all { struct ao_telemetry_baro baro; }; +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + /* * ao_gps.c */ @@ -1372,9 +1382,10 @@ extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_all_recv all; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; }; extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -1873,4 +1884,11 @@ void ao_battery_init(void); #endif /* BATTERY_PIN */ +/* + * ao_sqrt.c + */ + +uint32_t +ao_sqrt(uint32_t op); + #endif /* _AO_H_ */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 5a6f61dd..f7795fe4 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -26,6 +26,10 @@ #error Must define LEGACY_MONITOR #endif +#ifndef HAS_MONITOR_PUT +#define HAS_MONIOTOR_PUT 1 +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -73,6 +77,7 @@ ao_monitor_blink(void) } } +#if HAS_MONITOR_PUT void ao_monitor_put(void) { @@ -260,9 +265,10 @@ ao_monitor_put(void) ao_usb_flush(); } } +__xdata struct ao_task ao_monitor_put_task; +#endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_put_task; __xdata struct ao_task ao_monitor_blink_task; void @@ -293,7 +299,9 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_monitoring = monitoring; ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if HAS_MONITOR_PUT ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +#endif if (ao_monitor_led) ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } diff --git a/src/core/ao_sqrt.c b/src/core/ao_sqrt.c new file mode 100644 index 00000000..09c2e319 --- /dev/null +++ b/src/core/ao_sqrt.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* Adapted from int_sqrt.c in the linux kernel, which is licensed GPLv2 */ +/** + * int_sqrt - rough approximation to sqrt + * @x: integer of which to calculate the sqrt + * + * A very rough approximation to the sqrt() function. + */ + +uint32_t +ao_sqrt(uint32_t op) +{ + uint32_t res = 0; + uint32_t one = 1UL << (sizeof (one) * 8 - 2); + + while (one > op) + one >>= 2; + + while (one != 0) { + if (op >= res + one) { + op = op - (res + one); + res = res + 2 * one; + } + res /= 2; + one /= 4; + } + return res; +} diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index e62247ae..8745b3f6 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -19,6 +19,8 @@ static uint16_t ao_lcd_time = 3; +static __xdata uint8_t ao_lcd_mutex; + static void ao_lcd_delay(void) { @@ -39,7 +41,7 @@ ao_lcd_send_ins(uint8_t ins) ao_lcd_port_put_nibble(0, ins & 0xf); } -void +static void ao_lcd_put_byte(uint8_t c) { // printf ("send data %02x\n", c); @@ -54,8 +56,10 @@ ao_lcd_putstring(char *string) { char c; + ao_mutex_get(&ao_lcd_mutex); while ((c = (uint8_t) *string++)) ao_lcd_put_byte((uint8_t) c); + ao_mutex_put(&ao_lcd_mutex); } #define AO_LCD_POWER_CONTROL 0x54 @@ -63,24 +67,30 @@ ao_lcd_putstring(char *string) void ao_lcd_contrast_set(uint8_t contrast) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); ao_lcd_send_ins(0x70 | (contrast & 0xf)); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_clear(void) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x01); ao_delay(1); /* Entry mode */ ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_goto(uint8_t addr) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x80 | addr); ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 4f4195a9..40fc6bc2 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -7,8 +7,8 @@ # TM_VER, TM_DEF, TM_INC and TM_SRC and include # this file -vpath %.c ..:../core:../cc1111:../drivers:../product -vpath %.h ..:../core:../cc1111:../drivers:../product +vpath %.c .:..:../core:../cc1111:../drivers:../product +vpath %.h .:..:../core:../cc1111:../drivers:../product vpath ao-make-product.5c ../util ifndef VERSION @@ -72,7 +72,7 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PROG = telemetrum-v$(TM_VER)-$(VERSION)$(TM_EXTRA).ihx PRODUCT=TeleMetrum-v$(TM_VER) PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) IDPRODUCT=0x000b diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 3272970f..6ce29894 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,13 +31,14 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, TRUE); + ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); ao_report_init(); ao_log_single_init(); ao_radio_init(); ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_button_init(); ao_battery_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 3885db4e..cfbfb1fb 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,21 +16,450 @@ */ #include "ao.h" +#include + +static __xdata struct ao_telemetry_sensor ao_tel_sensor; +static __xdata struct ao_telemetry_location ao_tel_location; +static __xdata struct ao_telemetry_configuration ao_tel_config; +static __xdata int16_t ao_tel_max_speed; +static __xdata int16_t ao_tel_max_height; +static int8_t ao_tel_rssi; + +static __xdata char ao_lcd_line[17]; +static __xdata char ao_state_name[] = "SIPBFCDMLI"; + +static void +ao_terraui_line(uint8_t addr) +{ + ao_lcd_goto(addr); + ao_lcd_putstring(ao_lcd_line); +} + +#define ao_terraui_state() (ao_state_name[ao_tel_sensor.state]) + +static char +ao_terraui_igniter(int16_t sense) +{ + if (sense < AO_IGNITER_OPEN) + return '-'; + if (sense > AO_IGNITER_CLOSED) + return '+'; + return '?'; +} + +static char +ao_terraui_battery(void) +{ + if (ao_tel_sensor.v_batt > 25558) + return '+'; + return '-'; +} + +static char +ao_terraui_gps(void) +{ + if (ao_tel_location.flags & (1 << 4)) { + if ((ao_tel_location.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_local_gps(void) +{ + if (ao_gps_data.flags & (1 << 4)) { + if ((ao_gps_data.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_logging(void) +{ + if (ao_tel_config.flight != 0) + return '+'; + return '-'; +} + +static __code char ao_progress[4] = { '\011', '\012', '\014', '\013' }; + +static uint8_t ao_telem_progress; +static uint8_t ao_gps_progress; + +static void +ao_terraui_info(void) +{ + sprintf(ao_lcd_line, "S %4d %7.7s %c", + ao_tel_sensor.serial, + ao_tel_config.callsign, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "F %4d RSSI%4d%c", + ao_tel_config.flight, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_pad(void) +{ + sprintf(ao_lcd_line, "B%c A%c M%c L%c G%c %c", + ao_terraui_battery(), + ao_terraui_igniter(ao_tel_sensor.sense_d), + ao_terraui_igniter(ao_tel_sensor.sense_m), + ao_terraui_logging(), + ao_terraui_gps(), + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "SAT %2d RSSI%4d%c", + ao_tel_location.flags & 0xf, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_ascent(void) +{ + sprintf(ao_lcd_line, "S %5d S\011%5d%c", + ao_tel_sensor.speed >> 4, + ao_tel_max_speed >> 4, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H %5d H\011%5d%c", + ao_tel_sensor.height >> 4, + ao_tel_max_height >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static int16_t mag(int32_t d) +{ + if (d < 0) + d = -d; + if (d > 0x7fff) + d = 0x7fff; + return d; +} + +static uint32_t +dist(int32_t d) +{ + int32_t m; + + if (d < 0) + d = -d; + + m = 1000000; + while (d >= (2147483647 / 111198)) { + d /= 10; + m /= 10; + } + return (d * 111198) / m; +} + +static __code uint8_t cos_table[] = { + 0, /* 0 */ + 0, /* 1 */ + 0, /* 2 */ + 255, /* 3 */ + 254, /* 4 */ + 253, /* 5 */ + 252, /* 6 */ + 251, /* 7 */ + 249, /* 8 */ + 247, /* 9 */ + 245, /* 10 */ + 243, /* 11 */ + 240, /* 12 */ + 238, /* 13 */ + 235, /* 14 */ + 232, /* 15 */ + 228, /* 16 */ + 225, /* 17 */ + 221, /* 18 */ + 217, /* 19 */ + 213, /* 20 */ + 209, /* 21 */ + 205, /* 22 */ + 200, /* 23 */ + 195, /* 24 */ + 190, /* 25 */ + 185, /* 26 */ + 180, /* 27 */ + 175, /* 28 */ + 169, /* 29 */ + 163, /* 30 */ + 158, /* 31 */ + 152, /* 32 */ + 145, /* 33 */ + 139, /* 34 */ + 133, /* 35 */ + 126, /* 36 */ + 120, /* 37 */ + 113, /* 38 */ + 106, /* 39 */ + 100, /* 40 */ + 93, /* 41 */ + 86, /* 42 */ + 79, /* 43 */ + 71, /* 44 */ + 64, /* 45 */ + 57, /* 46 */ + 49, /* 47 */ + 42, /* 48 */ + 35, /* 49 */ + 27, /* 50 */ + 20, /* 51 */ + 12, /* 52 */ + 5, /* 53 */ + 1, /* 54 */ +}; + +static __code uint8_t tan_table[] = { + 0, /* 0 */ + 4, /* 1 */ + 9, /* 2 */ + 13, /* 3 */ + 18, /* 4 */ + 22, /* 5 */ + 27, /* 6 */ + 31, /* 7 */ + 36, /* 8 */ + 41, /* 9 */ + 45, /* 10 */ + 50, /* 11 */ + 54, /* 12 */ + 59, /* 13 */ + 64, /* 14 */ + 69, /* 15 */ + 73, /* 16 */ + 78, /* 17 */ + 83, /* 18 */ + 88, /* 19 */ + 93, /* 20 */ + 98, /* 21 */ + 103, /* 22 */ + 109, /* 23 */ + 114, /* 24 */ + 119, /* 25 */ + 125, /* 26 */ + 130, /* 27 */ + 136, /* 28 */ + 142, /* 29 */ + 148, /* 30 */ + 154, /* 31 */ + 160, /* 32 */ + 166, /* 33 */ + 173, /* 34 */ + 179, /* 35 */ + 186, /* 36 */ + 193, /* 37 */ + 200, /* 38 */ + 207, /* 39 */ + 215, /* 40 */ + 223, /* 41 */ + 231, /* 42 */ + 239, /* 43 */ + 247, /* 44 */ +}; + +int16_t ao_atan2(int32_t dy, int32_t dx) __reentrant +{ + int8_t m = 1; + int16_t a = 0; + uint8_t r; + int8_t t; + + if (dx == 0) { + if (dy > 0) + return 90; + if (dy < 0) + return -90; + return 0; + } + + if (dx < 0) { + a = 180; + m = -m; + dx = -dx; + } + + if (dy < 0) { + m = -m; + a = -a; + dy = -dy; + } + + if (dy > dx) { + int t; + + t = dy; dy = dx; dx = t; + a = a + m * 90; + m = -m; + } + + r = ((dy << 8) + (dx >> 1)) / dx; + for (t = 0; t < 44; t++) + if (tan_table[t] >= r) + break; + return t * m + a; +} + +static __pdata uint32_t lon_dist, lat_dist; +static __pdata uint32_t ground_dist, range; +static __pdata int16_t bearing, elevation; + +static void +ao_terraui_lat_dist(void) +{ + lat_dist = dist (ao_tel_location.latitude - ao_gps_data.latitude); +} + +static void +ao_terraui_lon_dist(void) +{ + uint8_t c = cos_table[ao_gps_data.latitude >> 24]; + lon_dist = dist(ao_tel_location.longitude - ao_gps_data.longitude); + if (c) + lon_dist = ((uint32_t) lon_dist * c) >> 8; +} + +static void +ao_terraui_compute(void) +{ + ao_terraui_lat_dist(); + ao_terraui_lon_dist(); + ground_dist = ao_sqrt (lat_dist * lat_dist + lon_dist * lon_dist); + range = ao_sqrt(ground_dist * ground_dist + ao_tel_sensor.height * ao_tel_sensor.height); + bearing = ao_atan2(lat_dist, lon_dist); + elevation = ao_atan2(ao_tel_sensor.height, ground_dist); +} + +static void +ao_terraui_descent(void) +{ + ao_terraui_compute(); + sprintf(ao_lcd_line, "\007 %4d \005 %3d %c", + bearing, elevation, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H:%5d S:%5d%c", + ao_tel_sensor.height, ao_tel_sensor.speed >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_coord(int32_t c, char plus, char minus, char extra) __reentrant +{ + uint16_t d; + uint8_t m; + uint16_t f; + + if (c < 0) { + plus = minus; + c = -c; + } + d = c / 10000000; + c = c % 10000000; + c = c * 60; + m = c / 10000000; + c = c % 10000000; + f = (c + 500) / 1000; + sprintf(ao_lcd_line, "%c %3d\362 %2d.%04d\"%c", + plus, d, m, f, extra); +} + +static void +ao_terraui_remote(void) +{ + ao_terraui_coord(ao_tel_location.latitude, 'N', 'S', ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_tel_location.longitude, 'E', 'W', ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_local(void) __reentrant +{ + ao_terraui_coord(ao_gps_data.latitude, 'n', 's', + ao_terraui_local_gps()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_gps_data.longitude, 'e', 'w', ao_progress[ao_gps_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_config(void) +{ + +} + +enum ao_page { + ao_page_info, + ao_page_pad, + ao_page_ascent, + ao_page_descent, + ao_page_remote, + ao_page_local, +}; static void ao_terraui(void) { + enum ao_page cur_page = ao_page_info; + + ao_lcd_start(); for (;;) { - char b = ao_button_get(); + char b; + switch (cur_page) { + case ao_page_info: + ao_terraui_info(); + break; + case ao_page_pad: + ao_terraui_pad(); + break; + case ao_page_ascent: + ao_terraui_ascent(); + break; + case ao_page_descent: + ao_terraui_descent(); + break; + case ao_page_remote: + ao_terraui_remote(); + break; + case ao_page_local: + ao_terraui_local(); + break; + } + + ao_alarm(AO_SEC_TO_TICKS(1)); + b = ao_button_get(); + ao_clear_alarm(); + switch (b) { + case 0: + break; case 1: - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_local) + cur_page = ao_page_info; + else + cur_page++; + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(50)); break; case 2: - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); break; case 3: - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_info) + cur_page = ao_page_local; + else + cur_page--; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); break; } } @@ -38,8 +467,68 @@ ao_terraui(void) __xdata static struct ao_task ao_terraui_task; +static void +ao_terramonitor(void) +{ + uint8_t monitor; + + monitor = ao_monitor_head; + for (monitor = ao_monitor_head;; + monitor = ao_monitor_ring_next(monitor)) + { + while (monitor == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (ao_monitoring != sizeof (union ao_telemetry_all)) + continue; + if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) + continue; + ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + ao_xmemcpy(&ao_tel_sensor, &ao_monitor_ring[monitor], sizeof (ao_tel_sensor)); + if (ao_tel_sensor.state < ao_flight_boost) { + ao_tel_max_speed = 0; + ao_tel_max_height = 0; + } else { + if (ao_tel_sensor.speed > ao_tel_max_speed) + ao_tel_max_speed = ao_tel_sensor.speed; + if (ao_tel_sensor.height > ao_tel_max_height) + ao_tel_max_height = ao_tel_sensor.height; + } + ao_telem_progress = (ao_telem_progress + 1) & 0x3; + break; + case AO_TELEMETRY_LOCATION: + ao_xmemcpy(&ao_tel_location, &ao_monitor_ring[monitor], sizeof (ao_tel_location)); + break; + case AO_TELEMETRY_CONFIGURATION: + ao_xmemcpy(&ao_tel_config, &ao_monitor_ring[monitor], sizeof (ao_tel_config)); + } + } +} + +__xdata static struct ao_task ao_terramonitor_task; + +static void +ao_terragps(void) +{ + uint16_t gps_tick = ao_gps_progress; + + for (;;) { + while (ao_gps_tick == gps_tick) + ao_sleep(&ao_gps_data); + gps_tick = ao_gps_tick; + ao_gps_progress = (ao_gps_progress + 1) & 3; + } +} + +__xdata static struct ao_task ao_terragps_task; + void ao_terraui_init(void) { ao_add_task(&ao_terraui_task, ao_terraui, "ui"); + ao_add_task(&ao_terramonitor_task, ao_terramonitor, "monitor"); + ao_add_task(&ao_terragps_task, ao_terragps, "gps"); } diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore index d25d7ad9..e2cf954c 100644 --- a/src/telelaunch-v0.1/.gitignore +++ b/src/telelaunch-v0.1/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sky* +telelaunch* ao_product.h diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index 00cdc9c5..d138b5ef 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sirf TM_INC = \ ao_25lc1024.h diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index e3c61db6..69cd3461 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sky TM_INC = \ ao_25lc1024.h diff --git a/src/teleterra-v0.2/.gitignore b/src/teleterra-v0.2/.gitignore new file mode 100644 index 00000000..9daebc3e --- /dev/null +++ b/src/teleterra-v0.2/.gitignore @@ -0,0 +1,2 @@ +teleterra-v0.2* +ao_product.h diff --git a/src/teleterra-v0.2/.sdcdbrc b/src/teleterra-v0.2/.sdcdbrc new file mode 100644 index 00000000..fbe9a599 --- /dev/null +++ b/src/teleterra-v0.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=../cc1111:../product:../core:../drivers:. diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 36f523a3..583805f6 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -26,6 +26,7 @@ CORE_SRC = \ ao_panic.c \ ao_report.c \ ao_rssi.c \ + ao_sqrt.c \ ao_state.c \ ao_stdio.c \ ao_storage.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 36f3c199..9c35b06a 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -45,6 +45,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_MONITOR_PUT 0 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 @@ -54,11 +55,18 @@ #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 - #define HAS_P2_ISR 1 - #define HAS_BUTTON_P0 1 - #define HAS_BUTTON_P2 1 + #define HAS_BUTTON 1 + #define BUTTON_1_REG 0 + #define BUTTON_1_MASK (1 << 4) /* P0_4 */ + + #define BUTTON_2_REG 2 + #define BUTTON_2_MASK (1 << 3) /* P2_3 */ + + #define BUTTON_3_REG 2 + #define BUTTON_3_MASK (1 << 4) /* P2_4 */ #define BATTERY_PIN 5 + #endif #if DBG_ON_P1 -- cgit v1.2.3 From c7e14a2750d437e8b77d68a944a0711e7a0c882b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 00:35:35 -0700 Subject: altos: Fix distance/bearing computations. Deal with large values Lots of little math errors dealing with large distances; easily tested as the GPS currently reports lat 24 lon 121, which is a long ways from Portland. Now reports distances in km when large, otherwise in m. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 79 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 14 deletions(-) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index cfbfb1fb..22bab5d6 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -145,20 +145,26 @@ static int16_t mag(int32_t d) return d; } -static uint32_t +static int32_t dist(int32_t d) { - int32_t m; + __pdata uint32_t m; + uint8_t neg = 0; - if (d < 0) + if (d < 0) { d = -d; + neg = 1; + } - m = 1000000; + m = 10000000; while (d >= (2147483647 / 111198)) { d /= 10; m /= 10; } - return (d * 111198) / m; + d = (d * 111198) / m; + if (neg) + d = -d; + return d; } static __code uint8_t cos_table[] = { @@ -295,22 +301,25 @@ int16_t ao_atan2(int32_t dy, int32_t dx) __reentrant } if (dy > dx) { - int t; + int32_t t; t = dy; dy = dx; dx = t; a = a + m * 90; m = -m; } - r = ((dy << 8) + (dx >> 1)) / dx; + dy = dy << 8; + dy = (dy + (dx >> 1)) / dx; + r = dy; for (t = 0; t < 44; t++) if (tan_table[t] >= r) break; return t * m + a; } -static __pdata uint32_t lon_dist, lat_dist; +static __pdata int32_t lon_dist, lat_dist; static __pdata uint32_t ground_dist, range; +static __pdata uint8_t dist_in_km; static __pdata int16_t bearing, elevation; static void @@ -320,22 +329,45 @@ ao_terraui_lat_dist(void) } static void -ao_terraui_lon_dist(void) +ao_terraui_lon_dist(void) __reentrant { uint8_t c = cos_table[ao_gps_data.latitude >> 24]; - lon_dist = dist(ao_tel_location.longitude - ao_gps_data.longitude); - if (c) - lon_dist = ((uint32_t) lon_dist * c) >> 8; + lon_dist = ao_tel_location.longitude; + + /* check if it's shorter to go the other way around */ + if ((int16_t) (lon_dist >> 24) < (int16_t) (ao_gps_data.longitude >> 24) - (int16_t) (1800000000 >> 24)) + lon_dist += 3600000000ul; + lon_dist = dist(lon_dist - ao_gps_data.longitude); + if (c) { + if (lon_dist & 0x7f800000) + lon_dist = (lon_dist >> 8) * c; + else + lon_dist = (lon_dist * (int16_t) c) >> 8; + } } +static int32_t sqr(int32_t x) { return x * x; } + static void ao_terraui_compute(void) { + uint16_t h = ao_tel_sensor.height; + ao_terraui_lat_dist(); ao_terraui_lon_dist(); - ground_dist = ao_sqrt (lat_dist * lat_dist + lon_dist * lon_dist); + if (lat_dist > 32767 || lon_dist > 32767) { + dist_in_km = 1; + ground_dist = sqr(lat_dist/1000) + sqr(lon_dist/1000); + h = h/1000; + } else { + dist_in_km = 0; + ground_dist = sqr(lat_dist) + sqr(lon_dist); + } + ground_dist = ao_sqrt (ground_dist); range = ao_sqrt(ground_dist * ground_dist + ao_tel_sensor.height * ao_tel_sensor.height); - bearing = ao_atan2(lat_dist, lon_dist); + bearing = ao_atan2(lon_dist, lat_dist); + if (bearing < 0) + bearing += 360; elevation = ao_atan2(ao_tel_sensor.height, ground_dist); } @@ -353,6 +385,21 @@ ao_terraui_descent(void) ao_terraui_line(AO_LCD_ADDR(1,0)); } +static void +ao_terraui_recover(void) +{ + ao_terraui_compute(); + sprintf(ao_lcd_line, "\007 %4d \005 %3d %c", + bearing, elevation, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "R%5ld%cRSSI%4d%c", + ground_dist, dist_in_km ? 'k' : ' ', + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + static void ao_terraui_coord(int32_t c, char plus, char minus, char extra) __reentrant { @@ -404,6 +451,7 @@ enum ao_page { ao_page_pad, ao_page_ascent, ao_page_descent, + ao_page_recover, ao_page_remote, ao_page_local, }; @@ -429,6 +477,9 @@ ao_terraui(void) case ao_page_descent: ao_terraui_descent(); break; + case ao_page_recover: + ao_terraui_recover(); + break; case ao_page_remote: ao_terraui_remote(); break; -- cgit v1.2.3 From 0669f0d74fc24c4f1925a45a9975b7a49a65b692 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 00:49:23 -0700 Subject: altosui: Only update GPS data when new GPS information arrives Track which telemetry packets are actually producing new GPS information and only update the GPS average position and count of stable GPS reports with new GPS info, instead of on every telemetry packet. Signed-off-by: Keith Packard --- altosui/AltosEepromIterable.java | 1 + altosui/AltosRecord.java | 3 +++ altosui/AltosState.java | 2 +- altosui/AltosTelemetryRecordLegacy.java | 6 +++++- altosui/AltosTelemetryRecordLocation.java | 1 + 5 files changed, 11 insertions(+), 2 deletions(-) diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index 812e5fc6..d8205816 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -177,6 +177,7 @@ public class AltosEepromIterable extends AltosRecordIterable { state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT; + state.new_gps = true; has_gps = true; break; case Altos.AO_LOG_GPS_LAT: diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 486c96b2..4dfa98be 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -65,6 +65,7 @@ public class AltosRecord implements Comparable { int flight_pres; AltosGPS gps; + boolean new_gps; double time; /* seconds since boost */ @@ -274,6 +275,7 @@ public class AltosRecord implements Comparable { speed = old.speed; height = old.height; gps = new AltosGPS(old.gps); + new_gps = false; companion = old.companion; } @@ -304,6 +306,7 @@ public class AltosRecord implements Comparable { speed = MISSING; height = MISSING; gps = new AltosGPS(); + new_gps = false; companion = null; } } diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 3d8e5e12..da498bc1 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -135,7 +135,7 @@ public class AltosState { time = tick / 100.0; - if (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle) { + if (cur.new_gps && (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle)) { /* Track consecutive 'good' gps reports, waiting for 10 of them */ if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java index f59027ab..f2f63358 100644 --- a/altosui/AltosTelemetryRecordLegacy.java +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -265,8 +265,10 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); - if (map.has(AO_TELEM_GPS_STATE)) + if (map.has(AO_TELEM_GPS_STATE)) { gps = new AltosGPS(map); + new_gps = true; + } else gps = null; } @@ -355,6 +357,7 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele } gps = new AltosGPS(words, i, version); + new_gps = true; } public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { @@ -467,6 +470,7 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { gps = new AltosGPS(); + new_gps = true; seen |= seen_gps_time | seen_gps_lat | seen_gps_lon; gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); diff --git a/altosui/AltosTelemetryRecordLocation.java b/altosui/AltosTelemetryRecordLocation.java index 76bd106e..80db454d 100644 --- a/altosui/AltosTelemetryRecordLocation.java +++ b/altosui/AltosTelemetryRecordLocation.java @@ -85,6 +85,7 @@ public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { next.gps.hdop = hdop; next.gps.vdop = vdop; next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; + next.new_gps = true; } return next; -- cgit v1.2.3 From a7b285ec0945830b8b31877115157ddd12d6a9fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 00:57:45 -0700 Subject: altos: Add i2c driver for avr chip Signed-off-by: Keith Packard --- src/avr/ao_i2c_usart.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/avr/ao_i2c_usart.c diff --git a/src/avr/ao_i2c_usart.c b/src/avr/ao_i2c_usart.c new file mode 100644 index 00000000..60e35f8c --- /dev/null +++ b/src/avr/ao_i2c_usart.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +/* + * Atmega32u4 TWI master mode (I2C) + */ + +__xdata uint8_t ao_i2c_mutex; + +/* Send bytes over I2C. + * + * This just polls; the I2C is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_i2c_send(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_i2c_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = *d++; + while (!(UCSR1A & (1 << RXC1))); + (void) UDR1; + } + ao_mutex_put(&ao_i2c_mutex); +} + +/* Receive bytes over I2C. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the I2C transmitter as that is what + * clocks the data coming in. + */ +void +ao_i2c_recv(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_i2c_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = 0; + while (!(UCSR1A & (1 << RXC1))); + *d++ = UDR1; + } + ao_mutex_put(&ao_i2c_mutex); +} + +#define XCK1_DDR DDRD +#define XCK1_PORT PORTD +#define XCK1 PORTD5 +#define XMS1_DDR DDRE +#define XMS1_PORT PORTE +#define XMS1 PORTE6 + +void +ao_i2c_init(void) +{ + /* Ensure the TWI is powered */ + + /* + * Set pin directions + */ + XCK1_DDR |= (1 << XCK1); + + /* Clear chip select (which is negated) */ + XMS1_PORT |= (1 < XMS1); + XMS1_DDR |= (1 << XMS1); + + /* Set baud register to zero (required before turning transmitter on) */ + UBRR1 = 0; + + UCSR1C = ((0x3 << UMSEL10) | /* Master I2C mode */ + (0 << UCSZ10) | /* I2C mode 0 */ + (0 << UCPOL1)); /* I2C mode 0 */ + + /* Enable transmitter and receiver */ + UCSR1B = ((1 << RXEN1) | + (1 << TXEN1)); + + /* It says that 0 is a legal value; we'll see... */ + UBRR1 = 0; +} -- cgit v1.2.3 From df08b2f6de464f4546c1809b931eb4910d88b558 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 01:01:11 -0700 Subject: altos: A bunch of missing .gitignore files (mostly) Signed-off-by: Keith Packard --- ao-tools/ao-telem/.gitignore | 1 + src/.gitignore | 1 + src/avr-demo/.gitignore | 3 + src/telepyro-v0.1/.gitignore | 2 + src/telescience-v0.1/.gitignore | 2 + src/teleterra-v0.1/.gitignore | 2 + src/teleterra-v0.1/ao_pins.h | 217 ++++++++++++++++++++++++++++++++++++++++ src/test/run-full | 31 ++++++ src/test/run-noisy | 23 +++++ 9 files changed, 282 insertions(+) create mode 100644 ao-tools/ao-telem/.gitignore create mode 100644 src/.gitignore create mode 100644 src/avr-demo/.gitignore create mode 100644 src/telepyro-v0.1/.gitignore create mode 100644 src/telescience-v0.1/.gitignore create mode 100644 src/teleterra-v0.1/.gitignore create mode 100644 src/teleterra-v0.1/ao_pins.h create mode 100755 src/test/run-full create mode 100755 src/test/run-noisy diff --git a/ao-tools/ao-telem/.gitignore b/ao-tools/ao-telem/.gitignore new file mode 100644 index 00000000..5ab6f649 --- /dev/null +++ b/ao-tools/ao-telem/.gitignore @@ -0,0 +1 @@ +ao-telem diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 00000000..7a5d6ef5 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1 @@ +altitude.h diff --git a/src/avr-demo/.gitignore b/src/avr-demo/.gitignore new file mode 100644 index 00000000..e7d16343 --- /dev/null +++ b/src/avr-demo/.gitignore @@ -0,0 +1,3 @@ +avr-demo +avr-demo.hex +ao_product.h diff --git a/src/telepyro-v0.1/.gitignore b/src/telepyro-v0.1/.gitignore new file mode 100644 index 00000000..5166481c --- /dev/null +++ b/src/telepyro-v0.1/.gitignore @@ -0,0 +1,2 @@ +telepyro-v0.1* +ao_product.h diff --git a/src/telescience-v0.1/.gitignore b/src/telescience-v0.1/.gitignore new file mode 100644 index 00000000..dfccadf8 --- /dev/null +++ b/src/telescience-v0.1/.gitignore @@ -0,0 +1,2 @@ +telescience-v0.1* +ao_product.h diff --git a/src/teleterra-v0.1/.gitignore b/src/teleterra-v0.1/.gitignore new file mode 100644 index 00000000..447007ce --- /dev/null +++ b/src/teleterra-v0.1/.gitignore @@ -0,0 +1,2 @@ +teleterra-v0.1* +ao_product.h diff --git a/src/teleterra-v0.1/ao_pins.h b/src/teleterra-v0.1/ao_pins.h new file mode 100644 index 00000000..33de055e --- /dev/null +++ b/src/teleterra-v0.1/ao_pins.h @@ -0,0 +1,217 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef TELETERRA_V_0_1 + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 + #define HAS_RSSI 0 + #define HAS_AES 1 + + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define M25_CS_MASK 0xf + #define M25_MAX_CHIPS 4 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/test/run-full b/src/test/run-full new file mode 100755 index 00000000..50ab7b5b --- /dev/null +++ b/src/test/run-full @@ -0,0 +1,31 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test "$i" > run-out.full + +#./ao_flight_test_accel "$i" > run-out.accel +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.full" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.full" using 1:9 with lines lt 3 axes x1y1 title "full height",\ +"run-out.full" using 1:11 with lines lt 4 axes x1y2 title "full speed",\ +"run-out.full" using 1:13 with lines lt 5 axes x1y2 title "full accel",\ +"run-out.full" using 1:17 with lines lt 6 axes x1y1 title "full drogue",\ +"run-out.full" using 1:19 with lines lt 7 axes x1y1 title "full main" +pause mouse close +EOF +done \ No newline at end of file diff --git a/src/test/run-noisy b/src/test/run-noisy new file mode 100755 index 00000000..2e3cddc7 --- /dev/null +++ b/src/test/run-noisy @@ -0,0 +1,23 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test_noisy_accel "$i" > run-out.noisy + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.noisy" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.noisy" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.noisy" using 1:9 with lines lt 3 axes x1y1 title "noisy height",\ +"run-out.noisy" using 1:11 with lines lt 4 axes x1y2 title "noisy speed",\ +"run-out.noisy" using 1:13 with lines lt 5 axes x1y2 title "noisy accel",\ +"run-out.noisy" using 1:17 with lines lt 6 axes x1y1 title "noisy drogue",\ +"run-out.noisy" using 1:19 with lines lt 7 axes x1y1 title "noisy main" +pause mouse close +EOF +done \ No newline at end of file -- cgit v1.2.3 From 8266d8d39c0103e68ef3e476b9639574d9a48771 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 16:54:18 -0800 Subject: altos: Shrink code size of Skytraq NMEA parser Just mess around with the code to make it smaller. These patches save 173 bytes. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 62 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 6e65d651..d88ded8b 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -25,17 +25,17 @@ static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; -static __pdata uint8_t ao_gps_cksum; -static __pdata uint8_t ao_gps_error; +static __data uint8_t ao_gps_cksum; +static __data uint8_t ao_gps_error; __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; static __pdata uint16_t ao_gps_next_tick; -static __xdata struct ao_telemetry_location ao_gps_next; +static __pdata struct ao_telemetry_location ao_gps_next; static __pdata uint8_t ao_gps_date_flags; -static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; +static __pdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 #define STQ_E 0x0d, 0x0a @@ -68,34 +68,41 @@ static __code uint8_t ao_gps_config[] = { static void ao_gps_lexchar(void) { + char c; if (ao_gps_error) - ao_gps_char = '\n'; + c = '\n'; else - ao_gps_char = ao_serial_getchar(); - ao_gps_cksum ^= ao_gps_char; + c = ao_serial_getchar(); + ao_gps_cksum ^= c; + ao_gps_char = c; } void ao_gps_skip_field(void) { - while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + for (;;) { + char c = ao_gps_char; + if (c == ',' || c == '*' || c == '\n') + break; ao_gps_lexchar(); + } } void ao_gps_skip_sep(void) { - if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + char c = ao_gps_char; + if (c == ',' || c == '.' || c == '*') ao_gps_lexchar(); } -__pdata static uint8_t ao_gps_num_width; +__data static uint8_t ao_gps_num_width; static int16_t ao_gps_decimal(uint8_t max_width) { int16_t v; - __pdata uint8_t neg = 0; + uint8_t neg = 0; ao_gps_skip_sep(); if (ao_gps_char == '-') { @@ -105,9 +112,10 @@ ao_gps_decimal(uint8_t max_width) v = 0; ao_gps_num_width = 0; while (ao_gps_num_width < max_width) { - if (ao_gps_char < '0' || '9' < ao_gps_char) + uint8_t c = ao_gps_char; + if (c < (uint8_t) '0' || (uint8_t) '9' < c) break; - v = v * (int16_t) 10 + ao_gps_char - '0'; + v = v * 10 + (uint8_t) (c - (uint8_t) '0'); ao_gps_num_width++; ao_gps_lexchar(); } @@ -117,23 +125,25 @@ ao_gps_decimal(uint8_t max_width) } static uint8_t -ao_gps_hex(uint8_t max_width) +ao_gps_hex(void) { - uint8_t v, d; + uint8_t v; ao_gps_skip_sep(); v = 0; ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if ('0' <= ao_gps_char && ao_gps_char <= '9') - d = ao_gps_char - '0'; - else if ('A' <= ao_gps_char && ao_gps_char <= 'F') - d = ao_gps_char - 'A' + 10; - else if ('a' <= ao_gps_char && ao_gps_char <= 'f') - d = ao_gps_char - 'a' + 10; + while (ao_gps_num_width < 2) { + uint8_t c = ao_gps_char; + uint8_t d; + if ((uint8_t) '0' <= c && c <= (uint8_t) '9') + d = - '0'; + else if ((uint8_t) 'A' <= c && c <= (uint8_t) 'F') + d = - 'A' + 10; + else if ((uint8_t) 'a' <= c && c <= (uint8_t) 'f') + d = - 'a' + 10; else break; - v = (v << 4) | d; + v = (v << 4) | (c + d); ao_gps_num_width++; ao_gps_lexchar(); } @@ -258,7 +268,7 @@ ao_nmea_gga() } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else ao_gps_error = 1; @@ -318,7 +328,7 @@ ao_nmea_gsv(void) } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else @@ -378,7 +388,7 @@ ao_nmea_rmc(void) } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else ao_gps_error = 1; -- cgit v1.2.3 From d3e8275572550b700563b3bde73cd7a43b608f17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 17:11:39 -0800 Subject: altos: shrink Skytraq NMEA parsing more This cuts another 78 bytes Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index d88ded8b..dd8d70ab 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -153,13 +153,15 @@ ao_gps_hex(void) static int32_t ao_gps_parse_pos(uint8_t deg_width) __reentrant { - int32_t d; - int32_t m; - int32_t f; + static __pdata uint16_t d; + static __pdata uint8_t m; + static __pdata uint16_t f; + char c; d = ao_gps_decimal(deg_width); m = ao_gps_decimal(2); - if (ao_gps_char == '.') { + c = ao_gps_char; + if (c == '.') { f = ao_gps_decimal(4); while (ao_gps_num_width < 4) { f *= 10; @@ -167,17 +169,14 @@ ao_gps_parse_pos(uint8_t deg_width) __reentrant } } else { f = 0; - if (ao_gps_char != ',') + if (c != ',') ao_gps_error = 1; } - d = d * 10000000l; - m = m * 10000l + f; - d = d + m * 50 / 3; - return d; + return d * 10000000l + (m * 10000l + f) * 50 / 3; } static uint8_t -ao_gps_parse_flag(char no_c, char yes_c) __reentrant +ao_gps_parse_flag(char no_c, char yes_c) { uint8_t ret = 0; ao_gps_skip_sep(); -- cgit v1.2.3 From 713bd503902526c17a7657c18be947ef8fa6a47a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 17:18:08 -0800 Subject: altos: Shrink Skytraq NMEA parsing - common nmea_finish code This shares the checksum testing across all three lines, saving another 103 bytes. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 59 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index dd8d70ab..1d457a1f 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -191,7 +191,27 @@ ao_gps_parse_flag(char no_c, char yes_c) } static void -ao_nmea_gga() +ao_nmea_finish(void) +{ + char c; + /* Skip remaining fields */ + for (;;) { + c = ao_gps_char; + if (c == '*' || c == '\n' || c == '\r') + break; + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (c == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex()) + ao_gps_error = 1; + } else + ao_gps_error = 1; +} + +static void +ao_nmea_gga(void) { uint8_t i; @@ -260,17 +280,8 @@ ao_nmea_gga() ao_gps_next.altitude = ao_gps_decimal(0xff); ao_gps_skip_field(); /* skip any fractional portion */ - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } else - ao_gps_error = 1; + ao_nmea_finish(); + if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; @@ -325,13 +336,9 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = i + 1; } } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } - else - ao_gps_error = 1; + + ao_nmea_finish(); + if (ao_gps_error) ao_gps_tracking_next.channels = 0; else if (done) { @@ -380,17 +387,9 @@ ao_nmea_rmc(void) a = ao_gps_decimal(2); c = ao_gps_decimal(2); i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } else - ao_gps_error = 1; + + ao_nmea_finish(); + if (!ao_gps_error) { ao_gps_next.year = i; ao_gps_next.month = c; -- cgit v1.2.3 From 7ecde50fbebe68a2e2200a2f8d081fd37074f840 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 22:24:22 -0800 Subject: altosui: Make UI Look&Feel configurable Saves the preferred style and uses that for all current and new windows. Signed-off-by: Keith Packard --- altosui/AltosBTManage.java | 2 +- altosui/AltosCSVUI.java | 2 +- altosui/AltosConfigFreqUI.java | 4 +- altosui/AltosConfigUI.java | 2 +- altosui/AltosConfigureUI.java | 102 ++++++++++++++++++++++++++++++++++++++- altosui/AltosDeviceDialog.java | 2 +- altosui/AltosDialog.java | 62 ++++++++++++++++++++++++ altosui/AltosEepromMonitor.java | 2 +- altosui/AltosEepromSelect.java | 2 +- altosui/AltosFlashUI.java | 2 +- altosui/AltosFlightUI.java | 2 +- altosui/AltosFrame.java | 56 +++++++++++++++++++++ altosui/AltosGraphUI.java | 2 +- altosui/AltosIdleMonitorUI.java | 10 +++- altosui/AltosIgniteUI.java | 2 +- altosui/AltosLaunchUI.java | 2 +- altosui/AltosPreferences.java | 42 +++++++++++++++- altosui/AltosRomconfigUI.java | 2 +- altosui/AltosScanUI.java | 2 +- altosui/AltosSiteMapPreload.java | 2 +- altosui/AltosUI.java | 4 +- altosui/AltosUIListener.java | 22 +++++++++ altosui/Makefile.am | 3 ++ 23 files changed, 312 insertions(+), 21 deletions(-) create mode 100644 altosui/AltosDialog.java create mode 100644 altosui/AltosFrame.java create mode 100644 altosui/AltosUIListener.java diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 10fdab3b..6d460701 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -32,7 +32,7 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosBTManage extends JDialog implements ActionListener, Iterable { +public class AltosBTManage extends AltosDialog implements ActionListener, Iterable { LinkedBlockingQueue found_devices; Frame frame; LinkedList listeners; diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index a212409e..6d3e9065 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -29,7 +29,7 @@ import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; public class AltosCSVUI - extends JDialog + extends AltosDialog implements ActionListener { JFileChooser csv_chooser; diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index 063d21b4..c6eabc53 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -30,7 +30,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -class AltosEditFreqUI extends JDialog implements ActionListener { +class AltosEditFreqUI extends AltosDialog implements ActionListener { Frame frame; JTextField frequency; JTextField description; @@ -165,7 +165,7 @@ class AltosEditFreqUI extends JDialog implements ActionListener { } } -public class AltosConfigFreqUI extends JDialog implements ActionListener { +public class AltosConfigFreqUI extends AltosDialog implements ActionListener { Frame frame; LinkedList listeners; diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index d20dd073..9fef8e3b 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -32,7 +32,7 @@ import java.util.concurrent.LinkedBlockingQueue; import libaltosJNI.*; public class AltosConfigUI - extends JDialog + extends AltosDialog implements ActionListener, ItemListener, DocumentListener { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 980068c0..06b5745c 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -19,6 +19,7 @@ package altosui; import java.awt.*; import java.awt.event.*; +import java.beans.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; @@ -28,9 +29,51 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import javax.swing.plaf.basic.*; + +class DelegatingRenderer implements ListCellRenderer { + + // ... + public static void install(JComboBox comboBox) { + DelegatingRenderer renderer = new DelegatingRenderer(comboBox); + renderer.initialise(); + comboBox.setRenderer(renderer); + } + + // ... + private final JComboBox comboBox; + + // ... + private ListCellRenderer delegate; + + // ... + private DelegatingRenderer(JComboBox comboBox) { + this.comboBox = comboBox; + } + + // ... + private void initialise() { + delegate = new JComboBox().getRenderer(); + comboBox.addPropertyChangeListener("UI", new PropertyChangeListener() { + + public void propertyChange(PropertyChangeEvent evt) { + delegate = new JComboBox().getRenderer(); + } + }); + } + + // ... + public Component getListCellRendererComponent(JList list, + Object value, int index, boolean isSelected, boolean cellHasFocus) { + + return delegate.getListCellRendererComponent(list, + ((UIManager.LookAndFeelInfo) value).getName(), + index, isSelected, cellHasFocus); + } +} public class AltosConfigureUI - extends JDialog + extends AltosDialog implements DocumentListener { JFrame owner; @@ -50,6 +93,9 @@ public class AltosConfigureUI JLabel font_size_label; JComboBox font_size_value; + JLabel look_and_feel_label; + JComboBox look_and_feel_value; + JRadioButton serial_debug; JButton manage_bluetooth; @@ -215,6 +261,60 @@ public class AltosConfigureUI pane.add(font_size_value, c); font_size_value.setToolTipText("Font size used in telemetry window"); + /* Look & Feel setting */ + c.gridx = 0; + c.gridy = row; + c.gridwidth = 1; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + pane.add(new JLabel("Look & feel"), c); + + class LookAndFeelRenderer extends BasicComboBoxRenderer implements ListCellRenderer { + + public LookAndFeelRenderer() { + super(); + } + + public Component getListCellRendererComponent( + JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + setText(((UIManager.LookAndFeelInfo) value).getName()); + return this; + } + } + + final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); + + System.out.printf("look_and_feels %d\n", look_and_feels.length); + look_and_feel_value = new JComboBox(look_and_feels); + + DelegatingRenderer.install(look_and_feel_value); + + String look_and_feel = AltosPreferences.look_and_feel(); + for (int i = 0; i < look_and_feels.length; i++) + if (look_and_feel.equals(look_and_feels[i].getClassName())) + look_and_feel_value.setSelectedIndex(i); + + look_and_feel_value.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int id = look_and_feel_value.getSelectedIndex(); + + AltosPreferences.set_look_and_feel(look_and_feels[id].getClassName()); + } + }); + c.gridx = 1; + c.gridy = row++; + c.gridwidth = 2; + c.fill = GridBagConstraints.BOTH; + c.anchor = GridBagConstraints.WEST; + pane.add(look_and_feel_value, c); + look_and_feel_value.setToolTipText("Look&feel used for new windows"); + /* Serial debug setting */ c.gridx = 0; c.gridy = row; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index 610bb73e..e53e75c1 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -24,7 +24,7 @@ import java.awt.*; import java.awt.event.*; import libaltosJNI.*; -public class AltosDeviceDialog extends JDialog implements ActionListener { +public class AltosDeviceDialog extends AltosDialog implements ActionListener { private AltosDevice value; private JList list; diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java new file mode 100644 index 00000000..c30b5757 --- /dev/null +++ b/altosui/AltosDialog.java @@ -0,0 +1,62 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +class AltosDialogListener extends WindowAdapter { + public void windowClosing (WindowEvent e) { + AltosPreferences.unregister_ui_listener((AltosDialog) e.getWindow()); + } +} + +public class AltosDialog extends JDialog implements AltosUIListener { + + public void ui_changed(String look_and_feel) { + SwingUtilities.updateComponentTreeUI(this); + this.pack(); + } + + public AltosDialog() { + AltosPreferences.register_ui_listener(this); + addWindowListener(new AltosDialogListener()); + } + + public AltosDialog(Frame frame, String label, boolean modal) { + super(frame, label, modal); + AltosPreferences.register_ui_listener(this); + addWindowListener(new AltosDialogListener()); + } + + public AltosDialog(Frame frame, boolean modal) { + super(frame, modal); + AltosPreferences.register_ui_listener(this); + addWindowListener(new AltosDialogListener()); + } +} diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index b9d913fa..34f5b891 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; -public class AltosEepromMonitor extends JDialog { +public class AltosEepromMonitor extends AltosDialog { Container pane; Box box; diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index 0a6eec17..ebafc4c8 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -62,7 +62,7 @@ class AltosEepromItem implements ActionListener { } } -public class AltosEepromSelect extends JDialog implements ActionListener { +public class AltosEepromSelect extends AltosDialog implements ActionListener { private JList list; private JFrame frame; JButton ok; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 3956ff20..39151641 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -29,7 +29,7 @@ import java.util.prefs.*; import java.util.concurrent.*; public class AltosFlashUI - extends JDialog + extends AltosDialog implements ActionListener { Container pane; diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index b44b9d43..d166c9ae 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -28,7 +28,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -public class AltosFlightUI extends JFrame implements AltosFlightDisplay, AltosFontListener { +public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; diff --git a/altosui/AltosFrame.java b/altosui/AltosFrame.java new file mode 100644 index 00000000..f8cc4f52 --- /dev/null +++ b/altosui/AltosFrame.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +class AltosFrameListener extends WindowAdapter { + public void windowClosing (WindowEvent e) { + AltosPreferences.unregister_ui_listener((AltosFrame) e.getWindow()); + } +} + +public class AltosFrame extends JFrame implements AltosUIListener { + + public void ui_changed(String look_and_feel) { + SwingUtilities.updateComponentTreeUI(this); + this.pack(); + } + + public AltosFrame() { + AltosPreferences.register_ui_listener(this); + addWindowListener(new AltosFrameListener()); + } + + public AltosFrame(String name) { + super(name); + AltosPreferences.register_ui_listener(this); + addWindowListener(new AltosFrameListener()); + } +} diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index 59e92499..c30dc476 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -20,7 +20,7 @@ import org.jfree.chart.axis.AxisLocation; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.RefineryUtilities; -public class AltosGraphUI extends JFrame +public class AltosGraphUI extends AltosFrame { JTabbedPane pane; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 988a797c..a5f41e25 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -255,7 +255,7 @@ class AltosIdleMonitor extends Thread { } } -public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { +public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosDevice device; JTabbedPane pane; AltosPad pad; @@ -289,6 +289,10 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { flightInfo.set_font(); } + public void font_size_changed(int font_size) { + set_font(); + } + public void show(AltosState state, int crc_errors) { try { pad.show(state, crc_errors); @@ -377,12 +381,16 @@ public class AltosIdleMonitorUI extends JFrame implements AltosFlightDisplay { bag.add(pane, c); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + + AltosPreferences.register_font_listener(this); + addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { disconnect(); setVisible(false); dispose(); + AltosPreferences.unregister_font_listener(AltosIdleMonitorUI.this); } }); diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index b215c228..8623cbef 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -30,7 +30,7 @@ import java.util.prefs.*; import java.util.concurrent.*; public class AltosIgniteUI - extends JDialog + extends AltosDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 47365e03..73fae16b 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -50,7 +50,7 @@ class FireButton extends JButton { } public class AltosLaunchUI - extends JDialog + extends AltosDialog implements ActionListener { AltosDevice device; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 48aed441..cc2b1a95 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -61,9 +61,12 @@ class AltosPreferences { /* Launcher serial preference name */ final static String launcherSerialPreference = "LAUNCHER-SERIAL"; - /* Launcher channel prefernce name */ + /* Launcher channel preference name */ final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + /* Look&Feel preference name */ + final static String lookAndFeelPreference = "LOOK-AND-FEEL"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -101,6 +104,10 @@ class AltosPreferences { static int font_size = Altos.font_size_medium; + static LinkedList ui_listeners; + + static String look_and_feel = null; + /* List of frequencies */ final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; static AltosFrequency[] common_frequencies; @@ -199,6 +206,10 @@ class AltosPreferences { AltosSerial.set_debug(serial_debug); common_frequencies = load_common_frequencies(); + + look_and_feel = preferences.get(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); + + ui_listeners = new LinkedList(); } static { init(); } @@ -390,6 +401,35 @@ class AltosPreferences { } } + public static void set_look_and_feel(String new_look_and_feel) { + look_and_feel = new_look_and_feel; + try { + UIManager.setLookAndFeel(look_and_feel); + } catch (Exception e) { + } + synchronized(preferences) { + preferences.put(lookAndFeelPreference, look_and_feel); + flush_preferences(); + for (AltosUIListener l : ui_listeners) + l.ui_changed(look_and_feel); + } + } + + public static String look_and_feel() { + return look_and_feel; + } + + public static void register_ui_listener(AltosUIListener l) { + synchronized(preferences) { + ui_listeners.add(l); + } + } + + public static void unregister_ui_listener(AltosUIListener l) { + synchronized (preferences) { + ui_listeners.remove(l); + } + } public static void set_serial_debug(boolean new_serial_debug) { serial_debug = new_serial_debug; AltosSerial.set_debug(serial_debug); diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index 7e21735c..e4e38c9c 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -29,7 +29,7 @@ import java.text.*; import java.util.prefs.*; public class AltosRomconfigUI - extends JDialog + extends AltosDialog implements ActionListener { Container pane; diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index df5c51d4..e188834e 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -102,7 +102,7 @@ class AltosScanResults extends LinkedList implements ListModel } public class AltosScanUI - extends JDialog + extends AltosDialog implements ActionListener { AltosUI owner; diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index aa07bebc..5de7a05e 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -212,7 +212,7 @@ class AltosSites extends Thread { } } -public class AltosSiteMapPreload extends JDialog implements ActionListener, ItemListener { +public class AltosSiteMapPreload extends AltosDialog implements ActionListener, ItemListener { AltosUI owner; AltosSiteMap map; diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 3e5bcf43..8799d560 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -30,7 +30,7 @@ import java.util.concurrent.*; import libaltosJNI.*; -public class AltosUI extends JFrame { +public class AltosUI extends AltosFrame { public AltosVoice voice = new AltosVoice(); public static boolean load_library(Frame frame) { @@ -519,7 +519,7 @@ public class AltosUI extends JFrame { public static void main(final String[] args) { try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + UIManager.setLookAndFeel(AltosPreferences.look_and_feel()); } catch (Exception e) { } /* Handle batch-mode */ diff --git a/altosui/AltosUIListener.java b/altosui/AltosUIListener.java new file mode 100644 index 00000000..7ee62afc --- /dev/null +++ b/altosui/AltosUIListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 interface AltosUIListener { + public void ui_changed(String look_and_feel); +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index c4d1e611..7cd383ac 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -110,6 +110,9 @@ altosui_JAVA = \ AltosTelemetry.java \ AltosTelemetryIterable.java \ AltosUI.java \ + AltosUIListener.java \ + AltosFrame.java \ + AltosDialog.java \ AltosWriter.java \ AltosDataPointReader.java \ AltosDataPoint.java \ -- cgit v1.2.3 From b132eefc5f63412bb4a98a4bb72b9055e40d5d42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 22:30:17 -0800 Subject: altos: Make ao_xmem funcs require __xdata void * instead of casting Having an explicit cast in the ao_xmem wrapper macros caused the compiler to generate garbage values for pdata addresses, making the upper byte 0x00 instead of the required 0xf0. Removing the casts from the ao_xmem macros exposed this problem, so a new PDATA_TO_XDATA macros was added, along with a CODE_TO_XDATA macro which serve to cast pointers, with suitable address modifications, so that things work again. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 18 ++++++++++++------ src/cc1111/ao_string.c | 23 +++++++++++++++-------- src/core/ao.h | 6 ++++++ src/core/ao_config.c | 2 +- src/core/ao_host.h | 4 ++++ src/core/ao_telemetry.c | 8 ++++---- src/drivers/ao_gps_skytraq.c | 5 ++--- 7 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index f0f0daae..001165fa 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -27,6 +27,12 @@ /* Convert a __data pointer into an __xdata pointer */ #define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) +/* Code and xdata use the same address space */ +#define CODE_TO_XDATA(a) ((__xdata void *) ((uint16_t) (a))) + +/* Pdata lives at the start of xdata */ +#define PDATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xf000)) + /* Stack runs from above the allocated __data space to 0xfe, which avoids * writing to 0xff as that triggers the stack overflow indicator */ @@ -228,18 +234,18 @@ ao_button_get(void) __critical; /* ao_string.c */ void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count); -#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcpy(d,s,c) _ao_xmemcpy(d,s,c) void -_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); +_ao_xmemset(__xdata void *dst, uint8_t value, uint8_t count); -#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) +#define ao_xmemset(d,v,c) _ao_xmemset(d,v,c) int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); -#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_string.c b/src/cc1111/ao_string.c index daa5c14b..3a07e47e 100644 --- a/src/cc1111/ao_string.c +++ b/src/cc1111/ao_string.c @@ -18,26 +18,33 @@ #include "ao.h" void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count) +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count) { - while (count--) - *dst++ = *src++; + while (count--) { + *(__xdata uint8_t *) dst = *(__xdata uint8_t *) src; + dst = (__xdata uint8_t *) dst + 1; + src = (__xdata uint8_t *) src + 1; + } } void -_ao_xmemset(__xdata uint8_t *dst, uint8_t v, uint8_t count) +_ao_xmemset(__xdata void *dst, uint8_t v, uint8_t count) { - while (count--) - *dst++ = v; + while (count--) { + *(__xdata uint8_t *) dst = v; + dst = (__xdata uint8_t *) dst + 1; + } } int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count) +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count) { while (count--) { - int8_t d = *a++ - *b++; + int8_t d = *(__xdata int8_t *) a - *(__xdata int8_t *) b; if (d) return d; + a = (__xdata int8_t *) a + 1; + b = (__xdata int8_t *) b + 1; } return 0; } diff --git a/src/core/ao.h b/src/core/ao.h index 9b8d3270..cbe2f8dc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -32,6 +32,12 @@ #ifndef DATA_TO_XDATA #define DATA_TO_XDATA(a) (a) #endif +#ifndef PDATA_TO_XDATA +#define PDATA_TO_XDATA(a) (a) +#endif +#ifndef CODE_TO_XDATA +#define CODE_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08cc79b1..f0a576ee 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -79,7 +79,7 @@ _ao_config_get(void) ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } diff --git a/src/core/ao_host.h b/src/core/ao_host.h index f2b2f0c9..6eb752c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -46,6 +46,10 @@ struct ao_adc { #define __code #define __reentrant +#define DATA_TO_XDATA(a) (a) +#define PDATA_TO_XDATA(a) (a) +#define CODE_TO_XDATA(a) (a) + enum ao_flight_state { ao_flight_startup = 0, ao_flight_idle = 1, diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index e66598d1..c68f1589 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -132,11 +132,11 @@ ao_send_configuration(void) telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; ao_xmemcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); + ao_config.callsign, + AO_MAX_CALLSIGN); ao_xmemcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); + CODE_TO_XDATA(ao_version), + AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); ao_telemetry_config_cur = ao_telemetry_config_max; } diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 1d457a1f..62909606 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -285,7 +285,7 @@ ao_nmea_gga(void) if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, PDATA_TO_XDATA(&ao_gps_next), sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -343,8 +343,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); + ao_xmemcpy(&ao_gps_tracking_data, PDATA_TO_XDATA(&ao_gps_tracking_next), sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); } -- cgit v1.2.3 From f6db11c3c87725c809c518f5f19b07325faf9c84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:10:18 -0800 Subject: altosui: Deal with serial port exceptions a bit better This catches a few exceptions and tries to make sure the serial port is closed afterwards. Signed-off-by: Keith Packard --- altosui/AltosDebug.java | 13 +++++++++++-- altosui/AltosFlashUI.java | 23 ++++++++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java index d18de80d..ce1cf5dd 100644 --- a/altosui/AltosDebug.java +++ b/altosui/AltosDebug.java @@ -163,7 +163,11 @@ public class AltosDebug extends AltosSerial { int i = 0; byte[] data = new byte[length]; while (i < length) { - String line = get_reply().trim(); + String line = get_reply(); + + if (line == null) + throw new IOException("Timeout in read_bytes"); + line = line.trim(); String tokens[] = line.split("\\s+"); for (int j = 0; j < tokens.length; j++) { if (!Altos.ishex(tokens[j]) || @@ -172,7 +176,12 @@ public class AltosDebug extends AltosSerial { String.format ("Invalid read_bytes reply \"%s\"", line)); try { - data[i + j] = (byte) Integer.parseInt(tokens[j], 16); + if (i + j >= length) + throw new IOException( + String.format + ("Invalid read_bytes reply \"%s\"", line)); + else + data[i + j] = (byte) Integer.parseInt(tokens[j], 16); } catch (NumberFormatException ne) { throw new IOException( String.format diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 39151641..704ce35c 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -247,7 +247,7 @@ public class AltosFlashUI flash.set_romconfig(ui.rom_config); flash.flash(); } - } catch (Exception ee) { + } catch (InterruptedException ee) { final Exception e = ee; System.out.printf("exception %s\n", e.toString()); SwingUtilities.invokeLater(new Runnable() { @@ -255,9 +255,26 @@ public class AltosFlashUI ui.exception(e); } }); + } catch (IOException ee) { + final Exception e = ee; + System.out.printf("exception %s\n", e.toString()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.exception(e); + } + }); + } catch (AltosSerialInUseException ee) { + final Exception e = ee; + System.out.printf("exception %s\n", e.toString()); + SwingUtilities.invokeLater(new Runnable() { + public void run() { + ui.exception(e); + } + }); + } finally { + if (flash != null) + flash.close(); } - if (flash != null) - flash.close(); } public flash_task(AltosFlashUI in_ui) { -- cgit v1.2.3 From ad41b5820c2e252627959e4627473f07784be23e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:29:38 -0800 Subject: altos: Build TeleTerra v0.2 by default Signed-off-by: Keith Packard --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 5da7c855..61b1a835 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,8 @@ SUBDIRS=\ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ - tidongle test telescience-v0.1 telepyro-v0.1 + tidongle test telescience-v0.1 telepyro-v0.1 \ + teleterra-v0.2 all: all-local all-recursive -- cgit v1.2.3 From 4de8bf6da4d725bb0514d032b0708c5cf420e8fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:30:56 -0800 Subject: altos: debounce buttons Provide API to clear out any button events that happen during startup, and then discard button events 'too close' together. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 3 +++ src/cc1111/ao_button.c | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 001165fa..eb8ce9be 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -231,6 +231,9 @@ ao_button_init(void); char ao_button_get(void) __critical; +void +ao_button_clear(void) __critical; + /* ao_string.c */ void diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 77a8dde8..69f3475f 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -36,11 +36,17 @@ static __code struct { #define NUM_BUTTONS ((sizeof ao_buttons) / sizeof (ao_buttons[0])) +static __xdata uint16_t ao_button_tick[NUM_BUTTONS]; + static void ao_button_insert(char n) { - ao_fifo_insert(ao_button_fifo, n); - ao_wakeup(&ao_button_fifo); + uint16_t now = ao_time(); + if ((now - ao_button_tick[n]) > 20) { + ao_button_tick[n] = now; + ao_fifo_insert(ao_button_fifo, n); + ao_wakeup(&ao_button_fifo); + } } static void @@ -77,6 +83,15 @@ ao_button_get(void) __critical return b; } +void +ao_button_clear(void) __critical +{ + char b; + + while (!ao_fifo_empty(ao_button_fifo)) + ao_fifo_remove(ao_button_fifo, b); +} + void ao_p0_isr(void) ao_arch_interrupt(13) { -- cgit v1.2.3 From 0a705b62829d492e3a48c81077907cee61afb860 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:31:46 -0800 Subject: altos: Initialize DMA config address at boot time Instead of resetting these each time a transfer is started, just set them once at boot time. Signed-off-by: Keith Packard --- src/cc1111/ao_dma.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c index 6052964a..ca33facb 100644 --- a/src/cc1111/ao_dma.c +++ b/src/cc1111/ao_dma.c @@ -46,6 +46,10 @@ ao_dma_alloc(__xdata uint8_t *done) DMAIRQ = 0; DMAIF = 0; IEN1 |= IEN1_DMAIE; + DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; + DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); + DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; + DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); } return id; @@ -69,13 +73,6 @@ ao_dma_set_transfer(uint8_t id, ao_dma_config[id].len_low = count; ao_dma_config[id].cfg0 = cfg0; ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; - if (id == 0) { - DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; - DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); - } else { - DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; - DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); - } } #define nop() _asm nop _endasm; @@ -85,9 +82,11 @@ ao_dma_start(uint8_t id) { uint8_t mask = (1 << id); DMAIRQ &= ~mask; - DMAARM = 0x80 | mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); + if (DMAARM & mask) { + DMAARM = 0x80 | mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + } *(ao_dma_done[id]) = 0; DMAARM = mask; nop(); nop(); nop(); nop(); -- cgit v1.2.3 From 2bce71eba9f44b6fcf64e307c8174824c3a0fb57 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:32:49 -0800 Subject: altos: Set SPI fill value each time it is used. This ensures that the final MOSI pin value will be high after a receive is finished. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index fbe613c7..1fa8e128 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -28,7 +28,7 @@ __xdata uint8_t ao_spi_dma_out_done; uint8_t ao_spi_dma_out_id; uint8_t ao_spi_dma_in_id; -static __xdata uint8_t ao_spi_const = 0xff; +static __xdata uint8_t ao_spi_const; /* Send bytes over SPI. * @@ -89,6 +89,8 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_DESTINC_1 | DMA_CFG1_PRIORITY_NORMAL); + ao_spi_const = 0xff; + ao_dma_set_transfer(ao_spi_dma_out_id, &ao_spi_const, &U0DBUFXADDR, -- cgit v1.2.3 From ef7f86453d686a49882e8c1b88a59228c4c631a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:37:53 -0800 Subject: altos: Check pdata+xdata memory usage during build The sdcc linker doesn't check the sum of pdata+xdata memory usage, it only ensures that xdata itself is small enough. This doesn't keep xdata below the end of usable ram on the cc1111 though (0xfe000). Fix up the check-stack program to also make sure all of xdata fits in available memory. Signed-off-by: Keith Packard --- src/product/Makefile.telebt | 2 +- src/product/Makefile.teledongle | 2 +- src/product/Makefile.telelaunch | 2 +- src/product/Makefile.telemetrum | 2 +- src/product/Makefile.telemini | 2 +- src/product/Makefile.telenano | 2 +- src/teleballoon-v1.1/Makefile | 2 +- src/teleterra-v0.2/Makefile | 5 +---- src/tidongle/Makefile | 2 +- src/util/check-stack | 10 ++++++++-- 10 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 8f7c7429..ea18ff18 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index c1b422c0..cf33d1f1 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index b40f61a2..97764517 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -84,7 +84,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 40fc6bc2..52c723ca 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -94,7 +94,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 9f90b01f..75beeae4 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -83,7 +83,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index eff3ea97..b30ca789 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -82,7 +82,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile index 89471cf4..fb88787b 100644 --- a/src/teleballoon-v1.1/Makefile +++ b/src/teleballoon-v1.1/Makefile @@ -103,7 +103,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 583805f6..0747bfbf 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -25,9 +25,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_rssi.c \ ao_sqrt.c \ - ao_state.c \ ao_stdio.c \ ao_storage.c \ ao_task.c @@ -38,7 +36,6 @@ CC1111_SRC = \ ao_button.c \ ao_dbg.c \ ao_dma.c \ - ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ @@ -90,7 +87,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 58b9d735..698d612c 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -76,7 +76,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/util/check-stack b/src/util/check-stack index 1e8044e0..3b639d70 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -4,10 +4,16 @@ MEM=$2 HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` +XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' exit 1 -else - exit 0 fi +if [ "$XRAM_END" -ge 65024 ]; then + echo $XRAM_END | awk '{ printf ("Uses too much XRAM, 0x%x >= 0x%x\n", $1, 65024); }' + exit 1 +fi + +exit 0 + -- cgit v1.2.3 From 5972c642f0de0789e90268bfa19ef8b51c06eebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:44:36 -0800 Subject: altos: Handle internal and external telem monitoring requests Record separate internal vs external monitoring state, allowing both to happen at the same time, and when either is turned off, the other keeps working. This also adds disable/enable so that other radio users can temporarily take over the radio; monitoring will resume when the other radio user is finished. Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 4 +- src/cc1111/ao_packet_master.c | 5 +- src/cc1111/ao_pins.h | 5 ++ src/cc1111/ao_radio.c | 5 +- src/core/ao.h | 11 ++- src/core/ao_log_telem.c | 2 + src/core/ao_monitor.c | 151 ++++++++++++++++++----------------------- src/product/ao_telebt.c | 2 +- src/product/ao_teledongle.c | 2 +- src/product/ao_teleterra_0_2.c | 2 +- src/product/ao_tidongle.c | 2 +- src/teleterra-v0.2/ao_pins.h | 3 +- 12 files changed, 96 insertions(+), 98 deletions(-) diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 41fbbe1f..e263f0db 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -78,7 +78,7 @@ radio_cmac_send(uint8_t len) __reentrant ao_config_get(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif ao_mutex_get(&ao_aes_mutex); @@ -107,7 +107,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant len = round_len(len); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif if (timeout) ao_alarm(timeout); diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index ab19f979..66f94288 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -114,7 +114,7 @@ ao_packet_forward(void) __reentrant flush(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); @@ -132,6 +132,9 @@ ao_packet_forward(void) __reentrant ao_wakeup(&ao_stdin_ready); ao_delay(AO_MS_TO_TICKS(10)); } +#if HAS_MONITOR + ao_monitor_enable(); +#endif } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 7c5b4574..2b6232a4 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -107,6 +107,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -218,6 +219,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -245,6 +247,7 @@ #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -274,6 +277,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -312,6 +316,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 75f241d4..ee506f89 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -421,7 +421,7 @@ ao_radio_test(void) mode++; if ((mode & 2) && !radio_on) { #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); @@ -439,6 +439,9 @@ ao_radio_test(void) ao_radio_idle(); ao_radio_put(); radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif } } diff --git a/src/core/ao.h b/src/core/ao.h index cbe2f8dc..f57398ce 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1406,13 +1406,18 @@ ao_monitor(void); #define AO_MONITORING_OFF 0 #define AO_MONITORING_ORIG 1 -#define AO_MONITORING_TINY 2 void -ao_set_monitor(uint8_t monitoring); +ao_monitor_set(uint8_t monitoring); void -ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; +ao_monitor_disable(void); + +void +ao_monitor_enable(void); + +void +ao_monitor_init(void) __reentrant; /* * ao_stdio.c diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 096ad919..9e1b06d3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -90,6 +90,8 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); ao_flight_state = ao_flight_startup; + ao_monitor_set(sizeof(struct ao_telemetry_generic)); + for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index f7795fe4..7960208e 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -30,13 +30,35 @@ #define HAS_MONIOTOR_PUT 1 #endif +#ifndef AO_MONITOR_LED +#error Must define AO_MONITOR_LED +#endif + __data uint8_t ao_monitoring; -__pdata uint8_t ao_monitor_led; +static __data uint8_t ao_monitor_disabled; +static __data uint8_t ao_internal_monitoring; +static __data uint8_t ao_external_monitoring; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; +static void +_ao_monitor_adjust(void) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + if (ao_monitor_disabled) + ao_monitoring = 0; + else { + if (ao_external_monitoring) + ao_monitoring = ao_external_monitoring; + else + ao_monitoring = ao_internal_monitoring; + } + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); +} + void ao_monitor_get(void) { @@ -51,9 +73,6 @@ ao_monitor_get(void) case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; - case AO_MONITORING_TINY: - size = sizeof (struct ao_telemetry_tiny_recv); - break; #endif default: if (ao_monitoring > AO_MAX_TELEMETRY) @@ -68,16 +87,21 @@ ao_monitor_get(void) } } +#if AO_MONITOR_LED +__xdata struct ao_task ao_monitor_blink_task; + void ao_monitor_blink(void) { for (;;) { ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); + ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100)); } } +#endif #if HAS_MONITOR_PUT + void ao_monitor_put(void) { @@ -96,11 +120,15 @@ ao_monitor_put(void) ao_monitor_tail = ao_monitor_head; for (;;) { - while (ao_monitor_tail == ao_monitor_head) + while (!ao_external_monitoring) + ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); + while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { + case 0: + break; #if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -172,71 +200,6 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); -#if HAS_RSSI - ao_rssi_set(rssi); -#endif - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - case AO_MONITORING_TINY: - state = recv_tiny.telemetry_tiny.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_tiny.telemetry_tiny.serial, - recv_tiny.telemetry_tiny.flight, - rssi, - ao_state_names[state], - recv_tiny.telemetry_tiny.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_tiny.telemetry_tiny.adc.pres, - recv_tiny.telemetry_tiny.adc.temp, - recv_tiny.telemetry_tiny.adc.v_batt, - recv_tiny.telemetry_tiny.adc.sense_d, - recv_tiny.telemetry_tiny.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_BARO_GROUND " %d ", - recv_tiny.telemetry_tiny.ground_pres); - -#if 1 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d\n", - recv_tiny.telemetry_tiny.height, - recv_tiny.telemetry_tiny.speed, - recv_tiny.telemetry_tiny.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d\n", - recv_tiny.telemetry_tiny.flight_accel, - recv_tiny.telemetry_tiny.flight_vel, - recv_tiny.telemetry_tiny.flight_pres); -#endif #if HAS_RSSI ao_rssi_set(rssi); #endif @@ -265,43 +228,59 @@ ao_monitor_put(void) ao_usb_flush(); } } + __xdata struct ao_task ao_monitor_put_task; #endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_blink_task; void -ao_set_monitor(uint8_t monitoring) +ao_monitor_set(uint8_t monitoring) { - if (ao_monitoring) - ao_radio_recv_abort(); - ao_monitoring = monitoring; - ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); + ao_internal_monitoring = monitoring; + _ao_monitor_adjust(); } +void +ao_monitor_disable(void) +{ + ++ao_monitor_disabled; + _ao_monitor_adjust(); +} + +void +ao_monitor_enable(void) +{ + --ao_monitor_disabled; + _ao_monitor_adjust(); +} + +#if HAS_MONITOR_PUT static void set_monitor(void) { ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i); + ao_external_monitoring = ao_cmd_lex_i; + ao_wakeup(DATA_TO_XDATA(&ao_external_monitoring)); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + _ao_monitor_adjust(); } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, { 0, NULL }, }; +#endif void -ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +ao_monitor_init(void) __reentrant { - ao_monitor_led = monitor_led; - ao_monitoring = monitoring; - ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); #if HAS_MONITOR_PUT + ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); #endif - if (ao_monitor_led) - ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if AO_MONITOR_LED + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); +#endif } diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index c4b40dfc..97c9d792 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); #if HAS_LOG ao_report_init(); #endif diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index b8be9f45..49b80500 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -28,7 +28,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 6ce29894..1a268c99 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,7 +31,7 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); + ao_monitor_init(); ao_report_init(); ao_log_single_init(); ao_radio_init(); diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index 5adbb05c..a504a747 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -30,7 +30,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 9c35b06a..72ded004 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -39,13 +39,14 @@ #define HAS_COMPANION 0 + #define AO_MONITOR_LED 0 #define LEDS_AVAILABLE 0 #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 - #define HAS_MONITOR_PUT 0 + #define HAS_MONITOR_PUT 1 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 -- cgit v1.2.3 From 20282ef00afe70e3f3193f6f0200254cb2c33e93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:47:08 -0800 Subject: altos: Set default flight log max to 127k on TM v0.1 The flash part on v0.1 boards is only 128kB. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao_config.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 2b6232a4..ca85c39f 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -199,6 +199,7 @@ #define HAS_ACCEL 1 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 127 * (uint32_t) 1024) #endif #if defined(TELEDONGLE_V_0_1) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index f0a576ee..921a2480 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -34,11 +34,13 @@ __xdata uint8_t ao_config_mutex; #error Please define USE_INTERNAL_FLASH #endif #endif +#ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX #if USE_INTERNAL_FLASH #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #endif +#endif #if HAS_EEPROM static void -- cgit v1.2.3 From 2ba946fea29ff134ffaeaea9d7932f4bd4e953aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:48:07 -0800 Subject: altos: Export 'ao_cmd_is_white' for use by other code This function tests the current input character. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_cmd.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index f57398ce..2139983c 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -349,6 +349,9 @@ ao_cmd_put8(uint8_t v); void ao_cmd_put16(uint16_t v); +uint8_t +ao_cmd_is_white(void); + void ao_cmd_white(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 0c902f6b..14cb7569 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -121,10 +121,16 @@ ao_cmd_put8(uint8_t v) putnibble(v & 0xf); } +uint8_t +ao_cmd_is_white(void) +{ + return ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t'; +} + void ao_cmd_white(void) { - while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + while (ao_cmd_is_white()) ao_cmd_lex(); } -- cgit v1.2.3 From 75a8490a7bee2a2c7afd559b13f1d9c40c2aa08f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:49:17 -0800 Subject: altos: Add configurable set of channels for TT This adds the channel list for TT, which will be configured by AltosUI. Signed-off-by: Keith Packard --- src/core/ao.h | 17 ++++++++++++++- src/core/ao_config.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index 2139983c..3c1aa156 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1495,9 +1495,21 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 9 +#define AO_CONFIG_MINOR 10 #define AO_AES_LEN 16 +#if HAS_RADIO_CHANNELS +#define AO_CHANNEL_NAME_LEN 10 + +#define AO_NUM_CHANNELS 10 + +struct ao_radio_channel { + char name[AO_CHANNEL_NAME_LEN]; + uint32_t kHz; + uint32_t radio_setting; +}; +#endif + struct ao_config { uint8_t major; uint8_t minor; @@ -1514,6 +1526,9 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ +#if HAS_RADIO_CHANNELS + struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 921a2480..86bbc473 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -111,6 +111,15 @@ _ao_config_get(void) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); +#if HAS_RADIO_CHANNELS + if (ao_config.minor < 10) { + ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); + ao_xmemcpy(&ao_config.radio_channels[0].name[0], + CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); + ao_config.radio_channels[0].kHz = 434550; + ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; + } +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -448,6 +457,53 @@ ao_config_key_set(void) __reentrant } #endif +#if HAS_RADIO_CHANNELS +void +ao_config_radio_config_show(void) __reentrant +{ + uint8_t i; + for (i = 0; i < AO_NUM_CHANNELS; i++) + if (ao_config.radio_channels[i].name[0]) { + printf("%2d %-16.16s %ld %ld\n", + i, + ao_config.radio_channels[i].name, + ao_config.radio_channels[i].kHz, + ao_config.radio_channels[i].radio_setting); + } +} + +void +ao_config_radio_config_set(void) __reentrant +{ + __xdata struct ao_radio_channel * ch; + uint8_t i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; + _ao_config_edit_start(); + ao_cmd_white(); + i = 0; + while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { + ch->name[i++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + if (i < AO_CHANNEL_NAME_LEN) { + ch->name[i] = '\0'; + ao_cmd_lex(); + } + ao_cmd_decimal(); + ch->kHz = ao_cmd_lex_u32; + ao_cmd_decimal(); + ch->radio_setting = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -499,6 +555,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if HAS_RADIO_CHANNELS + { "C / \0Set radio chan config", + ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 430b439b9a5cc98b32273a233505de2c2f975c59 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:51:03 -0800 Subject: altosui: Add ao_lcd_cursor_on/off This shows or hides a blinking cursor on the LCD. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/drivers/ao_lcd.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/core/ao.h b/src/core/ao.h index 3c1aa156..8bd7a3d2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1719,6 +1719,12 @@ ao_lcd_contrast_set(uint8_t contrast); void ao_lcd_clear(void); +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + #define AO_LCD_ADDR(row,col) ((row << 6) | (col)) void diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 8745b3f6..8ce32233 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -73,6 +73,22 @@ ao_lcd_contrast_set(uint8_t contrast) ao_mutex_put(&ao_lcd_mutex); } +void +ao_lcd_cursor_on(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04 | 0x02 | 0x01); + ao_mutex_put(&ao_lcd_mutex); +} + +void +ao_lcd_cursor_off(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04); + ao_mutex_put(&ao_lcd_mutex); +} + void ao_lcd_clear(void) { -- cgit v1.2.3 From 0f7d7a4fbede63b51208bf051e08aa73dfbf35a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:51:31 -0800 Subject: altos: Remove LCD debugging code This isn't needed anymore. Signed-off-by: Keith Packard --- src/drivers/ao_lcd.c | 71 ---------------------------------------------------- 1 file changed, 71 deletions(-) diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 8ce32233..6def0c80 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -143,79 +143,8 @@ ao_lcd_start(void) ao_lcd_clear(); } -void -ao_lcd_contrast(void) -{ - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) { - printf("setting contrast to %02x\n", ao_cmd_lex_i); - ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); - } -} - -static uint8_t -ao_cmd_hex_nibble(void) -{ - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - return ao_cmd_lex_c - '0'; - if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - return ao_cmd_lex_c - ('a' - 10); - if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - return ao_cmd_lex_c - ('A' - 10); - ao_cmd_status = ao_cmd_syntax_error; - return 0; -} - -void -ao_lcd_string(void) -{ - uint8_t col = 0; - char c; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); - ao_cmd_white(); - while (ao_cmd_lex_c != '\n') { - c = ao_cmd_lex_c; - if (c == '\\') { - ao_cmd_lex(); - c = ao_cmd_hex_nibble() << 4; - ao_cmd_lex(); - c |= ao_cmd_hex_nibble(); - } - ao_lcd_put_byte(c); - ao_cmd_lex(); - col++; - } - while (col < 16) { - ao_lcd_put_byte(' '); - col++; - } -} - -void -ao_lcd_delay_set(void) -{ - ao_cmd_decimal(); - if (ao_cmd_status == ao_cmd_success) { - printf("setting LCD delay to %d\n", ao_cmd_lex_i); - ao_lcd_time = ao_cmd_lex_i; - } -} - -__code struct ao_cmds ao_lcd_cmds[] = { - { ao_lcd_start, "S\0Start LCD" }, - { ao_lcd_contrast, "C \0Set LCD contrast" }, - { ao_lcd_string, "s \0Send string to LCD" }, - { ao_lcd_delay_set, "t \0Set LCD delay" }, - { 0, NULL }, -}; - void ao_lcd_init(void) { ao_lcd_port_init(); - ao_cmd_register(&ao_lcd_cmds[0]); } -- cgit v1.2.3 From d3dcb9451f40506abced72783966104645a73bc7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:52:02 -0800 Subject: altos: Allow TT/TBT reports to escape landed state The TM altitude reporting code kept beeping out state and altitude forever, which isn't very useful on TBT or TT. Signed-off-by: Keith Packard --- src/core/ao_report.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 70f0b49d..7c928792 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -99,14 +99,10 @@ ao_report_altitude(void) agl /= 10; } while (agl); - for (;;) { - ao_report_beep(); - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); - pause(AO_SEC_TO_TICKS(5)); - } + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); } #if HAS_IGNITE_REPORT @@ -159,9 +155,14 @@ ao_report(void) { ao_report_state = ao_flight_state; for(;;) { - if (ao_flight_state == ao_flight_landed) - ao_report_altitude(); ao_report_beep(); + if (ao_flight_state == ao_flight_landed) { + ao_report_altitude(); +#if HAS_FLIGHT + ao_delay(AO_SEC_TO_TICKS(5)); + continue; +#endif + } #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); @@ -173,11 +174,10 @@ ao_report(void) pause(AO_MS_TO_TICKS(100)); } #endif - __critical { - while (ao_report_state == ao_flight_state) - ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; - } + + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; } } -- cgit v1.2.3 From 7f9e76e0d3492dcc8bf4b5b1f07c3c727cfdc0ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:54:14 -0800 Subject: altos: Trim skytraq NMEA messages. Shrink NMEA header matching code Tell the skytraq to not bother sending a bunch of the NMEA messages that we don't parse. Explicitly look for 'G' follows by 'P' instead of having some general header matching code. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 62909606..050573e8 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -19,10 +19,6 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 2 - -static __code char ao_gps_header[] = "GP"; - __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; static __data uint8_t ao_gps_cksum; @@ -50,7 +46,7 @@ static __pdata struct ao_telemetry_satellite ao_gps_tracking_next; (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E static __code uint8_t ao_gps_config[] = { - SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + SKYTRAQ_MSG_8(0x08, 1, 0, 1, 0, 1, 0, 0, 0), /* configure nmea */ /* gga interval */ /* gsa interval */ /* gsv interval */ @@ -418,11 +414,12 @@ ao_gps_nmea_parse(void) ao_gps_cksum = 0; ao_gps_error = 0; - for (a = 0; a < AO_GPS_LEADER; a++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[a]) - return; - } + ao_gps_lexchar(); + if (ao_gps_char != 'G') + return; + ao_gps_lexchar(); + if (ao_gps_char != 'P') + return; ao_gps_lexchar(); a = ao_gps_char; @@ -459,7 +456,6 @@ ao_gps(void) __reentrant if (ao_serial_getchar() == '$') { ao_gps_nmea_parse(); } - } } -- cgit v1.2.3 From e7044fd95472449e2fb860cef902fa458b91ccac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:18:23 -0800 Subject: altos: Fix sdcdb settings for telemetrum v1.0 Signed-off-by: Keith Packard --- src/telemetrum-v1.0/.sdcdbrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/telemetrum-v1.0/.sdcdbrc b/src/telemetrum-v1.0/.sdcdbrc index 710b4a2f..fbe9a599 100644 --- a/src/telemetrum-v1.0/.sdcdbrc +++ b/src/telemetrum-v1.0/.sdcdbrc @@ -1 +1 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. -- cgit v1.2.3 From 02b4e52a5349217df43105eaa1fff6bfc7dac4cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:18:53 -0800 Subject: altos: Enable packet master and debug in TT The code was already getting linked in, so we might as well use it. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 1a268c99..68f02596 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -35,7 +35,9 @@ main(void) ao_report_init(); ao_log_single_init(); ao_radio_init(); + ao_packet_master_init(); ao_config_init(); + ao_dbg_init(); ao_lcd_init(); ao_terraui_init(); ao_button_init(); -- cgit v1.2.3 From c1e293ff4953b51c19af8b52f2999419ea84e7e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:19:40 -0800 Subject: altos: Add startup and config (view only) pages to TT The config page needs a pile of work before it's useful. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 111 +++++++++++++++++++++++++------------------ src/teleterra-v0.2/ao_pins.h | 3 ++ 2 files changed, 68 insertions(+), 46 deletions(-) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 22bab5d6..05157cb1 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -88,6 +88,15 @@ static __code char ao_progress[4] = { '\011', '\012', '\014', '\013' }; static uint8_t ao_telem_progress; static uint8_t ao_gps_progress; +static void +ao_terraui_startup(void) +{ + sprintf(ao_lcd_line, "%-16.16s", ao_product); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "%-8.8s %5u ", ao_version, ao_serial_number); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + static void ao_terraui_info(void) { @@ -441,76 +450,85 @@ ao_terraui_local(void) __reentrant } static void -ao_terraui_config(void) +ao_terraui_config(void) __reentrant { + uint8_t chan; + uint32_t kHz; + uint16_t MHz; + uint16_t frac; + + for (chan = 0; chan < AO_NUM_CHANNELS; chan++) + if (ao_config.radio_channels[chan].radio_setting == ao_config.radio_setting) + break; + if (chan == AO_NUM_CHANNELS) + chan = 0; + kHz = ao_config.radio_channels[chan].kHz; + MHz = kHz / 1000; + frac = kHz % 1000; + sprintf(ao_lcd_line, "%2d: %-10.10s ", chan, ao_config.radio_channels[chan].name); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "%-8.8s %3d.%03d", ao_config.callsign, MHz, frac); + ao_terraui_line(AO_LCD_ADDR(1,0)); + ao_lcd_goto(AO_LCD_ADDR(0,1)); + ao_lcd_cursor_on(); } -enum ao_page { - ao_page_info, - ao_page_pad, - ao_page_ascent, - ao_page_descent, - ao_page_recover, - ao_page_remote, - ao_page_local, +static __code void (*__code ao_terraui_page[])(void) = { + ao_terraui_startup, + ao_terraui_info, + ao_terraui_pad, + ao_terraui_ascent, + ao_terraui_descent, + ao_terraui_recover, + ao_terraui_remote, + ao_terraui_local, + ao_terraui_config, }; +#define NUM_PAGE (sizeof (ao_terraui_page)/sizeof (ao_terraui_page[0])) + +__pdata uint8_t ao_current_page = 0; +__pdata uint8_t ao_shown_about = 3; + static void ao_terraui(void) { - enum ao_page cur_page = ao_page_info; - ao_lcd_start(); + + ao_delay(AO_MS_TO_TICKS(100)); + ao_button_clear(); + for (;;) { char b; - switch (cur_page) { - case ao_page_info: - ao_terraui_info(); - break; - case ao_page_pad: - ao_terraui_pad(); - break; - case ao_page_ascent: - ao_terraui_ascent(); - break; - case ao_page_descent: - ao_terraui_descent(); - break; - case ao_page_recover: - ao_terraui_recover(); - break; - case ao_page_remote: - ao_terraui_remote(); - break; - case ao_page_local: - ao_terraui_local(); - break; - } - + ao_terraui_page[ao_current_page](); ao_alarm(AO_SEC_TO_TICKS(1)); b = ao_button_get(); ao_clear_alarm(); + if (b > 0) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(10)); + ao_shown_about = 0; + } + switch (b) { case 0: + if (ao_shown_about) { + if (--ao_shown_about == 0) + ao_current_page = 2; + } break; case 1: - if (cur_page == ao_page_local) - cur_page = ao_page_info; - else - cur_page++; - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(50)); + ao_current_page++; + if (ao_current_page >= NUM_PAGE) + ao_current_page = 0; break; case 2: - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); break; case 3: - if (cur_page == ao_page_info) - cur_page = ao_page_local; - else - cur_page--; - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + if (ao_current_page == 0) + ao_current_page = NUM_PAGE; + ao_current_page--; break; } } @@ -524,6 +542,7 @@ ao_terramonitor(void) uint8_t monitor; monitor = ao_monitor_head; + ao_monitor_set(sizeof (struct ao_telemetry_generic)); for (monitor = ao_monitor_head;; monitor = ao_monitor_ring_next(monitor)) { diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 72ded004..44a372cc 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -36,6 +36,7 @@ #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define HAS_RADIO_CHANNELS 1 #define HAS_COMPANION 0 @@ -66,6 +67,8 @@ #define BUTTON_3_REG 2 #define BUTTON_3_MASK (1 << 4) /* P2_4 */ + #define HAS_P2_ISR 1 + #define BATTERY_PIN 5 #endif -- cgit v1.2.3 From dbf7c0c59854e040b65f068069d80716f02fc1bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Nov 2011 23:03:22 -0800 Subject: altos: Fix pad orientation for pre-1.1 boards They use a different code path for accel as they don't have the VCC compensation code in place. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index b2b8e9f6..2bf9632f 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -182,6 +182,11 @@ ao_sample(void) if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = 0x7fff - ao_sample_accel; ao_adc->accel = ao_sample_accel; +#else + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; + } #endif #endif -- cgit v1.2.3 From 6baf6f41040f7b074d8cc84ef75e254c5d2b466b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Dec 2011 16:58:04 -0800 Subject: altosui: googleearth doesn't accept spaces between coordinates anymore it got pickier for some reason; let's not put spaces in now. Signed-off-by: Keith Packard --- altosui/AltosKML.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java index d586033f..6bdbecca 100644 --- a/altosui/AltosKML.java +++ b/altosui/AltosKML.java @@ -73,7 +73,7 @@ public class AltosKML implements AltosWriter { " \n"; static final String kml_coord_fmt = - " %12.7f, %12.7f, %12.7f \n"; + " %.7f,%.7f,%.7f \n"; static final String kml_placemark_end = " \n" + -- cgit v1.2.3 From eff8611e3eb19853b06acfcd7e978c9046cd5f78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Dec 2011 17:05:06 -0800 Subject: altos: Create TeleMetrum v1.2 directory The hardware is software-compatible with v1.1, but it's nice to have the right version number in all of the files. Signed-off-by: Keith Packard --- altosui/Makefile.am | 3 ++- altosui/altos-windows.nsi | 1 + doc/altusmetrum.xsl | 8 ++++---- src/Makefile | 2 +- src/cc1111/ao_pins.h | 37 +++++++++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 2 +- src/telemetrum-v1.2/.gitignore | 2 ++ src/telemetrum-v1.2/.sdcdbrc | 1 + src/telemetrum-v1.2/Makefile | 16 ++++++++++++++++ 9 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 src/telemetrum-v1.2/.gitignore create mode 100644 src/telemetrum-v1.2/.sdcdbrc create mode 100644 src/telemetrum-v1.2/Makefile diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 7cd383ac..fc024fff 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -171,7 +171,8 @@ FIRMWARE_TD=$(FIRMWARE_TD_0_2) FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1-$(VERSION).ihx -FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) +FIRMWARE_TM_1_2=$(top_srcdir)/src/telemetrum-v1.2-$(VERSION).ihx +FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) $(FIRMWARE_TM_1_2) FIRMWARE_TELEMINI_1_0=$(top_srcdir)/src/telemini-v1.0-$(VERSION).ihx FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index cbcb389d..e5e01d79 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -112,6 +112,7 @@ Section "TeleMetrum and TeleDongle Firmware" File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx" + File "../src/telemetrum-v1.2/telemetrum-v1.2-${VERSION}.ihx" File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx" File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 606c8b99..5c18fec3 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -586,7 +586,7 @@ NAR #88757, TRA #12200
Maximum Flight Log - TeleMetrum version 1.1 has 2MB of on-board flash storage, + TeleMetrum version 1.1 and 1.2 have 2MB of on-board flash storage, enough to hold over 40 minutes of data at full data rate (100 samples/second). TeleMetrum 1.0 has 1MB of on-board storage. As data are stored at a reduced rate during descent @@ -602,7 +602,7 @@ NAR #88757, TRA #12200 All of the configuration data is also stored in the flash - memory, which consumes 64kB on TeleMetrum v1.1 and 256B on + memory, which consumes 64kB on TeleMetrum v1.1/v1.2 and 256B on TeleMetrum v1.0. This configuration space is not available for storing flight log data. @@ -619,7 +619,7 @@ NAR #88757, TRA #12200 The default size, 192kB, allows for 10 flights of storage on - TeleMetrum v1.1 and 5 flights on TeleMetrum v1.0. This + TeleMetrum v1.1/v1.2 and 5 flights on TeleMetrum v1.0. This ensures that you won't need to erase the memory before flying each time while still allowing more than sufficient storage for each flight. @@ -1842,7 +1842,7 @@ NAR #88757, TRA #12200 Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible + name in the form telemetrum-v1.2-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find it. diff --git a/src/Makefile b/src/Makefile index 61b1a835..d3173254 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ - telemetrum-v1.1 telemetrum-v1.0 \ + telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index ca85c39f..a18c74c8 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -89,6 +89,43 @@ #define HAS_MONITOR 0 #endif +#if defined(TELEMETRUM_V_1_2) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if defined(TELEDONGLE_V_0_2) #define HAS_FLIGHT 0 #define HAS_USB 1 diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c68f1589..eb614b0f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/telemetrum-v1.2/.gitignore b/src/telemetrum-v1.2/.gitignore new file mode 100644 index 00000000..c2212151 --- /dev/null +++ b/src/telemetrum-v1.2/.gitignore @@ -0,0 +1,2 @@ +telemetrum-* +ao_product.h diff --git a/src/telemetrum-v1.2/.sdcdbrc b/src/telemetrum-v1.2/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.2/Makefile b/src/telemetrum-v1.2/Makefile new file mode 100644 index 00000000..4b650adf --- /dev/null +++ b/src/telemetrum-v1.2/Makefile @@ -0,0 +1,16 @@ +# +# AltOS build +# +# + +TM_VER=1.2 +TM_DEF=1_2 + +TM_INC = + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +include ../product/Makefile.telemetrum -- cgit v1.2.3 From 791c137728dd3398bd7275be13cc9e6be96d7af4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Dec 2011 15:37:28 -0800 Subject: altos: Add teleshield directory and bring-up code This is cobbled together from various existing bits, but should at least provide some ability to test a teleshield board. Signed-off-by: Keith Packard --- src/teleshield-v0.1/.gitignore | 2 + src/teleshield-v0.1/Makefile | 112 +++++++++++++++++++ src/teleshield-v0.1/ao_pins.h | 217 ++++++++++++++++++++++++++++++++++++ src/teleshield-v0.1/ao_teleshield.c | 48 ++++++++ 4 files changed, 379 insertions(+) create mode 100644 src/teleshield-v0.1/.gitignore create mode 100644 src/teleshield-v0.1/Makefile create mode 100644 src/teleshield-v0.1/ao_pins.h create mode 100644 src/teleshield-v0.1/ao_teleshield.c diff --git a/src/teleshield-v0.1/.gitignore b/src/teleshield-v0.1/.gitignore new file mode 100644 index 00000000..3ae78d33 --- /dev/null +++ b/src/teleshield-v0.1/.gitignore @@ -0,0 +1,2 @@ +teleshield-* +ao_product.h diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile new file mode 100644 index 00000000..58c2b65a --- /dev/null +++ b/src/teleshield-v0.1/Makefile @@ -0,0 +1,112 @@ +# +# TeleShield build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +TELESHIELD_VER=0.1 +TELESHIELD_DEF=0_1 + +TELESHIELD_INC = + +TELESHIELD_SRC = \ + ao_beep.c \ + ao_btm.c \ + ao_spi.c + +vpath %.c ..:../core:../cc1111:../drivers:../product:. +vpath %.h ..:../core:../cc1111:../drivers:../product:. +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h \ + $(TELESHIELD_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_state.c \ + ao_storage.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_intflash.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TELESHIELD_SRC) + +PRODUCT_SRC = \ + ao_teleshield.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teleshield-v$(TELESHIELD_VER)-$(VERSION).ihx +PRODUCT=TeleShield-v$(TELESHIELD_VER) +PRODUCT_DEF=-DTELESHIELD_V_$(TELESHIELD_DEF) +IDPRODUCT=0x0013 +CODESIZE=0x7800 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h new file mode 100644 index 00000000..cbedb238 --- /dev/null +++ b/src/teleshield-v0.1/ao_pins.h @@ -0,0 +1,217 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELESHIELD_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_LOG 0 + #define USE_INTERNAL_FLASH 1 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_RED + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 + #define LEGACY_MONITOR 0 + #define HAS_RSSI 0 + #define HAS_AES 0 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c new file mode 100644 index 00000000..fc203537 --- /dev/null +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_monitor_init(); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_AES + ao_aes_init(); + ao_radio_cmac_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 4783ac9653fd4f816f839452795e0d2e52129d5b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Dec 2011 15:47:54 -0800 Subject: altos: Switch teleshield to use radio slave mode And bring it up at startup time by default Signed-off-by: Keith Packard --- src/teleshield-v0.1/Makefile | 2 +- src/teleshield-v0.1/ao_pins.h | 4 ++-- src/teleshield-v0.1/ao_teleshield.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index 58c2b65a..b63a81d6 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -49,7 +49,7 @@ CC1111_SRC = \ ao_led.c \ ao_intflash.c \ ao_packet.c \ - ao_packet_master.c \ + ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index cbedb238..1f659739 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -37,8 +37,8 @@ #define DBG_ON_P0 0 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define AO_MONITOR_LED AO_LED_RED diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index fc203537..3e07a955 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -34,7 +34,7 @@ main(void) ao_usb_init(); ao_monitor_init(); ao_radio_init(); - ao_packet_master_init(); + ao_packet_slave_init(1); ao_btm_init(); #if HAS_DBG ao_dbg_init(); -- cgit v1.2.3 From bbb94a6a25a106316414a9a281e924f6c56e9f38 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 12:27:35 -0800 Subject: altos: SDCC 3.1 wants __at instead of at Older SDCC would accept __at, so just replace all occurances unconditionally. Signed-off-by: Keith Packard --- src/cc1111/cc1111.h | 162 ++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 11ea8bbb..70e8c9c7 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -442,12 +442,12 @@ __xdata __at (0xde17) volatile uint8_t USBCNTH; __xdata __at (0xde20) volatile uint8_t USBFIFO[12]; /* ADC Data register, low and high */ -__sfr at 0xBA ADCL; -__sfr at 0xBB ADCH; +__sfr __at 0xBA ADCL; +__sfr __at 0xBB ADCH; __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; /* ADC Control Register 1 */ -__sfr at 0xB4 ADCCON1; +__sfr __at 0xB4 ADCCON1; # define ADCCON1_EOC (1 << 7) /* conversion complete */ # define ADCCON1_ST (1 << 6) /* start conversion */ @@ -463,7 +463,7 @@ __sfr at 0xB4 ADCCON1; # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ /* ADC Control Register 2 */ -__sfr at 0xB5 ADCCON2; +__sfr __at 0xB5 ADCCON2; # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ @@ -498,7 +498,7 @@ __sfr at 0xB5 ADCCON2; /* ADC Control Register 3 */ -__sfr at 0xB6 ADCCON3; +__sfr __at 0xB6 ADCCON3; # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ @@ -533,13 +533,13 @@ __sfr at 0xB6 ADCCON3; * ADC configuration register, this selects which * GPIO pins are to be used as ADC inputs */ -__sfr at 0xF2 ADCCFG; +__sfr __at 0xF2 ADCCFG; /* * Watchdog timer */ -__sfr at 0xc9 WDCTL; +__sfr __at 0xc9 WDCTL; #define WDCTL_CLEAR_FIRST (0xa << 4) #define WDCTL_CLEAR_SECOND (0x5 << 4) @@ -556,9 +556,9 @@ __sfr at 0xc9 WDCTL; * Pin selectors, these set which pins are * using their peripheral function */ -__sfr at 0xF3 P0SEL; -__sfr at 0xF4 P1SEL; -__sfr at 0xF5 P2SEL; +__sfr __at 0xF3 P0SEL; +__sfr __at 0xF4 P1SEL; +__sfr __at 0xF5 P2SEL; #define P2SEL_PRI3P1_USART0 (0 << 6) #define P2SEL_PRI3P1_USART1 (1 << 6) @@ -585,9 +585,9 @@ __sfr at 0xF5 P2SEL; /* * For pins used as GPIOs, these set which are used as outputs */ -__sfr at 0xFD P0DIR; -__sfr at 0xFE P1DIR; -__sfr at 0xFF P2DIR; +__sfr __at 0xFD P0DIR; +__sfr __at 0xFE P1DIR; +__sfr __at 0xFF P2DIR; #define P2DIR_PRIP0_USART0_USART1 (0 << 6) #define P2DIR_PRIP0_USART1_USART0 (1 << 6) @@ -595,7 +595,7 @@ __sfr at 0xFF P2DIR; #define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) #define P2DIR_PRIP0_MASK (3 << 6) -__sfr at 0x8F P0INP; +__sfr __at 0x8F P0INP; /* Select between tri-state and pull up/down * for pins P0_0 - P0_7. @@ -617,7 +617,7 @@ __sfr at 0x8F P0INP; #define P0INP_MDP0_0_PULL (0 << 0) #define P0INP_MDP0_0_TRISTATE (1 << 0) -__sfr at 0xF6 P1INP; +__sfr __at 0xF6 P1INP; /* Select between tri-state and pull up/down * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are @@ -636,7 +636,7 @@ __sfr at 0xF6 P1INP; #define P1INP_MDP1_2_PULL (0 << 2) #define P1INP_MDP1_2_TRISTATE (1 << 2) -__sfr at 0xF7 P2INP; +__sfr __at 0xF7 P2INP; /* P2INP has three extra bits which are used to choose * between pull-up and pull-down when they are not tri-stated */ @@ -662,13 +662,13 @@ __sfr at 0xF7 P2INP; #define P2INP_MDP2_0_TRISTATE (1 << 0) /* GPIO interrupt status flags */ -__sfr at 0x89 P0IFG; -__sfr at 0x8A P1IFG; -__sfr at 0x8B P2IFG; +__sfr __at 0x89 P0IFG; +__sfr __at 0x8A P1IFG; +__sfr __at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) -__sfr at 0x8C PICTL; +__sfr __at 0x8C PICTL; #define PICTL_P2IEN (1 << 5) #define PICTL_P0IENH (1 << 4) #define PICTL_P0IENL (1 << 3) @@ -677,35 +677,35 @@ __sfr at 0x8C PICTL; #define PICTL_P0ICON (1 << 0) /* GPIO pins */ -__sfr at 0x80 P0; - -sbit at 0x80 P0_0; -sbit at 0x81 P0_1; -sbit at 0x82 P0_2; -sbit at 0x83 P0_3; -sbit at 0x84 P0_4; -sbit at 0x85 P0_5; -sbit at 0x86 P0_6; -sbit at 0x87 P0_7; - -__sfr at 0x90 P1; - -sbit at 0x90 P1_0; -sbit at 0x91 P1_1; -sbit at 0x92 P1_2; -sbit at 0x93 P1_3; -sbit at 0x94 P1_4; -sbit at 0x95 P1_5; -sbit at 0x96 P1_6; -sbit at 0x97 P1_7; - -__sfr at 0xa0 P2; - -sbit at 0xa0 P2_0; -sbit at 0xa1 P2_1; -sbit at 0xa2 P2_2; -sbit at 0xa3 P2_3; -sbit at 0xa4 P2_4; +__sfr __at 0x80 P0; + +sbit __at 0x80 P0_0; +sbit __at 0x81 P0_1; +sbit __at 0x82 P0_2; +sbit __at 0x83 P0_3; +sbit __at 0x84 P0_4; +sbit __at 0x85 P0_5; +sbit __at 0x86 P0_6; +sbit __at 0x87 P0_7; + +__sfr __at 0x90 P1; + +sbit __at 0x90 P1_0; +sbit __at 0x91 P1_1; +sbit __at 0x92 P1_2; +sbit __at 0x93 P1_3; +sbit __at 0x94 P1_4; +sbit __at 0x95 P1_5; +sbit __at 0x96 P1_6; +sbit __at 0x97 P1_7; + +__sfr __at 0xa0 P2; + +sbit __at 0xa0 P2_0; +sbit __at 0xa1 P2_1; +sbit __at 0xa2 P2_2; +sbit __at 0xa3 P2_3; +sbit __at 0xa4 P2_4; /* DMA controller */ struct cc_dma_channel { @@ -794,7 +794,7 @@ struct cc_dma_channel { * DMAARM - DMA Channel Arm */ -__sfr at 0xD6 DMAARM; +__sfr __at 0xD6 DMAARM; # define DMAARM_ABORT (1 << 7) # define DMAARM_DMAARM4 (1 << 4) @@ -807,7 +807,7 @@ __sfr at 0xD6 DMAARM; * DMAREQ - DMA Channel Start Request and Status */ -__sfr at 0xD7 DMAREQ; +__sfr __at 0xD7 DMAREQ; # define DMAREQ_DMAREQ4 (1 << 4) # define DMAREQ_DMAREQ3 (1 << 3) @@ -819,21 +819,21 @@ __sfr at 0xD7 DMAREQ; * DMA configuration 0 address */ -__sfr at 0xD5 DMA0CFGH; -__sfr at 0xD4 DMA0CFGL; +__sfr __at 0xD5 DMA0CFGH; +__sfr __at 0xD4 DMA0CFGL; /* * DMA configuration 1-4 address */ -__sfr at 0xD3 DMA1CFGH; -__sfr at 0xD2 DMA1CFGL; +__sfr __at 0xD3 DMA1CFGH; +__sfr __at 0xD2 DMA1CFGL; /* * DMAIRQ - DMA Interrupt Flag */ -__sfr at 0xD1 DMAIRQ; +__sfr __at 0xD1 DMAIRQ; # define DMAIRQ_DMAIF4 (1 << 4) # define DMAIRQ_DMAIF3 (1 << 3) @@ -846,8 +846,8 @@ __sfr at 0xD1 DMAIRQ; */ /* USART config/status registers */ -__sfr at 0x86 U0CSR; -__sfr at 0xF8 U1CSR; +__sfr __at 0x86 U0CSR; +__sfr __at 0xF8 U1CSR; # define UxCSR_MODE_UART (1 << 7) # define UxCSR_MODE_SPI (0 << 7) @@ -861,8 +861,8 @@ __sfr at 0xF8 U1CSR; # define UxCSR_ACTIVE (1 << 0) /* UART configuration registers */ -__sfr at 0xc4 U0UCR; -__sfr at 0xfb U1UCR; +__sfr __at 0xc4 U0UCR; +__sfr __at 0xfb U1UCR; # define UxUCR_FLUSH (1 << 7) # define UxUCR_FLOW_DISABLE (0 << 6) @@ -881,8 +881,8 @@ __sfr at 0xfb U1UCR; # define UxUCR_START_HIGH (1 << 0) /* USART General configuration registers (mostly SPI) */ -__sfr at 0xc5 U0GCR; -__sfr at 0xfc U1GCR; +__sfr __at 0xc5 U0GCR; +__sfr __at 0xfc U1GCR; # define UxGCR_CPOL_NEGATIVE (0 << 7) # define UxGCR_CPOL_POSITIVE (1 << 7) @@ -894,18 +894,18 @@ __sfr at 0xfc U1GCR; # define UxGCR_BAUD_E_SHIFT 0 /* USART data registers */ -__sfr at 0xc1 U0DBUF; +__sfr __at 0xc1 U0DBUF; __xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr at 0xf9 U1DBUF; +__sfr __at 0xf9 U1DBUF; __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; /* USART baud rate registers, M value */ -__sfr at 0xc2 U0BAUD; -__sfr at 0xfa U1BAUD; +__sfr __at 0xc2 U0BAUD; +__sfr __at 0xfa U1BAUD; /* Flash controller */ -__sfr at 0xAE FCTL; +__sfr __at 0xAE FCTL; #define FCTL_BUSY (1 << 7) #define FCTL_SWBSY (1 << 6) #define FCTL_CONTRD_ENABLE (1 << 4) @@ -913,22 +913,22 @@ __sfr at 0xAE FCTL; #define FCTL_ERASE (1 << 0) /* Flash write data. Write two bytes here */ -__sfr at 0xAF FWDATA; +__sfr __at 0xAF FWDATA; __xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; /* Flash write/erase address */ -__sfr at 0xAD FADDRH; -__sfr at 0xAC FADDRL; +__sfr __at 0xAD FADDRH; +__sfr __at 0xAC FADDRL; /* Flash timing */ -__sfr at 0xAB FWT; +__sfr __at 0xAB FWT; /* Radio */ -__sfr at 0xD9 RFD; -__xdata at (0xDFD9) volatile uint8_t RFDXADDR; +__sfr __at 0xD9 RFD; +__xdata __at (0xDFD9) volatile uint8_t RFDXADDR; -__sfr at 0xE9 RFIF; +__sfr __at 0xE9 RFIF; #define RFIF_IM_TXUNF (1 << 7) #define RFIF_IM_RXOVF (1 << 6) #define RFIF_IM_TIMEOUT (1 << 5) @@ -938,7 +938,7 @@ __sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) -__sfr at 0x91 RFIM; +__sfr __at 0x91 RFIM; #define RFIM_IM_TXUNF (1 << 7) #define RFIM_IM_RXOVF (1 << 6) #define RFIM_IM_TIMEOUT (1 << 5) @@ -948,7 +948,7 @@ __sfr at 0x91 RFIM; #define RFIM_IM_CCA (1 << 1) #define RFIM_IM_SFD (1 << 0) -__sfr at 0xE1 RFST; +__sfr __at 0xE1 RFST; #define RFST_SFSTXON 0x00 #define RFST_SCAL 0x01 @@ -1305,12 +1305,12 @@ __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; /* AES engine */ -__sfr at 0xB1 ENCDI; -__sfr at 0xB2 ENCDO; -__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; -__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; +__sfr __at 0xB1 ENCDI; +__sfr __at 0xB2 ENCDO; +__xdata __at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata __at (0xDFB2) volatile uint8_t ENCDOXADDR; -__sfr at 0xB3 ENCCCS; +__sfr __at 0xB3 ENCCCS; #define ENCCCS_MODE_CBC (0 << 4) #define ENCCCS_MODE_CFB (1 << 4) -- cgit v1.2.3 From 614ab6a991258a5caad0ca12ae35d0288a5b7503 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 15:38:32 -0800 Subject: altos: Clean up for SDCC 3.1 - more keywords _asm -> __asm sbit -> __sbit remove variables named 'data' Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 ++++---- src/cc1111/cc1111.h | 100 +++++++++++++++++++++++++-------------------------- src/core/ao.h | 12 +++---- 3 files changed, 63 insertions(+), 63 deletions(-) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index eb8ce9be..e6c27a1e 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -45,7 +45,7 @@ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) -#define ao_arch_nop() _asm nop _endasm +#define ao_arch_nop() __asm nop __endasm #define ao_arch_interrupt(n) __interrupt n #define ao_arch_naked_declare __naked @@ -106,7 +106,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Save current context */ #define ao_arch_save_regs() \ - _asm \ + __asm \ /* Push ACC first, as when restoring the context it must be restored \ * last (it is used to set the IE register). */ \ push ACC \ @@ -125,11 +125,11 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; push ar0 \ push ar1 \ push PSW \ - _endasm; \ + __endasm; \ PSW = 0; \ - _asm \ + __asm \ push _bp \ - _endasm + __endasm #define ao_arch_save_stack() { \ uint8_t stack_len; \ @@ -166,7 +166,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; *stack_ptr++ = *save_ptr++; \ while (--stack_len); \ \ - _asm \ + __asm \ pop _bp \ pop PSW \ pop ar1 \ @@ -193,7 +193,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Finally pop off the ACC, which was the first register saved. */ \ pop ACC \ ret \ - _endasm; \ + __endasm; \ } #define ao_arch_critical(b) __critical { b } diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 70e8c9c7..80d3fb70 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -42,14 +42,14 @@ __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) @@ -135,11 +135,11 @@ __sfr __at 0x87 PCON; /* Power Mode Control Register */ */ __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) @@ -152,8 +152,8 @@ sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically clea */ __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) @@ -171,13 +171,13 @@ __sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ */ __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 */ @@ -192,13 +192,13 @@ sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ */ __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) */ @@ -679,33 +679,33 @@ __sfr __at 0x8C PICTL; /* GPIO pins */ __sfr __at 0x80 P0; -sbit __at 0x80 P0_0; -sbit __at 0x81 P0_1; -sbit __at 0x82 P0_2; -sbit __at 0x83 P0_3; -sbit __at 0x84 P0_4; -sbit __at 0x85 P0_5; -sbit __at 0x86 P0_6; -sbit __at 0x87 P0_7; +__sbit __at 0x80 P0_0; +__sbit __at 0x81 P0_1; +__sbit __at 0x82 P0_2; +__sbit __at 0x83 P0_3; +__sbit __at 0x84 P0_4; +__sbit __at 0x85 P0_5; +__sbit __at 0x86 P0_6; +__sbit __at 0x87 P0_7; __sfr __at 0x90 P1; -sbit __at 0x90 P1_0; -sbit __at 0x91 P1_1; -sbit __at 0x92 P1_2; -sbit __at 0x93 P1_3; -sbit __at 0x94 P1_4; -sbit __at 0x95 P1_5; -sbit __at 0x96 P1_6; -sbit __at 0x97 P1_7; +__sbit __at 0x90 P1_0; +__sbit __at 0x91 P1_1; +__sbit __at 0x92 P1_2; +__sbit __at 0x93 P1_3; +__sbit __at 0x94 P1_4; +__sbit __at 0x95 P1_5; +__sbit __at 0x96 P1_6; +__sbit __at 0x97 P1_7; __sfr __at 0xa0 P2; -sbit __at 0xa0 P2_0; -sbit __at 0xa1 P2_1; -sbit __at 0xa2 P2_2; -sbit __at 0xa3 P2_3; -sbit __at 0xa4 P2_4; +__sbit __at 0xa0 P2_0; +__sbit __at 0xa1 P2_1; +__sbit __at 0xa2 P2_2; +__sbit __at 0xa3 P2_3; +__sbit __at 0xa4 P2_4; /* DMA controller */ struct cc_dma_channel { diff --git a/src/core/ao.h b/src/core/ao.h index 8bd7a3d2..1fbcf7df 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -376,7 +376,7 @@ struct ao_cmds { }; void -ao_cmd_register(__code struct ao_cmds *cmds); +ao_cmd_register(const __code struct ao_cmds *cmds); void ao_cmd_init(void); @@ -1352,10 +1352,10 @@ void ao_radio_set_packet(void); void -ao_radio_send(__xdata void *data, uint8_t size) __reentrant; +ao_radio_send(__xdata void *d, uint8_t size) __reentrant; uint8_t -ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; +ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; void ao_radio_recv_abort(void); @@ -1708,7 +1708,7 @@ ao_companion_init(void); /* ao_lcd.c */ void -ao_lcd_putchar(uint8_t data); +ao_lcd_putchar(uint8_t d); void ao_lcd_putstring(char *string); @@ -1739,14 +1739,14 @@ ao_lcd_init(void); /* ao_lcd_port.c */ void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); void ao_lcd_port_init(void); /* ao_aes.c */ -__xdata uint8_t ao_aes_mutex; +extern __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -- cgit v1.2.3 From 085625ff3992454b59583d95a3c415597c51f754 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 15:42:28 -0800 Subject: altos: More _asm -> __asm changes Missed a few last time Signed-off-by: Keith Packard --- src/cc1111/ao_dbg.c | 6 +++--- src/cc1111/ao_dma.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cc1111/ao_dbg.c b/src/cc1111/ao_dbg.c index d4c9567f..847b5aaf 100644 --- a/src/cc1111/ao_dbg.c +++ b/src/cc1111/ao_dbg.c @@ -22,10 +22,10 @@ static void ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { DBG_PORT = (DBG_PORT & ~msk) | (val & msk); - _asm + __asm nop nop - _endasm; + __endasm; } void @@ -187,7 +187,7 @@ ao_dbg_long_delay(void) uint8_t n; for (n = 0; n < 20; n++) - _asm nop _endasm; + __asm nop __endasm; } #define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c index ca33facb..8779ddf4 100644 --- a/src/cc1111/ao_dma.c +++ b/src/cc1111/ao_dma.c @@ -75,7 +75,7 @@ ao_dma_set_transfer(uint8_t id, ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; } -#define nop() _asm nop _endasm; +#define nop() __asm nop __endasm; void ao_dma_start(uint8_t id) -- cgit v1.2.3 From 7a42f2e0f145d2d520aed8e241fa39f7cb62b19f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:41:15 -0800 Subject: altos: Add support for UART0 in async mode And copy bytes from it to stdout. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 7 ++ src/cc1111/ao_serial.c | 5 +- src/cc1111/ao_serial0.c | 152 +++++++++++++++++++++++++++++++++++ src/core/ao.h | 29 +++++++ src/teleshield-v0.1/Makefile | 4 +- src/teleshield-v0.1/ao_ardu_serial.c | 38 +++++++++ src/teleshield-v0.1/ao_pins.h | 8 ++ src/teleshield-v0.1/ao_teleshield.c | 1 + 8 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/cc1111/ao_serial0.c create mode 100644 src/teleshield-v0.1/ao_ardu_serial.c diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index e6c27a1e..360b35c8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -251,4 +251,11 @@ _ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); #define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) +struct ao_serial_speed { + uint8_t baud; + uint8_t gcr; +}; + +extern const __code struct ao_serial_speed ao_serial_speeds[]; + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 82370c64..4d5b9abd 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -91,10 +91,7 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static __code struct { - uint8_t baud; - uint8_t gcr; -} ao_serial_speeds[] = { +const __code struct ao_serial_speed ao_serial_speeds[] = { /* [AO_SERIAL_SPEED_4800] = */ { /* .baud = */ 163, /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c new file mode 100644 index 00000000..140721b1 --- /dev/null +++ b/src/cc1111/ao_serial0.c @@ -0,0 +1,152 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + +void +ao_serial0_rx0_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_usart0_rx_fifo)) + ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); + ao_wakeup(&ao_usart0_rx_fifo); +} + +static __xdata uint8_t ao_serial0_tx0_started; + +static void +ao_serial0_tx0_start(void) +{ + if (!ao_fifo_empty(ao_usart0_tx_fifo) && + !ao_serial0_tx0_started) + { + ao_serial0_tx0_started = 1; + ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx0_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx0_started = 0; + ao_serial0_tx0_start(); + ao_wakeup(&ao_usart0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_usart0_rx_fifo)) + ao_sleep(&ao_usart0_rx_fifo); + ao_fifo_remove(ao_usart0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_usart0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); + ao_fifo_insert(ao_usart0_tx_fifo, c); + ao_serial0_tx0_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U1UCR |= UxUCR_FLUSH; + U1BAUD = ao_serial_speeds[speed].baud; + U1GCR = ao_serial_speeds[speed].gcr; +} + +void +ao_serial0_init(void) +{ +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +} diff --git a/src/core/ao.h b/src/core/ao.h index 1fbcf7df..494993f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -938,6 +938,35 @@ void ao_serial_init(void); #endif +#ifndef HAS_SERIAL_0 +#define HAS_SERIAL_0 0 +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx0_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx0_isr(void) ao_arch_interrupt(7); + +char +ao_serial0_getchar(void) __critical; + +void +ao_serial0_putchar(char c) __critical; + +void +ao_serial0_drain(void) __critical; + +void +ao_serial0_set_speed(uint8_t speed); + +void +ao_serial0_init(void); + +#endif + + /* * ao_spi.c */ diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index b63a81d6..a21a6052 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -53,6 +53,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ @@ -62,7 +63,8 @@ DRIVER_SRC = \ $(TELESHIELD_SRC) PRODUCT_SRC = \ - ao_teleshield.c + ao_teleshield.c \ + ao_ardu_serial.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c new file mode 100644 index 00000000..7d4dc0db --- /dev/null +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_ardu_serial_recv(void) +{ + char c; + + for (;;) { + c = ao_serial0_getchar(); + putchar (c); + } +} + +static __xdata struct ao_task ao_ardu_serial_recv_task; + +void +ao_ardu_serial_init (void) +{ + ao_serial0_init(); + ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); +} diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index 1f659739..a907e2a5 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -27,6 +27,10 @@ #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_0 1 + #define HAS_SERIAL_0_ALT_1 0 + #define HAS_SERIAL_0_ALT_2 1 + #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -214,4 +218,8 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +void +ao_ardu_serial_init (void); + + #endif /* _AO_PINS_H_ */ diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index 3e07a955..fd12ce7a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -43,6 +43,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 65b9b5d0d91fef2c7452dc77017f31f176672304 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:42:41 -0800 Subject: Build teleshield by default --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index d3173254..e5d0c960 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ SUBDIRS=\ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ tidongle test telescience-v0.1 telepyro-v0.1 \ - teleterra-v0.2 + teleterra-v0.2 teleshield-v0.1 all: all-local all-recursive -- cgit v1.2.3 From c6821ae734a7efaf2e069f6c5edf9605a9dbe125 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:46:25 -0800 Subject: altos: flush stdout when fifo from arduino serial port is empty This avoids leaving bytes pending inside altos Signed-off-by: Keith Packard --- src/core/ao.h | 4 ++++ src/teleshield-v0.1/ao_ardu_serial.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/core/ao.h b/src/core/ao.h index 494993f1..8c5335c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -943,6 +943,10 @@ ao_serial_init(void); #endif #if HAS_SERIAL_0 + +extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + void ao_serial0_rx0_isr(void) ao_arch_interrupt(2); diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7d4dc0db..7ff859af 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,6 +23,8 @@ ao_ardu_serial_recv(void) char c; for (;;) { + if (ao_fifo_empty(ao_usart0_rx_fifo)) + flush(); c = ao_serial0_getchar(); putchar (c); } -- cgit v1.2.3 From f450f8bc70f857053b26c4379f54a318062e89a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 22:27:59 -0800 Subject: altos: Set correct registers for serial0 baud oops. not going to work very well setting serial 1. Signed-off-by: Keith Packard --- src/cc1111/ao_serial0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c index 140721b1..e8c1eb35 100644 --- a/src/cc1111/ao_serial0.c +++ b/src/cc1111/ao_serial0.c @@ -94,9 +94,9 @@ ao_serial0_set_speed(uint8_t speed) ao_serial0_drain(); if (speed > AO_SERIAL_SPEED_57600) return; - U1UCR |= UxUCR_FLUSH; - U1BAUD = ao_serial_speeds[speed].baud; - U1GCR = ao_serial_speeds[speed].gcr; + U0UCR |= UxUCR_FLUSH; + U0BAUD = ao_serial_speeds[speed].baud; + U0GCR = ao_serial_speeds[speed].gcr; } void -- cgit v1.2.3 From 5d42ded7ebdb0c134c8dac61f41525c37d81ae61 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 13 Jan 2012 10:44:23 -0700 Subject: update turnon_telemetrum to v1.2, add more turnon scripts --- ao-bringup/turnon_telemetrum | 6 +++--- ao-bringup/turnon_teleshield | 48 ++++++++++++++++++++++++++++++++++++++++++++ ao-bringup/turnon_teleterra | 48 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 3 deletions(-) create mode 100755 ao-bringup/turnon_teleshield create mode 100755 ao-bringup/turnon_teleterra diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 47835c58..faf49d43 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -18,11 +18,11 @@ else exit 1 fi -echo "TeleMetrum v1.1 Turn-On and Calibration Program" +echo "TeleMetrum v1.2 Turn-On and Calibration Program" echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" echo echo "Expectations:" -echo "\tTeleMetrum v1.1 powered from USB" +echo "\tTeleMetrum v1.2 powered from USB" echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" echo "\t\twith coax from UHF to frequency counter" echo @@ -43,7 +43,7 @@ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE $AOLOAD --device 100 --cal $CAL_VALUE \ - /usr/share/altos/stable/telemetrum-v1.1*.ihx $SERIAL + /usr/share/altos/stable/telemetrum-v1.2*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_teleshield b/ao-bringup/turnon_teleshield new file mode 100755 index 00000000..e9f651fb --- /dev/null +++ b/ao-bringup/turnon_teleshield @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleShield v0.1 Turn-On and Calibration Program" +echo "Copyright 2012 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleShield v0.1 powered from USB" +echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from SMA to frequency counter" +echo +echo -n "TeleShield serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD -D 100 -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +$RAWLOAD -D 100 -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` + +echo "Programming flash with cal value " $CAL_VALUE +$AOLOAD -D 100 --cal $CAL_VALUE /home/bdale/debian/altos/src/teleshield-v0.1/*.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_teleterra b/ao-bringup/turnon_teleterra new file mode 100755 index 00000000..b63da2ff --- /dev/null +++ b/ao-bringup/turnon_teleterra @@ -0,0 +1,48 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleTerra v0.2 Turn-On and Calibration Program" +echo "Copyright 2012 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleTerra v0.2 powered from USB" +echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from SMA to frequency counter" +echo +echo -n "TeleTerra serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD -D 100 -r ao_led_blink.ihx +echo "LEDs should be blinking" +sleep 5 + +$RAWLOAD -D 100 -r ao_radio_xmit.ihx +echo -n "Generating RF carrier. Please enter measured frequency: " +read FREQ + +CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` + +echo "Programming flash with cal value " $CAL_VALUE +$AOLOAD -D 100 --cal $CAL_VALUE /home/bdale/debian/altos/src/teleterra-v0.2/*.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" -- cgit v1.2.3 From 1b4a4c7b6a0c3f93267f33482f490e7aa25c2158 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Jan 2012 10:40:30 -0800 Subject: doc: Add companion SPI message protocol doc Signed-off-by: Keith Packard --- doc/Makefile | 4 +- doc/companion.xsl | 347 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 doc/companion.xsl diff --git a/doc/Makefile b/doc/Makefile index 14bce5c9..6c77f0ee 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -10,8 +10,8 @@ RELNOTES=\ release-notes-1.0.1.html RELNOTES_XSL=$(RELNOTES:.html=.xsl) -HTML=altusmetrum.html altos.html telemetry.html $(RELNOTES) -PDF=altusmetrum.pdf altos.pdf telemetry.pdf +HTML=altusmetrum.html altos.html telemetry.html companion.html $(RELNOTES) +PDF=altusmetrum.pdf altos.pdf telemetry.pdf companion.pdf DOC=$(HTML) $(PDF) HTMLSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/html/docbook.xsl FOSTYLE=/usr/share/xml/docbook/stylesheet/docbook-xsl/fo/docbook.xsl diff --git a/doc/companion.xsl b/doc/companion.xsl new file mode 100644 index 00000000..1215d9af --- /dev/null +++ b/doc/companion.xsl @@ -0,0 +1,347 @@ + + + +
+ + AltOS Companion Port + Protocol Definitions + + Keith + Packard + + + 2012 + Keith Packard + + + + This document is released under the terms of the + + Creative Commons ShareAlike 3.0 + + license. + + + + + 0.1 + 13 January 2012 + Initial content + + + +
+ Companion Port + + Many Altus Metrum products come with an eight pin Micro MaTch + connector, called the Companion Port. This is often used to + program devices using a programming cable. However, it can also + be used to connect TeleMetrum to external companion boards + (hence the name). + + + The Companion Port provides two different functions: + + + Power. Both battery-level and 3.3V regulated power are + available. Note that the amount of regulated power is not + huge; TeleMetrum contains a 150mA regulator and uses, at + peak, about 120mA or so. For applications needing more than + a few dozen mA, placing a separate regulator on them and + using the battery for power is probably a good idea. + + + SPI. The flight computer operates as a SPI master, using + a protocol defined in this document. Companion boards + provide a matching SPI slave implementation which supplies + telemetry information for the radio downlink during flight + + + +
+
+ Companion SPI Protocol + + The flight computer implements a SPI master communications + channel over the companion port, and uses this to get + information about a connected companion board and then to get + telemetry data for transmission during flight. + + + At startup time, the flight computer sends a setup request + packet, and the companion board returns a board identifier, the + desired telemetry update period and the number of data channels + provided. The flight computer doesn't interpret the telemetry + data at all, simply packing it up and sending it over the link. + Telemetry packets are 32 bytes long, and companion packets use 8 + bytes as a header leaving room for a maximum of 12 16-bit data + values. + + + Because of the limits of the AVR processors used in the first + two companion boards, the SPI data rate is set to 187.5kbaud. + +
+
+ SPI Message Formats + This section first defines the command message format sent from + the flight computer to the companion board, and then the various + reply message formats for each type of command message. +
+ Command Message + + Companion Command Message + + + + + + + + Offset + Data Type + Name + Description + + + + + 0 + uint8_t + command + Command identifier + + + 1 + uint8_t + flight_state + Current flight computer state + + + 2 + uint16_t + tick + Flight computer clock (100 ticks/second) + + + 4 + uint16_t + serial + Flight computer serial number + + + 6 + uint16_t + flight + Flight number + + + 8 + + + +
+ + Companion Command Identifiers + + + + + + + Value + Name + Description + + + + + 1 + SETUP + Supply the flight computer with companion + information + + + 2 + FETCH + Return telemetry information + + + 3 + NOTIFY + Tell companion board when flight state + changes + + + +
+ + The flight computer will send a SETUP message shortly after + power-up and will then send FETCH messages no more often than + the rate specified in the SETUP reply. NOTIFY messages will be + sent whenever the flight state changes. + + + 'flight_state' records the current state of the flight, + whether on the pad, under power, coasting to apogee or + descending on the drogue or main chute. + + + 'tick' provides the current flight computer clock, which + be used to synchronize data recorded on the flight computer + with that recorded on the companion board in post-flight analysis. + + + 'serial' is the product serial number of the flight computer, + 'flight' is the flight sequence number. Together, these two + uniquely identify the flight and can be recorded with any + companion board data logging to associate the companion data + with the proper flight. + + + NOTIFY commands require no reply at all, they are used solely + to inform the companion board when the state of the flight, as + computed by the flight computer, changes. Companion boards can + use this to change data collection parameters, disabling data + logging until the flight starts and terminating it when the + flight ends. + +
+
+ SETUP reply message + + SETUP reply contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 0 + uint16_t + board_id + Board identifier + + + 2 + uint16_t + board_id_inverse + ~board_id—used to tell if a board is present + + + 4 + uint8_t + update_period + Minimum time (in 100Hz ticks) between FETCH commands + + + 5 + uint8_t + channels + Number of data channels to retrieve in FETCH command + + + 6 + + + +
+ + The SETUP reply contains enough information to uniquely + identify the companion board to the end user as well as for + the flight computer to know how many data values to expect in + reply to a FETCH command, and how often to fetch that data. + + + To detect the presence of a companion board, the flight + computer checks to make sure that board_id_inverse is the + bit-wise inverse of board_id. Current companion boards use + USB product ID as the board_id, but the flight computer does + not interpret this data and so it can be any value. + +
+
+ FETCH reply message + + FETCH reply contents + + + + + + + + Offset + Data Type + Name + Description + + + + + 0 + uint16_t + data0 + 0th data item + + + 2 + uint16_t + data1 + 1st data item + + + ... + + + +
+ + The FETCH reply contains arbitrary data to be reported over + the flight computer telemetry link. The number of 16-bit data items + must match the 'channels' value provided in the SETUP reply + message. + +
+
+
+ History and Motivation + + To allow cross-programming, the original TeleMetrum and + TeleDongle designs needed to include some kind of + connector. With that in place, adding the ability to connect + external cards to TeleMetrum was fairly simple. We set the + software piece of this puzzle aside until we had a companion + board to use. + + + The first companion board was TeleScience. Designed to collect + temperature data from the nose and fin of the airframe, the main + requirement for the companion port was that it be able to report + telemetry data during flight as a back-up in case the + TeleScience on-board data was lost. + + + The second companion board, TelePyro, provides 8 additional + channels for deployment, staging or other activities. To avoid + re-programming the TeleMetrum to use TelePyro, we decided to + provide enough information over the companion link for it to + independently control those channels. + + + Providing a standard, constant interface between the flight + computer and companion boards allows for the base flight + computer firmware to include support for companion boards. + +
+
-- cgit v1.2.3 From 77639dae0fb9975219c2e211ea6dd6c7965eeea2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Sep 2011 23:50:43 -0700 Subject: altos: Require callsign match in packet code Ignore packets with mismatching callsigns to avoid accidental connections between devices controlled by different stations. As a special case, if the device is configured with the default callsign (N0CALL), then let anyone connect. This allows configuration of new devices without needing to change the ground station callsign. Signed-off-by: Keith Packard --- src/cc1111/ao_packet.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index f502d67c..7eeb0710 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -68,6 +68,15 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return 0; + /* Accept packets with matching call signs, or any packet if + * our callsign hasn't been configured + */ + if (ao_xmemcmp(ao_rx_packet.packet.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN) != 0 && + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) + return 0; + /* SYN packets carry no data */ if (ao_rx_packet.packet.len == AO_PACKET_SYN) { rx_seq = ao_rx_packet.packet.seq; -- cgit v1.2.3 From 392a3107b9e9cc8c1ea51df6ff5ec54817adbc65 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 20:11:34 -0700 Subject: altosui: Restructure telemetry classes to be more sane * Make AltosTelemetryRecord be a class, rather than an interface. * Inherit from this for AltosTelemetryRecordLegacy and AltosTelemetryRecordRaw. * Remove bogus AltosTelemetryRecordGeneral class. Signed-off-by: Keith Packard --- altosui/AltosTelemetry.java | 2 +- altosui/AltosTelemetryRecord.java | 109 +++++++++++++- altosui/AltosTelemetryRecordGeneral.java | 43 ------ altosui/AltosTelemetryRecordLegacy.java | 248 ++++++++++++++++--------------- altosui/AltosTelemetryRecordRaw.java | 89 +---------- altosui/Makefile.am | 1 - 6 files changed, 241 insertions(+), 251 deletions(-) delete mode 100644 altosui/AltosTelemetryRecordGeneral.java diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index a05269f4..0052ef04 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -234,7 +234,7 @@ public class AltosTelemetry extends AltosRecord { final static String AO_TELEM_SAT_C_N_0 = "s_c"; static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { - AltosTelemetryRecord r = AltosTelemetryRecordGeneral.parse(line); + AltosTelemetryRecord r = AltosTelemetryRecord.parse(line); return r.update_state(previous); } diff --git a/altosui/AltosTelemetryRecord.java b/altosui/AltosTelemetryRecord.java index cfac309a..2e6b5ead 100644 --- a/altosui/AltosTelemetryRecord.java +++ b/altosui/AltosTelemetryRecord.java @@ -16,8 +16,113 @@ */ package altosui; +import java.lang.*; +import java.text.*; -public interface AltosTelemetryRecord { +public abstract class AltosTelemetryRecord { - public AltosRecord update_state(AltosRecord previous); + long received_time; + abstract public AltosRecord update_state(AltosRecord previous); + + static boolean cksum(int[] bytes) { + int sum = 0x5a; + for (int i = 1; i < bytes.length - 1; i++) + sum += bytes[i]; + sum &= 0xff; + return sum == bytes[bytes.length - 1]; + } + + final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); + final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); + final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; + + final static int packet_type_TM_sensor = 0x01; + final static int packet_type_Tm_sensor = 0x02; + final static int packet_type_Tn_sensor = 0x03; + final static int packet_type_configuration = 0x04; + final static int packet_type_location = 0x05; + final static int packet_type_satellite = 0x06; + final static int packet_type_companion = 0x07; + + static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + int[] bytes; + try { + bytes = Altos.hexbytes(hex); + } catch (NumberFormatException ne) { + throw new ParseException(ne.getMessage(), 0); + } + + /* one for length, one for checksum */ + if (bytes[0] != bytes.length - 2) + throw new ParseException(String.format("invalid length %d != %d\n", + bytes[0], + bytes.length - 2), 0); + if (!cksum(bytes)) + throw new ParseException(String.format("invalid line \"%s\"", hex), 0); + + int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; + int status = Altos.uint8(bytes, bytes.length - 2); + + if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) + throw new AltosCRCException(rssi); + + /* length, data ..., rssi, status, checksum -- 4 bytes extra */ + switch (bytes.length) { + case Altos.ao_telemetry_standard_len + 4: + int type = Altos.uint8(bytes, 4 + 1); + switch (type) { + case packet_type_TM_sensor: + case packet_type_Tm_sensor: + case packet_type_Tn_sensor: + r = new AltosTelemetryRecordSensor(bytes, rssi); + break; + case packet_type_configuration: + r = new AltosTelemetryRecordConfiguration(bytes); + break; + case packet_type_location: + r = new AltosTelemetryRecordLocation(bytes); + break; + case packet_type_satellite: + r = new AltosTelemetryRecordSatellite(bytes); + break; + case packet_type_companion: + r = new AltosTelemetryRecordCompanion(bytes); + break; + default: + r = new AltosTelemetryRecordRaw(bytes); + break; + } + break; + case Altos.ao_telemetry_0_9_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + case Altos.ao_telemetry_0_8_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + default: + throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); + } + r.received_time = System.currentTimeMillis(); + return r; + } + + public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + if (word[i].equals("TELEM")) + r = parse_hex(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } } diff --git a/altosui/AltosTelemetryRecordGeneral.java b/altosui/AltosTelemetryRecordGeneral.java deleted file mode 100644 index 722baba3..00000000 --- a/altosui/AltosTelemetryRecordGeneral.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -public class AltosTelemetryRecordGeneral { - - static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - String[] word = line.split("\\s+"); - int i =0; - if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(word[i++], "RSSI"); - throw new AltosCRCException(AltosParse.parse_int(word[i++])); - } - - if (word[i].equals("TELEM")) - r = AltosTelemetryRecordRaw.parse(word[i+1]); - else - r = new AltosTelemetryRecordLegacy(line); - return r; - } -} diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java index f2f63358..a72ebb0f 100644 --- a/altosui/AltosTelemetryRecordLegacy.java +++ b/altosui/AltosTelemetryRecordLegacy.java @@ -84,7 +84,7 @@ import java.util.HashMap; * */ -public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTelemetryRecord { +public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { /* * General header fields * @@ -232,152 +232,156 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele final static String AO_TELEM_SAT_SVID = "s_v"; final static String AO_TELEM_SAT_C_N_0 = "s_c"; + AltosRecord record; + private void parse_v4(String[] words, int i) throws ParseException { AltosTelemetryMap map = new AltosTelemetryMap(words, i); - callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); - serial = map.get_int(AO_TELEM_SERIAL, MISSING); - flight = map.get_int(AO_TELEM_FLIGHT, MISSING); - rssi = map.get_int(AO_TELEM_RSSI, MISSING); - state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); - tick = map.get_int(AO_TELEM_TICK, 0); + record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); + record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); + record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); + record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + record.tick = map.get_int(AO_TELEM_TICK, 0); /* raw sensor values */ - accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING); - pres = map.get_int(AO_TELEM_RAW_BARO, MISSING); - temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING); - batt = map.get_int(AO_TELEM_RAW_BATT, MISSING); - drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING); - main = map.get_int(AO_TELEM_RAW_MAIN, MISSING); + record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING); + record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING); + record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING); + record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING); + record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING); + record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING); /* sensor calibration information */ - ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING); - ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING); - accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING); - accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); + record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING); + record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING); + record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING); + record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); /* flight computer values */ - acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, MISSING, 1/16.0); - speed = map.get_double(AO_TELEM_KALMAN_SPEED, MISSING, 1/16.0); - height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); + record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); + record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); + record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); - flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); - flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); - flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); + record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); + record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); + record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING); if (map.has(AO_TELEM_GPS_STATE)) { - gps = new AltosGPS(map); - new_gps = true; + record.gps = new AltosGPS(map); + record.new_gps = true; } else - gps = null; + record.gps = null; } private void parse_legacy(String[] words, int i) throws ParseException { AltosParse.word (words[i++], "CALL"); - callsign = words[i++]; + record.callsign = words[i++]; AltosParse.word (words[i++], "SERIAL"); - serial = AltosParse.parse_int(words[i++]); + record.serial = AltosParse.parse_int(words[i++]); - if (version >= 2) { + if (record.version >= 2) { AltosParse.word (words[i++], "FLIGHT"); - flight = AltosParse.parse_int(words[i++]); + record.flight = AltosParse.parse_int(words[i++]); } else - flight = 0; + record.flight = 0; AltosParse.word(words[i++], "RSSI"); - rssi = AltosParse.parse_int(words[i++]); + record.rssi = AltosParse.parse_int(words[i++]); /* Older telemetry data had mis-computed RSSI value */ - if (version <= 2) - rssi = (rssi + 74) / 2 - 74; + if (record.version <= 2) + record.rssi = (record.rssi + 74) / 2 - 74; AltosParse.word(words[i++], "STATUS"); - status = AltosParse.parse_hex(words[i++]); + record.status = AltosParse.parse_hex(words[i++]); AltosParse.word(words[i++], "STATE"); - state = Altos.state(words[i++]); + record.state = Altos.state(words[i++]); - tick = AltosParse.parse_int(words[i++]); + record.tick = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "a:"); - accel = AltosParse.parse_int(words[i++]); + record.accel = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "p:"); - pres = AltosParse.parse_int(words[i++]); + record.pres = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "t:"); - temp = AltosParse.parse_int(words[i++]); + record.temp = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "v:"); - batt = AltosParse.parse_int(words[i++]); + record.batt = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "d:"); - drogue = AltosParse.parse_int(words[i++]); + record.drogue = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "m:"); - main = AltosParse.parse_int(words[i++]); + record.main = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "fa:"); - flight_accel = AltosParse.parse_int(words[i++]); + record.flight_accel = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "ga:"); - ground_accel = AltosParse.parse_int(words[i++]); + record.ground_accel = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "fv:"); - flight_vel = AltosParse.parse_int(words[i++]); + record.flight_vel = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "fp:"); - flight_pres = AltosParse.parse_int(words[i++]); + record.flight_pres = AltosParse.parse_int(words[i++]); /* Old TeleDongle code with kalman-reporting TeleMetrum code */ - if ((flight_vel & 0xffff0000) == 0x80000000) { - speed = ((short) flight_vel) / 16.0; - acceleration = flight_accel / 16.0; - height = flight_pres; - flight_vel = MISSING; - flight_pres = MISSING; - flight_accel = MISSING; + if ((record.flight_vel & 0xffff0000) == 0x80000000) { + record.speed = ((short) record.flight_vel) / 16.0; + record.acceleration = record.flight_accel / 16.0; + record.height = record.flight_pres; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; + record.flight_accel = AltosRecord.MISSING; } AltosParse.word(words[i++], "gp:"); - ground_pres = AltosParse.parse_int(words[i++]); + record.ground_pres = AltosParse.parse_int(words[i++]); - if (version >= 1) { + if (record.version >= 1) { AltosParse.word(words[i++], "a+:"); - accel_plus_g = AltosParse.parse_int(words[i++]); + record.accel_plus_g = AltosParse.parse_int(words[i++]); AltosParse.word(words[i++], "a-:"); - accel_minus_g = AltosParse.parse_int(words[i++]); + record.accel_minus_g = AltosParse.parse_int(words[i++]); } else { - accel_plus_g = ground_accel; - accel_minus_g = ground_accel + 530; + record.accel_plus_g = record.ground_accel; + record.accel_minus_g = record.ground_accel + 530; } - gps = new AltosGPS(words, i, version); - new_gps = true; + record.gps = new AltosGPS(words, i, record.version); + record.new_gps = true; } public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { String[] words = line.split("\\s+"); int i = 0; + record = new AltosRecord(); + 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); + record.rssi = AltosParse.parse_int(words[i++]); + throw new AltosCRCException(record.rssi); } if (words[i].equals("CALL")) { - version = 0; + record.version = 0; } else { AltosParse.word (words[i++], "VERSION"); - version = AltosParse.parse_int(words[i++]); + record.version = AltosParse.parse_int(words[i++]); } - if (version < 4) + if (record.version < 4) parse_legacy(words, i); else parse_v4(words, i); @@ -418,72 +422,74 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele static final int AO_GPS_COURSE_VALID = (1 << 7); public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { + record = new AltosRecord(); + bytes = in_bytes; - version = 4; + record.version = 4; adjust = 0; if (bytes.length == Altos.ao_telemetry_0_8_len + 4) { - serial = uint8(0); + record.serial = uint8(0); adjust = -1; } else - serial = uint16(0); - - seen = seen_flight | seen_sensor | seen_temp_volt | seen_deploy; - - callsign = string(62, 8); - flight = uint16(2); - rssi = in_rssi; - status = in_status; - state = uint8(4); - tick = uint16(21); - accel = int16(23); - pres = int16(25); - temp = int16(27); - batt = int16(29); - drogue = int16(31); - main = int16(33); + record.serial = uint16(0); + + record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy; + + record.callsign = string(62, 8); + record.flight = uint16(2); + record.rssi = in_rssi; + record.status = in_status; + record.state = uint8(4); + record.tick = uint16(21); + record.accel = int16(23); + record.pres = int16(25); + record.temp = int16(27); + record.batt = int16(29); + record.drogue = int16(31); + record.main = int16(33); - ground_accel = int16(7); - ground_pres = int16(15); - accel_plus_g = int16(17); - accel_minus_g = int16(19); + record.ground_accel = int16(7); + record.ground_pres = int16(15); + record.accel_plus_g = int16(17); + record.accel_minus_g = int16(19); if (uint16(11) == 0x8000) { - acceleration = int16(5); - speed = int16(9); - height = int16(13); - flight_accel = MISSING; - flight_vel = MISSING; - flight_pres = MISSING; + record.acceleration = int16(5); + record.speed = int16(9); + record.height = int16(13); + record.flight_accel = AltosRecord.MISSING; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; } else { - flight_accel = int16(5); - flight_vel = uint32(9); - flight_pres = int16(13); - acceleration = MISSING; - speed = MISSING; - height = MISSING; + record.flight_accel = int16(5); + record.flight_vel = uint32(9); + record.flight_pres = int16(13); + record.acceleration = AltosRecord.MISSING; + record.speed = AltosRecord.MISSING; + record.height = AltosRecord.MISSING; } - gps = null; + record.gps = null; int gps_flags = uint8(41); if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { - gps = new AltosGPS(); - new_gps = true; - - seen |= seen_gps_time | seen_gps_lat | seen_gps_lon; - gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); - gps.locked = (gps_flags & AO_GPS_VALID) != 0; - gps.connected = true; - gps.lat = uint32(42) / 1.0e7; - gps.lon = uint32(46) / 1.0e7; - gps.alt = int16(50); - gps.ground_speed = uint16(52) / 100.0; - gps.course = uint8(54) * 2; - gps.hdop = uint8(55) / 5.0; - gps.h_error = uint16(58); - gps.v_error = uint16(60); + record.gps = new AltosGPS(); + record.new_gps = true; + + record.seen |= record.seen_gps_time | record.seen_gps_lat | record.seen_gps_lon; + record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); + record.gps.locked = (gps_flags & AO_GPS_VALID) != 0; + record.gps.connected = true; + record.gps.lat = uint32(42) / 1.0e7; + record.gps.lon = uint32(46) / 1.0e7; + record.gps.alt = int16(50); + record.gps.ground_speed = uint16(52) / 100.0; + record.gps.course = uint8(54) * 2; + record.gps.hdop = uint8(55) / 5.0; + record.gps.h_error = uint16(58); + record.gps.v_error = uint16(60); int n_tracking_reported = uint8(70); if (n_tracking_reported > 12) @@ -494,22 +500,22 @@ public class AltosTelemetryRecordLegacy extends AltosRecord implements AltosTele n_tracking_actual++; } if (n_tracking_actual > 0) { - gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; + record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; n_tracking_actual = 0; for (int i = 0; i < n_tracking_reported; i++) { int svid = uint8(71 + i*2); int c_n0 = uint8(72 + i*2); if (svid != 0) - gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); + record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); } } } - time = 0.0; + record.time = 0.0; } public AltosRecord update_state(AltosRecord previous) { - return this; + return record; } } diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java index fb2b495c..08c85e85 100644 --- a/altosui/AltosTelemetryRecordRaw.java +++ b/altosui/AltosTelemetryRecordRaw.java @@ -21,94 +21,13 @@ import java.lang.*; import java.text.*; import java.util.HashMap; -public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { +public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { int[] bytes; int serial; int tick; int type; - final static int packet_type_TM_sensor = 0x01; - final static int packet_type_Tm_sensor = 0x02; - final static int packet_type_Tn_sensor = 0x03; - final static int packet_type_configuration = 0x04; - final static int packet_type_location = 0x05; - final static int packet_type_satellite = 0x06; - final static int packet_type_companion = 0x07; - - final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); - final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); - final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; - - static boolean cksum(int[] bytes) { - int sum = 0x5a; - for (int i = 1; i < bytes.length - 1; i++) - sum += bytes[i]; - sum &= 0xff; - return sum == bytes[bytes.length - 1]; - } - - public static AltosTelemetryRecord parse (String hex) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - int[] bytes; - try { - bytes = Altos.hexbytes(hex); - } catch (NumberFormatException ne) { - throw new ParseException(ne.getMessage(), 0); - } - - /* one for length, one for checksum */ - if (bytes[0] != bytes.length - 2) - throw new ParseException(String.format("invalid length %d != %d\n", - bytes[0], - bytes.length - 2), 0); - if (!cksum(bytes)) - throw new ParseException(String.format("invalid line \"%s\"", hex), 0); - - int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; - int status = Altos.uint8(bytes, bytes.length - 2); - - if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) - throw new AltosCRCException(rssi); - - /* length, data ..., rssi, status, checksum -- 4 bytes extra */ - switch (bytes.length) { - case Altos.ao_telemetry_standard_len + 4: - int type = Altos.uint8(bytes, 4 + 1); - switch (type) { - case packet_type_TM_sensor: - case packet_type_Tm_sensor: - case packet_type_Tn_sensor: - r = new AltosTelemetryRecordSensor(bytes, rssi); - break; - case packet_type_configuration: - r = new AltosTelemetryRecordConfiguration(bytes); - break; - case packet_type_location: - r = new AltosTelemetryRecordLocation(bytes); - break; - case packet_type_satellite: - r = new AltosTelemetryRecordSatellite(bytes); - break; - case packet_type_companion: - r = new AltosTelemetryRecordCompanion(bytes); - break; - default: - r = new AltosTelemetryRecordRaw(bytes); - break; - } - break; - case Altos.ao_telemetry_0_9_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - case Altos.ao_telemetry_0_8_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - default: - throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); - } - return r; - } + long received_time; public int int8(int off) { return Altos.int8(bytes, off + 1); @@ -151,4 +70,8 @@ public class AltosTelemetryRecordRaw implements AltosTelemetryRecord { next.tick = tick; return next; } + + public long received_time() { + return received_time; + } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index fc024fff..3138efac 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -86,7 +86,6 @@ altosui_JAVA = \ AltosRecordIterable.java \ AltosTelemetryReader.java \ AltosTelemetryRecord.java \ - AltosTelemetryRecordGeneral.java \ AltosTelemetryRecordRaw.java \ AltosTelemetryRecordSensor.java \ AltosTelemetryRecordConfiguration.java \ -- cgit v1.2.3 From 8610fdae8f47e1e8b6e8525227cc912664ecfafd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 22:04:13 -0700 Subject: altosui: Show time since last packet in flight status window Makes it easy to see when the UI is wedged, and when telemetry data are being successfully received. Signed-off-by: Keith Packard --- altosui/AltosFlightStatus.java | 18 +++++++++++++++++- altosui/AltosFlightUI.java | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index ed273384..45e55b4b 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -119,18 +119,31 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay value.setText(String.format("%d", state.data.rssi)); } public RSSI (GridBagLayout layout, int x) { - super (layout, x, "RSSI (dBm)"); + super (layout, x, "RSSI"); } } RSSI rssi; + class LastPacket extends FlightValue { + void show(AltosState state, int crc_errors) { + long secs = (System.currentTimeMillis() - state.report_time + 500) / 1000; + value.setText(String.format("%d", secs)); + } + public LastPacket(GridBagLayout layout, int x) { + super (layout, x, "Age"); + } + } + + LastPacket last_packet; + public void reset () { call.reset(); serial.reset(); flight.reset(); flight_state.reset(); rssi.reset(); + last_packet.reset(); } public void set_font () { @@ -139,6 +152,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay flight.set_font(); flight_state.set_font(); rssi.set_font(); + last_packet.set_font(); } public void show (AltosState state, int crc_errors) { @@ -147,6 +161,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay flight.show(state, crc_errors); flight_state.show(state, crc_errors); rssi.show(state, crc_errors); + last_packet.show(state, crc_errors); } public int height() { @@ -164,5 +179,6 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay flight = new Flight(layout, 2); flight_state = new FlightState(layout, 3); rssi = new RSSI(layout, 4); + last_packet = new LastPacket(layout, 5); } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index d166c9ae..dcf85277 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -28,6 +28,21 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +class AltosFlightStatusUpdate implements ActionListener { + + public AltosState saved_state; + AltosFlightStatus flightStatus; + + public void actionPerformed (ActionEvent e) { + if (saved_state != null) + flightStatus.show(saved_state, 0); + } + + public AltosFlightStatusUpdate (AltosFlightStatus in_flightStatus) { + flightStatus = in_flightStatus; + } +} + public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; AltosFlightReader reader; @@ -98,7 +113,11 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt set_font(); } + + AltosFlightStatusUpdate status_update; + public void show(AltosState state, int crc_errors) { + status_update.saved_state = state; JComponent tab = which_tab(state); try { pad.show(state, crc_errors); @@ -151,6 +170,8 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt AltosFreqList frequencies; JComboBox telemetries; + ActionListener show_timer; + public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { AltosPreferences.set_component(this); @@ -289,6 +310,10 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt thread = new AltosDisplayThread(this, voice, this, reader); + status_update = new AltosFlightStatusUpdate(flightStatus); + + new javax.swing.Timer(100, status_update).start(); + thread.start(); } -- cgit v1.2.3 From c2550d72aee371676d2f09316051567681e53a7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 22:05:04 -0700 Subject: altosui: Use ConcurrentHashMap for maps This data structure is accessed by multiple threads, so it needs to be re-entrant. Signed-off-by: Keith Packard --- altosui/AltosSiteMap.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index c258b3e5..63995c40 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -31,6 +31,7 @@ import java.util.prefs.*; import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; +import java.util.concurrent.*; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // preferred vertical step in a tile in naut. miles @@ -110,7 +111,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { return latlng(pt, scale_x, scale_y); } - HashMap mapTiles = new HashMap(); + ConcurrentHashMap mapTiles = new ConcurrentHashMap(); Point2D.Double centre; private Point2D.Double tileCoordOffset(Point p) { -- cgit v1.2.3 From c1d12a117b36de7fe8dd992959b890bfd1163e81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 23:35:35 -0700 Subject: Do radio settings solely by frequency Compute the radio setting needed based on the calibration value provided and the requested frequency. Signed-off-by: Keith Packard --- src/core/ao.h | 8 ++++- src/core/ao_cmd.c | 6 ++-- src/core/ao_config.c | 68 ++++++++++++++++++++++------------------- src/core/ao_freq.c | 52 +++++++++++++++++++++++++++++++ src/product/Makefile.telebt | 3 +- src/product/Makefile.teledongle | 3 +- src/product/Makefile.telelaunch | 3 +- src/product/Makefile.telemetrum | 3 +- src/product/Makefile.telemini | 3 +- src/product/Makefile.telenano | 3 +- src/product/ao_terraui.c | 2 +- src/teleshield-v0.1/Makefile | 3 +- src/teleterra-v0.2/Makefile | 3 +- src/tidongle/Makefile | 3 +- 14 files changed, 117 insertions(+), 46 deletions(-) create mode 100644 src/core/ao_freq.c diff --git a/src/core/ao.h b/src/core/ao.h index 8c5335c4..ce9a1f70 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1539,7 +1539,6 @@ ao_igniter_init(void); struct ao_radio_channel { char name[AO_CHANNEL_NAME_LEN]; uint32_t kHz; - uint32_t radio_setting; }; #endif @@ -1559,6 +1558,7 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ + uint32_t frequency; /* minor version 10 */ #if HAS_RADIO_CHANNELS struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ #endif @@ -1959,4 +1959,10 @@ ao_battery_init(void); uint32_t ao_sqrt(uint32_t op); +/* + * ao_freq.c + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal); + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 14cb7569..cde68b39 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -263,9 +263,9 @@ static __pdata uint8_t ao_ncmds; static void help(void) { - register uint8_t cmds; - register uint8_t cmd; - register __code struct ao_cmds * cs; + __pdata uint8_t cmds; + __pdata uint8_t cmd; + __code struct ao_cmds * __pdata cs; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 86bbc473..6fcebe1e 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,6 +64,12 @@ ao_config_put(void) } #endif +static void +ao_config_set_radio(void) +{ + ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); +} + static void _ao_config_get(void) { @@ -105,24 +111,23 @@ _ao_config_get(void) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; if (ao_config.minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 7) - ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); -#if HAS_RADIO_CHANNELS if (ao_config.minor < 10) { + ao_config.frequency = 434550; +#if HAS_RADIO_CHANNELS ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); ao_xmemcpy(&ao_config.radio_channels[0].name[0], CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); ao_config.radio_channels[0].kHz = 434550; - ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; - } #endif + } ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } + ao_config_set_radio(); ao_config_loaded = 1; } @@ -196,6 +201,26 @@ ao_config_radio_channel_set(void) __reentrant ao_radio_recv_abort(); } +void +ao_config_frequency_show(void) __reentrant +{ + printf("Frequency: %ld\n", + ao_config.frequency); +} + +void +ao_config_frequency_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.frequency = ao_cmd_lex_u32; + ao_config_set_radio(); + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + #if HAS_ADC void @@ -315,7 +340,8 @@ ao_config_radio_cal_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + ao_config.radio_cal = ao_cmd_lex_u32; + ao_config_set_radio(); _ao_config_edit_finish(); } @@ -394,25 +420,6 @@ ao_config_pad_orientation_set(void) __reentrant } #endif -void -ao_config_radio_setting_show(void) __reentrant -{ - printf("Radio setting: %ld\n", ao_config.radio_setting); -} - -void -ao_config_radio_setting_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_cmd_lex_u32; - ao_config.radio_channel = 0; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_radio_enable_show(void) __reentrant { @@ -464,11 +471,10 @@ ao_config_radio_config_show(void) __reentrant uint8_t i; for (i = 0; i < AO_NUM_CHANNELS; i++) if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld %ld\n", + printf("%2d %-16.16s %ld\n", i, ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz, - ao_config.radio_channels[i].radio_setting); + ao_config.radio_channels[i].kHz); } } @@ -498,8 +504,6 @@ ao_config_radio_config_set(void) __reentrant } ao_cmd_decimal(); ch->kHz = ao_cmd_lex_u32; - ao_cmd_decimal(); - ch->radio_setting = ao_cmd_lex_u32; _ao_config_edit_finish(); } #endif @@ -528,10 +532,10 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ADC */ { "r \0Radio channel (freq = 434.550 + chan * .1)", ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "F \0Frequency (kHz)", + ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, #if HAS_ACCEL diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c new file mode 100644 index 00000000..13bcb383 --- /dev/null +++ b/src/core/ao_freq.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +/* + * The provided 'calibration' value is + * that needed to tune the radio to precisely 434550kHz. + * Use that to 'walk' to the target frequency by following + * a 'bresenham' line from 434550kHz to the target + * frequency, and updating the radio setting along the way + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal) { + __pdata int32_t set = 0; + uint8_t neg = 0; + __pdata int32_t error = -434550 / 2; + + freq -= 434550; + if (freq < 0) { + neg = 1; + freq = -freq; + } + for (;;) { + if (freq == 0 && error <= 0) + break; + if (error > 0) { + error -= 434550; + set++; + } else { + error += cal; + freq--; + } + } + if (neg) + set = -set; + return cal + set; +} diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ea18ff18..e53aa2c4 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -28,7 +28,8 @@ CORE_SRC = \ ao_panic.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index cf33d1f1..27e7d24b 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -31,7 +31,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 97764517..8aab50e0 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -27,7 +27,8 @@ CORE_SRC = \ ao_panic.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 52c723ca..e4f55f88 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -40,7 +40,8 @@ CORE_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 75beeae4..82ec42a2 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index b30ca789..cf27527c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 05157cb1..9b40c42a 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -459,7 +459,7 @@ ao_terraui_config(void) __reentrant for (chan = 0; chan < AO_NUM_CHANNELS; chan++) - if (ao_config.radio_channels[chan].radio_setting == ao_config.radio_setting) + if (ao_config.radio_channels[chan].kHz == ao_config.frequency) break; if (chan == AO_NUM_CHANNELS) chan = 0; diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index a21a6052..44780476 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -41,7 +41,8 @@ CORE_SRC = \ ao_state.c \ ao_storage.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 0747bfbf..4967d187 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -28,7 +28,8 @@ CORE_SRC = \ ao_sqrt.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_battery.c \ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 698d612c..149b00c5 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -26,7 +26,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ -- cgit v1.2.3 From d8ebb83e64d66fa159e75aa560d39d80bb6d9d04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 10:38:32 -0700 Subject: altosui: Configure radio with new direct frequency setting Instead of computing the radio setting in altosui, let the radio do it directly. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 14 ++++++++++++-- altosui/AltosConfigData.java | 3 +++ altosui/AltosConfigUI.java | 1 + altosui/AltosConvert.java | 16 ++++++++++------ altosui/AltosFrequency.java | 2 +- altosui/AltosSerial.java | 19 +++++++++++++++++-- 6 files changed, 44 insertions(+), 11 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 93def70d..84261ec7 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -76,6 +76,7 @@ public class AltosConfig implements ActionListener { int_ref ignite_mode; int_ref pad_orientation; int_ref radio_setting; + int_ref radio_frequency; int_ref storage_size; int_ref storage_erase_unit; int_ref stored_flight; @@ -193,6 +194,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); get_int(line, "Radio setting:", radio_setting); + get_int(line, "Frequency:", radio_frequency); get_int(line, "Radio enable:", radio_enable); get_int(line, "Storage size:", storage_size); get_int(line, "Storage erase unit:", storage_erase_unit); @@ -230,6 +232,7 @@ public class AltosConfig implements ActionListener { apogee_delay.set(0); radio_channel.set(0); radio_setting.set(0); + radio_frequency.set(0); radio_calibration.set(1186611); radio_enable.set(-1); flight_log_max.set(0); @@ -275,6 +278,7 @@ public class AltosConfig implements ActionListener { void save_data() { try { double frequency = frequency(); + boolean has_frequency = radio_frequency.get() > 0; boolean has_setting = radio_setting.get() > 0; start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); @@ -282,6 +286,7 @@ public class AltosConfig implements ActionListener { if (!remote) serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.set_radio_frequency(frequency, + has_frequency, has_setting, radio_calibration.get()); if (remote) { @@ -378,15 +383,19 @@ public class AltosConfig implements ActionListener { } double frequency() { - return AltosConvert.radio_to_frequency(radio_setting.get(), + return AltosConvert.radio_to_frequency(radio_frequency.get(), + radio_setting.get(), radio_calibration.get(), radio_channel.get()); } void set_frequency(double freq) { + int frequency = radio_frequency.get(); int setting = radio_setting.get(); - if (setting > 0) { + if (frequency > 0) { + radio_frequency.set((int) Math.floor (freq * 1000 + 0.5)); + } else if (setting > 0) { radio_setting.set(AltosConvert.radio_frequency_to_setting(freq, radio_calibration.get())); radio_channel.set(0); @@ -453,6 +462,7 @@ public class AltosConfig implements ActionListener { apogee_delay = new int_ref(0); radio_channel = new int_ref(0); radio_setting = new int_ref(0); + radio_frequency = new int_ref(0); radio_calibration = new int_ref(1186611); radio_enable = new int_ref(-1); flight_log_max = new int_ref(0); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index c14dc5a1..e5c3566b 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -49,6 +49,7 @@ public class AltosConfigData implements Iterable { int apogee_delay; int radio_channel; int radio_setting; + int radio_frequency; String callsign; int accel_cal_plus, accel_cal_minus; int radio_calibration; @@ -107,6 +108,7 @@ public class AltosConfigData implements Iterable { serial_line.printf("c s\nf\nl\nv\n"); lines = new LinkedList(); radio_setting = 0; + radio_frequency = 0; stored_flight = 0; for (;;) { String line = serial_line.get_reply(); @@ -121,6 +123,7 @@ public class AltosConfigData implements Iterable { try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} + try { radio_frequency = get_int(line, "Frequency:"); } catch (Exception e) {} try { if (line.startsWith("Accel cal")) { String[] bits = line.split("\\s+"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 9fef8e3b..c8ec06d2 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -638,6 +638,7 @@ public class AltosConfigUI AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description); AltosPreferences.add_common_frequency(new_frequency); radio_frequency_value.insertItemAt(new_frequency, i); + radio_frequency_value.setSelectedIndex(i); } public double radio_frequency() { diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java index db7039ec..df41a522 100644 --- a/altosui/AltosConvert.java +++ b/altosui/AltosConvert.java @@ -190,14 +190,18 @@ public class AltosConvert { return ignite / 32767 * 15.0; } - static double radio_to_frequency(int setting, int cal, int channel) { + static double radio_to_frequency(int freq, int setting, int cal, int channel) { double f; - if (setting <= 0) - setting = cal; - f = 434.550 * setting / cal; - /* Round to nearest 50KHz */ - f = Math.floor (20.0 * f + 0.5) / 20.0; + if (freq > 0) + f = freq / 1000.0; + else { + if (setting <= 0) + setting = cal; + f = 434.550 * setting / cal; + /* Round to nearest 50KHz */ + f = Math.floor (20.0 * f + 0.5) / 20.0; + } return f + channel * 0.100; } diff --git a/altosui/AltosFrequency.java b/altosui/AltosFrequency.java index 0617ce74..b748e460 100644 --- a/altosui/AltosFrequency.java +++ b/altosui/AltosFrequency.java @@ -35,7 +35,7 @@ public class AltosFrequency { String description; public String toString() { - return String.format("%7.3f MHz %-20.20s", + return String.format("%7.3f MHz %-20s", frequency, description); } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 4cf306d0..ff1a91a5 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -363,12 +363,26 @@ public class AltosSerial implements Runnable { } } + private void set_radio_freq(int frequency) { + if (altos != null) { + if (monitor_mode) + printf("m 0\nc F %d\nm %x\n", + frequency, telemetry_len()); + else + printf("c F %d\n", frequency); + flush_output(); + } + } + public void set_radio_frequency(double frequency, + boolean has_frequency, boolean has_setting, int cal) { if (debug) - System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); - if (has_setting) + System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal); + if (has_frequency) + set_radio_freq((int) Math.floor (frequency * 1000)); + else if (has_setting) set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); else set_channel(AltosConvert.radio_frequency_to_channel(frequency)); @@ -378,6 +392,7 @@ public class AltosSerial implements Runnable { frequency = in_frequency; config_data(); set_radio_frequency(frequency, + config_data.radio_frequency != 0, config_data.radio_setting != 0, config_data.radio_calibration); } -- cgit v1.2.3 From d77a4ea206d627635159f35c76c744687d4e633b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 11:58:39 -0700 Subject: altosui: Show only supported telemetry version Make it clear in the UI which telemetry versions are supported, providing the combobox only for new firmware which supports all versions. Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 33 +++++++++++++++++ altosui/AltosFlightReader.java | 2 ++ altosui/AltosFlightUI.java | 74 +++++++++++++++++++++++++-------------- altosui/AltosTelemetryReader.java | 27 ++++++++++++++ 4 files changed, 110 insertions(+), 26 deletions(-) diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index e5c3566b..0608b4d3 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -104,6 +104,39 @@ public class AltosConfigData implements Iterable { } } + int[] parse_version(String v) { + String[] parts = v.split("\\."); + int r[] = new int[parts.length]; + + for (int i = 0; i < parts.length; i++) { + try { + r[i] = Altos.fromdec(parts[i]); + } catch (NumberFormatException n) { + r[i] = 0; + } + } + + return r; + } + + public int compare_version(String other) { + int[] me = parse_version(version); + int[] them = parse_version(other); + + int l = Math.min(me.length, them.length); + + for (int i = 0; i < l; i++) { + int d = me[i] - them[i]; + if (d != 0) + return d; + } + if (me.length > l) + return 1; + if (them.length > l) + return -1; + return 0; + } + public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { serial_line.printf("c s\nf\nl\nv\n"); lines = new LinkedList(); diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java index 47df375d..3ddf171d 100644 --- a/altosui/AltosFlightReader.java +++ b/altosui/AltosFlightReader.java @@ -43,5 +43,7 @@ public class AltosFlightReader { void update(AltosState state) throws InterruptedException { } + boolean supports_telemetry(int telemetry) { return false; } + File backing_file() { return null; } } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index dcf85277..d99da43d 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -169,6 +169,7 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt Container bag; AltosFreqList frequencies; JComboBox telemetries; + JLabel telemetry; ActionListener show_timer; @@ -216,32 +217,53 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt bag.add (frequencies, c); // Telemetry format menu - telemetries = new JComboBox(); - for (int i = 1; i <= Altos.ao_telemetry_max; i++) - telemetries.addItem(Altos.telemetry_name(i)); - int telemetry = AltosPreferences.telemetry(serial); - if (telemetry <= Altos.ao_telemetry_off || - telemetry > Altos.ao_telemetry_max) - telemetry = Altos.ao_telemetry_standard; - telemetries.setSelectedIndex(telemetry - 1); - telemetries.setMaximumRowCount(Altos.ao_telemetry_max); - telemetries.setPreferredSize(null); - telemetries.revalidate(); - telemetries.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - int telemetry = telemetries.getSelectedIndex() + 1; - reader.set_telemetry(telemetry); - reader.save_telemetry(); - } - }); - c.gridx = 1; - c.gridy = 0; - c.weightx = 0; - c.weighty = 0; - c.fill = GridBagConstraints.NONE; - c.anchor = GridBagConstraints.WEST; - bag.add (telemetries, c); - c.insets = new Insets(0, 0, 0, 0); + if (reader.supports_telemetry(Altos.ao_telemetry_standard)) { + telemetries = new JComboBox(); + for (int i = 1; i <= Altos.ao_telemetry_max; i++) + telemetries.addItem(Altos.telemetry_name(i)); + int telemetry = AltosPreferences.telemetry(serial); + if (telemetry <= Altos.ao_telemetry_off || + telemetry > Altos.ao_telemetry_max) + telemetry = Altos.ao_telemetry_standard; + telemetries.setSelectedIndex(telemetry - 1); + telemetries.setMaximumRowCount(Altos.ao_telemetry_max); + telemetries.setPreferredSize(null); + telemetries.revalidate(); + telemetries.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int telemetry = telemetries.getSelectedIndex() + 1; + reader.set_telemetry(telemetry); + reader.save_telemetry(); + } + }); + c.gridx = 1; + c.gridy = 0; + c.weightx = 0; + c.weighty = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + bag.add (telemetries, c); + c.insets = new Insets(0, 0, 0, 0); + } else { + String version; + + if (reader.supports_telemetry(Altos.ao_telemetry_0_9)) + version = "Telemetry: 0.9"; + else if (reader.supports_telemetry(Altos.ao_telemetry_0_8)) + version = "Telemetry: 0.8"; + else + version = "Telemetry: None"; + + telemetry = new JLabel(version); + c.gridx = 1; + c.gridy = 0; + c.weightx = 0; + c.weighty = 0; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.WEST; + bag.add (telemetry, c); + c.insets = new Insets(0, 0, 0, 0); + } } /* Flight status is always visible */ diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 1f327a67..85dc9cbc 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -56,6 +56,33 @@ class AltosTelemetryReader extends AltosFlightReader { serial.set_radio_frequency(frequency); } + public boolean supports_telemetry(int telemetry) { + + try { + /* Version 1.0 or later firmware supports all telemetry formats */ + if (serial.config_data().compare_version("1.0") >= 0) + return true; + + /* Version 0.9 firmware only supports 0.9 telemetry */ + if (serial.config_data().compare_version("0.9") >= 0) { + if (telemetry == Altos.ao_telemetry_0_9) + return true; + else + return false; + } + + /* Version 0.8 firmware only supports 0.8 telemetry */ + if (telemetry == Altos.ao_telemetry_0_8) + return true; + else + return false; + } catch (InterruptedException ie) { + return true; + } catch (TimeoutException te) { + return true; + } + } + void save_frequency() { AltosPreferences.set_frequency(device.getSerial(), frequency); } -- cgit v1.2.3 From 7dd1d62676c1e605fe69a4c0acfe7638c6b79aa5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 18:19:05 -0700 Subject: altos: Optimize ao_freq_to_set a bit Reduces size from 327 bytes to 287 bytes Signed-off-by: Keith Packard --- src/core/ao_freq.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 13bcb383..67b0b037 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -30,20 +30,18 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal) { uint8_t neg = 0; __pdata int32_t error = -434550 / 2; - freq -= 434550; - if (freq < 0) { + if ((freq -= 434550) < 0) { neg = 1; freq = -freq; } for (;;) { - if (freq == 0 && error <= 0) - break; if (error > 0) { error -= 434550; set++; } else { error += cal; - freq--; + if (--freq < 0) + break; } } if (neg) -- cgit v1.2.3 From 0952224c36eba25db34bd147d2d579c66b15bbf8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 18:24:51 -0700 Subject: altosui: Change flight data saving UI to separate download/delete selections First pop up a dialog to select flights for download. Download them. Then, after that, pop up a *new* dialog to select flights for delete. Offer to delete all of the downloaded flights by default. Then delete the flights. Signed-off-by: Keith Packard --- altosui/AltosEepromDelete.java | 2 +- altosui/AltosEepromDownload.java | 2 +- altosui/AltosEepromLog.java | 8 ++--- altosui/AltosEepromManage.java | 72 +++++++++++++++++++++------------------- altosui/AltosEepromSelect.java | 45 ++++++------------------- 5 files changed, 52 insertions(+), 77 deletions(-) diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index a9d77788..fcce8155 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -90,7 +90,7 @@ public class AltosEepromDelete implements Runnable { serial_line.start_remote(); for (AltosEepromLog log : flights) { - if (log.delete) { + if (log.selected) { DeleteLog(log); } } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index e7e52466..40c98bfd 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -351,7 +351,7 @@ public class AltosEepromDownload implements Runnable { for (AltosEepromLog log : flights) { parse_exception = null; - if (log.download) { + if (log.selected) { monitor.reset(); CaptureLog(log); } diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index ee77e5c8..475d7f12 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -43,8 +43,7 @@ public class AltosEepromLog { int year, month, day; - boolean download; - boolean delete; + boolean selected; public AltosEepromLog(AltosConfigData config_data, AltosSerial serial_line, @@ -63,10 +62,9 @@ public class AltosEepromLog { serial = config_data.serial; /* - * By default, request that every log be downloaded but not deleted + * Select all flights for download */ - download = true; - delete = false; + selected = true; /* * Look in TeleMetrum log data for date diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 083c7372..1e06f4ca 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -39,8 +39,6 @@ public class AltosEepromManage implements ActionListener { AltosEepromList flights; AltosEepromDownload download; AltosEepromDelete delete; - boolean any_download; - boolean any_delete; public void finish() { if (serial_line != null) { @@ -57,7 +55,7 @@ public class AltosEepromManage implements ActionListener { String result = ""; for (AltosEepromLog flight : flights) { - if (flight.delete) { + if (flight.selected) { if (result.equals("")) result = String.format("%d", flight.flight); else @@ -67,18 +65,38 @@ public class AltosEepromManage implements ActionListener { return result; } + public boolean download_done() { + AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Delete"); + + if (select.run()) { + boolean any_selected = false; + for (AltosEepromLog flight : flights) + any_selected = any_selected || flight.selected; + if (any_selected) { + delete = new AltosEepromDelete(frame, + serial_line, + remote, + flights); + delete.addActionListener(this); + /* + * Start flight log delete + */ + + delete.start(); + return true; + } + } + return false; + } + public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); boolean success = e.getID() != 0; boolean running = false; if (cmd.equals("download")) { - if (success) { - if (any_delete) { - delete.start(); - running = true; - } - } + if (success) + running = download_done(); } else if (cmd.equals("delete")) { if (success) { JOptionPane.showMessageDialog(frame, @@ -104,40 +122,26 @@ public class AltosEepromManage implements ActionListener { serial_line.device.toShortString(), JOptionPane.INFORMATION_MESSAGE); } else { - AltosEepromSelect select = new AltosEepromSelect(frame, flights); + AltosEepromSelect select = new AltosEepromSelect(frame, flights, "Download"); if (select.run()) { - for (AltosEepromLog flight : flights) { - any_download = any_download || flight.download; - any_delete = any_delete || flight.delete; - } - if (any_download) { + boolean any_selected = false; + for (AltosEepromLog flight : flights) + any_selected = any_selected || flight.selected; + if (any_selected) { download = new AltosEepromDownload(frame, serial_line, remote, flights); download.addActionListener(this); - } - - if (any_delete) { - delete = new AltosEepromDelete(frame, - serial_line, - remote, - flights); - delete.addActionListener(this); - } + /* + * Start flight log download + */ - /* - * Start flight log download - */ - - if (any_download) { download.start(); running = true; - } - else if (any_delete) { - delete.start(); - running = true; + } else { + running = download_done(); } } } @@ -203,8 +207,6 @@ public class AltosEepromManage implements ActionListener { device = AltosDeviceDialog.show(frame, Altos.product_any); remote = false; - any_download = false; - any_delete = false; if (device != null) { try { diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index ebafc4c8..e0fbeead 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -31,15 +31,11 @@ import libaltosJNI.SWIGTYPE_p_altos_list; class AltosEepromItem implements ActionListener { AltosEepromLog log; JLabel label; - JCheckBox download; + JCheckBox action; JCheckBox delete; public void actionPerformed(ActionEvent e) { - if (e.getSource() == download) { - log.download = download.isSelected(); - } else if (e.getSource() == delete) { - log.delete = delete.isSelected(); - } + log.selected = action.isSelected(); } public AltosEepromItem(AltosEepromLog in_log) { @@ -54,11 +50,8 @@ class AltosEepromItem implements ActionListener { label = new JLabel(text); - download = new JCheckBox("", log.download); - download.addActionListener(this); - - delete = new JCheckBox("", log.delete); - delete.addActionListener(this); + action = new JCheckBox("", log.selected); + action.addActionListener(this); } } @@ -86,7 +79,8 @@ public class AltosEepromSelect extends AltosDialog implements ActionListener { } public AltosEepromSelect (JFrame in_frame, - AltosEepromList flights) { + AltosEepromList flights, + String action) { super(in_frame, String.format("Flight list for serial %d", flights.config_data.serial), true); frame = in_frame; @@ -95,7 +89,7 @@ public class AltosEepromSelect extends AltosDialog implements ActionListener { Container contentPane = getContentPane(); /* First, we create a pane containing the dialog's header/title */ - JLabel selectLabel = new JLabel("Select flights to download and/or delete", SwingConstants.CENTER); + JLabel selectLabel = new JLabel(String.format ("Select flights to %s", action), SwingConstants.CENTER); JPanel labelPane = new JPanel(); labelPane.setLayout(new BoxLayout(labelPane, BoxLayout.X_AXIS)); @@ -132,19 +126,9 @@ public class AltosEepromSelect extends AltosDialog implements ActionListener { c.weightx = 0.5; c.anchor = GridBagConstraints.CENTER; c.insets = i; - JLabel downloadHeaderLabel = new JLabel("Download"); + JLabel downloadHeaderLabel = new JLabel(action); flightPane.add(downloadHeaderLabel, c); - /* Delete Header */ - c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 0; - c.fill = GridBagConstraints.NONE; - c.weightx = 0.5; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - JLabel deleteHeaderLabel = new JLabel("Delete"); - flightPane.add(deleteHeaderLabel, c); - /* Add the flights to the GridBag */ AltosEepromItem item; int itemNumber = 1; @@ -163,23 +147,14 @@ public class AltosEepromSelect extends AltosDialog implements ActionListener { c.insets = i; flightPane.add(item.label, c); - /* Add a download checkbox for the flight */ + /* Add action checkbox for the flight */ c = new GridBagConstraints(); c.gridx = 1; c.gridy = itemNumber; c.fill = GridBagConstraints.NONE; c.weightx = 0.5; c.anchor = GridBagConstraints.CENTER; c.insets = i; - flightPane.add(item.download, c); - - /* Add a delete checkbox for the flight */ - c = new GridBagConstraints(); - c.gridx = 2; c.gridy = itemNumber; - c.fill = GridBagConstraints.NONE; - c.weightx = 0.5; - c.anchor = GridBagConstraints.CENTER; - c.insets = i; - flightPane.add(item.delete, c); + flightPane.add(item.action, c); itemNumber++; } -- cgit v1.2.3 From 170510bb183715e9ba580b180f20657d6602644e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 21:13:31 -0700 Subject: altosui: Find actual landing time when computing stats (trac #23) Look for the last time the height went from >10m to <2m from the nominal landing altitude and use that as the landing time when computing things like main descent speed, time under main etc. Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 124 ++++++++++++++++++++++++------------------ altosui/AltosUI.java | 16 ++++-- 2 files changed, 82 insertions(+), 58 deletions(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index 72d12600..dce5cb3e 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -43,60 +43,88 @@ public class AltosFlightStats { int year, month, day; int hour, minute, second; - public AltosFlightStats(AltosFlightReader reader) throws InterruptedException, IOException { + double landed_time(AltosRecordIterable iterable) { + AltosState state = null; + for (AltosRecord record : iterable) { + state = new AltosState(record, state); + + if (state.state == Altos.ao_flight_landed) + break; + } + + double landed_height = state.height; + + state = null; + + boolean above = true; + + double landed_time = -1000; + + for (AltosRecord record : iterable) { + state = new AltosState(record, state); + + if (state.height > landed_height + 10) { + above = true; + } else { + if (above && state.height < landed_height + 2) { + above = false; + landed_time = state.time; + } + } + } + if (landed_time == -1000) + landed_time = state.time; + return landed_time; + } + + public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { AltosState state = null; AltosState new_state = null; double boost_time = -1; double end_time = 0; + double landed_time = landed_time(iterable); year = month = day = -1; hour = minute = second = -1; serial = flight = -1; - for (;;) { - try { - AltosRecord record = reader.read(); - if (record == null) - break; - if (serial < 0) - serial = record.serial; - if ((record.seen & AltosRecord.seen_flight) != 0 && flight < 0) - flight = record.flight; - new_state = new AltosState(record, state); - end_time = new_state.time; - state = new_state; - if (0 <= state.state && state.state < Altos.ao_flight_invalid) { - if (state.state >= Altos.ao_flight_boost) { - if (boost_time == -1) - boost_time = state.time; - if (state.gps != null && state.gps.locked && - year < 0) { - year = state.gps.year; - month = state.gps.month; - day = state.gps.day; - hour = state.gps.hour; - minute = state.gps.minute; - second = state.gps.second; - } + for (AltosRecord record : iterable) { + if (serial < 0) + serial = record.serial; + if ((record.seen & AltosRecord.seen_flight) != 0 && flight < 0) + flight = record.flight; + new_state = new AltosState(record, state); + end_time = new_state.time; + state = new_state; + if (0 <= state.state && state.state < Altos.ao_flight_invalid) { + if (state.state >= Altos.ao_flight_boost) { + if (boost_time == -1) + boost_time = state.time; + if (state.gps != null && state.gps.locked && + year < 0) { + year = state.gps.year; + month = state.gps.month; + day = state.gps.day; + hour = state.gps.hour; + minute = state.gps.minute; + second = state.gps.second; } - state_accel[state.state] += state.acceleration; - state_speed[state.state] += state.speed; - state_baro_speed[state.state] += state.baro_speed; - state_count[state.state]++; - if (state_start[state.state] == 0.0) - state_start[state.state] = state.time; - if (state_end[state.state] < state.time) - state_end[state.state] = state.time; - max_height = state.max_height; - if (state.max_speed != 0) - max_speed = state.max_speed; - else - max_speed = state.max_baro_speed; - max_acceleration = state.max_acceleration; } - } catch (ParseException pp) { - System.out.printf("Parse error: %d \"%s\"\n", pp.getErrorOffset(), pp.getMessage()); - } catch (AltosCRCException ce) { - + if (state.time >= landed_time) + state.state = Altos.ao_flight_landed; + state_accel[state.state] += state.acceleration; + state_speed[state.state] += state.speed; + state_baro_speed[state.state] += state.baro_speed; + state_count[state.state]++; + if (state_start[state.state] == 0.0) + state_start[state.state] = state.time; + if (state_end[state.state] < state.time) + state_end[state.state] = state.time; + max_height = state.max_height; + if (state.max_speed != 0) + max_speed = state.max_speed; + else + max_speed = state.max_baro_speed; + max_acceleration = state.max_acceleration; } } for (int s = Altos.ao_flight_startup; s <= Altos.ao_flight_landed; s++) { @@ -111,12 +139,4 @@ public class AltosFlightStats { state_end[s] = end_time; } } - - public AltosFlightStats(AltosRecordIterable iterable, File file) throws InterruptedException, IOException { - this(new AltosReplayReader(iterable.iterator(), file)); - } - - public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { - this(iterable, new File("")); - } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 8799d560..89f66c06 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -423,17 +423,17 @@ public class AltosUI extends AltosFrame { } } - static AltosRecordIterable record_iterable_file(String filename) { + static AltosRecordIterable record_iterable(File file) { FileInputStream in; try { - in = new FileInputStream(filename); + in = new FileInputStream(file); } catch (Exception e) { - System.out.printf("Failed to open file '%s'\n", filename); + System.out.printf("Failed to open file '%s'\n", file); return null; } AltosRecordIterable recs; AltosReplayReader reader; - if (filename.endsWith("eeprom")) { + if (file.getName().endsWith("eeprom")) { recs = new AltosEepromIterable(in); } else { recs = new AltosTelemetryIterable(in); @@ -441,6 +441,10 @@ public class AltosUI extends AltosFrame { return recs; } + static AltosRecordIterable record_iterable_file(String filename) { + return record_iterable (new File(filename)); + } + static AltosReplayReader replay_file(String filename) { AltosRecordIterable recs = record_iterable_file(filename); if (recs == null) @@ -466,9 +470,9 @@ public class AltosUI extends AltosFrame { } static void process_summary(String filename) { - AltosReplayReader reader = replay_file(filename); + AltosRecordIterable iterable = record_iterable_file(filename); try { - AltosFlightStats stats = new AltosFlightStats(reader); + AltosFlightStats stats = new AltosFlightStats(iterable); if (stats.serial > 0) System.out.printf("Serial: %5d\n", stats.serial); if (stats.flight > 0) -- cgit v1.2.3 From 2f19f9a0eaba22789fdc07a52849e8aaf6fe4695 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 21:48:43 -0700 Subject: altosui: Catch attempt to set radio frequency to 0.0 -- use default Monitor idle was setting the frequency to 0, which takes a while with the new native radio frequency setting code. Don't do that, instead pull out the preferred frequency for that, as is done in other places where a frequency of 0.0 is used. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index ff1a91a5..dffc74ea 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -380,6 +380,8 @@ public class AltosSerial implements Runnable { int cal) { if (debug) System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal); + if (frequency == 0) + return; if (has_frequency) set_radio_freq((int) Math.floor (frequency * 1000)); else if (has_setting) @@ -390,6 +392,8 @@ public class AltosSerial implements Runnable { public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { frequency = in_frequency; + if (frequency == 0.0) + frequency = AltosPreferences.frequency(device.getSerial()); config_data(); set_radio_frequency(frequency, config_data.radio_frequency != 0, -- cgit v1.2.3 From 7a9baabaf33db5e30eb4ef8f923a4fd96fd28fb4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 21:49:58 -0700 Subject: altosui: Mark data 'Age' in monitor idle UI too Just like with the flight monitor UI, it's nice to know how old the data in the monitor idle UI is, in case the data link to the TM isn't reliable. Signed-off-by: Keith Packard --- altosui/AltosFlightStatusUpdate.java | 45 ++++++++++++++++++++++++++++++++++++ altosui/AltosFlightUI.java | 15 ------------ altosui/AltosIdleMonitorUI.java | 7 ++++++ altosui/Makefile.am | 1 + 4 files changed, 53 insertions(+), 15 deletions(-) create mode 100644 altosui/AltosFlightStatusUpdate.java diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java new file mode 100644 index 00000000..a600bd02 --- /dev/null +++ b/altosui/AltosFlightStatusUpdate.java @@ -0,0 +1,45 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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.*; + +public class AltosFlightStatusUpdate implements ActionListener { + + public AltosState saved_state; + AltosFlightStatus flightStatus; + + public void actionPerformed (ActionEvent e) { + if (saved_state != null) + flightStatus.show(saved_state, 0); + } + + public AltosFlightStatusUpdate (AltosFlightStatus in_flightStatus) { + flightStatus = in_flightStatus; + } +} + diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index d99da43d..b2ae4858 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -28,21 +28,6 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -class AltosFlightStatusUpdate implements ActionListener { - - public AltosState saved_state; - AltosFlightStatus flightStatus; - - public void actionPerformed (ActionEvent e) { - if (saved_state != null) - flightStatus.show(saved_state, 0); - } - - public AltosFlightStatusUpdate (AltosFlightStatus in_flightStatus) { - flightStatus = in_flightStatus; - } -} - public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; AltosFlightReader reader; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index a5f41e25..dbac2d33 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -293,7 +293,10 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay set_font(); } + AltosFlightStatusUpdate status_update; + public void show(AltosState state, int crc_errors) { + status_update.saved_state = state; try { pad.show(state, crc_errors); flightStatus.show(state, crc_errors); @@ -399,6 +402,10 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay thread = new AltosIdleMonitor(this, device, remote); + status_update = new AltosFlightStatusUpdate(flightStatus); + + new javax.swing.Timer(100, status_update).start(); + thread.start(); } } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 3138efac..f89340fb 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -56,6 +56,7 @@ altosui_JAVA = \ AltosFlightStats.java \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ + AltosFlightStatusUpdate.java \ AltosFlightUI.java \ AltosFontListener.java \ AltosFrequency.java \ -- cgit v1.2.3 From 3f0379db7067eaf104892a82b9c49142087adece Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 22:02:13 -0700 Subject: altosui: Make 'monitor idle' work with older TeleMetrum firmware (trac #28) Older TM firmware did not have the 'done' line at the end of the GPS report, rather it would just stop after showing the Flags value. Check the TM version and stop looking for GPS data when the Flags line appears. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 10 ++++++++-- altosui/AltosSerial.java | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index dbac2d33..d877be4d 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -90,7 +90,9 @@ class AltosADC { } class AltosGPSQuery extends AltosGPS { - public AltosGPSQuery (AltosSerial serial) throws TimeoutException, InterruptedException { + public AltosGPSQuery (AltosSerial serial, AltosConfigData config_data) + throws TimeoutException, InterruptedException { + boolean says_done = config_data.compare_version("1.0") >= 0; serial.printf("g\n"); for (;;) { String line = serial.get_reply_no_dialog(5000); @@ -140,6 +142,8 @@ class AltosGPSQuery extends AltosGPS { int status = Integer.decode(bits[1]); connected = (status & Altos.AO_GPS_RUNNING) != 0; locked = (status & Altos.AO_GPS_VALID) != 0; + if (!says_done) + break; continue; } if (line.startsWith("Sats:")) { @@ -184,7 +188,7 @@ class AltosIdleMonitor extends Thread { serial.flush_input(); config_data = new AltosConfigData(serial); adc = new AltosADC(serial); - gps = new AltosGPSQuery(serial); + gps = new AltosGPSQuery(serial, config_data); } finally { if (remote) serial.stop_remote(); @@ -237,6 +241,8 @@ class AltosIdleMonitor extends Thread { update_state(); post_state(); } catch (TimeoutException te) { + if (AltosSerial.debug) + System.out.printf ("monitor idle data timeout\n"); } Thread.sleep(1000); } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index dffc74ea..77c926b1 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -55,7 +55,7 @@ public class AltosSerial implements Runnable { boolean monitor_mode; int telemetry; double frequency; - static boolean debug; + public static boolean debug; boolean remote; LinkedList pending_output = new LinkedList(); Frame frame; -- cgit v1.2.3 From b6c7ae2c1f8cba7351cd139c49322280d9d3af47 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 22:53:08 -0700 Subject: altos: Reset config version if it's too large as well Any future config values will get trashed if we down grade the firmware, so we must reset the firmware version whenever it gets written. Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 6fcebe1e..350ebcbe 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -91,7 +91,7 @@ _ao_config_get(void) sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } - if (ao_config.minor < AO_CONFIG_MINOR) { + if (ao_config.minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; -- cgit v1.2.3 From b98f75dbcccd40c8cbf32c3bfd21bd6f5648b861 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 22:54:17 -0700 Subject: altosui: Sanity check values from device configuration If someone has down-graded and re up-graded the firmware, the config entries may be garbage. Sanity check them to avoid crashing the UI. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 4 +++- altosui/AltosConfigData.java | 6 +++++- altosui/AltosConfigUI.java | 4 ++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 84261ec7..8eb71e1f 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -194,7 +194,9 @@ public class AltosConfig implements ActionListener { get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); get_int(line, "Radio setting:", radio_setting); - get_int(line, "Frequency:", radio_frequency); + if (get_int(line, "Frequency:", radio_frequency)) + if (radio_frequency.get() < 0) + radio_frequency.set(434550); get_int(line, "Radio enable:", radio_enable); get_int(line, "Storage size:", storage_size); get_int(line, "Storage erase unit:", storage_erase_unit); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 0608b4d3..53509dfa 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -156,7 +156,11 @@ public class AltosConfigData implements Iterable { try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} - try { radio_frequency = get_int(line, "Frequency:"); } catch (Exception e) {} + try { + radio_frequency = get_int(line, "Frequency:"); + if (radio_frequency < 0) + radio_frequency = 434550; + } catch (Exception e) {} try { if (line.startsWith("Accel cal")) { String[] bits = line.split("\\s+"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index c8ec06d2..879605bc 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -708,6 +708,8 @@ public class AltosConfigUI } public void set_ignite_mode(int new_ignite_mode) { + if (new_ignite_mode >= ignite_mode_values.length) + new_ignite_mode = 0; if (new_ignite_mode < 0) { ignite_mode_value.setEnabled(false); new_ignite_mode = 0; @@ -727,6 +729,8 @@ public class AltosConfigUI public void set_pad_orientation(int new_pad_orientation) { + if (new_pad_orientation >= pad_orientation_values.length) + new_pad_orientation = 0; if (new_pad_orientation < 0) { pad_orientation_value.setEnabled(false); new_pad_orientation = 0; -- cgit v1.2.3 From d60862fce6ac27a97ad6337eea32a4b48645d158 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 00:38:37 -0700 Subject: altos: Make sure config values are loaded in 'c s' command ao_config_get may not have been called when ao_config_show is invoked by the user, so make sure the config values are loaded before showing uninitialized data. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 350ebcbe..08e6deea 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -609,6 +609,7 @@ static void ao_config_show(void) __reentrant { uint8_t cmd; + ao_config_get(); printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) -- cgit v1.2.3 From cf1e95810559584705d0b8a787375938c68e07c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 00:37:52 -0700 Subject: altosui: Add Configure Ground Station dialog (trac #29) Allows the user to configure the teledongle frequency without opening up the flight monitor window, and also shows the teledongle fixed values like radio calibration, serial number and software version. Signed-off-by: Keith Packard --- altosui/AltosConfigTD.java | 373 +++++++++++++++++++++++++++++++++++++++++++ altosui/AltosConfigTDUI.java | 353 ++++++++++++++++++++++++++++++++++++++++ altosui/AltosUI.java | 31 ++-- altosui/Makefile.am | 2 + 4 files changed, 750 insertions(+), 9 deletions(-) create mode 100644 altosui/AltosConfigTD.java create mode 100644 altosui/AltosConfigTDUI.java diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java new file mode 100644 index 00000000..68f746b2 --- /dev/null +++ b/altosui/AltosConfigTD.java @@ -0,0 +1,373 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.*; + +import libaltosJNI.*; + +public class AltosConfigTD implements ActionListener { + + class int_ref { + int value; + + public int get() { + return value; + } + public void set(int i) { + value = i; + } + public int_ref(int i) { + value = i; + } + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref(String i) { + value = i; + } + } + + JFrame owner; + AltosDevice device; + AltosSerial serial_line; + int_ref serial; + int_ref radio_channel; + int_ref radio_calibration; + int_ref radio_setting; + int_ref radio_frequency; + string_ref config_version; + string_ref version; + string_ref product; + AltosConfigTDUI config_ui; + boolean serial_started; + boolean made_visible; + + boolean get_int(String line, String label, int_ref x) { + if (line.startsWith(label)) { + try { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) { + int i = Integer.parseInt(tokens[0]); + x.set(i); + return true; + } + } catch (NumberFormatException ne) { + } + } + return false; + } + + boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + void start_serial() throws InterruptedException, TimeoutException { + serial_started = true; + } + + void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + } + + void update_ui() { + config_ui.set_serial(serial.get()); + config_ui.set_product(product.get()); + config_ui.set_version(version.get()); + config_ui.set_radio_frequency(frequency()); + config_ui.set_radio_calibration(radio_calibration.get()); + config_ui.set_clean(); + if (!made_visible) { + made_visible = true; + config_ui.make_visible(); + } + } + + void process_line(String line) { + if (line == null) { + abort(); + return; + } + if (line.equals("all finished")) { + if (serial_line != null) + update_ui(); + return; + } + get_string(line, "Config version", config_version); + get_int(line, "serial-number", serial); + get_int(line, "Radio channel:", radio_channel); + if (get_int(line, "Radio cal:", radio_calibration)) + System.out.printf("got radio cal %d\n", radio_calibration.get()); + get_int(line, "Radio setting:", radio_setting); + get_string(line,"software-version", version); + get_string(line,"product", product); + } + + final static int serial_mode_read = 0; + final static int serial_mode_save = 1; + final static int serial_mode_reboot = 2; + + class SerialData implements Runnable { + AltosConfigTD config; + int serial_mode; + + void process_line(String line) { + config.process_line(line); + } + void callback(String in_line) { + final String line = in_line; + Runnable r = new Runnable() { + public void run() { + process_line(line); + } + }; + SwingUtilities.invokeLater(r); + } + + void reset_data() { + serial.set(0); + radio_channel.set(0); + radio_setting.set(0); + radio_frequency.set(0); + radio_calibration.set(1186611); + config_version.set("0.0"); + version.set("unknown"); + product.set("unknown"); + } + + void get_data() { + try { + boolean been_there = false; + config.start_serial(); + reset_data(); + + for (;;) { + config.serial_line.printf("c s\nf\nl\nv\n"); + for (;;) { + try { + String line = config.serial_line.get_reply(5000); + if (line == null) + stop_serial(); + callback(line); + if (line.startsWith("software-version")) + break; + } catch (Exception e) { + break; + } + } + System.out.printf("config_version %s\n", config_version.get()); + if (been_there) + break; + if (!config_version.get().equals("0.0")) + break; + been_there = true; + config.serial_line.printf("C\n "); + config.serial_line.flush_input(); + } + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + double pref_frequency = AltosPreferences.frequency(serial.get()); + if (pref_frequency != 0) + radio_frequency.set((int) Math.floor (pref_frequency * 1000 + 0.5)); + callback("all finished"); + } + + void save_data() { + double frequency = frequency(); + if (frequency != 0) + AltosPreferences.set_frequency(serial.get(), + frequency); + } + + public void run () { + switch (serial_mode) { + case serial_mode_save: + save_data(); + /* fall through ... */ + case serial_mode_read: + get_data(); + break; + } + } + + public SerialData(AltosConfigTD in_config, int in_serial_mode) { + config = in_config; + serial_mode = in_serial_mode; + } + } + + void run_serial_thread(int serial_mode) { + SerialData sd = new SerialData(this, serial_mode); + Thread st = new Thread(sd); + st.start(); + } + + void init_ui () throws InterruptedException, TimeoutException { + config_ui = new AltosConfigTDUI(owner); + config_ui.addActionListener(this); + serial_line.set_frame(owner); + set_ui(); + } + + void abort() { + serial_line.close(); + serial_line = null; + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + config_ui.setVisible(false); + } + + void set_ui() throws InterruptedException, TimeoutException { + if (serial_line != null) + run_serial_thread(serial_mode_read); + else + update_ui(); + } + + double frequency() { + return AltosConvert.radio_to_frequency(radio_frequency.get(), + radio_setting.get(), + radio_calibration.get(), + radio_channel.get()); + } + + void set_frequency(double freq) { + int frequency = radio_frequency.get(); + int setting = radio_setting.get(); + + if (frequency > 0) { + radio_frequency.set((int) Math.floor (freq * 1000 + 0.5)); + } else if (setting > 0) { + radio_setting.set(AltosConvert.radio_frequency_to_setting(freq, + radio_calibration.get())); + radio_channel.set(0); + } else { + radio_channel.set(AltosConvert.radio_frequency_to_channel(freq)); + } + } + + void save_data() { + + set_frequency(config_ui.radio_frequency()); + run_serial_thread(serial_mode_save); + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + try { + if (cmd.equals("Save")) { + save_data(); + } else if (cmd.equals("Reset")) { + set_ui(); + } else if (cmd.equals("Reboot")) { + if (serial_line != null) + run_serial_thread(serial_mode_reboot); + } else if (cmd.equals("Close")) { + if (serial_line != null) + serial_line.close(); + } + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } + } + + public AltosConfigTD(JFrame given_owner) { + owner = given_owner; + + serial = new int_ref(0); + radio_channel = new int_ref(0); + radio_setting = new int_ref(0); + radio_frequency = new int_ref(0); + radio_calibration = new int_ref(1186611); + config_version = new string_ref("0.0"); + version = new string_ref("unknown"); + product = new string_ref("unknown"); + + device = AltosDeviceDialog.show(owner, Altos.product_basestation); + if (device != null) { + try { + serial_line = new AltosSerial(device); + try { + init_ui(); + } catch (InterruptedException ie) { + abort(); + } catch (TimeoutException te) { + abort(); + } + } catch (FileNotFoundException ee) { + JOptionPane.showMessageDialog(owner, + ee.getMessage(), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } catch (AltosSerialInUseException si) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } catch (IOException ee) { + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } + } + } +} \ No newline at end of file diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java new file mode 100644 index 00000000..9f6badc7 --- /dev/null +++ b/altosui/AltosConfigTDUI.java @@ -0,0 +1,353 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.concurrent.LinkedBlockingQueue; + +import libaltosJNI.*; + +public class AltosConfigTDUI + extends AltosDialog + implements ActionListener, ItemListener, DocumentListener +{ + + Container pane; + Box box; + JLabel product_label; + JLabel version_label; + JLabel serial_label; + JLabel frequency_label; + JLabel radio_calibration_label; + JLabel radio_frequency_label; + + public boolean dirty; + + JFrame owner; + JLabel product_value; + JLabel version_value; + JLabel serial_value; + AltosFreqList radio_frequency_value; + JLabel radio_calibration_value; + + JButton save; + JButton reset; + JButton reboot; + JButton close; + + ActionListener listener; + + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosConfigTDUI ui; + + public ConfigListener(AltosConfigTDUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "Close")); + } + } + + /* Build the UI using a grid bag */ + public AltosConfigTDUI(JFrame in_owner) { + super (in_owner, "Configure TeleDongle", false); + + 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()); + + /* Product */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 0; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + product_label = new JLabel("Product:"); + pane.add(product_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 0; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + product_value = new JLabel(""); + pane.add(product_value, c); + + /* Version */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 1; + c.gridwidth = 4; + 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 = new GridBagConstraints(); + c.gridx = 4; c.gridy = 1; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + version_value = new JLabel(""); + pane.add(version_value, c); + + /* Serial */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 2; + c.gridwidth = 4; + 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 = new GridBagConstraints(); + c.gridx = 4; c.gridy = 2; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + serial_value = new JLabel(""); + pane.add(serial_value, c); + + /* Frequency */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 5; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_frequency_label = new JLabel("Frequency:"); + pane.add(radio_frequency_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 5; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_frequency_value = new AltosFreqList(); + radio_frequency_value.addItemListener(this); + pane.add(radio_frequency_value, c); + radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency"); + + /* Radio Calibration */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 6; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + radio_calibration_label = new JLabel("RF Calibration:"); + pane.add(radio_calibration_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 6; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_calibration_value = new JLabel(String.format("%d", 1186611)); + pane.add(radio_calibration_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 12; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + save = new JButton("Save"); + pane.add(save, c); + save.addActionListener(this); + save.setActionCommand("Save"); + + c = new GridBagConstraints(); + c.gridx = 2; c.gridy = 12; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = il; + reset = new JButton("Reset"); + pane.add(reset, c); + reset.addActionListener(this); + reset.setActionCommand("Reset"); + + c = new GridBagConstraints(); + c.gridx = 6; c.gridy = 12; + c.gridwidth = 2; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_END; + c.insets = il; + close = new JButton("Close"); + pane.add(close, c); + close.addActionListener(this); + close.setActionCommand("Close"); + + addWindowListener(new ConfigListener(this)); + } + + /* Once the initial values are set, the config code will show the dialog */ + public void make_visible() { + pack(); + setLocationRelativeTo(owner); + setVisible(true); + } + + /* If any values have been changed, confirm before closing */ + public boolean check_dirty(String operation) { + if (dirty) { + Object[] options = { String.format("%s anyway", operation), "Keep editing" }; + int i; + i = JOptionPane.showOptionDialog(this, + String.format("Configuration modified. %s anyway?", operation), + "Configuration Modified", + JOptionPane.DEFAULT_OPTION, + JOptionPane.WARNING_MESSAGE, + null, options, options[1]); + if (i != 0) + return false; + } + return true; + } + + /* Listen for events from our buttons */ + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + + if (cmd.equals("Close") || cmd.equals("Reboot")) + if (!check_dirty(cmd)) + return; + listener.actionPerformed(e); + if (cmd.equals("Close") || cmd.equals("Reboot")) { + setVisible(false); + dispose(); + } + dirty = false; + } + + /* ItemListener interface method */ + public void itemStateChanged(ItemEvent e) { + dirty = true; + } + + /* DocumentListener interface methods */ + public void changedUpdate(DocumentEvent e) { + dirty = true; + } + + public void insertUpdate(DocumentEvent e) { + dirty = true; + } + + public void removeUpdate(DocumentEvent e) { + dirty = true; + } + + /* Let the config code hook on a listener */ + public void addActionListener(ActionListener l) { + listener = l; + } + + /* set and get all of the dialog values */ + public void set_product(String product) { + radio_frequency_value.set_product(product); + product_value.setText(product); + } + + public void set_version(String version) { + version_value.setText(version); + } + + public void set_serial(int serial) { + radio_frequency_value.set_serial(serial); + serial_value.setText(String.format("%d", serial)); + } + + public void set_radio_frequency(double new_radio_frequency) { + int i; + for (i = 0; i < radio_frequency_value.getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i); + + if (f.close(new_radio_frequency)) { + radio_frequency_value.setSelectedIndex(i); + return; + } + } + for (i = 0; i < radio_frequency_value.getItemCount(); i++) { + AltosFrequency f = (AltosFrequency) radio_frequency_value.getItemAt(i); + + if (new_radio_frequency < f.frequency) + break; + } + String description = String.format("%s serial %s", + product_value.getText(), + serial_value.getText()); + AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description); + AltosPreferences.add_common_frequency(new_frequency); + radio_frequency_value.insertItemAt(new_frequency, i); + radio_frequency_value.setSelectedIndex(i); + } + + public double radio_frequency() { + return radio_frequency_value.frequency(); + } + + public void set_radio_calibration(int calibration) { + radio_calibration_value.setText(String.format("%d", calibration)); + } + + public void set_clean() { + dirty = false; + } +} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 89f66c06..75a12ece 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -165,28 +165,29 @@ public class AltosUI extends AltosFrame { } }); b.setToolTipText("Global AltosUI settings"); - b = addButton(2, 1, "Flash Image"); + + b = addButton(2, 1, "Configure Ground Station"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - FlashImage(); + ConfigureTeleDongle(); } }); - b.setToolTipText("Replace the firmware in any AltusMetrum product"); - b = addButton(3, 1, "Fire Igniter"); + b = addButton(3, 1, "Flash Image"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - FireIgniter(); + FlashImage(); } }); - b.setToolTipText("Remote control of igniters for deployment testing"); - b = addButton(4, 1, "Quit"); + b.setToolTipText("Replace the firmware in any AltusMetrum product"); + + b = addButton(4, 1, "Fire Igniter"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - System.exit(0); + FireIgniter(); } }); - b.setToolTipText("Close all active windows and terminate AltosUI"); + b.setToolTipText("Remote control of igniters for deployment testing"); b = addButton(0, 2, "Scan Channels"); b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -216,6 +217,14 @@ public class AltosUI extends AltosFrame { } }); + b = addButton(4, 2, "Quit"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + System.exit(0); + } + }); + b.setToolTipText("Close all active windows and terminate AltosUI"); + setTitle("AltOS"); pane.doLayout(); @@ -262,6 +271,10 @@ public class AltosUI extends AltosFrame { new AltosConfig(AltosUI.this); } + void ConfigureTeleDongle() { + new AltosConfigTD(AltosUI.this); + } + void FlashImage() { AltosFlashUI.show(AltosUI.this); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f89340fb..d436c6a0 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -26,6 +26,8 @@ altosui_JAVA = \ AltosConfigFreqUI.java \ AltosConfigUI.java \ AltosConfigureUI.java \ + AltosConfigTD.java \ + AltosConfigTDUI.java \ AltosConvert.java \ AltosCRCException.java \ AltosCSV.java \ -- cgit v1.2.3 From bdfcc9112c41c494de23594963980a730b625cc4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 00:49:29 -0700 Subject: altosui: Disable launch controller button The launch controller should just be a separate program. Signed-off-by: Keith Packard --- altosui/AltosUI.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 75a12ece..6993abab 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -210,12 +210,12 @@ public class AltosUI extends AltosFrame { }); b.setToolTipText("Check flight readiness of altimeter in idle mode"); - b = addButton(3, 2, "Launch Controller"); - b.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - LaunchController(); - } - }); +// b = addButton(3, 2, "Launch Controller"); +// b.addActionListener(new ActionListener() { +// public void actionPerformed(ActionEvent e) { +// LaunchController(); +// } +// }); b = addButton(4, 2, "Quit"); b.addActionListener(new ActionListener() { -- cgit v1.2.3 From 3c7d1f6cfffb43299041f2850a48177f4e9b83a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Feb 2012 23:26:03 +1300 Subject: 'stdin' is a special name in some compiler environments, don't use it. Switch to 'in' in the prototype for altos_serial_set_stdin. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index ce9a1f70..ac51c270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -917,7 +917,7 @@ char ao_serial_pollchar(void) __critical; void -ao_serial_set_stdin(uint8_t stdin); +ao_serial_set_stdin(uint8_t in); #endif void -- cgit v1.2.3 From e2f13aa43ba79becbff6c9bfc18c665a58d96185 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 14:25:37 -0700 Subject: Add example STM32L programs This loads to flash and sends data over the serial link. Signed-off-by: Keith Packard --- ao-bringup/stm/Makefile | 35 +++++ ao-bringup/stm/altos-ram.ld | 69 ++++++++++ ao-bringup/stm/altos.ld | 71 ++++++++++ ao-bringup/stm/bringup.c | 306 ++++++++++++++++++++++++++++++++++++++++++++ ao-bringup/stm/registers.ld | 46 +++++++ 5 files changed, 527 insertions(+) create mode 100644 ao-bringup/stm/Makefile create mode 100644 ao-bringup/stm/altos-ram.ld create mode 100644 ao-bringup/stm/altos.ld create mode 100644 ao-bringup/stm/bringup.c create mode 100644 ao-bringup/stm/registers.ld diff --git a/ao-bringup/stm/Makefile b/ao-bringup/stm/Makefile new file mode 100644 index 00000000..49966a4f --- /dev/null +++ b/ao-bringup/stm/Makefile @@ -0,0 +1,35 @@ +CC=arm-none-eabi-gcc +OBJCOPY=arm-none-eabi-objcopy + +C_LIB=/local/src/pdclib/pdclib.a +C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals + +DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) + +# to run from SRAM +LD_FLAGS_RAM=-Wl,-Taltos-ram.ld +LD_FLAGS=-Wl,-Taltos.ld + +CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY + +OBJS=bringup.o + +all: bringup-ram.elf bringup.elf + +%.bin: %.elf + $(OBJCOPY) -O binary $^ $@ + +bringup.elf: $(OBJS) $(C_LIB) altos.ld + $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld + $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup.o: bringup.c + $(CC) -c $(CFLAGS) bringup.c + +clean: + rm -rf *.elf + rm -rf *.bin + +.PHONY: all clean diff --git a/ao-bringup/stm/altos-ram.ld b/ao-bringup/stm/altos-ram.ld new file mode 100644 index 00000000..b8fffedc --- /dev/null +++ b/ao-bringup/stm/altos-ram.ld @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +C_STACK_SIZE = 512; + +INCLUDE registers.ld + +SECTIONS { + . = ORIGIN(ram); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > ram + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > ram + + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/ao-bringup/stm/altos.ld b/ao-bringup/stm/altos.ld new file mode 100644 index 00000000..0a25f853 --- /dev/null +++ b/ao-bringup/stm/altos.ld @@ -0,0 +1,71 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +C_STACK_SIZE = 512; + +SECTIONS { + . = ORIGIN(rom); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + . = ORIGIN(ram); + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/ao-bringup/stm/bringup.c b/ao-bringup/stm/bringup.c new file mode 100644 index 00000000..b6fe458d --- /dev/null +++ b/ao-bringup/stm/bringup.c @@ -0,0 +1,306 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +#include +#include "stm32l.h" + +void delay(void); + +static void +set_clock(void) +{ + uint32_t cfgr; + uint32_t cr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = stm_flash.acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + stm_flash.acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + stm_flash.acr = acr; + + /* HCLK to 16MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); +#define STM_AHB_PRESCALER 1 + + /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + stm_rcc.cfgr = cfgr; +#define STM_APB1_PRESCALER 1 + + /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + stm_rcc.cfgr = cfgr; +#define STM_APB2_PRESCALER 1 + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Enable HSI RC clock 16MHz */ + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } +#define STM_HSI 16000000 + + /* Switch to direct HSI for SYSCLK */ + if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + +// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); +// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + +#define STM_PLLMUL 6 +#define STM_PLLDIV 4 + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + +#define STM_PLLSRC STM_HSI + + stm_rcc.cfgr = cfgr; + + /* Enable the PLL and wait for it */ + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } +} + +#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL) +#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV) +#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER) +#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER) +#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER) + +#define BAUD_9600 (STM_APB2 / 9600) + +void +set_serial() +{ + uint32_t moder, afr; + + /* Enable GPIOA */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + /* Hook PA9, PA10 to USART1 (AFIO7) */ + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART1 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */ + + /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6} + * round to 104.1875 (1667 / 16) + * + * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps + */ + + stm_usart1.brr = BAUD_9600; + + stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CPHA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADD)); + + stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + (0 << STM_USART_CR3_CTSIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); +} + +void +outbyte(char c) +{ + if (c == '\n') + outbyte('\r'); + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))) + ; + stm_usart1.dr = c; +} + +int putc( int c, FILE * stream ) { + outbyte(c); +} + +void +serial_string(char *string) +{ + char c; + + while (c = *string++) + outbyte(c); +} + +void +set_timer6(void) +{ + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + +} + +void +main (void) +{ + set_clock(); + set_serial(); + set_timer6(); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT); + for (;;) { + stm_gpiob.odr = (1 << 7); + printf ("hello, "); + delay(); + stm_gpiob.odr = (1 << 6); + printf ("world\n"); + delay(); + } +} + +void +delay(void) +{ + int i; + for (i = 0; i < 1000000; i++) + __asm__ __volatile__ ("nop\n\t":::"memory"); +} + +static int x = 7; + +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +__attribute__ ((section(".interrupt"))) +static const void *interrupt[] = { + &__stack__, + start, +}; diff --git a/ao-bringup/stm/registers.ld b/ao-bringup/stm/registers.ld new file mode 100644 index 00000000..58204b9f --- /dev/null +++ b/ao-bringup/stm/registers.ld @@ -0,0 +1,46 @@ +stm_fsmc = 0xa0000000; +stm_aes = 0x50060000; +stm_dma = 0x40026000; +stm_flash = 0x40023c00; +stm_rcc = 0x40023800; +stm_crc = 0x40023000; +stm_gpioh = 0x40021400; +stm_gpioe = 0x40021000; +stm_gpiod = 0x40020c00; +stm_gpioc = 0x40020800; +stm_gpiob = 0x40020400; +stm_gpioa = 0x40020000; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_sdio = 0x40012c00; +stm_adc = 0x40012400; +stm_tim11 = 0x40011000; +stm_tim10 = 0x40010c00; +stm_tim9 = 0x40010800; +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; +stm_comp = 0x40007c00; +stm_ri = 0x40007c04; +stm_dac = 0x40007400; +stm_pwr = 0x40007000; +stm_usb_sram = 0x40006000; +stm_usb = 0x40005c00; +stm_i2c2 = 0x40005800; +stm_i2c1 = 0x40005400; +stm_usart5 = 0x40005000; +stm_usart4 = 0x40004c00; +stm_usart3 = 0x40004800; +stm_usart2 = 0x40004400; +stm_spi3 = 0x40003c00; /* docs are broken here */ +stm_spi2 = 0x40003800; /* docs are broken here */ +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; +stm_lcd = 0x40002400; +stm_tim7 = 0x40001400; +stm_tim6 = 0x40001000; +stm_tim5 = 0x40000c00; +stm_tim4 = 0x40000800; +stm_tim3 = 0x40000400; +stm_tim2 = 0x40000000; + -- cgit v1.2.3 From 9279fd42793123784ce83ca151df6f4630487722 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:21:09 -0700 Subject: Add STM platform and stm-bringup demo program The stm-bringup doesn't run altos, it just initializes the device and writes stuff over a serial port. Works on the STM32L Discovery board at least, should do stuff on other boards too. Signed-off-by: Keith Packard --- ao-bringup/stm/Makefile | 35 --- ao-bringup/stm/bringup.c | 306 --------------------- src/stm-bringup/Makefile | 35 +++ src/stm-bringup/bringup.c | 306 +++++++++++++++++++++ src/stm/altos-ram.ld | 69 +++++ src/stm/altos.ld | 72 +++++ src/stm/ao_arch.h | 129 +++++++++ src/stm/ao_interrupt.c | 169 ++++++++++++ src/stm/ao_led.c | 69 +++++ src/stm/ao_serial_stm.c | 184 +++++++++++++ src/stm/ao_timer.c | 167 ++++++++++++ src/stm/registers.ld | 47 ++++ src/stm/stm32l.h | 662 ++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 1909 insertions(+), 341 deletions(-) delete mode 100644 ao-bringup/stm/Makefile delete mode 100644 ao-bringup/stm/bringup.c create mode 100644 src/stm-bringup/Makefile create mode 100644 src/stm-bringup/bringup.c create mode 100644 src/stm/altos-ram.ld create mode 100644 src/stm/altos.ld create mode 100644 src/stm/ao_arch.h create mode 100644 src/stm/ao_interrupt.c create mode 100644 src/stm/ao_led.c create mode 100644 src/stm/ao_serial_stm.c create mode 100644 src/stm/ao_timer.c create mode 100644 src/stm/registers.ld create mode 100644 src/stm/stm32l.h diff --git a/ao-bringup/stm/Makefile b/ao-bringup/stm/Makefile deleted file mode 100644 index 49966a4f..00000000 --- a/ao-bringup/stm/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -CC=arm-none-eabi-gcc -OBJCOPY=arm-none-eabi-objcopy - -C_LIB=/local/src/pdclib/pdclib.a -C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals - -DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) - -# to run from SRAM -LD_FLAGS_RAM=-Wl,-Taltos-ram.ld -LD_FLAGS=-Wl,-Taltos.ld - -CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY - -OBJS=bringup.o - -all: bringup-ram.elf bringup.elf - -%.bin: %.elf - $(OBJCOPY) -O binary $^ $@ - -bringup.elf: $(OBJS) $(C_LIB) altos.ld - $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld - $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup.o: bringup.c - $(CC) -c $(CFLAGS) bringup.c - -clean: - rm -rf *.elf - rm -rf *.bin - -.PHONY: all clean diff --git a/ao-bringup/stm/bringup.c b/ao-bringup/stm/bringup.c deleted file mode 100644 index b6fe458d..00000000 --- a/ao-bringup/stm/bringup.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 - -#include -#include "stm32l.h" - -void delay(void); - -static void -set_clock(void) -{ - uint32_t cfgr; - uint32_t cr; - - /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = stm_flash.acr; - - /* Enable 64-bit access and prefetch */ - acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - stm_flash.acr = acr; - - /* Enable 1 wait state so the CPU can run at 32MHz */ - /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ - acr |= (1 << STM_FLASH_ACR_LATENCY); - stm_flash.acr = acr; - - /* HCLK to 16MHz -> AHB prescaler = /1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) - asm ("nop"); -#define STM_AHB_PRESCALER 1 - - /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); - stm_rcc.cfgr = cfgr; -#define STM_APB1_PRESCALER 1 - - /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); - stm_rcc.cfgr = cfgr; -#define STM_APB2_PRESCALER 1 - - /* Enable power interface clock */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); - - /* Set voltage range to 1.8V */ - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Configure voltage scaling range */ - cr = stm_pwr.cr; - cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); - cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); - stm_pwr.cr = cr; - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Enable HSI RC clock 16MHz */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSION); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) - asm("nop"); - } -#define STM_HSI 16000000 - - /* Switch to direct HSI for SYSCLK */ - if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) - asm("nop"); - } - - /* Disable the PLL */ - stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); - while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) - asm("nop"); - - /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); - cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); - -// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); -// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); - - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); - -#define STM_PLLMUL 6 -#define STM_PLLDIV 4 - - /* PLL source to HSI */ - cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - -#define STM_PLLSRC STM_HSI - - stm_rcc.cfgr = cfgr; - - /* Enable the PLL and wait for it */ - stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) - asm("nop"); - - /* Switch to the PLL for the system clock */ - - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - for (;;) { - uint32_t c, part, mask, val; - - c = stm_rcc.cfgr; - mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); - val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); - part = c & mask; - if (part == val) - break; - } -} - -#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL) -#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV) -#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER) -#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER) -#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER) - -#define BAUD_9600 (STM_APB2 / 9600) - -void -set_serial() -{ - uint32_t moder, afr; - - /* Enable GPIOA */ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - - /* Hook PA9, PA10 to USART1 (AFIO7) */ - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); - - /* Enable USART1 */ - stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - - /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */ - - /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6} - * round to 104.1875 (1667 / 16) - * - * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps - */ - - stm_usart1.brr = BAUD_9600; - - stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | - (1 << STM_USART_CR1_UE) | - (0 << STM_USART_CR1_M) | - (0 << STM_USART_CR1_WAKE) | - (0 << STM_USART_CR1_PCE) | - (0 << STM_USART_CR1_PS) | - (0 << STM_USART_CR1_PEIE) | - (0 << STM_USART_CR1_TXEIE) | - (0 << STM_USART_CR1_TCIE) | - (0 << STM_USART_CR1_RXNEIE) | - (0 << STM_USART_CR1_IDLEIE) | - (1 << STM_USART_CR1_TE) | - (1 << STM_USART_CR1_RE) | - (0 << STM_USART_CR1_RWU) | - (0 << STM_USART_CR1_SBK)); - - stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | - (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | - (0 << STM_USART_CR2_CLKEN) | - (0 << STM_USART_CR2_CPOL) | - (0 << STM_USART_CR2_CPHA) | - (0 << STM_USART_CR2_LBCL) | - (0 << STM_USART_CR2_LBDIE) | - (0 << STM_USART_CR2_LBDL) | - (0 << STM_USART_CR2_ADD)); - - stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | - (0 << STM_USART_CR3_CTSIE) | - (0 << STM_USART_CR3_CTSE) | - (0 << STM_USART_CR3_RTSE) | - (0 << STM_USART_CR3_DMAT) | - (0 << STM_USART_CR3_DMAR) | - (0 << STM_USART_CR3_SCEN) | - (0 << STM_USART_CR3_NACK) | - (0 << STM_USART_CR3_HDSEL) | - (0 << STM_USART_CR3_IRLP) | - (0 << STM_USART_CR3_IREN) | - (0 << STM_USART_CR3_EIE)); -} - -void -outbyte(char c) -{ - if (c == '\n') - outbyte('\r'); - while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))) - ; - stm_usart1.dr = c; -} - -int putc( int c, FILE * stream ) { - outbyte(c); -} - -void -serial_string(char *string) -{ - char c; - - while (c = *string++) - outbyte(c); -} - -void -set_timer6(void) -{ - /* Turn on timer 6 */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - - -} - -void -main (void) -{ - set_clock(); - set_serial(); - set_timer6(); - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT); - stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT); - for (;;) { - stm_gpiob.odr = (1 << 7); - printf ("hello, "); - delay(); - stm_gpiob.odr = (1 << 6); - printf ("world\n"); - delay(); - } -} - -void -delay(void) -{ - int i; - for (i = 0; i < 1000000; i++) - __asm__ __volatile__ ("nop\n\t":::"memory"); -} - -static int x = 7; - -extern char __stack__; -extern char __text_start__, __text_end__; -extern char __data_start__, __data_end__; -extern char __bss_start__, __bss_end__; - -void start(void) { - memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); - memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); - main(); -} - -__attribute__ ((section(".interrupt"))) -static const void *interrupt[] = { - &__stack__, - start, -}; diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile new file mode 100644 index 00000000..49966a4f --- /dev/null +++ b/src/stm-bringup/Makefile @@ -0,0 +1,35 @@ +CC=arm-none-eabi-gcc +OBJCOPY=arm-none-eabi-objcopy + +C_LIB=/local/src/pdclib/pdclib.a +C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals + +DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) + +# to run from SRAM +LD_FLAGS_RAM=-Wl,-Taltos-ram.ld +LD_FLAGS=-Wl,-Taltos.ld + +CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY + +OBJS=bringup.o + +all: bringup-ram.elf bringup.elf + +%.bin: %.elf + $(OBJCOPY) -O binary $^ $@ + +bringup.elf: $(OBJS) $(C_LIB) altos.ld + $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld + $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup.o: bringup.c + $(CC) -c $(CFLAGS) bringup.c + +clean: + rm -rf *.elf + rm -rf *.bin + +.PHONY: all clean diff --git a/src/stm-bringup/bringup.c b/src/stm-bringup/bringup.c new file mode 100644 index 00000000..b6fe458d --- /dev/null +++ b/src/stm-bringup/bringup.c @@ -0,0 +1,306 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +#include +#include "stm32l.h" + +void delay(void); + +static void +set_clock(void) +{ + uint32_t cfgr; + uint32_t cr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = stm_flash.acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + stm_flash.acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + stm_flash.acr = acr; + + /* HCLK to 16MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); +#define STM_AHB_PRESCALER 1 + + /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + stm_rcc.cfgr = cfgr; +#define STM_APB1_PRESCALER 1 + + /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + stm_rcc.cfgr = cfgr; +#define STM_APB2_PRESCALER 1 + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Enable HSI RC clock 16MHz */ + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } +#define STM_HSI 16000000 + + /* Switch to direct HSI for SYSCLK */ + if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + +// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); +// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + +#define STM_PLLMUL 6 +#define STM_PLLDIV 4 + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + +#define STM_PLLSRC STM_HSI + + stm_rcc.cfgr = cfgr; + + /* Enable the PLL and wait for it */ + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } +} + +#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL) +#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV) +#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER) +#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER) +#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER) + +#define BAUD_9600 (STM_APB2 / 9600) + +void +set_serial() +{ + uint32_t moder, afr; + + /* Enable GPIOA */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + /* Hook PA9, PA10 to USART1 (AFIO7) */ + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART1 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */ + + /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6} + * round to 104.1875 (1667 / 16) + * + * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps + */ + + stm_usart1.brr = BAUD_9600; + + stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CPHA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADD)); + + stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + (0 << STM_USART_CR3_CTSIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); +} + +void +outbyte(char c) +{ + if (c == '\n') + outbyte('\r'); + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))) + ; + stm_usart1.dr = c; +} + +int putc( int c, FILE * stream ) { + outbyte(c); +} + +void +serial_string(char *string) +{ + char c; + + while (c = *string++) + outbyte(c); +} + +void +set_timer6(void) +{ + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + +} + +void +main (void) +{ + set_clock(); + set_serial(); + set_timer6(); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT); + for (;;) { + stm_gpiob.odr = (1 << 7); + printf ("hello, "); + delay(); + stm_gpiob.odr = (1 << 6); + printf ("world\n"); + delay(); + } +} + +void +delay(void) +{ + int i; + for (i = 0; i < 1000000; i++) + __asm__ __volatile__ ("nop\n\t":::"memory"); +} + +static int x = 7; + +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +__attribute__ ((section(".interrupt"))) +static const void *interrupt[] = { + &__stack__, + start, +}; diff --git a/src/stm/altos-ram.ld b/src/stm/altos-ram.ld new file mode 100644 index 00000000..b8fffedc --- /dev/null +++ b/src/stm/altos-ram.ld @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +C_STACK_SIZE = 512; + +INCLUDE registers.ld + +SECTIONS { + . = ORIGIN(ram); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > ram + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > ram + + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/altos.ld b/src/stm/altos.ld new file mode 100644 index 00000000..4e955666 --- /dev/null +++ b/src/stm/altos.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) +C_STACK_SIZE = 512; + +SECTIONS { + . = ORIGIN(rom); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + . = ORIGIN(ram); + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h new file mode 100644 index 00000000..e6f54fdb --- /dev/null +++ b/src/stm/ao_arch.h @@ -0,0 +1,129 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include +#include + +/* + * STM32L definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 256 + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() /* XXX */ + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); +extern void ao_avr_stdio_init(void); + +extern const uint16_t ao_serial_number; + +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +#define ao_arch_task_members\ + uint32_t *sp; /* saved stack pointer */ + +#define cli() asm("cpsid i") +#define sei() asm("cpsie i") + +#define ao_arch_init_stack(task, start) do { \ + uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + ARM_PUSH32(sp, a); \ + \ + /* Invalid link register */ \ + ARM_PUSH32(sp, 0xffffffff); \ + \ + /* Clear register values */ \ + i = 13; \ + while (i--) \ + ARM_PUSH32(sp, 0); \ + \ + /* PSR with interrupts enabled */ \ + ARM_PUSH32(sp, 0x01000000); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_regs() do { \ + asm("push {r0-r12,lr}\n"); \ + cli(); \ + asm("mrs r0,psr" "\n\t" "push {r0}"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint32_t sp; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + ao_cur_task->sp = (uint32_t *) (sp); \ + } while (0) + +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + asm("wfi"); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint32_t sp; \ + sp = (uint32_t) ao_cur_task->sp; \ + cli(); \ + asm("mov sp, %0" : : "r" (sp) ); \ + asm("pop {r0}" "\n\t" "msr psr,r0"); \ + asm("pop {r0-r12,lr}\n"); \ + asm("bx lr"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) + +#define AO_ARM_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ +}; + + +#endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c new file mode 100644 index 00000000..6b4a9700 --- /dev/null +++ b/src/stm/ao_interrupt.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 "stm32l.h" +#include + +extern void main(void); +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +/* Interrupt functions */ + +void stm_halt_isr(void) +{ + for(;;); +} + +void stm_ignore_isr(void) +{ +} + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr + +__attribute__ ((section(".interrupt"))) +const void *stm_interrupt_vector[] = { + [0] = &__stack__, + [1] = start, + i(0x08, nmi), + i(0x0c, hardfault), + i(0x10, memmanage), + i(0x14, busfault), + i(0x18, usagefault), + i(0x2c, svc), + i(0x30, debugmon), + i(0x38, pendsv), + i(0x3c, systick), + i(0x40, wwdg), + i(0x44, pvd), + i(0x48, tamper_stamp), + i(0x4c, rtc_wkup), + i(0x50, flash), + i(0x54, rcc), + i(0x58, exti0), + i(0x5c, exti1), + i(0x60, exti2), + i(0x64, exti3), + i(0x68, exti4), + i(0x6c, dma1_channel1), + i(0x70, dma1_channel2), + i(0x74, dma1_channel3), + i(0x78, dma1_channel4), + i(0x7c, dma1_channel5), + i(0x80, dma1_channel6), + i(0x84, dma1_channel7), + i(0x88, adc1), + i(0x8c, usb_hp), + i(0x90, usb_lp), + i(0x94, dac), + i(0x98, comp), + i(0x9c, exti9_5), + i(0xa0, lcd), + i(0xa4, tim9), + i(0xa8, tim10), + i(0xac, tim11), + i(0xb0, tim2), + i(0xb4, tim3), + i(0xb8, tim4), + i(0xbc, i2c1_ev), + i(0xc0, i2c1_er), + i(0xc4, i2c2_ev), + i(0xc8, i2c2_er), + i(0xcc, spi1), + i(0xd0, spi2), + i(0xd4, usart1), + i(0xd8, usart2), + i(0xdc, usart3), + i(0xe0, exti15_10), + i(0xe4, rtc_alarm), + i(0xe8, usb_fs_wkup), + i(0xec, tim6), + i(0xf0, tim7), +}; diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c new file mode 100644 index 00000000..db65afdf --- /dev/null +++ b/src/stm/ao_led.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT STM_GPIOD + +void +ao_led_on(uint8_t colors) +{ + LED_PORT->odr |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT->odr &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT->odr = (LED_PORT->odr & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT->odr ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + int bit; + + ao_led_enable = enable; + LED_PORT->odr &= ~enable; + for (bit = 0; bit < 16; bit++) { + if (enable & (1 << bit)) { + stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); + } + } +} diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c new file mode 100644 index 00000000..dc446120 --- /dev/null +++ b/src/stm/ao_serial_stm.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + while (!(STM_USART1->usart_sr & (1 << STM_USART_SR_TXE))); + STM_USART1->usart_dr = c; +} + +#if 0 +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, STM_USART1->usart_dr); + } +} + +void usart1_isr(void) +{ + if (STM_USART1->usart_sr & (1 << STM_USART_SR_RXNE)) { + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, STM_USART1->usart_dr); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif + } + if (STM_USART1->usart_sr & (1 << STM_USART_SR_TXE)) { + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); + } +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +#endif + +int _write(int file, char *ptr, int len) +{ + int l = len; + while (l--) + ao_debug_out(*ptr++); + return len; +} + +#define F_CPU 24000000 + +static const struct { + uint32_t usart_brr; +} ao_serial_speeds[] = { + [AO_SERIAL_SPEED_4800] = { + (F_CPU * 16) / (16 * 4800) + }, + [AO_SERIAL_SPEED_9600] = { + (F_CPU * 16) / (16 * 9600) + }, + [AO_SERIAL_SPEED_19200] = { + (F_CPU * 16) / (16 * 19200) + }, + [AO_SERIAL_SPEED_57600] = { + (F_CPU * 16) / (16 * 57600) + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ +#if 0 + ao_serial_drain(); +#endif + if (speed > AO_SERIAL_SPEED_57600) + return; + STM_USART1->usart_brr = ao_serial_speeds[speed].usart_brr; +} + +void +ao_serial_init(void) +{ + STM_USART1->usart_cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | /* XXX enable */ + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | /* XXX enable */ + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + STM_USART1->usart_cr2 = 0; + STM_USART1->usart_cr3 = 0; + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + printf ("serial initialized\n"); +#if 0 +#if USE_SERIAL_STDIN + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +#endif +} diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c new file mode 100644 index 00000000..f253e0c0 --- /dev/null +++ b/src/stm/ao_timer.c @@ -0,0 +1,167 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T2_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T2_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + + +void tim2_isr(void) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ +} + +void +ao_clock_init(void) +{ + uint32_t cfgr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = STM_FLASH->acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + STM_FLASH->acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + STM_FLASH->acr = acr; + + /* Enable HSI RC clock 16MHz */ + if (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) { + STM_RCC->cr |= (1 << STM_RCC_CR_HSION); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } + + /* Switch to direct HSI for SYSCLK */ + if ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + STM_RCC->cr &= ~(1 << STM_RCC_CR_PLLON); + while (STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + + /* SYSCLK to 32MHz from PLL clock -> PLLDIV = /3 */ + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + + STM_RCC->cfgr = cfgr; + + /* Enable the PLL and wait for it */ + STM_RCC->cr |= (1 << STM_RCC_CR_PLLON); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS)) + asm("nop"); + + /* HCLK to 32MHz -> AHB prescaler = /1 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); + + /* PCLK1 to 16MHz -> APB1 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_2 << STM_RCC_CFGR_PPRE1); + STM_RCC->cfgr = cfgr; + + /* PCLK2 to 16MHz -> APB2 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_2 << STM_RCC_CFGR_PPRE2); + STM_RCC->cfgr = cfgr; + +} diff --git a/src/stm/registers.ld b/src/stm/registers.ld new file mode 100644 index 00000000..51921444 --- /dev/null +++ b/src/stm/registers.ld @@ -0,0 +1,47 @@ +stm_fsmc = 0xa0000000; +stm_aes = 0x50060000; +stm_dma = 0x40026000; +stm_flash = 0x40023c00; +stm_rcc = 0x40023800; +stm_crc = 0x40023000; +stm_gpioh = 0x40021400; +stm_gpioe = 0x40021000; +stm_gpiod = 0x40020c00; +stm_gpioc = 0x40020800; +stm_gpiob = 0x40020400; +stm_gpioa = 0x40020000; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_sdio = 0x40012c00; +stm_adc = 0x40012400; +stm_tim11 = 0x40011000; +stm_tim10 = 0x40010c00; +stm_tim9 = 0x40010800; +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; +stm_comp = 0x40007c00; +stm_ri = 0x40007c04; +stm_dac = 0x40007400; +stm_pwr = 0x40007000; +stm_usb_sram = 0x40006000; +stm_usb = 0x40005c00; +stm_i2c2 = 0x40005800; +stm_i2c1 = 0x40005400; +stm_usart5 = 0x40005000; +stm_usart4 = 0x40004c00; +stm_usart3 = 0x40004800; +stm_usart2 = 0x40004400; +stm_spi3 = 0x40003c00; /* docs are broken here */ +stm_spi2 = 0x40003800; /* docs are broken here */ +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; +stm_lcd = 0x40002400; +stm_tim7 = 0x40001400; +stm_tim6 = 0x40001000; +stm_tim5 = 0x40000c00; +stm_tim4 = 0x40000800; +stm_tim3 = 0x40000400; +stm_tim2 = 0x40000000; + +stm_nvic = 0xe000e100; \ No newline at end of file diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h new file mode 100644 index 00000000..c5e2a797 --- /dev/null +++ b/src/stm/stm32l.h @@ -0,0 +1,662 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _STM32L_H_ +#define _STM32L_H_ + +#include + +typedef volatile uint32_t vuint32_t; + +struct stm_gpio { + vuint32_t moder; + vuint32_t otyper; + vuint32_t ospeedr; + vuint32_t pupdr; + + vuint32_t idr; + vuint32_t odr; + vuint32_t bsrr; + vuint32_t lckr; + + vuint32_t afrl; + vuint32_t afrh; +}; + +#define STM_MODER_SHIFT(pin) ((pin) << 1) +#define STM_MODER_MASK 3 +#define STM_MODER_INPUT 0 +#define STM_MODER_OUTPUT 1 +#define STM_MODER_ALTERNATE 2 +#define STM_MODER_ANALOG 3 + +static inline void +stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->moder = ((gpio->moder & + ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | + value << STM_MODER_SHIFT(pin)); +} + +static inline vuint32_t +stm_moder_get(struct stm_gpio *gpio, int pin) { + return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; +} + +#define STM_OTYPER_SHIFT(pin) (pin) +#define STM_OTYPER_MASK 1 +#define STM_OTYPER_PUSH_PULL 0 +#define STM_OTYPER_OPEN_DRAIN 1 + +static inline void +stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->otyper = ((gpio->otyper & + ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | + value << STM_OTYPER_SHIFT(pin)); +} + +static inline vuint32_t +stm_otyper_get(struct stm_gpio *gpio, int pin) { + return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; +} + +#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1) +#define STM_OSPEEDR_MASK 3 +#define STM_OSPEEDR_400kHz 0 +#define STM_OSPEEDR_2MHz 1 +#define STM_OSPEEDR_10MHz 2 +#define STM_OSPEEDR_40MHz 3 + +static inline void +stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->ospeedr = ((gpio->ospeedr & + ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | + value << STM_OSPEEDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_ospeedr_get(struct stm_gpio *gpio, int pin) { + return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; +} + +#define STM_PUPDR_SHIFT(pin) ((pin) << 1) +#define STM_PUPDR_MASK 3 +#define STM_PUPDR_NONE 0 +#define STM_PUPDR_PULL_UP 1 +#define STM_PUPDR_PULL_DOWN 2 +#define STM_PUPDR_RESERVED 3 + +static inline void +stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->pupdr = ((gpio->pupdr & + ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | + value << STM_PUPDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_pupdr_get(struct stm_gpio *gpio, int pin) { + return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; +} + +#define STM_AFR_SHIFT(pin) ((pin) << 2) +#define STM_AFR_MASK 0xf +#define STM_AFR_NONE 0 +#define STM_AFR_AF0 0x0 +#define STM_AFR_AF1 0x1 +#define STM_AFR_AF2 0x2 +#define STM_AFR_AF3 0x3 +#define STM_AFR_AF4 0x4 +#define STM_AFR_AF5 0x5 +#define STM_AFR_AF6 0x6 +#define STM_AFR_AF7 0x7 +#define STM_AFR_AF8 0x8 +#define STM_AFR_AF9 0x9 +#define STM_AFR_AF10 0xa +#define STM_AFR_AF11 0xb +#define STM_AFR_AF12 0xc +#define STM_AFR_AF13 0xd +#define STM_AFR_AF14 0xe +#define STM_AFR_AF15 0xf + +static inline void +stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + if (pin < 8) + gpio->afrl = ((gpio->afrl & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + else { + pin -= 8; + gpio->afrh = ((gpio->afrh & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + } +} + +static inline uint32_t +stm_afr_get(struct stm_gpio *gpio, int pin) { + if (pin < 8) + return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + else { + pin -= 8; + return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + } +} + +extern struct stm_gpio stm_gpioa; +extern struct stm_gpio stm_gpiob; +extern struct stm_gpio stm_gpioc; +extern struct stm_gpio stm_gpiod; +extern struct stm_gpio stm_gpioe; +extern struct stm_gpio stm_gpioh; + +struct stm_usart { + vuint32_t sr; /* status register */ + vuint32_t dr; /* data register */ + vuint32_t brr; /* baud rate register */ + vuint32_t cr1; /* control register 1 */ + + vuint32_t cr2; /* control register 2 */ + vuint32_t cr3; /* control register 3 */ + vuint32_t gtpr; /* guard time and prescaler */ +}; + +extern struct stm_usart stm_usart1; + +#define STM_USART_SR_CTS (9) /* CTS flag */ +#define STM_USART_SR_LBD (8) /* LIN break detection flag */ +#define STM_USART_SR_TXE (7) /* Transmit data register empty */ +#define STM_USART_SR_TC (6) /* Transmission complete */ +#define STM_USART_SR_RXNE (5) /* Read data register not empty */ +#define STM_USART_SR_IDLE (4) /* IDLE line detected */ +#define STM_USART_SR_ORE (3) /* Overrun error */ +#define STM_USART_SR_NF (2) /* Noise detected flag */ +#define STM_USART_SR_FE (1) /* Framing error */ +#define STM_USART_SR_PE (0) /* Parity error */ + +#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */ +#define STM_USART_CR1_UE (13) /* USART enable */ +#define STM_USART_CR1_M (12) /* Word length */ +#define STM_USART_CR1_WAKE (11) /* Wakeup method */ +#define STM_USART_CR1_PCE (10) /* Parity control enable */ +#define STM_USART_CR1_PS (9) /* Parity selection */ +#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */ +#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */ +#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */ +#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */ +#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */ +#define STM_USART_CR1_TE (3) /* Transmitter enable */ +#define STM_USART_CR1_RE (2) /* Receiver enable */ +#define STM_USART_CR1_RWU (1) /* Receiver wakeup */ +#define STM_USART_CR1_SBK (0) /* Send break */ + +#define STM_USART_CR2_LINEN (14) /* LIN mode enable */ +#define STM_USART_CR2_STOP (12) /* STOP bits */ +#define STM_USART_CR2_STOP_MASK 3 +#define STM_USART_CR2_STOP_1 0 +#define STM_USART_CR2_STOP_0_5 1 +#define STM_USART_CR2_STOP_2 2 +#define STM_USART_CR2_STOP_1_5 3 + +#define STM_USART_CR2_CLKEN (11) /* Clock enable */ +#define STM_USART_CR2_CPOL (10) /* Clock polarity */ +#define STM_USART_CR2_CPHA (9) /* Clock phase */ +#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */ +#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */ +#define STM_USART_CR2_LBDL (5) /* lin break detection length */ +#define STM_USART_CR2_ADD (0) +#define STM_USART_CR2_ADD_MASK 0xf + +#define STM_USART_CR3_ONEBITE (11) /* One sample bit method enable */ +#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */ +#define STM_USART_CR3_CTSE (9) /* CTS enable */ +#define STM_USART_CR3_RTSE (8) /* RTS enable */ +#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */ +#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */ +#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */ +#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */ +#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */ +#define STM_USART_CR3_IRLP (2) /* IrDA low-power */ +#define STM_USART_CR3_IREN (1) /* IrDA mode enable */ +#define STM_USART_CR3_EIE (0) /* Error interrupt enable */ + +struct stm_spi { +}; + +extern struct stm_spi stm_spi1; + +struct stm_tim { +}; + +extern struct stm_tim stm_tim9; +extern struct stm_tim stm_tim10; +extern struct stm_tim stm_tim11; + +/* Flash interface */ + +struct stm_flash { + vuint32_t acr; + vuint32_t pecr; + vuint32_t pdkeyr; + vuint32_t pekeyr; + + vuint32_t prgkeyr; + vuint32_t optkeyr; + vuint32_t sr; + vuint32_t obr; + + vuint32_t wrpr; +}; + +extern struct stm_flash stm_flash; + +#define STM_FLASH_ACR_RUN_PD (4) +#define STM_FLASH_ACR_SLEEP_PD (3) +#define STM_FLASH_ACR_ACC64 (2) +#define STM_FLASH_ACR_PRFEN (1) +#define STM_FLASH_ACR_LATENCY (0) + +struct stm_rcc { + vuint32_t cr; + vuint32_t icscr; + vuint32_t cfgr; + vuint32_t cir; + + vuint32_t ahbrstr; + vuint32_t apb2rstr; + vuint32_t abp1rstr; + vuint32_t ahbenr; + + vuint32_t apb2enr; + vuint32_t apb1enr; + vuint32_t ahblenr; + vuint32_t apb2lpenr; + + vuint32_t apb1lpenr; + vuint32_t csr; +}; + +extern struct stm_rcc stm_rcc; + +#define STM_RCC_CR_RTCPRE (29) +#define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 +#define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 +#define STM_RCC_CR_RTCPRE_HSE_DIV_8 2 +#define STM_RCC_CR_RTCPRE_HSE_DIV_16 3 +#define STM_RCC_CR_RTCPRE_HSE_MASK 3 + +#define STM_RCC_CR_CSSON (28) +#define STM_RCC_CR_PLLRDY (25) +#define STM_RCC_CR_PLLON (24) +#define STM_RCC_CR_HSEBYP (18) +#define STM_RCC_CR_HSERDY (17) +#define STM_RCC_CR_HSEON (16) +#define STM_RCC_CR_MSIRDY (9) +#define STM_RCC_CR_MSION (8) +#define STM_RCC_CR_HSIRDY (1) +#define STM_RCC_CR_HSION (0) + +#define STM_RCC_CFGR_MCOPRE (28) +#define STM_RCC_CFGR_MCOPRE_DIV_1 0 +#define STM_RCC_CFGR_MCOPRE_DIV_2 1 +#define STM_RCC_CFGR_MCOPRE_DIV_4 2 +#define STM_RCC_CFGR_MCOPRE_DIV_8 3 +#define STM_RCC_CFGR_MCOPRE_DIV_16 4 +#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7 + +#define STM_RCC_CFGR_MCOSEL (24) +#define STM_RCC_CFGR_MCOSEL_DISABLE 0 +#define STM_RCC_CFGR_MCOSEL_SYSCLK 1 +#define STM_RCC_CFGR_MCOSEL_HSI 2 +#define STM_RCC_CFGR_MCOSEL_MSI 3 +#define STM_RCC_CFGR_MCOSEL_HSE 4 +#define STM_RCC_CFGR_MCOSEL_PLL 5 +#define STM_RCC_CFGR_MCOSEL_LSI 6 +#define STM_RCC_CFGR_MCOSEL_LSE 7 +#define STM_RCC_CFGR_MCOSEL_MASK 7 + +#define STM_RCC_CFGR_PLLDIV (22) +#define STM_RCC_CFGR_PLLDIV_2 1 +#define STM_RCC_CFGR_PLLDIV_3 2 +#define STM_RCC_CFGR_PLLDIV_4 3 +#define STM_RCC_CFGR_PLLDIV_MASK 3 + +#define STM_RCC_CFGR_PLLMUL (18) +#define STM_RCC_CFGR_PLLMUL_3 0 +#define STM_RCC_CFGR_PLLMUL_4 1 +#define STM_RCC_CFGR_PLLMUL_6 2 +#define STM_RCC_CFGR_PLLMUL_8 3 +#define STM_RCC_CFGR_PLLMUL_12 4 +#define STM_RCC_CFGR_PLLMUL_16 5 +#define STM_RCC_CFGR_PLLMUL_24 6 +#define STM_RCC_CFGR_PLLMUL_32 7 +#define STM_RCC_CFGR_PLLMUL_48 8 +#define STM_RCC_CFGR_PLLMUL_MASK 0xf + +#define STM_RCC_CFGR_PLLSRC (16) + +#define STM_RCC_CFGR_PPRE2 (11) +#define STM_RCC_CFGR_PPRE2_DIV_1 0 +#define STM_RCC_CFGR_PPRE2_DIV_2 4 +#define STM_RCC_CFGR_PPRE2_DIV_4 5 +#define STM_RCC_CFGR_PPRE2_DIV_8 6 +#define STM_RCC_CFGR_PPRE2_DIV_16 7 +#define STM_RCC_CFGR_PPRE2_MASK 7 + +#define STM_RCC_CFGR_PPRE1 (8) +#define STM_RCC_CFGR_PPRE1_DIV_1 0 +#define STM_RCC_CFGR_PPRE1_DIV_2 4 +#define STM_RCC_CFGR_PPRE1_DIV_4 5 +#define STM_RCC_CFGR_PPRE1_DIV_8 6 +#define STM_RCC_CFGR_PPRE1_DIV_16 7 +#define STM_RCC_CFGR_PPRE1_MASK 7 + +#define STM_RCC_CFGR_HPRE (4) +#define STM_RCC_CFGR_HPRE_DIV_1 0 +#define STM_RCC_CFGR_HPRE_DIV_2 8 +#define STM_RCC_CFGR_HPRE_DIV_4 9 +#define STM_RCC_CFGR_HPRE_DIV_8 0xa +#define STM_RCC_CFGR_HPRE_DIV_16 0xb +#define STM_RCC_CFGR_HPRE_DIV_64 0xc +#define STM_RCC_CFGR_HPRE_DIV_128 0xd +#define STM_RCC_CFGR_HPRE_DIV_256 0xe +#define STM_RCC_CFGR_HPRE_DIV_512 0xf +#define STM_RCC_CFGR_HPRE_MASK 0xf + +#define STM_RCC_CFGR_SWS (2) +#define STM_RCC_CFGR_SWS_MSI 0 +#define STM_RCC_CFGR_SWS_HSI 1 +#define STM_RCC_CFGR_SWS_HSE 2 +#define STM_RCC_CFGR_SWS_PLL 3 +#define STM_RCC_CFGR_SWS_MASK 3 + +#define STM_RCC_CFGR_SW (0) +#define STM_RCC_CFGR_SW_MSI 0 +#define STM_RCC_CFGR_SW_HSI 1 +#define STM_RCC_CFGR_SW_HSE 2 +#define STM_RCC_CFGR_SW_PLL 3 +#define STM_RCC_CFGR_SW_MASK 3 + +#define STM_RCC_AHBENR_DMA1EN (24) +#define STM_RCC_AHBENR_FLITFEN (15) +#define STM_RCC_AHBENR_CRCEN (12) +#define STM_RCC_AHBENR_GPIOHEN (5) +#define STM_RCC_AHBENR_GPIOEEN (4) +#define STM_RCC_AHBENR_GPIODEN (3) +#define STM_RCC_AHBENR_GPIOCEN (2) +#define STM_RCC_AHBENR_GPIOBEN (1) +#define STM_RCC_AHBENR_GPIOAEN (0) + +#define STM_RCC_APB2ENR_USART1EN (14) +#define STM_RCC_APB2ENR_SPI1EN (12) +#define STM_RCC_APB2ENR_ADC1EN (9) +#define STM_RCC_APB2ENR_TIM11EN (4) +#define STM_RCC_APB2ENR_TIM10EN (3) +#define STM_RCC_APB2ENR_TIM9EN (2) +#define STM_RCC_APB2ENR_SYSCFGEN (0) + +#define STM_RCC_APB1ENR_COMPEN (31) +#define STM_RCC_APB1ENR_DACEN (29) +#define STM_RCC_APB1ENR_PWREN (28) +#define STM_RCC_APB1ENR_USBEN (23) +#define STM_RCC_APB1ENR_I2C2EN (22) +#define STM_RCC_APB1ENR_I2C1EN (21) +#define STM_RCC_APB1ENR_USART3EN (18) +#define STM_RCC_APB1ENR_USART2EN (17) +#define STM_RCC_APB1ENR_SPI2EN (14) +#define STM_RCC_APB1ENR_WWDGEN (11) +#define STM_RCC_APB1ENR_LCDEN (9) +#define STM_RCC_APB1ENR_TIM7EN (5) +#define STM_RCC_APB1ENR_TIM6EN (4) +#define STM_RCC_APB1ENR_TIM4EN (2) +#define STM_RCC_APB1ENR_TIM3EN (1) +#define STM_RCC_APB1ENR_TIM2EN (0) + +struct stm_pwr { + vuint32_t cr; + vuint32_t csr; +}; + +extern struct stm_pwr stm_pwr; + +#define STM_PWR_CR_LPRUN (14) + +#define STM_PWR_CR_VOS (11) +#define STM_PWR_CR_VOS_1_8 1 +#define STM_PWR_CR_VOS_1_5 2 +#define STM_PWR_CR_VOS_1_2 3 +#define STM_PWR_CR_VOS_MASK 3 + +#define STM_PWR_CR_FWU (10) +#define STM_PWR_CR_ULP (9) +#define STM_PWR_CR_DBP (8) + +#define STM_PWR_CR_PLS (5) +#define STM_PWR_CR_PLS_1_9 0 +#define STM_PWR_CR_PLS_2_1 1 +#define STM_PWR_CR_PLS_2_3 2 +#define STM_PWR_CR_PLS_2_5 3 +#define STM_PWR_CR_PLS_2_7 4 +#define STM_PWR_CR_PLS_2_9 5 +#define STM_PWR_CR_PLS_3_1 6 +#define STM_PWR_CR_PLS_EXT 7 +#define STM_PWR_CR_PLS_MASK 7 + +#define STM_PWR_CR_PVDE (4) +#define STM_PWR_CR_CSBF (3) +#define STM_PWR_CR_CWUF (2) +#define STM_PWR_CR_PDDS (1) +#define STM_PWR_CR_LPSDSR (0) + +#define STM_PWR_CSR_EWUP3 (10) +#define STM_PWR_CSR_EWUP2 (9) +#define STM_PWR_CSR_EWUP1 (8) +#define STM_PWR_CSR_REGLPF (5) +#define STM_PWR_CSR_VOSF (4) +#define STM_PWR_CSR_VREFINTRDYF (3) +#define STM_PWR_CSR_PVDO (2) +#define STM_PWR_CSR_SBF (1) +#define STM_PWR_CSR_WUF (0) + +struct stm_tim67 { + vuint32_t cr1; + vuint32_t cr2; + uint32_t _unused_08; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + uint32_t _unused_18; + uint32_t _unused_1c; + + uint32_t _unused_20; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; +}; + +extern struct stm_tim67 stm_tim6; + +#define STM_TIM67_CR1_ARPE (7) +#define STM_TIM67_CR1_OPM (3) +#define STM_TIM67_CR1_URS (2) +#define STM_TIM67_CR1_UDIS (1) +#define STM_TIM67_CR1_CEN (0) + +#define STM_TIM67_CR2_MMS (4) +#define STM_TIM67_CR2_MMS_RESET 0 +#define STM_TIM67_CR2_MMS_ENABLE 1 +#define STM_TIM67_CR2_MMS_UPDATE 2 +#define STM_TIM67_CR2_MMS_MASK 7 + +#define STM_TIM67_DIER_UDE (8) +#define STM_TIM67_DIER_UIE (0) + +#define STM_TIM67_SR_UIF (0) + +#define STM_TIM67_EGR_UG (0) + +struct stm_nvic { + vuint32_t iser[3]; /* 0x000 */ + + uint8_t _unused00c[0x080 - 0x00c]; + + vuint32_t icer[3]; /* 0x080 */ + + uint8_t _unused08c[0x100 - 0x08c]; + + vuint32_t ispr[3]; /* 0x100 */ + + uint8_t _unused10c[0x180 - 0x10c]; + + vuint32_t icpr[3]; /* 0x180 */ + + uint8_t _unused18c[0x200 - 0x18c]; + + vuint32_t iabr[3]; /* 0x200 */ + + uint8_t _unused20c[0x300 - 0x20c]; + + vuint32_t ipr[21]; /* 0x300 */ + + uint8_t _unused324[0xe00 - 0x324]; + + vuint32_t stir; /* 0xe00 */ +}; + +extern struct stm_nvic stm_nvic; + +#define IRQ_REG(irq) ((irq) >> 5) +#define IRQ_BIT(irq) ((irq) & 0x1f) +#define IRQ_MASK(irq) (1 << IRQ_BIT(irq)) +#define IRQ_BOOL(v,irq) (((v) >> IRQ_BIT(irq)) & 1) + +static inline void +stm_nvic_set_enable(int irq) { + stm_nvic.iser[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_enable(int irq) { + stm_nvic.icer[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_enabled(int irq) { + return IRQ_BOOL(stm_nvic.iser[IRQ_REG(irq)], irq); +} + +static inline void +stm_nvic_set_pending(int irq) { + stm_nvic.ispr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_pending(int irq) { + stm_nvic.icpr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_pending(int irq) { + return IRQ_BOOL(stm_nvic.ispr[IRQ_REG(irq)], irq); +} + +static inline int +stm_nvic_active(int irq) { + return IRQ_BOOL(stm_nvic.iabr[IRQ_REG(irq)], irq); +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +stm_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = stm_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + stm_nvic.ipr[n] = v; +} + +static inline uint8_t +stm_nvic_get_priority(int irq) { + return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + +#define isr(name) void stm_ ## name ## _isr(void); + +isr(nmi) +isr(hardfault) +isr(memmanage) +isr(busfault) +isr(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define STM_ISR_TIM6_POS 43 + +#undef isr + +#endif /* _STM32L_H_ */ -- cgit v1.2.3 From b8100ea5042013bb4eed67907b4e9d4e5c196df2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:23:31 -0700 Subject: Add stm bringup timers and move most of the setup code to the stm dir Signed-off-by: Keith Packard --- src/stm-bringup/Makefile | 33 +++++++++++++++++----------- src/stm-bringup/bringup.c | 56 +++++++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 49966a4f..1ba480ba 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -1,34 +1,41 @@ +vpath % ..:../core:../product:../drivers:../stm +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -C_LIB=/local/src/pdclib/pdclib.a -C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals +PDCLIB=/home/keithp/sat +C_LIB=$(PDCLIB)/lib/pdclib.a +C_INC=-I$(PDCLIB)/include -DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) +DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) # to run from SRAM -LD_FLAGS_RAM=-Wl,-Taltos-ram.ld -LD_FLAGS=-Wl,-Taltos.ld +LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld +LD_FLAGS=-L../stm -Wl,-Taltos.ld CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY -OBJS=bringup.o +SRC=bringup.c ao_interrupt.c +OBJ=$(SRC:.c=.o) all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJS) $(C_LIB) altos.ld - $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld - $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc +bringup.elf: $(OBJ) $(C_LIB) altos.ld + $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc -bringup.o: bringup.c - $(CC) -c $(CFLAGS) bringup.c +bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld + $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJ) $(C_LIB) -lgcc clean: + rm -f *.o rm -rf *.elf rm -rf *.bin diff --git a/src/stm-bringup/bringup.c b/src/stm-bringup/bringup.c index b6fe458d..c5fad4a3 100644 --- a/src/stm-bringup/bringup.c +++ b/src/stm-bringup/bringup.c @@ -250,13 +250,46 @@ serial_string(char *string) outbyte(c); } +volatile uint16_t tick_count; + +void +stm_tim6_isr(void) +{ + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + ++tick_count; + } +} + +#define TIMER_10kHz (STM_APB1 / 10000) + void set_timer6(void) { + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + /* Turn on timer 6 */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - + stm_tim6.psc = TIMER_10kHz; + stm_tim6.arr = 100; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + + /* And turn it on */ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); } void @@ -273,7 +306,7 @@ main (void) printf ("hello, "); delay(); stm_gpiob.odr = (1 << 6); - printf ("world\n"); + printf ("world %d\n", tick_count); delay(); } } @@ -285,22 +318,3 @@ delay(void) for (i = 0; i < 1000000; i++) __asm__ __volatile__ ("nop\n\t":::"memory"); } - -static int x = 7; - -extern char __stack__; -extern char __text_start__, __text_end__; -extern char __data_start__, __data_end__; -extern char __bss_start__, __bss_end__; - -void start(void) { - memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); - memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); - main(); -} - -__attribute__ ((section(".interrupt"))) -static const void *interrupt[] = { - &__stack__, - start, -}; -- cgit v1.2.3 From 1d1b24bb20dec09145fbaa6fe6897898d47dd16e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:24:29 -0700 Subject: These were moved to the src/stm directory Signed-off-by: Keith Packard --- ao-bringup/stm/altos-ram.ld | 69 ------------------------------------------- ao-bringup/stm/altos.ld | 71 --------------------------------------------- ao-bringup/stm/registers.ld | 46 ----------------------------- 3 files changed, 186 deletions(-) delete mode 100644 ao-bringup/stm/altos-ram.ld delete mode 100644 ao-bringup/stm/altos.ld delete mode 100644 ao-bringup/stm/registers.ld diff --git a/ao-bringup/stm/altos-ram.ld b/ao-bringup/stm/altos-ram.ld deleted file mode 100644 index b8fffedc..00000000 --- a/ao-bringup/stm/altos-ram.ld +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -MEMORY { - ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K -} - -C_STACK_SIZE = 512; - -INCLUDE registers.ld - -SECTIONS { - . = ORIGIN(ram); - - /* - * Rom contents - */ - - __text_start__ = .; - - .text : { - *(.interrupt) /* Interrupt vectors */ - *(.text) /* Executable code */ - *(.rodata) /* Constants */ - } > ram - - .ARM.exidx : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __text_end__ = .; - } > ram - - __data_start__ = .; - - /* Data -- relocated to RAM, but written to ROM - */ - .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { - *(.data) /* initialized data */ - __data_end__ = .; - __bss_start__ = .; - } >ram - - .bss : { - *(.bss) - *(COMMON) - __bss_end__ = .; - } >ram - - PROVIDE(__stack__ = . + C_STACK_SIZE); - PROVIDE(end = .); - -} - -ENTRY(start); - - diff --git a/ao-bringup/stm/altos.ld b/ao-bringup/stm/altos.ld deleted file mode 100644 index 0a25f853..00000000 --- a/ao-bringup/stm/altos.ld +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K -} - -INCLUDE registers.ld - -C_STACK_SIZE = 512; - -SECTIONS { - . = ORIGIN(rom); - - /* - * Rom contents - */ - - __text_start__ = .; - - .text : { - *(.interrupt) /* Interrupt vectors */ - *(.text) /* Executable code */ - *(.rodata) /* Constants */ - } > rom - - .ARM.exidx : { - *(.ARM.exidx* .gnu.linkonce.armexidx.*) - __text_end__ = .; - } > rom - - . = ORIGIN(ram); - __data_start__ = .; - - /* Data -- relocated to RAM, but written to ROM - */ - .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { - *(.data) /* initialized data */ - __data_end__ = .; - __bss_start__ = .; - } >ram - - .bss : { - *(.bss) - *(COMMON) - __bss_end__ = .; - } >ram - - PROVIDE(__stack__ = . + C_STACK_SIZE); - PROVIDE(end = .); - -} - -ENTRY(start); - - diff --git a/ao-bringup/stm/registers.ld b/ao-bringup/stm/registers.ld deleted file mode 100644 index 58204b9f..00000000 --- a/ao-bringup/stm/registers.ld +++ /dev/null @@ -1,46 +0,0 @@ -stm_fsmc = 0xa0000000; -stm_aes = 0x50060000; -stm_dma = 0x40026000; -stm_flash = 0x40023c00; -stm_rcc = 0x40023800; -stm_crc = 0x40023000; -stm_gpioh = 0x40021400; -stm_gpioe = 0x40021000; -stm_gpiod = 0x40020c00; -stm_gpioc = 0x40020800; -stm_gpiob = 0x40020400; -stm_gpioa = 0x40020000; -stm_usart1 = 0x40013800; -stm_spi1 = 0x40013000; -stm_sdio = 0x40012c00; -stm_adc = 0x40012400; -stm_tim11 = 0x40011000; -stm_tim10 = 0x40010c00; -stm_tim9 = 0x40010800; -stm_exti = 0x40010400; -stm_syscfg = 0x40010000; -stm_comp = 0x40007c00; -stm_ri = 0x40007c04; -stm_dac = 0x40007400; -stm_pwr = 0x40007000; -stm_usb_sram = 0x40006000; -stm_usb = 0x40005c00; -stm_i2c2 = 0x40005800; -stm_i2c1 = 0x40005400; -stm_usart5 = 0x40005000; -stm_usart4 = 0x40004c00; -stm_usart3 = 0x40004800; -stm_usart2 = 0x40004400; -stm_spi3 = 0x40003c00; /* docs are broken here */ -stm_spi2 = 0x40003800; /* docs are broken here */ -stm_iwdg = 0x40003000; -stm_wwdg = 0x40002c00; -stm_rtc = 0x40002800; -stm_lcd = 0x40002400; -stm_tim7 = 0x40001400; -stm_tim6 = 0x40001000; -stm_tim5 = 0x40000c00; -stm_tim4 = 0x40000800; -stm_tim3 = 0x40000400; -stm_tim2 = 0x40000000; - -- cgit v1.2.3 From 8ba5344514f8ed51f6fd69ca09f6c7035c4fd0da Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Mar 2012 00:06:59 -0700 Subject: Add stm-demo program This runs AltOS and talks over the serial port. Signed-off-by: Keith Packard --- src/stm-demo/.gitignore | 2 + src/stm-demo/Makefile | 95 ++++++++++++++++++++++++++++ src/stm-demo/ao_demo.c | 49 ++++++++++++++ src/stm-demo/ao_pins.h | 27 ++++++++ src/stm/ao_arch.h | 4 ++ src/stm/ao_romconfig.c | 20 ++++++ src/stm/ao_serial_stm.c | 111 +++++++++++++++++++++----------- src/stm/ao_timer.c | 165 +++++++++++++++++++++++++++++++++--------------- src/stm/stm32l.h | 13 ++++ 9 files changed, 398 insertions(+), 88 deletions(-) create mode 100644 src/stm-demo/.gitignore create mode 100644 src/stm-demo/Makefile create mode 100644 src/stm-demo/ao_demo.c create mode 100644 src/stm-demo/ao_pins.h create mode 100644 src/stm/ao_romconfig.c diff --git a/src/stm-demo/.gitignore b/src/stm-demo/.gitignore new file mode 100644 index 00000000..32b08ce8 --- /dev/null +++ b/src/stm-demo/.gitignore @@ -0,0 +1,2 @@ +stm-demo +ao_product.h diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile new file mode 100644 index 00000000..e009c30c --- /dev/null +++ b/src/stm-demo/Makefile @@ -0,0 +1,95 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../stm +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +#PROGRAMMER=stk500v2 -P usb +#PROGRAMMER=usbtiny +#LOADCMD=avrdude +#LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=arm-none-eabi-gcc +#OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_task.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_serial_stm.c + +PRODUCT=StmDemo-v0.0 +PRODUCT_DEF=-DSTM_DEMO +IDPRODUCT=0x000a +CPU=cortex-m3 +CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. +CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) + +NICKLE=nickle + +PROG=stm-demo + +SRC=$(ALTOS_SRC) ao_demo.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CLIB=/home/keithp/sat/lib/pdclib.a +CINC=-I/home/keithp/sat/include +LDFLAGS=-L../stm -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(CLIB) -lgcc + +../altitude.h: make-altitude + nickle $< > $@ + +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 + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h \ No newline at end of file diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c new file mode 100644 index 00000000..90216535 --- /dev/null +++ b/src/stm-demo/ao_demo.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +struct ao_task demo_task; + +void +ao_demo(void) +{ + int i = 0; + for (;;) { + printf ("hello %d\n", i++); + } +} + +void _close() { } +void _sbrk() { } +void _isatty() { } +void _lseek() { } +void _exit () { } +void _read () { } +void _fstat() { } +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + ao_timer_init(); + ao_cmd_init(); + + ao_demo(); + return 0; +} diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h new file mode 100644 index 00000000..82d70bb6 --- /dev/null +++ b/src/stm-demo/ao_pins.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_STDIN 1 +#define HAS_USB 0 +#define HAS_BEEP 0 +#define PACKET_HAS_SLAVE 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index e6f54fdb..b3c0190d 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -124,6 +124,10 @@ struct ao_adc { uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ }; +/* + * For now, we're running at a weird frequency + */ +#define STM_APB1 (16000000 * 6 / 4) #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c new file mode 100644 index 00000000..bbb677e2 --- /dev/null +++ b/src/stm/ao_romconfig.c @@ -0,0 +1,20 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +const uint16_t ao_serial_number = 0; diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index dc446120..ead2570f 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -25,11 +25,16 @@ ao_debug_out(char c) { if (c == '\n') ao_debug_out('\r'); - while (!(STM_USART1->usart_sr & (1 << STM_USART_SR_TXE))); - STM_USART1->usart_dr = c; + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))); + stm_usart1.dr = c; +} + +void +outbyte(char c) +{ + putchar(c); } -#if 0 static __xdata uint8_t ao_serial_tx1_started; static void @@ -39,21 +44,26 @@ ao_serial_tx1_start(void) !ao_serial_tx1_started) { ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, STM_USART1->usart_dr); + ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr); } } -void usart1_isr(void) +void stm_usart1_isr(void) { - if (STM_USART1->usart_sr & (1 << STM_USART_SR_RXNE)) { + uint32_t sr; + cli(); + sr = stm_usart1.sr; + stm_usart1.sr = 0; + sei(); + if (sr & (1 << STM_USART_SR_RXNE)) { if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, STM_USART1->usart_dr); + ao_fifo_insert(ao_usart1_rx_fifo, stm_usart1.dr); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN ao_wakeup(&ao_stdin_ready); #endif } - if (STM_USART1->usart_sr & (1 << STM_USART_SR_TXE)) { + if (sr & (1 << STM_USART_SR_TXE)) { ao_serial_tx1_started = 0; ao_serial_tx1_start(); ao_wakeup(&ao_usart1_tx_fifo); @@ -108,8 +118,6 @@ ao_serial_drain(void) __critical sei(); } -#endif - int _write(int file, char *ptr, int len) { int l = len; @@ -118,22 +126,20 @@ int _write(int file, char *ptr, int len) return len; } -#define F_CPU 24000000 - static const struct { - uint32_t usart_brr; + uint32_t brr; } ao_serial_speeds[] = { [AO_SERIAL_SPEED_4800] = { - (F_CPU * 16) / (16 * 4800) + STM_APB1 / 4800 }, [AO_SERIAL_SPEED_9600] = { - (F_CPU * 16) / (16 * 9600) + STM_APB1 / 9600 }, [AO_SERIAL_SPEED_19200] = { - (F_CPU * 16) / (16 * 19200) + STM_APB1 / 19200 }, [AO_SERIAL_SPEED_57600] = { - (F_CPU * 16) / (16 * 57600) + STM_APB1 / 57600 }, }; @@ -145,30 +151,60 @@ ao_serial_set_speed(uint8_t speed) #endif if (speed > AO_SERIAL_SPEED_57600) return; - STM_USART1->usart_brr = ao_serial_speeds[speed].usart_brr; + stm_usart1.brr = ao_serial_speeds[speed].brr; } void ao_serial_init(void) { - STM_USART1->usart_cr1 = ((0 << STM_USART_CR1_OVER8) | - (1 << STM_USART_CR1_UE) | - (0 << STM_USART_CR1_M) | - (0 << STM_USART_CR1_WAKE) | - (0 << STM_USART_CR1_PCE) | - (0 << STM_USART_CR1_PS) | - (0 << STM_USART_CR1_PEIE) | - (0 << STM_USART_CR1_TXEIE) | /* XXX enable */ - (0 << STM_USART_CR1_TCIE) | - (0 << STM_USART_CR1_RXNEIE) | /* XXX enable */ - (0 << STM_USART_CR1_IDLEIE) | - (1 << STM_USART_CR1_TE) | - (1 << STM_USART_CR1_RE) | - (0 << STM_USART_CR1_RWU) | - (0 << STM_USART_CR1_SBK)); - - STM_USART1->usart_cr2 = 0; - STM_USART1->usart_cr3 = 0; + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART1 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (1 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (1 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CPHA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADD)); + + stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + (0 << STM_USART_CR3_CTSIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); /* Pick a 9600 baud rate */ ao_serial_set_speed(AO_SERIAL_SPEED_9600); @@ -181,4 +217,7 @@ ao_serial_init(void) NULL); #endif #endif + + stm_nvic_set_enable(STM_ISR_USART1_POS); + stm_nvic_set_priority(STM_ISR_USART1_POS, 4); } diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f253e0c0..76304f0e 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -37,9 +37,6 @@ ao_delay(uint16_t ticks) ao_sleep(&ao_forever); } -#define T2_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -#define T2_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ - #if HAS_ADC volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; @@ -49,7 +46,7 @@ void ao_debug_out(char c); -void tim2_isr(void) +void stm_tim6_isr(void) { ++ao_tick_count; #if HAS_ADC @@ -69,99 +66,163 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif +#define TIMER_10kHz (STM_APB1 / 10000) + void ao_timer_init(void) { + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + stm_tim6.psc = TIMER_10kHz; + stm_tim6.arr = 100; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + + /* And turn it on */ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); } void ao_clock_init(void) { uint32_t cfgr; + uint32_t cr; /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = STM_FLASH->acr; + uint32_t acr = stm_flash.acr; /* Enable 64-bit access and prefetch */ acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - STM_FLASH->acr = acr; + stm_flash.acr = acr; /* Enable 1 wait state so the CPU can run at 32MHz */ + /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ acr |= (1 << STM_FLASH_ACR_LATENCY); - STM_FLASH->acr = acr; + stm_flash.acr = acr; + + /* HCLK to 16MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); +#define STM_AHB_PRESCALER 1 + + /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + stm_rcc.cfgr = cfgr; +#define STM_APB1_PRESCALER 1 + + /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + stm_rcc.cfgr = cfgr; +#define STM_APB2_PRESCALER 1 + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); /* Enable HSI RC clock 16MHz */ - if (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) { - STM_RCC->cr |= (1 << STM_RCC_CR_HSION); - while (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) asm("nop"); } +#define STM_HSI 16000000 /* Switch to direct HSI for SYSCLK */ - if ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { - cfgr = STM_RCC->cfgr; + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) asm("nop"); } /* Disable the PLL */ - STM_RCC->cr &= ~(1 << STM_RCC_CR_PLLON); - while (STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY)) + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) asm("nop"); - /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6 */ - cfgr = STM_RCC->cfgr; + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - - /* SYSCLK to 32MHz from PLL clock -> PLLDIV = /3 */ cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); - cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + +// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); +// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + +#define STM_PLLMUL 6 +#define STM_PLLDIV 4 /* PLL source to HSI */ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - STM_RCC->cfgr = cfgr; +#define STM_PLLSRC STM_HSI + + stm_rcc.cfgr = cfgr; /* Enable the PLL and wait for it */ - STM_RCC->cr |= (1 << STM_RCC_CR_PLLON); - while (!(STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY))) + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) asm("nop"); /* Switch to the PLL for the system clock */ - cfgr = STM_RCC->cfgr; + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS)) - asm("nop"); - - /* HCLK to 32MHz -> AHB prescaler = /1 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) - asm ("nop"); - - /* PCLK1 to 16MHz -> APB1 Prescaler = 2 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_2 << STM_RCC_CFGR_PPRE1); - STM_RCC->cfgr = cfgr; - - /* PCLK2 to 16MHz -> APB2 Prescaler = 2 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_2 << STM_RCC_CFGR_PPRE2); - STM_RCC->cfgr = cfgr; - + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } } diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index c5e2a797..5b3f6b2f 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -655,7 +655,20 @@ isr(usb_fs_wkup) isr(tim6) isr(tim7) +#define STM_ISR_TIM9_POS 25 +#define STM_ISR_TIM10_POS 26 +#define STM_ISR_TIM11_POS 27 +#define STM_ISR_TIM2_POS 28 +#define STM_ISR_TIM3_POS 29 +#define STM_ISR_TIM4_POS 30 + +#define STM_ISR_SPI1_POS 35 +#define STM_ISR_SPI2_POS 36 +#define STM_ISR_USART1_POS 37 +#define STM_ISR_USART2_POS 38 +#define STM_ISR_USART3_POS 39 #define STM_ISR_TIM6_POS 43 +#define STM_ISR_TIM7_POS 44 #undef isr -- cgit v1.2.3 From 93481fd3d9305a107b88c8a64de4194a6d94dc0e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:05:46 -0700 Subject: Incorrect type in ao_task_info for wchan Would truncate 32-bit pointers on arm. Signed-off-by: Keith Packard --- src/core/ao_task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a19a6a6f..d7d0e8a2 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -164,7 +164,7 @@ ao_task_info(void) task = ao_tasks[i]; printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan); + (int) task->wchan); } } -- cgit v1.2.3 From 4bfce11873f34af9621c60f83a8355f85769f6d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:07:07 -0700 Subject: When debugging, send pre-init output to ao_debug_out Before tasking is running, send output to ao_debug_out to help debug system initialization. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index c0138a30..2967e705 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -30,6 +30,15 @@ __pdata int8_t ao_num_stdios; void putchar(char c) { +#if LOW_LEVEL_DEBUG + if (!ao_cur_task) { + extern void ao_debug_out(char c); + if (c == '\n') + ao_debug_out('\r'); + ao_debug_out(c); + return; + } +#endif if (c == '\n') (*ao_stdios[ao_cur_stdio].putchar)('\r'); (*ao_stdios[ao_cur_stdio].putchar)(c); -- cgit v1.2.3 From 1ca46760cf903860dccb4864578558a1abb6e0fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:08:48 -0700 Subject: When debugging, send ao_panic message to ao_debug_out Use the low-level debug hooks to get the panic state sent to the serial port. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 244917a8..25dc145e 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -45,6 +45,10 @@ ao_panic(uint8_t reason) { uint8_t n; +#if LOW_LEVEL_DEBUG + ao_cur_task = NULL; + printf ("panic %d\n", reason); +#endif __critical for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { -- cgit v1.2.3 From 0cc01d378ae96325e429ad608b953661582939b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:09:20 -0700 Subject: Add AO_PANIC_STACK Provide a panic code for stack overflow. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ao.h b/src/core/ao.h index ac51c270..86a943a8 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -113,6 +113,7 @@ ao_start_scheduler(void); #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ +#define AO_PANIC_STACK 12 /* Stack overflow */ /* Stop the operating system, beeping and blinking the reason */ void -- cgit v1.2.3 From ab6ea9043b592c25948a70b6204d613756a9a250 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:10:02 -0700 Subject: Basic OS running on STM32L This gets stm-demo working Signed-off-by: Keith Packard --- src/Makefile | 1 + src/stm-demo/Makefile | 2 +- src/stm-demo/ao_demo.c | 5 ++-- src/stm-demo/ao_pins.h | 2 ++ src/stm/ao_arch.h | 19 ++++++++------- src/stm/ao_serial_stm.c | 15 ++++++------ src/stm/ao_timer.c | 13 +++++++---- src/stm/stm32l.h | 61 +++++++++++++++++++++++++++++++++++++------------ 8 files changed, 77 insertions(+), 41 deletions(-) diff --git a/src/Makefile b/src/Makefile index e5d0c960..3603c277 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ + stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index e009c30c..a675182e 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -47,7 +47,7 @@ PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 90216535..5fe0b154 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -42,8 +42,9 @@ main(void) ao_serial_init(); ao_timer_init(); - ao_cmd_init(); +// ao_cmd_init(); - ao_demo(); + ao_add_task(&demo_task, ao_demo, "demo"); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 82d70bb6..f436e9c8 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -24,4 +24,6 @@ #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 +#define LOW_LEVEL_DEBUG 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index b3c0190d..205f95d7 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 256 +#define AO_STACK_SIZE 1024 /* Various definitions to make GCC look more like SDCC */ @@ -67,29 +67,26 @@ extern const uint16_t ao_serial_number; #define ao_arch_init_stack(task, start) do { \ uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ - uint16_t a = (uint16_t) start; \ + uint32_t a = (uint32_t) start; \ int i; \ \ - /* Return address */ \ + /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ - /* Invalid link register */ \ - ARM_PUSH32(sp, 0xffffffff); \ - \ /* Clear register values */ \ i = 13; \ while (i--) \ ARM_PUSH32(sp, 0); \ \ - /* PSR with interrupts enabled */ \ - ARM_PUSH32(sp, 0x01000000); \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ task->sp = sp; \ } while (0); #define ao_arch_save_regs() do { \ asm("push {r0-r12,lr}\n"); \ cli(); \ - asm("mrs r0,psr" "\n\t" "push {r0}"); \ + asm("mrs r0,apsr" "\n\t" "push {r0}"); \ sei(); \ } while (0) @@ -97,6 +94,8 @@ extern const uint16_t ao_serial_number; uint32_t sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ ao_cur_task->sp = (uint32_t *) (sp); \ + if ((uint8_t *) ao_cur_task->sp < ao_cur_task->stack) \ + ao_panic (AO_PANIC_STACK); \ } while (0) #define ao_arch_isr_stack() /* nothing */ @@ -110,7 +109,7 @@ extern const uint16_t ao_serial_number; sp = (uint32_t) ao_cur_task->sp; \ cli(); \ asm("mov sp, %0" : : "r" (sp) ); \ - asm("pop {r0}" "\n\t" "msr psr,r0"); \ + asm("pop {r0}" "\n\t" "msr apsr,r0"); \ asm("pop {r0-r12,lr}\n"); \ asm("bx lr"); \ } while(0) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index ead2570f..38f16e5e 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -51,19 +51,20 @@ ao_serial_tx1_start(void) void stm_usart1_isr(void) { uint32_t sr; - cli(); + sr = stm_usart1.sr; stm_usart1.sr = 0; - sei(); + if (sr & (1 << STM_USART_SR_RXNE)) { + char c = stm_usart1.dr; if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, stm_usart1.dr); + ao_fifo_insert(ao_usart1_rx_fifo, c); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN ao_wakeup(&ao_stdin_ready); #endif } - if (sr & (1 << STM_USART_SR_TXE)) { + if (sr & (1 << STM_USART_SR_TC)) { ao_serial_tx1_started = 0; ao_serial_tx1_start(); ao_wakeup(&ao_usart1_tx_fifo); @@ -174,8 +175,8 @@ ao_serial_init(void) (0 << STM_USART_CR1_PCE) | (0 << STM_USART_CR1_PS) | (0 << STM_USART_CR1_PEIE) | - (1 << STM_USART_CR1_TXEIE) | - (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_TXEIE) | + (1 << STM_USART_CR1_TCIE) | (1 << STM_USART_CR1_RXNEIE) | (0 << STM_USART_CR1_IDLEIE) | (1 << STM_USART_CR1_TE) | @@ -210,12 +211,10 @@ ao_serial_init(void) ao_serial_set_speed(AO_SERIAL_SPEED_9600); printf ("serial initialized\n"); -#if 0 #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, ao_serial_putchar, NULL); -#endif #endif stm_nvic_set_enable(STM_ISR_USART1_POS); diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 76304f0e..387df184 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -48,13 +48,16 @@ ao_debug_out(char c); void stm_tim6_isr(void) { - ++ao_tick_count; + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + ++ao_tick_count; #if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; - ao_adc_poll(); - } + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } #endif + } } #if HAS_ADC diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 5b3f6b2f..d7c382a6 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -655,21 +655,52 @@ isr(usb_fs_wkup) isr(tim6) isr(tim7) -#define STM_ISR_TIM9_POS 25 -#define STM_ISR_TIM10_POS 26 -#define STM_ISR_TIM11_POS 27 -#define STM_ISR_TIM2_POS 28 -#define STM_ISR_TIM3_POS 29 -#define STM_ISR_TIM4_POS 30 - -#define STM_ISR_SPI1_POS 35 -#define STM_ISR_SPI2_POS 36 -#define STM_ISR_USART1_POS 37 -#define STM_ISR_USART2_POS 38 -#define STM_ISR_USART3_POS 39 -#define STM_ISR_TIM6_POS 43 -#define STM_ISR_TIM7_POS 44 - #undef isr +#define STM_ISR_WWDG_POS 0 +#define STM_ISR_PVD_POS 1 +#define STM_ISR_TAMPER_STAMP_POS 2 +#define STM_ISR_RTC_WKUP_POS 3 +#define STM_ISR_FLASH_POS 4 +#define STM_ISR_RCC_POS 5 +#define STM_ISR_EXTI0_POS 6 +#define STM_ISR_EXTI1_POS 7 +#define STM_ISR_EXTI2_POS 8 +#define STM_ISR_EXTI3_POS 9 +#define STM_ISR_EXTI4_POS 10 +#define STM_ISR_DMA1_CHANNEL1_POS 11 +#define STM_ISR_DMA2_CHANNEL1_POS 12 +#define STM_ISR_DMA3_CHANNEL1_POS 13 +#define STM_ISR_DMA4_CHANNEL1_POS 14 +#define STM_ISR_DMA5_CHANNEL1_POS 15 +#define STM_ISR_DMA6_CHANNEL1_POS 16 +#define STM_ISR_DMA7_CHANNEL1_POS 17 +#define STM_ISR_ADC1_POS 18 +#define STM_ISR_USB_HP_POS 19 +#define STM_ISR_USB_LP_POS 20 +#define STM_ISR_DAC_POS 21 +#define STM_ISR_COMP_POS 22 +#define STM_ISR_EXTI9_5_POS 23 +#define STM_ISR_LCD_POS 24 +#define STM_ISR_TIM9_POS 25 +#define STM_ISR_TIM10_POS 26 +#define STM_ISR_TIM11_POS 27 +#define STM_ISR_TIM2_POS 28 +#define STM_ISR_TIM3_POS 29 +#define STM_ISR_TIM4_POS 30 +#define STM_ISR_I2C1_EV_POS 31 +#define STM_ISR_I2C1_ER_POS 32 +#define STM_ISR_I2C2_EV_POS 33 +#define STM_ISR_I2C2_ER_POS 34 +#define STM_ISR_SPI1_POS 35 +#define STM_ISR_SPI2_POS 36 +#define STM_ISR_USART1_POS 37 +#define STM_ISR_USART2_POS 38 +#define STM_ISR_USART3_POS 39 +#define STM_ISR_EXTI15_10_POS 40 +#define STM_ISR_RTC_ALARM_POS 41 +#define STM_ISR_USB_FS_WKUP_POS 42 +#define STM_ISR_TIM6_POS 43 +#define STM_ISR_TIM7_POS 44 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 4be74ef0d13114707fd8217907a5ec457f886160 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:26:43 -0700 Subject: Fix STM LED driver and blink LEDs on discovery board This adds a task to blink the LEDs, after first fixing up the LED output code to enable the GPIO and talk to the right pins for the discovery board. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 1 + src/stm-demo/ao_demo.c | 13 +++++++++---- src/stm-demo/ao_pins.h | 11 +++++++++++ src/stm/ao_led.c | 17 ++++++++--------- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index a675182e..b2413a2c 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -37,6 +37,7 @@ ALTOS_SRC = \ ao_romconfig.c \ ao_cmd.c \ ao_task.c \ + ao_led.c \ ao_stdio.c \ ao_panic.c \ ao_timer.c \ diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5fe0b154..94527089 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -22,9 +22,13 @@ struct ao_task demo_task; void ao_demo(void) { - int i = 0; for (;;) { - printf ("hello %d\n", i++); + ao_led_on(AO_LED_BLUE); + ao_delay(AO_MS_TO_TICKS(500)); + ao_led_off(AO_LED_BLUE); + ao_led_on(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(500)); + ao_led_off(AO_LED_GREEN); } } @@ -42,9 +46,10 @@ main(void) ao_serial_init(); ao_timer_init(); -// ao_cmd_init(); - + ao_cmd_init(); + ao_led_init(LEDS_AVAILABLE); ao_add_task(&demo_task, ao_demo, "demo"); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index f436e9c8..39d4fc3c 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -26,4 +26,15 @@ #define LOW_LEVEL_DEBUG 1 +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN +#define LED_PORT stm_gpiob +#define LED_PIN_GREEN 7 +#define LED_PIN_BLUE 6 +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_BLUE (1 << LED_PIN_BLUE) + +#define AO_LED_RED AO_LED_BLUE /* a patent lie */ + +#define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN) + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index db65afdf..0574aa2a 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -19,30 +19,28 @@ __pdata uint8_t ao_led_enable; -#define LED_PORT STM_GPIOD - void ao_led_on(uint8_t colors) { - LED_PORT->odr |= (colors & ao_led_enable); + LED_PORT.odr |= (colors & ao_led_enable); } void ao_led_off(uint8_t colors) { - LED_PORT->odr &= ~(colors & ao_led_enable); + LED_PORT.odr &= ~(colors & ao_led_enable); } void ao_led_set(uint8_t colors) { - LED_PORT->odr = (LED_PORT->odr & ~(ao_led_enable)) | (colors & ao_led_enable); + LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); } void ao_led_toggle(uint8_t colors) { - LED_PORT->odr ^= (colors & ao_led_enable); + LED_PORT.odr ^= (colors & ao_led_enable); } void @@ -58,12 +56,13 @@ ao_led_init(uint8_t enable) { int bit; + stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); ao_led_enable = enable; - LED_PORT->odr &= ~enable; + LED_PORT.odr &= ~enable; for (bit = 0; bit < 16; bit++) { if (enable & (1 << bit)) { - stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); - stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); + stm_moder_set(&LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(&LED_PORT, bit, STM_OTYPER_PUSH_PULL); } } } -- cgit v1.2.3 From 7662a0096a860cddac413a310305fe842830c3b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:29:51 -0700 Subject: Add .gitignore file to stm-bringup Ignore generated binaries Signed-off-by: Keith Packard --- src/stm-bringup/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/stm-bringup/.gitignore diff --git a/src/stm-bringup/.gitignore b/src/stm-bringup/.gitignore new file mode 100644 index 00000000..50992530 --- /dev/null +++ b/src/stm-bringup/.gitignore @@ -0,0 +1 @@ +*.elf -- cgit v1.2.3 From 6a14bee42a8431c909bcd74b0acec57329bc0284 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Mar 2012 11:24:43 -0700 Subject: Don't disable interrupts before saving interrupt flag on AVR This ignores the interrupt disabled state, so we'd always leave ao_yield with interrupts disabled. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c189ccba..b816279e 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -105,7 +105,6 @@ extern uint8_t ao_cpu_sleep_disable; asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ - cli(); \ asm("in r0, __SREG__" "\n\t" "push r0"); \ sei(); \ } while (0) -- cgit v1.2.3 From faf2bea4fdb3dca7fbed35423a4fe4459ee92ceb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Mar 2012 11:25:40 -0700 Subject: Save/restore PRIMASK register on Cortex-M3 This preserves the interrupt-enabled bit across context switches Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 9 ++++++--- src/stm/ao_arch.h | 51 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index b2413a2c..9e4f9e38 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -3,8 +3,8 @@ # # vpath % ..:../core:../product:../drivers:../stm -vpath make-altitude .. -vpath make-kalman .. +vpath make-altitude ../util +vpath make-kalman ../util vpath kalman.5c ../kalman vpath kalman_filter.5c ../kalman vpath load_csv.5c ../kalman @@ -24,6 +24,7 @@ endif INC = \ ao.h \ + ao_arch.h \ ao_pins.h \ altitude.h \ ao_kalman.h @@ -48,7 +49,7 @@ PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle @@ -77,6 +78,8 @@ $(PROG): Makefile $(OBJ) ../altitude.h: make-altitude nickle $< > $@ +$(OBJ): $(INC) + ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 205f95d7..c4b98c7a 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -70,31 +70,44 @@ extern const uint16_t ao_serial_number; uint32_t a = (uint32_t) start; \ int i; \ \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ + \ + /* PRIMASK with interrupts enabled */ \ + ARM_PUSH32(sp, 0); \ + \ /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ - /* Clear register values */ \ + /* Clear register values r0-r12 */ \ i = 13; \ while (i--) \ ARM_PUSH32(sp, 0); \ \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ task->sp = sp; \ } while (0); -#define ao_arch_save_regs() do { \ +#define ao_arch_save_regs() do { \ + uint32_t apsr; \ + uint32_t primask; \ + \ + /* Save APSR */ \ + asm("mrs %0,apsr" : "=&r" (apsr)); \ + asm("push {%0}" : : "r" (apsr)); \ + \ + /* Save PRIMASK */ \ + asm("mrs %0,primask" : "=&r" (primask)); \ + asm("push {%0}" : : "r" (primask)); \ + \ + /* Save general registers */ \ asm("push {r0-r12,lr}\n"); \ - cli(); \ - asm("mrs r0,apsr" "\n\t" "push {r0}"); \ - sei(); \ } while (0) #define ao_arch_save_stack() do { \ - uint32_t sp; \ + uint32_t *sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ - ao_cur_task->sp = (uint32_t *) (sp); \ - if ((uint8_t *) ao_cur_task->sp < ao_cur_task->stack) \ + ao_cur_task->sp = (sp); \ + if ((uint8_t *) sp < ao_cur_task->stack) \ ao_panic (AO_PANIC_STACK); \ } while (0) @@ -106,11 +119,25 @@ extern const uint16_t ao_serial_number; #define ao_arch_restore_stack() do { \ uint32_t sp; \ + uint32_t primask; \ + uint32_t apsr; \ sp = (uint32_t) ao_cur_task->sp; \ - cli(); \ + \ + /* Switch stacks */ \ asm("mov sp, %0" : : "r" (sp) ); \ - asm("pop {r0}" "\n\t" "msr apsr,r0"); \ + \ + /* Restore general registers */ \ asm("pop {r0-r12,lr}\n"); \ + \ + /* Restore PRIMASK */ \ + asm("pop {%0}" : "=&r" (primask) ); \ + asm("msr primask,%0" : : "r" (primask) ); \ + \ + /* Restore APSR */ \ + asm("pop {%0}" : "=&r" (apsr) ); \ + asm("msr apsr,%0" : : "r" (apsr) ); \ + \ + /* Return to calling function */ \ asm("bx lr"); \ } while(0) -- cgit v1.2.3 From f560c961ae4fedec0c9f11d5b3635fcb0d67ed8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Mar 2012 16:18:26 -0700 Subject: Add support for multiple serial ports on STM32L Signed-off-by: Keith Packard --- src/stm-demo/ao_pins.h | 2 + src/stm/ao_serial_stm.c | 236 +++++++++++++++++++++++++++++++++--------------- src/stm/stm32l.h | 2 + 3 files changed, 168 insertions(+), 72 deletions(-) diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 39d4fc3c..c72cd04b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,6 +19,8 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 +#define HAS_SERIAL_2 1 +#define HAS_SERIAL_3 1 #define USE_SERIAL_STDIN 1 #define HAS_USB 0 #define HAS_BEEP 0 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 38f16e5e..9302bdf8 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -17,8 +17,22 @@ #include -__xdata struct ao_fifo ao_usart1_rx_fifo; -__xdata struct ao_fifo ao_usart1_tx_fifo; +struct ao_stm_usart { + struct ao_fifo rx_fifo; + struct ao_fifo tx_fifo; + struct stm_usart *reg; + uint8_t tx_started; +}; + +#if HAS_SERIAL_1 +struct ao_stm_usart ao_stm_usart1; +#endif +#if HAS_SERIAL_2 +struct ao_stm_usart ao_stm_usart2; +#endif +#if HAS_SERIAL_3 +struct ao_stm_usart ao_stm_usart3; +#endif void ao_debug_out(char c) @@ -29,107 +43,106 @@ ao_debug_out(char c) stm_usart1.dr = c; } +#if 0 void outbyte(char c) { putchar(c); } - -static __xdata uint8_t ao_serial_tx1_started; +#endif static void -ao_serial_tx1_start(void) +ao_usart_tx_start(struct ao_stm_usart *usart) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) + if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr); + usart->tx_started = 1; + ao_fifo_remove(usart->tx_fifo, usart->reg->dr); } } -void stm_usart1_isr(void) +static void +ao_usart_isr(struct ao_stm_usart *usart, int stdin) { uint32_t sr; - sr = stm_usart1.sr; - stm_usart1.sr = 0; + sr = usart->reg->sr; + usart->reg->sr = 0; if (sr & (1 << STM_USART_SR_RXNE)) { - char c = stm_usart1.dr; - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, c); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN - ao_wakeup(&ao_stdin_ready); -#endif + char c = usart->reg->dr; + if (!ao_fifo_full(usart->rx_fifo)) + ao_fifo_insert(usart->rx_fifo, c); + ao_wakeup(&usart->rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); } if (sr & (1 << STM_USART_SR_TC)) { - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + usart->tx_started = 0; + ao_usart_tx_start(usart); + ao_wakeup(&usart->tx_fifo); } } +#if HAS_SERIAL_1 +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } +#endif +#if HAS_SERIAL_2 +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } +#endif +#if HAS_SERIAL_3 +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } +#endif + char -ao_serial_getchar(void) __critical +ao_usart_getchar(struct ao_stm_usart *usart) { - char c; + char c; cli(); - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(usart->rx_fifo)) + ao_sleep(&usart->rx_fifo); + ao_fifo_remove(usart->rx_fifo, c); sei(); return c; } -#if USE_SERIAL_STDIN char -ao_serial_pollchar(void) __critical +ao_usart_pollchar(struct ao_stm_usart *usart) { char c; cli(); - if (ao_fifo_empty(ao_usart1_rx_fifo)) { + if (ao_fifo_empty(usart->rx_fifo)) { sei(); return AO_READ_AGAIN; } - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(usart->rx_fifo,c); sei(); return c; } -#endif void -ao_serial_putchar(char c) __critical +ao_usart_putchar(struct ao_stm_usart *usart, char c) { cli(); - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); + while (ao_fifo_full(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); + ao_fifo_insert(usart->tx_fifo, c); + ao_usart_tx_start(usart); sei(); } void -ao_serial_drain(void) __critical +ao_usart_drain(struct ao_stm_usart *usart) { cli(); - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); sei(); } -int _write(int file, char *ptr, int len) -{ - int l = len; - while (l--) - ao_debug_out(*ptr++); - return len; -} - static const struct { uint32_t brr; -} ao_serial_speeds[] = { +} ao_usart_speeds[] = { [AO_SERIAL_SPEED_4800] = { STM_APB1 / 4800 }, @@ -145,30 +158,17 @@ static const struct { }; void -ao_serial_set_speed(uint8_t speed) +ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { -#if 0 - ao_serial_drain(); -#endif if (speed > AO_SERIAL_SPEED_57600) return; - stm_usart1.brr = ao_serial_speeds[speed].brr; + stm_usart1.brr = ao_usart_speeds[speed].brr; } void -ao_serial_init(void) +ao_usart_init(struct ao_stm_usart *usart) { - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); - - /* Enable USART1 */ - stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - - stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) | (1 << STM_USART_CR1_UE) | (0 << STM_USART_CR1_M) | (0 << STM_USART_CR1_WAKE) | @@ -184,7 +184,7 @@ ao_serial_init(void) (0 << STM_USART_CR1_RWU) | (0 << STM_USART_CR1_SBK)); - stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + usart->reg->cr2 = ((0 << STM_USART_CR2_LINEN) | (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | (0 << STM_USART_CR2_CLKEN) | (0 << STM_USART_CR2_CPOL) | @@ -194,7 +194,7 @@ ao_serial_init(void) (0 << STM_USART_CR2_LBDL) | (0 << STM_USART_CR2_ADD)); - stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + usart->reg->cr3 = ((0 << STM_USART_CR3_ONEBITE) | (0 << STM_USART_CR3_CTSIE) | (0 << STM_USART_CR3_CTSE) | (0 << STM_USART_CR3_RTSE) | @@ -208,15 +208,107 @@ ao_serial_init(void) (0 << STM_USART_CR3_EIE)); /* Pick a 9600 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); +} + +void +ao_serial_init(void) +{ +#ifdef HAS_SERIAL_1 + /* + * TX RX + * PA9 PA10 + * PB6 PB7 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - printf ("serial initialized\n"); + ao_stm_usart1.reg = &stm_usart1; + + stm_nvic_set_enable(STM_ISR_USART1_POS); + stm_nvic_set_priority(STM_ISR_USART1_POS, 4); #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, ao_serial_putchar, NULL); #endif +#endif - stm_nvic_set_enable(STM_ISR_USART1_POS); - stm_nvic_set_priority(STM_ISR_USART1_POS, 4); +#if HAS_SERIAL_2 + /* + * TX RX + * PA2 PA3 + * PD5 PD6 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 3, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + + ao_stm_usart2.reg = &stm_usart2; + + stm_nvic_set_enable(STM_ISR_USART2_POS); + stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +#endif + +#if HAS_SERIAL_3 + /* + * TX RX + * PB10 PB11 + * PC10 PC11 + * PD8 PD9 + */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + + stm_moder_set(&stm_gpiob, 10, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpiob, 11, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpiob, 10, STM_AFR_AF7); + stm_afr_set(&stm_gpiob, 11, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); + + ao_stm_usart3.reg = &stm_usart3; + + stm_nvic_set_enable(STM_ISR_USART3_POS); + stm_nvic_set_priority(STM_ISR_USART3_POS, 4); +#endif +} + +#if HAS_SERIAL_1 +char +ao_serial_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart1); +} +#endif + +void +ao_serial_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); } +#endif /* HAS_SERIAL_1 */ + + diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index d7c382a6..21dc9a14 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -174,6 +174,8 @@ struct stm_usart { }; extern struct stm_usart stm_usart1; +extern struct stm_usart stm_usart2; +extern struct stm_usart stm_usart3; #define STM_USART_SR_CTS (9) /* CTS flag */ #define STM_USART_SR_LBD (8) /* LIN break detection flag */ -- cgit v1.2.3 From 03fbc18ea17a9e77a1d4d8e0ddb97abbe5da3658 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Mar 2012 16:24:06 -0700 Subject: Clean up multiple serial port support for STM32L Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 9302bdf8..881819db 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -24,16 +24,6 @@ struct ao_stm_usart { uint8_t tx_started; }; -#if HAS_SERIAL_1 -struct ao_stm_usart ao_stm_usart1; -#endif -#if HAS_SERIAL_2 -struct ao_stm_usart ao_stm_usart2; -#endif -#if HAS_SERIAL_3 -struct ao_stm_usart ao_stm_usart3; -#endif - void ao_debug_out(char c) { @@ -43,14 +33,6 @@ ao_debug_out(char c) stm_usart1.dr = c; } -#if 0 -void -outbyte(char c) -{ - putchar(c); -} -#endif - static void ao_usart_tx_start(struct ao_stm_usart *usart) { @@ -84,16 +66,6 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } } -#if HAS_SERIAL_1 -void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } -#endif -#if HAS_SERIAL_2 -void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } -#endif -#if HAS_SERIAL_3 -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } -#endif - char ao_usart_getchar(struct ao_stm_usart *usart) { @@ -211,6 +183,19 @@ ao_usart_init(struct ao_stm_usart *usart) ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } +#if HAS_SERIAL_1 +struct ao_stm_usart ao_stm_usart1; +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } +#endif +#if HAS_SERIAL_2 +struct ao_stm_usart ao_stm_usart2; +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } +#endif +#if HAS_SERIAL_3 +struct ao_stm_usart ao_stm_usart3; +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } +#endif + void ao_serial_init(void) { -- cgit v1.2.3 From f6e557bc2f0bd6d4272ed00dd09554d27a83be89 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:41:23 -0700 Subject: Actually enable usarts with the new usart code And move USART1 to PB6/PB7 to avoid conflicting with the LCD pins. Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 881819db..bd3b1e61 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -203,21 +203,22 @@ ao_serial_init(void) /* * TX RX * PA9 PA10 - * PB6 PB7 + * PB6 PB7 * */ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + stm_moder_set(&stm_gpiob, 6, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpiob, 7, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF7); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF7); /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - ao_stm_usart1.reg = &stm_usart1; + ao_usart_init(&ao_stm_usart1); + stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); #if USE_SERIAL_STDIN @@ -243,6 +244,7 @@ ao_serial_init(void) /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + ao_usart_init(&stm_usart1); ao_stm_usart2.reg = &stm_usart2; @@ -266,6 +268,7 @@ ao_serial_init(void) /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); + ao_usart_init(&stm_usart1); ao_stm_usart3.reg = &stm_usart3; -- cgit v1.2.3 From a953ac32033ded18adf0cb3ca20134385fcd0a6d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:42:18 -0700 Subject: Add defines for LCD controller and RTC clocking Signed-off-by: Keith Packard --- src/stm/stm32l.h | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 21dc9a14..50e5cc34 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -426,6 +426,30 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_APB1ENR_TIM3EN (1) #define STM_RCC_APB1ENR_TIM2EN (0) +#define STM_RCC_CSR_LPWRRSTF (31) +#define STM_RCC_CSR_WWDGRSTF (30) +#define STM_RCC_CSR_IWDGRSTF (29) +#define STM_RCC_CSR_SFTRSTF (28) +#define STM_RCC_CSR_PORRSTF (27) +#define STM_RCC_CSR_PINRSTF (26) +#define STM_RCC_CSR_OBLRSTF (25) +#define STM_RCC_CSR_RMVF (24) +#define STM_RCC_CSR_RTFRST (23) +#define STM_RCC_CSR_RTCEN (22) +#define STM_RCC_CSR_RTCSEL (16) + +#define STM_RCC_CSR_RTCSEL_NONE 0 +#define STM_RCC_CSR_RTCSEL_LSE 1 +#define STM_RCC_CSR_RTCSEL_LSI 2 +#define STM_RCC_CSR_RTCSEL_HSE 3 +#define STM_RCC_CSR_RTCSEL_MASK 3 + +#define STM_RCC_CSR_LSEBYP (10) +#define STM_RCC_CSR_LSERDY (9) +#define STM_RCC_CSR_LSEON (8) +#define STM_RCC_CSR_LSIRDY (1) +#define STM_RCC_CSR_LSION (0) + struct stm_pwr { vuint32_t cr; vuint32_t csr; @@ -510,6 +534,115 @@ extern struct stm_tim67 stm_tim6; #define STM_TIM67_EGR_UG (0) +struct stm_lcd { + vuint32_t cr; + vuint32_t fcr; + vuint32_t sr; + vuint32_t clr; + uint32_t unused_0x10; + vuint32_t ram[8*2]; +}; + +extern struct stm_lcd stm_lcd; + +#define STM_LCD_CR_MUX_SEG (7) + +#define STM_LCD_CR_BIAS (5) +#define STM_LCD_CR_BIAS_1_4 0 +#define STM_LCD_CR_BIAS_1_2 1 +#define STM_LCD_CR_BIAS_1_3 2 +#define STM_LCD_CR_BIAS_MASK 3 + +#define STM_LCD_CR_DUTY (2) +#define STM_LCD_CR_DUTY_STATIC 0 +#define STM_LCD_CR_DUTY_1_2 1 +#define STM_LCD_CR_DUTY_1_3 2 +#define STM_LCD_CR_DUTY_1_4 3 +#define STM_LCD_CR_DUTY_1_8 4 +#define STM_LCD_CR_DUTY_MASK 7 + +#define STM_LCD_CR_VSEL (1) +#define STM_LCD_CR_LCDEN (0) + +#define STM_LCD_FCR_PS (22) +#define STM_LCD_FCR_PS_1 0x0 +#define STM_LCD_FCR_PS_2 0x1 +#define STM_LCD_FCR_PS_4 0x2 +#define STM_LCD_FCR_PS_8 0x3 +#define STM_LCD_FCR_PS_16 0x4 +#define STM_LCD_FCR_PS_32 0x5 +#define STM_LCD_FCR_PS_64 0x6 +#define STM_LCD_FCR_PS_128 0x7 +#define STM_LCD_FCR_PS_256 0x8 +#define STM_LCD_FCR_PS_512 0x9 +#define STM_LCD_FCR_PS_1024 0xa +#define STM_LCD_FCR_PS_2048 0xb +#define STM_LCD_FCR_PS_4096 0xc +#define STM_LCD_FCR_PS_8192 0xd +#define STM_LCD_FCR_PS_16384 0xe +#define STM_LCD_FCR_PS_32768 0xf +#define STM_LCD_FCR_PS_MASK 0xf + +#define STM_LCD_FCR_DIV (18) +#define STM_LCD_FCR_DIV_16 0x0 +#define STM_LCD_FCR_DIV_17 0x1 +#define STM_LCD_FCR_DIV_18 0x2 +#define STM_LCD_FCR_DIV_19 0x3 +#define STM_LCD_FCR_DIV_20 0x4 +#define STM_LCD_FCR_DIV_21 0x5 +#define STM_LCD_FCR_DIV_22 0x6 +#define STM_LCD_FCR_DIV_23 0x7 +#define STM_LCD_FCR_DIV_24 0x8 +#define STM_LCD_FCR_DIV_25 0x9 +#define STM_LCD_FCR_DIV_26 0xa +#define STM_LCD_FCR_DIV_27 0xb +#define STM_LCD_FCR_DIV_28 0xc +#define STM_LCD_FCR_DIV_29 0xd +#define STM_LCD_FCR_DIV_30 0xe +#define STM_LCD_FCR_DIV_31 0xf +#define STM_LCD_FCR_DIV_MASK 0xf + +#define STM_LCD_FCR_BLINK (16) +#define STM_LCD_FCR_BLINK_DISABLE 0 +#define STM_LCD_FCR_BLINK_SEG0_COM0 1 +#define STM_LCD_FCR_BLINK_SEG0_COMALL 2 +#define STM_LCD_FCR_BLINK_SEGALL_COMALL 3 +#define STM_LCD_FCR_BLINK_MASK 3 + +#define STM_LCD_FCR_BLINKF (13) +#define STM_LCD_FCR_BLINKF_8 0 +#define STM_LCD_FCR_BLINKF_16 1 +#define STM_LCD_FCR_BLINKF_32 2 +#define STM_LCD_FCR_BLINKF_64 3 +#define STM_LCD_FCR_BLINKF_128 4 +#define STM_LCD_FCR_BLINKF_256 5 +#define STM_LCD_FCR_BLINKF_512 6 +#define STM_LCD_FCR_BLINKF_1024 7 +#define STM_LCD_FCR_BLINKF_MASK 7 + +#define STM_LCD_FCR_CC (10) +#define STM_LCD_FCR_CC_MASK 7 + +#define STM_LCD_FCR_DEAD (7) +#define STM_LCD_FCR_DEAD_MASK 7 + +#define STM_LCD_FCR_PON (4) +#define STM_LCD_FCR_PON_MASK 7 + +#define STM_LCD_FCR_UDDIE (3) +#define STM_LCD_FCR_SOFIE (1) +#define STM_LCD_FCR_HD (0) + +#define STM_LCD_SR_FCRSF (5) +#define STM_LCD_SR_RDY (4) +#define STM_LCD_SR_UDD (3) +#define STM_LCD_SR_UDR (2) +#define STM_LCD_SR_SOF (1) +#define STM_LCD_SR_ENS (0) + +#define STM_LCD_CLR_UDDC (3) +#define STM_LCD_CLR_SOFC (1) + struct stm_nvic { vuint32_t iser[3]; /* 0x000 */ -- cgit v1.2.3 From 6da2f5846f2d28ea1f09f60ef2cc3f68113ac62a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:43:29 -0700 Subject: Add LCD device driver to STM32L port This enables the 6-digit 14-character display on the STM32L discovery board and provides an ascii output to it. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 6 +- src/stm-demo/ao_demo.c | 5 +- src/stm-demo/ao_pins.h | 59 ++- src/stm/ao-parse-font.5c | 174 +++++++ src/stm/ao_arch.h | 4 + src/stm/ao_lcd_font.c | 101 ++++ src/stm/ao_lcd_font.h | 1152 ++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_lcd_stm.c | 393 ++++++++++++++++ 8 files changed, 1888 insertions(+), 6 deletions(-) create mode 100644 src/stm/ao-parse-font.5c create mode 100644 src/stm/ao_lcd_font.c create mode 100644 src/stm/ao_lcd_font.h create mode 100644 src/stm/ao_lcd_stm.c diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 9e4f9e38..ecdf6b7f 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -42,14 +42,16 @@ ALTOS_SRC = \ ao_stdio.c \ ao_panic.c \ ao_timer.c \ - ao_serial_stm.c + ao_serial_stm.c \ + ao_lcd_stm.c \ + ao_lcd_font.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 94527089..24566f9b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -47,8 +47,9 @@ main(void) ao_serial_init(); ao_timer_init(); ao_cmd_init(); - ao_led_init(LEDS_AVAILABLE); - ao_add_task(&demo_task, ao_demo, "demo"); +// ao_led_init(LEDS_AVAILABLE); + ao_lcd_stm_init(); +// ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); return 0; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index c72cd04b..8d7ed76b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,8 +19,8 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 -#define HAS_SERIAL_2 1 -#define HAS_SERIAL_3 1 +#define HAS_SERIAL_2 0 +#define HAS_SERIAL_3 0 #define USE_SERIAL_STDIN 1 #define HAS_USB 0 #define HAS_BEEP 0 @@ -39,4 +39,59 @@ #define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN) +#define AO_LCD_STM_SEG_ENABLED_0 ( \ + (1 << 0) | /* PA1 */ \ + (1 << 1) | /* PA2 */ \ + (1 << 2) | /* PA3 */ \ + (0 << 3) | /* PA6 */ \ + (0 << 4) | /* PA7 */ \ + (0 << 5) | /* PB0 */ \ + (0 << 6) | /* PB1 */ \ + (1 << 7) | /* PB3 */ \ + (1 << 8) | /* PB4 */ \ + (1 << 9) | /* PB5 */ \ + (1 << 10) | /* PB10 */ \ + (1 << 11) | /* PB11 */ \ + (1 << 12) | /* PB12 */ \ + (1 << 13) | /* PB13 */ \ + (1 << 14) | /* PB14 */ \ + (1 << 15) | /* PB15 */ \ + (1 << 16) | /* PB8 */ \ + (1 << 17) | /* PA15 */ \ + (1 << 18) | /* PC0 */ \ + (1 << 19) | /* PC1 */ \ + (1 << 20) | /* PC2 */ \ + (1 << 21) | /* PC3 */ \ + (0 << 22) | /* PC4 */ \ + (0 << 23) | /* PC5 */ \ + (1 << 24) | /* PC6 */ \ + (1 << 25) | /* PC7 */ \ + (1 << 26) | /* PC8 */ \ + (1 << 27) | /* PC9 */ \ + (1 << 28) | /* PC10 or PD8 */ \ + (1 << 29) | /* PC11 or PD9 */ \ + (0 << 30) | /* PC12 or PD10 */ \ + (0 << 31)) /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 ( \ + (0 << 0) | /* PD12 */ \ + (0 << 1) | /* PD13 */ \ + (0 << 2) | /* PD14 */ \ + (0 << 3) | /* PD15 */ \ + (0 << 4) | /* PE0 */ \ + (0 << 5) | /* PE1 */ \ + (0 << 6) | /* PE2 */ \ + (0 << 7)) /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED ( \ + (1 << 0) | /* PA8 */ \ + (1 << 1) | /* PA9 */ \ + (1 << 2) | /* PA10 */ \ + (1 << 3) | /* PB9 */ \ + (0 << 4) | /* PC10 */ \ + (0 << 5) | /* PC11 */ \ + (0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao-parse-font.5c b/src/stm/ao-parse-font.5c new file mode 100644 index 00000000..fe785854 --- /dev/null +++ b/src/stm/ao-parse-font.5c @@ -0,0 +1,174 @@ +#!/usr/bin/env nickle +# +# Parse a 14-segment font file +# and construct the bitmasks for each +# character. Output is in the same +# format as the input: +# [5] = 0x1212, +# /* +# CHAR 37 '%' +# +# | / +# | / +# +# / | +# / | +# +# */ +# +# Note that there can only be tabs before the glyph image +# as spaces are significant in the image itself. +# + +typedef struct { + int c; + bool[14] bits; +} glyph; + +exception done(); + +glyph read_glyph(file f) { + int c; + + for (;;) { + if (File::end(f)) + raise done(); + string l = File::fgets(f); + if (File::sscanf(l, "CHAR %d", &c) == 1) + break; + } + + string strip_tab(string x) { + int i = 0; + while (i < String::length(x) && x[i] == '\t') + i++; + string n = String::substr(x, i, String::length(x) - i); + while (String::length(n) < 7) + n = n + " "; + return n; + } + + string[7] lines = { [i] = strip_tab(File::fgets(f)) }; + + glyph g = { .c = c }; + + g.bits[0] = lines[0][1] == '-'; + + g.bits[1] = lines[1][0] == '|'; + g.bits[2] = lines[1][1] == '\\'; + g.bits[3] = lines[1][3] == '|'; + g.bits[4] = lines[1][5] == '/'; + g.bits[5] = lines[1][6] == '|'; + + g.bits[6] = lines[3][1] == '-'; + g.bits[7] = lines[3][4] == '-'; + + g.bits[8] = lines[5][0] == '|'; + g.bits[9] = lines[5][1] == '/'; + g.bits[10] = lines[5][3] == '|'; + g.bits[11] = lines[5][5] == '\\'; + g.bits[12] = lines[5][6] == '|'; + + g.bits[13] = lines[6][1] == '-'; + return g; +} + +string[*] glyph_image(glyph g) { + int[7][7] chars = { { ' ' ... } ... }; + + if (g.bits[0]) + for (int c = 1; c < 6; c++) + chars[0][c] = '-'; + + if (g.bits[1]) + for (int r = 1; r < 3; r++) + chars[r][0] = '|'; + if (g.bits[2]) + for (int p = 1; p < 3; p++) + chars[p][p] = '\\'; + if (g.bits[3]) + for (int p = 1; p < 3; p++) + chars[p][3] = '|'; + if (g.bits[4]) + for (int p = 1; p < 3; p++) + chars[p][6-p] = '/'; + if (g.bits[5]) + for (int p = 1; p < 3; p++) + chars[p][6] = '|'; + + if (g.bits[6]) + for (int p = 1; p < 3; p++) + chars[3][p] = '-'; + if (g.bits[7]) + for (int p = 4; p < 6; p++) + chars[3][p] = '-'; + + if (g.bits[8]) + for (int r = 4; r < 6; r++) + chars[r][0] = '|'; + if (g.bits[9]) + for (int p = 4; p < 6; p++) + chars[p][6-p] = '/'; + if (g.bits[10]) + for (int p = 4; p < 6; p++) + chars[p][3] = '|'; + if (g.bits[11]) + for (int p = 4; p < 6; p++) + chars[p][p] = '\\'; + if (g.bits[12]) + for (int p = 4; p < 6; p++) + chars[p][6] = '|'; + + if (g.bits[13]) + for (int c = 1; c < 6; c++) + chars[6][c] = '-'; + + return (string[7]) { [i] = String::new(chars[i]) }; + +} + +int glyph_value(glyph g) { + int v = 0; + + for (int b = 0; b < 14; b++) + if (g.bits[b]) + v |= (1 << b); + return v; +} + +void write_glyph(file f, glyph g) { + File::fprintf (f, "CHAR %d '%s'\n", g.c, g.c == 127 ? "DEL" : String::new(g.c)); + string[7] lines = glyph_image(g); + for (int i = 0; i < 7; i++) + File::fprintf (f, "\t%s\n", lines[i]); +} + +autoload Sort; + +glyph[*] read_font(file f) { + glyph[128 - 32] font = { [i] = read_glyph(f) }; + + Sort::qsort(&font, bool func (glyph a, glyph b) = (a.c > b.c)); + return font; +} + +glyph[*] font; +void init () { + twixt (file f = File::open("ao_lcd_font.h", "r"); File::close(f)) { + font = read_font(f); + } +} + +void dump() { + twixt(file f = File::open("ao_lcd_font.h.new", "w"); File::close(f)) { + for (int i = 0; i < dim(font); i++) { + File::fprintf (f, "\t[%d] = 0x%04x,\n", i, glyph_value(font[i])); + File::fprintf (f, "/*\n"); + write_glyph(f, font[i]); + File::fprintf (f, "*/\n\n"); + } + } +} + +init(); +dump(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index c4b98c7a..96cbfe85 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -155,5 +155,9 @@ struct ao_adc { */ #define STM_APB1 (16000000 * 6 / 4) +void ao_lcd_stm_init(void); + +void ao_lcd_font_string(char *s); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c new file mode 100644 index 00000000..f6074587 --- /dev/null +++ b/src/stm/ao_lcd_font.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +static const uint16_t ao_lcd_font[] = { +#include "ao_lcd_font.h" +}; + +/* + ----- 0 + |\ | /| 1 2 3 4 5 + | \|/ | @ 14 + -- -- 6 7 + | /|\ | 8 9 10 11 12 + |/ | \| @ 14 + ----- 13 + @ 15 +*/ + +static const uint8_t ao_bit_src[] = { + 8, 7, 5, 6, + 13, 12, 0, 1, + 10, 14, 4, 9, + 11, 15, 3, 2 +}; + +static const uint8_t ao_bit_dst[6][4] = { + { 0, 1, 28, 29 }, + { 2, 7, 26, 27 }, + { 8, 9, 24, 25 }, + { 10, 11, 20, 21 }, + { 12, 13, 18, 19 }, + { 14, 15, 17, 16 }, +}; + +static void +ao_draw_glyph(uint8_t pos, uint16_t glyph) { + uint8_t col, seg, src, dst; + uint32_t ram; + + for (col = 0; col < 4; col++) { + for (seg = 0; seg < 4; seg++) { + src = ao_bit_src[(col << 2) | seg]; + dst = ao_bit_dst[pos][seg]; + ram = stm_lcd.ram[col * 2]; + ram &= ~(1 << dst); + ram |= (uint32_t) ((glyph >> src) & 1) << dst; + stm_lcd.ram[col*2] = ram; + } + } +} + +#define AO_LCD_FONT_COLON (1 << 14) +#define AO_LCD_FONT_DECIMAL (1 << 15) + +void +ao_lcd_font_char(uint8_t pos, char c, uint16_t flags) { + if (pos > 5) + pos = 5; + if (c < ' ' || c > 127) + c = 127; + ao_draw_glyph(pos, ao_lcd_font[c - ' '] | flags); +} + +void +ao_lcd_font_string(char *s) { + uint8_t pos = 0; + uint16_t flags; + char c; + + while (pos < 6 && (c = *s++)) { + flags = 0; + for (;;) { + if (*s == ':') + flags |= AO_LCD_FONT_COLON; + else if (*s == '.') + flags |= AO_LCD_FONT_DECIMAL; + else + break; + s++; + } + ao_lcd_font_char(pos++, c, flags); + } + while (pos < 6) + ao_lcd_font_char(pos++, ' ', 0); +} diff --git a/src/stm/ao_lcd_font.h b/src/stm/ao_lcd_font.h new file mode 100644 index 00000000..08adc9ab --- /dev/null +++ b/src/stm/ao_lcd_font.h @@ -0,0 +1,1152 @@ + [0] = 0x0000, +/* +CHAR 32 ' ' + + + + + + + +*/ + + [1] = 0x0102, +/* +CHAR 33 '!' + + | + | + + | + | + +*/ + + [2] = 0x000a, +/* +CHAR 34 '"' + + | | + | | + + + + +*/ + + [3] = 0x05e8, +/* +CHAR 35 '#' + + | | + | | + -- -- + | | + | | + +*/ + + [4] = 0x34cb, +/* +CHAR 36 '$' + ----- + | | + | | + -- -- + | | + | | + ----- +*/ + + [5] = 0x1212, +/* +CHAR 37 '%' + + | / + | / + + / | + / | + +*/ + + [6] = 0x2955, +/* +CHAR 38 '&' + ----- + \ / + \ / + -- + | \ + | \ + ----- +*/ + + [7] = 0x0008, +/* +CHAR 39 ''' + + | + | + + + + +*/ + + [8] = 0x2103, +/* +CHAR 40 '(' + ----- + | + | + + | + | + ----- +*/ + + [9] = 0x3021, +/* +CHAR 41 ')' + ----- + | + | + + | + | + ----- +*/ + + [10] = 0x0e1c, +/* +CHAR 42 '*' + + \ | / + \|/ + + /|\ + / | \ + +*/ + + [11] = 0x04c8, +/* +CHAR 43 '+' + + | + | + -- -- + | + | + +*/ + + [12] = 0x0200, +/* +CHAR 44 ',' + + + + + / + / + +*/ + + [13] = 0x00c0, +/* +CHAR 45 '-' + + + + -- -- + + + +*/ + + [14] = 0x0800, +/* +CHAR 46 '.' + + + + + \ + \ + +*/ + + [15] = 0x0210, +/* +CHAR 47 '/' + + / + / + + / + / + +*/ + + [16] = 0x3333, +/* +CHAR 48 '0' + ----- + | /| + | / | + + | / | + |/ | + ----- +*/ + + [17] = 0x1030, +/* +CHAR 49 '1' + + /| + / | + + | + | + +*/ + + [18] = 0x21e1, +/* +CHAR 50 '2' + ----- + | + | + -- -- + | + | + ----- +*/ + + [19] = 0x30a1, +/* +CHAR 51 '3' + ----- + | + | + -- + | + | + ----- +*/ + + [20] = 0x10e2, +/* +CHAR 52 '4' + + | | + | | + -- -- + | + | + +*/ + + [21] = 0x30c3, +/* +CHAR 53 '5' + ----- + | + | + -- -- + | + | + ----- +*/ + + [22] = 0x31c3, +/* +CHAR 54 '6' + ----- + | + | + -- -- + | | + | | + ----- +*/ + + [23] = 0x0411, +/* +CHAR 55 '7' + ----- + / + / + + | + | + +*/ + + [24] = 0x31e3, +/* +CHAR 56 '8' + ----- + | | + | | + -- -- + | | + | | + ----- +*/ + + [25] = 0x10e3, +/* +CHAR 57 '9' + ----- + | | + | | + -- -- + | + | + +*/ + + [26] = 0x0408, +/* +CHAR 58 ':' + + | + | + + | + | + +*/ + + [27] = 0x0208, +/* +CHAR 59 ';' + + | + | + + / + / + +*/ + + [28] = 0x0810, +/* +CHAR 60 '<' + + / + / + + \ + \ + +*/ + + [29] = 0x20c0, +/* +CHAR 61 '=' + + + + -- -- + + + ----- +*/ + + [30] = 0x0204, +/* +CHAR 62 '>' + + \ + \ + + / + / + +*/ + + [31] = 0x0413, +/* +CHAR 63 '?' + ----- + | / + | / + + | + | + +*/ + + [32] = 0x39b3, +/* +CHAR 64 '@' + ----- + | /| + | / | + -- + | \ | + | \| + ----- +*/ + + [33] = 0x11e3, +/* +CHAR 65 'A' + ----- + | | + | | + -- -- + | | + | | + +*/ + + [34] = 0x34a9, +/* +CHAR 66 'B' + ----- + | | + | | + -- + | | + | | + ----- +*/ + + [35] = 0x2103, +/* +CHAR 67 'C' + ----- + | + | + + | + | + ----- +*/ + + [36] = 0x3429, +/* +CHAR 68 'D' + ----- + | | + | | + + | | + | | + ----- +*/ + + [37] = 0x2143, +/* +CHAR 69 'E' + ----- + | + | + -- + | + | + ----- +*/ + + [38] = 0x0143, +/* +CHAR 70 'F' + ----- + | + | + -- + | + | + +*/ + + [39] = 0x3183, +/* +CHAR 71 'G' + ----- + | + | + -- + | | + | | + ----- +*/ + + [40] = 0x11e2, +/* +CHAR 72 'H' + + | | + | | + -- -- + | | + | | + +*/ + + [41] = 0x2409, +/* +CHAR 73 'I' + ----- + | + | + + | + | + ----- +*/ + + [42] = 0x3120, +/* +CHAR 74 'J' + + | + | + + | | + | | + ----- +*/ + + [43] = 0x0952, +/* +CHAR 75 'K' + + | / + | / + -- + | \ + | \ + +*/ + + [44] = 0x2102, +/* +CHAR 76 'L' + + | + | + + | + | + ----- +*/ + + [45] = 0x1136, +/* +CHAR 77 'M' + + |\ /| + | \ / | + + | | + | | + +*/ + + [46] = 0x1926, +/* +CHAR 78 'N' + + |\ | + | \ | + + | \ | + | \| + +*/ + + [47] = 0x3123, +/* +CHAR 79 'O' + ----- + | | + | | + + | | + | | + ----- +*/ + + [48] = 0x01e3, +/* +CHAR 80 'P' + ----- + | | + | | + -- -- + | + | + +*/ + + [49] = 0x3923, +/* +CHAR 81 'Q' + ----- + | | + | | + + | \ | + | \| + ----- +*/ + + [50] = 0x09e3, +/* +CHAR 82 'R' + ----- + | | + | | + -- -- + | \ + | \ + +*/ + + [51] = 0x3085, +/* +CHAR 83 'S' + ----- + \ + \ + -- + | + | + ----- +*/ + + [52] = 0x0409, +/* +CHAR 84 'T' + ----- + | + | + + | + | + +*/ + + [53] = 0x3122, +/* +CHAR 85 'U' + + | | + | | + + | | + | | + ----- +*/ + + [54] = 0x0312, +/* +CHAR 86 'V' + + | / + | / + + | / + |/ + +*/ + + [55] = 0x1b22, +/* +CHAR 87 'W' + + | | + | | + + | / \ | + |/ \| + +*/ + + [56] = 0x0a14, +/* +CHAR 88 'X' + + \ / + \ / + + / \ + / \ + +*/ + + [57] = 0x0414, +/* +CHAR 89 'Y' + + \ / + \ / + + | + | + +*/ + + [58] = 0x2211, +/* +CHAR 90 'Z' + ----- + / + / + + / + / + ----- +*/ + + [59] = 0x2103, +/* +CHAR 91 '[' + ----- + | + | + + | + | + ----- +*/ + + [60] = 0x0804, +/* +CHAR 92 '\' + + \ + \ + + \ + \ + +*/ + + [61] = 0x3021, +/* +CHAR 93 ']' + ----- + | + | + + | + | + ----- +*/ + + [62] = 0x0023, +/* +CHAR 94 '^' + ----- + | | + | | + + + + +*/ + + [63] = 0x2000, +/* +CHAR 95 '_' + + + + + + + ----- +*/ + + [64] = 0x0004, +/* +CHAR 96 '`' + + \ + \ + + + + +*/ + + [65] = 0x2540, +/* +CHAR 97 'a' + + + + -- + | | + | | + ----- +*/ + + [66] = 0x2942, +/* +CHAR 98 'b' + + | + | + -- + | \ + | \ + ----- +*/ + + [67] = 0x21c0, +/* +CHAR 99 'c' + + + + -- -- + | + | + ----- +*/ + + [68] = 0x32a0, +/* +CHAR 100 'd' + + | + | + -- + / | + / | + ----- +*/ + + [69] = 0x2340, +/* +CHAR 101 'e' + + + + -- + | / + |/ + ----- +*/ + + [70] = 0x0143, +/* +CHAR 102 'f' + ----- + | + | + -- + | + | + +*/ + + [71] = 0x10a5, +/* +CHAR 103 'g' + ----- + \ | + \ | + -- + | + | + +*/ + + [72] = 0x11c2, +/* +CHAR 104 'h' + + | + | + -- -- + | | + | | + +*/ + + [73] = 0x0400, +/* +CHAR 105 'i' + + + + + | + | + +*/ + + [74] = 0x3000, +/* +CHAR 106 'j' + + + + + | + | + ----- +*/ + + [75] = 0x0c88, +/* +CHAR 107 'k' + + | + | + -- + |\ + | \ + +*/ + + [76] = 0x0408, +/* +CHAR 108 'l' + + | + | + + | + | + +*/ + + [77] = 0x15c0, +/* +CHAR 109 'm' + + + + -- -- + | | | + | | | + +*/ + + [78] = 0x0940, +/* +CHAR 110 'n' + + + + -- + | \ + | \ + +*/ + + [79] = 0x31c0, +/* +CHAR 111 'o' + + + + -- -- + | | + | | + ----- +*/ + + [80] = 0x0146, +/* +CHAR 112 'p' + + |\ + | \ + -- + | + | + +*/ + + [81] = 0x10b0, +/* +CHAR 113 'q' + + /| + / | + -- + | + | + +*/ + + [82] = 0x0140, +/* +CHAR 114 'r' + + + + -- + | + | + +*/ + + [83] = 0x2880, +/* +CHAR 115 's' + + + + -- + \ + \ + ----- +*/ + + [84] = 0x2142, +/* +CHAR 116 't' + + | + | + -- + | + | + ----- +*/ + + [85] = 0x3100, +/* +CHAR 117 'u' + + + + + | | + | | + ----- +*/ + + [86] = 0x0300, +/* +CHAR 118 'v' + + + + + | / + |/ + +*/ + + [87] = 0x1b00, +/* +CHAR 119 'w' + + + + + | / \ | + |/ \| + +*/ + + [88] = 0x0a14, +/* +CHAR 120 'x' + + \ / + \ / + + / \ + / \ + +*/ + + [89] = 0x3800, +/* +CHAR 121 'y' + + + + + \ | + \| + ----- +*/ + + [90] = 0x2240, +/* +CHAR 122 'z' + + + + -- + / + / + ----- +*/ + + [91] = 0x2245, +/* +CHAR 123 '{' + ----- + \ + \ + -- + / + / + ----- +*/ + + [92] = 0x0408, +/* +CHAR 124 '|' + + | + | + + | + | + +*/ + + [93] = 0x2891, +/* +CHAR 125 '}' + ----- + / + / + -- + \ + \ + ----- +*/ + + [94] = 0x000e, +/* +CHAR 126 '~' + + |\ | + | \| + + + + +*/ + + [95] = 0x3fff, +/* +CHAR 127 'DEL' + ----- + |\ | /| + | \|/ | + -- -- + | /|\ | + |/ | \| + ----- +*/ + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c new file mode 100644 index 00000000..2d2fa9b3 --- /dev/null +++ b/src/stm/ao_lcd_stm.c @@ -0,0 +1,393 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +struct ao_lcd_segment { + uint8_t reg; + uint8_t bit; +}; + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 + +static struct stm_gpio *gpios[] = { + &stm_gpioa, + &stm_gpiob, + &stm_gpioc, + &stm_gpiod, + &stm_gpioe +}; + +static inline int ao_lcd_stm_seg_enabled(int seg) { + if (seg < 32) + return (AO_LCD_STM_SEG_ENABLED_0 >> seg) & 1; + else + return (AO_LCD_STM_SEG_ENABLED_1 >> (seg - 32)) & 1; +} + +static inline int ao_lcd_stm_com_enabled(int com) { + return (AO_LCD_STM_COM_ENABLED >> com) & 1; +} + +#define AO_LCD_STM_GPIOA_SEGS_0 ( \ + (1 << 0) | \ + (1 << 1) | \ + (1 << 2) | \ + (1 << 3) | \ + (1 << 4) | \ + (1 << 17)) + +#define AO_LCD_STM_GPIOA_SEGS_1 0 + +#define AO_LCD_STM_USES_GPIOA (!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_GPIOB_SEGS_0 ( \ + (1 << 5) | \ + (1 << 6) | \ + (1 << 7) | \ + (1 << 8) | \ + (1 << 9) | \ + (1 << 10) | \ + (1 << 11) | \ + (1 << 12) | \ + (1 << 13) | \ + (1 << 14) | \ + (1 << 15) | \ + (1 << 16)) + +#define AO_LCD_STM_GPIOB_SEGS_1 0 + +#if AO_LCD_28_ON_C + +#define AO_LCD_STM_GPIOC_28_SEGS ( \ + (1 << 28) | \ + (1 << 29) | \ + (1 << 30)) + +#define AO_LCD_STM_GPIOD_28_SEGS ( \ + (1 << 31)) + +#else +#define AO_LCD_STM_GPIOC_28_C_SEGS 0 + +#define AO_LCD_STM_GPIOD_28_SEGS ( \ + (1 << 28) | \ + (1 << 29) | \ + (1 << 30) | \ + (1 << 31)) +#endif + +#define AO_LCD_STM_GPIOC_SEGS_0 ( \ + (1 << 18) | \ + (1 << 19) | \ + (1 << 20) | \ + (1 << 21) | \ + (1 << 22) | \ + (1 << 23) | \ + (1 << 24) | \ + (1 << 25) | \ + (1 << 26) | \ + (1 << 27) | \ + AO_LCD_STM_GPIOC_28_SEGS) + +#define AO_LCD_STM_GPIOC_SEGS_1 ( \ + (1 << (40 - 32)) | \ + (1 << (41 - 32)) | \ + (1 << (42 - 32))) + +#define AO_LCD_STM_GPIOD_SEGS_0 ( \ + AO_LCD_STM_GPIOD_28_SEGS) + +#define AO_LCD_STM_GPIOD_SEGS_1 ( \ + (1 << (32 - 32)) | \ + (1 << (33 - 32)) | \ + (1 << (34 - 32)) | \ + (1 << (35 - 32)) | \ + (1 << (43 - 32))) + +#define AO_LCD_STM_GPIOE_SEGS_0 0 + +#define AO_LCD_STM_GPIOE_SEGS_1 ( \ + (1 << (36 - 32)) | \ + (1 << (37 - 32)) | \ + (1 << (38 - 32)) | \ + (1 << (39 - 32))) + +#define AO_LCD_STM_USES_GPIOA (!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOB (!!((AO_LCD_STM_GPIOB_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOB_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOC (!!((AO_LCD_STM_GPIOC_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOC_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOD (!!((AO_LCD_STM_GPIOD_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOD_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOE (!!((AO_LCD_STM_GPIOE_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOE_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +static const struct ao_lcd_segment segs[] = { + { A, 1 }, /* 0 */ + { A, 2 }, + { A, 3 }, + { A, 6 }, + + { A, 7 }, /* 4 */ + { B, 0 }, + { B, 1 }, + { B, 3 }, + + { B, 4 }, /* 8 */ + { B, 5 }, + { B, 10 }, + { B, 11 }, + + { B, 12 }, /* 12 */ + { B, 13 }, + { B, 14 }, + { B, 15 }, + + { B, 8 }, /* 16 */ + { A, 15 }, + { C, 0 }, + { C, 1 }, + + { C, 2 }, /* 20 */ + { C, 3 }, + { C, 4 }, + { C, 5 }, + + { C, 6 }, /* 24 */ + { C, 7 }, + { C, 8 }, + { C, 9 }, + +#if AO_LCD_28_ON_C + { C, 10 }, /* 28 */ + { C, 11 }, + { C, 12 }, + { D, 2 }, +#else + { D, 8 }, /* 28 */ + { D, 9 }, + { D, 10 }, + { D, 11 }, +#endif + { D, 12 }, /* 32 */ + { D, 13 }, + { D, 14 }, + { D, 15 }, + + { E, 0 }, /* 36 */ + { E, 1 }, + { E, 2 }, + { E, 3 }, + + { C, 10 }, /* 40 */ + { C, 11 }, + { C, 12 }, + { D, 2 }, +}; + +static const struct ao_lcd_segment coms[] = { + { A, 8 }, /* 0 */ + { A, 9 }, /* 1 */ + { A, 10 }, /* 2 */ + { B, 9 }, /* 3 */ + { C, 10 }, /* 4 */ + { C, 11 }, /* 5 */ + { C, 12 }, /* 6 */ +}; + +#define NSEG (sizeof segs/sizeof segs[0]) +#define NCOM (sizeof coms/sizeof coms[0]) + +static void +ao_lcd_stm_fcr_sync(void) +{ + while ((stm_lcd.sr & (1 << STM_LCD_SR_FCRSF)) == 0) + asm("nop"); +} + +static void +ao_lcd_stm_seg_set(void) +{ + int com, seg, val; + int n, bit; + ao_cmd_decimal(); + com = ao_cmd_lex_i; + ao_cmd_decimal(); + seg = ao_cmd_lex_u32; + ao_cmd_decimal(); + val = ao_cmd_lex_i; + printf ("com: %d seg: %d val: %d\n", com, seg, val); + n = (seg >> 5) & 1; + if (com >= NCOM) + com = NCOM-1; + if (seg >= NSEG) + seg = NSEG-1; + if (val) + stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); + else + stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_clear(void) +{ + int i; + + for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) + stm_lcd.ram[i] = 0; + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_text(void) +{ + char string[7]; + uint8_t c = 0; + ao_cmd_white(); + while (ao_cmd_lex_c != '\n' && c < sizeof (string)) { + string[c++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + string[c++] = '\0'; + ao_lcd_font_string(string); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +const struct ao_cmds ao_lcd_stm_cmds[] = { + { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, + { ao_lcd_stm_clear, "C\0Clear LCD" }, + { ao_lcd_stm_text, "t \0Write to LCD" }, + { 0, NULL }, +}; + +void +ao_lcd_stm_init(void) +{ + int s, c; + int r; + uint32_t csr; + + stm_rcc.ahbenr |= ((AO_LCD_STM_USES_GPIOA << STM_RCC_AHBENR_GPIOAEN) | + (AO_LCD_STM_USES_GPIOB << STM_RCC_AHBENR_GPIOBEN) | + (AO_LCD_STM_USES_GPIOC << STM_RCC_AHBENR_GPIOCEN) | + (AO_LCD_STM_USES_GPIOD << STM_RCC_AHBENR_GPIODEN) | + (AO_LCD_STM_USES_GPIOE << STM_RCC_AHBENR_GPIOEEN)); + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LCDEN); + + /* Turn on the LSI clock */ + if ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) { + stm_rcc.csr |= (1 << STM_RCC_CSR_LSION); + while ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) + asm("nop"); + } + + /* Enable RTC clock config (required to change the RTC/LCD clock */ + + stm_pwr.cr |= (1 << STM_PWR_CR_DBP); + + /* Configure the LCDCLK - use the LSI clock */ + + csr = stm_rcc.csr; + csr &= ~(STM_RCC_CSR_RTCSEL_MASK << STM_RCC_CSR_RTCSEL); + csr |= (STM_RCC_CSR_RTCSEL_LSI << STM_RCC_CSR_RTCSEL); + stm_rcc.csr = csr; + + for (s = 0; s < NSEG; s++) { + uint8_t reg = segs[s].reg; + uint8_t bit = segs[s].bit; + + if (ao_lcd_stm_seg_enabled(s)) { + stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); + stm_afr_set(gpios[reg], bit, STM_AFR_AF11); + } + } + + for (c = 0; c < NCOM; c++) { + uint8_t reg = coms[c].reg; + uint8_t bit = coms[c].bit; + + if (ao_lcd_stm_com_enabled(c)) { + stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); + stm_afr_set(gpios[reg], bit, STM_AFR_AF11); + } + } + + /* duty cycle 1/3, radio 352, frame rate about 33Hz */ + stm_lcd.fcr = ((STM_LCD_FCR_PS_1 << STM_LCD_FCR_PS) | + (STM_LCD_FCR_DIV_31 << STM_LCD_FCR_DIV) | + (4 << STM_LCD_FCR_CC) | + (4 << STM_LCD_FCR_PON) | + (0 << STM_LCD_FCR_UDDIE) | + (0 << STM_LCD_FCR_SOFIE) | + (0 << STM_LCD_FCR_HD)); + + ao_lcd_stm_fcr_sync(); + + /* Program desired DUTY in LCD_CR */ + /* Program desired BIAS in LCD_CR */ + /* Enable mux seg */ + /* Internal voltage source */ + stm_lcd.cr = ((STM_LCD_CR_DUTY_1_4 << STM_LCD_CR_DUTY) | + (STM_LCD_CR_BIAS_1_3 << STM_LCD_CR_BIAS) | + (0 << STM_LCD_CR_VSEL) | + (1 << STM_LCD_CR_MUX_SEG)); + + ao_lcd_stm_fcr_sync(); + + /* Enable the display (LCDEN bit in LCD_CR) */ + stm_lcd.cr |= (1 << STM_LCD_CR_LCDEN); + + while ((stm_lcd.sr & (1 << STM_LCD_SR_RDY)) == 0) + asm("nop"); + + /* Load initial data into LCD_RAM and set the + * UDR bit in the LCD_SR register */ + for (r = 0; r < NCOM; r++) { + stm_lcd.ram[r*2] = 0; + stm_lcd.ram[r*2 + 1] = 0; + } + + stm_lcd.sr = (1 << STM_LCD_SR_UDR); + + /* Program desired frame rate (PS and DIV bits in LCD_FCR) */ + + /* Program the contrast (CC bits in LCD_FCR) */ + + /* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */ + + /* Program the required interrupts */ + + /* All done */ + ao_cmd_register(ao_lcd_stm_cmds); +} -- cgit v1.2.3 From d236a5c7cd6e9b1d7192e801d63b4bd348cc2f12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 20:02:30 -0700 Subject: Move LCD string output code to ao_lcd_font.c It's all very specific to the 14-segment display, so stick it there. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 1 + src/stm/ao_arch.h | 2 ++ src/stm/ao_lcd_font.c | 27 +++++++++++++++++++++++++++ src/stm/ao_lcd_stm.c | 15 --------------- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 24566f9b..a672964b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -49,6 +49,7 @@ main(void) ao_cmd_init(); // ao_led_init(LEDS_AVAILABLE); ao_lcd_stm_init(); + ao_lcd_font_init(); // ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 96cbfe85..61e62f5d 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -157,6 +157,8 @@ struct ao_adc { void ao_lcd_stm_init(void); +void ao_lcd_font_init(void); + void ao_lcd_font_string(char *s); #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c index f6074587..2bd787ed 100644 --- a/src/stm/ao_lcd_font.c +++ b/src/stm/ao_lcd_font.c @@ -99,3 +99,30 @@ ao_lcd_font_string(char *s) { while (pos < 6) ao_lcd_font_char(pos++, ' ', 0); } + +static void +ao_lcd_font_text(void) +{ + char string[20]; + uint8_t c = 0; + ao_cmd_white(); + while (ao_cmd_lex_c != '\n' && c < sizeof (string) - 1) { + string[c++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + string[c++] = '\0'; + ao_lcd_font_string(string); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +const struct ao_cmds ao_lcd_font_cmds[] = { + { ao_lcd_font_text, "t \0Write to LCD" }, + { 0, NULL } +}; + +void +ao_lcd_font_init(void) +{ + ao_cmd_register(ao_lcd_font_cmds); +} + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 2d2fa9b3..f68cf165 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -268,25 +268,10 @@ ao_lcd_stm_clear(void) stm_lcd.sr = (1 << STM_LCD_SR_UDR); } -static void -ao_lcd_stm_text(void) -{ - char string[7]; - uint8_t c = 0; - ao_cmd_white(); - while (ao_cmd_lex_c != '\n' && c < sizeof (string)) { - string[c++] = ao_cmd_lex_c; - ao_cmd_lex(); - } - string[c++] = '\0'; - ao_lcd_font_string(string); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); -} const struct ao_cmds ao_lcd_stm_cmds[] = { { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, { ao_lcd_stm_clear, "C\0Clear LCD" }, - { ao_lcd_stm_text, "t \0Write to LCD" }, { 0, NULL }, }; -- cgit v1.2.3 From bf060b3e3ed655bbb8464f342d0a0b1745a06173 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:01:50 -0700 Subject: Allow for more than one serial port in core AltOS Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index 86a943a8..b2f3305f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -899,7 +899,7 @@ ao_dbg_init(void); #error Please define HAS_SERIAL_1 #endif -#if HAS_SERIAL_1 +#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 #ifndef USE_SERIAL_STDIN #error Please define USE_SERIAL_STDIN #endif -- cgit v1.2.3 From c9e61a4f1f0ce5e5177a2252e8b7a02a578e77f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:02:38 -0700 Subject: Allow any STM usart to be used for stdio This also adds the alternate pin configurations for the other two usarts Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 + src/stm/ao_serial_stm.c | 170 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 131 insertions(+), 41 deletions(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 61e62f5d..55976c89 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -161,5 +161,7 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); +#define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index bd3b1e61..95189f0c 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -184,35 +184,111 @@ ao_usart_init(struct ao_stm_usart *usart) } #if HAS_SERIAL_1 + struct ao_stm_usart ao_stm_usart1; -void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } -#endif + +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } + +#if USE_SERIAL_1_STDIN +char +ao_serial1_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +void +ao_serial1_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); +} + +char +ao_serial1_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart1); +} +#endif /* USE_SERIAL_1_STDIN */ +#endif /* HAS_SERIAL_1 */ + #if HAS_SERIAL_2 + struct ao_stm_usart ao_stm_usart2; -void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } -#endif + +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } + +#if USE_SERIAL_2_STDIN +char +ao_serial2_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart2); +} + +void +ao_serial2_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart2, c); +} + +char +ao_serial2_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart2); +} +#endif /* USE_SERIAL_2_STDIN */ +#endif /* HAS_SERIAL_2 */ + #if HAS_SERIAL_3 + struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } -#endif + +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } + +#if USE_SERIAL_3_STDIN +char +ao_serial3_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart3); +} + +void +ao_serial3_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart3, c); +} + +char +ao_serial3_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart2); +} +#endif /* USE_SERIAL_3_STDIN */ +#endif /* HAS_SERIAL_3 */ void ao_serial_init(void) { -#ifdef HAS_SERIAL_1 +#if HAS_SERIAL_1 /* * TX RX * PA9 PA10 * PB6 PB7 * */ +#if SERIAL_1_PA9_PA10 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); +#else +#if SERIAL_1_PB6_PB7 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 6, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpiob, 7, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpiob, 6, STM_AFR_AF7); stm_afr_set(&stm_gpiob, 7, STM_AFR_AF7); - +#else +#error "No SERIAL_1 port configuration specified" +#endif +#endif /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); ao_stm_usart1.reg = &stm_usart1; @@ -221,9 +297,9 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, +#if USE_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, NULL); #endif #endif @@ -235,21 +311,34 @@ ao_serial_init(void) * PD5 PD6 */ +#if SERIAL_2_PA2_PA3 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 3, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); - +#else +#if SERIAL_2_PD5_PD6 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + + stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7); + stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7); +#else +#error "No SERIAL_2 port configuration specified" +#endif +#endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); - ao_usart_init(&stm_usart1); ao_stm_usart2.reg = &stm_usart2; + ao_usart_init(&ao_stm_usart2); stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +#if USE_SERIAL_2_STDIN + ao_add_stdio(ao_serial2_pollchar, + ao_serial2_putchar, + NULL); +#endif #endif #if HAS_SERIAL_3 @@ -259,44 +348,43 @@ ao_serial_init(void) * PC10 PC11 * PD8 PD9 */ +#if SERIAL_3_PB10_PB11 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 10, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpiob, 11, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpiob, 10, STM_AFR_AF7); stm_afr_set(&stm_gpiob, 11, STM_AFR_AF7); +#else +#if SERIAL_3_PC10_PC11 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + + stm_afr_set(&stm_gpioc, 10, STM_AFR_AF7); + stm_afr_set(&stm_gpioc, 11, STM_AFR_AF7); +#else +#if SERIAL_3_PD8_PD9 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + + stm_afr_set(&stm_gpiod, 8, STM_AFR_AF7); + stm_afr_set(&stm_gpiod, 9, STM_AFR_AF7); +#else +#error "No SERIAL_3 port configuration specified" +#endif +#endif +#endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); - ao_usart_init(&stm_usart1); ao_stm_usart3.reg = &stm_usart3; + ao_usart_init(&ao_stm_usart3); stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, 4); +#if USE_SERIAL_3_STDIN + ao_add_stdio(ao_serial3_pollchar, + ao_serial3_putchar, + NULL); #endif -} - -#if HAS_SERIAL_1 -char -ao_serial_getchar(void) -{ - return ao_usart_getchar(&ao_stm_usart1); -} - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) -{ - return ao_usart_pollchar(&ao_stm_usart1); -} #endif - -void -ao_serial_putchar(char c) -{ - ao_usart_putchar(&ao_stm_usart1, c); } -#endif /* HAS_SERIAL_1 */ -- cgit v1.2.3 From 6337b5f522be11926a6490d7bb27a4f7795da569 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:03:29 -0700 Subject: Automatically set ALTERNATE pin mode when setting alternate function When selecting an alternate function, set the pin to alternate mode as well; there's no sense requiring two separate calls everywhere. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 50e5cc34..531a4fb9 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -133,6 +133,10 @@ stm_pupdr_get(struct stm_gpio *gpio, int pin) { static inline void stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + /* + * Set alternate pin mode too + */ + stm_moder_set(gpio, pin, STM_MODER_ALTERNATE); if (pin < 8) gpio->afrl = ((gpio->afrl & ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | -- cgit v1.2.3 From 9b5e98a3407b369803109bfc1409e4f8b6e848ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:04:21 -0700 Subject: Flush LCD changes each time the text is updated Rather than requiring the caller to do it. Signed-off-by: Keith Packard --- src/stm/ao_lcd_font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c index 2bd787ed..0d7d87c1 100644 --- a/src/stm/ao_lcd_font.c +++ b/src/stm/ao_lcd_font.c @@ -98,6 +98,7 @@ ao_lcd_font_string(char *s) { } while (pos < 6) ao_lcd_font_char(pos++, ' ', 0); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); } static void @@ -112,7 +113,6 @@ ao_lcd_font_text(void) } string[c++] = '\0'; ao_lcd_font_string(string); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); } const struct ao_cmds ao_lcd_font_cmds[] = { -- cgit v1.2.3 From 41a3fded116a3101789df44647d0eb06be07a25b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:04:47 -0700 Subject: Make stm-demo display a scrolling message Instead of trying to frob the LEDs, which are now owned by the serial port. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 26 ++++++++++++++++++-------- src/stm-demo/ao_pins.h | 14 +++++++++++++- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index a672964b..544f261f 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -19,16 +19,27 @@ struct ao_task demo_task; +static inline int min(int a, int b) { return a < b ? a : b; } + void ao_demo(void) { + char message[] = "Hello, Mike & Bdale --- "; + char part[7]; + int i = 0; + int len = sizeof(message) - 1; + int first, second; + + part[6] = '\0'; for (;;) { - ao_led_on(AO_LED_BLUE); - ao_delay(AO_MS_TO_TICKS(500)); - ao_led_off(AO_LED_BLUE); - ao_led_on(AO_LED_GREEN); - ao_delay(AO_MS_TO_TICKS(500)); - ao_led_off(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(150)); + first = min(6, len - i); + second = 6 - first; + memcpy(part, message + i, first); + memcpy(part + first, message, second); + ao_lcd_font_string(part); + if (++i >= len) + i = 0; } } @@ -47,10 +58,9 @@ main(void) ao_serial_init(); ao_timer_init(); ao_cmd_init(); -// ao_led_init(LEDS_AVAILABLE); ao_lcd_stm_init(); ao_lcd_font_init(); -// ao_add_task(&demo_task, ao_demo, "demo"); + ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); return 0; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 8d7ed76b..798a292e 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,9 +19,21 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 1 +#define SERIAL_1_PB6_PB7 1 +#define SERIAL_1_PA9_PA10 0 + #define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 1 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 1 + #define HAS_SERIAL_3 0 -#define USE_SERIAL_STDIN 1 +#define USE_SERIAL_3_STDIN 1 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 1 + #define HAS_USB 0 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From 87ca5c9c5f9cea1b9e14468e4694ce6acc21955a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:19:06 -0700 Subject: Clean up STM build by moving common defs to Makefile.defs Shortens default Makefile a bit Signed-off-by: Keith Packard --- src/stm/Makefile.defs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/stm/Makefile.defs diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs new file mode 100644 index 00000000..c799231a --- /dev/null +++ b/src/stm/Makefile.defs @@ -0,0 +1,33 @@ +vpath % ../stm:../product:../drivers:../core:../util:../kalman:.. +vpath make-altitude ../util +vpath make-kalman ../util +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +CC=arm-none-eabi-gcc +SAT=$(HOME)/sat +SAT_CLIB=$(SAT)/lib/pdclib.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include ../Version +endif + +AO_CFLAGS=-I. -I../stm -I../core -I.. +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< -- cgit v1.2.3 From 25184baa36c20e3d661f94e642a33e8aae179d60 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:40:09 -0700 Subject: Allow for more than 8 LEDs Provide hook for architecture-specific LED mask (AO_LED_TYPE) Signed-off-by: Keith Packard --- src/core/ao.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index b2f3305f..c9f17dc0 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -258,29 +258,33 @@ ao_beep_init(void); #define AO_LED_NONE 0 +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + /* Turn on the specified LEDs */ void -ao_led_on(uint8_t colors); +ao_led_on(AO_LED_TYPE colors); /* Turn off the specified LEDs */ void -ao_led_off(uint8_t colors); +ao_led_off(AO_LED_TYPE colors); /* Set all of the LEDs to the specified state */ void -ao_led_set(uint8_t colors); +ao_led_set(AO_LED_TYPE colors); /* Toggle the specified LEDs */ void -ao_led_toggle(uint8_t colors); +ao_led_toggle(AO_LED_TYPE colors); /* Turn on the specified LEDs for the indicated interval */ void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; /* Initialize the LEDs */ void -ao_led_init(uint8_t enable); +ao_led_init(AO_LED_TYPE enable); /* * ao_usb.c -- cgit v1.2.3 From 606d866153cb639a2400cbedbc45046372ad1b30 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:40:48 -0700 Subject: Allow skytraq to be on non-default serial port Provide ao_gps_getchar, ao_gps_putchar and ao_gps_set_speed hooks to let product specify functions for serial access. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 050573e8..39e36cc8 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -19,6 +19,18 @@ #include "ao.h" #endif +#ifndef ao_gps_getchar +#define ao_gps_getchar ao_serial_getchar +#endif + +#ifndef ao_gps_putchar +#define ao_gps_putchar ao_serial_putchar +#endif + +#ifndef ao_gps_set_speed +#define ao_gps_set_speed ao_serial_set_speed +#endif + __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; static __data uint8_t ao_gps_cksum; @@ -68,7 +80,7 @@ ao_gps_lexchar(void) if (ao_gps_error) c = '\n'; else - c = ao_serial_getchar(); + c = ao_gps_getchar(); ao_gps_cksum ^= c; ao_gps_char = c; } @@ -402,7 +414,7 @@ ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) uint8_t c = *b++; if (c == 0xa0) ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(c); + ao_gps_putchar(c); } } @@ -444,7 +456,7 @@ ao_gps_nmea_parse(void) void ao_gps(void) __reentrant { - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_gps_set_speed(AO_SERIAL_SPEED_9600); /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); @@ -453,7 +465,7 @@ ao_gps(void) __reentrant for (;;) { /* Locate the begining of the next record */ - if (ao_serial_getchar() == '$') { + if (ao_gps_getchar() == '$') { ao_gps_nmea_parse(); } } -- cgit v1.2.3 From d7ddfd4e6d75e50ca64a342181f5c52e9f4919af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:42:13 -0700 Subject: Use 16-bits for STM32 LED mask. Export serial I/O functions Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 38 ++++++++++++++++++++++++++++++++++++++ src/stm/ao_led.c | 14 +++++++------- src/stm/ao_serial_stm.c | 26 +++++++++++++++++++------- 3 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 55976c89..fcc177ef 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -27,6 +27,8 @@ #define AO_STACK_SIZE 1024 +#define AO_LED_TYPE uint16_t + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) @@ -163,5 +165,41 @@ void ao_lcd_font_string(char *s); #define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) +char +ao_serial1_getchar(void); + +void +ao_serial1_putchar(char c); + +char +ao_serial1_pollchar(void); + +void +ao_serial1_set_speed(uint8_t speed); + +char +ao_serial2_getchar(void); + +void +ao_serial2_putchar(char c); + +char +ao_serial2_pollchar(void); + +void +ao_serial2_set_speed(uint8_t speed); + +char +ao_serial3_getchar(void); + +void +ao_serial3_putchar(char c); + +char +ao_serial3_pollchar(void); + +void +ao_serial3_set_speed(uint8_t speed); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index 0574aa2a..d649f3d7 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -17,34 +17,34 @@ #include "ao.h" -__pdata uint8_t ao_led_enable; +__pdata uint16_t ao_led_enable; void -ao_led_on(uint8_t colors) +ao_led_on(uint16_t colors) { LED_PORT.odr |= (colors & ao_led_enable); } void -ao_led_off(uint8_t colors) +ao_led_off(uint16_t colors) { LED_PORT.odr &= ~(colors & ao_led_enable); } void -ao_led_set(uint8_t colors) +ao_led_set(uint16_t colors) { LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); } void -ao_led_toggle(uint8_t colors) +ao_led_toggle(uint16_t colors) { LED_PORT.odr ^= (colors & ao_led_enable); } void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +ao_led_for(uint16_t colors, uint16_t ticks) __reentrant { ao_led_on(colors); ao_delay(ticks); @@ -52,7 +52,7 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant } void -ao_led_init(uint8_t enable) +ao_led_init(uint16_t enable) { int bit; diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 95189f0c..a8c10222 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -189,7 +189,6 @@ struct ao_stm_usart ao_stm_usart1; void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } -#if USE_SERIAL_1_STDIN char ao_serial1_getchar(void) { @@ -207,7 +206,12 @@ ao_serial1_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart1); } -#endif /* USE_SERIAL_1_STDIN */ + +void +ao_serial1_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart1, speed); +} #endif /* HAS_SERIAL_1 */ #if HAS_SERIAL_2 @@ -216,7 +220,6 @@ struct ao_stm_usart ao_stm_usart2; void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } -#if USE_SERIAL_2_STDIN char ao_serial2_getchar(void) { @@ -234,7 +237,12 @@ ao_serial2_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart2); } -#endif /* USE_SERIAL_2_STDIN */ + +void +ao_serial2_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart2, speed); +} #endif /* HAS_SERIAL_2 */ #if HAS_SERIAL_3 @@ -243,7 +251,6 @@ struct ao_stm_usart ao_stm_usart3; void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } -#if USE_SERIAL_3_STDIN char ao_serial3_getchar(void) { @@ -259,9 +266,14 @@ ao_serial3_putchar(char c) char ao_serial3_pollchar(void) { - return ao_usart_pollchar(&ao_stm_usart2); + return ao_usart_pollchar(&ao_stm_usart3); +} + +void +ao_serial3_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart3, speed); } -#endif /* USE_SERIAL_3_STDIN */ #endif /* HAS_SERIAL_3 */ void -- cgit v1.2.3 From c27e211796a64b6bbacfe6a1516e9872fdb0853e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:43:17 -0700 Subject: Use new Makefile.defs in stm-demo Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 43 ++++++------------------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index ecdf6b7f..f2e6618e 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -2,32 +2,16 @@ # AltOS build # # -vpath % ..:../core:../product:../drivers:../stm -vpath make-altitude ../util -vpath make-kalman ../util -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c ../util - -#PROGRAMMER=stk500v2 -P usb -#PROGRAMMER=usbtiny -#LOADCMD=avrdude -#LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=arm-none-eabi-gcc -#OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif + +include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ ao_pins.h \ altitude.h \ - ao_kalman.h + ao_kalman.h \ + ao_product.h # # Common AltOS sources @@ -49,33 +33,20 @@ ALTOS_SRC = \ PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CPU=cortex-m3 -CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) -NICKLE=nickle +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) PROG=stm-demo SRC=$(ALTOS_SRC) ao_demo.c OBJ=$(SRC:.c=.o) -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - all: $(PROG) -CLIB=/home/keithp/sat/lib/pdclib.a -CINC=-I/home/keithp/sat/include LDFLAGS=-L../stm -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ../altitude.h: make-altitude nickle $< > $@ @@ -97,5 +68,3 @@ clean: install: uninstall: - -$(OBJ): ao.h ao_product.h \ No newline at end of file -- cgit v1.2.3 From 0bda768c2be5b81bec13f21d4d3bb6a11a8e88fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:43:47 -0700 Subject: Add preliminary MegaMetrum v0.1 support This turns on an LED, enables the internal R/C clock, hooks USART3 to the GPS chip and USART1 to the console. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 70 +++++++++++++++++++++++++++++++++++++ src/megametrum-v0.1/ao_megametrum.c | 33 +++++++++++++++++ src/megametrum-v0.1/ao_pins.h | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 src/megametrum-v0.1/Makefile create mode 100644 src/megametrum-v0.1/ao_megametrum.c create mode 100644 src/megametrum-v0.1/ao_pins.h diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile new file mode 100644 index 00000000..4f5e9244 --- /dev/null +++ b/src/megametrum-v0.1/Makefile @@ -0,0 +1,70 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_gps_skytraq.c + +PRODUCT=MegaMetrum-v0.1 +PRODUCT_DEF=-DMEGAMETRUM +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) + +PROG=megametrum-v0.1 + +SRC=$(ALTOS_SRC) ao_megametrum.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../stm -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +../altitude.h: make-altitude + nickle $< > $@ + +$(OBJ): $(INC) + +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 + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c new file mode 100644 index 00000000..14881eb8 --- /dev/null +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + ao_cmd_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h new file mode 100644 index 00000000..dadeb380 --- /dev/null +++ b/src/megametrum-v0.1/ao_pins.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 1 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 1 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 1 +#define SERIAL_3_PD8_PD9 0 + +#define ao_gps_getchar ao_serial3_getchar +#define ao_gps_putchar ao_serial3_putchar +#define ao_gps_set_speed ao_serial3_set_speed + +#define HAS_USB 0 +#define HAS_BEEP 0 + +#define HAS_SPI_1 1 +#define SPI_1_PE13_PE14_PE15 1 + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 + +#define HAS_I2C_1 1 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 1 +#define I2C_2_PB10_PB11 1 + +#define PACKET_HAS_SLAVE 1 + +#define LOW_LEVEL_DEBUG 1 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT stm_gpioc +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From f2c110fb4531144f18f62200e4127738c84e87f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:55:53 -0700 Subject: Get config stuff hooked up for MegaMetrum This stubs out enough stuff to let ao_config link and work Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 4 +++- src/megametrum-v0.1/ao_megametrum.c | 2 ++ src/stm/ao_arch.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 4f5e9244..ed91d04f 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -21,6 +21,7 @@ ALTOS_SRC = \ ao_product.c \ ao_romconfig.c \ ao_cmd.c \ + ao_config.c \ ao_task.c \ ao_led.c \ ao_stdio.c \ @@ -28,7 +29,8 @@ ALTOS_SRC = \ ao_timer.c \ ao_mutex.c \ ao_serial_stm.c \ - ao_gps_skytraq.c + ao_gps_skytraq.c \ + ao_cc1120.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 14881eb8..6bf43cb1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -27,6 +27,8 @@ main(void) ao_led_on(AO_LED_GREEN); ao_timer_init(); ao_cmd_init(); + ao_gps_init(); + ao_config_init(); ao_start_scheduler(); return 0; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index fcc177ef..188b8996 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -201,5 +201,7 @@ ao_serial3_pollchar(void); void ao_serial3_set_speed(uint8_t speed); +extern uint32_t ao_radio_cal; + #endif /* _AO_ARCH_H_ */ -- cgit v1.2.3 From c1531fb26461b9f4ec39672bbfaeb70e6f4d1056 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 01:42:32 -0700 Subject: Use -Os for STM apps. Fix altos.ld to matchall .rodata* sections Without .rodata*, it would stick the flash copy of the data on top of any further .rodata* sections. Fortunately, the linker catches that and complains... Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- src/stm-demo/Makefile | 2 +- src/stm/Makefile.defs | 2 ++ src/stm/altos.ld | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index ed91d04f..510bee6a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -36,7 +36,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index f2e6618e..f1655d57 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -34,7 +34,7 @@ PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os PROG=stm-demo diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index c799231a..6191ec45 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -19,6 +19,8 @@ endif AO_CFLAGS=-I. -I../stm -I../core -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) +LDFLAGS=-L../stm -Wl,-Taltos.ld + NICKLE=nickle V=0 diff --git a/src/stm/altos.ld b/src/stm/altos.ld index 4e955666..7fede558 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -36,8 +36,8 @@ SECTIONS { .text : { *(.interrupt) /* Interrupt vectors */ - *(.text) /* Executable code */ - *(.rodata) /* Constants */ + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ } > rom .ARM.exidx : { -- cgit v1.2.3 From a157edbe1bf7fffd5a6041f7b1760674addd2229 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Mar 2012 13:08:05 -0700 Subject: stm-demo does not use altitude.h --- src/megametrum-v0.1/Makefile | 2 -- src/stm-demo/Makefile | 10 +--------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 510bee6a..b07d1e1d 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -45,8 +45,6 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -LDFLAGS=-L../stm -Wl,-Taltos.ld - $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index f1655d57..366291c6 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -9,8 +9,6 @@ INC = \ ao.h \ ao_arch.h \ ao_pins.h \ - altitude.h \ - ao_kalman.h \ ao_product.h # @@ -48,16 +46,10 @@ LDFLAGS=-L../stm -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc -../altitude.h: make-altitude - nickle $< > $@ - -$(OBJ): $(INC) - 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 - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +$(OBJ): $(INC) distclean: clean -- cgit v1.2.3 From 0993595035a2813deba6991fa25bc0d475f2e6bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:45:02 -0700 Subject: altos: Add ao_freq.c to megametrum build I think this will be needed to compute radio settings on the cc1120 Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b07d1e1d..6347f8c3 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -30,7 +30,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ - ao_cc1120.c + ao_cc1120.c \ + ao_freq.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM @@ -38,7 +39,7 @@ IDPRODUCT=0x000a CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g -PROG=megametrum-v0.1 +PROG=megametrum-v0.1-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) -- cgit v1.2.3 From b711768da6310a1b06f3b995a280587fed5f26cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:45:44 -0700 Subject: Bump version to 1.0.9.4 Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 19db6d27..f8707056 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.3) +AC_INIT([altos], 1.0.9.4) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From 93ae5f6ce09fa71ebd34f77a884684b3670c8b44 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Mar 2012 13:29:15 -0600 Subject: openocd config file for MegaMetrum --- ao-bringup/megametrum.cfg | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ao-bringup/megametrum.cfg diff --git a/ao-bringup/megametrum.cfg b/ao-bringup/megametrum.cfg new file mode 100644 index 00000000..e95c6f2b --- /dev/null +++ b/ao-bringup/megametrum.cfg @@ -0,0 +1,4 @@ +# openocd config for MegaMetrum using the Olimex ARM-USB-OCD dongle + +source /opt/stm32/share/openocd/scripts/interface/olimex-arm-usb-ocd.cfg +source /opt/stm32/share/openocd/scripts/target/stm32l.cfg -- cgit v1.2.3 From 47a9925f16f6a13b173c49d3873d91fc7cf6d46e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:53:30 -0700 Subject: altos: Move cc1111 AES driver to cc1111 directory Signed-off-by: Keith Packard --- src/ao_aes.c | 142 ---------------------------------------------------- src/cc1111/ao_aes.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 142 deletions(-) delete mode 100644 src/ao_aes.c create mode 100644 src/cc1111/ao_aes.c diff --git a/src/ao_aes.c b/src/ao_aes.c deleted file mode 100644 index d50fecfb..00000000 --- a/src/ao_aes.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -#if !HAS_AES -#error Must define HAS_AES 1 -#endif - -__xdata uint8_t ao_aes_mutex; -__xdata uint8_t ao_aes_done; -__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; -__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; -__pdata enum ao_aes_mode ao_aes_current_mode; - -void -ao_aes_isr(void) __interrupt 4 -{ - S0CON = 0; - if (ENCCCS & ENCCCS_RDY) { - ao_aes_done = 1; - ao_wakeup(&ao_aes_done); - } -} - -void -ao_aes_set_mode(enum ao_aes_mode mode) -{ - ao_aes_current_mode = mode; -} - -void -ao_aes_set_key(__xdata uint8_t *in) -{ - ao_dma_set_transfer(ao_aes_dma_in, - in, - &ENCDIXADDR, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_DW, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_LOW); - ao_dma_start(ao_aes_dma_in); - ao_aes_done = 0; - ENCCCS = ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_LOAD_KEY; - ENCCCS |= ENCCCS_START; - __critical while (!ao_aes_done) - ao_sleep(&ao_aes_done); -} - -void -ao_aes_zero_iv(void) -{ - uint8_t b; - - ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; - for (b = 0; b < AO_AES_LEN; b++) - ENCDI = 0; -} - -void -ao_aes_run(__xdata uint8_t *in, - __xdata uint8_t *out) -{ - uint8_t b; - if (in) { - ao_dma_set_transfer(ao_aes_dma_in, - in, - &ENCDIXADDR, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_DW, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_LOW); - } - if (out) { - ao_dma_set_transfer(ao_aes_dma_out, - &ENCDOXADDR, - out, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_UP, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_LOW); - } - switch (ao_aes_current_mode) { - case ao_aes_mode_cbc_mac: - if (out) - b = (ENCCCS_MODE_CBC | - ENCCCS_CMD_ENCRYPT); - else - b = (ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_ENCRYPT); - break; - default: - return; - } - ao_aes_done = 0; - if (in) - ao_dma_start(ao_aes_dma_in); - if (out) - ao_dma_start(ao_aes_dma_out); - ENCCCS = b; - ENCCCS |= ENCCCS_START; - if (out) { - __critical while (!ao_aes_dma_out_done) - ao_sleep(&ao_aes_dma_out_done); - } else { - __critical while (!ao_aes_done) - ao_sleep(&ao_aes_done); - } -} - -void -ao_aes_init(void) -{ - ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); - ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); - S0CON = 0; - ENCIE = 1; -} diff --git a/src/cc1111/ao_aes.c b/src/cc1111/ao_aes.c new file mode 100644 index 00000000..d50fecfb --- /dev/null +++ b/src/cc1111/ao_aes.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t ao_aes_done; +__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ + S0CON = 0; + if (ENCCCS & ENCCCS_RDY) { + ao_aes_done = 1; + ao_wakeup(&ao_aes_done); + } +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + ao_dma_start(ao_aes_dma_in); + ao_aes_done = 0; + ENCCCS = ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_LOAD_KEY; + ENCCCS |= ENCCCS_START; + __critical while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_zero_iv(void) +{ + uint8_t b; + + ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; + for (b = 0; b < AO_AES_LEN; b++) + ENCDI = 0; +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t b; + if (in) { + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + } + if (out) { + ao_dma_set_transfer(ao_aes_dma_out, + &ENCDOXADDR, + out, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_UP, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_LOW); + } + switch (ao_aes_current_mode) { + case ao_aes_mode_cbc_mac: + if (out) + b = (ENCCCS_MODE_CBC | + ENCCCS_CMD_ENCRYPT); + else + b = (ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_ENCRYPT); + break; + default: + return; + } + ao_aes_done = 0; + if (in) + ao_dma_start(ao_aes_dma_in); + if (out) + ao_dma_start(ao_aes_dma_out); + ENCCCS = b; + ENCCCS |= ENCCCS_START; + if (out) { + __critical while (!ao_aes_dma_out_done) + ao_sleep(&ao_aes_dma_out_done); + } else { + __critical while (!ao_aes_done) + ao_sleep(&ao_aes_done); + } +} + +void +ao_aes_init(void) +{ + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + S0CON = 0; + ENCIE = 1; +} -- cgit v1.2.3 From 1f2b75518169c4f2da9762de46bf1d9a71a04d17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:54:32 -0700 Subject: altos: Move cc1111 DMA engine interface to cc1111/ao_arch.h from ao.h It's hardware specific Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/core/ao.h | 36 ------------------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 360b35c8..847ac1a6 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -258,4 +258,40 @@ struct ao_serial_speed { extern const __code struct ao_serial_speed ao_serial_speeds[]; +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) ao_arch_interrupt(8); + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c9f17dc0..8263a529 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -394,42 +394,6 @@ uint8_t ao_cmd_filter(void); #endif -/* - * ao_dma.c - */ - -/* Allocate a DMA channel. the 'done' parameter will be set when the - * dma is finished and will be used to wakeup any waiters - */ - -uint8_t -ao_dma_alloc(__xdata uint8_t * done); - -/* Setup a DMA channel */ -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1); - -/* Start a DMA channel */ -void -ao_dma_start(uint8_t id); - -/* Manually trigger a DMA channel */ -void -ao_dma_trigger(uint8_t id); - -/* Abort a running DMA transfer */ -void -ao_dma_abort(uint8_t id); - -/* DMA interrupt routine */ -void -ao_dma_isr(void) ao_arch_interrupt(8); - /* * ao_mutex.c */ -- cgit v1.2.3 From bbf31b8591f89e2a1fcc7dac5f42d730a81473d2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Mar 2012 12:43:58 -0700 Subject: altos: Add stub cc1120 driver Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/drivers/ao_cc1120.c diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c new file mode 100644 index 00000000..9470fa87 --- /dev/null +++ b/src/drivers/ao_cc1120.c @@ -0,0 +1,25 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +uint32_t ao_radio_cal = 1186611; + +void +ao_radio_recv_abort(void) +{ +} -- cgit v1.2.3 From b89f11139fae7ae722ed78d342a169ed2bf5c948 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Mar 2012 12:44:14 -0700 Subject: Build megametrum-v0.1 by default --- src/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Makefile b/src/Makefile index 3603c277..db9bd508 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ + megametrum-v0.1 \ stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ -- cgit v1.2.3 From 246618baf9b8803e5ae4e650eb46740d1128a010 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Mar 2012 16:43:11 -0600 Subject: add config file for gdb use with MegaMetrum via Olimex dongle --- ao-bringup/megametrum.gdb | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 ao-bringup/megametrum.gdb diff --git a/ao-bringup/megametrum.gdb b/ao-bringup/megametrum.gdb new file mode 100644 index 00000000..964ae1f3 --- /dev/null +++ b/ao-bringup/megametrum.gdb @@ -0,0 +1,2 @@ +target remote localhost:3333 +monitor poll -- cgit v1.2.3 From 4ca52908c8b3f98a79588981f6878025250f0924 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Mar 2012 16:43:39 -0600 Subject: use explicit path not $(HOME) to find ARM toolchain for now --- src/stm/Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 6191ec45..76962a3e 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -8,7 +8,7 @@ vpath matrix.5c ../kalman vpath ao-make-product.5c ../util CC=arm-none-eabi-gcc -SAT=$(HOME)/sat +SAT=/home/keithp/sat SAT_CLIB=$(SAT)/lib/pdclib.a SAT_CFLAGS=-I$(SAT)/include -- cgit v1.2.3 From 440226df03a85cd0047d876b57b2a3410bfb2b02 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Mar 2012 17:53:25 -0600 Subject: be explicit in a couple places about only using single-cell LiPo batteries --- doc/altusmetrum.xsl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 5c18fec3..ad08aecc 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -258,7 +258,8 @@ NAR #88757, TRA #12200 A typical TeleMetrum or TeleMini installation involves attaching only a suitable Lithium Polymer battery, a single pole switch for power on/off, and two pairs of wires connecting e-matches for the - apogee and main ejection charges. + apogee and main ejection charges. All Altus Metrum products are + designed for use with single-cell batteries with 3.7 volts nominal.
By default, we use the unregulated output of the Li-Po battery directly @@ -1447,8 +1448,9 @@ NAR #88757, TRA #12200 In the rocket itself, you just need a TeleMetrum or TeleMini board and - a Li-Po rechargeable battery. An 860mAh battery weighs less than a 9V - alkaline battery, and will run a TeleMetrum for hours. + a single-cell, 3.7 volt nominal Li-Po rechargeable battery. An + 850mAh battery weighs less than a 9V alkaline battery, and will + run a TeleMetrum for hours. A 110mAh battery weighs less than a triple A battery and will run a TeleMetrum for a few hours, or a TeleMini for much (much) longer. -- cgit v1.2.3 From c09d155328bd446bb84ac1068d380cceb884df22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 19:27:53 -0700 Subject: altos: Oops. Set per-USART STM baud rate register instead of usart1 Was accidentally always setting usart1 instead of the per-usart register. Didn't work too well for other usarts... Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index a8c10222..f8db6883 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -134,7 +134,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { if (speed > AO_SERIAL_SPEED_57600) return; - stm_usart1.brr = ao_usart_speeds[speed].brr; + usart->reg->brr = ao_usart_speeds[speed].brr; } void @@ -303,8 +303,8 @@ ao_serial_init(void) #endif /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - ao_stm_usart1.reg = &stm_usart1; + ao_stm_usart1.reg = &stm_usart1; ao_usart_init(&ao_stm_usart1); stm_nvic_set_enable(STM_ISR_USART1_POS); @@ -382,7 +382,6 @@ ao_serial_init(void) #endif #endif #endif - /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); -- cgit v1.2.3 From cf1e4d60e1fcd75fa734365a2666ea8930938128 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 22:58:54 -0700 Subject: altos: Move SPI functions to architecture-specific location Some architecture specific stuff needs to use core altos code, so create new ao_arch_funcs.h files per architecture that get pulled in at the end of ao.h Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 43 ++-------------------------------- src/stm/ao_arch_funcs.h | 35 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 41 deletions(-) create mode 100644 src/avr/ao_arch_funcs.h create mode 100644 src/cc1111/ao_arch_funcs.h create mode 100644 src/stm/ao_arch_funcs.h diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/avr/ao_arch_funcs.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/cc1111/ao_arch_funcs.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/core/ao.h b/src/core/ao.h index 8263a529..080cadb2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -940,47 +940,6 @@ ao_serial0_init(void); #endif -/* - * ao_spi.c - */ - -extern __xdata uint8_t ao_spi_mutex; - -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ - } while (0) - -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ - } while (0) - -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -/* - * The SPI mutex must be held to call either of these - * functions -- this mutex covers the entire SPI operation, - * from chip select low to chip select high - */ - -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_init(void); - /* * ao_spi_slave.c */ @@ -1934,4 +1893,6 @@ ao_sqrt(uint32_t op); int32_t ao_freq_to_set(int32_t freq, int32_t cal); +#include + #endif /* _AO_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h new file mode 100644 index 00000000..9b68f19a --- /dev/null +++ b/src/stm/ao_arch_funcs.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +extern uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } +static inline void ao_spi_put(uint8_t spi_index) { ao_mutex_put(&ao_spi_mutex[spi_index]); } + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_init(uint8_t spi_index); + +#endif /* _AO_ARCH_FUNCS_H_ */ -- cgit v1.2.3 From 2a04ac8dff1bfc3efba8c7e4dc9c1a827496dbdf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 23:00:29 -0700 Subject: altos: megametrum builds an ELF file, not an IHX file Name it appropriately. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6347f8c3..23160d9b 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -39,7 +39,7 @@ IDPRODUCT=0x000a CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g -PROG=megametrum-v0.1-$(VERSION).ihx +PROG=megametrum-v0.1-$(VERSION).elf SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) -- cgit v1.2.3 From 9b12bc445fe482306e4587ad60c6d2daf65a60f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 18:07:07 -0700 Subject: altos: Add DMA, SPI and MS5607 drivers Signed-off-by: Keith Packard --- src/core/ao.h | 7 ++ src/drivers/ao_ms5607.c | 164 ++++++++++++++++++++++++ src/drivers/ao_ms5607.h | 38 ++++++ src/megametrum-v0.1/Makefile | 7 +- src/megametrum-v0.1/ao_megametrum.c | 3 + src/megametrum-v0.1/ao_pins.h | 5 +- src/stm-demo/Makefile | 5 +- src/stm-demo/ao_demo.c | 79 +++++++++++- src/stm-demo/ao_pins.h | 5 + src/stm/ao_arch_funcs.h | 28 ++++- src/stm/ao_dma_stm.c | 99 +++++++++++++++ src/stm/ao_spi_stm.c | 240 ++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 180 ++++++++++++++++++++++++++- 13 files changed, 847 insertions(+), 13 deletions(-) create mode 100644 src/drivers/ao_ms5607.c create mode 100644 src/drivers/ao_ms5607.h create mode 100644 src/stm/ao_dma_stm.c create mode 100644 src/stm/ao_spi_stm.c diff --git a/src/core/ao.h b/src/core/ao.h index 080cadb2..67efa437 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -114,6 +114,7 @@ ao_start_scheduler(void); #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ +#define AO_PANIC_SPI 13 /* SPI communication failure */ /* Stop the operating system, beeping and blinking the reason */ void @@ -1895,4 +1896,10 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal); #include +/* + * ao_ms5607.c + */ + +void ao_ms5607_init(void); + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c new file mode 100644 index 00000000..970fea1e --- /dev/null +++ b/src/drivers/ao_ms5607.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include "ao_ms5607.h" + +#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) + +struct ms5607_prom { + uint16_t reserved; + uint16_t sens; + uint16_t off; + uint16_t tcs; + uint16_t tco; + uint16_t tref; + uint16_t tempsens; + uint16_t crc; +}; + +static struct ms5607_prom ms5607_prom; + +static void +ao_ms5607_start(void) { + ao_spi_get(AO_MS5607_SPI_INDEX); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); +} + +static void +ao_ms5607_stop(void) { + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + ao_spi_put(AO_MS5607_SPI_INDEX); +} + +static void +ao_ms5607_reset(void) { + uint8_t cmd; + + cmd = AO_MS5607_RESET; + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); +} + +static uint16_t +ao_ms5607_prom_read(uint8_t addr) +{ + uint8_t cmd = AO_MS5607_PROM_READ(addr); + uint8_t d[2]; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +} + +static void +ao_ms5607_init_chip(void) { + uint8_t addr; + uint16_t *prom; + ao_ms5607_reset(); + prom = &ms5607_prom.reserved; + + for (addr = 0; addr <= 7; addr++) + prom[addr] = ao_ms5607_prom_read(addr); +} + +static uint32_t +ao_ms5607_convert(uint8_t cmd) { + uint8_t reply[3]; + uint8_t read; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + ao_delay(AO_MS_TO_TICKS(200)); + + ao_ms5607_start(); + read = AO_MS5607_ADC_READ; + ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(&reply, 3, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; +} + +static void +ao_ms5607_dump(void) +{ + uint8_t addr; + uint32_t d1, d2; + int32_t dT; + int32_t TEMP; + int64_t OFF; + int64_t SENS; + int32_t P; + + ao_ms5607_init_chip(); + printf ("reserved: %d\n", ms5607_prom.reserved); + printf ("sens: %d\n", ms5607_prom.sens); + printf ("off: %d\n", ms5607_prom.off); + printf ("tcs: %d\n", ms5607_prom.tcs); + printf ("tco: %d\n", ms5607_prom.tco); + printf ("tref: %d\n", ms5607_prom.tref); + printf ("tempsens: %d\n", ms5607_prom.tempsens); + printf ("crc: %d\n", ms5607_prom.crc); + d1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); + printf ("Conversion D1: %d\n", d1); + d2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); + printf ("Conversion D2: %d\n", d2); + + dT = d2 - ((int32_t) ms5607_prom.tref << 8); + + TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + + OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); + + SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); + + if (TEMP < 2000) { + int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31; + int32_t TEMPM = TEMP - 2000; + int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; + int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + } + + P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; + + printf ("Temperature: %d", TEMP); + printf ("Pressure %d\n", P); +} + +__code struct ao_cmds ao_ms5607_cmds[] = { + { ao_ms5607_dump, "p\0Display MS5607 data" }, + { 0, NULL }, +}; + +void +ao_ms5607_init(void) +{ + ao_cmd_register(&ao_ms5607_cmds[0]); + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); +} diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h new file mode 100644 index 00000000..6c245368 --- /dev/null +++ b/src/drivers/ao_ms5607.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MS5607_H_ +#define _AO_MS5607_H_ + +#define AO_MS5607_RESET 0x1e + +#define AO_MS5607_CONVERT_D1_256 0x40 +#define AO_MS5607_CONVERT_D1_512 0x42 +#define AO_MS5607_CONVERT_D1_1024 0x44 +#define AO_MS5607_CONVERT_D1_2048 0x46 +#define AO_MS5607_CONVERT_D1_4096 0x48 + +#define AO_MS5607_CONVERT_D2_256 0x50 +#define AO_MS5607_CONVERT_D2_512 0x52 +#define AO_MS5607_CONVERT_D2_1024 0x54 +#define AO_MS5607_CONVERT_D2_2048 0x56 +#define AO_MS5607_CONVERT_D2_4096 0x58 + +#define AO_MS5607_ADC_READ 0x00 +#define AO_MS5607_PROM_READ(ad) 0xA0 | ((ad) << 1) + +#endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 23160d9b..fbcb4a57 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -31,13 +31,16 @@ ALTOS_SRC = \ ao_serial_stm.c \ ao_gps_skytraq.c \ ao_cc1120.c \ - ao_freq.c + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_ms5607.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 6bf43cb1..0d88f4c1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -29,6 +29,9 @@ main(void) ao_cmd_init(); ao_gps_init(); ao_config_init(); + ao_dma_init(); + ao_spi_init(); + ao_ms5607_init(); ao_start_scheduler(); return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dadeb380..ee4510e6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,10 +42,13 @@ #define HAS_BEEP 0 #define HAS_SPI_1 1 -#define SPI_1_PE13_PE14_PE15 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 366291c6..c1f49371 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -26,7 +26,10 @@ ALTOS_SRC = \ ao_timer.c \ ao_serial_stm.c \ ao_lcd_stm.c \ - ao_lcd_font.c + ao_lcd_font.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_spi_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 544f261f..54f7c8f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -50,6 +50,71 @@ void _lseek() { } void _exit () { } void _read () { } void _fstat() { } + +static void +ao_dma_test(void) { + static char src[20] = "hello, world"; + static char dst[20]; + + dst[0] = '\0'; + ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, + (1 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_LOW << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (1 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + ao_dma_start(STM_DMA_INDEX(1)); + cli(); + while (!ao_dma_done[STM_DMA_INDEX(1)]) + ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); + sei(); + printf ("copied %s\n", dst); +} + +static void +ao_spi_write(void) { + unsigned char data[] = { 0x55, 0xaa, 0xff, 0x00 }; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_send(data, 1, 0); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + printf("."); + flush(); + ao_delay(100); + } +} + +static void +ao_spi_read(void) { + unsigned char data[4]; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_recv(data, 4, 0); + printf("."); + flush(); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + ao_delay(100); + } +} + +__code struct ao_cmds ao_demo_cmds[] = { + { ao_dma_test, "D\0DMA test" }, + { ao_spi_write, "W\0SPI write" }, + { ao_spi_read, "R\0SPI read" }, + { 0, NULL } +}; + int main(void) { @@ -57,11 +122,19 @@ main(void) ao_serial_init(); ao_timer_init(); + ao_dma_init(); ao_cmd_init(); - ao_lcd_stm_init(); - ao_lcd_font_init(); - ao_add_task(&demo_task, ao_demo, "demo"); +// ao_lcd_stm_init(); +// ao_lcd_font_init(); + ao_spi_init(); + + ao_cmd_register(&ao_demo_cmds[0]); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&stm_gpioc, 12, 1); + stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); + stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 798a292e..09c88f90 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -34,6 +34,11 @@ #define SERIAL_3_PC10_PC11 0 #define SERIAL_3_PD8_PD9 1 +#define HAS_SPI_1 1 +#define SPI_1_PB3_PB4_PB5 1 + +#define HAS_SPI_2 0 + #define HAS_USB 0 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9b68f19a..29e3f42f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -18,6 +18,8 @@ #ifndef _AO_ARCH_FUNCS_H_ #define _AO_ARCH_FUNCS_H_ +/* ao_spi_stm.c + */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } @@ -30,6 +32,30 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void -ao_spi_init(uint8_t spi_index); +ao_spi_init(void); + +/* ao_dma_stm.c + */ + +extern uint8_t ao_dma_done[STM_NUM_DMA]; + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr); + +void +ao_dma_start(uint8_t index); + +void +ao_dma_done_transfer(uint8_t index); + +void +ao_dma_abort(uint8_t index); + +void +ao_dma_init(void); #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c new file mode 100644 index 00000000..70b9e48a --- /dev/null +++ b/src/stm/ao_dma_stm.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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" + +#define NUM_DMA 7 + +struct ao_dma_config { + uint32_t isr; +}; + +uint8_t ao_dma_done[NUM_DMA]; + +static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_mutex[NUM_DMA]; + +static void +ao_dma_isr(uint8_t index) { + /* Get channel interrupt bits */ + uint32_t isr = stm_dma.isr & (STM_DMA_ISR_MASK << + STM_DMA_ISR(index)); + + /* Ack them */ + stm_dma.ifcr = isr; + isr >>= STM_DMA_ISR(index); + ao_dma_config[index].isr |= isr; + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); +} + +void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } +void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } +void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); } +void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); } +void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr) +{ + ao_mutex_get(&ao_dma_mutex[index]); + stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + stm_dma.channel[index].cndtr = count; + stm_dma.channel[index].cpar = (uint32_t) peripheral; + stm_dma.channel[index].cmar = (uint32_t) memory; +} + +void +ao_dma_start(uint8_t index) +{ + ao_dma_done[index] = 0; + stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_abort(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +} + +void +ao_dma_init(void) +{ + int index; + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + + for (index = 0; index < STM_NUM_DMA; index++) { + stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); + stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + } + +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c new file mode 100644 index 00000000..da04302b --- /dev/null +++ b/src/stm/ao_spi_stm.c @@ -0,0 +1,240 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +struct ao_spi_stm_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; +#if 0 + uint8_t *d = block; + + while (len--) { + stm_spi->dr = 0xff; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); + *d++ = stm_spi->dr; + } + while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); +#else + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +#endif +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + (0 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCNEXT) | + (0 << STM_SPI_CR1_DFF) | + (0 << STM_SPI_CR1_RXONLY) | + (1 << STM_SPI_CR1_SSM) | + (1 << STM_SPI_CR1_SSI) | + (0 << STM_SPI_CR1_LSBFIRST) | + (1 << STM_SPI_CR1_SPE) | + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_MSTR) | + (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPHA)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); +# else +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); +# else +# if SPI_1_PE13_PE14_PE15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); +# else +# error "No SPI_1 port configuration specified" +# endif +# endif +# endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + + ao_spi_channel_init(0); + + stm_nvic_set_enable(STM_ISR_SPI1_POS); + stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB13_PB14_PB15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); +# else +# if SPI_2_PPD1_PD3_PD4 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); +# else +# error "No SPI_2 port configuration specified" +# endif +# endif + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + + ao_spi_channel_init(1); + + stm_nvic_set_enable(STM_ISR_SPI2_POS); + stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); +#endif +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 531a4fb9..b40ec0ee 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -159,6 +159,17 @@ stm_afr_get(struct stm_gpio *gpio, int pin) { } } +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); +} + +static inline uint8_t +stm_gpio_isset(struct stm_gpio *gpio, int pin) { + return (gpio->idr >> pin) & 1; +} + extern struct stm_gpio stm_gpioa; extern struct stm_gpio stm_gpiob; extern struct stm_gpio stm_gpioc; @@ -238,11 +249,6 @@ extern struct stm_usart stm_usart3; #define STM_USART_CR3_IREN (1) /* IrDA mode enable */ #define STM_USART_CR3_EIE (0) /* Error interrupt enable */ -struct stm_spi { -}; - -extern struct stm_spi stm_spi1; - struct stm_tim { }; @@ -842,4 +848,168 @@ isr(tim7) #define STM_ISR_TIM6_POS 43 #define STM_ISR_TIM7_POS 44 +struct stm_dma_channel { + vuint32_t ccr; + vuint32_t cndtr; + vuint32_t cpar; + vuint32_t cmar; + vuint32_t reserved; +}; + +#define STM_NUM_DMA 7 + +struct stm_dma { + vuint32_t isr; + vuint32_t ifcr; + struct stm_dma_channel channel[STM_NUM_DMA]; +}; + +extern struct stm_dma stm_dma; + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel) ((channel) - 1) + +#define STM_DMA_ISR(index) ((index) << 2) +#define STM_DMA_ISR_MASK 0xf +#define STM_DMA_ISR_TEIF 3 +#define STM_DMA_ISR_HTIF 2 +#define STM_DMA_ISR_TCIF 1 +#define STM_DMA_ISR_GIF 0 + +#define STM_DMA_IFCR(index) ((index) << 2) +#define STM_DMA_IFCR_MASK 0xf +#define STM_DMA_IFCR_CTEIF 3 +#define STM_DMA_IFCR_CHTIF 2 +#define STM_DMA_IFCR_CTCIF 1 +#define STM_DMA_IFCR_CGIF 0 + +#define STM_DMA_CCR_MEM2MEM (14) + +#define STM_DMA_CCR_PL (12) +#define STM_DMA_CCR_PL_LOW (0) +#define STM_DMA_CCR_PL_MEDIUM (1) +#define STM_DMA_CCR_PL_HIGH (2) +#define STM_DMA_CCR_PL_VERY_HIGH (3) +#define STM_DMA_CCR_PL_MASK (3) + +#define STM_DMA_CCR_MSIZE (10) +#define STM_DMA_CCR_MSIZE_8 (0) +#define STM_DMA_CCR_MSIZE_16 (1) +#define STM_DMA_CCR_MSIZE_32 (2) +#define STM_DMA_CCR_MSIZE_MASK (3) + +#define STM_DMA_CCR_PSIZE (8) +#define STM_DMA_CCR_PSIZE_8 (0) +#define STM_DMA_CCR_PSIZE_16 (1) +#define STM_DMA_CCR_PSIZE_32 (2) +#define STM_DMA_CCR_PSIZE_MASK (3) + +#define STM_DMA_CCR_MINC (7) +#define STM_DMA_CCR_PINC (6) +#define STM_DMA_CCR_CIRC (5) +#define STM_DMA_CCR_DIR (4) +#define STM_DMA_CCR_DIR_PER_TO_MEM 0 +#define STM_DMA_CCR_DIR_MEM_TO_PER 1 +#define STM_DMA_CCR_TEIE (3) +#define STM_DMA_CCR_HTIE (2) +#define STM_DMA_CCR_TCIE (1) +#define STM_DMA_CCR_EN (0) + +#define STM_DMA_CHANNEL_ADC1 1 +#define STM_DMA_CHANNEL_SPI1_RX 2 +#define STM_DMA_CHANNEL_SPI1_TX 3 +#define STM_DMA_CHANNEL_SPI2_RX 4 +#define STM_DMA_CHANNEL_SPI2_TX 5 +#define STM_DMA_CHANNEL_USART3_TX 2 +#define STM_DMA_CHANNEL_USART3_RX 3 +#define STM_DMA_CHANNEL_USART1_TX 4 +#define STM_DMA_CHANNEL_USART1_RX 5 +#define STM_DMA_CHANNEL_USART2_RX 6 +#define STM_DMA_CHANNEL_USART2_TX 7 +#define STM_DMA_CHANNEL_I2C2_TX 4 +#define STM_DMA_CHANNEL_I2C2_RX 5 +#define STM_DMA_CHANNEL_I2C1_RX 6 +#define STM_DMA_CHANNEL_I2C1_TX 7 +#define STM_DMA_CHANNEL_TIM2_CH3 1 +#define STM_DMA_CHANNEL_TIM2_UP 2 +#define STM_DMA_CHANNEL_TIM2_CH1 5 +#define STM_DMA_CHANNEL_TIM2_CH2 7 +#define STM_DMA_CHANNEL_TIM2_CH4 7 +#define STM_DMA_CHANNEL_TIM3_CH3 2 +#define STM_DMA_CHANNEL_TIM3_CH4 3 +#define STM_DMA_CHANNEL_TIM3_UP 3 +#define STM_DMA_CHANNEL_TIM3_CH1 6 +#define STM_DMA_CHANNEL_TIM3_TRIG 6 +#define STM_DMA_CHANNEL_TIM4_CH1 1 +#define STM_DMA_CHANNEL_TIM4_CH2 4 +#define STM_DMA_CHANNEL_TIM4_CH3 5 +#define STM_DMA_CHANNEL_TIM4_UP 7 +#define STM_DMA_CHANNEL_TIM6_UP_DA 2 +#define STM_DMA_CHANNEL_C_CHANNEL1 2 +#define STM_DMA_CHANNEL_TIM7_UP_DA 3 +#define STM_DMA_CHANNEL_C_CHANNEL2 3 + +/* + * Only spi channel 1 and 2 can use DMA + */ +#define STM_NUM_SPI 2 + +struct stm_spi { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t sr; + vuint32_t dr; + vuint32_t crcpr; + vuint32_t rxcrcr; + vuint32_t txcrcr; +}; + +extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel) ((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE 15 +#define STM_SPI_CR1_BIDIOE 14 +#define STM_SPI_CR1_CRCEN 13 +#define STM_SPI_CR1_CRCNEXT 12 +#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_RXONLY 10 +#define STM_SPI_CR1_SSM 9 +#define STM_SPI_CR1_SSI 8 +#define STM_SPI_CR1_LSBFIRST 7 +#define STM_SPI_CR1_SPE 6 +#define STM_SPI_CR1_BR 3 +#define STM_SPI_CR1_BR_PCLK_2 0 +#define STM_SPI_CR1_BR_PCLK_4 1 +#define STM_SPI_CR1_BR_PCLK_8 2 +#define STM_SPI_CR1_BR_PCLK_16 3 +#define STM_SPI_CR1_BR_PCLK_32 4 +#define STM_SPI_CR1_BR_PCLK_64 5 +#define STM_SPI_CR1_BR_PCLK_128 6 +#define STM_SPI_CR1_BR_PCLK_256 7 +#define STM_SPI_CR1_BR_MASK 7 + +#define STM_SPI_CR1_MSTR 2 +#define STM_SPI_CR1_CPOL 1 +#define STM_SPI_CR1_CPHA 0 + +#define STM_SPI_CR2_TXEIE 7 +#define STM_SPI_CR2_RXNEIE 6 +#define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_SSOE 2 +#define STM_SPI_CR2_TXDMAEN 1 +#define STM_SPI_CR2_RXDMAEN 0 + +#define STM_SPI_SR_BSY 7 +#define STM_SPI_SR_OVR 6 +#define STM_SPI_SR_MODF 5 +#define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_TXE 1 +#define STM_SPI_SR_RXNE 0 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 20926b62a87154a846cb950dc542c737cd54826d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:39:12 -0700 Subject: altos: Disable STM SPI transceiver when idle Should save a bit of power. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 7 +++-- src/stm/ao_spi_stm.c | 71 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 27 deletions(-) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 29e3f42f..e0ecb0a5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -22,8 +22,11 @@ */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; -static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } -static inline void ao_spi_put(uint8_t spi_index) { ao_mutex_put(&ao_spi_mutex[spi_index]); } +void +ao_spi_get(uint8_t spi_index); + +void +ao_spi_put(uint8_t spi_index); void ao_spi_send(void *block, uint16_t len, uint8_t spi_index); diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index da04302b..92747d87 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -47,6 +47,7 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, block, @@ -59,8 +60,14 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, &spi_dev_null, @@ -93,19 +100,10 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; -#if 0 - uint8_t *d = block; - - while (len--) { - stm_spi->dr = 0xff; - while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); - *d++ = stm_spi->dr; - } - while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); -#else uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up transmit DMA to make the SPI hardware actually run */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, &spi_dev_null, @@ -118,8 +116,11 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, block, @@ -132,6 +133,7 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | @@ -140,36 +142,55 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (1 << STM_SPI_CR2_RXDMAEN)); ao_dma_start(miso_dma_index); ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ ao_arch_critical( while (!ao_dma_done[miso_dma_index]) ao_sleep(&ao_dma_done[miso_dma_index]); ); + ao_dma_done_transfer(mosi_dma_index); ao_dma_done_transfer(miso_dma_index); -#endif } -static void -ao_spi_channel_init(uint8_t spi_index) +void +ao_spi_get(uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - stm_spi->cr1 = 0; - (void) stm_spi->sr; - stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + ao_mutex_get(&ao_spi_mutex[spi_index]); + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ (0 << STM_SPI_CR1_BIDIOE) | - (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ (0 << STM_SPI_CR1_CRCNEXT) | (0 << STM_SPI_CR1_DFF) | (0 << STM_SPI_CR1_RXONLY) | - (1 << STM_SPI_CR1_SSM) | - (1 << STM_SPI_CR1_SSI) | - (0 << STM_SPI_CR1_LSBFIRST) | - (1 << STM_SPI_CR1_SPE) | - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Little endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | - (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); +} + +void +ao_spi_put(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_mutex[spi_index]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | -- cgit v1.2.3 From 0bcc23c3be1a20a362fea268901c600f9f0d287a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:39:45 -0700 Subject: altos: Disable DMA unit when idle Should save a bit of power Signed-off-by: Keith Packard --- src/stm/ao_dma_stm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 70b9e48a..f996e7cd 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -27,6 +27,7 @@ uint8_t ao_dma_done[NUM_DMA]; static struct ao_dma_config ao_dma_config[NUM_DMA]; static uint8_t ao_dma_mutex[NUM_DMA]; +static uint8_t ao_dma_active; static void ao_dma_isr(uint8_t index) { @@ -58,10 +59,12 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr) { ao_mutex_get(&ao_dma_mutex[index]); + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); stm_dma.channel[index].cndtr = count; - stm_dma.channel[index].cpar = (uint32_t) peripheral; - stm_dma.channel[index].cmar = (uint32_t) memory; + stm_dma.channel[index].cpar = peripheral; + stm_dma.channel[index].cmar = memory; } void @@ -75,6 +78,8 @@ void ao_dma_done_transfer(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ao_mutex_put(&ao_dma_mutex[index]); } @@ -89,8 +94,6 @@ ao_dma_init(void) { int index; - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); - for (index = 0; index < STM_NUM_DMA; index++) { stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); -- cgit v1.2.3 From 89201cdf2062b7319a0da4e266e4d6edba1493f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:40:17 -0700 Subject: altos: Declare stm DMA address registers as volatile void * Eliminates a cast when assigning to them. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b40ec0ee..e03556b0 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -21,6 +21,7 @@ #include typedef volatile uint32_t vuint32_t; +typedef volatile void * vvoid_t; struct stm_gpio { vuint32_t moder; @@ -851,8 +852,8 @@ isr(tim7) struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; - vuint32_t cpar; - vuint32_t cmar; + vvoid_t cpar; + vvoid_t cmar; vuint32_t reserved; }; -- cgit v1.2.3 From 2db6b0f58811ffc44a468c8fbcacc08d37edd26c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:40:49 -0700 Subject: altos: Shuffle stm-demo SPI test code around a bit Move a debug printf beyond the chip select boundary to allow for more accurate timing. Send four bytes instead of just one. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 54f7c8f2..5ff2b32a 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -82,7 +82,7 @@ ao_spi_write(void) { for (i = 0; i < 10; i++) { ao_spi_get(0); stm_gpio_set(&stm_gpioc, 12, 0); - ao_spi_send(data, 1, 0); + ao_spi_send(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); ao_spi_put(0); printf("."); @@ -100,10 +100,10 @@ ao_spi_read(void) { ao_spi_get(0); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_recv(data, 4, 0); - printf("."); - flush(); stm_gpio_set(&stm_gpioc, 12, 1); ao_spi_put(0); + printf("."); + flush(); ao_delay(100); } } -- cgit v1.2.3 From 5569e4df50648a3ec131ba5e244da9b67d1a67db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:21:03 -0700 Subject: altosui: Radio channel gets set to zero by altos when frequency is set Just remember what the channe is going to get set to. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 8eb71e1f..bb2665c2 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -397,6 +397,7 @@ public class AltosConfig implements ActionListener { if (frequency > 0) { radio_frequency.set((int) Math.floor (freq * 1000 + 0.5)); + radio_channel.set(0); } else if (setting > 0) { radio_setting.set(AltosConvert.radio_frequency_to_setting(freq, radio_calibration.get())); -- cgit v1.2.3 From 5f63065a16b65618b39314880c72074f0a8b5550 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:22:02 -0700 Subject: altos: Add fake install/uninstall targets for stm-bringup Keep global 'make install' from failing. Signed-off-by: Keith Packard --- src/stm-bringup/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 1ba480ba..01c80614 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -40,3 +40,7 @@ clean: rm -rf *.bin .PHONY: all clean + +install: + +uninstall: -- cgit v1.2.3 From 41a8383ccd29351f3a88a374f9456d6efb71b9a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:22:41 -0700 Subject: altos: Save memory in ao_cmd.c Shrink a couple of help strings move a variable in ao_cmd from data to pdata. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index cde68b39..fdc70007 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -300,7 +300,7 @@ ao_cmd_register(__code struct ao_cmds *cmds) void ao_cmd(void) { - char c; + __pdata char c; uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); @@ -336,8 +336,8 @@ __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { { help, "?\0Help" }, - { ao_task_info, "T\0Show tasks" }, - { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_task_info, "T\0Tasks" }, + { echo, "E <0 off, 1 on>\0Echo" }, { ao_reboot, "r eboot\0Reboot" }, { version, "v\0Version" }, { 0, NULL }, -- cgit v1.2.3 From 8405efb6ca68c8216413b94e7acbdf51af00554a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:23:55 -0700 Subject: altos: Save memory in ao_config.c Shorten help messages. Stop setting aes_key on products not using aes key. Signed-off-by: Keith Packard --- src/core/ao_config.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08e6deea..1dafab8d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -113,8 +113,10 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; +#if HAS_AES if (ao_config.minor < 9) - memset(&ao_config.aes_key, 0, AO_AES_LEN); + ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); +#endif if (ao_config.minor < 10) { ao_config.frequency = 434550; #if HAS_RADIO_CHANNELS @@ -525,12 +527,12 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_ADC - { "m \0Main deploy (in meters)", + { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, - { "d \0Apogee delay (in seconds)", + { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, #endif /* HAS_ADC */ - { "r \0Radio channel (freq = 434.550 + chan * .1)", + { "r \0Radio channel", ao_config_radio_channel_set, ao_config_radio_channel_show }, { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, @@ -545,7 +547,7 @@ __code struct ao_config_var ao_config_vars[] = { { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, #if HAS_LOG - { "l \0Flight log size in kB", + { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, #endif #if HAS_IGNITE @@ -637,7 +639,7 @@ ao_config_write(void) __reentrant #endif __code struct ao_cmds ao_config_cmds[] = { - { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { ao_config_set, "c \0Set config (? for help, s to show)" }, { 0, NULL }, }; -- cgit v1.2.3 From d0d0d20c20e5eeacbc9a1ec1c93141a2044830fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:24:59 -0700 Subject: altos: Shorten help strings Save a bit of code space Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 +- src/core/ao_log_single.c | 6 +++--- src/core/ao_monitor.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 6d3ad535..db60707d 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -264,7 +264,7 @@ ao_log_delete(void) __reentrant } __code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List flight logs" }, + { ao_log_list, "l\0List logs" }, { ao_log_delete, "d \0Delete flight" }, { 0, NULL }, }; diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c index 9e90bd82..3f6235a6 100644 --- a/src/core/ao_log_single.c +++ b/src/core/ao_log_single.c @@ -180,9 +180,9 @@ ao_log_single_query(void) } const struct ao_cmds ao_log_single_cmds[] = { - { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_single_list, "l\0List stored flight logs" }, - { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_set, "L <0 off, 1 on>\0Set logging" }, + { ao_log_single_list, "l\0List stored logs" }, + { ao_log_single_delete, "d 1\0Delete all stored logs" }, { ao_log_single_query, "q\0Query log status" }, { 0, NULL }, }; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 7960208e..830464d8 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -267,7 +267,7 @@ set_monitor(void) } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Set radio monitoring" }, { 0, NULL }, }; #endif -- cgit v1.2.3 From c7119405a3dd7128120374a2a001bc98ef523619 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:26 -0700 Subject: altos: Make ao_freq_to_set reentrant Save a bunch of data space this way. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_freq.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index 67efa437..150c0817 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1892,7 +1892,7 @@ ao_sqrt(uint32_t op); * ao_freq.c */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal); +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant; #include diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 67b0b037..12496f6f 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -25,10 +25,15 @@ * frequency, and updating the radio setting along the way */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal) { - __pdata int32_t set = 0; - uint8_t neg = 0; - __pdata int32_t error = -434550 / 2; +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant +{ + static __pdata int32_t set; + static __pdata uint8_t neg; + static __pdata int32_t error; + + set = 0; + neg = 0; + error = -434550 / 2; if ((freq -= 434550) < 0) { neg = 1; -- cgit v1.2.3 From a0a650a2be007b0436bd527d6c18f36eef6fbe2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:50 -0700 Subject: altos: Force radio channel to zero when setting frequency Otherwise, the actual radio frequency will include the channel offset, which is not useful. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 1dafab8d..2d3d2870 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -218,6 +218,7 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; + ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); -- cgit v1.2.3 From 4700f63937786e8f6e9b4882363234a33eb54c46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 01:01:06 -0700 Subject: altos: Make ao_config_set_radio public Allows other bits of code to reset the radio parameters. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_config.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index 150c0817..f7db3bf4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1510,6 +1510,9 @@ ao_config_get(void); void ao_config_put(void); +void +ao_config_set_radio(void); + void ao_config_init(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 2d3d2870..32798f75 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,7 +64,7 @@ ao_config_put(void) } #endif -static void +void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); -- cgit v1.2.3 From d35c4df12a3d8e2dab5d41f8d918ff4237f91e46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 01:01:33 -0700 Subject: altos: Add ability to change radio frequency in TeleTerra Provide a way to set the frequency locally. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 83 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 21 deletions(-) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 9b40c42a..8875ff48 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -98,13 +98,19 @@ ao_terraui_startup(void) } static void -ao_terraui_info(void) +ao_terraui_info_firstline(void) { sprintf(ao_lcd_line, "S %4d %7.7s %c", ao_tel_sensor.serial, ao_tel_config.callsign, ao_terraui_state()); ao_terraui_line(AO_LCD_ADDR(0,0)); +} + +static void +ao_terraui_info(void) +{ + ao_terraui_info_firstline(); sprintf(ao_lcd_line, "F %4d RSSI%4d%c", ao_tel_config.flight, ao_tel_rssi, @@ -449,31 +455,57 @@ ao_terraui_local(void) __reentrant ao_terraui_line(AO_LCD_ADDR(1,0)); } +static __pdata uint8_t ao_set_freq; +static __pdata uint32_t ao_set_freq_orig; + static void -ao_terraui_config(void) __reentrant +ao_terraui_freq(void) __reentrant { - uint8_t chan; - uint32_t kHz; uint16_t MHz; uint16_t frac; - - for (chan = 0; chan < AO_NUM_CHANNELS; chan++) - if (ao_config.radio_channels[chan].kHz == ao_config.frequency) - break; - if (chan == AO_NUM_CHANNELS) - chan = 0; - kHz = ao_config.radio_channels[chan].kHz; - MHz = kHz / 1000; - frac = kHz % 1000; - sprintf(ao_lcd_line, "%2d: %-10.10s ", chan, ao_config.radio_channels[chan].name); - ao_terraui_line(AO_LCD_ADDR(0,0)); - sprintf(ao_lcd_line, "%-8.8s %3d.%03d", ao_config.callsign, MHz, frac); + MHz = ao_config.frequency / 1000; + frac = ao_config.frequency % 1000; + ao_terraui_info_firstline(); + sprintf(ao_lcd_line, "Freq: %3d.%03d MHz", MHz, frac); ao_terraui_line(AO_LCD_ADDR(1,0)); - ao_lcd_goto(AO_LCD_ADDR(0,1)); + ao_lcd_goto(AO_LCD_ADDR(1,11)); +} + +static void +ao_terraui_freq_start(void) +{ + ao_set_freq = 1; + ao_set_freq_orig = ao_config.frequency; ao_lcd_cursor_on(); } +static void +ao_terraui_freq_button(char b) { + + switch (b) { + case 0: + return; + case 1: + if (ao_config.frequency > 430000) + ao_config.frequency -= 100; + break; + case 2: + ao_set_freq = 0; + ao_lcd_cursor_off(); + if (ao_set_freq_orig != ao_config.frequency) + ao_config_put(); + return; + case 3: + if (ao_config.frequency < 438000) + ao_config.frequency += 100; + break; + + } + ao_config_set_radio(); + ao_radio_recv_abort(); +} + static __code void (*__code ao_terraui_page[])(void) = { ao_terraui_startup, ao_terraui_info, @@ -483,13 +515,12 @@ static __code void (*__code ao_terraui_page[])(void) = { ao_terraui_recover, ao_terraui_remote, ao_terraui_local, - ao_terraui_config, }; #define NUM_PAGE (sizeof (ao_terraui_page)/sizeof (ao_terraui_page[0])) -__pdata uint8_t ao_current_page = 0; -__pdata uint8_t ao_shown_about = 3; +static __pdata uint8_t ao_current_page = 0; +static __pdata uint8_t ao_shown_about = 3; static void ao_terraui(void) @@ -501,7 +532,12 @@ ao_terraui(void) for (;;) { char b; - ao_terraui_page[ao_current_page](); + + if (ao_set_freq) + ao_terraui_freq(); + else + ao_terraui_page[ao_current_page](); + ao_alarm(AO_SEC_TO_TICKS(1)); b = ao_button_get(); ao_clear_alarm(); @@ -511,6 +547,10 @@ ao_terraui(void) ao_shown_about = 0; } + if (ao_set_freq) { + ao_terraui_freq_button(b); + continue; + } switch (b) { case 0: if (ao_shown_about) { @@ -524,6 +564,7 @@ ao_terraui(void) ao_current_page = 0; break; case 2: + ao_terraui_freq_start(); break; case 3: if (ao_current_page == 0) -- cgit v1.2.3 From 20066268d8d1853055d0afe108584db34b425fcb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:35:26 -0700 Subject: altosui: Integrate accel speed from very start of eeprom record Don't wait for the flight computer to have detected boost--that's often several samples after boost actually occurred, which can leave a bunch of acceleration out of the speed computation. Signed-off-by: Keith Packard --- altosui/AltosEepromIterable.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index d8205816..6fdaf8e0 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -99,6 +99,7 @@ public class AltosEepromIterable extends AltosRecordIterable { double ground_pres; int gps_tick; int boost_tick; + int sensor_tick; EepromState() { seen = 0; @@ -128,10 +129,13 @@ public class AltosEepromIterable extends AltosRecordIterable { state.flight_pres = state.ground_pres; } else { state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - state.flight_vel += (state.accel_plus_g - state.accel); } + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; has_accel = true; break; case Altos.AO_LOG_PRESSURE: -- cgit v1.2.3 From e56038b65ba1c6413ba9942be3c092644986f126 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:36:36 -0700 Subject: altosui: When computing flight stats, auto-detect boost time Detect when boost actually starts by looking for the last low acceleration value before the recorded boost time. This improves the computation of the boost state data. Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index dce5cb3e..ed5a336e 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -77,10 +77,30 @@ public class AltosFlightStats { return landed_time; } + double boost_time(AltosRecordIterable iterable) { + double boost_time = -1000; + + AltosState state = null; + + for (AltosRecord record : iterable) { + state = new AltosState(record, state); + + if (state.acceleration < 1) + boost_time = state.time; + if (state.state >= Altos.ao_flight_boost) + break; + } + if (boost_time == -1000) + boost_time = state.time; + System.out.printf ("boost time %f instead of %f\n", boost_time, state.time); + return boost_time; + } + + public AltosFlightStats(AltosRecordIterable iterable) throws InterruptedException, IOException { AltosState state = null; AltosState new_state = null; - double boost_time = -1; + double boost_time = boost_time(iterable); double end_time = 0; double landed_time = landed_time(iterable); @@ -95,10 +115,12 @@ public class AltosFlightStats { new_state = new AltosState(record, state); end_time = new_state.time; state = new_state; + if (state.time >= boost_time && state.state < Altos.ao_flight_boost) + state.state = Altos.ao_flight_boost; + if (state.time >= landed_time && state.state < Altos.ao_flight_landed) + state.state = Altos.ao_flight_landed; if (0 <= state.state && state.state < Altos.ao_flight_invalid) { if (state.state >= Altos.ao_flight_boost) { - if (boost_time == -1) - boost_time = state.time; if (state.gps != null && state.gps.locked && year < 0) { year = state.gps.year; @@ -109,8 +131,6 @@ public class AltosFlightStats { second = state.gps.second; } } - if (state.time >= landed_time) - state.state = Altos.ao_flight_landed; state_accel[state.state] += state.acceleration; state_speed[state.state] += state.speed; state_baro_speed[state.state] += state.baro_speed; -- cgit v1.2.3 From fa96ee3db9b57cc2a88e9edd74bb9efcc228ccf3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:44:11 -0700 Subject: altosui: remove debug printf from AltosFlightStats Signed-off-by: Keith Packard --- altosui/AltosFlightStats.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index ed5a336e..578be3f9 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -92,7 +92,6 @@ public class AltosFlightStats { } if (boost_time == -1000) boost_time = state.time; - System.out.printf ("boost time %f instead of %f\n", boost_time, state.time); return boost_time; } -- cgit v1.2.3 From 5e41d1e03680af9806c599aad80b9b64dd719f9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:53:12 -0700 Subject: altos: Add support for STM ADC DMA-based driver for the STM analog to digital converter. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_arch.h | 10 +-- src/stm/ao_arch_funcs.h | 3 + src/stm/ao_dma_stm.c | 31 +++++-- src/stm/stm32l.h | 139 ++++++++++++++++++++++++++++++ 5 files changed, 392 insertions(+), 16 deletions(-) create mode 100644 src/stm/ao_adc_stm.c diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c new file mode 100644 index 00000000..1722a9ec --- /dev/null +++ b/src/stm/ao_adc_stm.c @@ -0,0 +1,225 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; +static uint8_t ao_adc_ready; + +#define AO_ADC_CR2_VAL ((0 << STM_ADC_CR2_SWSTART) | \ + (STM_ADC_CR2_EXTEN_DISABLE << STM_ADC_CR2_EXTEN) | \ + (0 << STM_ADC_CR2_EXTSEL) | \ + (0 << STM_ADC_CR2_JWSTART) | \ + (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \ + (0 << STM_ADC_CR2_JEXTSEL) | \ + (1 << STM_ADC_CR2_ALIGN) | \ + (0 << STM_ADC_CR2_EOCS) | \ + (1 << STM_ADC_CR2_DDS) | \ + (1 << STM_ADC_CR2_DMA) | \ + (STM_ADC_CR2_DELS_NONE << STM_ADC_CR2_DELS) | \ + (0 << STM_ADC_CR2_CONT) | \ + (1 << STM_ADC_CR2_ADON)) + +/* + * Callback from DMA ISR + * + * Mark time in ring, shut down DMA engine + */ +static void ao_adc_done(void) +{ + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup((void *) &ao_adc_head); + ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + ao_adc_ready = 1; +} + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_poll(void) +{ + if (!ao_adc_ready) + return; + ao_adc_ready = 0; + stm_adc.sr = 0; + ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), + &stm_adc.dr, + (void *) (&ao_adc_ring[ao_adc_head].tick + 1), + AO_NUM_ADC, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done); + ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + + stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); +} + +/* + * Fetch a copy of the most recent ADC data + */ +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_adc_head); + memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ + struct ao_adc packet; + int16_t *d; + uint8_t i; + + ao_adc_get(&packet); + printf("tick: %5u", packet.tick); + d = (int16_t *) (&packet.tick + 1); + for (i = 0; i < AO_NUM_ADC; i++) + printf (" %2d: %5d", i, d[i]); + printf("\n"); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ +#ifdef AO_ADC_PIN0_PORT + stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR; +#endif + +#ifdef AO_ADC_PIN0_PORT + stm_moder_set(&AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN1_PORT + stm_moder_set(&AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN2_PORT + stm_moder_set(&AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN3_PORT + stm_moder_set(&AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN4_PORT + stm_moder_set(&AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN5_PORT + stm_moder_set(&AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN6_PORT + stm_moder_set(&AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN7_PORT + stm_moder_set(&AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN8_PORT + stm_moder_set(&AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN9_PORT + stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); +#endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); + + /* Turn off ADC during configuration */ + stm_adc.cr2 = 0; + + stm_adc.cr1 = ((0 << STM_ADC_CR1_OVRIE ) | + (STM_ADC_CR1_RES_12 << STM_ADC_CR1_RES ) | + (0 << STM_ADC_CR1_AWDEN ) | + (0 << STM_ADC_CR1_JAWDEN ) | + (0 << STM_ADC_CR1_PDI ) | + (0 << STM_ADC_CR1_PDD ) | + (0 << STM_ADC_CR1_DISCNUM ) | + (0 << STM_ADC_CR1_JDISCEN ) | + (0 << STM_ADC_CR1_DISCEN ) | + (0 << STM_ADC_CR1_JAUTO ) | + (0 << STM_ADC_CR1_AWDSGL ) | + (1 << STM_ADC_CR1_SCAN ) | + (0 << STM_ADC_CR1_JEOCIE ) | + (0 << STM_ADC_CR1_AWDIE ) | + (0 << STM_ADC_CR1_EOCIE ) | + (0 << STM_ADC_CR1_AWDCH )); + + /* 4 cycle sample time for everyone */ + stm_adc.smpr1 = 0; + stm_adc.smpr2 = 0; + stm_adc.smpr3 = 0; + + stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); + stm_adc.sqr2 = 0; + stm_adc.sqr3 = 0; + stm_adc.sqr4 = 0; + stm_adc.sqr5 = 0; +#if AO_NUM_ADC > 0 + stm_adc.sqr5 |= (AO_ADC_SQ1 << 0); +#endif +#if AO_NUM_ADC > 1 + stm_adc.sqr5 |= (AO_ADC_SQ2 << 5); +#endif +#if AO_NUM_ADC > 2 + stm_adc.sqr5 |= (AO_ADC_SQ3 << 10); +#endif +#if AO_NUM_ADC > 3 + stm_adc.sqr5 |= (AO_ADC_SQ4 << 15); +#endif +#if AO_NUM_ADC > 4 + stm_adc.sqr5 |= (AO_ADC_SQ5 << 20); +#endif +#if AO_NUM_ADC > 5 + stm_adc.sqr5 |= (AO_ADC_SQ6 << 25); +#endif +#if AO_NUM_ADC > 6 + stm_adc.sqr4 |= (AO_ADC_SQ7 << 0); +#endif +#if AO_NUM_ADC > 7 + stm_adc.sqr4 |= (AO_ADC_SQ8 << 5); +#endif +#if AO_NUM_ADC > 8 + stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); +#endif + + /* Turn ADC on */ + stm_adc.cr2 = AO_ADC_CR2_VAL; + + /* Wait for ADC to be ready */ + while (!(stm_adc.sr & (1 << STM_ADC_SR_ADONS))) + ; + +#if HAS_ADC_TEMP + stm_adc.ccr = ((1 << STM_ADC_CCR_TSVREFE)); +#else + stm_adc.ccr = 0; +#endif + /* Clear any stale status bits */ + stm_adc.sr = 0; + ao_adc_ready = 1; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 188b8996..ce3a22e2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -145,13 +145,6 @@ extern const uint16_t ao_serial_number; #define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) -#define AO_ARM_NUM_ADC 12 - -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ -}; - /* * For now, we're running at a weird frequency */ @@ -203,5 +196,8 @@ ao_serial3_set_speed(uint8_t speed); extern uint32_t ao_radio_cal; +void +ao_adc_init(); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index e0ecb0a5..a42fe10f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -49,6 +49,9 @@ ao_dma_set_transfer(uint8_t index, uint16_t count, uint32_t ccr); +void +ao_dma_set_isr(uint8_t index, void (*isr)(void)); + void ao_dma_start(uint8_t index); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index f996e7cd..785235a8 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -20,7 +20,7 @@ #define NUM_DMA 7 struct ao_dma_config { - uint32_t isr; + void (*isr)(void); }; uint8_t ao_dma_done[NUM_DMA]; @@ -37,10 +37,12 @@ ao_dma_isr(uint8_t index) { /* Ack them */ stm_dma.ifcr = isr; - isr >>= STM_DMA_ISR(index); - ao_dma_config[index].isr |= isr; - ao_dma_done[index] = 1; - ao_wakeup(&ao_dma_done[index]); + if (ao_dma_config[index].isr) + (*ao_dma_config[index].isr)(); + else { + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); + } } void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } @@ -59,12 +61,21 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr) { ao_mutex_get(&ao_dma_mutex[index]); - if (ao_dma_active++ == 0) - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ); stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); stm_dma.channel[index].cndtr = count; stm_dma.channel[index].cpar = peripheral; stm_dma.channel[index].cmar = memory; + ao_dma_config[index].isr = NULL; +} + +void +ao_dma_set_isr(uint8_t index, void (*isr)(void)) +{ + ao_dma_config[index].isr = isr; } void @@ -78,8 +89,10 @@ void ao_dma_done_transfer(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); - if (--ao_dma_active == 0) - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ); ao_mutex_put(&ao_dma_mutex[index]); } diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e03556b0..b9f45513 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1013,4 +1013,143 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_SR_TXE 1 #define STM_SPI_SR_RXNE 0 +struct stm_adc { + vuint32_t sr; + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smpr1; + vuint32_t smpr2; + vuint32_t smpr3; + vuint32_t jofr1; + vuint32_t jofr2; + vuint32_t jofr3; + vuint32_t jofr4; + vuint32_t htr; + vuint32_t ltr; + vuint32_t sqr1; + vuint32_t sqr2; + vuint32_t sqr3; + vuint32_t sqr4; + vuint32_t sqr5; + vuint32_t jsqr; + vuint32_t jdr1; + vuint32_t jdr2; + vuint32_t jdr3; + vuint32_t jdr4; + vuint32_t dr; + uint8_t reserved[0x300 - 0x5c]; + vuint32_t csr; + vuint32_t ccr; +}; + +extern struct stm_adc stm_adc; + +#define STM_ADC_SR_JCNR 9 +#define STM_ADC_SR_RCNR 8 +#define STM_ADC_SR_ADONS 6 +#define STM_ADC_SR_OVR 5 +#define STM_ADC_SR_STRT 4 +#define STM_ADC_SR_JSTRT 3 +#define STM_ADC_SR_JEOC 2 +#define STM_ADC_SR_EOC 1 +#define STM_ADC_SR_AWD 0 + +#define STM_ADC_CR1_OVRIE 26 +#define STM_ADC_CR1_RES 24 +#define STM_ADC_CR1_RES_12 0 +#define STM_ADC_CR1_RES_10 1 +#define STM_ADC_CR1_RES_8 2 +#define STM_ADC_CR1_RES_6 3 +#define STM_ADC_CR1_RES_MASK 3 +#define STM_ADC_CR1_AWDEN 23 +#define STM_ADC_CR1_JAWDEN 22 +#define STM_ADC_CR1_PDI 17 +#define STM_ADC_CR1_PDD 16 +#define STM_ADC_CR1_DISCNUM 13 +#define STM_ADC_CR1_DISCNUM_1 0 +#define STM_ADC_CR1_DISCNUM_2 1 +#define STM_ADC_CR1_DISCNUM_3 2 +#define STM_ADC_CR1_DISCNUM_4 3 +#define STM_ADC_CR1_DISCNUM_5 4 +#define STM_ADC_CR1_DISCNUM_6 5 +#define STM_ADC_CR1_DISCNUM_7 6 +#define STM_ADC_CR1_DISCNUM_8 7 +#define STM_ADC_CR1_DISCNUM_MASK 7 +#define STM_ADC_CR1_JDISCEN 12 +#define STM_ADC_CR1_DISCEN 11 +#define STM_ADC_CR1_JAUTO 10 +#define STM_ADC_CR1_AWDSGL 9 +#define STM_ADC_CR1_SCAN 8 +#define STM_ADC_CR1_JEOCIE 7 +#define STM_ADC_CR1_AWDIE 6 +#define STM_ADC_CR1_EOCIE 5 +#define STM_ADC_CR1_AWDCH 0 +#define STM_ADC_CR1_AWDCH_MASK 0x1f + +#define STM_ADC_CR2_SWSTART 30 +#define STM_ADC_CR2_EXTEN 28 +#define STM_ADC_CR2_EXTEN_DISABLE 0 +#define STM_ADC_CR2_EXTEN_RISING 1 +#define STM_ADC_CR2_EXTEN_FALLING 2 +#define STM_ADC_CR2_EXTEN_BOTH 3 +#define STM_ADC_CR2_EXTEN_MASK 3 +#define STM_ADC_CR2_EXTSEL 24 +#define STM_ADC_CR2_EXTSEL_TIM9_CC2 0 +#define STM_ADC_CR2_EXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_EXTSEL_TIM2_CC3 2 +#define STM_ADC_CR2_EXTSEL_TIM2_CC2 3 +#define STM_ADC_CR2_EXTSEL_TIM3_TRGO 4 +#define STM_ADC_CR2_EXTSEL_TIM4_CC4 5 +#define STM_ADC_CR2_EXTSEL_TIM2_TRGO 6 +#define STM_ADC_CR2_EXTSEL_TIM3_CC1 7 +#define STM_ADC_CR2_EXTSEL_TIM3_CC3 8 +#define STM_ADC_CR2_EXTSEL_TIM4_TRGO 9 +#define STM_ADC_CR2_EXTSEL_TIM6_TRGO 10 +#define STM_ADC_CR2_EXTSEL_EXTI_11 15 +#define STM_ADC_CR2_EXTSEL_MASK 15 +#define STM_ADC_CR2_JWSTART 22 +#define STM_ADC_CR2_JEXTEN 20 +#define STM_ADC_CR2_JEXTEN_DISABLE 0 +#define STM_ADC_CR2_JEXTEN_RISING 1 +#define STM_ADC_CR2_JEXTEN_FALLING 2 +#define STM_ADC_CR2_JEXTEN_BOTH 3 +#define STM_ADC_CR2_JEXTEN_MASK 3 +#define STM_ADC_CR2_JEXTSEL 16 +#define STM_ADC_CR2_JEXTSEL_TIM9_CC1 0 +#define STM_ADC_CR2_JEXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_JEXTSEL_TIM2_TRGO 2 +#define STM_ADC_CR2_JEXTSEL_TIM2_CC1 3 +#define STM_ADC_CR2_JEXTSEL_TIM3_CC4 4 +#define STM_ADC_CR2_JEXTSEL_TIM4_TRGO 5 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC1 6 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC2 7 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC3 8 +#define STM_ADC_CR2_JEXTSEL_TIM10_CC1 9 +#define STM_ADC_CR2_JEXTSEL_TIM7_TRGO 10 +#define STM_ADC_CR2_JEXTSEL_EXTI_15 15 +#define STM_ADC_CR2_JEXTSEL_MASK 15 +#define STM_ADC_CR2_ALIGN 11 +#define STM_ADC_CR2_EOCS 10 +#define STM_ADC_CR2_DDS 9 +#define STM_ADC_CR2_DMA 8 +#define STM_ADC_CR2_DELS 4 +#define STM_ADC_CR2_DELS_NONE 0 +#define STM_ADC_CR2_DELS_UNTIL_READ 1 +#define STM_ADC_CR2_DELS_7 2 +#define STM_ADC_CR2_DELS_15 3 +#define STM_ADC_CR2_DELS_31 4 +#define STM_ADC_CR2_DELS_63 5 +#define STM_ADC_CR2_DELS_127 6 +#define STM_ADC_CR2_DELS_255 7 +#define STM_ADC_CR2_DELS_MASK 7 +#define STM_ADC_CR2_CONT 1 +#define STM_ADC_CR2_ADON 0 + +#define STM_ADC_CCR_TSVREFE 23 +#define STM_ADC_CCR_ADCPRE 16 +#define STM_ADC_CCR_ADCPRE_HSI_1 0 +#define STM_ADC_CCR_ADCPRE_HSI_2 1 +#define STM_ADC_CCR_ADCPRE_HSI_4 2 +#define STM_ADC_CCR_ADCPRE_MASK 3 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From b5e9d14b4e3e8f29ad8a7bb9b339890be4bcfa2f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:54:32 -0700 Subject: altos: STM SPI is not using interrupts itself All SPI transfers are done via DMA, so the DMA interrupts suffice. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 92747d87..ecf7934f 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -229,9 +229,6 @@ ao_spi_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); ao_spi_channel_init(0); - - stm_nvic_set_enable(STM_ISR_SPI1_POS); - stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); #endif #if HAS_SPI_2 @@ -254,8 +251,5 @@ ao_spi_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); ao_spi_channel_init(1); - - stm_nvic_set_enable(STM_ISR_SPI2_POS); - stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); #endif } -- cgit v1.2.3 From 9b9357f48597a034211affb3f18fc6089816456d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:55:20 -0700 Subject: altos: Add ADC tests to stm-demo Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 5 +++-- src/stm-demo/ao_demo.c | 24 +++++++++++++----------- src/stm-demo/ao_pins.h | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index c1f49371..26c81a82 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -29,13 +29,14 @@ ALTOS_SRC = \ ao_lcd_font.c \ ao_mutex.c \ ao_dma_stm.c \ - ao_spi_stm.c + ao_spi_stm.c \ + ao_adc_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -O0 PROG=stm-demo diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5ff2b32a..63647aac 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -51,13 +51,15 @@ void _exit () { } void _read () { } void _fstat() { } +#define AO_DMA_TEST_INDEX STM_DMA_INDEX(4) + static void ao_dma_test(void) { static char src[20] = "hello, world"; static char dst[20]; dst[0] = '\0'; - ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, + ao_dma_set_transfer(AO_DMA_TEST_INDEX, dst, src, 13, (1 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_LOW << STM_DMA_CCR_PL) | (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | @@ -66,11 +68,12 @@ ao_dma_test(void) { (1 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - ao_dma_start(STM_DMA_INDEX(1)); - cli(); - while (!ao_dma_done[STM_DMA_INDEX(1)]) - ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); - sei(); + ao_dma_start(AO_DMA_TEST_INDEX); + ao_arch_critical( + while (!ao_dma_done[AO_DMA_TEST_INDEX]) + ao_sleep(&ao_dma_done[AO_DMA_TEST_INDEX]); + ); + ao_dma_done_transfer(AO_DMA_TEST_INDEX); printf ("copied %s\n", dst); } @@ -128,13 +131,12 @@ main(void) // ao_lcd_font_init(); ao_spi_init(); + ao_timer_set_adc_interval(100); + + ao_adc_init(); + ao_cmd_register(&ao_demo_cmds[0]); - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); - stm_gpio_set(&stm_gpioc, 12, 1); - stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); - stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); - ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 09c88f90..fecd8cda 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -111,4 +111,29 @@ #define AO_LCD_28_ON_C 1 +#define HAS_ADC 1 + +#define AO_ADC_RING 32 + +struct ao_adc { + uint16_t tick; + int16_t idd; + int16_t temp; +}; + +#define AO_ADC_IDD 4 +#define AO_ADC_PIN0_PORT stm_gpioa +#define AO_ADC_PIN0_PIN 4 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) +#define AO_ADC_TEMP 16 + +#define HAS_ADC_TEMP 1 + +#define AO_NUM_ADC 2 + +#define AO_ADC_SQ1 AO_ADC_IDD +#define AO_ADC_SQ2 AO_ADC_TEMP + + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From a41628c97e90770890cce1d6f580e92c1cad1a7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:55:53 -0700 Subject: altos: Add ADC support to megametrum firmware Measures all MM igniter and battery voltages. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 +- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 82 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index fbcb4a57..71f4adf7 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -34,7 +34,8 @@ ALTOS_SRC = \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ - ao_ms5607.c + ao_ms5607.c \ + ao_adc_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 0d88f4c1..02fe91fe 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -32,6 +32,7 @@ main(void) ao_dma_init(); ao_spi_init(); ao_ms5607_init(); + ao_adc_init(); ao_start_scheduler(); return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index ee4510e6..803678b2 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -69,4 +69,86 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define HAS_ADC 1 + +#define AO_ADC_RING 32 +#define AO_ADC_NUM_SENSE 6 + +struct ao_adc { + uint16_t tick; + int16_t sense[AO_ADC_NUM_SENSE]; + int16_t v_batt; + int16_t v_pbatt; + int16_t temp; +}; + +#define AO_ADC_SENSE_A 0 +#define AO_ADC_SENSE_A_PORT stm_gpioa +#define AO_ADC_SENSE_A_PIN 0 + +#define AO_ADC_SENSE_B 1 +#define AO_ADC_SENSE_B_PORT stm_gpioa +#define AO_ADC_SENSE_B_PIN 1 + +#define AO_ADC_SENSE_C 2 +#define AO_ADC_SENSE_C_PORT stm_gpioa +#define AO_ADC_SENSE_C_PIN 2 + +#define AO_ADC_SENSE_D 3 +#define AO_ADC_SENSE_D_PORT stm_gpioa +#define AO_ADC_SENSE_D_PIN 3 + +#define AO_ADC_SENSE_E 4 +#define AO_ADC_SENSE_E_PORT stm_gpioa +#define AO_ADC_SENSE_E_PIN 4 + +#define AO_ADC_SENSE_F 22 +#define AO_ADC_SENSE_F_PORT stm_gpioe +#define AO_ADC_SENSE_F_PIN 7 + +#define AO_ADC_V_BATT 8 +#define AO_ADC_V_BATT_PORT stm_gpiob +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_V_PBATT 9 +#define AO_ADC_V_PBATT_PORT stm_gpiob +#define AO_ADC_V_PBATT_PIN 1 + +#define AO_ADC_TEMP 16 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ + (1 << STM_RCC_AHBENR_GPIOEEN) | \ + (1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) + +#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT +#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN +#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT +#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN +#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT +#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN +#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT +#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN +#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT +#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN +#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT +#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN +#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN +#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT +#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN + +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) + +#define AO_ADC_SQ1 AO_ADC_SENSE_A +#define AO_ADC_SQ2 AO_ADC_SENSE_B +#define AO_ADC_SQ3 AO_ADC_SENSE_C +#define AO_ADC_SQ4 AO_ADC_SENSE_D +#define AO_ADC_SQ5 AO_ADC_SENSE_E +#define AO_ADC_SQ6 AO_ADC_SENSE_F +#define AO_ADC_SQ7 AO_ADC_V_BATT +#define AO_ADC_SQ8 AO_ADC_V_PBATT +#define AO_ADC_SQ9 AO_ADC_TEMP + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 0bce68e6a0abc19f49c573331164d13643c9bee5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:31:58 -0700 Subject: altos: Add STM temperature sensor calibration data Each stm32l has two-point factory temperature calibration data. Provide access to that for displaying temperature data. Signed-off-by: Keith Packard --- src/stm/registers.ld | 5 ++++- src/stm/stm32l.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/stm/registers.ld b/src/stm/registers.ld index 51921444..fd61e486 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -44,4 +44,7 @@ stm_tim4 = 0x40000800; stm_tim3 = 0x40000400; stm_tim2 = 0x40000000; -stm_nvic = 0xe000e100; \ No newline at end of file +stm_nvic = 0xe000e100; + +/* calibration data in system memory */ +stm_temp_cal = 0x1ff80078; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b9f45513..338bc471 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1152,4 +1152,16 @@ extern struct stm_adc stm_adc; #define STM_ADC_CCR_ADCPRE_HSI_4 2 #define STM_ADC_CCR_ADCPRE_MASK 3 +struct stm_temp_cal { + uint16_t vref; + uint16_t ts_cal_cold; + uint16_t reserved; + uint16_t ts_cal_hot; +}; + +extern struct stm_temp_cal stm_temp_cal; + +#define stm_temp_cal_cold 25 +#define stm_temp_cal_hot 110 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 98aa481741b8fbc617545beda3d295b53de90716 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:33:27 -0700 Subject: altos: Use 384 cycle ADC sample time This is plenty fast, and provides nice stable readings. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 1722a9ec..d758e629 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -28,11 +28,11 @@ static uint8_t ao_adc_ready; (0 << STM_ADC_CR2_JWSTART) | \ (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \ (0 << STM_ADC_CR2_JEXTSEL) | \ - (1 << STM_ADC_CR2_ALIGN) | \ + (0 << STM_ADC_CR2_ALIGN) | \ (0 << STM_ADC_CR2_EOCS) | \ (1 << STM_ADC_CR2_DDS) | \ (1 << STM_ADC_CR2_DMA) | \ - (STM_ADC_CR2_DELS_NONE << STM_ADC_CR2_DELS) | \ + (STM_ADC_CR2_DELS_UNTIL_READ << STM_ADC_CR2_DELS) | \ (0 << STM_ADC_CR2_CONT) | \ (1 << STM_ADC_CR2_ADON)) @@ -168,10 +168,10 @@ ao_adc_init(void) (0 << STM_ADC_CR1_EOCIE ) | (0 << STM_ADC_CR1_AWDCH )); - /* 4 cycle sample time for everyone */ - stm_adc.smpr1 = 0; - stm_adc.smpr2 = 0; - stm_adc.smpr3 = 0; + /* 384 cycle sample time for everyone */ + stm_adc.smpr1 = 0x3ffff; + stm_adc.smpr2 = 0x3fffffff; + stm_adc.smpr3 = 0x3fffffff; stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); stm_adc.sqr2 = 0; -- cgit v1.2.3 From f7cfbbce2b94b5ac0094a0e34e1766fe1ceb12c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:35:17 -0700 Subject: altos: Show temperature in stm-demo Use the ADC to show current temperature Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 19 +++++++++++++++++++ src/stm-demo/ao_pins.h | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 63647aac..ea4dadfa 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -111,10 +111,29 @@ ao_spi_read(void) { } } + + +static void +ao_temp (void) +{ + struct ao_adc adc; + int temp; + + ao_adc_get(&adc); + + /* + * r = (110 - 25) / (ts_cal_hot - ts_cal_cold) + * 25 + (110 - 25) * (temp - ts_cal_cold) / (ts_cal_hot - ts_cal_cold) + */ + temp = 25 + (110 - 25) * (adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); + printf ("temp: %d\n", temp); +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, + { ao_temp, "t\0Show temp" }, { 0, NULL } }; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index fecd8cda..42f4123d 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -119,6 +119,7 @@ struct ao_adc { uint16_t tick; int16_t idd; int16_t temp; + int16_t vref; }; #define AO_ADC_IDD 4 @@ -127,13 +128,15 @@ struct ao_adc { #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) #define AO_ADC_TEMP 16 +#define AO_ADC_VREF 17 #define HAS_ADC_TEMP 1 -#define AO_NUM_ADC 2 +#define AO_NUM_ADC 3 #define AO_ADC_SQ1 AO_ADC_IDD #define AO_ADC_SQ2 AO_ADC_TEMP +#define AO_ADC_SQ3 AO_ADC_VREF #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 059f09dbca4703c25b42389b54c6510331c39485 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:05:18 -0700 Subject: altos: Allow STM DMA channels to be reserved for one use This allows a single user of a DMA channel to reserve it for use without needing to lock the mutex; this is required for DMA from the ADC to work on megametrum as it wants to start DMA from an interrupt handler, which cannot block on a mutex. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 2 ++ src/stm/ao_arch_funcs.h | 3 +++ src/stm/ao_dma_stm.c | 23 +++++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index d758e629..729551c4 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -221,5 +221,7 @@ ao_adc_init(void) /* Clear any stale status bits */ stm_adc.sr = 0; ao_adc_ready = 1; + + ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_cmd_register(&ao_adc_cmds[0]); } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index a42fe10f..7dc576d1 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -61,6 +61,9 @@ ao_dma_done_transfer(uint8_t index); void ao_dma_abort(uint8_t index); +void +ao_dma_alloc(uint8_t index); + void ao_dma_init(void); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 785235a8..21390748 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -26,6 +26,7 @@ struct ao_dma_config { uint8_t ao_dma_done[NUM_DMA]; static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_allocated[NUM_DMA]; static uint8_t ao_dma_mutex[NUM_DMA]; static uint8_t ao_dma_active; @@ -60,7 +61,12 @@ ao_dma_set_transfer(uint8_t index, uint16_t count, uint32_t ccr) { - ao_mutex_get(&ao_dma_mutex[index]); + if (ao_dma_allocated[index]) { + if (ao_dma_mutex[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_mutex[index] = 1; + } else + ao_mutex_get(&ao_dma_mutex[index]); ao_arch_critical( if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); @@ -93,7 +99,10 @@ ao_dma_done_transfer(uint8_t index) if (--ao_dma_active == 0) stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ); - ao_mutex_put(&ao_dma_mutex[index]); + if (ao_dma_allocated[index]) + ao_dma_mutex[index] = 0; + else + ao_mutex_put(&ao_dma_mutex[index]); } void @@ -102,6 +111,14 @@ ao_dma_abort(uint8_t index) stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); } +void +ao_dma_alloc(uint8_t index) +{ + if (ao_dma_allocated[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_allocated[index] = 1; +} + void ao_dma_init(void) { @@ -110,6 +127,8 @@ ao_dma_init(void) for (index = 0; index < STM_NUM_DMA; index++) { stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + ao_dma_allocated[index] = 0; + ao_dma_mutex[index] = 0; } } -- cgit v1.2.3 From e027247a9ef82746c26bcb8d0a851a0fa06511de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:06:35 -0700 Subject: altos: Slow STM SPI down a bit so the MS5607 returns values It's still not working right, but at least it returns something other than all zeros... Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index ecf7934f..d3e1ca4b 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -167,9 +167,9 @@ ao_spi_get(uint8_t spi_index) (0 << STM_SPI_CR1_RXONLY) | (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ (1 << STM_SPI_CR1_SSI) | /* ... */ - (0 << STM_SPI_CR1_LSBFIRST) | /* Little endian */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From e9362841b1075a2ae59eecc73137b20e700567a8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:08:20 -0700 Subject: altos: add STM I2C driver. Not well tested yet... Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 20 +++++ src/stm/ao_i2c_stm.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 76 ++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 src/stm/ao_i2c_stm.c diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 7dc576d1..052abb65 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -67,4 +67,24 @@ ao_dma_alloc(uint8_t index); void ao_dma_init(void); +/* ao_i2c_stm.c */ + +void +ao_i2c_get(uint8_t i2c_index); + +uint8_t +ao_i2c_start(uint8_t i2c_index, uint16_t address); + +void +ao_i2c_put(uint8_t i2c_index); + +void +ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index); + +void +ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index); + +void +ao_i2c_init(void); + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c new file mode 100644 index 00000000..1a0280d3 --- /dev/null +++ b/src/stm/ao_i2c_stm.c @@ -0,0 +1,230 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +struct ao_i2c_stm_info { + uint8_t tx_dma_index; + uint8_t rx_dma_index; + struct stm_i2c *stm_i2c; +}; + +#define I2C_IDLE 0 +#define I2C_RUNNING 1 +#define I2C_ERROR 2 + +static uint8_t ao_i2c_state[STM_NUM_I2C]; +static uint16_t ao_i2c_addr[STM_NUM_I2C]; +uint8_t ao_i2c_mutex[STM_NUM_I2C]; + +#define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) | \ + (0 << STM_I2C_CR1_ALERT) | \ + (0 << STM_I2C_CR1_PEC) | \ + (0 << STM_I2C_CR1_POS) | \ + (0 << STM_I2C_CR1_ACK) | \ + (0 << STM_I2C_CR1_STOP) | \ + (0 << STM_I2C_CR1_START) | \ + (0 << STM_I2C_CR1_NOSTRETCH) | \ + (0 << STM_I2C_CR1_ENGC) | \ + (0 << STM_I2C_CR1_ENPEC) | \ + (0 << STM_I2C_CR1_ENARP) | \ + (0 << STM_I2C_CR1_SMBTYPE) | \ + (0 << STM_I2C_CR1_SMBUS) | \ + (1 << STM_I2C_CR1_PE)) + +#define AO_STM_I2C_CR2 ((0 << STM_I2C_CR2_LAST) | \ + (1 << STM_I2C_CR2_DMAEN) | \ + (0 << STM_I2C_CR2_ITBUFEN) | \ + (0 << STM_I2C_CR2_ITEVTEN) | \ + (0 << STM_I2C_CR2_ITERREN) | \ + (STM_I2C_CR2_FREQ_16_MHZ << STM_I2C_CR2_FREQ)) + +static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { + { + .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_TX), + .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_RX), + .stm_i2c = &stm_i2c1 + }, + { + .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_TX), + .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_RX), + .stm_i2c = &stm_i2c2 + }, +}; + +static void +ao_i2c_ev_isr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1; + + sr1 = stm_i2c->sr1; + if (sr1 & (1 << STM_I2C_SR1_SB)) + stm_i2c->dr = ao_i2c_addr[index]; + if (sr1 & (1 << STM_I2C_SR1_ADDR)) { + (void) stm_i2c->sr2; + ao_i2c_state[index] = I2C_RUNNING; + ao_wakeup(&ao_i2c_state[index]); + } +} + +void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } +void stm_i2c2_ev_isr(void) { ao_i2c_ev_isr(1); } + +static void +ao_i2c_er_isr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1; + + sr1 = stm_i2c->sr1; + if (sr1 & (1 << STM_I2C_SR1_AF)) { + ao_i2c_state[index] = I2C_ERROR; + stm_i2c->sr1 = sr1 & ~(1 << STM_I2C_SR1_AF); + ao_wakeup(&ao_i2c_state[index]); + } +} + +void stm_i2c1_er_isr(void) { ao_i2c_er_isr(0); } +void stm_i2c2_er_isr(void) { ao_i2c_er_isr(1); } + +void +ao_i2c_get(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + ao_mutex_get(&ao_i2c_mutex[index]); + + stm_i2c->sr1 = 0; + stm_i2c->sr2 = 0; +} + +void +ao_i2c_put(uint8_t index) +{ + ao_mutex_put(&ao_i2c_mutex[index]); +} + +uint8_t +ao_i2c_start(uint8_t index, uint16_t addr) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + ao_i2c_state[index] = I2C_IDLE; + ao_i2c_addr[index] = addr; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); + ao_arch_critical( + while (ao_i2c_state[index] == I2C_IDLE) + ao_sleep(&ao_i2c_state[index]); + ); + return ao_i2c_state[index] == I2C_RUNNING; +} + +void +ao_i2c_send(void *block, uint16_t len, uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + + ao_dma_set_transfer(tx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + ao_dma_start(tx_dma_index); + ao_arch_critical( + while (!ao_dma_done[tx_dma_index]) + ao_sleep(&ao_dma_done[tx_dma_index]); + ); + ao_dma_done_transfer(tx_dma_index); +} + +void +ao_i2c_channel_init(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + /* Turn I2C off while configuring */ + stm_i2c->cr1 = 0; + stm_i2c->cr2 = AO_STM_I2C_CR2; + + (void) stm_i2c->sr1; + (void) stm_i2c->sr2; + (void) stm_i2c->dr; + + stm_i2c->sr1 = 0; + stm_i2c->sr2 = 0; + + stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) | + (0 << STM_I2C_CCR_DUTY) | + (20 << STM_I2C_CCR_CCR)); + + stm_i2c->cr1 = AO_STM_I2C_CR1; +} + +void +ao_i2c_init(void) +{ + /* All of the I2C configurations are on port B */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +#if HAS_I2C_1 +# if I2C_1_PB6_PB7 + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF4); +# else +# if I2C_1_PB8_PB9 + stm_afr_set(&stm_gpiob, 8, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 9, STM_AFR_AF4); +# else +# error "No I2C_1 port configuration specified" +# endif +# endif + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C1EN); + ao_i2c_channel_init(0); + + stm_nvic_set_enable(STM_ISR_I2C1_EV_POS); + stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, 3); + stm_nvic_set_enable(STM_ISR_I2C1_ER_POS); + stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, 3); +#endif + +#if HAS_I2C_2 +# if I2C_2_PB10_PB11 + stm_afr_set(&stm_gpiob, 10, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 11, STM_AFR_AF4); +# else +# error "No I2C_2 port configuration specified" +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C2EN); + ao_i2c_channel_init(1); + + stm_nvic_set_enable(STM_ISR_I2C2_EV_POS); + stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, 3); + stm_nvic_set_enable(STM_ISR_I2C2_ER_POS); + stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); +#endif +} + diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 338bc471..54d95c9a 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1164,4 +1164,80 @@ extern struct stm_temp_cal stm_temp_cal; #define stm_temp_cal_cold 25 #define stm_temp_cal_hot 110 +#define STM_NUM_I2C 2 + +#define STM_I2C_INDEX(channel) ((channel) - 1) + +struct stm_i2c { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t oar1; + vuint32_t oar2; + vuint32_t dr; + vuint32_t sr1; + vuint32_t sr2; + vuint32_t ccr; + vuint32_t trise; +}; + +extern struct stm_i2c stm_i2c1, stm_i2c2; + +#define STM_I2C_CR1_SWRST 15 +#define STM_I2C_CR1_ALERT 13 +#define STM_I2C_CR1_PEC 12 +#define STM_I2C_CR1_POS 11 +#define STM_I2C_CR1_ACK 10 +#define STM_I2C_CR1_STOP 9 +#define STM_I2C_CR1_START 8 +#define STM_I2C_CR1_NOSTRETCH 7 +#define STM_I2C_CR1_ENGC 6 +#define STM_I2C_CR1_ENPEC 5 +#define STM_I2C_CR1_ENARP 4 +#define STM_I2C_CR1_SMBTYPE 3 +#define STM_I2C_CR1_SMBUS 1 +#define STM_I2C_CR1_PE 0 + +#define STM_I2C_CR2_LAST 12 +#define STM_I2C_CR2_DMAEN 11 +#define STM_I2C_CR2_ITBUFEN 10 +#define STM_I2C_CR2_ITEVTEN 9 +#define STM_I2C_CR2_ITERREN 8 +#define STM_I2C_CR2_FREQ 0 +#define STM_I2C_CR2_FREQ_2_MHZ 2 +#define STM_I2C_CR2_FREQ_4_MHZ 4 +#define STM_I2C_CR2_FREQ_8_MHZ 8 +#define STM_I2C_CR2_FREQ_16_MHZ 16 +#define STM_I2C_CR2_FREQ_32_MHZ 32 +#define STM_I2C_CR2_FREQ_MASK 0x3f; + +#define STM_I2C_SR1_SMBALERT 15 +#define STM_I2C_SR1_TIMEOUT 14 +#define STM_I2C_SR1_PECERR 12 +#define STM_I2C_SR1_OVR 11 +#define STM_I2C_SR1_AF 10 +#define STM_I2C_SR1_ARLO 9 +#define STM_I2C_SR1_BERR 8 +#define STM_I2C_SR1_TXE 7 +#define STM_I2C_SR1_RXNE 6 +#define STM_I2C_SR1_STOPF 4 +#define STM_I2C_SR1_ADD10 3 +#define STM_I2C_SR1_BTF 2 +#define STM_I2C_SR1_ADDR 1 +#define STM_I2C_SR1_SB 0 + +#define STM_I2C_SR2_PEC 8 +#define STM_I2C_SR2_PEC_MASK 0xff00 +#define STM_I2C_SR2_DUALF 7 +#define STM_I2C_SR2_SMBHOST 6 +#define STM_I2C_SR2_SMBDEFAULT 5 +#define STM_I2C_SR2_GENCALL 4 +#define STM_I2C_SR2_TRA 2 +#define STM_I2C_SR2_BUSY 1 +#define STM_I2C_SR2_MSL 0 + +#define STM_I2C_CCR_FS 15 +#define STM_I2C_CCR_DUTY 14 +#define STM_I2C_CCR_CCR 0 +#define STM_I2C_CCR_MASK 0x7ff + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 597c3df668ccf656d8c014f665c154a03166577c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:09:18 -0700 Subject: altos: Make ms5607 driver do something It's loading prom values and converting sensor data, but it's getting the wrong answer at present. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 970fea1e..51922dc7 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -55,6 +55,7 @@ ao_ms5607_reset(void) { cmd = AO_MS5607_RESET; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_delay(AO_MS_TO_TICKS(100)); ao_ms5607_stop(); } @@ -63,12 +64,15 @@ ao_ms5607_prom_read(uint8_t addr) { uint8_t cmd = AO_MS5607_PROM_READ(addr); uint8_t d[2]; + uint16_t v; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; + v = ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +// printf ("ms5607_prom_read recv %02x %02x -> %04x\n", d[0], d[1], v); + return v; } static void @@ -80,6 +84,14 @@ ao_ms5607_init_chip(void) { for (addr = 0; addr <= 7; addr++) prom[addr] = ao_ms5607_prom_read(addr); + printf ("reserved: %d\n", ms5607_prom.reserved); + printf ("sens: %d\n", ms5607_prom.sens); + printf ("off: %d\n", ms5607_prom.off); + printf ("tcs: %d\n", ms5607_prom.tcs); + printf ("tco: %d\n", ms5607_prom.tco); + printf ("tref: %d\n", ms5607_prom.tref); + printf ("tempsens: %d\n", ms5607_prom.tempsens); + printf ("crc: %d\n", ms5607_prom.crc); } static uint32_t @@ -91,7 +103,7 @@ ao_ms5607_convert(uint8_t cmd) { ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(10)); ao_ms5607_start(); read = AO_MS5607_ADC_READ; @@ -106,28 +118,19 @@ static void ao_ms5607_dump(void) { uint8_t addr; - uint32_t d1, d2; + uint32_t D1, D2; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; int32_t P; - ao_ms5607_init_chip(); - printf ("reserved: %d\n", ms5607_prom.reserved); - printf ("sens: %d\n", ms5607_prom.sens); - printf ("off: %d\n", ms5607_prom.off); - printf ("tcs: %d\n", ms5607_prom.tcs); - printf ("tco: %d\n", ms5607_prom.tco); - printf ("tref: %d\n", ms5607_prom.tref); - printf ("tempsens: %d\n", ms5607_prom.tempsens); - printf ("crc: %d\n", ms5607_prom.crc); - d1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); - printf ("Conversion D1: %d\n", d1); - d2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); - printf ("Conversion D2: %d\n", d2); + D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); + printf ("Conversion D2: %d\n", D2); + D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); + printf ("Conversion D1: %d\n", D1); - dT = d2 - ((int32_t) ms5607_prom.tref << 8); + dT = D2 - ((int32_t) ms5607_prom.tref << 8); TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); @@ -142,13 +145,14 @@ ao_ms5607_dump(void) int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; } - P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; + P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - printf ("Temperature: %d", TEMP); + printf ("Temperature: %d\n", TEMP); printf ("Pressure %d\n", P); } __code struct ao_cmds ao_ms5607_cmds[] = { + { ao_ms5607_init_chip, "i\0Init MS5607" }, { ao_ms5607_dump, "p\0Display MS5607 data" }, { 0, NULL }, }; -- cgit v1.2.3 From 0a198dfcd1b0defe194feaf301f4586e5573d6e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:10:01 -0700 Subject: altos: ARM -O0 flag appears to generate buggy code Use -Os always, which is annoying... Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 71f4adf7..297d136a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -8,6 +8,7 @@ include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ + ao_arch_funcs.h \ ao_pins.h \ altitude.h \ ao_kalman.h \ @@ -41,7 +42,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1-$(VERSION).elf -- cgit v1.2.3 From 67044cca5b463772491d0712d0ce07a8f897a476 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:10:43 -0700 Subject: altos: Test I2C code on discovery board. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 4 +++- src/stm-demo/ao_demo.c | 21 +++++++++++++++++++++ src/stm-demo/ao_pins.h | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 26c81a82..2f156ea4 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -8,6 +8,7 @@ include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ + ao_arch_funcs.h \ ao_pins.h \ ao_product.h @@ -30,7 +31,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_dma_stm.c \ ao_spi_stm.c \ - ao_adc_stm.c + ao_adc_stm.c \ + ao_i2c_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index ea4dadfa..879f7f75 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -111,7 +111,26 @@ ao_spi_read(void) { } } +static void +ao_i2c_write(void) { + unsigned char data[] = { 0x55, 0xaa, 0xff, 0x00 }; + int i; + for (i = 0; i < 10; i++) { + ao_i2c_get(0); + if (ao_i2c_start(0, 0x55)) + ao_i2c_send(data, 4, 0); + else { + printf ("i2c start failed\n"); + ao_i2c_put(0); + break; + } + ao_i2c_put(0); + printf("."); + flush(); + ao_delay(100); + } +} static void ao_temp (void) @@ -133,6 +152,7 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, + { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, { 0, NULL } }; @@ -149,6 +169,7 @@ main(void) // ao_lcd_stm_init(); // ao_lcd_font_init(); ao_spi_init(); + ao_i2c_init(); ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 42f4123d..9fd1175d 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -138,5 +138,11 @@ struct ao_adc { #define AO_ADC_SQ2 AO_ADC_TEMP #define AO_ADC_SQ3 AO_ADC_VREF +#define HAS_I2C_1 1 +#define I2C_1_PB6_PB7 0 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 1dcfbb05531767e67df45c2799a2fe533834fb71 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 20:28:19 -0700 Subject: altos: Add beeper driver to STM arch Drives the MegaMetrum beeper Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 6 +- src/megametrum-v0.1/ao_megametrum.c | 13 +++ src/stm/ao_beep_stm.c | 130 ++++++++++++++++++++++ src/stm/stm32l.h | 215 ++++++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 src/stm/ao_beep_stm.c diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 297d136a..5b20a8a5 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -12,7 +12,8 @@ INC = \ ao_pins.h \ altitude.h \ ao_kalman.h \ - ao_product.h + ao_product.h \ + ao_ms5607.h # # Common AltOS sources @@ -36,7 +37,8 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_ms5607.c \ - ao_adc_stm.c + ao_adc_stm.c \ + ao_beep_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 02fe91fe..4d9343e1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -17,6 +17,17 @@ #include "ao.h" +void +beep(void) +{ + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(2000)); +} + +const struct ao_cmds ao_mm_cmds[] = { + { beep, "b\0Beep" }, + { 0, NULL }, +}; + int main(void) { @@ -32,8 +43,10 @@ main(void) ao_dma_init(); ao_spi_init(); ao_ms5607_init(); + ao_beep_init(); ao_adc_init(); + ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); return 0; } diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c new file mode 100644 index 00000000..8c0c0ee3 --- /dev/null +++ b/src/stm/ao_beep_stm.c @@ -0,0 +1,130 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + stm_tim3.cr1 = 0; + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN); + } else { + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN); + + stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (0 << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (0 << STM_TIM234_CR1_CEN)); + + stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_RESET << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + /* Set prescaler to match cc1111 clocks + */ + stm_tim3.psc = STM_APB1 / 750000; + + /* 1. Select the counter clock (internal, external, prescaler). + * + * Setting SMCR to zero means use the internal clock + */ + + stm_tim3.smcr = 0; + + /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */ + stm_tim3.arr = beep; + stm_tim3.ccr1 = beep; + + /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a + * DMA request is to be generated. + */ + /* don't want this */ + + /* 4. Select the output mode. For example, you must write + * OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output + * pin when CNT matches CCRx, CCRx preload is not used, OCx + * is enabled and active high. + */ + + stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | + (STM_TIM234_CCMR1_OC2M_FROZEN << STM_TIM234_CCMR1_OC2M) | + (0 << STM_TIM234_CCMR1_OC2PE) | + (0 << STM_TIM234_CCMR1_OC2FE) | + (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) | + + (0 << STM_TIM234_CCMR1_OC1CE) | + (STM_TIM234_CCMR1_OC1M_TOGGLE << STM_TIM234_CCMR1_OC1M) | + (0 << STM_TIM234_CCMR1_OC1PE) | + (0 << STM_TIM234_CCMR1_OC1FE) | + (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); + + + stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) | + (0 << STM_TIM234_CCER_CC4P) | + (0 << STM_TIM234_CCER_CC4E) | + (0 << STM_TIM234_CCER_CC3NP) | + (0 << STM_TIM234_CCER_CC3P) | + (0 << STM_TIM234_CCER_CC3E) | + (0 << STM_TIM234_CCER_CC2NP) | + (0 << STM_TIM234_CCER_CC2P) | + (0 << STM_TIM234_CCER_CC2E) | + (0 << STM_TIM234_CCER_CC1NP) | + (0 << STM_TIM234_CCER_CC1P) | + (1 << STM_TIM234_CCER_CC1E)); + + + /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ + + stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (0 << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on PC6, which is hooked to TIM3_CH1, + * which is on PC6 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + + stm_afr_set(&stm_gpioc, 6, STM_AFR_AF2); + + /* Leave the timer off until requested */ + + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN); +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 54d95c9a..39dd710d 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1240,4 +1240,219 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CCR_CCR 0 #define STM_I2C_CCR_MASK 0x7ff +struct stm_tim234 { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smcr; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + vuint32_t ccmr2; + + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + + uint32_t reserved_30; + vuint32_t ccr1; + vuint32_t ccr2; + vuint32_t ccr3; + + vuint32_t ccr4; + uint32_t reserved_44; + vuint32_t dcr; + vuint32_t dmar; + + uint32_t reserved_50; +}; + +extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; + +#define STM_TIM234_CR1_CKD 8 +#define STM_TIM234_CR1_CKD_1 0 +#define STM_TIM234_CR1_CKD_2 1 +#define STM_TIM234_CR1_CKD_4 2 +#define STM_TIM234_CR1_CKD_MASK 3 +#define STM_TIM234_CR1_ARPE 7 +#define STM_TIM234_CR1_CMS 5 +#define STM_TIM234_CR1_CMS_EDGE 0 +#define STM_TIM234_CR1_CMS_CENTER_1 1 +#define STM_TIM234_CR1_CMS_CENTER_2 2 +#define STM_TIM234_CR1_CMS_CENTER_3 3 +#define STM_TIM234_CR1_CMS_MASK 3 +#define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_OPM 3 +#define STM_TIM234_CR1_URS 2 +#define STM_TIM234_CR1_UDIS 1 +#define STM_TIM234_CR1_CEN 0 + +#define STM_TIM234_CR2_TI1S 7 +#define STM_TIM234_CR2_MMS 4 +#define STM_TIM234_CR2_MMS_RESET 0 +#define STM_TIM234_CR2_MMS_ENABLE 1 +#define STM_TIM234_CR2_MMS_UPDATE 2 +#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3 +#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4 +#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5 +#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6 +#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7 +#define STM_TIM234_CR2_MMS_MASK 7 +#define STM_TIM234_CR2_CCDS 3 + +#define STM_TIM234_SMCR_ETP 15 +#define STM_TIM234_SMCR_ECE 14 +#define STM_TIM234_SMCR_ETPS 12 +#define STM_TIM234_SMCR_ETPS_OFF 0 +#define STM_TIM234_SMCR_ETPS_DIV_2 1 +#define STM_TIM234_SMCR_ETPS_DIV_4 2 +#define STM_TIM234_SMCR_ETPS_DIV_8 3 +#define STM_TIM234_SMCR_ETPS_MASK 3 +#define STM_TIM234_SMCR_ETF 8 +#define STM_TIM234_SMCR_ETF_NONE 0 +#define STM_TIM234_SMCR_ETF_INT_N_2 1 +#define STM_TIM234_SMCR_ETF_INT_N_4 2 +#define STM_TIM234_SMCR_ETF_INT_N_8 3 +#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4 +#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5 +#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6 +#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7 +#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8 +#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9 +#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10 +#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11 +#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12 +#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13 +#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14 +#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15 +#define STM_TIM234_SMCR_ETF_MASK 15 +#define STM_TIM234_SMCR_MSM 7 +#define STM_TIM234_SMCR_TS 4 +#define STM_TIM234_SMCR_TS_TR0 0 +#define STM_TIM234_SMCR_TS_TR1 1 +#define STM_TIM234_SMCR_TS_TR2 2 +#define STM_TIM234_SMCR_TS_TR3 3 +#define STM_TIM234_SMCR_TS_TI1F_ED 4 +#define STM_TIM234_SMCR_TS_TI1FP1 5 +#define STM_TIM234_SMCR_TS_TI2FP2 6 +#define STM_TIM234_SMCR_TS_ETRF 7 +#define STM_TIM234_SMCR_TS_MASK 7 +#define STM_TIM234_SMCR_OCCS 3 +#define STM_TIM234_SMCR_SMS 0 +#define STM_TIM234_SMCR_SMS_DISABLE 0 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3 +#define STM_TIM234_SMCR_SMS_RESET_MODE 4 +#define STM_TIM234_SMCR_SMS_GATED_MODE 5 +#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6 +#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 +#define STM_TIM234_SMCR_SMS_MASK 7 + +#define STM_TIM234_SR_CC4OF 12 +#define STM_TIM234_SR_CC3OF 11 +#define STM_TIM234_SR_CC2OF 10 +#define STM_TIM234_SR_CC1OF 9 +#define STM_TIM234_SR_TIF 6 +#define STM_TIM234_SR_CC4IF 4 +#define STM_TIM234_SR_CC3IF 3 +#define STM_TIM234_SR_CC2IF 2 +#define STM_TIM234_SR_CC1IF 1 +#define STM_TIM234_SR_UIF 0 + +#define STM_TIM234_CCMR1_OC2CE 15 +#define STM_TIM234_CCMR1_OC2M 12 +#define STM_TIM234_CCMR1_OC2M_FROZEN 0 +#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC2M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC2M_MASK 7 +#define STM_TIM234_CCMR1_OC2PE 11 +#define STM_TIM234_CCMR1_OC2FE 10 +#define STM_TIM234_CCMR1_CC2S 8 +#define STM_TIM234_CCMR1_CC2S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2 +#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC2S_MASK 3 + +#define STM_TIM234_CCMR1_OC1CE 7 +#define STM_TIM234_CCMR1_OC1M 4 +#define STM_TIM234_CCMR1_OC1M_FROZEN 0 +#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC1M_MASK 7 +#define STM_TIM234_CCMR1_OC1PE 11 +#define STM_TIM234_CCMR1_OC1FE 2 +#define STM_TIM234_CCMR1_CC1S 0 +#define STM_TIM234_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC1S_MASK 3 + +#define STM_TIM234_CCMR2_OC2CE 15 +#define STM_TIM234_CCMR2_OC4M 12 +#define STM_TIM234_CCMR2_OC4M_FROZEN 0 +#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC4M_MASK 7 +#define STM_TIM234_CCMR2_OC4PE 11 +#define STM_TIM234_CCMR2_OC4FE 10 +#define STM_TIM234_CCMR2_CC4S 8 +#define STM_TIM234_CCMR2_CC4S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2 +#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC4S_MASK 3 + +#define STM_TIM234_CCMR2_OC3CE 7 +#define STM_TIM234_CCMR2_OC3M 4 +#define STM_TIM234_CCMR2_OC3M_FROZEN 0 +#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC3M_MASK 7 +#define STM_TIM234_CCMR2_OC3PE 11 +#define STM_TIM234_CCMR2_OC3FE 2 +#define STM_TIM234_CCMR2_CC3S 0 +#define STM_TIM234_CCMR2_CC3S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2 +#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC3S_MASK 3 + +#define STM_TIM234_CCER_CC4NP 15 +#define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4E 12 +#define STM_TIM234_CCER_CC3NP 11 +#define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3E 8 +#define STM_TIM234_CCER_CC2NP 7 +#define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2E 4 +#define STM_TIM234_CCER_CC1NP 3 +#define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1E 0 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 51aef5d4fc29986353ad887f4a67ed2fe35f8c8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:17:33 -0700 Subject: altos: Make STM clock configuration per-product. Fix 32MHz CPU speed This moves all of the STM clock configuration into ao_pins.h so that each product can configure it separately. While doing this, I discovered that the flash memory mode (64-bit, prefetch, latency 1) wasn't actually getting set, which is why the CPU refused to work at 32MHz. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 23 ++++++++++++++ src/stm-demo/ao_pins.h | 17 ++++++++++ src/stm/ao_arch.h | 25 ++++++++++++++- src/stm/ao_beep_stm.c | 2 +- src/stm/ao_serial_stm.c | 8 ++--- src/stm/ao_timer.c | 73 ++++++++++++++++++++++++------------------- src/stm/stm32l.h | 3 ++ 7 files changed, 113 insertions(+), 38 deletions(-) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 803678b2..f5789cf9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -18,6 +18,29 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work*/ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 #define SERIAL_1_PB6_PB7 0 diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 9fd1175d..3192c2b7 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -18,6 +18,23 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +/* No external crystal */ +#define AO_HSE 0 + +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define AO_PLLMUL 6 +#define AO_PLLDIV 4 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6) +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) + #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 #define SERIAL_1_PB6_PB7 1 diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index ce3a22e2..dd9579f1 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -148,7 +148,30 @@ extern const uint16_t ao_serial_number; /* * For now, we're running at a weird frequency */ -#define STM_APB1 (16000000 * 6 / 4) + +#if AO_HSE +#define AO_PLLSRC AO_HSE +#else +#define AO_PLLSRC STM_HSI_FREQ +#endif + +#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL) +#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV) +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) +#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) +#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) + +#if AO_APB1_PRESCALER == 1 +#define AO_TIM23467_CLK AO_PCLK1 +#else +#define AO_TIM23467_CLK (2 * AO_PCLK1) +#endif + +#if AO_APB2_PRESCALER == 1 +#define AO_TIM91011_CLK AO_PCLK2 +#else +#define AO_TIM91011_CLK (2 * AO_PCLK2) +#endif void ao_lcd_stm_init(void); diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 8c0c0ee3..37c30e25 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -41,7 +41,7 @@ ao_beep(uint8_t beep) /* Set prescaler to match cc1111 clocks */ - stm_tim3.psc = STM_APB1 / 750000; + stm_tim3.psc = AO_TIM23467_CLK / 750000; /* 1. Select the counter clock (internal, external, prescaler). * diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index f8db6883..3cebc094 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -116,16 +116,16 @@ static const struct { uint32_t brr; } ao_usart_speeds[] = { [AO_SERIAL_SPEED_4800] = { - STM_APB1 / 4800 + AO_PCLK1 / 4800 }, [AO_SERIAL_SPEED_9600] = { - STM_APB1 / 9600 + AO_PCLK1 / 9600 }, [AO_SERIAL_SPEED_19200] = { - STM_APB1 / 19200 + AO_PCLK1 / 19200 }, [AO_SERIAL_SPEED_57600] = { - STM_APB1 / 57600 + AO_PCLK1 / 57600 }, }; diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 387df184..e7f1ddfe 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -69,7 +69,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif -#define TIMER_10kHz (STM_APB1 / 10000) +#define TIMER_10kHz (AO_PCLK1 / 10000) void ao_timer_init(void) @@ -107,44 +107,41 @@ ao_clock_init(void) uint32_t cr; /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = stm_flash.acr; /* Enable 64-bit access and prefetch */ - acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - stm_flash.acr = acr; + stm_flash.acr |= (1 << STM_FLASH_ACR_ACC64); + stm_flash.acr |= (1 << STM_FLASH_ACR_PRFEN); /* Enable 1 wait state so the CPU can run at 32MHz */ /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ - acr |= (1 << STM_FLASH_ACR_LATENCY); - stm_flash.acr = acr; + stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY); + /* HCLK to 16MHz -> AHB prescaler = /1 */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE); stm_rcc.cfgr = cfgr; while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE)) asm ("nop"); -#define STM_AHB_PRESCALER 1 - /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + /* APB1 Prescaler = AO_APB1_PRESCALER */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + cfgr |= (AO_RCC_CFGR_PPRE1_DIV << STM_RCC_CFGR_PPRE1); stm_rcc.cfgr = cfgr; -#define STM_APB1_PRESCALER 1 - /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + /* APB2 Prescaler = AO_APB2_PRESCALER */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + cfgr |= (AO_RCC_CFGR_PPRE2_DIV << STM_RCC_CFGR_PPRE2); stm_rcc.cfgr = cfgr; -#define STM_APB2_PRESCALER 1 /* Enable power interface clock */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + /* Set voltage range to 1.8V */ /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ @@ -161,23 +158,42 @@ ao_clock_init(void) while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) asm("nop"); +#if AO_HSE + /* Enable HSE clock */ + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) + asm("nop"); + } +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) +#define STM_PLLSRC AO_HSE +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) +#else +#define STM_HSI 16000000 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) +#define STM_PLLSRC STM_HSI +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) +#endif + +#if !AO_HSE || HAS_ADC /* Enable HSI RC clock 16MHz */ if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { stm_rcc.cr |= (1 << STM_RCC_CR_HSION); while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) asm("nop"); } -#define STM_HSI 16000000 - - /* Switch to direct HSI for SYSCLK */ +#endif + /* Switch to direct high speed clock for SYSCLK */ if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + STM_RCC_CFGR_SWS_TARGET_CLOCK) { cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + cfgr |= STM_RCC_CFGR_SW_TARGET_CLOCK; stm_rcc.cfgr = cfgr; while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + STM_RCC_CFGR_SWS_TARGET_CLOCK); asm("nop"); } @@ -191,19 +207,12 @@ ao_clock_init(void) cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); -// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); -// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); - - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL); + cfgr |= (AO_RCC_CFGR_PLLDIV << STM_RCC_CFGR_PLLDIV); -#define STM_PLLMUL 6 -#define STM_PLLDIV 4 - - /* PLL source to HSI */ + /* PLL source */ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - -#define STM_PLLSRC STM_HSI + cfgr |= STM_RCC_CFGR_PLLSRC_TARGET_CLOCK; stm_rcc.cfgr = cfgr; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 39dd710d..b922b6bc 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -303,6 +303,9 @@ struct stm_rcc { extern struct stm_rcc stm_rcc; +/* Nominal high speed internal oscillator frequency is 16MHz */ +#define STM_HSI_FREQ 16000000 + #define STM_RCC_CR_RTCPRE (29) #define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 #define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 -- cgit v1.2.3 From c5bbfc7244faaae41c7b581644c3c253e9b7f462 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:21:46 -0700 Subject: altos: Reduce MS5607 reset delay, increase conversion delay Reset doesn't take very long, while doing a conversion seems to take more than 10ms. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 51922dc7..87748272 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -18,11 +18,6 @@ #include #include "ao_ms5607.h" -#define AO_MS5607_CS_GPIO stm_gpioc -#define AO_MS5607_CS 4 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) - struct ms5607_prom { uint16_t reserved; uint16_t sens; @@ -55,7 +50,7 @@ ao_ms5607_reset(void) { cmd = AO_MS5607_RESET; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_delay(AO_MS_TO_TICKS(100)); + ao_delay(AO_MS_TO_TICKS(10)); ao_ms5607_stop(); } @@ -70,28 +65,27 @@ ao_ms5607_prom_read(uint8_t addr) ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - v = ((uint16_t) d[0] << 8) | (uint16_t) d[1]; -// printf ("ms5607_prom_read recv %02x %02x -> %04x\n", d[0], d[1], v); - return v; + return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; } static void ao_ms5607_init_chip(void) { uint8_t addr; uint16_t *prom; + ao_ms5607_reset(); prom = &ms5607_prom.reserved; for (addr = 0; addr <= 7; addr++) prom[addr] = ao_ms5607_prom_read(addr); - printf ("reserved: %d\n", ms5607_prom.reserved); - printf ("sens: %d\n", ms5607_prom.sens); - printf ("off: %d\n", ms5607_prom.off); - printf ("tcs: %d\n", ms5607_prom.tcs); - printf ("tco: %d\n", ms5607_prom.tco); - printf ("tref: %d\n", ms5607_prom.tref); - printf ("tempsens: %d\n", ms5607_prom.tempsens); - printf ("crc: %d\n", ms5607_prom.crc); + printf ("reserved: 0x%x\n", ms5607_prom.reserved); + printf ("sens: 0x%x\n", ms5607_prom.sens); + printf ("off: 0x%x\n", ms5607_prom.off); + printf ("tcs: 0x%x\n", ms5607_prom.tcs); + printf ("tco: 0x%x\n", ms5607_prom.tco); + printf ("tref: 0x%x\n", ms5607_prom.tref); + printf ("tempsens: 0x%x\n", ms5607_prom.tempsens); + printf ("crc: 0x%x\n", ms5607_prom.crc); } static uint32_t @@ -103,7 +97,7 @@ ao_ms5607_convert(uint8_t cmd) { ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(10)); + ao_delay(AO_MS_TO_TICKS(20)); ao_ms5607_start(); read = AO_MS5607_ADC_READ; -- cgit v1.2.3 From 3909fca0a3f918121888a415f9bf9bca99505366 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:22:58 -0700 Subject: altos: Add missing parens in ao_ms5607.h Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 6c245368..489190a4 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -33,6 +33,6 @@ #define AO_MS5607_CONVERT_D2_4096 0x58 #define AO_MS5607_ADC_READ 0x00 -#define AO_MS5607_PROM_READ(ad) 0xA0 | ((ad) << 1) +#define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) #endif /* _AO_MS5607_H_ */ -- cgit v1.2.3 From 0cd682ef0c8cdcf364b7e173ff3a9f84e485c113 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:23:52 -0700 Subject: altos: Move MS5607 configuration to ao_pins.h Which SPI port and where chip select is to be found are product specific. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f5789cf9..e200a692 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -174,4 +174,12 @@ struct ao_adc { #define AO_ADC_SQ8 AO_ADC_V_PBATT #define AO_ADC_SQ9 AO_ADC_TEMP +/* + * Pressure sensor settings + */ +#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From d15c4976ed9c23c861e620eb9c429d1cb7eedbee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:24:36 -0700 Subject: altos: Increase STM SPI speed to PCLK/4 The pressure sensor seems happy at this speed. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index d3e1ca4b..be24ebcf 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -169,7 +169,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 9804528e249db256e020d4b5340ba6216d3474f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:25:13 -0700 Subject: altos: Check for cc1111 flash overflow The linker is supposed to do this, but it ignores the static initializer data added after the code. Signed-off-by: Keith Packard --- src/util/check-stack | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/util/check-stack b/src/util/check-stack index 3b639d70..7b62e460 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -5,6 +5,8 @@ MEM=$2 HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` +FLASH_END=`awk '/ROM\/EPROM\/FLASH/ { print strtonum ($3)}' $MEM` +echo FLASH_END $FLASH_END if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' @@ -14,6 +16,10 @@ if [ "$XRAM_END" -ge 65024 ]; then echo $XRAM_END | awk '{ printf ("Uses too much XRAM, 0x%x >= 0x%x\n", $1, 65024); }' exit 1 fi +if [ "$FLASH_END" -ge 32768 ]; then + echo $FLASH_END | awk '{ printf ("Uses too much FLASH, 0x%x >= 0x%x\n", $1, 32768); }' + exit 1 +fi exit 0 -- cgit v1.2.3 From 35e3c47da895bdd868b9b66b98bca64bd82db862 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:25:59 -0700 Subject: altos: make megametrum beeper test keep beeping Used to measure the beep frequency. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_megametrum.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 4d9343e1..eaab9b50 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -20,7 +20,11 @@ void beep(void) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(2000)); + ao_beep(AO_BEEP_MID); + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + ao_beep(0); } const struct ao_cmds ao_mm_cmds[] = { -- cgit v1.2.3 From 0dd9e1dd62656a931f9559af6da9131f704f83f9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 23:27:43 -0700 Subject: altos: Add support for multiple SPI busses and sharing device drivers The STM32L151 has several SPI busses, and we want to use more than one, so add a 'bus' parameter to the SPI interfaces. To avoid wasting time on AVR and CC1111 processors which only use one SPI bus, elide those parameters from the actual functions by wrapping them with macros. Configuring chip select is now all macroized so that each chip can have its own version, allowing the STM to share the various SPI device drivers with the cc1111 and avr processors. Note that only the M25 driver has been ported; porting the others is 'trivial', but not necessary at this point. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 35 +++++++++++++++----------- src/avr/ao_pins.h | 3 +++ src/avr/ao_spi_usart.c | 4 +-- src/cc1111/ao_arch_funcs.h | 21 +++++++++++----- src/cc1111/ao_pins.h | 8 +++--- src/cc1111/ao_spi.c | 4 +-- src/drivers/ao_25lc1024.c | 20 +++++++-------- src/drivers/ao_at45db161d.c | 18 +++++++------- src/drivers/ao_companion.c | 10 ++++---- src/drivers/ao_m25.c | 43 ++++++++++++++------------------ src/drivers/ao_ms5607.c | 5 +--- src/megametrum-v0.1/Makefile | 4 ++- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 9 +++++++ src/stm/ao_arch_funcs.h | 49 +++++++++++++++++++++++++++++++++++++ src/teleterra-v0.2/ao_pins.h | 3 +++ 16 files changed, 157 insertions(+), 80 deletions(-) diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index 9ad14fbb..1eeca6cc 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -21,24 +21,24 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ +#define ao_spi_get_mask(reg,mask,bus) do { \ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ } while (0) -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_mask(reg,mask,bus) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ +#define ao_spi_get_bit(bit) do { \ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) /* @@ -48,11 +48,18 @@ extern __xdata uint8_t ao_spi_mutex; */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; + +#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) +#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) void ao_spi_init(void); +#define ao_spi_init_cs(port, mask) do { \ + SPI_CS_PORT |= (mask); \ + SPI_CS_DIR |= (mask); \ + } while (0) diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index bf02db1b..6a63468f 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -85,4 +85,7 @@ #define SPI_SLAVE_PIN_2_5 0 #endif +#define AO_M25_SPI_CS_PORT SPI_CS_PORT +#define AO_M25_SPI_CS_MASK M25_CS_MASK + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 5ea11da6..7c41042a 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -29,7 +29,7 @@ __xdata uint8_t ao_spi_mutex; * so using interrupts would take way too long */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; @@ -46,7 +46,7 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant * Poll, sending zeros and reading data back */ void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 9ad14fbb..d9f5955a 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -21,26 +21,27 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask) do {\ +#define ao_spi_get_mask(reg,mask,bus) do { \ ao_mutex_get(&ao_spi_mutex); \ (reg) &= ~(mask); \ } while (0) -#define ao_spi_put_mask(reg,mask) do { \ +#define ao_spi_put_mask(reg,mask,bus) do { \ (reg) |= (mask); \ ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do {\ +#define ao_spi_get_bit(bit,bus) do { \ ao_mutex_get(&ao_spi_mutex); \ (bit) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ +#define ao_spi_put_bit(bit,bus) do { \ (bit) = 1; \ ao_mutex_put(&ao_spi_mutex); \ } while (0) + /* * The SPI mutex must be held to call either of these * functions -- this mutex covers the entire SPI operation, @@ -48,11 +49,19 @@ extern __xdata uint8_t ao_spi_mutex; */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; + +#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) +#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) void ao_spi_init(void); +#define ao_spi_init_cs(port, mask) do { \ + SPI_CS_PORT |= mask; \ + SPI_CS_DIR |= mask; \ + SPI_CS_SEL &= ~mask; \ + } while (0) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index a18c74c8..5c0cb7df 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -82,7 +82,7 @@ #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define AO_M25_SPI_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 @@ -119,7 +119,7 @@ #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define AO_M25_SPI_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 @@ -358,7 +358,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define AO_M25_SPI_CS_MASK 0x04 /* CS0 is P1_2 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 @@ -458,6 +458,8 @@ #define SPI_CS_DIR P0DIR #endif +#define AO_M25_SPI_CS_PORT SPI_CS_PORT + #ifndef IGNITE_ON_P2 #error Please define IGNITE_ON_P2 #endif diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 1fa8e128..1bf5e155 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -38,7 +38,7 @@ static __xdata uint8_t ao_spi_const; * completion one byte before the transfer is actually complete */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, @@ -76,7 +76,7 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant * clocks the data coming in. */ void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant { ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index 2d047a44..f0fb13c9 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -49,9 +49,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS, AO_EE_SPI_BUS) -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS, AO_EE_SPI_BUS) struct ao_ee_instruction { uint8_t instruction; @@ -63,7 +63,7 @@ ao_ee_write_enable(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WREN; - ao_spi_send(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1, AO_EE_SPI_BUS); ao_ee_cs_high(); } @@ -72,8 +72,8 @@ ao_ee_rdsr(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_RDSR; - ao_spi_send(&ao_ee_instruction, 1); - ao_spi_recv(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1, AO_EE_SPI_BUS); + ao_spi_recv(&ao_ee_instruction, 1, AO_EE_SPI_BUS); ao_ee_cs_high(); return ao_ee_instruction.instruction; } @@ -84,7 +84,7 @@ ao_ee_wrsr(uint8_t status) ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WRSR; ao_ee_instruction.address[0] = status; - ao_spi_send(&ao_ee_instruction, 2); + ao_spi_send(&ao_ee_instruction, 2, AO_EE_SPI_BUS); ao_ee_cs_high(); } @@ -111,8 +111,8 @@ ao_ee_write_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); + ao_spi_send(&ao_ee_instruction, 4, AO_EE_SPI_BUS); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE, AO_EE_SPI_BUS); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -130,8 +130,8 @@ ao_ee_read_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); + ao_spi_send(&ao_ee_instruction, 4, AO_EE_SPI_BUS); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE, AO_EE_SPI_BUS); ao_ee_cs_high(); } diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index 6cd689e5..afe0080b 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,9 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS, AO_FLASH_SPI_BUS) -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS, AO_FLASH_SPI_BUS) struct ao_flash_instruction { uint8_t instruction; @@ -60,7 +60,7 @@ ao_flash_set_pagesize_512(void) ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); ao_flash_cs_high(); } @@ -70,8 +70,8 @@ ao_flash_read_status(void) { ao_flash_cs_low(); ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_spi_send(&ao_flash_instruction, 1); - ao_spi_recv(&ao_flash_instruction, 1); + ao_spi_send(&ao_flash_instruction, 1, AO_FLASH_SPI_BUS); + ao_spi_recv(&ao_flash_instruction, 1, AO_FLASH_SPI_BUS); ao_flash_cs_high(); return ao_flash_instruction.instruction; } @@ -190,8 +190,8 @@ ao_flash_write_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, ao_storage_block); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); + ao_spi_send(ao_flash_data, ao_storage_block, AO_FLASH_SPI_BUS); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -208,8 +208,8 @@ ao_flash_read_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, ao_flash_block_size); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); + ao_spi_recv(ao_flash_data, ao_flash_block_size, AO_FLASH_SPI_BUS); ao_flash_cs_high(); } diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 2e587f8e..fe88e998 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -27,8 +27,8 @@ UxGCR_ORDER_MSB | \ (17 << UxGCR_BAUD_E_SHIFT))) -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS, AO_COMPANION_BUS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS, AO_COMPANION_BUS); } while (0) __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; @@ -45,7 +45,7 @@ ao_companion_send_command(uint8_t command) ao_companion_command.tick = ao_time(); ao_companion_command.serial = ao_serial_number; ao_companion_command.flight = ao_flight_number; - ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command), AO_COMPANION_SPI_BUS); } static uint8_t @@ -53,7 +53,7 @@ ao_companion_get_setup(void) { COMPANION_SELECT(); ao_companion_send_command(AO_COMPANION_SETUP); - ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup), AO_COMPANION_SPI_BUS); COMPANION_DESELECT(); return (ao_companion_setup.board_id == ~ao_companion_setup.board_id_inverse); @@ -65,7 +65,7 @@ ao_companion_get_data(void) COMPANION_SELECT(); ao_companion_send_command(AO_COMPANION_FETCH); ao_mutex_get(&ao_companion_mutex); - ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2, AO_COMPANION_SPI_BUS); ao_mutex_put(&ao_companion_mutex); COMPANION_DESELECT(); } diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 28cb1dd7..c807cd68 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -99,8 +99,8 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) -#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) +#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) +#define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L @@ -116,9 +116,9 @@ ao_m25_wait_wip(uint8_t cs) if (ao_m25_wip & cs) { M25_SELECT(cs); ao_m25_instruction[0] = M25_RDSR; - ao_spi_send(ao_m25_instruction, 1); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); do { - ao_spi_recv(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, 1, AO_M25_SPI_BUS); } while (ao_m25_instruction[0] & M25_STATUS_WIP); M25_DESELECT(cs); ao_m25_wip &= ~cs; @@ -135,7 +135,7 @@ ao_m25_write_enable(uint8_t cs) { M25_SELECT(cs); ao_m25_instruction[0] = M25_WREN; - ao_spi_send(&ao_m25_instruction, 1); + ao_spi_send(&ao_m25_instruction, 1, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_m25_wip |= cs; } @@ -150,8 +150,8 @@ ao_m25_read_capacity(uint8_t cs) uint8_t capacity; M25_SELECT(cs); ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN, AO_M25_SPI_BUS); M25_DESELECT(cs); /* Check to see if the chip is present */ @@ -183,7 +183,7 @@ ao_m25_set_address(uint32_t pos) chip = ao_m25_pin[chip]; #else - chip = M25_CS_MASK; + chip = AO_M25_SPI_CS_MASK; #endif ao_m25_wait_wip(chip); @@ -210,7 +210,7 @@ ao_m25_scan(void) #if M25_MAX_CHIPS > 1 ao_m25_numchips = 0; for (pin = 1; pin != 0; pin <<= 1) { - if (M25_CS_MASK & pin) { + if (AO_M25_SPI_CS_MASK & pin) { size = ao_m25_read_capacity(pin); if (size != 0) { ao_m25_size[ao_m25_numchips] = size; @@ -221,7 +221,7 @@ ao_m25_scan(void) } } #else - ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); + ao_m25_total = ao_m25_read_capacity(AO_M25_SPI_CS_MASK); #endif if (!ao_m25_total) return 0; @@ -253,7 +253,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_m25_instruction[0] = M25_SE; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_m25_wip |= cs; @@ -280,8 +280,8 @@ ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant ao_m25_instruction[0] = M25_PP; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_send(d, len); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); + ao_spi_send(d, len, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_mutex_put(&ao_m25_mutex); @@ -306,8 +306,8 @@ ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant /* No need to use the FAST_READ as we're running at only 8MHz */ ao_m25_instruction[0] = M25_READ; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_recv(d, len); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); + ao_spi_recv(d, len, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_mutex_put(&ao_m25_mutex); @@ -350,14 +350,14 @@ ao_storage_device_info(void) __reentrant printf ("Available chips:\n"); for (cs = 1; cs != 0; cs <<= 1) { - if ((M25_CS_MASK & cs) == 0) + if ((AO_M25_SPI_CS_MASK & cs) == 0) continue; ao_mutex_get(&ao_m25_mutex); M25_SELECT(cs); ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN, AO_M25_SPI_BUS); M25_DESELECT(cs); printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", @@ -373,10 +373,5 @@ ao_storage_device_info(void) __reentrant void ao_storage_device_init(void) { - /* Set up chip select wires */ - SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ - SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ -#ifdef SPI_CS_SEL - SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ -#endif + ao_spi_init_cs (AO_M25_SPI_CS_PORT, AO_M25_SPI_CS_MASK); } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 87748272..3c0a310d 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -155,8 +155,5 @@ void ao_ms5607_init(void) { ao_cmd_register(&ao_ms5607_cmds[0]); - - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); - stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); + ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); } diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5b20a8a5..b0f2a612 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -38,7 +38,9 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_ms5607.c \ ao_adc_stm.c \ - ao_beep_stm.c + ao_beep_stm.c \ + ao_storage.c \ + ao_m25.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index eaab9b50..77a2bf0a 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -49,6 +49,7 @@ main(void) ao_ms5607_init(); ao_beep_init(); ao_adc_init(); + ao_storage_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e200a692..46098d34 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -182,4 +182,13 @@ struct ao_adc { #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT stm_gpiod +#define AO_M25_SPI_CS_MASK (1 << 3) +#define AO_M25_SPI_BUS STM_SPI_INDEX(2) + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 052abb65..309937d5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -37,6 +37,55 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_init(void); +#define ao_spi_get_mask(reg,mask,bus) do { \ + ao_spi_get(bus); \ + (reg).bsrr = ((uint32_t) mask) << 16; \ + } while (0) + +#define ao_spi_put_mask(reg,mask,bus) do { \ + (reg).bsrr = mask; \ + ao_spi_put(bus); \ + } while (0) + +#define ao_stm_enable_port(port) do { \ + if (&(port) == &stm_gpioa) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ + else if (&(port) == &stm_gpiob) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); \ + else if (&(port) == &stm_gpioc) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); \ + else if (&(port) == &stm_gpiod) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); \ + else if (&(port) == &stm_gpioe) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \ + } while (0) + + +#define ao_stm_enable_cs(port,bit) do { \ + stm_gpio_set(&(port), bit, 1); \ + stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_spi_init_cs(port, mask) do { \ + ao_stm_enable_port(port); \ + if (mask & 0x0001) ao_stm_enable_cs(port, 0); \ + if (mask & 0x0002) ao_stm_enable_cs(port, 1); \ + if (mask & 0x0004) ao_stm_enable_cs(port, 2); \ + if (mask & 0x0008) ao_stm_enable_cs(port, 3); \ + if (mask & 0x0010) ao_stm_enable_cs(port, 4); \ + if (mask & 0x0020) ao_stm_enable_cs(port, 5); \ + if (mask & 0x0040) ao_stm_enable_cs(port, 6); \ + if (mask & 0x0080) ao_stm_enable_cs(port, 7); \ + if (mask & 0x0100) ao_stm_enable_cs(port, 8); \ + if (mask & 0x0200) ao_stm_enable_cs(port, 9); \ + if (mask & 0x0400) ao_stm_enable_cs(port, 10); \ + if (mask & 0x0800) ao_stm_enable_cs(port, 11); \ + if (mask & 0x1000) ao_stm_enable_cs(port, 12); \ + if (mask & 0x2000) ao_stm_enable_cs(port, 13); \ + if (mask & 0x4000) ao_stm_enable_cs(port, 14); \ + if (mask & 0x8000) ao_stm_enable_cs(port, 15); \ + } while (0) + /* ao_dma_stm.c */ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 44a372cc..29b97385 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -229,4 +229,7 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +#define AO_M25_SPI_CS_PORT SPI_CS_PORT +#define AO_M25_SPI_CS_MASK M25_CS_MASK + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 150881f86f8d90b5867507889441990d18223e62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:25:36 -0700 Subject: altos: Add register definitions for STM syscfg and usb Signed-off-by: Keith Packard --- src/stm/stm32l.h | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b922b6bc..e884ef04 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -289,7 +289,7 @@ struct stm_rcc { vuint32_t ahbrstr; vuint32_t apb2rstr; - vuint32_t abp1rstr; + vuint32_t apb1rstr; vuint32_t ahbenr; vuint32_t apb2enr; @@ -852,6 +852,25 @@ isr(tim7) #define STM_ISR_TIM6_POS 43 #define STM_ISR_TIM7_POS 44 +struct stm_syscfg { + vuint32_t memrmp; + vuint32_t pmc; + vuint32_t exticr1; + vuint32_t exticr2; + vuint32_t exticr3; + vuint32_t exticr4; +}; + +extern struct stm_syscfg stm_syscfg; + +#define STM_SYSCFG_MEMRMP_MEM_MODE 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MAIN_FLASH 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SYSTEM_FLASH 1 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SRAM 3 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MASK 3 + +#define STM_SYSCFG_PMC_USB_PU 0 + struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; @@ -1458,4 +1477,116 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CCER_CC1P 1 #define STM_TIM234_CCER_CC1E 0 +struct stm_usb { + vuint32_t epr[8]; + uint8_t reserved_20[0x40 - 0x20]; + vuint32_t cntr; + vuint32_t istr; + vuint32_t fnr; + vuint32_t daddr; + vuint32_t btable; +}; + +#define STM_USB_EPR_CTR_RX 15 +#define STM_USB_EPR_CTR_RX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_RX 14 +#define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_RX 12 +#define STM_USB_EPR_STAT_RX_DISABLED 0 +#define STM_USB_EPR_STAT_RX_STALL 1 +#define STM_USB_EPR_STAT_RX_NAK 2 +#define STM_USB_EPR_STAT_RX_VALID 3 +#define STM_USB_EPR_STAT_RX_MASK 3 +#define STM_USB_EPR_STAT_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_SETUP 11 +#define STM_USB_EPR_EP_TYPE 9 +#define STM_USB_EPR_EP_TYPE_BULK 0 +#define STM_USB_EPR_EP_TYPE_CONTROL 1 +#define STM_USB_EPR_EP_TYPE_ISO 2 +#define STM_USB_EPR_EP_TYPE_INTERRUPT 3 +#define STM_USB_EPR_EP_TYPE_MASK 3 +#define STM_USB_EPR_EP_KIND 8 +#define STM_USB_EPR_EP_KIND_DBL_BUF 1 /* Bulk */ +#define STM_USB_EPR_EP_KIND_STATUS_OUT 1 /* Control */ +#define STM_USB_EPR_CTR_TX 7 +#define STM_USB_CTR_TX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_TX 6 +#define STM_USB_EPR_DTOG_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX 4 +#define STM_USB_EPR_STAT_TX_DISABLED 0 +#define STM_USB_EPR_STAT_TX_STALL 1 +#define STM_USB_EPR_STAT_TX_NAK 2 +#define STM_USB_EPR_STAT_TX_VALID 3 +#define STM_USB_EPR_STAT_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX_MASK 3 +#define STM_USB_EPR_EA 0 +#define STM_USB_EPR_EA_MASK 0xf + +#define STM_USB_CNTR_CTRM 15 +#define STM_USB_CNTR_PMAOVRM 14 +#define STM_USB_CNTR_ERRM 13 +#define STM_USB_CNTR_WKUPM 12 +#define STM_USB_CNTR_SUSPM 11 +#define STM_USB_CNTR_RESETM 10 +#define STM_USB_CNTR_SOFM 9 +#define STM_USB_CNTR_ESOFM 8 +#define STM_USB_CNTR_RESUME 4 +#define STM_USB_CNTR_FSUSP 3 +#define STM_USB_CNTR_LP_MODE 2 +#define STM_USB_CNTR_PDWN 1 +#define STM_USB_CNTR_FRES 0 + +#define STM_USB_ISTR_CTR 15 +#define STM_USB_ISTR_PMAOVR 14 +#define STM_USB_ISTR_ERR 13 +#define STM_USB_ISTR_WKUP 12 +#define STM_USB_ISTR_SUSP 11 +#define STM_USB_ISTR_RESET 10 +#define STM_USB_ISTR_SOF 9 +#define STM_USB_ISTR_ESOF 8 +#define STM_USB_ISTR_DIR 4 +#define STM_USB_ISTR_EP_ID 0 +#define STM_USB_ISTR_EP_ID_MASK 0xf + +#define STM_USB_FNR_RXDP 15 +#define STM_USB_FNR_RXDM 14 +#define STM_USB_FNR_LCK 13 +#define STM_USB_FNR_LSOF 11 +#define STM_USB_FNR_LSOF_MASK 0x3 +#define STM_USB_FNR_FN 0 +#define STM_USB_FNR_FN_MASK 0x7ff + +#define STM_USB_DADDR_EF 7 +#define STM_USB_DADDR_ADD 0 +#define STM_USB_DADDR_ADD_MASK 0x7f + +extern struct stm_usb stm_usb; + +union stm_usb_bdt { + struct { + vuint32_t addr_tx; + vuint32_t count_tx; + vuint32_t addr_rx; + vuint32_t count_rx; + } single; + struct { + vuint32_t addr; + vuint32_t count; + } double_tx[2]; + struct { + vuint32_t addr; + vuint32_t count; + } double_rx[2]; +}; + +#define STM_USB_BDT_COUNT_RX_BL_SIZE 15 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK 10 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK_MASK 0x1f +#define STM_USB_BDT_COUNT_RX_COUNT_RX 0 +#define STM_USB_BDT_COUNT_RX_COUNT_RX_MASK 0x1ff + +#define STM_USB_BDT_SIZE 8 + +extern uint8_t stm_usb_sram[]; + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From afd52a8b54fe31577d939a161ea9cf5ad48e3a43 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:26:30 -0700 Subject: altos: Add STM ao_arch_reboot implementation Uses the AIRCR register to force a reset Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index dd9579f1..adb6eb94 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -42,7 +42,9 @@ #define __interrupt(n) #define __at(n) -#define ao_arch_reboot() /* XXX */ +#define CORTEX_M3_AIRCR ((uint32_t *) 0xe000ed0c) + +#define ao_arch_reboot() (*((uint32_t *) 0xe000ed0c) = 0x05fa0004) #define ao_arch_nop() asm("nop") -- cgit v1.2.3 From d432307a3c2709634350eaa1262b935028d073d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:28:45 -0700 Subject: altos: Add STM USB driver Emulates the usual CDC-ACM device Signed-off-by: Keith Packard --- src/stm/ao_usb.h | 101 +++++ src/stm/ao_usb_stm.c | 1027 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1128 insertions(+) create mode 100644 src/stm/ao_usb.h create mode 100644 src/stm/ao_usb_stm.c diff --git a/src/stm/ao_usb.h b/src/stm/ao_usb.h new file mode 100644 index 00000000..d3129d34 --- /dev/null +++ b/src/stm/ao_usb.h @@ -0,0 +1,101 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_INT_SIZE 8 +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c new file mode 100644 index 00000000..5a447d43 --- /dev/null +++ b/src/stm/ao_usb_stm.c @@ -0,0 +1,1027 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" +#include "ao_product.h" + +#define USB_DEBUG 0 +#define USB_DEBUG_DATA 0 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args); +#else +#define debug(format, args...) +#endif + +#if USB_DEBUG_DATA +#define debug_data(format, args...) printf(format, ## args); +#else +#define debug_data(format, args...) +#endif + +struct ao_task ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} ao_usb_setup; + +static uint8_t ao_usb_ep0_state; +static const uint8_t * ao_usb_ep0_in_data; +static uint8_t ao_usb_ep0_in_len; +static uint8_t ao_usb_ep0_in_pending; +static uint8_t ao_usb_ep0_in_buf[2]; +static uint8_t ao_usb_ep0_out_len; +static uint8_t *ao_usb_ep0_out_data; +static union stm_usb_bdt *ao_usb_bdt; +static uint16_t ao_usb_sram_addr; +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx_count; +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t ao_usb_rx_count, ao_usb_rx_pos; + +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 + +/* + * Pointers into the USB packet buffer area + */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +static uint8_t ao_usb_in_flushed; +static uint8_t ao_usb_in_pending; +static uint8_t ao_usb_out_avail; +static uint8_t ao_usb_running; +static uint8_t ao_usb_configuration; +static uint8_t ueienx_0; + +#define AO_USB_EP0_GOT_RESET 1 +#define AO_USB_EP0_GOT_SETUP 2 +#define AO_USB_EP0_GOT_RX_DATA 4 +#define AO_USB_EP0_GOT_TX_ACK 8 + +static uint8_t ao_usb_ep0_receive; +static uint8_t ao_usb_address; +static uint8_t ao_usb_address_pending; + +static inline uint32_t set_toggle(uint32_t current_value, + uint32_t mask, + uint32_t desired_value) +{ + return (current_value ^ desired_value) & mask; +} + +static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) +{ + return (uint32_t *) (stm_usb_sram + 2 * sram_addr); +} + +static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK; +} + +static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_TX) & STM_USB_EPR_STAT_TX_MASK; +} + +static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_RX) & 1; +} + +static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_TX) & 1; +} + +static inline uint32_t ao_usb_epr_setup(uint32_t epr) { + return (epr >> STM_USB_EPR_SETUP) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_RX) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_TX) & 1; +} + +/* + * Set current device address and mark the + * interface as active + */ +void +ao_usb_set_address(uint8_t address) +{ + debug("ao_usb_set_address %02x\n", address); + stm_usb.daddr = (1 << STM_USB_DADDR_EF) | address; + ao_usb_address_pending = 0; +} + +/* + * Set just endpoint 0, for use during startup + */ + +static void +ao_usb_set_ep0(void) +{ + uint32_t epr; + int e; + + ao_usb_sram_addr = 0; + + /* buffer table is at the start of USB memory */ + stm_usb.btable = 0; + ao_usb_bdt = (void *) stm_usb_sram; + + ao_usb_sram_addr += 8 * STM_USB_BDT_SIZE; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_tx = 0; + ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_CONTROL_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + cli(); + epr = stm_usb.epr[0]; + epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_CONTROL_EP << STM_USB_EPR_EA)); + stm_usb.epr[0] = epr; + sei(); + debug ("epr 0 now %x\n", stm_usb.epr[0]); + + /* Clear all of the other endpoints */ + for (e = 1; e < 8; e++) { + cli(); + epr = stm_usb.epr[e]; + epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | + (0 << STM_USB_EPR_EA)); + stm_usb.epr[e] = epr; + sei(); + } + + ao_usb_set_address(0); +} + +static void +ao_usb_set_configuration(void) +{ + uint32_t epr; + + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_INT_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_INT_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_INT_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_INT_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_INT_EPR, epr, stm_usb.epr[AO_USB_INT_EPR]); + + /* Set up the OUT end point */ + ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_OUT_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_OUT_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | + (AO_USB_OUT_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_OUT_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_OUT_EPR, epr, stm_usb.epr[AO_USB_OUT_EPR]); + + /* Set up the IN end point */ + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_IN_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_IN_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_IN_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_IN_EPR, epr, stm_usb.epr[AO_USB_IN_EPR]); + ao_usb_running = 1; +} + +static uint16_t control_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +/* + * Write these values to preserve register contents under HW changes + */ + +#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) + +#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ + (1 << STM_USB_EPR_EP_KIND) | \ + (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) + +void +stm_usb_lp_isr(void) +{ + uint32_t istr = stm_usb.istr; + + if (istr & (1 << STM_USB_ISTR_CTR)) { + uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK; + uint32_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = stm_usb.epr[ep]; + epr_write = epr; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write &= ~(1 << STM_USB_EPR_CTR_RX); + epr_write &= ~(1 << STM_USB_EPR_CTR_TX); + stm_usb.epr[ep] = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_wakeup(&ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + ao_usb_out_avail = 1; + ao_wakeup(&ao_stdin_ready); + } + break; + case AO_USB_IN_EPR: + ++in_count; + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + } + return; + } + + if (istr & (1 << STM_USB_ISTR_RESET)) { + ++reset_count; + stm_usb.istr &= ~(1 << STM_USB_ISTR_RESET); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_wakeup(&ao_usb_ep0_receive); + } +} + +void +stm_usb_hp_isr(void) +{ + stm_usb_lp_isr(); +} + +void +stm_usb_fs_wkup(void) +{ + /* USB wakeup, just clear the bit for now */ + stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ + ao_usb_ep0_in_pending = in_pending; + +#if 0 + if (in_pending) + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ +#endif +} + +/* The USB memory holds 16 bit values on 32 bit boundaries + * and must be accessed only in 32 bit units. Sigh. + */ + +static inline void +ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) { + *base = (*base & 0xff) | ((uint32_t) byte << 8); + } else { + *base = (*base & 0xff00) | byte; + } +} + +static inline void +ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +{ + base[offset>>1] = data; +} + +static void +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src++, base, offset++); + bytes--; + } + while (bytes >= 2) { + debug_data (" %02x %02x", src[0], src[1]); + ao_usb_write_short((src[1] << 8) | src[0], base, offset); + offset += 2; + src += 2; + bytes -= 2; + } + if (bytes) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src, base, offset); + } +} + +static inline uint8_t +ao_usb_read_byte(uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) + return (*base >> 8) & 0xff; + else + return *base & 0xff; +} + +static inline uint16_t +ao_usb_read_short(uint32_t *base, uint16_t offset) +{ + return base[offset>>1]; +} + +static void +ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + *dst++ = ao_usb_read_byte(base, offset++); + debug_data (" %02x", dst[-1]); + bytes--; + } + while (bytes >= 2) { + uint16_t s = ao_usb_read_short(base, offset); + dst[0] = s; + dst[1] = s >> 8; + debug_data (" %02x %02x", dst[0], dst[1]); + offset += 2; + dst += 2; + bytes -= 2; + } + if (bytes) { + *dst = ao_usb_read_byte(base, offset); + debug_data (" %02x", dst[0]); + } +} + +static inline void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { + uint32_t epr_write, epr_old, epr_new, epr_want; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, + stat_tx << STM_USB_EPR_STAT_TX); + stm_usb.epr[ep] = epr_write; + epr_new = stm_usb.epr[ep]; + sei(); + epr_want = (epr_old & ~(STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) | + (stat_tx << STM_USB_EPR_STAT_TX); + if (epr_new != epr_want) { + debug ("**** set_stat_tx to %x. old %08x want %08x write %08x new %08x\n", + stat_tx, epr_old, epr_want, epr_write, epr_new); + } +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + uint8_t this_len; + + /* Check to see if the endpoint is still busy */ + if (ao_usb_epr_stat_tx(stm_usb.epr[0]) == STM_USB_EPR_STAT_TX_VALID) { + debug("EP0 not accepting IN data\n"); + ao_usb_ep0_set_in_pending(1); + } else { + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + ao_usb_ep0_in_len -= this_len; + + /* Set IN interrupt enable */ + if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) + ao_usb_ep0_set_in_pending(0); + else + ao_usb_ep0_set_in_pending(1); + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[0].single.count_tx = this_len; + ao_usb_set_stat_tx(0, STM_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[0]); + } +} + +static inline void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old, epr_new, epr_want; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, + stat_rx << STM_USB_EPR_STAT_RX); + stm_usb.epr[ep] = epr_write; + epr_new = stm_usb.epr[ep]; + sei(); + epr_want = (epr_old & ~(STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX)) | + (stat_rx << STM_USB_EPR_STAT_RX); + if (epr_new != epr_want) { + debug ("**** set_stat_rx to %x. old %08x want %08x write %08x new %08x\n", + stat_rx, epr_old, epr_want, epr_write, epr_new); + } +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(void) +{ + uint16_t len = ao_usb_bdt[0].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + + /* Pull all of the data out of the packet */ + debug_data ("Fill EP0 len %d:", len); + ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + debug_data ("\n"); + ao_usb_ep0_out_data += len; + + /* ACK the packet */ + ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID); +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_address = ao_usb_setup.value; + ao_usb_address_pending = 1; + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + ao_usb_ep0_flush(); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + uint8_t receive; + ao_arch_critical( + while (!(receive = ao_usb_ep0_receive)) + ao_sleep(&ao_usb_ep0_receive); + ao_usb_ep0_receive = 0; + ); + + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + continue; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + ao_usb_ep0_fill(); + ao_usb_ep0_set_in_pending(1); + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + ao_usb_ep0_flush(); + if (ao_usb_address_pending) { + ao_usb_set_address(ao_usb_address); + ao_usb_set_configuration(); + } + } + } +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ + debug ("send %d\n", ao_usb_tx_count); + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + ao_usb_in_pending = 1; + ao_usb_tx_count = 0; +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx_count < AO_USB_IN_SIZE) + break; + + cli(); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + sei(); + } +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + if (!ao_usb_in_flushed) { + ao_usb_in_flushed = 1; + cli(); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + sei(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx_count == AO_USB_IN_SIZE) + ao_usb_in_send(); + ao_usb_in_flushed = 0; +} + +static void +ao_usb_out_recv(void) +{ + ao_usb_out_avail = 0; + + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + debug ("recv %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + debug_data("\n"); + ao_usb_rx_pos = 0; + + /* ACK the packet */ + ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); +} + +static char +_ao_usb_pollchar(void) +{ + char c; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + if (ao_usb_rx_pos != ao_usb_rx_count) + break; + + /* Check to see if a packet has arrived */ + if (!ao_usb_out_avail) + return AO_READ_AGAIN; + ao_usb_out_recv(); + } + + /* Pull a character out of the fifo */ + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + return c; +} + +char +ao_usb_pollchar(void) +{ + char c; + cli(); + c = _ao_usb_pollchar(); + sei(); + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + cli(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + sei(); + return c; +} + +void +ao_usb_disable(void) +{ + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + stm_usb.istr = 0; + + /* Disable USB pull-up */ + stm_syscfg.pmc &= ~(1 << STM_SYSCFG_PMC_USB_PU); + + /* Switch off the device */ + stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES); + + /* Disable the interface */ + stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); +} + +void +ao_usb_enable(void) +{ + uint16_t tick; + + /* Enable SYSCFG */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); + + /* Disable USB pull-up */ + stm_syscfg.pmc &= ~(1 << STM_SYSCFG_PMC_USB_PU); + + /* Enable USB device */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USBEN); + + /* Do not touch the GPIOA configuration; USB takes priority + * over GPIO on pins A11 and A12, but if you select alternate + * input 10 (the documented correct selection), then USB is + * pulled low and doesn't work at all + */ + + /* Route interrupts */ + stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); + stm_nvic_set_enable(STM_ISR_USB_LP_POS); + + ao_usb_configuration = 0; + + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + + /* Clear the power down bit */ + stm_usb.cntr = 0; + + /* Clear any spurious interrupts */ + stm_usb.istr = 0; + + debug ("ao_usb_enable\n"); + + /* Enable interrupts */ + stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | + (0 << STM_USB_CNTR_PMAOVRM) | + (0 << STM_USB_CNTR_ERRM) | + (0 << STM_USB_CNTR_WKUPM) | + (0 << STM_USB_CNTR_SUSPM) | + (1 << STM_USB_CNTR_RESETM) | + (0 << STM_USB_CNTR_SOFM) | + (0 << STM_USB_CNTR_ESOFM) | + (0 << STM_USB_CNTR_RESUME) | + (0 << STM_USB_CNTR_FSUSP) | + (0 << STM_USB_CNTR_LP_MODE) | + (0 << STM_USB_CNTR_PDWN) | + (0 << STM_USB_CNTR_FRES)); + + /* Enable USB pull-up */ + stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); +} + +#if USB_DEBUG +struct ao_task ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} +#endif + +static void +ao_usb_irq(void) +{ + printf ("control: %d out: %d in: %d reset: %d\n", + control_count, out_count, in_count, reset_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { + { ao_usb_irq, "I\0Show USB interrupt counts" }, + { 0, NULL } +}; + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + debug ("ao_usb_init\n"); + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); +#if USB_DEBUG + ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif + ao_cmd_register(&ao_usb_cmds[0]); +#if !USB_DEBUG + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +} -- cgit v1.2.3 From 93ef7e4a23d13540615f1a9782e1d58ddb7f258e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:29:38 -0700 Subject: altos: Use new USB driver in megametrum-v0.1 product Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 6 ++---- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b0f2a612..3c3d7173 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -40,7 +40,8 @@ ALTOS_SRC = \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ - ao_m25.c + ao_m25.c \ + ao_usb_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM @@ -66,9 +67,6 @@ $(OBJ): $(INC) 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 - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< - distclean: clean clean: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 77a2bf0a..9efde598 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -50,6 +50,7 @@ main(void) ao_beep_init(); ao_adc_init(); ao_storage_init(); + ao_usb_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 46098d34..e4e5def6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -21,7 +21,7 @@ /* 8MHz High speed external crystal */ #define AO_HSE 8000000 -/* PLLVCO = 96MHz (so that USB will work*/ +/* PLLVCO = 96MHz (so that USB will work) */ #define AO_PLLMUL 12 #define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) @@ -61,8 +61,8 @@ #define ao_gps_putchar ao_serial3_putchar #define ao_gps_set_speed ao_serial3_set_speed -#define HAS_USB 0 -#define HAS_BEEP 0 +#define HAS_USB 1 +#define HAS_BEEP 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 -- cgit v1.2.3 From 49ac2828510e8b5fcba7e31631dac0580a455011 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:30:13 -0700 Subject: altos: Rework how STM clocks are initialized. Clean all of the RCC configuration up after turning on the clocks. Use the MSI clock during initialization to avoid messing around with the HSI clock temporarily. Allow for an external clock on the HSE line. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 151 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 59 deletions(-) diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index e7f1ddfe..099a0ece 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -106,6 +106,53 @@ ao_clock_init(void) uint32_t cfgr; uint32_t cr; + /* Switch to MSI while messing about */ + stm_rcc.cr |= (1 << STM_RCC_CR_MSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_MSIRDY))) + asm("nop"); + + /* reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE */ + stm_rcc.cfgr &= (uint32_t)0x88FFC00C; + + /* reset HSION, HSEON, CSSON and PLLON bits */ + stm_rcc.cr &= 0xeefefffe; + + /* reset PLLSRC, PLLMUL and PLLDIV bits */ + stm_rcc.cfgr &= 0xff02ffff; + + /* Disable all interrupts */ + stm_rcc.cir = 0; + +#if AO_HSE +#if AO_HSE_BYPASS + stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP); +#else + stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP); +#endif + /* Enable HSE clock */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) + asm("nop"); + +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) +#define STM_PLLSRC AO_HSE +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) +#else +#define STM_HSI 16000000 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) +#define STM_PLLSRC STM_HSI +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) +#endif + +#if !AO_HSE || HAS_ADC + /* Enable HSI RC clock 16MHz */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); +#endif + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ /* Enable 64-bit access and prefetch */ @@ -116,6 +163,24 @@ ao_clock_init(void) /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY); + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); /* HCLK to 16MHz -> AHB prescaler = /1 */ cfgr = stm_rcc.cfgr; @@ -138,65 +203,6 @@ ao_clock_init(void) cfgr |= (AO_RCC_CFGR_PPRE2_DIV << STM_RCC_CFGR_PPRE2); stm_rcc.cfgr = cfgr; - /* Enable power interface clock */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); - - - /* Set voltage range to 1.8V */ - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Configure voltage scaling range */ - cr = stm_pwr.cr; - cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); - cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); - stm_pwr.cr = cr; - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - -#if AO_HSE - /* Enable HSE clock */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) - asm("nop"); - } -#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) -#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) -#define STM_PLLSRC AO_HSE -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) -#else -#define STM_HSI 16000000 -#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) -#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) -#define STM_PLLSRC STM_HSI -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) -#endif - -#if !AO_HSE || HAS_ADC - /* Enable HSI RC clock 16MHz */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSION); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) - asm("nop"); - } -#endif - /* Switch to direct high speed clock for SYSCLK */ - if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - STM_RCC_CFGR_SWS_TARGET_CLOCK) { - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= STM_RCC_CFGR_SW_TARGET_CLOCK; - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - STM_RCC_CFGR_SWS_TARGET_CLOCK); - asm("nop"); - } - /* Disable the PLL */ stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) @@ -237,4 +243,31 @@ ao_clock_init(void) if (part == val) break; } + +#if 0 + stm_rcc.apb2rstr = 0xffff; + stm_rcc.apb1rstr = 0xffff; + stm_rcc.ahbrstr = 0x3f; + stm_rcc.ahbenr = (1 << STM_RCC_AHBENR_FLITFEN); + stm_rcc.apb2enr = 0; + stm_rcc.apb1enr = 0; + stm_rcc.ahbrstr = 0; + stm_rcc.apb1rstr = 0; + stm_rcc.apb2rstr = 0; +#endif + + /* Clear reset flags */ + stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); + + + /* Output SYSCLK on PA8 for measurments */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0); + stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE); + stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz); + + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE); + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); } -- cgit v1.2.3 From 6d1606895f70c6bca20c25084107f90bd0b613ec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:31:28 -0700 Subject: altos: Switch stm-demo to HSE clock, add USB Requires that SB17 be soldered shut so that the MCO from the STlink CPU is available the target for HSE input. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 3 ++- src/stm-demo/ao_demo.c | 1 + src/stm-demo/ao_pins.h | 31 +++++++++++++++++++------------ 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 2f156ea4..dd7e6e02 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -32,7 +32,8 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_adc_stm.c \ - ao_i2c_stm.c + ao_i2c_stm.c \ + ao_usb_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 879f7f75..7bb53047 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -174,6 +174,7 @@ main(void) ao_timer_set_adc_interval(100); ao_adc_init(); + ao_usb_init(); ao_cmd_register(&ao_demo_cmds[0]); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 3192c2b7..1daab351 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -18,22 +18,29 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -/* No external crystal */ -#define AO_HSE 0 +/* Bridge SB17 on the board and use the MCO from the other chip */ +#define AO_HSE 8000000 +#define AO_HSE_BYPASS 1 +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHZ (CPU clock) */ #define AO_AHB_PRESCALER 1 #define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 -#define AO_APB1_PRESCALER 2 -#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -#define AO_APB2_PRESCALER 2 -#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1 -#define AO_PLLMUL 6 -#define AO_PLLDIV 4 -#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6) -#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 @@ -56,7 +63,7 @@ #define HAS_SPI_2 0 -#define HAS_USB 0 +#define HAS_USB 1 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From f952f9c285e2718a433c8c720c9b5d9c369e7036 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:50:12 -0700 Subject: altos: Start adding apogee lockout support Remove radio channel support too. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 2 +- src/core/ao.h | 20 ++------- src/core/ao_config.c | 112 ++++++++++++-------------------------------------- 3 files changed, 32 insertions(+), 102 deletions(-) diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index ee506f89..51ed369b 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -286,7 +286,7 @@ ao_radio_get(uint8_t len) ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + RF_CHANNR = 0; RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_setting); diff --git a/src/core/ao.h b/src/core/ao.h index f7db3bf4..9a3b5829 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1457,26 +1457,16 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 10 -#define AO_AES_LEN 16 - -#if HAS_RADIO_CHANNELS -#define AO_CHANNEL_NAME_LEN 10 +#define AO_CONFIG_MINOR 11 -#define AO_NUM_CHANNELS 10 - -struct ao_radio_channel { - char name[AO_CHANNEL_NAME_LEN]; - uint32_t kHz; -}; -#endif +#define AO_AES_LEN 16 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; int16_t accel_plus_g; /* changed for minor version 2 */ - uint8_t radio_channel; + uint8_t _legacy_radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ @@ -1488,9 +1478,7 @@ struct ao_config { uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ -#if HAS_RADIO_CHANNELS - struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ -#endif + uint16_t apogee_lockout; /* minor version 11 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 32798f75..55fb8590 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -85,7 +85,6 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; - ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); @@ -113,19 +112,12 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; -#if HAS_AES if (ao_config.minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); -#endif - if (ao_config.minor < 10) { + if (ao_config.minor < 10) ao_config.frequency = 434550; -#if HAS_RADIO_CHANNELS - ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); - ao_xmemcpy(&ao_config.radio_channels[0].name[0], - CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); - ao_config.radio_channels[0].kHz = 434550; -#endif - } + if (ao_config.minor < 11) + ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -184,25 +176,6 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } -void -ao_config_radio_channel_show(void) __reentrant -{ - printf("Radio channel: %d\n", - ao_config.radio_channel); -} - -void -ao_config_radio_channel_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_channel = ao_cmd_lex_i; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_frequency_show(void) __reentrant { @@ -218,13 +191,12 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; - ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); } -#if HAS_ADC +#if HAS_FLIGHT void ao_config_main_deploy_show(void) __reentrant @@ -328,7 +300,25 @@ ao_config_apogee_delay_set(void) __reentrant _ao_config_edit_finish(); } -#endif /* HAS_ADC */ +void +ao_config_apogee_lockout_show(void) __reentrant +{ + printf ("Apogee lockout: %d seconds\n", + ao_config.apogee_lockout); +} + +void +ao_config_apogee_lockout_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_lockout = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_FLIGHT */ void ao_config_radio_cal_show(void) __reentrant @@ -467,50 +457,6 @@ ao_config_key_set(void) __reentrant } #endif -#if HAS_RADIO_CHANNELS -void -ao_config_radio_config_show(void) __reentrant -{ - uint8_t i; - for (i = 0; i < AO_NUM_CHANNELS; i++) - if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld\n", - i, - ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz); - } -} - -void -ao_config_radio_config_set(void) __reentrant -{ - __xdata struct ao_radio_channel * ch; - uint8_t i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; - _ao_config_edit_start(); - ao_cmd_white(); - i = 0; - while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { - ch->name[i++] = ao_cmd_lex_c; - ao_cmd_lex(); - } - if (i < AO_CHANNEL_NAME_LEN) { - ch->name[i] = '\0'; - ao_cmd_lex(); - } - ao_cmd_decimal(); - ch->kHz = ao_cmd_lex_u32; - _ao_config_edit_finish(); -} -#endif - struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -527,14 +473,14 @@ static void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { -#if HAS_ADC +#if HAS_FLIGHT { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, -#endif /* HAS_ADC */ - { "r \0Radio channel", - ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "L \0Apogee detect lockout (s)", + ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, +#endif /* HAS_FLIGHT */ { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", @@ -562,10 +508,6 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, -#endif -#if HAS_RADIO_CHANNELS - { "C / \0Set radio chan config", - ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 040a6eb119451026e1ec7c3a6a8e76b439c632d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:51:07 -0700 Subject: altos: Massive product config cleanup Support multiple serial ports more cleanly Split out parts of ao.h into separate feature header files Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 7 - src/avr/ao_pins.h | 15 +- src/avr/ao_serial_avr.c | 62 +-- src/avr/ao_usb.h | 100 ----- src/avr/ao_usb_avr.c | 6 +- src/cc1111/ao_arch.h | 30 ++ src/cc1111/ao_pins.h | 24 +- src/cc1111/ao_serial.c | 227 +++++++++-- src/cc1111/ao_serial0.c | 152 -------- src/cc1111/ao_usb.c | 6 +- src/cc1111/ao_usb.h | 100 ----- src/core/ao.h | 704 ++--------------------------------- src/core/ao_adc.h | 62 +++ src/core/ao_beep.h | 74 ++++ src/core/ao_dbg.h | 62 +++ src/core/ao_flight.h | 59 +++ src/core/ao_led.h | 55 +++ src/core/ao_log.h | 196 ++++++++++ src/core/ao_log_telem.c | 4 +- src/core/ao_product.c | 8 +- src/core/ao_report.c | 2 + src/core/ao_sample.h | 137 +++++++ src/core/ao_serial.h | 86 +++++ src/core/ao_stdio.c | 6 + src/core/ao_storage.c | 2 +- src/core/ao_storage.h | 84 +++++ src/core/ao_usb.h | 136 +++++++ src/drivers/ao_btm.c | 30 +- src/drivers/ao_gps_sirf.c | 36 +- src/drivers/ao_gps_skytraq.c | 6 +- src/drivers/ao_science_slave.c | 1 + src/megametrum-v0.1/ao_pins.h | 2 + src/product/ao_telebt.c | 2 + src/product/ao_terraui.c | 1 + src/stm/ao_arch.h | 2 - src/stm/ao_serial_stm.c | 2 +- src/stm/ao_usb.h | 101 ----- src/stm/ao_usb_stm.c | 6 +- src/teleballoon-v1.1/ao_pins.h | 5 - src/telepyro-v0.1/Makefile | 6 +- src/telescience-v0.1/Makefile | 9 +- src/teleshield-v0.1/Makefile | 1 - src/teleshield-v0.1/ao_ardu_serial.c | 3 +- src/teleshield-v0.1/ao_pins.h | 8 +- src/teleshield-v0.1/ao_teleshield.c | 3 + src/teleterra-v0.1/ao_pins.h | 5 - src/teleterra-v0.2/ao_pins.h | 5 - src/test/ao_gps_test.c | 6 +- src/test/ao_gps_test_skytraq.c | 6 +- 49 files changed, 1342 insertions(+), 1310 deletions(-) delete mode 100644 src/avr/ao_usb.h delete mode 100644 src/cc1111/ao_serial0.c delete mode 100644 src/cc1111/ao_usb.h create mode 100644 src/core/ao_adc.h create mode 100644 src/core/ao_beep.h create mode 100644 src/core/ao_dbg.h create mode 100644 src/core/ao_flight.h create mode 100644 src/core/ao_led.h create mode 100644 src/core/ao_log.h create mode 100644 src/core/ao_sample.h create mode 100644 src/core/ao_serial.h create mode 100644 src/core/ao_storage.h create mode 100644 src/core/ao_usb.h delete mode 100644 src/stm/ao_usb.h diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index b816279e..c775dab6 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -146,12 +146,5 @@ extern uint8_t ao_cpu_sleep_disable; #define AO_TELESCIENCE_NUM_ADC 12 -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ -}; - -#define AO_ADC_RING 16 - #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 6a63468f..f2b40fb4 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -21,7 +21,7 @@ #ifdef AVR_DEMO #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 @@ -37,11 +37,11 @@ #define HAS_USB 1 #define HAS_LOG 1 #define TEENSY 0 - #define USE_SERIAL_STDIN 0 #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_EEPROM 1 #define HAS_STORAGE_DEBUG 0 #define AVR_VCC_5V 0 @@ -66,7 +66,7 @@ #define HAS_USB 1 #define HAS_LOG 0 #define TEENSY 0 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_1 1 #define HAS_USB 1 #define HAS_ADC 1 @@ -88,4 +88,13 @@ #define AO_M25_SPI_CS_PORT SPI_CS_PORT #define AO_M25_SPI_CS_MASK M25_CS_MASK +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index 6885c339..dcee246c 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -__xdata struct ao_fifo ao_usart1_rx_fifo; -__xdata struct ao_fifo ao_usart1_tx_fifo; +__xdata struct ao_fifo ao_serial1_rx_fifo; +__xdata struct ao_fifo ao_serial1_tx_fifo; void ao_debug_out(char c) @@ -31,10 +31,10 @@ ao_debug_out(char c) ISR(USART1_RX_vect) { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, UDR1); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, UDR1); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL_1_STDIN ao_wakeup(&ao_stdin_ready); #endif } @@ -42,68 +42,68 @@ ISR(USART1_RX_vect) static __xdata uint8_t ao_serial_tx1_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && + if (!ao_fifo_empty(ao_serial1_tx_fifo) && !ao_serial_tx1_started) { ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + ao_fifo_remove(ao_serial1_tx_fifo, UDR1); } } ISR(USART1_UDRE_vect) { - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; cli(); - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); sei(); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; cli(); - if (ao_fifo_empty(ao_usart1_rx_fifo)) { + if (ao_fifo_empty(ao_serial1_rx_fifo)) { sei(); return AO_READ_AGAIN; } - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); sei(); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { cli(); - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); ao_serial_tx1_start(); sei(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { cli(); - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); sei(); } @@ -125,7 +125,7 @@ static const struct { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { ao_serial_drain(); if (speed > AO_SERIAL_SPEED_57600) @@ -154,9 +154,9 @@ ao_serial_init(void) (1 << TXEN1) | /* Enable transmitter */ (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, +#if USE_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, NULL); #endif } diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/avr/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index fc8899d8..23a27c73 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -330,17 +330,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 847ac1a6..9d0643b4 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -294,4 +294,34 @@ ao_dma_abort(uint8_t id); void ao_dma_isr(void) ao_arch_interrupt(8); +/* ao_adc.c */ + +#if HAS_ADC +/* The A/D interrupt handler */ +void +ao_adc_isr(void) ao_arch_interrupt(1); +#endif + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) ao_arch_interrupt(6); +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx_isr(void) ao_arch_interrupt(7); +#endif + +#if HAS_SERIAL_1 +void +ao_serial1_rx_isr(void) ao_arch_interrupt(3); + +void +ao_serial1_tx_isr(void) ao_arch_interrupt(14); +#endif + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 5c0cb7df..4f6edd37 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -58,7 +57,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -95,7 +93,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -131,7 +128,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -161,7 +157,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -188,7 +183,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -214,7 +208,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -244,7 +237,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -273,7 +265,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -301,7 +292,8 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -339,7 +331,8 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 1 @@ -379,7 +372,6 @@ #define HAS_BEEP 1 #define HAS_GPS 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -468,14 +460,6 @@ #error Please define IGNITE_ON_P0 #endif -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 4d5b9abd..00c85ff3 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -17,78 +17,168 @@ #include "ao.h" -volatile __xdata struct ao_fifo ao_usart1_rx_fifo; -volatile __xdata struct ao_fifo ao_usart1_tx_fifo; +#if HAS_SERIAL_0 + +volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +void +ao_serial0_rx_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_serial0_rx_fifo)) + ao_fifo_insert(ao_serial0_rx_fifo, U0DBUF); + ao_wakeup(&ao_serial0_rx_fifo); +#if USE_SERIAL_0_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial0_tx_started; + +static void +ao_serial0_tx_start(void) +{ + if (!ao_fifo_empty(ao_serial0_tx_fifo) && + !ao_serial0_tx_started) + { + ao_serial0_tx_started = 1; + ao_fifo_remove(ao_serial0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx_started = 0; + ao_serial0_tx_start(); + ao_wakeup(&ao_serial0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_serial0_rx_fifo)) + ao_sleep(&ao_serial0_rx_fifo); + ao_fifo_remove(ao_serial0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_0_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_serial0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_serial0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); + ao_fifo_insert(ao_serial0_tx_fifo, c); + ao_serial0_tx_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U0UCR |= UxUCR_FLUSH; + U0BAUD = ao_serial_speeds[speed].baud; + U0GCR = ao_serial_speeds[speed].gcr; +} +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 + +volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +volatile __xdata struct ao_fifo ao_serial1_tx_fifo; void -ao_serial_rx1_isr(void) __interrupt 3 +ao_serial1_rx_isr(void) __interrupt 3 { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL1_STDIN ao_wakeup(&ao_stdin_ready); #endif } -static __xdata uint8_t ao_serial_tx1_started; +static __xdata uint8_t ao_serial1_tx_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) + if (!ao_fifo_empty(ao_serial1_tx_fifo) && + !ao_serial1_tx_started) { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); + ao_serial1_tx_started = 1; + ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF); } } void -ao_serial_tx1_isr(void) __interrupt 14 +ao_serial1_tx_isr(void) __interrupt 14 { UTX1IF = 0; - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; - if (ao_fifo_empty(ao_usart1_rx_fifo)) + if (ao_fifo_empty(ao_serial1_rx_fifo)) return AO_READ_AGAIN; - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); + ao_serial1_tx_start(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); } const __code struct ao_serial_speed ao_serial_speeds[] = { @@ -111,9 +201,9 @@ const __code struct ao_serial_speed ao_serial_speeds[] = { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { - ao_serial_drain(); + ao_serial1_drain(); if (speed > AO_SERIAL_SPEED_57600) return; U1UCR |= UxUCR_FLUSH; @@ -121,9 +211,67 @@ ao_serial_set_speed(uint8_t speed) U1GCR = ao_serial_speeds[speed].gcr; } +#endif /* HAS_SERIAL_1 */ + void ao_serial_init(void) { +#if HAS_SERIAL_0 +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +#if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN + ao_add_stdio(ao_serial0_pollchar, + ao_serial0_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 #if HAS_SERIAL_1_ALT_1 /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; @@ -151,7 +299,7 @@ ao_serial_init(void) U1CSR = (UxCSR_MODE_UART | UxCSR_RE); /* Pick a 4800 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_serial1_set_speed(AO_SERIAL_SPEED_4800); /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | @@ -169,4 +317,11 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; + +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_1 */ } diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c deleted file mode 100644 index e8c1eb35..00000000 --- a/src/cc1111/ao_serial0.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) __interrupt 2 -{ - if (!ao_fifo_full(ao_usart0_rx_fifo)) - ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); - ao_wakeup(&ao_usart0_rx_fifo); -} - -static __xdata uint8_t ao_serial0_tx0_started; - -static void -ao_serial0_tx0_start(void) -{ - if (!ao_fifo_empty(ao_usart0_tx_fifo) && - !ao_serial0_tx0_started) - { - ao_serial0_tx0_started = 1; - ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); - } -} - -void -ao_serial0_tx0_isr(void) __interrupt 7 -{ - UTX0IF = 0; - ao_serial0_tx0_started = 0; - ao_serial0_tx0_start(); - ao_wakeup(&ao_usart0_tx_fifo); -} - -char -ao_serial0_getchar(void) __critical -{ - char c; - while (ao_fifo_empty(ao_usart0_rx_fifo)) - ao_sleep(&ao_usart0_rx_fifo); - ao_fifo_remove(ao_usart0_rx_fifo, c); - return c; -} - -#if USE_SERIAL_STDIN -char -ao_serial0_pollchar(void) __critical -{ - char c; - if (ao_fifo_empty(ao_usart0_rx_fifo)) - return AO_READ_AGAIN; - ao_fifo_remove(ao_usart0_rx_fifo,c); - return c; -} -#endif - -void -ao_serial0_putchar(char c) __critical -{ - while (ao_fifo_full(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); - ao_fifo_insert(ao_usart0_tx_fifo, c); - ao_serial0_tx0_start(); -} - -void -ao_serial0_drain(void) __critical -{ - while (!ao_fifo_empty(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); -} - -void -ao_serial0_set_speed(uint8_t speed) -{ - ao_serial0_drain(); - if (speed > AO_SERIAL_SPEED_57600) - return; - U0UCR |= UxUCR_FLUSH; - U0BAUD = ao_serial_speeds[speed].baud; - U0GCR = ao_serial_speeds[speed].gcr; -} - -void -ao_serial0_init(void) -{ -#if HAS_SERIAL_0_ALT_1 - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; - - P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; - - /* Make the USART pins be controlled by the USART */ - P0SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P0SEL |= (1 << 4) | (1 << 5); -#endif -#else - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | - (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); - - /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P1SEL |= (1 << 5) | (1 << 4); -#endif -#endif - - /* UART mode with receiver enabled */ - U0CSR = (UxCSR_MODE_UART | UxCSR_RE); - - /* Pick a 9600 baud rate */ - ao_serial0_set_speed(AO_SERIAL_SPEED_9600); - - /* Reasonable serial parameters */ - U0UCR = (UxUCR_FLUSH | -#if HAS_SERIAL_0_HW_FLOW - UxUCR_FLOW_ENABLE | -#else - UxUCR_FLOW_DISABLE | -#endif - UxUCR_D9_EVEN_PARITY | - UxUCR_BIT9_8_BITS | - UxUCR_PARITY_DISABLE | - UxUCR_SPB_1_STOP_BIT | - UxUCR_STOP_HIGH | - UxUCR_START_LOW); - - IEN0 |= IEN0_URX0IE; - IEN2 |= IEN2_UTX0IE; -} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 35c9ac20..ce26e808 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -261,15 +261,15 @@ ao_usb_ep0_setup(void) break; case AO_USB_TYPE_CLASS: switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/cc1111/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9a3b5829..28d0ba87 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -154,182 +154,14 @@ void ao_clock_init(void); /* - * One set of samples read from the A/D converter or telemetry - */ - -#if HAS_ADC - -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif - -/* Trigger a conversion sequence (called from the timer interrupt) */ -void -ao_adc_poll(void); - -/* Suspend the current task until another A/D sample is converted */ -void -ao_adc_sleep(void); - -/* Get a copy of the last complete A/D sample set */ -void -ao_adc_get(__xdata struct ao_adc *packet); - -/* The A/D interrupt handler */ - -void -ao_adc_isr(void) ao_arch_interrupt(1); - -/* Initialize the A/D converter */ -void -ao_adc_init(void); - -#endif /* HAS_ADC */ - -/* - * ao_beep.c - */ - -/* - * Various pre-defined beep frequencies - * - * frequency = 1/2 (24e6/32) / beep - */ - -#define AO_BEEP_LOW 150 /* 2500Hz */ -#define AO_BEEP_MID 94 /* 3989Hz */ -#define AO_BEEP_HIGH 75 /* 5000Hz */ -#define AO_BEEP_OFF 0 /* off */ - -#define AO_BEEP_g 240 /* 1562.5Hz */ -#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ -#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ -#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ -#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ -#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ -#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ -#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ -#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ -#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ -#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ -#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ -#define AO_BEEP_gg 120 /* 3125Hz */ -#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ -#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ -#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ -#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ -#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ -#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ -#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ -#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ -#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ -#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ -#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ -#define AO_BEEP_ggg 60 /* 6250Hz */ - -/* Set the beeper to the specified tone */ -void -ao_beep(uint8_t beep); - -/* Turn on the beeper for the specified time */ -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; - -/* Initialize the beeper */ -void -ao_beep_init(void); - -/* - * ao_led.c - */ - -#define AO_LED_NONE 0 - -#ifndef AO_LED_TYPE -#define AO_LED_TYPE uint8_t -#endif - -/* Turn on the specified LEDs */ -void -ao_led_on(AO_LED_TYPE colors); - -/* Turn off the specified LEDs */ -void -ao_led_off(AO_LED_TYPE colors); - -/* Set all of the LEDs to the specified state */ -void -ao_led_set(AO_LED_TYPE colors); - -/* Toggle the specified LEDs */ -void -ao_led_toggle(AO_LED_TYPE colors); - -/* Turn on the specified LEDs for the indicated interval */ -void -ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; - -/* Initialize the LEDs */ -void -ao_led_init(AO_LED_TYPE enable); - -/* - * ao_usb.c - */ - -/* Put one character to the USB output queue */ -void -ao_usb_putchar(char c); - -/* Get one character from the USB input queue */ -char -ao_usb_getchar(void); - -/* Poll for a charcter on the USB input queue. - * returns AO_READ_AGAIN if none are available + * ao_mutex.c */ -char -ao_usb_pollchar(void); - -/* Flush the USB output queue */ -void -ao_usb_flush(void); - -#if HAS_USB -/* USB interrupt handler */ -void -ao_usb_isr(void) ao_arch_interrupt(6); -#endif -/* Enable the USB controller */ void -ao_usb_enable(void); - -/* Disable the USB controller */ -void -ao_usb_disable(void); +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; -/* Initialize the USB system */ void -ao_usb_init(void); - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; /* * ao_cmd.c @@ -396,405 +228,36 @@ ao_cmd_filter(void); #endif /* - * ao_mutex.c - */ - -void -ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; - -void -ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; - -/* - * Storage interface, provided by one of the eeprom or flash - * drivers - */ - -/* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __pdata uint16_t ao_storage_unit; - -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - -/* Initialize above values. Can only be called once the OS is running */ -void -ao_storage_setup(void) __reentrant; - -/* Write data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Read data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Erase a block of storage. This always clears ao_storage_block bytes */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant; - -/* Flush any pending writes to stable storage */ -void -ao_storage_flush(void) __reentrant; - -/* Initialize the storage code */ -void -ao_storage_init(void); - -/* - * Low-level functions wrapped by ao_storage.c - */ - -/* Read data within a storage unit */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Write data within a storage unit */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Initialize low-level device bits */ -void -ao_storage_device_init(void); - -/* Print out information about flash chips */ -void -ao_storage_device_info(void) __reentrant; - -/* - * ao_log.c - */ - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -extern __pdata uint32_t ao_log_current_pos; -extern __pdata uint32_t ao_log_end_pos; -extern __pdata uint32_t ao_log_start_pos; -extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; - -/* required functions from the underlying log system */ - -#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ -#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ -#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ -#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ -#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_NONE 127 /* No log at all */ - -extern __code uint8_t ao_log_format; - -/* Return the flight number from the given log slot, 0 if none */ -uint16_t -ao_log_flight(uint8_t slot); - -/* Flush the log */ -void -ao_log_flush(void); - -/* Logging thread main routine */ -void -ao_log(void); - -/* functions provided in ao_log.c */ - -/* Figure out the current flight number */ -void -ao_log_scan(void) __reentrant; - -/* Return the position of the start of the given log slot */ -uint32_t -ao_log_pos(uint8_t slot); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - -/* - * ao_log_big.c + * Various drivers */ - -/* - * The data log is recorded in the eeprom as a sequence - * of data packets. - * - * Each packet starts with a 4-byte header that has the - * packet type, the packet checksum and the tick count. Then - * they all contain 2 16 bit values which hold packet-specific - * data. - * - * For each flight, the first packet - * is FLIGHT packet, indicating the serial number of the - * device and a unique number marking the number of flights - * recorded by this device. - * - * During flight, data from the accelerometer and barometer - * are recorded in SENSOR packets, using the raw 16-bit values - * read from the A/D converter. - * - * Also during flight, but at a lower rate, the deployment - * sensors are recorded in DEPLOY packets. The goal here is to - * detect failure in the deployment circuits. - * - * STATE packets hold state transitions as the flight computer - * transitions through different stages of the flight. - */ -#define AO_LOG_FLIGHT 'F' -#define AO_LOG_SENSOR 'A' -#define AO_LOG_TEMP_VOLT 'T' -#define AO_LOG_DEPLOY 'D' -#define AO_LOG_STATE 'S' -#define AO_LOG_GPS_TIME 'G' -#define AO_LOG_GPS_LAT 'N' -#define AO_LOG_GPS_LON 'W' -#define AO_LOG_GPS_ALT 'H' -#define AO_LOG_GPS_SAT 'V' -#define AO_LOG_GPS_DATE 'Y' - -#define AO_LOG_POS_NONE (~0UL) - -struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; - union { - struct { - int16_t ground_accel; - uint16_t flight; - } flight; - struct { - int16_t accel; - int16_t pres; - } sensor; - struct { - int16_t temp; - int16_t v_batt; - } temp_volt; - struct { - int16_t drogue; - int16_t main; - } deploy; - struct { - uint16_t state; - uint16_t reason; - } state; - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - } gps_time; - int32_t gps_latitude; - int32_t gps_longitude; - struct { - int16_t altitude; - uint16_t unused; - } gps_altitude; - struct { - uint16_t svid; - uint8_t unused; - uint8_t c_n; - } gps_sat; - struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t extra; - } gps_date; - struct { - uint16_t d0; - uint16_t d1; - } anon; - } u; -}; - -/* Write a record to the eeprom log */ -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant; - -/* - * ao_flight.c - */ - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern __pdata enum ao_flight_state ao_flight_state; - -extern __pdata uint16_t ao_launch_time; -extern __pdata uint8_t ao_flight_force_idle; - -/* Flight thread */ -void -ao_flight(void); - -/* Initialize flight thread */ -void -ao_flight_init(void); - -/* - * ao_flight_nano.c - */ - -void -ao_flight_nano_init(void); - -/* - * ao_sample.c - */ - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -/* - * Speed and acceleration are scaled by 16 to provide a bit more - * resolution while still having reasonable range. Note that this - * limits speed to 2047m/s (around mach 6) and acceleration to - * 2047m/s² (over 200g) - */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ -extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ - -#if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#if HAS_ADC +#include #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#if HAS_BEEP +#include #endif -void ao_sample_init(void); - -/* returns FALSE in preflight mode, TRUE in flight mode */ -uint8_t ao_sample(void); - -/* - * ao_kalman.c - */ - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) +#if LEDS_AVAILABLE +#include +#endif -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ +#if HAS_USB +#include +#endif -extern __pdata int16_t ao_error_h; -extern __pdata int16_t ao_error_h_sq_avg; +#if HAS_EEPROM +#include +#endif -#if HAS_ACCEL -extern __pdata int16_t ao_error_a; +#if HAS_LOG +#include #endif -void ao_kalman(void); +#if HAS_FLIGHT +#include +#include +#endif /* * ao_report.c @@ -819,125 +282,12 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; -/* - * ao_dbg.c - * - * debug another telemetrum board - */ - -/* Send a byte to the dbg target */ -void -ao_dbg_send_byte(uint8_t byte); - -/* Receive a byte from the dbg target */ -uint8_t -ao_dbg_recv_byte(void); - -/* Start a bulk transfer to/from dbg target memory */ -void -ao_dbg_start_transfer(uint16_t addr); - -/* End a bulk transfer to/from dbg target memory */ -void -ao_dbg_end_transfer(void); - -/* Write a byte to dbg target memory */ -void -ao_dbg_write_byte(uint8_t byte); - -/* Read a byte from dbg target memory */ -uint8_t -ao_dbg_read_byte(void); - -/* Enable dbg mode, switching use of the pins */ -void -ao_dbg_debug_mode(void); - -/* Reset the dbg target */ -void -ao_dbg_reset(void); - -void -ao_dbg_init(void); - -/* - * ao_serial.c - */ - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 +#if HAS_DBG +#include #endif -#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -void -ao_serial_rx1_isr(void) ao_arch_interrupt(3); - -void -ao_serial_tx1_isr(void) ao_arch_interrupt(14); - -char -ao_serial_getchar(void) __critical; - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical; - -void -ao_serial_set_stdin(uint8_t in); -#endif - -void -ao_serial_putchar(char c) __critical; - -void -ao_serial_drain(void) __critical; - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_19200 2 -#define AO_SERIAL_SPEED_57600 3 - -void -ao_serial_set_speed(uint8_t speed); - -void -ao_serial_init(void); -#endif - -#ifndef HAS_SERIAL_0 -#define HAS_SERIAL_0 0 -#endif - -#if HAS_SERIAL_0 - -extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) ao_arch_interrupt(2); - -void -ao_serial0_tx0_isr(void) ao_arch_interrupt(7); - -char -ao_serial0_getchar(void) __critical; - -void -ao_serial0_putchar(char c) __critical; - -void -ao_serial0_drain(void) __critical; - -void -ao_serial0_set_speed(uint8_t speed); - -void -ao_serial0_init(void); - +#if HAS_SERIAL_0 || HAS_SERIAL_1 || HAS_SERIAL_2 || HAS_SERIAL_3 +#include #endif diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h new file mode 100644 index 00000000..db5bfab3 --- /dev/null +++ b/src/core/ao_adc.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ADC_H_ +#define _AO_ADC_H_ + + + +/* + * One set of samples read from the A/D converter or telemetry + */ + + +/* + * ao_adc.c + */ + +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* _AO_ADC_H_ */ diff --git a/src/core/ao_beep.h b/src/core/ao_beep.h new file mode 100644 index 00000000..55f61171 --- /dev/null +++ b/src/core/ao_beep.h @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BEEP_H_ +#define _AO_BEEP_H_ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +#endif /* _AO_BEEP_H_ */ diff --git a/src/core/ao_dbg.h b/src/core/ao_dbg.h new file mode 100644 index 00000000..181e6ec2 --- /dev/null +++ b/src/core/ao_dbg.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_DBG_H_ +#define _AO_DBG_H_ + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +#endif /* _AO_DBG_H_ */ diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h new file mode 100644 index 00000000..aa5ab60d --- /dev/null +++ b/src/core/ao_flight.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FLIGHT_H_ +#define _AO_FLIGHT_H_ + + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +#endif /* _AO_FLIGHT_H_ */ diff --git a/src/core/ao_led.h b/src/core/ao_led.h new file mode 100644 index 00000000..edc5fd1f --- /dev/null +++ b/src/core/ao_led.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LED_H_ +#define _AO_LED_H_ + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + +/* Turn on the specified LEDs */ +void +ao_led_on(AO_LED_TYPE colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(AO_LED_TYPE colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(AO_LED_TYPE colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(AO_LED_TYPE colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +void +ao_led_init(AO_LED_TYPE enable); + +#endif /* _AO_LED_H_ */ diff --git a/src/core/ao_log.h b/src/core/ao_log.h new file mode 100644 index 00000000..611c00d5 --- /dev/null +++ b/src/core/ao_log.h @@ -0,0 +1,196 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LOG_H_ +#define _AO_LOG_H_ + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#define AO_LOG_TEMP_VOLT 'T' +#define AO_LOG_DEPLOY 'D' +#define AO_LOG_STATE 'S' +#define AO_LOG_GPS_TIME 'G' +#define AO_LOG_GPS_LAT 'N' +#define AO_LOG_GPS_LON 'W' +#define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +#endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9e1b06d3..18ab85dd 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -15,7 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include +#include __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; diff --git a/src/core/ao_product.c b/src/core/ao_product.c index fb59580b..f79922f5 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -70,26 +70,26 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = /* Header functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x00, /* bDescriptor SubType Header */ LE_WORD(0x0110), /* CDC version 1.1 */ /* Call management functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x01, /* bDescriptor SubType Call Management */ 0x01, /* bmCapabilities = device handles call management */ 0x01, /* bDataInterface call management interface number */ /* ACM functional descriptor */ 0x04, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x02, /* bDescriptor SubType Abstract Control Management */ 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ /* Union functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x06, /* bDescriptor SubType Union Functional descriptor */ 0x00, /* bMasterInterface */ 0x01, /* bSlaveInterface0 */ diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 7c928792..eb90a4f8 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -16,6 +16,8 @@ */ #include "ao.h" +#include +#include #define BIT(i,x) ((x) ? (1 << (i)) : 0) #define MORSE1(a) (1 | BIT(3,a)) diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h new file mode 100644 index 00000000..fb0e69e8 --- /dev/null +++ b/src/core/ao_sample.h @@ -0,0 +1,137 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SAMPLE_H_ +#define _AO_SAMPLE_H_ + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +#endif /* _AO_SAMPLE_H_ */ diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h new file mode 100644 index 00000000..53aa8a89 --- /dev/null +++ b/src/core/ao_serial.h @@ -0,0 +1,86 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SERIAL_H_ +#define _AO_SERIAL_H_ + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +#if HAS_SERIAL_0 +extern volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +char +ao_serial0_getchar(void); + +void +ao_serial0_putchar(char c); + +void +ao_serial0_drain(void); + +void +ao_serial0_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_1 +extern volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial1_tx_fifo; + +char +ao_serial1_getchar(void); + +char +ao_serial1_pollchar(void); + +void +ao_serial1_putchar(char c); + +void +ao_serial1_drain(void); + +void +ao_serial1_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_2 +extern volatile __xdata struct ao_fifo ao_serial2_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial2_tx_fifo; + +char +ao_serial2_getchar(void); + +char +ao_serial2_pollchar(void); + +void +ao_serial2_putchar(char c); + +void +ao_serial2_drain(void); + +void +ao_serial2_set_speed(uint8_t speed); +#endif + +void +ao_serial_init(void); + +#endif /* _AO_SERIAL_H_ */ diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 2967e705..18fa913e 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,6 +21,12 @@ * Basic I/O functions to support SDCC stdio package */ +#ifdef SERIAL_STDIN_PORT +#define USE_SERIAL_STDIN 1 +#else +#define USE_SERIAL_STDIN 0 +#endif + #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index ff4747d0..66394e01 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include uint8_t ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h new file mode 100644 index 00000000..873fe097 --- /dev/null +++ b/src/core/ao_storage.h @@ -0,0 +1,84 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_STORAGE_H_ +#define _AO_STORAGE_H_ + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +#endif /* _AO_STORAGE_H_ */ diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h new file mode 100644 index 00000000..e051db93 --- /dev/null +++ b/src/core/ao_usb.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +ao_usb_init(void); + +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_CONTROL_SIZE 32 + +#define AO_USB_INT_EP 1 +#define AO_USB_INT_SIZE 8 + +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +/* + * USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define AO_USB_CS_INTERFACE 0x24 +#define AO_USB_CS_ENDPOINT 0x25 + +#define AO_USB_SET_LINE_CODING 0x20 +#define AO_USB_GET_LINE_CODING 0x21 +#define AO_USB_SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 5eb78815..f193ac8e 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -17,6 +17,13 @@ #include "ao.h" +#ifndef ao_serial_btm_getchar +#define ao_serial_btm_putchar ao_serial1_putchar +#define ao_serial_btm_pollchar ao_serial1_pollchar +#define ao_serial_btm_set_speed ao_serial1_set_speed +#define ao_serial_btm_drain ao_serial1_drain +#endif + int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -80,9 +87,9 @@ ao_btm_speed(void) { ao_cmd_decimal(); if (ao_cmd_lex_u32 == 57600) - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_57600); else if (ao_cmd_lex_u32 == 19200) - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); else ao_cmd_status = ao_cmd_syntax_error; } @@ -104,8 +111,6 @@ __code struct ao_cmds ao_btm_cmds[] = { #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; - /* * Read a line of data from the serial port, truncating * it after a few characters. @@ -119,7 +124,7 @@ ao_btm_get_line(void) for (;;) { - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + while ((c = ao_serial_btm_pollchar()) != AO_READ_AGAIN) { ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; @@ -128,7 +133,7 @@ ao_btm_get_line(void) } for (c = 0; c < 10; c++) { ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) + if (!ao_fifo_empty(ao_serial1_rx_fifo)) break; } if (c == 10) @@ -168,7 +173,7 @@ void ao_btm_putchar(char c) { ao_btm_log_out_char(c); - ao_serial_putchar(c); + ao_serial_btm_putchar(c); ao_delay(1); } @@ -229,8 +234,8 @@ ao_btm_set_name(void) uint8_t ao_btm_try_speed(uint8_t speed) { - ao_serial_set_speed(speed); - ao_btm_drain(); + ao_serial_btm_set_speed(speed); + ao_serial_btm_drain(); (void) ao_btm_cmd("\rATE0\rATQ0\r"); if (ao_btm_cmd("AT\r") == 1) return 1; @@ -274,8 +279,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, + ao_btm_stdio = ao_add_stdio(ao_serial_btm_pollchar, + ao_serial_btm_putchar, NULL); ao_btm_echo(0); @@ -341,7 +346,8 @@ void ao_btm_init (void) { ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); #if BT_LINK_ON_P1 /* diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c index f2abbf84..91fc948b 100644 --- a/src/drivers/ao_gps_sirf.c +++ b/src/drivers/ao_gps_sirf.c @@ -124,7 +124,13 @@ static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; static __pdata uint16_t ao_sirf_cksum; static __pdata uint16_t ao_sirf_len; -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) +#ifndef ao_sirf_getchar +#define ao_sirf_getchar ao_serial1_getchar +#define ao_sirf_putchar ao_serial1_putchar +#define ao_sirf_set_speed ao_serial1_set_speed +#endif + +#define ao_sirf_byte() ((uint8_t) ao_sirf_getchar()) static uint8_t data_byte(void) { @@ -283,15 +289,15 @@ static void ao_gps_setup(void) __reentrant { uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_sirf_set_speed(AO_SERIAL_SPEED_4800); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); for (k = 0; k < 3; k++) for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_sirf_putchar(ao_gps_set_nmea[i]); + ao_sirf_set_speed(AO_SERIAL_SPEED_57600); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); } static const char ao_gps_set_message_rate[] = { @@ -307,16 +313,16 @@ ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant uint8_t i; for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); + ao_sirf_putchar(ao_gps_set_message_rate[i]); + ao_sirf_putchar(msg); + ao_sirf_putchar(rate); cksum = 0xa6 + msg + rate; for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); + ao_sirf_putchar(0); + ao_sirf_putchar((cksum >> 8) & 0x7f); + ao_sirf_putchar(cksum & 0xff); + ao_sirf_putchar(0xb0); + ao_sirf_putchar(0xb3); } static const uint8_t sirf_disable[] = { @@ -338,7 +344,7 @@ ao_gps(void) __reentrant for (k = 0; k < 5; k++) { for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); + ao_sirf_putchar(ao_gps_config[i]); for (i = 0; i < sizeof (sirf_disable); i++) ao_sirf_set_message_rate(sirf_disable[i], 0); ao_sirf_set_message_rate(41, 1); diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 39e36cc8..84616a05 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -20,15 +20,15 @@ #endif #ifndef ao_gps_getchar -#define ao_gps_getchar ao_serial_getchar +#define ao_gps_getchar ao_serial1_getchar #endif #ifndef ao_gps_putchar -#define ao_gps_putchar ao_serial_putchar +#define ao_gps_putchar ao_serial1_putchar #endif #ifndef ao_gps_set_speed -#define ao_gps_set_speed ao_serial_set_speed +#define ao_gps_set_speed ao_serial1_set_speed #endif __xdata uint8_t ao_gps_mutex; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 1ebb1480..fa9db98b 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_product.h" +#include "ao_flight.h" struct ao_companion_command ao_companion_command; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e4e5def6..f761e5c3 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -61,6 +61,8 @@ #define ao_gps_putchar ao_serial3_putchar #define ao_gps_set_speed ao_serial3_set_speed +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 #define HAS_USB 1 #define HAS_BEEP 1 diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 97c9d792..46c63418 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -17,7 +17,9 @@ #include "ao.h" +#if HAS_LOG __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 8875ff48..963c7be4 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include #include static __xdata struct ao_telemetry_sensor ao_tel_sensor; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index adb6eb94..62af86f7 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -181,8 +181,6 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); -#define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) - char ao_serial1_getchar(void); diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 3cebc094..406da9fb 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -249,7 +249,7 @@ ao_serial2_set_speed(uint8_t speed) struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); } char ao_serial3_getchar(void) diff --git a/src/stm/ao_usb.h b/src/stm/ao_usb.h deleted file mode 100644 index d3129d34..00000000 --- a/src/stm/ao_usb.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_INT_SIZE 8 -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 5a447d43..586f1e33 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -717,17 +717,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h index a96c6f2b..3305719a 100644 --- a/src/teleballoon-v1.1/ao_pins.h +++ b/src/teleballoon-v1.1/ao_pins.h @@ -30,7 +30,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -127,10 +126,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2f664fcb..2ac7e747 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -85,8 +85,10 @@ load: $(PROG).hex 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 - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index be99f10d..10e4a2a3 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -22,7 +22,8 @@ INC = \ ao.h \ ao_arch.h \ ao_usb.h \ - ao_pins.h + ao_pins.h \ + ao_product.h # # Common AltOS sources @@ -96,8 +97,10 @@ load: $(PROG).hex 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 - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index 44780476..c1f45f37 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -54,7 +54,6 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ - ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7ff859af..e6e19f67 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,7 +23,7 @@ ao_ardu_serial_recv(void) char c; for (;;) { - if (ao_fifo_empty(ao_usart0_rx_fifo)) + if (ao_fifo_empty(ao_serial0_rx_fifo)) flush(); c = ao_serial0_getchar(); putchar (c); @@ -35,6 +35,5 @@ static __xdata struct ao_task ao_ardu_serial_recv_task; void ao_ardu_serial_init (void) { - ao_serial0_init(); ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); } diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index a907e2a5..701e25fc 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -26,14 +26,14 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_0 1 #define HAS_SERIAL_0_ALT_1 0 #define HAS_SERIAL_0_ALT_2 1 #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 - #define HAS_EEPROM 0 + #define HAS_EEPROM 1 #define HAS_LOG 0 #define USE_INTERNAL_FLASH 1 #define HAS_BTM 1 @@ -128,10 +128,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index fd12ce7a..4c32817a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -17,7 +17,9 @@ #include "ao.h" +#if 0 __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) @@ -43,6 +45,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_serial_init(); ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/teleterra-v0.1/ao_pins.h b/src/teleterra-v0.1/ao_pins.h index 33de055e..ba7177af 100644 --- a/src/teleterra-v0.1/ao_pins.h +++ b/src/teleterra-v0.1/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -124,10 +123,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 29b97385..2bea4e04 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -139,10 +138,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 93d7a9ab..4d4012df 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -317,7 +317,7 @@ static uint8_t sirf_in_message[4096]; static int sirf_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -351,7 +351,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -388,7 +388,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 1 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index a78fae0f..88bed305 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -319,7 +319,7 @@ static uint8_t skytraq_in_message[4096]; static int skytraq_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -354,7 +354,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -392,7 +392,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 2 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; -- cgit v1.2.3 From 2b4a53342980618b193cbee5b803e56f7c937893 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 09:36:00 -0700 Subject: altos: ao_telelaunch.c got left in src directory Should live in product/ao_telelaunch.c Signed-off-by: Keith Packard --- src/ao_telelaunch.c | 46 --------------------------------------------- src/product/ao_telelaunch.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 46 deletions(-) delete mode 100644 src/ao_telelaunch.c create mode 100644 src/product/ao_telelaunch.c diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c deleted file mode 100644 index 506431de..00000000 --- a/src/ao_telelaunch.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_cmd_init(); - ao_spi_init(); - ao_storage_init(); - ao_usb_init(); - ao_radio_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_aes_init(); - ao_radio_cmac_init(); - ao_launch_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/product/ao_telelaunch.c b/src/product/ao_telelaunch.c new file mode 100644 index 00000000..506431de --- /dev/null +++ b/src/product/ao_telelaunch.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_aes_init(); + ao_radio_cmac_init(); + ao_launch_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 0667261e03b3fd403e97d02ea6204b007bb13f58 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 09:39:20 -0700 Subject: altos: Pull more interfaces out of ao.h and move to separate files This moves the aes, btm, companion, lcd and packet interfaces out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 199 +++------------------------------------- src/core/ao_aes.h | 69 ++++++++++++++ src/core/ao_btm.h | 36 ++++++++ src/core/ao_companion.h | 51 ++++++++++ src/core/ao_lcd.h | 60 ++++++++++++ src/core/ao_log_telescience.c | 2 + src/core/ao_packet.h | 88 ++++++++++++++++++ src/drivers/ao_pyro_slave.c | 5 +- src/drivers/ao_science_slave.c | 1 + src/product/Makefile.telelaunch | 2 - src/teleterra-v0.2/ao_pins.h | 1 + 11 files changed, 323 insertions(+), 191 deletions(-) create mode 100644 src/core/ao_aes.h create mode 100644 src/core/ao_btm.h create mode 100644 src/core/ao_companion.h create mode 100644 src/core/ao_lcd.h create mode 100644 src/core/ao_packet.h diff --git a/src/core/ao.h b/src/core/ao.h index 28d0ba87..27b9c5c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -900,201 +900,26 @@ struct ao_fifo { #define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) #define ao_fifo_empty(f) ((f).insert == (f).remove) -/* - * ao_packet.c - * - * Packet-based command interface - */ - -#define AO_PACKET_MAX 64 -#define AO_PACKET_SYN (uint8_t) 0xff - -struct ao_packet { - uint8_t addr; - uint8_t len; - uint8_t seq; - uint8_t ack; - uint8_t d[AO_PACKET_MAX]; - uint8_t callsign[AO_MAX_CALLSIGN]; -}; - -struct ao_packet_recv { - struct ao_packet packet; - int8_t rssi; - uint8_t status; -}; - -extern __xdata struct ao_packet_recv ao_rx_packet; -extern __xdata struct ao_packet ao_tx_packet; -extern __xdata struct ao_task ao_packet_task; -extern __xdata uint8_t ao_packet_enable; -extern __xdata uint8_t ao_packet_master_sleeping; -extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -void -ao_packet_send(void); - -uint8_t -ao_packet_recv(void); - -void -ao_packet_flush(void); - -void -ao_packet_putchar(char c) __reentrant; - -char -ao_packet_pollchar(void) __critical; - -/* ao_packet_master.c */ - -void -ao_packet_master_init(void); - -/* ao_packet_slave.c */ - -void -ao_packet_slave_start(void); - -void -ao_packet_slave_stop(void); - -void -ao_packet_slave_init(uint8_t enable); - -/* ao_btm.c */ - -/* If bt_link is on P2, this interrupt is shared by USB, so the USB - * code calls this function. Otherwise, it's a regular ISR. - */ - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 +#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE +#include #endif - ; - -void -ao_btm_init(void); - -/* ao_companion.c */ - -#define AO_COMPANION_SETUP 1 -#define AO_COMPANION_FETCH 2 -#define AO_COMPANION_NOTIFY 3 - -struct ao_companion_command { - uint8_t command; - uint8_t flight_state; - uint16_t tick; - uint16_t serial; - uint16_t flight; -}; - -struct ao_companion_setup { - uint16_t board_id; - uint16_t board_id_inverse; - uint8_t update_period; - uint8_t channels; -}; - -extern __pdata uint8_t ao_companion_running; -extern __xdata uint8_t ao_companion_mutex; -extern __xdata struct ao_companion_command ao_companion_command; -extern __xdata struct ao_companion_setup ao_companion_setup; -extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; - -void -ao_companion_init(void); - -/* ao_lcd.c */ - -void -ao_lcd_putchar(uint8_t d); - -void -ao_lcd_putstring(char *string); - -void -ao_lcd_contrast_set(uint8_t contrast); - -void -ao_lcd_clear(void); - -void -ao_lcd_cursor_on(void); - -void -ao_lcd_cursor_off(void); - -#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) - -void -ao_lcd_goto(uint8_t addr); - -void -ao_lcd_start(void); - -void -ao_lcd_init(void); - -/* ao_lcd_port.c */ - -void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); - -void -ao_lcd_port_init(void); - -/* ao_aes.c */ -extern __xdata uint8_t ao_aes_mutex; +#if HAS_BTM +#include +#endif -/* AES keys and blocks are 128 bits */ +#if HAS_COMPANION +#include +#endif -enum ao_aes_mode { - ao_aes_mode_cbc_mac -}; +#if HAS_LCD +#include +#endif #if HAS_AES -void -ao_aes_isr(void) __interrupt 4; +#include #endif -void -ao_aes_set_mode(enum ao_aes_mode mode); - -void -ao_aes_set_key(__xdata uint8_t *in); - -void -ao_aes_zero_iv(void); - -void -ao_aes_run(__xdata uint8_t *in, - __xdata uint8_t *out); - -void -ao_aes_init(void); - -/* ao_radio_cmac.c */ - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; - -#define AO_RADIO_CMAC_OK 0 -#define AO_RADIO_CMAC_LEN_ERROR -1 -#define AO_RADIO_CMAC_CRC_ERROR -2 -#define AO_RADIO_CMAC_MAC_ERROR -3 -#define AO_RADIO_CMAC_TIMEOUT -4 - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; - -void -ao_radio_cmac_init(void); - /* ao_launch.c */ struct ao_launch_command { diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h new file mode 100644 index 00000000..7f67374d --- /dev/null +++ b/src/core/ao_aes.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_AES_H_ +#define _AO_AES_H_ + +/* ao_aes.c */ + +extern __xdata uint8_t ao_aes_mutex; + +/* AES keys and blocks are 128 bits */ + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_zero_iv(void); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +void +ao_aes_init(void); + +/* ao_radio_cmac.c */ + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + +void +ao_radio_cmac_init(void); + +#endif /* _AO_AES_H_ */ diff --git a/src/core/ao_btm.h b/src/core/ao_btm.h new file mode 100644 index 00000000..484e5d7f --- /dev/null +++ b/src/core/ao_btm.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BTM_H_ +#define _AO_BTM_H_ + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; +void +ao_btm_init(void); + +#endif /* _AO_BTM_H_ */ diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h new file mode 100644 index 00000000..47e0acf5 --- /dev/null +++ b/src/core/ao_companion.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_COMPANION_H_ +#define _AO_COMPANION_H_ + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + +#endif /* _AO_COMPANION_H_ */ diff --git a/src/core/ao_lcd.h b/src/core/ao_lcd.h new file mode 100644 index 00000000..f7e1391a --- /dev/null +++ b/src/core/ao_lcd.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCD_H_ +#define _AO_LCD_H_ + +/* ao_lcd.c */ + +void +ao_lcd_putchar(uint8_t d); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + +void +ao_lcd_init(void); + +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); + +void +ao_lcd_port_init(void); + +#endif /* _AO_LCD_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index 31eda381..ae045281 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -17,6 +17,8 @@ #include "ao.h" #include "ao_product.h" +#include "ao_log.h" +#include "ao_companion.h" static uint8_t ao_log_adc_pos; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h new file mode 100644 index 00000000..618ccda4 --- /dev/null +++ b/src/core/ao_packet.h @@ -0,0 +1,88 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PACKET_H_ +#define _AO_PACKET_H_ + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +#if PACKET_HAS_MASTER +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); +#endif + +#if PACKET_HAS_SLAVE +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +#endif + +#endif /* _AO_PACKET_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 5ef42b5a..5a8ab922 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -15,8 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" -#include "ao_product.h" +#include +#include +#include struct ao_companion_command ao_companion_command; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index fa9db98b..a86b5151 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -18,6 +18,7 @@ #include "ao.h" #include "ao_product.h" #include "ao_flight.h" +#include "ao_companion.h" struct ao_companion_command ao_companion_command; diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 8aab50e0..688ac5f3 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -39,8 +39,6 @@ CC1111_SRC = \ ao_ignite.c \ ao_intflash.c \ ao_led.c \ - ao_packet.c \ - ao_packet_slave.c \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 2bea4e04..bcabdfee 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,6 +25,7 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 + #define HAS_LCD 1 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 -- cgit v1.2.3 From 3c67543f3e5fddc6a8850f33ac519ccd55b607f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:34:52 -0700 Subject: altos: Set USB Interrupt endpoint interval to maximum allowed We don't ever send anything over this channel, so there's no sense asking the host to poll it very often. Signed-off-by: Keith Packard --- src/core/ao_product.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao_product.c b/src/core/ao_product.c index f79922f5..67ec6793 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -100,7 +100,7 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = AO_USB_INT_EP|0x80, /* bEndpointAddress */ 0x03, /* bmAttributes = intr */ LE_WORD(8), /* wMaxPacketSize */ - 0x0A, /* bInterval */ + 0xff, /* bInterval */ /* Data class interface descriptor */ 0x09, -- cgit v1.2.3 From 1a84d34fa08f43a5f79b1a5f8d8de7674d04647d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:35:46 -0700 Subject: altos: Check all USE_SERIAL_*_STDIO when computing AO_NUM_STDIOS AO_NUM_STDIOS is allocated based on the total number of possible stdio values. Now that multiple serial stdio are possible, make sure to check all of them. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 18fa913e..9b4ea473 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,11 +21,47 @@ * Basic I/O functions to support SDCC stdio package */ -#ifdef SERIAL_STDIN_PORT -#define USE_SERIAL_STDIN 1 -#else -#define USE_SERIAL_STDIN 0 +#ifndef USE_SERIAL_0_STDIN +#define USE_SERIAL_0_STDIN 0 #endif +#ifndef USE_SERIAL_1_STDIN +#define USE_SERIAL_1_STDIN 0 +#endif +#ifndef USE_SERIAL_2_STDIN +#define USE_SERIAL_2_STDIN 0 +#endif +#ifndef USE_SERIAL_3_STDIN +#define USE_SERIAL_3_STDIN 0 +#endif +#ifndef USE_SERIAL_4_STDIN +#define USE_SERIAL_4_STDIN 0 +#endif +#ifndef USE_SERIAL_5_STDIN +#define USE_SERIAL_5_STDIN 0 +#endif +#ifndef USE_SERIAL_6_STDIN +#define USE_SERIAL_6_STDIN 0 +#endif +#ifndef USE_SERIAL_7_STDIN +#define USE_SERIAL_7_STDIN 0 +#endif +#ifndef USE_SERIAL_8_STDIN +#define USE_SERIAL_8_STDIN 0 +#endif +#ifndef USE_SERIAL_9_STDIN +#define USE_SERIAL_9_STDIN 0 +#endif + +#define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ + USE_SERIAL_1_STDIN | \ + USE_SERIAL_2_STDIN | \ + USE_SERIAL_3_STDIN | \ + USE_SERIAL_4_STDIN | \ + USE_SERIAL_5_STDIN | \ + USE_SERIAL_6_STDIN | \ + USE_SERIAL_7_STDIN | \ + USE_SERIAL_8_STDIN | \ + USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) -- cgit v1.2.3 From e9f6fca7cfe796cbd86ae9d8f1ebe31bba7251db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:38:29 -0700 Subject: altos: Correct STM USB driver Configure endpoint registers correctly now. Restructure code to make sure we send the right IN packets. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 579 ++++++++++++++++++++++++++------------------------- 1 file changed, 293 insertions(+), 286 deletions(-) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 586f1e33..223fdeaa 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -21,6 +21,7 @@ #define USB_DEBUG 0 #define USB_DEBUG_DATA 0 +#define USB_ECHO 0 #if USB_DEBUG #define debug(format, args...) printf(format, ## args); @@ -45,34 +46,68 @@ struct ao_usb_setup { } ao_usb_setup; static uint8_t ao_usb_ep0_state; -static const uint8_t * ao_usb_ep0_in_data; -static uint8_t ao_usb_ep0_in_len; -static uint8_t ao_usb_ep0_in_pending; + +/* Pending EP0 IN data */ +static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ +static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ + +/* Temp buffer for smaller EP0 in data */ static uint8_t ao_usb_ep0_in_buf[2]; -static uint8_t ao_usb_ep0_out_len; + +/* Pending EP0 OUT data */ static uint8_t *ao_usb_ep0_out_data; +static uint8_t ao_usb_ep0_out_len; + +/* + * Objects allocated in special USB memory + */ + +/* Buffer description tables */ static union stm_usb_bdt *ao_usb_bdt; +/* USB address of end of allocated storage */ static uint16_t ao_usb_sram_addr; + +/* Pointer to ep0 tx/rx buffers in USB memory */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +/* Pointer to bulk data tx/rx buffers in USB memory */ +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; + static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -#define AO_USB_INT_EPR 1 -#define AO_USB_OUT_EPR 2 -#define AO_USB_IN_EPR 3 - /* - * Pointers into the USB packet buffer area + * End point register indices */ -static uint32_t *ao_usb_ep0_tx_buffer; -static uint32_t *ao_usb_ep0_rx_buffer; -static uint32_t *ao_usb_in_tx_buffer; -static uint32_t *ao_usb_out_rx_buffer; +#define AO_USB_CONTROL_EPR 0 +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 +/* Marks when we don't need to send an IN packet. + * This happens only when the last IN packet is not full, + * otherwise the host will expect to keep seeing packets. + * Send a zero-length packet as required + */ static uint8_t ao_usb_in_flushed; + +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ static uint8_t ao_usb_in_pending; + +/* Marks when an OUT packet has been received by the hardware + * but not pulled to the shadow buffer. + */ static uint8_t ao_usb_out_avail; static uint8_t ao_usb_running; static uint8_t ao_usb_configuration; @@ -139,10 +174,104 @@ ao_usb_set_address(uint8_t address) ao_usb_address_pending = 0; } +/* + * Write these values to preserve register contents under HW changes + */ + +#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) + +#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ + (1 << STM_USB_EPR_EP_KIND) | \ + (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) + +/* + * Set the state of the specified endpoint register to a new + * value. This is tricky because the bits toggle where the new + * value is one, and we need to write invariant values in other + * spots of the register. This hardware is strange... + */ +static void +_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + uint32_t epr_write, epr_old; + + epr_old = epr_write = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, + stat_tx << STM_USB_EPR_STAT_TX); + stm_usb.epr[ep] = epr_write; +} + +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + cli(); + _ao_usb_set_stat_tx(ep, stat_tx); + sei(); +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, + stat_rx << STM_USB_EPR_STAT_RX); + stm_usb.epr[ep] = epr_write; + sei(); +} + /* * Set just endpoint 0, for use during startup */ +static void +ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +{ + uint32_t epr; + cli(); + epr = stm_usb.epr[ep]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (stat_rx << STM_USB_EPR_STAT_RX)) | + (type << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (stat_tx << STM_USB_EPR_STAT_TX)) | + (addr << STM_USB_EPR_EA)); + stm_usb.epr[ep] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + ep, epr, stm_usb.epr[ep]); +} + static void ao_usb_set_ep0(void) { @@ -170,44 +299,17 @@ ao_usb_set_ep0(void) ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_CONTROL_SIZE; - cli(); - epr = stm_usb.epr[0]; - epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_CONTROL_EP << STM_USB_EPR_EA)); - stm_usb.epr[0] = epr; - sei(); - debug ("epr 0 now %x\n", stm_usb.epr[0]); + ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_NAK); /* Clear all of the other endpoints */ for (e = 1; e < 8; e++) { - cli(); - epr = stm_usb.epr[e]; - epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | - (0 << STM_USB_EPR_EA)); - stm_usb.epr[e] = epr; - sei(); + ao_usb_init_ep(e, 0, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_DISABLED); } ao_usb_set_address(0); @@ -226,26 +328,12 @@ ao_usb_set_configuration(void) ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_INT_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_INT_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_INT_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_INT_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_INT_EPR, epr, stm_usb.epr[AO_USB_INT_EPR]); - + ao_usb_init_ep(AO_USB_INT_EPR, + AO_USB_INT_EP, + STM_USB_EPR_EP_TYPE_INTERRUPT, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + /* Set up the OUT end point */ ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | @@ -253,25 +341,11 @@ ao_usb_set_configuration(void) ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_OUT_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_OUT_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | - (AO_USB_OUT_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_OUT_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_OUT_EPR, epr, stm_usb.epr[AO_USB_OUT_EPR]); + ao_usb_init_ep(AO_USB_OUT_EPR, + AO_USB_OUT_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_DISABLED); /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; @@ -279,59 +353,21 @@ ao_usb_set_configuration(void) ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_IN_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_IN_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_IN_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_IN_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_IN_EPR, epr, stm_usb.epr[AO_USB_IN_EPR]); + ao_usb_init_ep(AO_USB_IN_EPR, + AO_USB_IN_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + ao_usb_running = 1; } static uint16_t control_count; +static uint16_t int_count; static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; -/* - * Write these values to preserve register contents under HW changes - */ - -#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ - (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ - (1 << STM_USB_EPR_CTR_TX) | \ - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ - (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) - -#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ - (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ - (1 << STM_USB_EPR_CTR_TX) | \ - (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) - -/* - * These bits are purely under sw control, so preserve them in the - * register by re-writing what was read - */ -#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ - (1 << STM_USB_EPR_EP_KIND) | \ - (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) - void stm_usb_lp_isr(void) { @@ -379,6 +415,11 @@ stm_usb_lp_isr(void) ao_wakeup(&ao_usb_in_pending); } break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK); + break; } return; } @@ -391,12 +432,6 @@ stm_usb_lp_isr(void) } } -void -stm_usb_hp_isr(void) -{ - stm_usb_lp_isr(); -} - void stm_usb_fs_wkup(void) { @@ -404,42 +439,6 @@ stm_usb_fs_wkup(void) stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; - -/* Walk through the list of descriptors and find a match - */ -static void -ao_usb_get_descriptor(uint16_t value) -{ - const uint8_t *descriptor; - uint8_t type = value >> 8; - uint8_t index = value; - - descriptor = ao_usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == AO_USB_DESC_CONFIGURATION) - ao_usb_ep0_in_len = descriptor[2]; - else - ao_usb_ep0_in_len = descriptor[0]; - ao_usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -static void -ao_usb_ep0_set_in_pending(uint8_t in_pending) -{ - ao_usb_ep0_in_pending = in_pending; - -#if 0 - if (in_pending) - ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ -#endif -} - /* The USB memory holds 16 bit values on 32 bit boundaries * and must be accessed only in 32 bit units. Sigh. */ @@ -525,28 +524,6 @@ ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) } } -static inline void -ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { - uint32_t epr_write, epr_old, epr_new, epr_want; - - cli(); - epr_write = epr_old = stm_usb.epr[ep]; - epr_write &= STM_USB_EPR_PRESERVE_MASK; - epr_write |= STM_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, - stat_tx << STM_USB_EPR_STAT_TX); - stm_usb.epr[ep] = epr_write; - epr_new = stm_usb.epr[ep]; - sei(); - epr_want = (epr_old & ~(STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) | - (stat_tx << STM_USB_EPR_STAT_TX); - if (epr_new != epr_want) { - debug ("**** set_stat_tx to %x. old %08x want %08x write %08x new %08x\n", - stat_tx, epr_old, epr_want, epr_write, epr_new); - } -} - /* Send an IN data packet */ static void ao_usb_ep0_flush(void) @@ -556,52 +533,27 @@ ao_usb_ep0_flush(void) /* Check to see if the endpoint is still busy */ if (ao_usb_epr_stat_tx(stm_usb.epr[0]) == STM_USB_EPR_STAT_TX_VALID) { debug("EP0 not accepting IN data\n"); - ao_usb_ep0_set_in_pending(1); - } else { - this_len = ao_usb_ep0_in_len; - if (this_len > AO_USB_CONTROL_SIZE) - this_len = AO_USB_CONTROL_SIZE; - - ao_usb_ep0_in_len -= this_len; - - /* Set IN interrupt enable */ - if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) - ao_usb_ep0_set_in_pending(0); - else - ao_usb_ep0_set_in_pending(1); - - debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); - debug_data ("\n"); - ao_usb_ep0_in_data += this_len; - - /* Mark the endpoint as TX valid to send the packet */ - ao_usb_bdt[0].single.count_tx = this_len; - ao_usb_set_stat_tx(0, STM_USB_EPR_STAT_TX_VALID); - debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[0]); + return; } -} -static inline void -ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - uint32_t epr_write, epr_old, epr_new, epr_want; + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; - cli(); - epr_write = epr_old = stm_usb.epr[ep]; - epr_write &= STM_USB_EPR_PRESERVE_MASK; - epr_write |= STM_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, - stat_rx << STM_USB_EPR_STAT_RX); - stm_usb.epr[ep] = epr_write; - epr_new = stm_usb.epr[ep]; - sei(); - epr_want = (epr_old & ~(STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX)) | - (stat_rx << STM_USB_EPR_STAT_RX); - if (epr_new != epr_want) { - debug ("**** set_stat_rx to %x. old %08x want %08x write %08x new %08x\n", - stat_rx, epr_old, epr_want, epr_write, epr_new); - } + if (this_len < AO_USB_CONTROL_SIZE) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_len -= this_len; + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; + ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, STM_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[AO_USB_CONTROL_EPR]); } /* Read data from the ep0 OUT fifo */ @@ -624,39 +576,87 @@ ao_usb_ep0_fill(void) ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID); } -void -ao_usb_ep0_queue_byte(uint8_t a) +static void +ao_usb_ep0_in_reset(void) +{ + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; +} + +static void +ao_usb_ep0_in_queue_byte(uint8_t a) { - ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; + if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf)) + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_in_set(const uint8_t *data, uint8_t len) +{ + ao_usb_ep0_in_data = data; + ao_usb_ep0_in_len = len; +} + +static void +ao_usb_ep0_out_set(uint8_t *data, uint8_t len) +{ + ao_usb_ep0_out_data = data; + ao_usb_ep0_out_len = len; +} + +static void +ao_usb_ep0_in_start(uint8_t max) +{ + /* Don't send more than asked for */ + if (ao_usb_ep0_in_len > max) + ao_usb_ep0_in_len = max; + ao_usb_ep0_flush(); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + uint8_t len; + if (type == AO_USB_DESC_CONFIGURATION) + len = descriptor[2]; + else + len = descriptor[0]; + ao_usb_ep0_in_set(descriptor, len); + break; + } + descriptor += descriptor[0]; + } } static void ao_usb_ep0_setup(void) { /* Pull the setup packet out of the fifo */ - ao_usb_ep0_out_data = (uint8_t *) &ao_usb_setup; - ao_usb_ep0_out_len = 8; + ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8); ao_usb_ep0_fill(); if (ao_usb_ep0_out_len != 0) { debug ("invalid setup packet length\n"); return; } - /* Figure out how to ACK the setup packet */ - if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } else { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } + if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + + ao_usb_ep0_in_reset(); - ao_usb_ep0_in_data = ao_usb_ep0_in_buf; - ao_usb_ep0_in_len = 0; switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { case AO_USB_TYPE_STANDARD: debug ("Standard setup packet\n"); @@ -666,8 +666,8 @@ ao_usb_ep0_setup(void) switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: debug ("get status\n"); - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_SET_ADDRESS: debug ("set address %d\n", ao_usb_setup.value); @@ -680,7 +680,7 @@ ao_usb_ep0_setup(void) break; case AO_USB_REQ_GET_CONFIGURATION: debug ("get configuration %d\n", ao_usb_configuration); - ao_usb_ep0_queue_byte(ao_usb_configuration); + ao_usb_ep0_in_queue_byte(ao_usb_configuration); break; case AO_USB_REQ_SET_CONFIGURATION: ao_usb_configuration = ao_usb_setup.value; @@ -693,11 +693,11 @@ ao_usb_ep0_setup(void) debug ("Interface setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_GET_INTERFACE: - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_SET_INTERFACE: break; @@ -707,8 +707,8 @@ ao_usb_ep0_setup(void) debug ("Endpoint setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; } break; @@ -719,24 +719,23 @@ ao_usb_ep0_setup(void) switch (ao_usb_setup.request) { case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); - ao_usb_ep0_out_len = 7; - ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; + ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7); break; case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); - ao_usb_ep0_in_len = 7; - ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7); break; case AO_USB_SET_CONTROL_LINE_STATE: break; } break; } - if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { - if (ao_usb_setup.length < ao_usb_ep0_in_len) - ao_usb_ep0_in_len = ao_usb_setup.length; - ao_usb_ep0_flush(); - } + + /* If we're not waiting to receive data from the host, + * queue an IN response + */ + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_in_start(ao_usb_setup.length); } /* End point 0 receives all of the control messages. */ @@ -766,16 +765,24 @@ ao_usb_ep0(void) } if (receive & AO_USB_EP0_GOT_RX_DATA) { debug ("\tgot rx data\n"); - ao_usb_ep0_fill(); - ao_usb_ep0_set_in_pending(1); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); + } + } } if (receive & AO_USB_EP0_GOT_TX_ACK) { debug ("\tgot tx ack\n"); - ao_usb_ep0_flush(); - if (ao_usb_address_pending) { + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) ao_usb_set_address(ao_usb_address); - ao_usb_set_configuration(); - } + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); } } } @@ -982,7 +989,7 @@ ao_usb_enable(void) stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); } -#if USB_DEBUG +#if USB_ECHO struct ao_task ao_usb_echo_task; static void @@ -1001,8 +1008,8 @@ ao_usb_echo(void) static void ao_usb_irq(void) { - printf ("control: %d out: %d in: %d reset: %d\n", - control_count, out_count, in_count, reset_count); + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); } __code struct ao_cmds ao_usb_cmds[] = { @@ -1017,11 +1024,11 @@ ao_usb_init(void) debug ("ao_usb_init\n"); ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); -#if USB_DEBUG +#if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif ao_cmd_register(&ao_usb_cmds[0]); -#if !USB_DEBUG +#if !USB_ECHO ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif } -- cgit v1.2.3 From 9a8fec1b6d8f3346f988882ffb03d7d0e45b3c81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:00:32 -0700 Subject: altos: Clean up test scripts The flight test scripts were using invalid bash syntax. Clean that up and also switch the default flight directory to my new ~/misc/rockets/flights directory. Signed-off-by: Keith Packard --- src/test/run-one | 16 +++++++++++++--- src/test/run-tests | 10 +++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/test/run-one b/src/test/run-one index 7d0f95ae..8fa0787c 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -1,10 +1,20 @@ #!/bin/sh +DIR=~/misc/rockets/flights + for i in "$@"; do -./ao_flight_test "$i" > run-out.full -./ao_flight_test_baro "$i" > run-out.baro +case "$i" in + */*) + file="$i" + ;; + *) + file="$DIR/$i" + ;; +esac +./ao_flight_test "$file" > run-out.full +./ao_flight_test_baro "$file" > run-out.baro -#./ao_flight_test_accel "$i" > run-out.accel +#./ao_flight_test_accel "$file" > run-out.accel #"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ #"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ #"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ diff --git a/src/test/run-tests b/src/test/run-tests index 3e0cad3c..a8a8dc3f 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash -DIR=~/src/cc1111/flights +DIR=~/misc/rockets/flights bad_baro=0 bad_full=0 @@ -8,15 +8,15 @@ while read flight description; do if ./ao_flight_test_baro -s $DIR/$flight; then : else - ((bad_baro++)) + : $((bad_baro++)) fi if ./ao_flight_test -s $DIR/$flight; then : else - ((bad_full++)) + : $((bad_full++)) fi done < test-flights echo baro errors $bad_baro echo full errors $bad_full -((bad = bad_baro + bad_full)) +: $((bad = bad_baro + bad_full)) exit $bad \ No newline at end of file -- cgit v1.2.3 From 6cb744e305116a738b5d71686c6748f6f08c12ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:02:14 -0700 Subject: altos: Respect apogee lockout time in flight algorithm This prevents any apogee detection from occurring until the specified number of seconds after boost. This also prevents the switch from accel+baro to baro only mode in the Kalman filter. The test frame work is also changed to look for Apogee lockout: in the eeprom input file. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 11 +++++++++++ src/test/ao_flight_test.c | 4 ++++ 2 files changed, 15 insertions(+) diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 5e194638..494e656d 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -223,6 +223,17 @@ ao_flight(void) #endif case ao_flight_coast: + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + /* apogee detect: coast to drogue deploy: * * speed: < 0 diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 921d44e7..4a8625cf 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -184,6 +184,7 @@ struct ao_config { int16_t accel_plus_g; int16_t accel_minus_g; uint8_t pad_orientation; + uint16_t apogee_lockout; }; #define AO_PAD_ORIENTATION_ANTENNA_UP 0 @@ -523,6 +524,9 @@ ao_sleep(void *wchan) ao_config.accel_minus_g = atoi(words[5]); } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); + } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 && + strcmp(words[1], "lockout:") == 0) { + ao_config.apogee_lockout = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 5c8af6d35ebfc8fd896dfbf9928ec8f9dbfa531f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:05:28 -0700 Subject: altos: Remove debug printf from cc1111 check-stack script Signed-off-by: Keith Packard --- src/util/check-stack | 1 - 1 file changed, 1 deletion(-) diff --git a/src/util/check-stack b/src/util/check-stack index 7b62e460..f4cada2b 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -6,7 +6,6 @@ HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` FLASH_END=`awk '/ROM\/EPROM\/FLASH/ { print strtonum ($3)}' $MEM` -echo FLASH_END $FLASH_END if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' -- cgit v1.2.3 From b4ab9f5dfa9f2a50e0528acf0a1fdeaa1f9bc523 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 13:52:37 -0700 Subject: altosui: Read frequency from device while configuring ground station Missed this when adding the TD config UI. Signed-off-by: Keith Packard --- altosui/AltosConfigTD.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index 68f746b2..d3c452e1 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -144,6 +144,8 @@ public class AltosConfigTD implements ActionListener { get_int(line, "Radio channel:", radio_channel); if (get_int(line, "Radio cal:", radio_calibration)) System.out.printf("got radio cal %d\n", radio_calibration.get()); + if (get_int(line, "Frequency:", radio_frequency)) + System.out.printf("got radio freq %d\n", radio_frequency.get()); get_int(line, "Radio setting:", radio_setting); get_string(line,"software-version", version); get_string(line,"product", product); -- cgit v1.2.3 From cc305ea231ae22278abf91c0d9925f5992945369 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 13:53:36 -0700 Subject: altosui: Add apogee lockout configuration Provide suggested values of 5/10/15/20 seconds. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 7 +++ altosui/AltosConfigUI.java | 109 +++++++++++++++++++++++++++++++++------------ 2 files changed, 88 insertions(+), 28 deletions(-) diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index bb2665c2..58da405f 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -70,6 +70,7 @@ public class AltosConfig implements ActionListener { int_ref log_format; int_ref main_deploy; int_ref apogee_delay; + int_ref apogee_lockout; int_ref radio_channel; int_ref radio_calibration; int_ref flight_log_max; @@ -148,6 +149,7 @@ public class AltosConfig implements ActionListener { config_ui.set_version(version.get()); config_ui.set_main_deploy(main_deploy.get()); config_ui.set_apogee_delay(apogee_delay.get()); + config_ui.set_apogee_lockout(apogee_lockout.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); boolean max_enabled = true; @@ -188,6 +190,7 @@ public class AltosConfig implements ActionListener { get_int(line, "log-format", log_format); get_int(line, "Main deploy:", main_deploy); get_int(line, "Apogee delay:", apogee_delay); + get_int(line, "Apogee lockout:", apogee_lockout); get_int(line, "Radio channel:", radio_channel); get_int(line, "Radio cal:", radio_calibration); get_int(line, "Max flight log:", flight_log_max); @@ -232,6 +235,7 @@ public class AltosConfig implements ActionListener { log_format.set(Altos.AO_LOG_FORMAT_UNKNOWN); main_deploy.set(250); apogee_delay.set(0); + apogee_lockout.set(0); radio_channel.set(0); radio_setting.set(0); radio_frequency.set(0); @@ -285,6 +289,7 @@ public class AltosConfig implements ActionListener { start_serial(); serial_line.printf("c m %d\n", main_deploy.get()); serial_line.printf("c d %d\n", apogee_delay.get()); + serial_line.printf("c L %d\n", apogee_lockout.get()); if (!remote) serial_line.printf("c f %d\n", radio_calibration.get()); serial_line.set_radio_frequency(frequency, @@ -422,6 +427,7 @@ public class AltosConfig implements ActionListener { main_deploy.set(config_ui.main_deploy()); apogee_delay.set(config_ui.apogee_delay()); + apogee_lockout.set(config_ui.apogee_lockout()); radio_calibration.set(config_ui.radio_calibration()); set_frequency(config_ui.radio_frequency()); flight_log_max.set(config_ui.flight_log_max()); @@ -463,6 +469,7 @@ public class AltosConfig implements ActionListener { log_format = new int_ref(Altos.AO_LOG_FORMAT_UNKNOWN); main_deploy = new int_ref(250); apogee_delay = new int_ref(0); + apogee_lockout = new int_ref(0); radio_channel = new int_ref(0); radio_setting = new int_ref(0); radio_frequency = new int_ref(0); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 879605bc..b0cd7f27 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -43,6 +43,7 @@ public class AltosConfigUI JLabel serial_label; JLabel main_deploy_label; JLabel apogee_delay_label; + JLabel apogee_lockout_label; JLabel frequency_label; JLabel radio_calibration_label; JLabel radio_frequency_label; @@ -60,6 +61,7 @@ public class AltosConfigUI JLabel serial_value; JComboBox main_deploy_value; JComboBox apogee_delay_value; + JComboBox apogee_lockout_value; AltosFreqList radio_frequency_value; JTextField radio_calibration_value; JRadioButton radio_enable_value; @@ -84,6 +86,10 @@ public class AltosConfigUI "0", "1", "2", "3", "4", "5" }; + static String[] apogee_lockout_values = { + "0", "5", "10", "15", "20" + }; + static String[] flight_log_max_values = { "64", "128", "192", "256", "320", "384", "448", "512", "576", "640", @@ -179,6 +185,7 @@ public class AltosConfigUI owner = in_owner; GridBagConstraints c; + int row = 0; Insets il = new Insets(4,4,4,4); Insets ir = new Insets(4,4,4,4); @@ -188,7 +195,7 @@ public class AltosConfigUI /* Product */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 0; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -197,7 +204,7 @@ public class AltosConfigUI pane.add(product_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 0; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -205,10 +212,11 @@ public class AltosConfigUI c.insets = ir; product_value = new JLabel(""); pane.add(product_value, c); + row++; /* Version */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 1; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -218,7 +226,7 @@ public class AltosConfigUI pane.add(version_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 1; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -227,10 +235,11 @@ public class AltosConfigUI c.ipady = 5; version_value = new JLabel(""); pane.add(version_value, c); + row++; /* Serial */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 2; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -240,7 +249,7 @@ public class AltosConfigUI pane.add(serial_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 2; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -249,10 +258,11 @@ public class AltosConfigUI c.ipady = 5; serial_value = new JLabel(""); pane.add(serial_value, c); + row++; /* Main deploy */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 3; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -262,7 +272,7 @@ public class AltosConfigUI pane.add(main_deploy_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 3; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -274,10 +284,11 @@ public class AltosConfigUI main_deploy_value.addItemListener(this); pane.add(main_deploy_value, c); main_deploy_value.setToolTipText("Height above pad altitude to fire main charge"); + row++; /* Apogee delay */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 4; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -287,7 +298,7 @@ public class AltosConfigUI pane.add(apogee_delay_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 4; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -299,10 +310,37 @@ public class AltosConfigUI apogee_delay_value.addItemListener(this); pane.add(apogee_delay_value, c); apogee_delay_value.setToolTipText("Delay after apogee before charge fires"); + row++; + + /* Apogee lockout */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + apogee_lockout_label = new JLabel("Apogee Lockout(s):"); + pane.add(apogee_lockout_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = row; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + apogee_lockout_value = new JComboBox(apogee_lockout_values); + apogee_lockout_value.setEditable(true); + apogee_lockout_value.addItemListener(this); + pane.add(apogee_lockout_value, c); + apogee_lockout_value.setToolTipText("Time after boost while apogee detection is locked out"); + row++; /* Frequency */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 5; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -312,7 +350,7 @@ public class AltosConfigUI pane.add(radio_frequency_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 5; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -323,10 +361,11 @@ public class AltosConfigUI radio_frequency_value.addItemListener(this); pane.add(radio_frequency_value, c); radio_frequency_value.setToolTipText("Telemetry, RDF and packet frequency"); + row++; /* Radio Calibration */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 6; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -336,7 +375,7 @@ public class AltosConfigUI pane.add(radio_calibration_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 6; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -349,10 +388,11 @@ public class AltosConfigUI radio_calibration_value.setEnabled(false); pane.add(radio_calibration_value, c); set_radio_calibration_tool_tip(); + row++; /* Radio Enable */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 7; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -362,7 +402,7 @@ public class AltosConfigUI pane.add(radio_enable_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 7; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -373,10 +413,11 @@ public class AltosConfigUI radio_enable_value.addItemListener(this); pane.add(radio_enable_value, c); set_radio_enable_tool_tip(); + row++; /* Callsign */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -386,7 +427,7 @@ public class AltosConfigUI pane.add(callsign_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 8; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -397,10 +438,11 @@ public class AltosConfigUI callsign_value.getDocument().addDocumentListener(this); pane.add(callsign_value, c); callsign_value.setToolTipText("Callsign reported in telemetry data"); + row++; /* Flight log max */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 9; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -410,7 +452,7 @@ public class AltosConfigUI pane.add(flight_log_max_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 9; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -422,10 +464,11 @@ public class AltosConfigUI flight_log_max_value.addItemListener(this); pane.add(flight_log_max_value, c); set_flight_log_max_tool_tip(); + row++; /* Ignite mode */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 10; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -435,7 +478,7 @@ public class AltosConfigUI pane.add(ignite_mode_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 10; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -447,10 +490,11 @@ public class AltosConfigUI ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); set_ignite_mode_tool_tip(); + row++; /* Pad orientation */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 11; + c.gridx = 0; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -460,7 +504,7 @@ public class AltosConfigUI pane.add(pad_orientation_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 11; + c.gridx = 4; c.gridy = row; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -472,10 +516,11 @@ public class AltosConfigUI pad_orientation_value.addItemListener(this); pane.add(pad_orientation_value, c); set_pad_orientation_tool_tip(); + row++; /* Buttons */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 12; + c.gridx = 0; c.gridy = row; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -486,7 +531,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 12; + c.gridx = 2; c.gridy = row; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -497,7 +542,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 12; + c.gridx = 4; c.gridy = row; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -508,7 +553,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 12; + c.gridx = 6; c.gridy = row; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -616,6 +661,14 @@ public class AltosConfigUI return Integer.parseInt(apogee_delay_value.getSelectedItem().toString()); } + public void set_apogee_lockout(int new_apogee_lockout) { + apogee_lockout_value.setSelectedItem(Integer.toString(new_apogee_lockout)); + } + + public int apogee_lockout() { + return Integer.parseInt(apogee_lockout_value.getSelectedItem().toString()); + } + public void set_radio_frequency(double new_radio_frequency) { int i; for (i = 0; i < radio_frequency_value.getItemCount(); i++) { -- cgit v1.2.3 From 1489263b895a2a825e29d0560c9b1dbba8a3f431 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Apr 2012 11:01:18 -0700 Subject: altos: Starting to write cc1120 driver This does "something" in radio test mode, appearing to generate a 730MHz signal. Signed-off-by: Keith Packard --- src/cc1111/ao_packet.c | 161 ----------- src/cc1111/ao_packet_master.c | 151 ---------- src/cc1111/ao_packet_slave.c | 66 ----- src/drivers/ao_cc1120.c | 534 ++++++++++++++++++++++++++++++++++++ src/drivers/ao_cc1120.h | 320 +++++++++++++++++++++ src/drivers/ao_cc1120_CC1120.h | 191 +++++++++++++ src/drivers/ao_packet.c | 163 +++++++++++ src/drivers/ao_packet_master.c | 151 ++++++++++ src/drivers/ao_packet_slave.c | 66 +++++ src/megametrum-v0.1/Makefile | 5 +- src/megametrum-v0.1/ao_megametrum.c | 5 +- src/megametrum-v0.1/ao_pins.h | 13 + src/stm/Makefile.defs | 2 +- src/stm/ao_arch_funcs.h | 44 +-- src/stm/ao_dma_stm.c | 1 + src/stm/ao_exti.h | 38 +++ src/stm/ao_exti_stm.c | 109 ++++++++ src/stm/ao_spi_stm.c | 113 ++++++++ src/stm/ao_usb_stm.c | 4 + src/stm/stm32l.h | 16 +- 20 files changed, 1751 insertions(+), 402 deletions(-) delete mode 100644 src/cc1111/ao_packet.c delete mode 100644 src/cc1111/ao_packet_master.c delete mode 100644 src/cc1111/ao_packet_slave.c create mode 100644 src/drivers/ao_cc1120.h create mode 100644 src/drivers/ao_cc1120_CC1120.h create mode 100644 src/drivers/ao_packet.c create mode 100644 src/drivers/ao_packet_master.c create mode 100644 src/drivers/ao_packet_slave.c create mode 100644 src/stm/ao_exti.h create mode 100644 src/stm/ao_exti_stm.c diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c deleted file mode 100644 index 7eeb0710..00000000 --- a/src/cc1111/ao_packet.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -__xdata struct ao_packet_recv ao_rx_packet; -__xdata struct ao_packet ao_tx_packet; -__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_seq; - -__xdata struct ao_task ao_packet_task; -__xdata uint8_t ao_packet_enable; -__xdata uint8_t ao_packet_master_sleeping; - -void -ao_packet_send(void) -{ -#ifdef AO_LED_RED - ao_led_on(AO_LED_RED); -#endif - /* If any tx data is pending then copy it into the tx packet */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) { - ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); - ao_tx_packet.len = ao_packet_tx_used; - ao_tx_packet.seq++; - ao_packet_tx_used = 0; - ao_wakeup(&tx_data); - } - ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); -#ifdef AO_LED_RED - ao_led_off(AO_LED_RED); -#endif -} - -uint8_t -ao_packet_recv(void) -{ - uint8_t dma_done; - -#ifdef AO_LED_GREEN - ao_led_on(AO_LED_GREEN); -#endif - dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); -#ifdef AO_LED_GREEN - ao_led_off(AO_LED_GREEN); -#endif - - /* Check to see if we got a valid packet */ - if (!dma_done) - return 0; - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return 0; - - /* Accept packets with matching call signs, or any packet if - * our callsign hasn't been configured - */ - if (ao_xmemcmp(ao_rx_packet.packet.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN) != 0 && - ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) - return 0; - - /* SYN packets carry no data */ - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; - ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - - /* Check for incoming data at the next sequence and - * for an empty data buffer - */ - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && - ao_packet_rx_used == ao_packet_rx_len) { - - /* Copy data to the receive data buffer and set up the - * offsets - */ - ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - - /* Mark the sequence that we've received to - * let the sender know when we return a packet - */ - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - - /* Poke anyone looking for received data */ - ao_wakeup(&ao_stdin_ready); - } - } - - /* If the other side has seen the latest data we queued, - * wake up any task waiting to send data and let them go again - */ - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); - } - return 1; -} - -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - -#if PACKET_HAS_MASTER -void -ao_packet_flush(void) -{ - /* If there is data to send, and this is the master, - * then poke the master to send all queued data - */ - if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); -} -#endif /* PACKET_HAS_MASTER */ - -void -ao_packet_putchar(char c) __reentrant -{ - while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { -#if PACKET_HAS_MASTER - ao_packet_flush(); -#endif - ao_sleep(&tx_data); - } - - if (ao_packet_enable) - tx_data[ao_packet_tx_used++] = c; -} - -char -ao_packet_pollchar(void) __critical -{ - if (!ao_packet_enable) - return AO_READ_AGAIN; - - if (ao_packet_rx_used == ao_packet_rx_len) - return AO_READ_AGAIN; - - return rx_data[ao_packet_rx_used++]; -} diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c deleted file mode 100644 index 66f94288..00000000 --- a/src/cc1111/ao_packet_master.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static char -ao_packet_getchar(void) __critical -{ - char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { - if (!ao_packet_enable) - break; - if (ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); - flush(); - ao_sleep(&ao_stdin_ready); - } - return c; -} - -static void -ao_packet_echo(void) __reentrant -{ - char c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (c != AO_READ_AGAIN) - putchar(c); - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; -static __xdata uint16_t ao_packet_master_delay; -static __xdata uint16_t ao_packet_master_time; - -#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) -#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) -#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) - -static void -ao_packet_master_busy(void) -{ - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - ao_packet_master_time = ao_time(); -} - -static void -ao_packet_master_check_busy(void) -{ - int16_t idle; - if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) - return; - idle = (int16_t) (ao_time() - ao_packet_master_time); - - if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; -} - -void -ao_packet_master(void) -{ - ao_config_get(); - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - ao_packet_master_time = ao_time(); - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - while (ao_packet_enable) { - uint8_t r; - ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - ao_packet_send(); - if (ao_tx_packet.len) - ao_packet_master_busy(); - ao_packet_master_check_busy(); - ao_alarm(ao_packet_master_delay); - r = ao_packet_recv(); - ao_clear_alarm(); - if (r) { - /* if we can transmit data, do so */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) - continue; - if (ao_rx_packet.packet.len) - ao_packet_master_busy(); - ao_packet_master_sleeping = 1; - ao_alarm(ao_packet_master_delay); - ao_sleep(&ao_packet_master_sleeping); - ao_clear_alarm(); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - flush(); -#if HAS_MONITOR - ao_monitor_disable(); -#endif - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { - 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; - while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_wakeup(&ao_stdin_ready); - ao_delay(AO_MS_TO_TICKS(10)); - } -#if HAS_MONITOR - ao_monitor_enable(); -#endif -} - - - -__code struct ao_cmds ao_packet_master_cmds[] = { - { ao_packet_forward, "p\0Remote packet link." }, - { 0, NULL }, -}; - -void -ao_packet_master_init(void) -{ - ao_cmd_register(&ao_packet_master_cmds[0]); -} diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c deleted file mode 100644 index fd5d443e..00000000 --- a/src/cc1111/ao_packet_slave.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * 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" - -void -ao_packet_slave(void) -{ - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - if (ao_packet_recv()) { - ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); -#if HAS_FLIGHT - ao_flight_force_idle = TRUE; -#endif - ao_packet_send(); - } - } - ao_exit(); -} - -void -ao_packet_slave_start(void) -{ - if (!ao_packet_enable) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - } -} - -void -ao_packet_slave_stop(void) -{ - if (ao_packet_enable) { - ao_packet_enable = 0; - while (ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_delay(AO_MS_TO_TICKS(10)); - } - } -} - -void -ao_packet_slave_init(uint8_t enable) -{ - ao_add_stdio(ao_packet_pollchar, - ao_packet_putchar, - NULL); - if (enable) - ao_packet_slave_start(); -} diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 9470fa87..272371d0 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -16,10 +16,544 @@ */ #include +#include +#include + +uint8_t ao_radio_done; +uint8_t ao_radio_mutex; +uint8_t ao_radio_abort; + +#define CC1120_DEBUG 1 uint32_t ao_radio_cal = 1186611; +#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS) + +static uint8_t +ao_radio_reg_read(uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + +#if CC1120_DEBUG + printf("ao_radio_reg_read (%04x): ", addr); flush(); +#endif + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); + ao_radio_spi_recv(data, 1); + ao_radio_deselect(); +#if CC1120_DEBUG + printf (" %02x\n", data[0]); +#endif + return data[0]; +} + +static void +ao_radio_reg_write(uint16_t addr, uint8_t value) +{ + uint8_t data[3]; + uint8_t d; + +#if CC1120_DEBUG + printf("ao_radio_reg_write (%04x): %02x\n", addr, value); +#endif + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + addr); + d = 1; + } + data[d] = value; + ao_radio_select(); + ao_radio_spi_send(data, d+1); + ao_radio_deselect(); +} + +static uint8_t +ao_radio_strobe(uint8_t addr) +{ + uint8_t in; + + ao_radio_select(); + ao_radio_duplex(&addr, &in, 1); + ao_radio_deselect(); + return in; +} + +static uint8_t +ao_radio_fifo_read(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_recv(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((0 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_send(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t addr = ((0 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_send_fixed(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_status(void) +{ + return ao_radio_strobe (CC1120_SNOP); +} + void ao_radio_recv_abort(void) { + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); +} + +#define ao_radio_rdf_value 0x55 + +static const uint16_t rdf_setup[] = { +}; + +void +ao_radio_rdf(uint8_t len) +{ + int i; + + ao_radio_abort = 0; + ao_radio_get(len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); + cli(); + while (!ao_radio_done) + ao_sleep(&ao_radio_done); + sei(); + ao_radio_set_packet(); + ao_radio_put(); +} + +void +ao_radio_rdf_abort(void) +{ +} + +static void +ao_radio_test(void) +{ + uint8_t mode = 2; + uint8_t radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + ao_radio_strobe(CC1120_STX); + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif + } +} + +void +ao_radio_send(void *d, uint8_t size) +{ + ao_radio_get(size); + ao_radio_done = 0; + ao_radio_fifo_write(d, size); + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); + cli(); + while (!ao_radio_done) + ao_sleep(&ao_radio_done); + sei(); + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size) +{ + /* configure interrupt pin */ + ao_radio_get(size); + ao_radio_done = 0; + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); + cli(); + while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + sei(); + if (ao_radio_done) + ao_radio_fifo_read(d, size); + ao_radio_put(); + return 0; +} + +static const uint16_t packet_setup[] = { +}; + +void +ao_radio_set_packet(void) +{ + int i; + + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); +} + +void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = ao_radio_strobe(CC1120_SIDLE); + if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + break; + } +} + +static const uint16_t radio_setup[] = { +#include "ao_cc1120_CC1120.h" +}; + +static uint8_t ao_radio_configured = 0; + +static void +ao_radio_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); +} + +static void +ao_radio_setup(void) +{ + int i; + + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) + ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + + /* Disable GPIO2 pin (radio_int) */ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_HIGHZ); + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1120_INT_PORT); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_RISING, ao_radio_isr); + + ao_radio_set_packet(); + ao_radio_configured = 1; +} + +void +ao_radio_get(uint8_t len) +{ + ao_mutex_get(&ao_radio_mutex); + if (!ao_radio_configured) + ao_radio_setup(); + ao_radio_reg_write(CC1120_PKT_LEN, len); +} + +#if CC1120_DEBUG +static char *cc1120_state_name[] = { + [CC1120_STATUS_STATE_IDLE] = "IDLE", + [CC1120_STATUS_STATE_RX] = "RX", + [CC1120_STATUS_STATE_TX] = "TX", + [CC1120_STATUS_STATE_FSTXON] = "FSTXON", + [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE", + [CC1120_STATUS_STATE_SETTLING] = "SETTLING", + [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR", + [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR", +}; + +struct ao_cc1120_reg { + uint16_t addr; + char *name; +}; + +const static struct ao_cc1120_reg ao_cc1120_reg[] = { + { .addr = CC1120_IOCFG3, .name = "IOCFG3" }, + { .addr = CC1120_IOCFG2, .name = "IOCFG2" }, + { .addr = CC1120_IOCFG1, .name = "IOCFG1" }, + { .addr = CC1120_IOCFG0, .name = "IOCFG0" }, + { .addr = CC1120_SYNC3, .name = "SYNC3" }, + { .addr = CC1120_SYNC2, .name = "SYNC2" }, + { .addr = CC1120_SYNC1, .name = "SYNC1" }, + { .addr = CC1120_SYNC0, .name = "SYNC0" }, + { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" }, + { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" }, + { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" }, + { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" }, + { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" }, + { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" }, + { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, + { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" }, + { .addr = CC1120_IQIC, .name = "IQIC" }, + { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" }, + { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" }, + { .addr = CC1120_DRATE2, .name = "DRATE2" }, + { .addr = CC1120_DRATE1, .name = "DRATE1" }, + { .addr = CC1120_DRATE0, .name = "DRATE0" }, + { .addr = CC1120_AGC_REF, .name = "AGC_REF" }, + { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" }, + { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" }, + { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" }, + { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" }, + { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" }, + { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" }, + { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" }, + { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" }, + { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" }, + { .addr = CC1120_FS_CFG, .name = "FS_CFG" }, + { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" }, + { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" }, + { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" }, + { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" }, + { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" }, + { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" }, + { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" }, + { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" }, + { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" }, + { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" }, + { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" }, + { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" }, + { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" }, + { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" }, + { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" }, + { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" }, + { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" }, + { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" }, + { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" }, + { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" }, + { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" }, + { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" }, + { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" }, + { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" }, + { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" }, + { .addr = CC1120_FREQ2, .name = "FREQ2" }, + { .addr = CC1120_FREQ1, .name = "FREQ1" }, + { .addr = CC1120_FREQ0, .name = "FREQ0" }, + { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" }, + { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" }, + { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" }, + { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" }, + { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" }, + { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" }, + { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" }, + { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" }, + { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" }, + { .addr = CC1120_FS_CHP, .name = "FS_CHP" }, + { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" }, + { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" }, + { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" }, + { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" }, + { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" }, + { .addr = CC1120_FS_LBI, .name = "FS_LBI" }, + { .addr = CC1120_FS_PFD, .name = "FS_PFD" }, + { .addr = CC1120_FS_PRE, .name = "FS_PRE" }, + { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" }, + { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" }, + { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" }, + { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" }, + { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" }, + { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" }, + { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" }, + { .addr = CC1120_GBIAS6, .name = "GBIAS6" }, + { .addr = CC1120_GBIAS5, .name = "GBIAS5" }, + { .addr = CC1120_GBIAS4, .name = "GBIAS4" }, + { .addr = CC1120_GBIAS3, .name = "GBIAS3" }, + { .addr = CC1120_GBIAS2, .name = "GBIAS2" }, + { .addr = CC1120_GBIAS1, .name = "GBIAS1" }, + { .addr = CC1120_GBIAS0, .name = "GBIAS0" }, + { .addr = CC1120_IFAMP, .name = "IFAMP" }, + { .addr = CC1120_LNA, .name = "LNA" }, + { .addr = CC1120_RXMIX, .name = "RXMIX" }, + { .addr = CC1120_XOSC5, .name = "XOSC5" }, + { .addr = CC1120_XOSC4, .name = "XOSC4" }, + { .addr = CC1120_XOSC3, .name = "XOSC3" }, + { .addr = CC1120_XOSC2, .name = "XOSC2" }, + { .addr = CC1120_XOSC1, .name = "XOSC1" }, + { .addr = CC1120_XOSC0, .name = "XOSC0" }, + { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" }, + { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" }, + { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" }, + { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" }, + { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" }, + { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" }, + { .addr = CC1120_BIST, .name = "BIST" }, + { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" }, + { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" }, + { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" }, + { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" }, + { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" }, + { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" }, + { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" }, + { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" }, + { .addr = CC1120_RSSI1, .name = "RSSI1" }, + { .addr = CC1120_RSSI0, .name = "RSSI0" }, + { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" }, + { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" }, + { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" }, + { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" }, + { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" }, + { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" }, + { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" }, + { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" }, + { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" }, + { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" }, + { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" }, + { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" }, + { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" }, + { .addr = CC1120_RNDGEN, .name = "RNDGEN" }, + { .addr = CC1120_MAGN2, .name = "MAGN2" }, + { .addr = CC1120_MAGN1, .name = "MAGN1" }, + { .addr = CC1120_MAGN0, .name = "MAGN0" }, + { .addr = CC1120_ANG1, .name = "ANG1" }, + { .addr = CC1120_ANG0, .name = "ANG0" }, + { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" }, + { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" }, + { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" }, + { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" }, + { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" }, + { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" }, + { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" }, + { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" }, + { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" }, + { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" }, + { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" }, + { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" }, + { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" }, + { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" }, + { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" }, + { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, + { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" }, + { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" }, + { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" }, + { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" }, + { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" }, + { .addr = CC1120_ATEST, .name = "ATEST" }, + { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" }, + { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" }, + { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" }, + { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" }, + { .addr = CC1120_RXFIRST, .name = "RXFIRST" }, + { .addr = CC1120_TXFIRST, .name = "TXFIRST" }, + { .addr = CC1120_RXLAST, .name = "RXLAST" }, + { .addr = CC1120_TXLAST, .name = "TXLAST" }, + { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" }, + { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" }, + { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" }, + { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" }, +}; + +#define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0]) + +static void ao_radio_show(void) { + uint8_t status = ao_radio_status(); + int i; + + ao_radio_get(0xff); + status = ao_radio_status(); + printf ("Status: %02x\n", status); + printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1); + printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]); + + for (i = 0; i < AO_NUM_CC1120_REG; i++) + printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); + ao_radio_put(); +} +#endif + +static const struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if CC1120_DEBUG + { ao_radio_show, "R\0Show CC1120 status" }, +#endif + { 0, NULL } +}; + +void +ao_radio_init(void) +{ + ao_radio_configured = 0; + ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); + + ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h new file mode 100644 index 00000000..67c0a1b8 --- /dev/null +++ b/src/drivers/ao_cc1120.h @@ -0,0 +1,320 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_CC1120_H_ +#define _AO_CC1120_H_ + +#define CC1120_READ (7) +#define CC1120_BURST (6) + +/* Register space */ +#define CC1120_IOCFG3 0x00 +#define CC1120_IOCFG_GPIO_ATRAN 7 +#define CC1120_IOCFG_GPIO_INV 6 +#define CC1120_IOCFG_GPIO_CFG 0 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR 0 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR 2 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW 5 +#define CC1120_IOCFG_GPIO_CFG_PKT_SYNC_RXTX 6 +#define CC1120_IOCFG_GPIO_CFG_CRC_OK 7 +#define CC1120_IOCFG_GPIO_CFG_SERIAL_CLK 8 +#define CC1120_IOCFG_GPIO_CFG_SERIAL_RX 9 +#define CC1120_IOCFG_GPIO_CFG_PQT_REACHED 11 +#define CC1120_IOCFG_GPIO_CFG_PQT_VALID 12 +#define CC1120_IOCFG_GPIO_CFG_RSSI_VALID 13 +#define CC1120_IOCFG_GPIO3_CFG_RSSI_UPDATE 14 +#define CC1120_IOCFG_GPIO2_CFG_RSSI_UPDATE 14 +#define CC1120_IOCFG_GPIO1_CFG_AGC_HOLD 14 +#define CC1120_IOCFG_GPIO0_CFG_AGC_UPDATE 14 +#define CC1120_IOCFG_GPIO3_CFG_CGA_STATUS 15 +#define CC1120_IOCFG_GPIO2_CFG_TXONCCA_DONE 15 +#define CC1120_IOCFG_GPIO1_CFG_CCA_STATUS 15 +#define CC1120_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15 +#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID 16 +#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE 17 +#define CC1120_IOCFG_GPIO3_CFG_DSSS_CLK 18 +#define CC1120_IOCFG_GPIO2_CFG_DSSS_DATA0 18 +#define CC1120_IOCFG_GPIO1_CFG_DSSS_CLK 18 +#define CC1120_IOCFG_GPIO0_CFG_DSSS_DATA1 18 +#define CC1120_IOCFG_GPIO_CFG_PKT_CRC_OK 19 +#define CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20 +#define CC1120_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21 +#define CC1120_IOCFG_GPIO_CFG_LNA_PA_REG_PD 23 +#define CC1120_IOCFG_GPIO_CFG_LNA_PD 24 +#define CC1120_IOCFG_GPIO_CFG_PA_RD 25 +#define CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG 26 +#define CC1120_IOCFG_GPIO_CFG_IMAGE_FOUND 28 +#define CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT 29 +#define CC1120_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK 30 +#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33 +#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34 +#define CC1120_IOCFG_GPIO_CFG_ANTENNA_SELECT 36 +#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1 37 +#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0 38 +#define CC1120_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW 39 +#define CC1120_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW 39 +#define CC1120_IOCFG_GPIO3_CFG_MAGN_VALID 40 +#define CC1120_IOCFG_GPIO2_CFG_CHFILT_VALID 40 +#define CC1120_IOCFG_GPIO1_CFG_RCC_CAL_VALID 40 +#define CC1120_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40 +#define CC1120_IOCFG_GPIO3_CFG_COLLISION_FOUND 41 +#define CC1120_IOCFG_GPIO2_CFG_SYNC_EVENT 41 +#define CC1120_IOCFG_GPIO1_CFG_COLLISION_FOUND 41 +#define CC1120_IOCFG_GPIO0_CFG_COLLISION_EVENT 41 +#define CC1120_IOCFG_GPIO_CFG_PA_RAMP_UP 42 +#define CC1120_IOCFG_GPIO3_CFG_CRC_FAILED 43 +#define CC1120_IOCFG_GPIO2_CFG_LENGTH_FAILED 43 +#define CC1120_IOCFG_GPIO1_CFG_ADDR_FAILED 43 +#define CC1120_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR 43 +#define CC1120_IOCFG_GPIO_CFG_AGC_STABLE_GAIN 44 +#define CC1120_IOCFG_GPIO_CFG_AGC_UPDATE 45 +#define CC1120_IOCFG_GPIO3_CFG_ADC_CLOCK 46 +#define CC1120_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE 46 +#define CC1120_IOCFG_GPIO1_CFG_ADC_CLOCK 46 +#define CC1120_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE 46 +#define CC1120_IOCFG_GPIO_CFG_HIGHZ 48 +#define CC1120_IOCFG_GPIO_CFG_EXT_CLOCK 49 +#define CC1120_IOCFG_GPIO_CFG_CHIP_RDY 50 +#define CC1120_IOCFG_GPIO_CFG_HW0 51 +#define CC1120_IOCFG_GPIO_CFG_CLOCK_32K 54 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT0 55 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT1 56 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT2 57 +#define CC1120_IOCFG_GPIO_CFG_XOSC_STABLE 59 +#define CC1120_IOCFG_GPIO_CFG_EXT_OSC_EN 60 +#define CC1120_IOCFG_GPIO_CFG_MASK 0x3f + +#define CC1120_IOCFG3 0x00 +#define CC1120_IOCFG2 0x01 +#define CC1120_IOCFG1 0x02 +#define CC1120_IOCFG0 0x03 +#define CC1120_SYNC3 0x04 +#define CC1120_SYNC2 0x05 +#define CC1120_SYNC1 0x06 +#define CC1120_SYNC0 0x07 +#define CC1120_SYNC_CFG1 0x08 +#define CC1120_SYNC_CFG0 0x09 +#define CC1120_DEVIATION_M 0x0a +#define CC1120_MODCFG_DEV_E 0x0b +#define CC1120_DCFILT_CFG 0x0c +#define CC1120_PREAMBLE_CFG1 0x0d +#define CC1120_PREAMBLE_CFG0 0x0e +#define CC1120_FREQ_IF_CFG 0x0f +#define CC1120_IQIC 0x10 +#define CC1120_CHAN_BW 0x11 +#define CC1120_MDMCFG1 0x12 +#define CC1120_MDMCFG0 0x13 +#define CC1120_DRATE2 0x14 +#define CC1120_DRATE1 0x15 +#define CC1120_DRATE0 0x16 +#define CC1120_AGC_REF 0x17 +#define CC1120_AGC_CS_THR 0x18 +#define CC1120_AGC_GAIN_ADJUST 0x19 +#define CC1120_AGC_CFG3 0x1a +#define CC1120_AGC_CFG2 0x1b +#define CC1120_AGC_CFG1 0x1c +#define CC1120_AGC_CFG0 0x1d +#define CC1120_FIFO_CFG 0x1e +#define CC1120_DEV_ADDR 0x1f +#define CC1120_SETTLING_CFG 0x20 +#define CC1120_FS_CFG 0x21 +#define CC1120_WOR_CFG1 0x22 +#define CC1120_WOR_CFG0 0x23 +#define CC1120_WOR_EVENT0_MSB 0x24 +#define CC1120_WOR_EVENT0_LSB 0x25 +#define CC1120_PKT_CFG2 0x26 +#define CC1120_PKT_CFG1 0x27 +#define CC1120_PKT_CFG0 0x28 +#define CC1120_RFEND_CFG1 0x29 +#define CC1120_RFEND_CFG0 0x2a +#define CC1120_PA_CFG2 0x2b +#define CC1120_PA_CFG1 0x2c +#define CC1120_PA_CFG0 0x2d +#define CC1120_PKT_LEN 0x2e + +#define CC1120_EXTENDED 0x2f + +/* Command strobes */ +#define CC1120_SRES 0x30 +#define CC1120_SFSTXON 0x31 +#define CC1120_SXOFF 0x32 +#define CC1120_SCAL 0x33 +#define CC1120_SRX 0x34 +#define CC1120_STX 0x35 +#define CC1120_SIDLE 0x36 +#define CC1120_SAFC 0x37 +#define CC1120_SWOR 0x38 +#define CC1120_SPWD 0x39 +#define CC1120_SFRX 0x3a +#define CC1120_SFTX 0x3b +#define CC1120_SWORRST 0x3c +#define CC1120_SNOP 0x3d + +#define CC1120_DIRECT_FIFO 0x3e +#define CC1120_FIFO 0x3f + +/* Extended register space */ + +#define CC1120_EXTENDED_BIT 0x8000 + +#define CC1120_IS_EXTENDED(r) ((r) & CC1120_EXTENDED_BIT) + +#define CC1120_IF_MIX_CFG (CC1120_EXTENDED_BIT | 0x00) +#define CC1120_FREQOFF_CFG (CC1120_EXTENDED_BIT | 0x01) +#define CC1120_TOC_CFG (CC1120_EXTENDED_BIT | 0x02) +#define CC1120_MARC_SPARE (CC1120_EXTENDED_BIT | 0x03) +#define CC1120_ECG_CFG (CC1120_EXTENDED_BIT | 0x04) +#define CC1120_SOFT_TX_DATA_CFG (CC1120_EXTENDED_BIT | 0x05) +#define CC1120_EXT_CTRL (CC1120_EXTENDED_BIT | 0x06) +#define CC1120_RCCAL_FINE (CC1120_EXTENDED_BIT | 0x07) +#define CC1120_RCCAL_COARSE (CC1120_EXTENDED_BIT | 0x08) +#define CC1120_RCCAL_OFFSET (CC1120_EXTENDED_BIT | 0x09) +#define CC1120_FREQOFF1 (CC1120_EXTENDED_BIT | 0x0A) +#define CC1120_FREQOFF0 (CC1120_EXTENDED_BIT | 0x0B) +#define CC1120_FREQ2 (CC1120_EXTENDED_BIT | 0x0C) +#define CC1120_FREQ1 (CC1120_EXTENDED_BIT | 0x0D) +#define CC1120_FREQ0 (CC1120_EXTENDED_BIT | 0x0E) +#define CC1120_IF_ADC2 (CC1120_EXTENDED_BIT | 0x0F) +#define CC1120_IF_ADC1 (CC1120_EXTENDED_BIT | 0x10) +#define CC1120_IF_ADC0 (CC1120_EXTENDED_BIT | 0x11) +#define CC1120_FS_DIG1 (CC1120_EXTENDED_BIT | 0x12) +#define CC1120_FS_DIG0 (CC1120_EXTENDED_BIT | 0x13) +#define CC1120_FS_CAL3 (CC1120_EXTENDED_BIT | 0x14) +#define CC1120_FS_CAL2 (CC1120_EXTENDED_BIT | 0x15) +#define CC1120_FS_CAL1 (CC1120_EXTENDED_BIT | 0x16) +#define CC1120_FS_CAL0 (CC1120_EXTENDED_BIT | 0x17) +#define CC1120_FS_CHP (CC1120_EXTENDED_BIT | 0x18) +#define CC1120_FS_DIVTWO (CC1120_EXTENDED_BIT | 0x19) +#define CC1120_FS_DSM1 (CC1120_EXTENDED_BIT | 0x1A) +#define CC1120_FS_DSM0 (CC1120_EXTENDED_BIT | 0x1B) +#define CC1120_FS_DVC1 (CC1120_EXTENDED_BIT | 0x1C) +#define CC1120_FS_DVC0 (CC1120_EXTENDED_BIT | 0x1D) +#define CC1120_FS_LBI (CC1120_EXTENDED_BIT | 0x1E) +#define CC1120_FS_PFD (CC1120_EXTENDED_BIT | 0x1F) +#define CC1120_FS_PRE (CC1120_EXTENDED_BIT | 0x20) +#define CC1120_FS_REG_DIV_CML (CC1120_EXTENDED_BIT | 0x21) +#define CC1120_FS_SPARE (CC1120_EXTENDED_BIT | 0x22) +#define CC1120_FS_VCO4 (CC1120_EXTENDED_BIT | 0x23) +#define CC1120_FS_VCO3 (CC1120_EXTENDED_BIT | 0x24) +#define CC1120_FS_VCO2 (CC1120_EXTENDED_BIT | 0x25) +#define CC1120_FS_VCO1 (CC1120_EXTENDED_BIT | 0x26) +#define CC1120_FS_VCO0 (CC1120_EXTENDED_BIT | 0x27) +#define CC1120_GBIAS6 (CC1120_EXTENDED_BIT | 0x28) +#define CC1120_GBIAS5 (CC1120_EXTENDED_BIT | 0x29) +#define CC1120_GBIAS4 (CC1120_EXTENDED_BIT | 0x2A) +#define CC1120_GBIAS3 (CC1120_EXTENDED_BIT | 0x2B) +#define CC1120_GBIAS2 (CC1120_EXTENDED_BIT | 0x2C) +#define CC1120_GBIAS1 (CC1120_EXTENDED_BIT | 0x2D) +#define CC1120_GBIAS0 (CC1120_EXTENDED_BIT | 0x2E) +#define CC1120_IFAMP (CC1120_EXTENDED_BIT | 0x2F) +#define CC1120_LNA (CC1120_EXTENDED_BIT | 0x30) +#define CC1120_RXMIX (CC1120_EXTENDED_BIT | 0x31) +#define CC1120_XOSC5 (CC1120_EXTENDED_BIT | 0x32) +#define CC1120_XOSC4 (CC1120_EXTENDED_BIT | 0x33) +#define CC1120_XOSC3 (CC1120_EXTENDED_BIT | 0x34) +#define CC1120_XOSC2 (CC1120_EXTENDED_BIT | 0x35) +#define CC1120_XOSC1 (CC1120_EXTENDED_BIT | 0x36) +#define CC1120_XOSC0 (CC1120_EXTENDED_BIT | 0x37) +#define CC1120_ANALOG_SPARE (CC1120_EXTENDED_BIT | 0x38) +#define CC1120_PA_CFG3 (CC1120_EXTENDED_BIT | 0x39) +#define CC1120_WOR_TIME1 (CC1120_EXTENDED_BIT | 0x64) +#define CC1120_WOR_TIME0 (CC1120_EXTENDED_BIT | 0x65) +#define CC1120_WOR_CAPTURE1 (CC1120_EXTENDED_BIT | 0x66) +#define CC1120_WOR_CAPTURE0 (CC1120_EXTENDED_BIT | 0x67) +#define CC1120_BIST (CC1120_EXTENDED_BIT | 0x68) +#define CC1120_DCFILTOFFSET_I1 (CC1120_EXTENDED_BIT | 0x69) +#define CC1120_DCFILTOFFSET_I0 (CC1120_EXTENDED_BIT | 0x6A) +#define CC1120_DCFILTOFFSET_Q1 (CC1120_EXTENDED_BIT | 0x6B) +#define CC1120_DCFILTOFFSET_Q0 (CC1120_EXTENDED_BIT | 0x6C) +#define CC1120_IQIE_I1 (CC1120_EXTENDED_BIT | 0x6D) +#define CC1120_IQIE_I0 (CC1120_EXTENDED_BIT | 0x6E) +#define CC1120_IQIE_Q1 (CC1120_EXTENDED_BIT | 0x6f) +#define CC1120_IQIE_Q0 (CC1120_EXTENDED_BIT | 0x70) +#define CC1120_RSSI1 (CC1120_EXTENDED_BIT | 0x71) +#define CC1120_RSSI0 (CC1120_EXTENDED_BIT | 0x72) +#define CC1120_MARCSTATE (CC1120_EXTENDED_BIT | 0x73) +#define CC1120_LQI_VAL (CC1120_EXTENDED_BIT | 0x74) +#define CC1120_PQT_SYNC_ERR (CC1120_EXTENDED_BIT | 0x75) +#define CC1120_DEM_STATUS (CC1120_EXTENDED_BIT | 0x76) +#define CC1120_FREQOFF_EST1 (CC1120_EXTENDED_BIT | 0x77) +#define CC1120_FREQOFF_EST0 (CC1120_EXTENDED_BIT | 0x78) +#define CC1120_AGC_GAIN3 (CC1120_EXTENDED_BIT | 0x79) +#define CC1120_AGC_GAIN2 (CC1120_EXTENDED_BIT | 0x7a) +#define CC1120_AGC_GAIN1 (CC1120_EXTENDED_BIT | 0x7b) +#define CC1120_AGC_GAIN0 (CC1120_EXTENDED_BIT | 0x7c) +#define CC1120_SOFT_RX_DATA_OUT (CC1120_EXTENDED_BIT | 0x7d) +#define CC1120_SOFT_TX_DATA_IN (CC1120_EXTENDED_BIT | 0x7e) +#define CC1120_ASK_SOFT_RX_DATA (CC1120_EXTENDED_BIT | 0x7f) +#define CC1120_RNDGEN (CC1120_EXTENDED_BIT | 0x80) +#define CC1120_MAGN2 (CC1120_EXTENDED_BIT | 0x81) +#define CC1120_MAGN1 (CC1120_EXTENDED_BIT | 0x82) +#define CC1120_MAGN0 (CC1120_EXTENDED_BIT | 0x83) +#define CC1120_ANG1 (CC1120_EXTENDED_BIT | 0x84) +#define CC1120_ANG0 (CC1120_EXTENDED_BIT | 0x85) +#define CC1120_CHFILT_I2 (CC1120_EXTENDED_BIT | 0x86) +#define CC1120_CHFILT_I1 (CC1120_EXTENDED_BIT | 0x87) +#define CC1120_CHFILT_I0 (CC1120_EXTENDED_BIT | 0x88) +#define CC1120_CHFILT_Q2 (CC1120_EXTENDED_BIT | 0x89) +#define CC1120_CHFILT_Q1 (CC1120_EXTENDED_BIT | 0x8a) +#define CC1120_CHFILT_Q0 (CC1120_EXTENDED_BIT | 0x8b) +#define CC1120_GPIO_STATUS (CC1120_EXTENDED_BIT | 0x8c) +#define CC1120_FSCAL_CTRL (CC1120_EXTENDED_BIT | 0x8d) +#define CC1120_PHASE_ADJUST (CC1120_EXTENDED_BIT | 0x8e) +#define CC1120_PARTNUMBER (CC1120_EXTENDED_BIT | 0x8f) +#define CC1120_PARTVERSION (CC1120_EXTENDED_BIT | 0x90) +#define CC1120_SERIAL_STATUS (CC1120_EXTENDED_BIT | 0x91) +#define CC1120_RX_STATUS (CC1120_EXTENDED_BIT | 0x92) +#define CC1120_TX_STATUS (CC1120_EXTENDED_BIT | 0x93) +#define CC1120_MARC_STATUS1 (CC1120_EXTENDED_BIT | 0x94) +#define CC1120_MARC_STATUS0 (CC1120_EXTENDED_BIT | 0x95) +#define CC1120_PA_IFAMP_TEST (CC1120_EXTENDED_BIT | 0x96) +#define CC1120_FSRF_TEST (CC1120_EXTENDED_BIT | 0x97) +#define CC1120_PRE_TEST (CC1120_EXTENDED_BIT | 0x98) +#define CC1120_PRE_OVR (CC1120_EXTENDED_BIT | 0x99) +#define CC1120_ADC_TEST (CC1120_EXTENDED_BIT | 0x9a) +#define CC1120_DVC_TEST (CC1120_EXTENDED_BIT | 0x9b) +#define CC1120_ATEST (CC1120_EXTENDED_BIT | 0x9c) +#define CC1120_ATEST_LVDS (CC1120_EXTENDED_BIT | 0x9d) +#define CC1120_ATEST_MODE (CC1120_EXTENDED_BIT | 0x9e) +#define CC1120_XOSC_TEST1 (CC1120_EXTENDED_BIT | 0x9f) +#define CC1120_XOSC_TEST0 (CC1120_EXTENDED_BIT | 0xa0) +#define CC1120_RXFIRST (CC1120_EXTENDED_BIT | 0xd2) +#define CC1120_TXFIRST (CC1120_EXTENDED_BIT | 0xd3) +#define CC1120_RXLAST (CC1120_EXTENDED_BIT | 0xd4) +#define CC1120_TXLAST (CC1120_EXTENDED_BIT | 0xd5) +#define CC1120_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd6) +#define CC1120_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd7) +#define CC1120_FIFO_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd8) +#define CC1120_FIFO_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd9) + +/* Status byte */ +#define CC1120_STATUS_CHIP_RDY 7 +#define CC1120_STATUS_STATE 4 +#define CC1120_STATUS_STATE_IDLE 0 +#define CC1120_STATUS_STATE_RX 1 +#define CC1120_STATUS_STATE_TX 2 +#define CC1120_STATUS_STATE_FSTXON 3 +#define CC1120_STATUS_STATE_CALIBRATE 4 +#define CC1120_STATUS_STATE_SETTLING 5 +#define CC1120_STATUS_STATE_RX_FIFO_ERROR 6 +#define CC1120_STATUS_STATE_TX_FIFO_ERROR 7 +#define CC1120_STATUS_STATE_MASK 7 + +#endif /* _AO_CC1120_H_ */ diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h new file mode 100644 index 00000000..a96c22fc --- /dev/null +++ b/src/drivers/ao_cc1120_CC1120.h @@ -0,0 +1,191 @@ +/* RX filter BW = 100.000000 */ +/* Address config = No address check */ +/* Packet length = 255 */ +/* Symbol rate = 38.3606 */ +/* PA ramping = false */ +/* Carrier frequency = 434.549988 */ +/* Bit rate = 38.3606 */ +/* Whitening = true */ +/* Manchester enable = false */ +/* Modulation format = 2-GFSK */ +/* Packet length mode = Variable */ +/* Device address = 0 */ +/* TX power = 15 */ +/* Deviation = 20.507812 */ +/*************************************************************** + * SmartRF Studio(tm) Export + * + * Radio register settings specifed with address, value + * + * RF device: CC1120 + * + ***************************************************************/ + + + CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ + CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ + CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ + CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ + CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ + CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ + CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ + CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ + CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ + CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ + CC1120_PREAMBLE_CFG0, 0x2a, /* */ + CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ + CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ + CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ + CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ + CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ + CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ + CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ + CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ + CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ + CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ + CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ + CC1120_AGC_CFG3, 0x91, /* AGC Configuration */ + CC1120_AGC_CFG2, 0x20, /* AGC Configuration */ + CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */ + CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ + CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ + CC1120_SETTLING_CFG, 0x03, /* Frequency Synthesizer Calibration and Settling Configuration */ + CC1120_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ + CC1120_WOR_CFG1, 0x08, /* eWOR Configuration, Reg 1 */ + CC1120_WOR_CFG0, 0x21, /* eWOR Configuration, Reg 0 */ + CC1120_WOR_EVENT0_MSB, 0x00, /* Event 0 Configuration */ + CC1120_WOR_EVENT0_LSB, 0x00, /* Event 0 Configuration */ + CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ + CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ + CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ + CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ + CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ + CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ + CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ + CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ + CC1120_IF_MIX_CFG, 0x00, /* IF Mix Configuration */ + CC1120_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */ + CC1120_TOC_CFG, 0x0b, /* Timing Offset Correction Configuration */ + CC1120_MARC_SPARE, 0x00, /* MARC Spare */ + CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */ + CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */ + CC1120_EXT_CTRL, 0x01, /* External Control Configuration */ + CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */ + CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */ + CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ + CC1120_FREQOFF1, 0x00, /* Frequency Offset (MSB) */ + CC1120_FREQOFF0, 0x00, /* Frequency Offset (LSB) */ + CC1120_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ + CC1120_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ + CC1120_FREQ0, 0x33, /* Frequency Configuration [7:0] */ + CC1120_IF_ADC2, 0x02, /* Analog to Digital Converter Configuration, Reg 2 */ + CC1120_IF_ADC1, 0xa6, /* Analog to Digital Converter Configuration, Reg 1 */ + CC1120_IF_ADC0, 0x04, /* Analog to Digital Converter Configuration, Reg 0 */ + CC1120_FS_DIG1, 0x00, /* */ + CC1120_FS_DIG0, 0x5f, /* */ + CC1120_FS_CAL3, 0x00, /* */ + CC1120_FS_CAL2, 0x20, /* */ + CC1120_FS_CAL1, 0x40, /* */ + CC1120_FS_CAL0, 0x0e, /* */ + CC1120_FS_CHP, 0x28, /* Charge Pump Configuration */ + CC1120_FS_DIVTWO, 0x03, /* Divide by 2 */ + CC1120_FS_DSM1, 0x00, /* Digital Synthesizer Module Configuration, Reg 1 */ + CC1120_FS_DSM0, 0x33, /* Digital Synthesizer Module Configuration, Reg 0 */ + CC1120_FS_DVC1, 0xff, /* Divider Chain Configuration, Reg 1 */ + CC1120_FS_DVC0, 0x17, /* Divider Chain Configuration, Reg 0 */ + CC1120_FS_LBI, 0x00, /* Local Bias Configuration */ + CC1120_FS_PFD, 0x50, /* Phase Frequency Detector Configuration */ + CC1120_FS_PRE, 0x6e, /* Prescaler Configuration */ + CC1120_FS_REG_DIV_CML, 0x14, /* */ + CC1120_FS_SPARE, 0xac, /* */ + CC1120_FS_VCO4, 0x14, /* VCO Configuration, Reg 4 */ + CC1120_FS_VCO3, 0x00, /* VCO Configuration, Reg 3 */ + CC1120_FS_VCO2, 0x00, /* VCO Configuration, Reg 2 */ + CC1120_FS_VCO1, 0x00, /* VCO Configuration, Reg 1 */ + CC1120_FS_VCO0, 0xb4, /* VCO Configuration, Reg 0 */ + CC1120_GBIAS6, 0x00, /* Global Bias Configuration, Reg 6 */ + CC1120_GBIAS5, 0x02, /* Global Bias Configuration, Reg 5 */ + CC1120_GBIAS4, 0x00, /* Global Bias Configuration, Reg 4 */ + CC1120_GBIAS3, 0x00, /* Global Bias Configuration, Reg 3 */ + CC1120_GBIAS2, 0x10, /* Global Bias Configuration, Reg 2 */ + CC1120_GBIAS1, 0x00, /* Global Bias Configuration, Reg 1 */ + CC1120_GBIAS0, 0x00, /* Global Bias Configuration, Reg 0 */ + CC1120_IFAMP, 0x01, /* Intermediate Frequency Amplifier Configuration */ + CC1120_LNA, 0x01, /* Low Noise Amplifier Configuration */ + CC1120_RXMIX, 0x01, /* RX Mixer Configuration */ + CC1120_XOSC5, 0x0e, /* Crystal Oscillator Configuration, Reg 5 */ + CC1120_XOSC4, 0xa0, /* Crystal Oscillator Configuration, Reg 4 */ + CC1120_XOSC3, 0x03, /* Crystal Oscillator Configuration, Reg 3 */ + CC1120_XOSC2, 0x04, /* Crystal Oscillator Configuration, Reg 2 */ + CC1120_XOSC1, 0x01, /* Crystal Oscillator Configuration, Reg 1 */ + CC1120_XOSC0, 0x00, /* Crystal Oscillator Configuration, Reg 0 */ + CC1120_ANALOG_SPARE, 0x00, /* */ + CC1120_PA_CFG3, 0x00, /* Power Amplifier Configuration, Reg 3 */ + CC1120_WOR_TIME1, 0x00, /* eWOR Timer Status (MSB) */ + CC1120_WOR_TIME0, 0x00, /* eWOR Timer Status (LSB) */ + CC1120_WOR_CAPTURE1, 0x00, /* eWOR Timer Capture (MSB) */ + CC1120_WOR_CAPTURE0, 0x00, /* eWOR Timer Capture (LSB) */ + CC1120_BIST, 0x00, /* MARC BIST */ + CC1120_DCFILTOFFSET_I1, 0x00, /* DC Filter Offset I (MSB) */ + CC1120_DCFILTOFFSET_I0, 0x00, /* DC Filter Offset I (LSB) */ + CC1120_DCFILTOFFSET_Q1, 0x00, /* DC Filter Offset Q (MSB) */ + CC1120_DCFILTOFFSET_Q0, 0x00, /* DC Filter Offset Q (LSB) */ + CC1120_IQIE_I1, 0x00, /* IQ Imbalance Value I (MSB) */ + CC1120_IQIE_I0, 0x00, /* IQ Imbalance Value I (LSB) */ + CC1120_IQIE_Q1, 0x00, /* IQ Imbalance Value Q (MSB) */ + CC1120_IQIE_Q0, 0x00, /* IQ Imbalance Value Q (LSB) */ + CC1120_RSSI1, 0x80, /* Received Signal Strength Indicator (MSB) */ + CC1120_RSSI0, 0x00, /* Received Signal Strength Indicator (LSB) */ + CC1120_MARCSTATE, 0x41, /* MARC State */ + CC1120_LQI_VAL, 0x00, /* Link Quality Indicator Value */ + CC1120_PQT_SYNC_ERR, 0xff, /* Preamble and Sync Word Error */ + CC1120_DEM_STATUS, 0x00, /* Demodulator Status */ + CC1120_FREQOFF_EST1, 0x00, /* Frequency Offset Estimate (MSB) */ + CC1120_FREQOFF_EST0, 0x00, /* Frequency Offset Estimate (LSB) */ + CC1120_AGC_GAIN3, 0x00, /* AGC Gain, Reg 3 */ + CC1120_AGC_GAIN2, 0xd1, /* AGC Gain, Reg 2 */ + CC1120_AGC_GAIN1, 0x00, /* AGC Gain, Reg 1 */ + CC1120_AGC_GAIN0, 0x3f, /* AGC Gain, Reg 0 */ + CC1120_SOFT_RX_DATA_OUT, 0x00, /* Soft Decision Symbol Data */ + CC1120_SOFT_TX_DATA_IN, 0x00, /* Soft TX Data Input Register */ + CC1120_ASK_SOFT_RX_DATA, 0x30, /* AGC ASK Soft Decision Output */ + CC1120_RNDGEN, 0x7f, /* Random Number Value */ + CC1120_MAGN2, 0x00, /* Signal Magnitude after CORDIC [16] */ + CC1120_MAGN1, 0x00, /* Signal Magnitude after CORDIC [15:8] */ + CC1120_MAGN0, 0x00, /* Signal Magnitude after CORDIC [7:0] */ + CC1120_ANG1, 0x00, /* Signal Angular after CORDIC [9:8] */ + CC1120_ANG0, 0x00, /* Signal Angular after CORDIC [7:0] */ + CC1120_CHFILT_I2, 0x08, /* Channel Filter Data Real Part [18:16] */ + CC1120_CHFILT_I1, 0x00, /* Channel Filter Data Real Part [15:8] */ + CC1120_CHFILT_I0, 0x00, /* Channel Filter Data Real Part [7:0] */ + CC1120_CHFILT_Q2, 0x00, /* Channel Filter Data Imaginary Part [18:16] */ + CC1120_CHFILT_Q1, 0x00, /* Channel Filter Data Imaginary Part [15:8] */ + CC1120_CHFILT_Q0, 0x00, /* Channel Filter Data Imaginary Part [7:0] */ + CC1120_GPIO_STATUS, 0x00, /* GPIO Status */ + CC1120_FSCAL_CTRL, 0x01, /* */ + CC1120_PHASE_ADJUST, 0x00, /* */ + CC1120_PARTNUMBER, 0x00, /* Part Number */ + CC1120_PARTVERSION, 0x00, /* Part Revision */ + CC1120_SERIAL_STATUS, 0x00, /* Serial Status */ + CC1120_RX_STATUS, 0x01, /* RX Status */ + CC1120_TX_STATUS, 0x00, /* TX Status */ + CC1120_MARC_STATUS1, 0x00, /* MARC Status, Reg 1 */ + CC1120_MARC_STATUS0, 0x00, /* MARC Status, Reg 0 */ + CC1120_PA_IFAMP_TEST, 0x00, /* */ + CC1120_FSRF_TEST, 0x00, /* */ + CC1120_PRE_TEST, 0x00, /* */ + CC1120_PRE_OVR, 0x00, /* */ + CC1120_ADC_TEST, 0x00, /* ADC Test */ + CC1120_DVC_TEST, 0x0b, /* DVC Test */ + CC1120_ATEST, 0x40, /* */ + CC1120_ATEST_LVDS, 0x00, /* */ + CC1120_ATEST_MODE, 0x00, /* */ + CC1120_XOSC_TEST1, 0x3c, /* */ + CC1120_XOSC_TEST0, 0x00, /* */ + CC1120_RXFIRST, 0x00, /* RX FIFO Pointer (first entry) */ + CC1120_TXFIRST, 0x00, /* TX FIFO Pointer (first entry) */ + CC1120_RXLAST, 0x00, /* RX FIFO Pointer (last entry) */ + CC1120_TXLAST, 0x00, /* TX FIFO Pointer (last entry) */ + diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c new file mode 100644 index 00000000..19fe0558 --- /dev/null +++ b/src/drivers/ao_packet.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_seq; + +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_send(void) +{ +#ifdef AO_LED_RED + ao_led_on(AO_LED_RED); +#endif + /* If any tx data is pending then copy it into the tx packet */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; + ao_wakeup(&tx_data); + } + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED + ao_led_off(AO_LED_RED); +#endif +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + +#ifdef AO_LED_GREEN + ao_led_on(AO_LED_GREEN); +#endif + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); +#ifdef AO_LED_GREEN + ao_led_off(AO_LED_GREEN); +#endif + + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; +#ifdef PKT_APPEND_STATUS_1_CRC_OK + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; +#endif + + /* Accept packets with matching call signs, or any packet if + * our callsign hasn't been configured + */ + if (ao_xmemcmp(ao_rx_packet.packet.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN) != 0 && + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); + } + } + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; +} + +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER +void +ao_packet_flush(void) +{ + /* If there is data to send, and this is the master, + * then poke the master to send all queued data + */ + if (ao_packet_tx_used && ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); +} +#endif /* PACKET_HAS_MASTER */ + +void +ao_packet_putchar(char c) __reentrant +{ + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER + ao_packet_flush(); +#endif + ao_sleep(&tx_data); + } + + if (ao_packet_enable) + tx_data[ao_packet_tx_used++] = c; +} + +char +ao_packet_pollchar(void) __critical +{ + if (!ao_packet_enable) + return AO_READ_AGAIN; + + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; + + return rx_data[ao_packet_rx_used++]; +} diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c new file mode 100644 index 00000000..66f94288 --- /dev/null +++ b/src/drivers/ao_packet_master.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static char +ao_packet_getchar(void) __critical +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); + flush(); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + char c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (c != AO_READ_AGAIN) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + ao_config_get(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + uint8_t r; + ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + r = ao_packet_recv(); + ao_clear_alarm(); + if (r) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + ao_packet_master_sleeping = 1; + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); + ao_clear_alarm(); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); +#if HAS_MONITOR + ao_monitor_disable(); +#endif + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + 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; + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); + ao_delay(AO_MS_TO_TICKS(10)); + } +#if HAS_MONITOR + ao_monitor_enable(); +#endif +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c new file mode 100644 index 00000000..fd5d443e --- /dev/null +++ b/src/drivers/ao_packet_slave.c @@ -0,0 +1,66 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_packet_slave(void) +{ + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + if (ao_packet_recv()) { + ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif + ao_packet_send(); + } + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } +} + +void +ao_packet_slave_stop(void) +{ + if (ao_packet_enable) { + ao_packet_enable = 0; + while (ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); + } + } +} + +void +ao_packet_slave_init(uint8_t enable) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + NULL); + if (enable) + ao_packet_slave_start(); +} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 3c3d7173..37832d16 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -41,7 +41,10 @@ ALTOS_SRC = \ ao_beep_stm.c \ ao_storage.c \ ao_m25.c \ - ao_usb_stm.c + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_packet.c \ + ao_packet_slave.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 9efde598..d93480f2 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -15,7 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include void beep(void) @@ -51,6 +52,8 @@ main(void) ao_adc_init(); ao_storage_init(); ao_usb_init(); + ao_exti_init(); + ao_radio_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f761e5c3..2e83de8a 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -193,4 +193,17 @@ struct ao_adc { #define AO_M25_SPI_CS_MASK (1 << 3) #define AO_M25_SPI_BUS STM_SPI_INDEX(2) +/* + * Radio (cc1120) + */ + +#define AO_CC1120_SPI_CS_PORT stm_gpioc +#define AO_CC1120_SPI_CS_PIN 5 +#define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) + +#define AO_CC1120_INT_PORT stm_gpioc +#define AO_CC1120_INT_PIN 14 + +#define AO_CC1120_INT_GPIO 2 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 76962a3e..3edfa41d 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -16,7 +16,7 @@ ifndef VERSION include ../Version endif -AO_CFLAGS=-I. -I../stm -I../core -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 309937d5..05bb7784 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -31,9 +31,15 @@ ao_spi_put(uint8_t spi_index); void ao_spi_send(void *block, uint16_t len, uint8_t spi_index); +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); + void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); + void ao_spi_init(void); @@ -47,7 +53,7 @@ ao_spi_init(void); ao_spi_put(bus); \ } while (0) -#define ao_stm_enable_port(port) do { \ +#define ao_enable_port(port) do { \ if (&(port) == &stm_gpioa) \ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ else if (&(port) == &stm_gpiob) \ @@ -61,29 +67,29 @@ ao_spi_init(void); } while (0) -#define ao_stm_enable_cs(port,bit) do { \ +#define ao_enable_cs(port,bit) do { \ stm_gpio_set(&(port), bit, 1); \ stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \ } while (0) #define ao_spi_init_cs(port, mask) do { \ - ao_stm_enable_port(port); \ - if (mask & 0x0001) ao_stm_enable_cs(port, 0); \ - if (mask & 0x0002) ao_stm_enable_cs(port, 1); \ - if (mask & 0x0004) ao_stm_enable_cs(port, 2); \ - if (mask & 0x0008) ao_stm_enable_cs(port, 3); \ - if (mask & 0x0010) ao_stm_enable_cs(port, 4); \ - if (mask & 0x0020) ao_stm_enable_cs(port, 5); \ - if (mask & 0x0040) ao_stm_enable_cs(port, 6); \ - if (mask & 0x0080) ao_stm_enable_cs(port, 7); \ - if (mask & 0x0100) ao_stm_enable_cs(port, 8); \ - if (mask & 0x0200) ao_stm_enable_cs(port, 9); \ - if (mask & 0x0400) ao_stm_enable_cs(port, 10); \ - if (mask & 0x0800) ao_stm_enable_cs(port, 11); \ - if (mask & 0x1000) ao_stm_enable_cs(port, 12); \ - if (mask & 0x2000) ao_stm_enable_cs(port, 13); \ - if (mask & 0x4000) ao_stm_enable_cs(port, 14); \ - if (mask & 0x8000) ao_stm_enable_cs(port, 15); \ + ao_enable_port(port); \ + if ((mask) & 0x0001) ao_enable_cs(port, 0); \ + if ((mask) & 0x0002) ao_enable_cs(port, 1); \ + if ((mask) & 0x0004) ao_enable_cs(port, 2); \ + if ((mask) & 0x0008) ao_enable_cs(port, 3); \ + if ((mask) & 0x0010) ao_enable_cs(port, 4); \ + if ((mask) & 0x0020) ao_enable_cs(port, 5); \ + if ((mask) & 0x0040) ao_enable_cs(port, 6); \ + if ((mask) & 0x0080) ao_enable_cs(port, 7); \ + if ((mask) & 0x0100) ao_enable_cs(port, 8); \ + if ((mask) & 0x0200) ao_enable_cs(port, 9); \ + if ((mask) & 0x0400) ao_enable_cs(port, 10);\ + if ((mask) & 0x0800) ao_enable_cs(port, 11);\ + if ((mask) & 0x1000) ao_enable_cs(port, 12);\ + if ((mask) & 0x2000) ao_enable_cs(port, 13);\ + if ((mask) & 0x4000) ao_enable_cs(port, 14);\ + if ((mask) & 0x8000) ao_enable_cs(port, 15);\ } while (0) /* ao_dma_stm.c diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 21390748..e76c8e8c 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -109,6 +109,7 @@ void ao_dma_abort(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_wakeup(&ao_dma_done[index]); } void diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h new file mode 100644 index 00000000..43eaa52f --- /dev/null +++ b/src/stm/ao_exti.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 + +void +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c new file mode 100644 index 00000000..013d453b --- /dev/null +++ b/src/stm/ao_exti_stm.c @@ -0,0 +1,109 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +static void (*ao_exti_callback[16])(void); + +static void +ao_exti_isr(void) { + uint32_t pending = stm_exti.pr; + uint8_t pin; + + /* Clear pending interrupts */ + stm_exti.pr = pending; + for (pin = 0; pin < 16 && pending; pin++) { + uint32_t mask = (1 << pin); + + if (pending & mask) { + pending &= ~mask; + if (ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); + } + } +} + +void stm_exti0_isr(void) { ao_exti_isr(); } +void stm_exti1_isr(void) { ao_exti_isr(); } +void stm_exti2_isr(void) { ao_exti_isr(); } +void stm_exti3_isr(void) { ao_exti_isr(); } +void stm_exti4_isr(void) { ao_exti_isr(); } +void stm_exti9_5_isr(void) { ao_exti_isr(); } +void stm_exti15_10_isr(void) { ao_exti_isr(); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint32_t mask = 1 << pin; + uint32_t pupdr; + uint8_t irq; + + ao_exti_callback[pin] = callback; + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); + + /* Set interrupt mask and rising/falling mode */ + stm_exti.imr &= ~mask; + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + + if (pin <= 4) + irq = STM_ISR_EXTI0_POS + pin; + else if (pin <= 9) + irq = STM_ISR_EXTI9_5_POS; + else + irq = STM_ISR_EXTI15_10_POS; + stm_nvic_set_priority(irq, 10); + stm_nvic_set_enable(irq); +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr |= (1 << pin); +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr &= ~(1 << pin); +} + +void +ao_exti_init(void) +{ + stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index be24ebcf..8bb0d8e8 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -96,6 +96,62 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) ao_dma_done_transfer(miso_dma_index); } +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &value, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) { @@ -153,6 +209,63 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) ao_dma_done_transfer(miso_dma_index); } +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + /* Set up transmit DMA to send data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + out, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + in, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + void ao_spi_get(uint8_t spi_index) { diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 223fdeaa..71bf1bc7 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -1005,6 +1005,7 @@ ao_usb_echo(void) } #endif +#if USB_DEBUG static void ao_usb_irq(void) { @@ -1016,6 +1017,7 @@ __code struct ao_cmds ao_usb_cmds[] = { { ao_usb_irq, "I\0Show USB interrupt counts" }, { 0, NULL } }; +#endif void ao_usb_init(void) @@ -1027,7 +1029,9 @@ ao_usb_init(void) #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif +#if USB_DEBUG ao_cmd_register(&ao_usb_cmds[0]); +#endif #if !USB_ECHO ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e884ef04..10a53a47 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -101,13 +101,13 @@ stm_ospeedr_get(struct stm_gpio *gpio, int pin) { #define STM_PUPDR_RESERVED 3 static inline void -stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { +stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { gpio->pupdr = ((gpio->pupdr & ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | value << STM_PUPDR_SHIFT(pin)); } -static inline vuint32_t +static inline uint32_t stm_pupdr_get(struct stm_gpio *gpio, int pin) { return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; } @@ -1589,4 +1589,16 @@ union stm_usb_bdt { extern uint8_t stm_usb_sram[]; +struct stm_exti { + vuint32_t imr; + vuint32_t emr; + vuint32_t rtsr; + vuint32_t ftsr; + + vuint32_t swier; + vuint32_t pr; +}; + +extern struct stm_exti stm_exti; + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 5f55d0490017faa19b8d70b1742e4a45266c7e79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Apr 2012 22:26:16 -0500 Subject: altosui: Mac OS Lion Java default heap space is too small (Trac #37) Increase it to 512M in the Info.plist file. Signed-off-by: Keith Packard --- altosui/AltosUI.app/Contents/Info.plist | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/altosui/AltosUI.app/Contents/Info.plist b/altosui/AltosUI.app/Contents/Info.plist index 97b1b59c..60842804 100644 --- a/altosui/AltosUI.app/Contents/Info.plist +++ b/altosui/AltosUI.app/Contents/Info.plist @@ -29,10 +29,16 @@ JVMVersion 1.5+ ClassPath - + $JAVAROOT/altosui.jar $JAVAROOT/freetts.jar - + + VMOptions + + -Xms512M + -Xmx512M + -Dosgi.clean=true + -- cgit v1.2.3 From 962476911aaab17fd482593a0e8b95fe47de2f29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:25:43 -0700 Subject: altos: Oopsed the STM DMA channels for I2C1 TX is 6, RX is 7 Signed-off-by: Keith Packard --- src/stm/stm32l.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 10a53a47..0bc7483e 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -953,8 +953,8 @@ extern struct stm_dma stm_dma; #define STM_DMA_CHANNEL_USART2_TX 7 #define STM_DMA_CHANNEL_I2C2_TX 4 #define STM_DMA_CHANNEL_I2C2_RX 5 -#define STM_DMA_CHANNEL_I2C1_RX 6 -#define STM_DMA_CHANNEL_I2C1_TX 7 +#define STM_DMA_CHANNEL_I2C1_TX 6 +#define STM_DMA_CHANNEL_I2C1_RX 7 #define STM_DMA_CHANNEL_TIM2_CH3 1 #define STM_DMA_CHANNEL_TIM2_UP 2 #define STM_DMA_CHANNEL_TIM2_CH1 5 -- cgit v1.2.3 From 0266e08dbf19e2204fb5f758d5d0f944d2afff7d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:26:57 -0700 Subject: altos: Add STM I2C recv and stop funcs Recv doesn't appear to work with more than one byte Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 3 +++ src/stm/ao_i2c_stm.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 05bb7784..3027b337 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -130,6 +130,9 @@ ao_i2c_get(uint8_t i2c_index); uint8_t ao_i2c_start(uint8_t i2c_index, uint16_t address); +void +ao_i2c_stop(uint8_t i2c_index); + void ao_i2c_put(uint8_t i2c_index); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 1a0280d3..0717be98 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -134,12 +134,22 @@ ao_i2c_start(uint8_t index, uint16_t addr) return ao_i2c_state[index] == I2C_RUNNING; } +void +ao_i2c_stop(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + ao_i2c_state[index] = I2C_IDLE; + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); +} + void ao_i2c_send(void *block, uint16_t len, uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_LAST); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -161,6 +171,34 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index) ao_dma_done_transfer(tx_dma_index); } +void +ao_i2c_recv(void *block, uint16_t len, uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + + stm_i2c->cr2 |= (1 << STM_I2C_CR2_LAST); + ao_dma_set_transfer(rx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + ao_dma_start(rx_dma_index); + cli(); + while (!ao_dma_done[rx_dma_index]) + ao_sleep(&ao_dma_done[rx_dma_index]); + sei(); + ao_dma_done_transfer(rx_dma_index); +} + void ao_i2c_channel_init(uint8_t index) { -- cgit v1.2.3 From e0b8c614ec4d11f432963e48d94e4497d31a9ddc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:27:58 -0700 Subject: altos: Add mpu6000 and hmc5883 stubs No real drivers here yet, just some testing stubs Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_hmc5883.h | 41 ++++++++++++++ src/drivers/ao_mpu6000.c | 97 +++++++++++++++++++++++++++++++++ src/drivers/ao_mpu6000.h | 30 ++++++++++ 4 files changed, 307 insertions(+) create mode 100644 src/drivers/ao_hmc5883.c create mode 100644 src/drivers/ao_hmc5883.h create mode 100644 src/drivers/ao_mpu6000.c create mode 100644 src/drivers/ao_mpu6000.h diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c new file mode 100644 index 00000000..0077daf9 --- /dev/null +++ b/src/drivers/ao_hmc5883.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +static uint8_t ao_hmc5883_wake; +static uint8_t ao_hmc5883_configured; + +static void +ao_hmc5883_isr(void) +{ + ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_wake = 1; + ao_wakeup(&ao_hmc5883_wake); +} + +static uint8_t ao_hmc5883_addr_reg; + +static void +ao_hmc5883_update_addr (uint8_t len) +{ + ao_hmc5883_addr_reg += len; + if (ao_hmc5883_addr_reg == 9) + ao_hmc5883_addr_reg = 3; + else if (ao_hmc5883_addr_reg > 12) + ao_hmc5883_addr_reg = 0; + +} + +static void +ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + if (len) { + ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static void +ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + if (addr != ao_hmc5883_addr_reg) { + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + } + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + if (len) { + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static uint8_t +ao_hmc5883_setup(void) +{ + uint8_t present; + if (ao_hmc5883_configured) + return 1; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_HMC5883_INT_PORT); + ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, + AO_EXTI_MODE_FALLING, ao_hmc5883_isr); + + ao_hmc5883_addr_reg = 0xff; + + ao_i2c_get(AO_HMC5883_I2C_INDEX); + present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (!present) + return 0; + ao_hmc5883_configured = 1; + return 1; +} + +static void +ao_hmc5883_show(void) +{ + uint8_t addr, data; + + for (addr = 0x00; addr <= 0x7f; addr++) + { + ao_i2c_get(AO_HMC5883_I2C_INDEX); + data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (data) + printf("address %02x responds\n", addr << 1); + } + if (!ao_hmc5883_setup()) { + printf("hmc5883 not present\n"); + return; + } + for (addr = 0; addr <= 12; addr++) { + ao_hmc5883_read(addr, &data, 1); + printf ("hmc5883 register %2d: %02x\n", + addr, data); + } +} + +static const struct ao_cmds ao_hmc5883_cmds[] = { + { ao_hmc5883_show, "M\0Show HMC5883 status" }, + { 0, NULL } +}; + +void +ao_hmc5883_init(void) +{ + ao_hmc5883_configured = 0; + + ao_cmd_register(&ao_hmc5883_cmds[0]); +} diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h new file mode 100644 index 00000000..399ddcdd --- /dev/null +++ b/src/drivers/ao_hmc5883.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_HMC5883_H_ +#define _AO_HMC5883_H_ + +#define HMC5883_ADDR_WRITE 0x3c +#define HMC5883_ADDR_READ 0x3d + +#define HMC5883_CONFIG_A 0 +#define HMC5883_CONFIG_B 1 +#define HMC5883_MODE 2 +#define HMC5883_X_MSB 3 +#define HMC5883_X_LSB 4 +#define HMC5883_Y_MSB 5 +#define HMC5883_Y_LSB 6 +#define HMC5883_Z_MSB 7 +#define HMC5883_Z_LSB 8 +#define HMC5883_STATUS 9 +#define HMC5883_ID_A 10 +#define HMC5883_ID_B 11 +#define HMC5883_ID_C 12 + +void +ao_hmc5883_init(void); + +#endif /* _AO_HMC5883_H_ */ diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c new file mode 100644 index 00000000..290f1390 --- /dev/null +++ b/src/drivers/ao_mpu6000.c @@ -0,0 +1,97 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +static uint8_t ao_mpu6000_wake; +static uint8_t ao_mpu6000_configured; + +static void +ao_mpu6000_isr(void) +{ + ao_exti_disable(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN); + ao_mpu6000_wake = 1; + ao_wakeup(&ao_mpu6000_wake); +} + +static void +ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + if (len) + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); + if (len) + ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_setup(void) +{ + if (ao_mpu6000_configured) + return; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_MPU6000_INT_PORT); + ao_exti_setup(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN, + AO_EXTI_MODE_FALLING, ao_mpu6000_isr); + + ao_mpu6000_configured = 1; +} + +static void +ao_mpu6000_show(void) +{ + uint8_t addr; + uint8_t data[14]; + uint8_t i; + + ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); + printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); + for (i = 0; i < 14; i++) + printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +} + +static const struct ao_cmds ao_mpu6000_cmds[] = { + { ao_mpu6000_show, "I\0Show MPU6000 status" }, + { 0, NULL } +}; + +void +ao_mpu6000_init(void) +{ + ao_mpu6000_configured = 0; + + ao_cmd_register(&ao_mpu6000_cmds[0]); +} diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h new file mode 100644 index 00000000..d436a3e0 --- /dev/null +++ b/src/drivers/ao_mpu6000.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MPU6000_H_ +#define _AO_MPU6000_H_ + +#define MPU6000_ADDR_WRITE 0xd0 +#define MPU6000_ADDR_READ 0xd1 + +#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_WHO_AM_I 0x75 + +void +ao_mpu6000_init(void); + +#endif /* _AO_MPU6000_H_ */ -- cgit v1.2.3 From 7b0b6bcc40891d8dd106d091d3af8107b2941c66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:29:20 -0700 Subject: altos: Add hmc5883 and mpu6000 drivers to megametrum build Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 12 +++++++++--- src/megametrum-v0.1/ao_megametrum.c | 4 ++++ src/megametrum-v0.1/ao_pins.h | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 37832d16..5d73c1d0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -13,7 +13,10 @@ INC = \ altitude.h \ ao_kalman.h \ ao_product.h \ - ao_ms5607.h + ao_ms5607.h \ + ao_hmc5883.h \ + ao_mpu6000.h \ + stm32l.h # # Common AltOS sources @@ -44,13 +47,16 @@ ALTOS_SRC = \ ao_usb_stm.c \ ao_exti_stm.c \ ao_packet.c \ - ao_packet_slave.c + ao_packet_slave.c \ + ao_i2c_stm.c \ + ao_hmc5883.c \ + ao_mpu6000.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index d93480f2..8283f533 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -16,6 +16,7 @@ */ #include +#include #include void @@ -54,6 +55,9 @@ main(void) ao_usb_init(); ao_exti_init(); ao_radio_init(); + ao_i2c_init(); + ao_hmc5883_init(); + ao_mpu6000_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2e83de8a..cd270739 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,7 +42,7 @@ #define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 #define HAS_SERIAL_1 1 -#define USE_SERIAL_1_STDIN 1 +#define USE_SERIAL_1_STDIN 0 #define SERIAL_1_PB6_PB7 0 #define SERIAL_1_PA9_PA10 1 @@ -206,4 +206,20 @@ struct ao_adc { #define AO_CC1120_INT_GPIO 2 +/* + * Mag sensor (hmc5883) + */ + +#define AO_HMC5883_INT_PORT stm_gpioc +#define AO_HMC5883_INT_PIN 12 +#define AO_HMC5883_I2C_INDEX STM_SPI_INDEX(1) + +/* + * mpu6000 + */ + +#define AO_MPU6000_INT_PORT stm_gpioc +#define AO_MPU6000_INT_PIN 13 +#define AO_MPU6000_I2C_INDEX STM_SPI_INDEX(1) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 8b08095b3d41e21684a10bddfb54431019da5af6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 May 2012 11:08:49 -0700 Subject: altos: Report latest telemetry data, rather than using the oldest ao_sample_adc points to the *next* ADC entry, rather than the most recent one. Step back one entry to get the latest valid data. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index eb614b0f..46d72609 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,8 +53,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample; - sample = ao_sample_adc; + uint8_t sample = ao_adc_ring_prev(ao_sample_adc); telemetry.generic.tick = ao_adc_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; -- cgit v1.2.3 From 69feb1e3d94a028d04529edb015654bafd06353b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 May 2012 18:12:41 -0700 Subject: ao-tools: Add GPS and rssi printing to ao-telem This prints all of the basic telemetrum messages now. Signed-off-by: Keith Packard --- ao-tools/ao-telem/ao-telem.c | 64 +++++++++++++++++++++++++++++++++++++++----- ao-tools/lib/cc-telemetry.c | 2 +- ao-tools/lib/cc-telemetry.h | 4 ++- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c index 0f671e1b..6207d433 100644 --- a/ao-tools/ao-telem/ao-telem.c +++ b/ao-tools/ao-telem/ao-telem.c @@ -34,6 +34,8 @@ static void usage(char *program) exit(1); } +#define bool(b) ((b) ? "true" : "false") + int main (int argc, char **argv) { @@ -63,21 +65,28 @@ main (int argc, char **argv) serial = 0; while (fgets(line, sizeof (line), file)) { union ao_telemetry_all telem; - char call[AO_MAX_CALLSIGN+1]; + char call[AO_MAX_CALLSIGN+1]; char version[AO_MAX_VERSION+1]; if (cc_telemetry_parse(line, &telem)) { - printf ("serial %5d tick %5d type %3d ", - telem.generic.serial, telem.generic.tick, telem.generic.type); + int rssi = (int8_t) telem.generic.rssi / 2 - 74; + + printf ("serial %5d rssi %d status %02x tick %5d type %3d ", + telem.generic.serial, rssi, telem.generic.status, + telem.generic.tick, telem.generic.type); + if ((telem.generic.status & (1 << 7)) == 0) { + printf ("CRC error\n"); + continue; + } switch (telem.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: case AO_TELEMETRY_SENSOR_TELENANO: printf ("state %1d accel %5d pres %5d ", telem.sensor.state, telem.sensor.accel, telem.sensor.pres); - printf ("accel %5d speed %5d height %5d ", - telem.sensor.acceleration, - telem.sensor.speed, + printf ("accel %6.2f speed %6.2f height %5d ", + telem.sensor.acceleration / 16.0, + telem.sensor.speed / 16.0, telem.sensor.height); printf ("ground_pres %5d ground_accel %5d accel_plus %5d accel_minus %5d\n", telem.sensor.ground_pres, @@ -100,6 +109,49 @@ main (int argc, char **argv) telem.configuration.flight_log_max); printf (" call %8s version %8s\n", call, version); break; + case AO_TELEMETRY_LOCATION: + printf ("sats %d flags %s%s%s%s", + telem.location.flags & 0xf, + (telem.location.flags & (1 << 4)) ? "valid" : "invalid", + (telem.location.flags & (1 << 5)) ? ",running" : "", + (telem.location.flags & (1 << 6)) ? ",date" : "", + (telem.location.flags & (1 << 7)) ? ",course" : ""); + printf (" alt %5d lat %12.7f lon %12.7f", + telem.location.altitude, + telem.location.latitude / 1e7, + telem.location.longitude / 1e7); + if ((telem.location.flags & (1 << 6)) != 0) { + printf (" year %2d month %2d day %2d", + telem.location.year, + telem.location.month, + telem.location.day); + printf (" hour %2d minute %2d second %2d", + telem.location.hour, + telem.location.minute, + telem.location.second); + } + printf (" pdop %3.1f hdop %3.1f vdop %3.1f mode %d", + telem.location.pdop / 5.0, + telem.location.hdop / 5.0, + telem.location.vdop / 5.0, + telem.location.mode); + if ((telem.location.flags & (1 << 7)) != 0) + printf (" ground_speed %6.2f climb_rate %6.2f course %d", + telem.location.ground_speed / 100.0, + telem.location.climb_rate / 100.0, + telem.location.course * 2); + printf ("\n"); + break; + case AO_TELEMETRY_SATELLITE: + printf ("sats %d", telem.satellite.channels); + for (c = 0; c < 12 && c < telem.satellite.channels; c++) { + printf (" sat %d svid %d c_n_1 %d", + c, + telem.satellite.sats[c].svid, + telem.satellite.sats[c].c_n_1); + } + printf ("\n"); + break; default: printf("\n"); } diff --git a/ao-tools/lib/cc-telemetry.c b/ao-tools/lib/cc-telemetry.c index 2cdb9cac..99da2680 100644 --- a/ao-tools/lib/cc-telemetry.c +++ b/ao-tools/lib/cc-telemetry.c @@ -57,6 +57,6 @@ cc_telemetry_parse(const char *input_line, union ao_telemetry_all *telemetry) } if (hex[0] != 34) return FALSE; - memcpy(telemetry, hex+1, 32); + memcpy(telemetry, hex+1, 34); return TRUE; } diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h index 5a66b971..71f6844d 100644 --- a/ao-tools/lib/cc-telemetry.h +++ b/ao-tools/lib/cc-telemetry.h @@ -29,7 +29,9 @@ struct ao_telemetry_generic { uint16_t tick; /* 2 */ uint8_t type; /* 4 */ uint8_t payload[27]; /* 5 */ - /* 32 */ + uint8_t rssi; /* 32 */ + uint8_t status; /* 33 */ + /* 34 */ }; #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -- cgit v1.2.3 From 0f0cc91ce8e9807dca48a5c0c53d821f5060e245 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:47:33 -0700 Subject: altos: STM i2c work. Start now driven by interrupts Send now done with DMA and interrupts Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 22 ++-- src/drivers/ao_mpu6000.c | 16 +-- src/stm/ao_arch_funcs.h | 13 +- src/stm/ao_i2c_stm.c | 328 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 327 insertions(+), 52 deletions(-) diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 0077daf9..43d04f70 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -48,13 +48,10 @@ ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); ao_hmc5883_addr_reg = addr; - if (len) { - ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); - ao_hmc5883_update_addr(len); - } - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX, TRUE); + ao_hmc5883_update_addr(len); ao_i2c_put(AO_HMC5883_I2C_INDEX); } @@ -64,15 +61,12 @@ ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) ao_i2c_get(AO_HMC5883_I2C_INDEX); if (addr != ao_hmc5883_addr_reg) { ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); ao_hmc5883_addr_reg = addr; } ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - if (len) { - ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); - ao_hmc5883_update_addr(len); - } - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); + ao_hmc5883_update_addr(len); ao_i2c_put(AO_HMC5883_I2C_INDEX); } @@ -92,7 +86,7 @@ ao_hmc5883_setup(void) ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); if (!present) return 0; @@ -109,7 +103,7 @@ ao_hmc5883_show(void) { ao_i2c_get(AO_HMC5883_I2C_INDEX); data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); if (data) printf("address %02x responds\n", addr << 1); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 290f1390..d7f67d6e 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -35,10 +35,8 @@ ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); - if (len) - ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); - ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } @@ -47,11 +45,9 @@ ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); - if (len) - ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); - ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } @@ -78,9 +74,11 @@ ao_mpu6000_show(void) ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); - ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); +#if 0 + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 14); for (i = 0; i < 14; i++) printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +#endif } static const struct ao_cmds ao_mpu6000_cmds[] = { diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 3027b337..447042dd 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -105,7 +105,7 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr); void -ao_dma_set_isr(uint8_t index, void (*isr)(void)); +ao_dma_set_isr(uint8_t index, void (*isr)(int index)); void ao_dma_start(uint8_t index); @@ -130,17 +130,14 @@ ao_i2c_get(uint8_t i2c_index); uint8_t ao_i2c_start(uint8_t i2c_index, uint16_t address); -void -ao_i2c_stop(uint8_t i2c_index); - void ao_i2c_put(uint8_t i2c_index); -void -ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); -void -ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 0717be98..9ab001d7 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -23,6 +23,8 @@ struct ao_i2c_stm_info { struct stm_i2c *stm_i2c; }; +#define I2C_TIMEOUT 100 + #define I2C_IDLE 0 #define I2C_RUNNING 1 #define I2C_ERROR 2 @@ -47,7 +49,7 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; (1 << STM_I2C_CR1_PE)) #define AO_STM_I2C_CR2 ((0 << STM_I2C_CR2_LAST) | \ - (1 << STM_I2C_CR2_DMAEN) | \ + (0 << STM_I2C_CR2_DMAEN) | \ (0 << STM_I2C_CR2_ITBUFEN) | \ (0 << STM_I2C_CR2_ITEVTEN) | \ (0 << STM_I2C_CR2_ITERREN) | \ @@ -66,20 +68,44 @@ static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { }, }; +static uint8_t *ao_i2c_recv_data[STM_NUM_I2C]; +static uint16_t ao_i2c_recv_len[STM_NUM_I2C]; +static uint16_t ev_count; + static void ao_i2c_ev_isr(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint32_t sr1; + ++ev_count; sr1 = stm_i2c->sr1; if (sr1 & (1 << STM_I2C_SR1_SB)) stm_i2c->dr = ao_i2c_addr[index]; if (sr1 & (1 << STM_I2C_SR1_ADDR)) { - (void) stm_i2c->sr2; + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); ao_i2c_state[index] = I2C_RUNNING; ao_wakeup(&ao_i2c_state[index]); } + if (sr1 & (1 << STM_I2C_SR1_BTF)) { + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); + ao_wakeup(&ao_i2c_state[index]); + } +#if 0 + if (sr1 & (1 << STM_I2C_SR1_RXNE)) { + if (ao_i2c_recv_len[index]) { + switch (--ao_i2c_recv_len[index]) { + case 0: + ao_wakeup(&ao_i2c_recv_len[index]); + break; + case 1: + stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK); + break; + } + *(ao_i2c_recv_data[index]++) = stm_i2c->dr; + } + } +#endif } void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } @@ -118,38 +144,205 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { + uint32_t sr1 = stm_i2c->sr1; + printf("%s: sr1: %x\n", where, sr1); flush(); + return sr1; +} + +static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { + uint32_t sr2 = stm_i2c->sr2; + printf("%s: sr2: %x\n", where, sr2); flush(); + return sr2; +} + +static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { + printf("%s: cr1: %x\n", where, cr1); flush(); + stm_i2c->cr1 = cr1; +} + +static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { + uint32_t cr1 = stm_i2c->cr1; + printf("%s: cr1: %x\n", where, cr1); flush(); + return cr1; +} + +static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { + printf("%s: cr2: %x\n", where, cr2); flush(); + stm_i2c->cr2 = cr2; +} + +static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { + uint32_t dr = stm_i2c->dr; + printf("%s: dr: %x\n", where, dr); flush(); + return dr; +} + +static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { + printf("%s: dr: %x\n", where, dr); flush(); + stm_i2c->dr = dr; +} + uint8_t -ao_i2c_start(uint8_t index, uint16_t addr) +ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1_got, sr2_got; + + if (sr1_want) { + sr1_got = in_sr1(where, stm_i2c); + if ((sr1_got & sr1_want) != sr1_want) { + printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got); + return FALSE; + } + } + if (sr2_want) { + sr2_got = in_sr2(where, stm_i2c); + if ((sr2_got & sr2_want) != sr2_want) { + printf ("%s: sr1 wanted %x got %x\n", + where, sr2_want, sr2_got); + return FALSE; + } + } + printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want); + return TRUE; +} + +static uint8_t +ao_i2c_check_idle(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t s = 0; + int t; + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!ao_i2c_check_status("check idle", index, + 0, + (1 << STM_I2C_SR2_BUSY))) + { + break; + } + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + return TRUE; +} + +uint8_t +ao_i2c_start(uint8_t index, uint16_t addr) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1, sr2; + int t; + +#if 0 + if (!ao_i2c_check_idle(index)) { + printf ("i2c busy\n"); + return FALSE; + } +#endif + ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); - ao_arch_critical( - while (ao_i2c_state[index] == I2C_IDLE) - ao_sleep(&ao_i2c_state[index]); - ); +#if 0 + out_cr2("start", stm_i2c, AO_STM_I2C_CR2); + out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("waiting for start", + index, + (1 << STM_I2C_SR1_SB), + (1 << STM_I2C_SR2_BUSY) | + (1 << STM_I2C_SR2_MSL))) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) { + printf ("No start mode\n"); + return FALSE; + } + out_dr("address", stm_i2c, addr); + if (addr & 1) { + sr1 = (1 << STM_I2C_SR1_ADDR); + sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); + } else { + sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR); + sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); + } + + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("waiting for addr", + index, + sr1, sr2)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) { + printf ("Set addr failed\n"); + return FALSE; + } + ao_i2c_state[index] = I2C_RUNNING; +#else + out_cr2("start", stm_i2c, AO_STM_I2C_CR2); + out_cr1("start", stm_i2c, + AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + out_cr2("start", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + ao_alarm(1); + cli(); + while (ao_i2c_state[index] == I2C_IDLE) + if (ao_sleep(&ao_i2c_state[index])) + break; + sei(); + ao_clear_alarm(); +#endif return ao_i2c_state[index] == I2C_RUNNING; } -void +static void ao_i2c_stop(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; ao_i2c_state[index] = I2C_IDLE; - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); + out_cr2("enable isr", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + ev_count = 0; + out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + + /* XXX check to see if there is an interrupt here */ + while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)) + ao_yield(); + printf ("ev_count in stop: %d\n", ev_count); } -void -ao_i2c_send(void *block, uint16_t len, uint8_t index) +uint8_t +ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t *b = block; + uint32_t sr1; + int t; + +#if 0 + while (len--) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("send", index, + (1 << STM_I2C_SR1_TXE), + 0)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + out_dr("send", stm_i2c, *b++); + } +#else uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; - stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_LAST); + /* Clear any pending ADDR bit */ + in_sr2("send clear addr", stm_i2c); + out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN)); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -164,20 +357,104 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index) (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); ao_dma_start(tx_dma_index); - ao_arch_critical( - while (!ao_dma_done[tx_dma_index]) - ao_sleep(&ao_dma_done[tx_dma_index]); - ); + ao_alarm(1 + len); + cli(); + while (!ao_dma_done[tx_dma_index]) + if (ao_sleep(&ao_dma_done[tx_dma_index])) { + printf ("send timeout\n"); + break; + } ao_dma_done_transfer(tx_dma_index); + out_cr2("send enable isr", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0) + if (ao_sleep(&ao_i2c_state[index])) + break; + out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); + sei(); +#endif + if (stop) + ao_i2c_stop(index); + return TRUE; } void -ao_i2c_recv(void *block, uint16_t len, uint8_t index) +ao_i2c_recv_dma_isr(int index) +{ + int i; + struct stm_i2c *stm_i2c = NULL; + + for (i = 0; i < STM_NUM_I2C; i++) + if (index == ao_i2c_stm_info[i].rx_dma_index) { + stm_i2c = ao_i2c_stm_info[i].stm_i2c; + break; + } + if (!stm_i2c) + return; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); +} + +uint8_t +ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + uint8_t *b = block; + int t; + + switch (len) { + case 0: + return TRUE; + case 1: + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + /* Clear any pending ADDR bit */ + in_sr2("clear addr", stm_i2c); + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + break; + case 2: + /* Clear any pending ADDR bit */ + out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS)); + if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) + in_sr2("clear addr", stm_i2c); + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + break; + default: +// out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS)); + out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + /* Clear any pending ADDR bit */ + if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) + in_sr2("clear addr", stm_i2c); + break; + } + + while (len--) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + *b++ = in_dr("recv", stm_i2c); + if (len == 2 && stop) { + out_cr1("clear ack", stm_i2c, +// AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS)); + AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + } + } + if (stop) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + } - stm_i2c->cr2 |= (1 << STM_I2C_CR2_LAST); +#if 0 + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; ao_dma_set_transfer(rx_dma_index, &stm_i2c->dr, block, @@ -190,6 +467,13 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + if (len >= 2) { + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS); + stm_i2c->cr2 = AO_STM_I2C_CR2; + } else { + stm_i2c->cr1 = AO_STM_I2C_CR1; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); + } ao_dma_start(rx_dma_index); cli(); @@ -197,6 +481,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index) ao_sleep(&ao_dma_done[rx_dma_index]); sei(); ao_dma_done_transfer(rx_dma_index); +#endif } void @@ -219,6 +504,7 @@ ao_i2c_channel_init(uint8_t index) (0 << STM_I2C_CCR_DUTY) | (20 << STM_I2C_CCR_CCR)); + stm_i2c->cr1 = AO_STM_I2C_CR1; } -- cgit v1.2.3 From f66f5de7a6cae71948da777ad0638bc6267a710f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:52:56 -0700 Subject: altos: Switch megametrum compile to -Os Looks like gcc has compiler bugs with -O0 Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5d73c1d0..437e1a9e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -56,7 +56,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1-$(VERSION).elf -- cgit v1.2.3 From fad6cda3d081d438b18305611f37fe05335aa372 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:53:25 -0700 Subject: altos: megametrum needs ao_mpu6000.h Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_megametrum.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 8283f533..2e1f9298 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -17,6 +17,7 @@ #include #include +#include #include void -- cgit v1.2.3 From ddaf501ddcfc1a5f74a1ef1b6b76e1c82d89c77a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 23:54:13 -0700 Subject: altos: stm i2c DMA for large recv appears to work Transaction appears to be clean on the i2c bus now; correct number of bytes received, and the nack and stop at the right time. This tests > 2 length reads; should try that too. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 256 ++++++++++++++------------------------------------- 1 file changed, 70 insertions(+), 186 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 9ab001d7..e46211cd 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -91,21 +91,13 @@ ao_i2c_ev_isr(uint8_t index) stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); ao_wakeup(&ao_i2c_state[index]); } -#if 0 if (sr1 & (1 << STM_I2C_SR1_RXNE)) { if (ao_i2c_recv_len[index]) { - switch (--ao_i2c_recv_len[index]) { - case 0: - ao_wakeup(&ao_i2c_recv_len[index]); - break; - case 1: - stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK); - break; - } *(ao_i2c_recv_data[index]++) = stm_i2c->dr; + if (!--ao_i2c_recv_len[index]) + ao_wakeup(&ao_i2c_recv_len[index]); } } -#endif } void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } @@ -144,91 +136,52 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +#define I2C_DEBUG 0 +#if I2C_DEBUG +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { uint32_t sr1 = stm_i2c->sr1; - printf("%s: sr1: %x\n", where, sr1); flush(); + DBG("%s: sr1: %x\n", where, sr1); flush(); return sr1; } static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { uint32_t sr2 = stm_i2c->sr2; - printf("%s: sr2: %x\n", where, sr2); flush(); + DBG("%s: sr2: %x\n", where, sr2); flush(); return sr2; } static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - printf("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); flush(); stm_i2c->cr1 = cr1; } static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { uint32_t cr1 = stm_i2c->cr1; - printf("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); flush(); return cr1; } static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - printf("%s: cr2: %x\n", where, cr2); flush(); + DBG("%s: cr2: %x\n", where, cr2); flush(); stm_i2c->cr2 = cr2; } static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { uint32_t dr = stm_i2c->dr; - printf("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); flush(); return dr; } static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - printf("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); flush(); stm_i2c->dr = dr; } -uint8_t -ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want) -{ - struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint32_t sr1_got, sr2_got; - - if (sr1_want) { - sr1_got = in_sr1(where, stm_i2c); - if ((sr1_got & sr1_want) != sr1_want) { - printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got); - return FALSE; - } - } - if (sr2_want) { - sr2_got = in_sr2(where, stm_i2c); - if ((sr2_got & sr2_want) != sr2_want) { - printf ("%s: sr1 wanted %x got %x\n", - where, sr2_want, sr2_got); - return FALSE; - } - } - printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want); - return TRUE; -} - -static uint8_t -ao_i2c_check_idle(uint8_t index) -{ - struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint32_t s = 0; - int t; - - for (t = 0; t < I2C_TIMEOUT; t++) { - if (!ao_i2c_check_status("check idle", index, - 0, - (1 << STM_I2C_SR2_BUSY))) - { - break; - } - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - return TRUE; -} - uint8_t ao_i2c_start(uint8_t index, uint16_t addr) { @@ -236,53 +189,9 @@ ao_i2c_start(uint8_t index, uint16_t addr) uint32_t sr1, sr2; int t; -#if 0 - if (!ao_i2c_check_idle(index)) { - printf ("i2c busy\n"); - return FALSE; - } -#endif - ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; -#if 0 - out_cr2("start", stm_i2c, AO_STM_I2C_CR2); - out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("waiting for start", - index, - (1 << STM_I2C_SR1_SB), - (1 << STM_I2C_SR2_BUSY) | - (1 << STM_I2C_SR2_MSL))) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) { - printf ("No start mode\n"); - return FALSE; - } - out_dr("address", stm_i2c, addr); - if (addr & 1) { - sr1 = (1 << STM_I2C_SR1_ADDR); - sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); - } else { - sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR); - sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); - } - - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("waiting for addr", - index, - sr1, sr2)) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) { - printf ("Set addr failed\n"); - return FALSE; - } - ao_i2c_state[index] = I2C_RUNNING; -#else + printf ("start sr1: %x\n", stm_i2c->sr1); out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); @@ -295,7 +204,6 @@ ao_i2c_start(uint8_t index, uint16_t addr) break; sei(); ao_clear_alarm(); -#endif return ao_i2c_state[index] == I2C_RUNNING; } @@ -324,20 +232,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint32_t sr1; int t; -#if 0 - while (len--) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("send", index, - (1 << STM_I2C_SR1_TXE), - 0)) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - out_dr("send", stm_i2c, *b++); - } -#else uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ @@ -372,7 +266,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); sei(); -#endif if (stop) ao_i2c_stop(index); return TRUE; @@ -402,46 +295,66 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t *b = block; int t; + uint8_t ret = TRUE; - switch (len) { - case 0: + if (len == 0) return TRUE; - case 1: + if (len == 1) { + ao_i2c_recv_data[index] = block; + ao_i2c_recv_len[index] = 1; out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + /* Clear any pending ADDR bit */ in_sr2("clear addr", stm_i2c); - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - break; - case 2: - /* Clear any pending ADDR bit */ - out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS)); - if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) - in_sr2("clear addr", stm_i2c); - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - break; - default: -// out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS)); - out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + + /* Enable interrupts to transfer the byte */ + out_cr2("setup recv 1", stm_i2c, + AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_ITEVTEN) | + (1 << STM_I2C_CR2_ITERREN) | + (1 << STM_I2C_CR2_ITBUFEN)); + if (stop) + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + + ao_alarm(1); + cli(); + while (ao_i2c_recv_len[index]) + if (ao_sleep(&ao_i2c_recv_len[index])) + break; + sei(); + ret = ao_i2c_recv_len[index] == 0; + ao_clear_alarm(); + } else { + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + ao_dma_set_transfer(rx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + out_cr1("recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + out_cr2("recv > 1", stm_i2c, AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST)); /* Clear any pending ADDR bit */ - if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) - in_sr2("clear addr", stm_i2c); - break; - } + in_sr2("clear addr", stm_i2c); - while (len--) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE)) + ao_dma_start(rx_dma_index); + ao_alarm(len); + cli(); + while (!ao_dma_done[rx_dma_index]) + if (ao_sleep(&ao_dma_done[rx_dma_index])) break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - *b++ = in_dr("recv", stm_i2c); - if (len == 2 && stop) { - out_cr1("clear ack", stm_i2c, -// AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS)); - AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - } + sei(); + ao_clear_alarm(); + ret = ao_dma_done[rx_dma_index]; + ao_dma_done_transfer(rx_dma_index); + out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); } if (stop) { for (t = 0; t < I2C_TIMEOUT; t++) { @@ -452,36 +365,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) if (t == I2C_TIMEOUT) return FALSE; } - -#if 0 - uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; - ao_dma_set_transfer(rx_dma_index, - &stm_i2c->dr, - block, - len, - (0 << STM_DMA_CCR_MEM2MEM) | - (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | - (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | - (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | - (1 << STM_DMA_CCR_MINC) | - (0 << STM_DMA_CCR_PINC) | - (0 << STM_DMA_CCR_CIRC) | - (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); - if (len >= 2) { - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS); - stm_i2c->cr2 = AO_STM_I2C_CR2; - } else { - stm_i2c->cr1 = AO_STM_I2C_CR1; - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); - } - - ao_dma_start(rx_dma_index); - cli(); - while (!ao_dma_done[rx_dma_index]) - ao_sleep(&ao_dma_done[rx_dma_index]); - sei(); - ao_dma_done_transfer(rx_dma_index); -#endif + return ret; } void -- cgit v1.2.3 From 744d05e6037ffc11688a9faa9c7b5dcda4065ee3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:47:17 -0700 Subject: altos: stm: share i2c_stop code between send and recv This waits for the stop signal to appear on the bus, necessary before starting another transaction. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index e46211cd..763ae6cd 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -191,7 +191,6 @@ ao_i2c_start(uint8_t index, uint16_t addr) ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - printf ("start sr1: %x\n", stm_i2c->sr1); out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); @@ -208,20 +207,17 @@ ao_i2c_start(uint8_t index, uint16_t addr) } static void -ao_i2c_stop(uint8_t index) +ao_i2c_wait_stop(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - - ao_i2c_state[index] = I2C_IDLE; - out_cr2("enable isr", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - ev_count = 0; - out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + int t; - /* XXX check to see if there is an interrupt here */ - while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)) + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(in_cr1("wait stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + break; ao_yield(); - printf ("ev_count in stop: %d\n", ev_count); + } + ao_i2c_state[index] = I2C_IDLE; } uint8_t @@ -266,8 +262,10 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); sei(); - if (stop) - ao_i2c_stop(index); + if (stop) { + out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + ao_i2c_wait_stop(index); + } return TRUE; } @@ -356,15 +354,8 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_done_transfer(rx_dma_index); out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); } - if (stop) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - } + if (stop) + ao_i2c_wait_stop(index); return ret; } -- cgit v1.2.3 From dd7699cf8daded17ac41abf5c5170cfb599b6ff5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:49:24 -0700 Subject: altos: stm: delay during USB config with pull-up off This makes sure that a reboot will reliably cause the device to disconnect from the USB bus. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 71bf1bc7..c093f526 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -937,7 +937,7 @@ ao_usb_disable(void) void ao_usb_enable(void) { - uint16_t tick; + int t; /* Enable SYSCFG */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); @@ -985,6 +985,8 @@ ao_usb_enable(void) (0 << STM_USB_CNTR_PDWN) | (0 << STM_USB_CNTR_FRES)); + for (t = 0; t < 1000; t++) + ao_arch_nop(); /* Enable USB pull-up */ stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); } -- cgit v1.2.3 From af949c67eeb9dc310b1430d3435d241adccfc0a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:50:26 -0700 Subject: altos: stm: pass DMA buffer index to DMA completion callback This lets the user know which DMA has finished. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 2 +- src/stm/ao_dma_stm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 729551c4..a2569908 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -41,7 +41,7 @@ static uint8_t ao_adc_ready; * * Mark time in ring, shut down DMA engine */ -static void ao_adc_done(void) +static void ao_adc_done(int index) { ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index e76c8e8c..8379a1a5 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -20,7 +20,7 @@ #define NUM_DMA 7 struct ao_dma_config { - void (*isr)(void); + void (*isr)(int index); }; uint8_t ao_dma_done[NUM_DMA]; @@ -39,7 +39,7 @@ ao_dma_isr(uint8_t index) { /* Ack them */ stm_dma.ifcr = isr; if (ao_dma_config[index].isr) - (*ao_dma_config[index].isr)(); + (*ao_dma_config[index].isr)(index); else { ao_dma_done[index] = 1; ao_wakeup(&ao_dma_done[index]); @@ -79,7 +79,7 @@ ao_dma_set_transfer(uint8_t index, } void -ao_dma_set_isr(uint8_t index, void (*isr)(void)) +ao_dma_set_isr(uint8_t index, void (*isr)(int)) { ao_dma_config[index].isr = isr; } -- cgit v1.2.3 From 318b564486aa9965bbad54c71e51fcb32b414162 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:51:25 -0700 Subject: altos: Get mpu6000 working This initializes the device appropraitely, and provides a command to dump the current values in converted form. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 225 ++++++++++++++++++++++++++++++++++++++++++----- src/drivers/ao_mpu6000.h | 133 +++++++++++++++++++++++++++- 2 files changed, 334 insertions(+), 24 deletions(-) diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index d7f67d6e..d27c42b0 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -23,25 +23,27 @@ static uint8_t ao_mpu6000_wake; static uint8_t ao_mpu6000_configured; static void -ao_mpu6000_isr(void) +ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) { - ao_exti_disable(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN); - ao_mpu6000_wake = 1; - ao_wakeup(&ao_mpu6000_wake); + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_put(AO_MPU6000_I2C_INDEX); } static void -ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) +ao_mpu6000_reg_write(uint8_t addr, uint8_t value) { + uint8_t d[2] = { addr, value }; ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); - ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_send(d, 2, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } static void -ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) +ao_mpu6000_read(uint8_t addr, void *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); @@ -51,34 +53,211 @@ ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) ao_i2c_put(AO_MPU6000_I2C_INDEX); } +static uint8_t +ao_mpu6000_reg_read(uint8_t addr) +{ + uint8_t value; + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); + ao_i2c_recv(&value, 1, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_put(AO_MPU6000_I2C_INDEX); + return value; +} + +static void +ao_mpu6000_sample(struct ao_mpu6000_sample *sample) +{ + uint16_t *d = (uint16_t *) sample; + int i = sizeof (*sample) / 2; + + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); + /* byte swap (sigh) */ + while (i--) { + uint16_t t = *d; + *d++ = (t >> 8) | (t << 8); + } +} + +#define G 981 /* in cm/s² */ + +static int16_t /* cm/s² */ +ao_mpu6000_accel(int16_t v) +{ + return (int16_t) ((v * (int32_t) (16.0 * 980.665 + 0.5)) / 32767); +} + +static int16_t /* deg*10/s */ +ao_mpu6000_gyro(int16_t v) +{ + return (int16_t) ((v * (int32_t) 20000) / 32767); +} + +static uint8_t +ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) +{ + int16_t diff = test - normal; + + if (diff < MPU6000_ST_ACCEL(16) / 2) { + printf ("%s accel self test value too small (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + if (diff > MPU6000_ST_ACCEL(16) * 2) { + printf ("%s accel self test value too large (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + return TRUE; +} + +static uint8_t +ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) +{ + int16_t diff = test - normal; + + if (diff < 0) + diff = -diff; + if (diff < MPU6000_ST_GYRO(2000) / 2) { + printf ("%s gyro self test value too small (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + if (diff > MPU6000_ST_GYRO(2000) * 2) { + printf ("%s gyro self test value too large (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + return TRUE; +} + static void ao_mpu6000_setup(void) { + struct ao_mpu6000_sample normal_mode, test_mode; + int t; + if (ao_mpu6000_configured) return; - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_MPU6000_INT_PORT); - ao_exti_setup(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN, - AO_EXTI_MODE_FALLING, ao_mpu6000_isr); + /* Reset the whole chip */ + + ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); + while (ao_mpu6000_reg_read(MPU6000_PWR_MGMT_1) & + (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)) + ao_yield(); + + /* Reset signal conditioning */ + ao_mpu6000_reg_write(MPU6000_USER_CONTROL, + (0 << MPU6000_USER_CONTROL_FIFO_EN) | + (0 << MPU6000_USER_CONTROL_I2C_MST_EN) | + (0 << MPU6000_USER_CONTROL_I2C_IF_DIS) | + (0 << MPU6000_USER_CONTROL_FIFO_RESET) | + (0 << MPU6000_USER_CONTROL_I2C_MST_RESET) | + (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)); + + while (ao_mpu6000_reg_read(MPU6000_USER_CONTROL) & (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)) + ao_yield(); + + /* Reset signal paths */ + ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (1 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + + ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (0 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + /* Select clocks, disable sleep */ + ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (0 << MPU6000_PWR_MGMT_1_DEVICE_RESET) | + (0 << MPU6000_PWR_MGMT_1_SLEEP) | + (0 << MPU6000_PWR_MGMT_1_CYCLE) | + (0 << MPU6000_PWR_MGMT_1_TEMP_DIS) | + (MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS << MPU6000_PWR_MGMT_1_CLKSEL)); + + /* Set sample rate divider to sample at full speed + ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, 0); + + /* Disable filtering */ + ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG)); + + /* Configure accelerometer to +/-16G in self-test mode */ + ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (1 << MPU600_ACCEL_CONFIG_XA_ST) | + (1 << MPU600_ACCEL_CONFIG_YA_ST) | + (1 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s in self-test mode */ + ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (1 << MPU600_GYRO_CONFIG_XG_ST) | + (1 << MPU600_GYRO_CONFIG_YG_ST) | + (1 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(200)); + ao_mpu6000_sample(&test_mode); + + /* Configure accelerometer to +/-16G */ + ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (0 << MPU600_ACCEL_CONFIG_XA_ST) | + (0 << MPU600_ACCEL_CONFIG_YA_ST) | + (0 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s */ + ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (0 << MPU600_GYRO_CONFIG_XG_ST) | + (0 << MPU600_GYRO_CONFIG_YG_ST) | + (0 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(10)); + ao_mpu6000_sample(&normal_mode); + + ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); + ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); + ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); + + ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); + ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); + ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + + /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ + ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_94_98 << MPU6000_CONFIG_DLPF_CFG)); + + /* Set sample rate divider to sample at 200Hz (v = gyro/rate - 1) */ + ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, + 1000 / 200 - 1); + + ao_delay(AO_MS_TO_TICKS(100)); ao_mpu6000_configured = 1; } + static void ao_mpu6000_show(void) { - uint8_t addr; - uint8_t data[14]; - uint8_t i; - - ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); - printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); -#if 0 - ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 14); - for (i = 0; i < 14; i++) - printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); -#endif + struct ao_mpu6000_sample sample; + + ao_mpu6000_setup(); + ao_mpu6000_sample(&sample); + printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", + ao_mpu6000_accel(sample.accel_x), + ao_mpu6000_accel(sample.accel_y), + ao_mpu6000_accel(sample.accel_z), + ao_mpu6000_gyro(sample.gyro_x), + ao_mpu6000_gyro(sample.gyro_y), + ao_mpu6000_gyro(sample.gyro_z)); } static const struct ao_cmds ao_mpu6000_cmds[] = { diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index d436a3e0..ca76b081 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -21,9 +21,140 @@ #define MPU6000_ADDR_WRITE 0xd0 #define MPU6000_ADDR_READ 0xd1 -#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_SMPRT_DIV 0x19 + +#define MPU6000_CONFIG 0x1a + +#define MPU6000_CONFIG_EXT_SYNC_SET 3 +#define MPU6000_CONFIG_EXT_SYNC_SET_DISABLED 0 +#define MPU6000_CONFIG_EXT_SYNC_SET_TEMP_OUT_L 1 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_XOUT_L 2 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_YOUT_L 3 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_ZOUT_L 4 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_XOUT_L 5 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_YOUT_L 6 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_ZOUT_L 7 +#define MPU6000_CONFIG_EXT_SYNC_SET_MASK 7 + +#define MPU6000_CONFIG_DLPF_CFG 0 +#define MPU6000_CONFIG_DLPF_CFG_260_256 0 +#define MPU6000_CONFIG_DLPF_CFG_184_188 1 +#define MPU6000_CONFIG_DLPF_CFG_94_98 2 +#define MPU6000_CONFIG_DLPF_CFG_44_42 3 +#define MPU6000_CONFIG_DLPF_CFG_21_20 4 +#define MPU6000_CONFIG_DLPF_CFG_10_10 5 +#define MPU6000_CONFIG_DLPF_CFG_5_5 6 +#define MPU6000_CONFIG_DLPF_CFG_MASK 7 + +#define MPU6000_GYRO_CONFIG 0x1b +# define MPU600_GYRO_CONFIG_XG_ST 7 +# define MPU600_GYRO_CONFIG_YG_ST 6 +# define MPU600_GYRO_CONFIG_ZG_ST 5 +# define MPU600_GYRO_CONFIG_FS_SEL 3 +# define MPU600_GYRO_CONFIG_FS_SEL_250 0 +# define MPU600_GYRO_CONFIG_FS_SEL_500 1 +# define MPU600_GYRO_CONFIG_FS_SEL_1000 2 +# define MPU600_GYRO_CONFIG_FS_SEL_2000 3 +# define MPU600_GYRO_CONFIG_FS_SEL_MASK 3 + +#define MPU6000_ACCEL_CONFIG 0x1c +# define MPU600_ACCEL_CONFIG_XA_ST 7 +# define MPU600_ACCEL_CONFIG_YA_ST 6 +# define MPU600_ACCEL_CONFIG_ZA_ST 5 +# define MPU600_ACCEL_CONFIG_AFS_SEL 3 +# define MPU600_ACCEL_CONFIG_AFS_SEL_2G 0 +# define MPU600_ACCEL_CONFIG_AFS_SEL_4G 1 +# define MPU600_ACCEL_CONFIG_AFS_SEL_8G 2 +# define MPU600_ACCEL_CONFIG_AFS_SEL_16G 3 +# define MPU600_ACCEL_CONFIG_AFS_SEL_MASK 3 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF 0 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_RESET 0 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_5Hz 1 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_2_5Hz 2 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_1_25Hz 3 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_0_63Hz 4 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_HOLD 7 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_MASK 7 + +#define MPU6000_INT_ENABLE 0x38 +#define MPU6000_INT_ENABLE_FF_EN 7 +#define MPU6000_INT_ENABLE_MOT_EN 6 +#define MPU6000_INT_ENABLE_ZMOT_EN 5 +#define MPU6000_INT_ENABLE_FIFO_OFLOW_EN 4 +#define MPU6000_INT_ENABLE_I2C_MST_INT_EN 3 +#define MPU6000_INT_ENABLE_DATA_RDY_EN 0 + +#define MPU6000_INT_STATUS 0x3a +#define MPU6000_INT_STATUS_FF_EN 7 +#define MPU6000_INT_STATUS_MOT_EN 6 +#define MPU6000_INT_STATUS_ZMOT_EN 5 +#define MPU6000_INT_STATUS_FIFO_OFLOW_EN 4 +#define MPU6000_INT_STATUS_I2C_MST_INT_EN 3 +#define MPU6000_INT_STATUS_DATA_RDY_EN 0 + +#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_ACCEL_XOUT_L 0x3c +#define MPU6000_ACCEL_YOUT_H 0x3d +#define MPU6000_ACCEL_YOUT_L 0x3e +#define MPU6000_ACCEL_ZOUT_H 0x3f +#define MPU6000_ACCEL_ZOUT_L 0x40 +#define MPU6000_TEMP_H 0x41 +#define MPU6000_TEMP_L 0x42 +#define MPU6000_GYRO_XOUT_H 0x43 +#define MPU6000_GYRO_XOUT_L 0x44 +#define MPU6000_GYRO_YOUT_H 0x45 +#define MPU6000_GYRO_YOUT_L 0x46 +#define MPU6000_GYRO_ZOUT_H 0x47 +#define MPU6000_GYRO_ZOUT_L 0x48 + +#define MPU6000_SIGNAL_PATH_RESET 0x68 +#define MPU6000_SIGNAL_PATH_RESET_GYRO_RESET 2 +#define MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET 1 +#define MPU6000_SIGNAL_PATH_RESET_TEMP_RESET 0 + +#define MPU6000_USER_CONTROL 0x6a +#define MPU6000_USER_CONTROL_FIFO_EN 6 +#define MPU6000_USER_CONTROL_I2C_MST_EN 5 +#define MPU6000_USER_CONTROL_I2C_IF_DIS 4 +#define MPU6000_USER_CONTROL_FIFO_RESET 2 +#define MPU6000_USER_CONTROL_I2C_MST_RESET 1 +#define MPU6000_USER_CONTROL_SIG_COND_RESET 0 + +#define MPU6000_PWR_MGMT_1 0x6b +#define MPU6000_PWR_MGMT_1_DEVICE_RESET 7 +#define MPU6000_PWR_MGMT_1_SLEEP 6 +#define MPU6000_PWR_MGMT_1_CYCLE 5 +#define MPU6000_PWR_MGMT_1_TEMP_DIS 3 +#define MPU6000_PWR_MGMT_1_CLKSEL 0 +#define MPU6000_PWR_MGMT_1_CLKSEL_INTERNAL 0 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS 1 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_Y_AXIS 2 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_Z_AXIS 3 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_EXTERNAL_32K 4 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_EXTERNAL_19M 5 +#define MPU6000_PWR_MGMT_1_CLKSEL_STOP 7 +#define MPU6000_PWR_MGMT_1_CLKSEL_MASK 7 + +#define MPU6000_PWR_MGMT_2 0x6c + #define MPU6000_WHO_AM_I 0x75 +/* Self test acceleration is approximately 0.5g */ +#define MPU6000_ST_ACCEL(full_scale) (32767 / ((full_scale) * 2)) + +/* Self test gyro is approximately 50°/s */ +#define MPU6000_ST_GYRO(full_scale) ((int16_t) (((int32_t) 32767 * (int32_t) 50) / (full_scale))) + +struct ao_mpu6000_sample { + int16_t accel_x; + int16_t accel_y; + int16_t accel_z; + int16_t temp; + int16_t gyro_x; + int16_t gyro_y; + int16_t gyro_z; +}; + void ao_mpu6000_init(void); -- cgit v1.2.3 From 73c26f39b1a08fcc13e23a5b1a4293bc7df9f163 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:52:12 -0700 Subject: altos: Hacking at cc1120 driver Still doesn't work, but this adds a ton more register definitions Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 225 ++++++++++++++++++++++++++++++++++++----- src/drivers/ao_cc1120.h | 164 ++++++++++++++++++++++++++++++ src/drivers/ao_cc1120_CC1120.h | 16 ++- 3 files changed, 376 insertions(+), 29 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 272371d0..95b21170 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -19,7 +19,7 @@ #include #include -uint8_t ao_radio_done; +uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; @@ -27,6 +27,8 @@ uint8_t ao_radio_abort; uint32_t ao_radio_cal = 1186611; +#define FOSC 32000000 + #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) @@ -41,7 +43,7 @@ ao_radio_reg_read(uint16_t addr) uint8_t d; #if CC1120_DEBUG - printf("ao_radio_reg_read (%04x): ", addr); flush(); + printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); #endif if (CC1120_IS_EXTENDED(addr)) { data[0] = ((1 << CC1120_READ) | @@ -72,7 +74,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) uint8_t d; #if CC1120_DEBUG - printf("ao_radio_reg_write (%04x): %02x\n", addr, value); + printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { data[0] = ((1 << CC1120_READ) | @@ -97,9 +99,15 @@ ao_radio_strobe(uint8_t addr) { uint8_t in; +#if CC1120_DEBUG + printf("\t\tao_radio_strobe (%02x): ", addr); flush(); +#endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); +#if CC1120_DEBUG + printf("%02x\n", in); +#endif return in; } @@ -141,10 +149,12 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) CC1120_FIFO); uint8_t status; + printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); ao_radio_select(); ao_radio_duplex(&addr, &status, 1); ao_radio_spi_send_fixed(data, len); ao_radio_deselect(); + printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); return status; } @@ -158,32 +168,116 @@ void ao_radio_recv_abort(void) { ao_radio_abort = 1; - ao_wakeup(&ao_radio_done); + ao_wakeup(&ao_radio_wake); } #define ao_radio_rdf_value 0x55 -static const uint16_t rdf_setup[] = { +/* + * RDF deviation is 5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + */ + +#define RDF_DEV_E 3 +#define RDF_DEV_M 71 +#define RDF_PACKET_LEN 50 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) + * + * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 511705 + * DATARATE_E = 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 511705 +#define RDF_PACKET_LEN 50 + +static const uint16_t rdf_setup[] = { + CC1120_DEVIATION_M, RDF_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), }; +#define int_pin(w) printf("\t%s: %d\n", \ + w,\ + (AO_CC1120_INT_PORT.idr >> AO_CC1120_INT_PIN) & 1) + +static uint8_t +ao_radio_marc_status(void) +{ + return ao_radio_reg_read(CC1120_MARC_STATUS1); +} + +static uint8_t +ao_radio_tx_done(void) +{ + return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED; +} + +static uint8_t +ao_radio_rx_done(void) +{ + return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; +} + void ao_radio_rdf(uint8_t len) { int i; - ao_radio_abort = 0; ao_radio_get(len); - ao_radio_done = 0; + ao_radio_abort = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + ao_radio_reg_write(CC1120_PKT_LEN, len); + int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + int_pin ("After CFG"); ao_radio_strobe(CC1120_STX); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + int_pin ("After strobe"); + ao_delay(AO_MS_TO_TICKS(100)); + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + int_pin ("After delay"); cli(); - while (!ao_radio_done) - ao_sleep(&ao_radio_done); + for (i = 0; i < 20; i++) { +#if CC1120_DEBUG + ao_delay(AO_MS_TO_TICKS(50)); + int_pin ("Waited"); + printf ("Status %02x num_tx_bytes %d marc status %x\n", + ao_radio_status(), + ao_radio_reg_read(CC1120_NUM_TXBYTES), + ao_radio_marc_status()); +#else + ao_sleep(&ao_radio_wake); +#endif + } sei(); + printf ("num_tx_bytes %d marc status %x\n", + ao_radio_reg_read(CC1120_NUM_TXBYTES), + ao_radio_marc_status()); + if (!ao_radio_tx_done()) + ao_radio_idle(); ao_radio_set_packet(); ao_radio_put(); } @@ -191,6 +285,8 @@ ao_radio_rdf(uint8_t len) void ao_radio_rdf_abort(void) { + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); } static void @@ -213,6 +309,14 @@ ao_radio_test(void) #endif ao_radio_get(0xff); ao_radio_strobe(CC1120_STX); +#if CC1120_DEBUG + { int t; + for (t = 0; t < 10; t++) { + printf ("status: %02x\n", ao_radio_status()); + ao_delay(AO_MS_TO_TICKS(100)); + } + } +#endif radio_on = 1; } if (mode == 3) { @@ -233,15 +337,23 @@ ao_radio_test(void) void ao_radio_send(void *d, uint8_t size) { + uint8_t marc_status; + ao_radio_get(size); - ao_radio_done = 0; + ao_radio_wake = 0; ao_radio_fifo_write(d, size); - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); cli(); - while (!ao_radio_done) - ao_sleep(&ao_radio_done); + for (;;) { + if (ao_radio_wake) { + marc_status = ao_radio_marc_status(); + if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) + break; + ao_radio_wake = 0; + } + ao_sleep(&ao_radio_wake); + } sei(); ao_radio_put(); } @@ -249,23 +361,73 @@ ao_radio_send(void *d, uint8_t size) uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { + uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + /* configure interrupt pin */ ao_radio_get(size); - ao_radio_done = 0; - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT); + ao_radio_wake = 0; ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_SRX); cli(); - while (!ao_radio_done && !ao_radio_abort) - ao_sleep(&ao_radio_done); + for (;;) { + if (ao_radio_abort) + break; + if (ao_radio_wake) { + marc_status = ao_radio_marc_status(); + if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) + break; + ao_radio_wake = 0; + } + ao_sleep(&ao_radio_wake); + } sei(); - if (ao_radio_done) + if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) ao_radio_fifo_read(d, size); ao_radio_put(); - return 0; + return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; } +/* + * Packet deviation is 20.5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + */ + +#define PACKET_DEV_E 5 +#define PACKET_DEV_M 80 + +/* + * For our packet data, set the symbol rate to 38360 Baud + * + * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 405002 + * DATARATE_E = 10 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define PACKET_DRATE_E 10 +#define PACKET_DRATE_M 405002 + static const uint16_t packet_setup[] = { + CC1120_DEVIATION_M, PACKET_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((1 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (1 << CC1120_PKT_CFG1_APPEND_STATUS)), }; void @@ -285,6 +447,8 @@ ao_radio_idle(void) if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) break; } + ao_radio_strobe(CC1120_SFTX); + ao_radio_strobe(CC1120_SFRX); } static const uint16_t radio_setup[] = { @@ -297,8 +461,8 @@ static void ao_radio_isr(void) { ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_done = 1; - ao_wakeup(&ao_radio_done); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); } static void @@ -306,15 +470,17 @@ ao_radio_setup(void) { int i; + ao_radio_strobe(CC1120_SRES); + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - /* Disable GPIO2 pin (radio_int) */ - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_HIGHZ); + /* Enable marc status interrupt on gpio 2 pin */ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_RISING, ao_radio_isr); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); ao_radio_set_packet(); ao_radio_configured = 1; @@ -534,17 +700,24 @@ static void ao_radio_show(void) { printf ("Status: %02x\n", status); printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1); printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]); + printf ("MARC: %02x\n", ao_radio_marc_status()); for (i = 0; i < AO_NUM_CC1120_REG; i++) printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); ao_radio_put(); } + +static void ao_radio_beep(void) { + ao_radio_rdf(120); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, + { ao_radio_beep, "B\0Emit an RDF beacon" }, #endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 67c0a1b8..0f03f2c7 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -110,18 +110,101 @@ #define CC1120_SYNC1 0x06 #define CC1120_SYNC0 0x07 #define CC1120_SYNC_CFG1 0x08 +#define CC1120_SYNC_CFG1_DEM_CFG 5 +#define CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED 0 +#define CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED 2 +#define CC1120_SYNC_CFG1_DEM_CFG_MASK 0x7 + +#define CC1120_SYNC_CFG1_SYNC_THR 0 +#define CC1120_SYNC_CFG1_SYNC_MASK 0x1f + #define CC1120_SYNC_CFG0 0x09 +#define CC1120_SYNC_CFG0_SYNC_MODE 2 +#define CC1120_SYNC_CFG0_SYNC_MODE_NONE 0 +#define CC1120_SYNC_CFG0_SYNC_MODE_11_BITS 1 +#define CC1120_SYNC_CFG0_SYNC_MODE_16_BITS 2 +#define CC1120_SYNC_CFG0_SYNC_MODE_18_BITS 3 +#define CC1120_SYNC_CFG0_SYNC_MODE_24_BITS 4 +#define CC1120_SYNC_CFG0_SYNC_MODE_32_BITS 5 +#define CC1120_SYNC_CFG0_SYNC_MODE_16H_BITS 6 +#define CC1120_SYNC_CFG0_SYNC_MODE_16D_BITS 7 +#define CC1120_SYNC_CFG0_SYNC_MODE_MASK 7 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR 0 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_0 0 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 1 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED 3 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_MASK 3 + #define CC1120_DEVIATION_M 0x0a #define CC1120_MODCFG_DEV_E 0x0b +#define CC1120_MODCFG_DEV_E_MODEM_MODE 6 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL 0 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_MASK 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_SC_MSK_UNSHAPED 6 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_SC_MSK_SHAPED 7 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_MASK 7 +#define CC1120_MODCFG_DEV_E_DEV_E 0 +#define CC1120_MODCFG_DEV_E_DEV_E_MASK 7 + #define CC1120_DCFILT_CFG 0x0c #define CC1120_PREAMBLE_CFG1 0x0d +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE 2 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE 0 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_0_5_BYTE 1 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_1_BYTE 2 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_1_5_BYTE 3 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_2_BYTES 4 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_3_BYTES 5 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES 6 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_5_BYTES 7 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_6_BYTES 8 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_7_BYTES 9 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_8_BYTES 10 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_12_BYTES 11 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_24_BYTES 12 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_30_BYTES 13 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_MASK 0xf + +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD 0 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA 0 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_55 1 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_33 2 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_CC 3 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 + #define CC1120_PREAMBLE_CFG0 0x0e #define CC1120_FREQ_IF_CFG 0x0f #define CC1120_IQIC 0x10 #define CC1120_CHAN_BW 0x11 #define CC1120_MDMCFG1 0x12 +#define CC1120_MDMCFG1_CARRIER_SENSE_GATE 7 +#define CC1120_MDMCFG1_FIFO_EN 6 +#define CC1120_MDMCFG1_MANCHESTER_EN 5 +#define CC1120_MDMCFG1_INVERT_DATA_EN 4 +#define CC1120_MDMCFG1_COLLISION_DETECT_EN 3 +#define CC1120_MDMCFG1_DVGA_GAIN 1 +#define CC1120_MDMCFG1_DVGA_GAIN_0 0 +#define CC1120_MDMCFG1_DVGA_GAIN_3 1 +#define CC1120_MDMCFG1_DVGA_GAIN_6 2 +#define CC1120_MDMCFG1_DVGA_GAIN_9 3 +#define CC1120_MDMCFG1_DVGA_GAIN_MASK 3 +#define CC1120_MDMCFG1_SINGLE_ADC_EN 0 + #define CC1120_MDMCFG0 0x13 #define CC1120_DRATE2 0x14 +#define CC1120_DRATE2_DATARATE_E 4 +#define CC1120_DRATE2_DATARATE_E_MASK 0xf +#define CC1120_DRATE2_DATARATE_M_19_16 0 +#define CC1120_DRATE2_DATARATE_M_19_16_MASK 0xf + #define CC1120_DRATE1 0x15 #define CC1120_DRATE0 0x16 #define CC1120_AGC_REF 0x17 @@ -134,14 +217,81 @@ #define CC1120_FIFO_CFG 0x1e #define CC1120_DEV_ADDR 0x1f #define CC1120_SETTLING_CFG 0x20 +#define CC1120_SETTLING_CFG_FS_AUTOCAL 3 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_NEVER 0 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON 1 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_ON_TO_IDLE 2 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME 3 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_MASK 3 +#define CC1120_SETTLING_CFG_LOCK_TIME 1 +#define CC1120_SETTLING_CFG_LOCK_TIME_50_20 0 +#define CC1120_SETTLING_CFG_LOCK_TIME_70_30 1 +#define CC1120_SETTLING_CFG_LOCK_TIME_100_40 2 +#define CC1120_SETTLING_CFG_LOCK_TIME_150_60 3 +#define CC1120_SETTLING_CFG_LOCK_TIME_MASK 3 +#define CC1120_SETTLING_CFG_FSREG_TIME 0 +#define CC1120_SETTLING_CFG_FSREG_TIME_30 0 +#define CC1120_SETTLING_CFG_FSREG_TIME_60 1 +#define CC1120_SETTLING_CFG_FSREG_TIME_MASK 1 + #define CC1120_FS_CFG 0x21 +#define CC1120_FS_CFG_LOCK_EN 4 +#define CC1120_FS_CFG_FSD_BANDSELECT 0 +#define CC1120_FS_CFG_FSD_BANDSELECT_820_960 2 +#define CC1120_FS_CFG_FSD_BANDSELECT_410_480 4 +#define CC1120_FS_CFG_FSD_BANDSELECT_273_320 6 +#define CC1120_FS_CFG_FSD_BANDSELECT_205_240 8 +#define CC1120_FS_CFG_FSD_BANDSELECT_164_192 10 +#define CC1120_FS_CFG_FSD_BANDSELECT_136_160 11 +#define CC1120_FS_CFG_FSD_BANDSELECT_MASK 0xf + #define CC1120_WOR_CFG1 0x22 #define CC1120_WOR_CFG0 0x23 #define CC1120_WOR_EVENT0_MSB 0x24 #define CC1120_WOR_EVENT0_LSB 0x25 #define CC1120_PKT_CFG2 0x26 +#define CC1120_PKT_CFG2_CCA_MODE 2 +#define CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1 +#define CC1120_PKT_CFG2_CCA_MODE_NOT_RECEIVING 2 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_OR_NOT 3 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_AND_ETSI_LBT 4 +#define CC1120_PKT_CFG2_CCA_MODE_MASK 7 +#define CC1120_PKT_CFG2_PKT_FORMAT 0 +#define CC1120_PKT_CFG2_PKT_FORMAT_NORMAL 0 +#define CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL 1 +#define CC1120_PKT_CFG2_PKT_FORMAT_RANDOM 2 +#define CC1120_PKT_CFG2_PKT_FORMAT_TRANSPARENT_SERIAL 3 +#define CC1120_PKT_CFG2_PKT_FORMAT_MASK 3 + #define CC1120_PKT_CFG1 0x27 +#define CC1120_PKT_CFG1_WHITE_DATA 6 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG 4 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE 0 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_MASK 3 +#define CC1120_PKT_CFG1_CRC_CFG 2 +#define CC1120_PKT_CFG1_CRC_CFG_DISABLED 0 +#define CC1120_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1 +#define CC1120_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2 +#define CC1120_PKT_CFG1_CRC_CFG_MASK 3 +#define CC1120_PKT_CFG1_BYTE_SWAP_EN 1 +#define CC1120_PKT_CFG1_APPEND_STATUS 0 + #define CC1120_PKT_CFG0 0x28 +#define CC1120_PKT_CFG0_LENGTH_CONFIG 5 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED 0 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE 2 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE_5LSB 3 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_MASK 3 +#define CC1120_PKT_CFG0_PKG_BIT_LEN 2 +#define CC1120_PKT_CFG0_PKG_BIT_LEN_MASK 7 +#define CC1120_PKT_CFG0_UART_MODE_EN 1 +#define CC1120_PKT_CFG0_UART_SWAP_EN 0 + #define CC1120_RFEND_CFG1 0x29 #define CC1120_RFEND_CFG0 0x2a #define CC1120_PA_CFG2 0x2b @@ -283,6 +433,20 @@ #define CC1120_RX_STATUS (CC1120_EXTENDED_BIT | 0x92) #define CC1120_TX_STATUS (CC1120_EXTENDED_BIT | 0x93) #define CC1120_MARC_STATUS1 (CC1120_EXTENDED_BIT | 0x94) +# define CC1120_MARC_STATUS1_NO_FAILURE 0 +# define CC1120_MARC_STATUS1_RX_TIMEOUT 1 +# define CC1120_MARC_STATUS1_RX_TERMINATION 2 +# define CC1120_MARC_STATUS1_EWOR_SYNC_LOST 3 +# define CC1120_MARC_STATUS1_MAXIMUM_LENGTH 4 +# define CC1120_MARC_STATUS1_ADDRESS 5 +# define CC1120_MARC_STATUS1_CRC 6 +# define CC1120_MARC_STATUS1_TX_FIFO_OVERFLOW 7 +# define CC1120_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 +# define CC1120_MARC_STATUS1_RX_FIFO_OVERFLOW 9 +# define CC1120_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 +# define CC1120_MARC_STATUS1_TX_ON_CCA_FAILED 11 +# define CC1120_MARC_STATUS1_TX_FINISHED 0x40 +# define CC1120_MARC_STATUS1_RX_FINISHED 0x80 #define CC1120_MARC_STATUS0 (CC1120_EXTENDED_BIT | 0x95) #define CC1120_PA_IFAMP_TEST (CC1120_EXTENDED_BIT | 0x96) #define CC1120_FSRF_TEST (CC1120_EXTENDED_BIT | 0x97) diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index a96c22fc..1799c274 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -21,15 +21,16 @@ * ***************************************************************/ - CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ +#if 0 CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ +#endif CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ CC1120_PREAMBLE_CFG0, 0x2a, /* */ @@ -38,9 +39,11 @@ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ +#if 0 CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ +#endif CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ @@ -50,14 +53,21 @@ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ - CC1120_SETTLING_CFG, 0x03, /* Frequency Synthesizer Calibration and Settling Configuration */ - CC1120_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ + CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ + (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) | + (CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) | + (CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME), + CC1120_FS_CFG, /* Frequency Synthesizer Configuration */ + (1 << CC1120_FS_CFG_LOCK_EN) | + (CC1120_FS_CFG_FSD_BANDSELECT_410_480 << CC1120_FS_CFG_FSD_BANDSELECT), CC1120_WOR_CFG1, 0x08, /* eWOR Configuration, Reg 1 */ CC1120_WOR_CFG0, 0x21, /* eWOR Configuration, Reg 0 */ CC1120_WOR_EVENT0_MSB, 0x00, /* Event 0 Configuration */ CC1120_WOR_EVENT0_LSB, 0x00, /* Event 0 Configuration */ +#if 0 CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ +#endif CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ -- cgit v1.2.3 From b5b898264077fcada29e73efa28dcbe4729f2709 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:53:11 -0700 Subject: altosui: Output recorded clock tick in CSV files This allows eeprom and telem files to be correlated accurately Signed-off-by: Keith Packard --- altosui/AltosCSV.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index cf649db0..9ec21bef 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -31,9 +31,9 @@ public class AltosCSV implements AltosWriter { LinkedList pad_records; AltosState state; - static final int ALTOS_CSV_VERSION = 3; + static final int ALTOS_CSV_VERSION = 4; - /* Version 3 format: + /* Version 4 format: * * General info * version number @@ -41,6 +41,7 @@ public class AltosCSV implements AltosWriter { * flight number * callsign * time (seconds since boost) + * clock (tick count / 100) * rssi * link quality * @@ -91,13 +92,13 @@ public class AltosCSV implements AltosWriter { */ void write_general_header() { - out.printf("version,serial,flight,call,time,rssi,lqi"); + out.printf("version,serial,flight,call,time,clock,rssi,lqi"); } void write_general(AltosRecord record) { - out.printf("%s, %d, %d, %s, %8.2f, %4d, %3d", + out.printf("%s, %d, %d, %s, %8.2f, %8.2f, %4d, %3d", ALTOS_CSV_VERSION, record.serial, record.flight, record.callsign, - (double) record.time, + (double) record.time, (double) record.tick / 100.0, record.rssi, record.status & 0x7f); } -- cgit v1.2.3 From da2c920b9f3378d5a18551e008c1da5dace1e0ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:53:53 -0700 Subject: altosui: Try to make telem tick counts match eeprom telem files can have an extra wrap or two of tick count if they start recording a long time before the flight. Account for this so that the CSV file output from each have matching tick values. Signed-off-by: Keith Packard --- altosui/AltosTelemetryIterable.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index 278cbfb7..a1b25332 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -88,6 +88,15 @@ public class AltosTelemetryIterable extends AltosRecordIterable { if (previous != null) records.add(previous); + /* Adjust all tick counts to match expected eeprom values, + * which starts with a 16-bit tick count 16 samples before boost + */ + + int tick_adjust = (boost_tick - 16) & 0xffff0000; + for (AltosRecord r : this) + r.tick -= tick_adjust; + boost_tick -= tick_adjust; + /* adjust all tick counts to be relative to boost time */ for (AltosRecord r : this) r.time = (r.tick - boost_tick) / 100.0; -- cgit v1.2.3 From d387f246b24502642b76aad04eb3e0f1a5b78a05 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 16 May 2012 09:09:44 -0600 Subject: build-dep on default-jdk instead of openjdk-6-jdk, closes: #655580 --- debian/control | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/control b/debian/control index 31daaf1b..0b35bbe3 100644 --- a/debian/control +++ b/debian/control @@ -3,8 +3,8 @@ Section: electronics Priority: optional Maintainer: Bdale Garbee Uploaders: Keith Packard -Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, openjdk-6-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config -Standards-Version: 3.9.2 +Build-Depends: debhelper (>= 7), autoconf, automake, gawk, libreadline-dev, libusb-1.0-0-dev, nickle, sdcc, xsltproc, fop, docbook-xml, docbook-xsl, swig, default-jdk, freetts, libtool, libjfreechart-java, libbluetooth-dev, pkg-config +Standards-Version: 3.9.3 Homepage: http://altusmetrum.org/AltOS Vcs-Git: git://git.gag.com/fw/altos Vcs-Browser: http://git.gag.com/?p=fw/altos -- cgit v1.2.3 From 6a62edd4a1f01a6ee380c3aabaff3f437e8d6f1e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 23:14:14 -0700 Subject: altos: Conditional byte swapping in mpu6000 driver Only needed on LSB machines. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index d27c42b0..eb4044be 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -73,11 +73,13 @@ ao_mpu6000_sample(struct ao_mpu6000_sample *sample) int i = sizeof (*sample) / 2; ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); - /* byte swap (sigh) */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* byte swap */ while (i--) { uint16_t t = *d; *d++ = (t >> 8) | (t << 8); } +#endif } #define G 981 /* in cm/s² */ -- cgit v1.2.3 From 1541fc0bde71f503b1ae5757497e9e1e6d023111 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 23:14:57 -0700 Subject: altos: Check MS5607 CRC. Clean up MS5607 API It's not ready for flight yet, but at least it's sensible now. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 124 ++++++++++++++++++++++++++++++++---------------- src/drivers/ao_ms5607.h | 22 +++++++++ 2 files changed, 104 insertions(+), 42 deletions(-) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 3c0a310d..4594f07c 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -18,18 +18,8 @@ #include #include "ao_ms5607.h" -struct ms5607_prom { - uint16_t reserved; - uint16_t sens; - uint16_t off; - uint16_t tcs; - uint16_t tco; - uint16_t tref; - uint16_t tempsens; - uint16_t crc; -}; - static struct ms5607_prom ms5607_prom; +static uint8_t ms5607_configured; static void ao_ms5607_start(void) { @@ -54,38 +44,68 @@ ao_ms5607_reset(void) { ao_ms5607_stop(); } -static uint16_t -ao_ms5607_prom_read(uint8_t addr) +static uint8_t +ao_ms5607_crc(uint8_t *prom) { - uint8_t cmd = AO_MS5607_PROM_READ(addr); - uint8_t d[2]; - uint16_t v; - - ao_ms5607_start(); - ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); - ao_ms5607_stop(); - return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; + uint8_t crc_byte = prom[15]; + uint8_t cnt; + uint16_t n_rem = 0; + uint16_t crc_read; + uint8_t n_bit; + + prom[15] = 0; + for (cnt = 0; cnt < 16; cnt++) { + n_rem ^= prom[cnt]; + for (n_bit = 8; n_bit > 0; n_bit--) { + if (n_rem & 0x8000) + n_rem = (n_rem << 1) ^ 0x3000; + else + n_rem = (n_rem << 1); + } + } + n_rem = (n_rem >> 12) & 0xf; + prom[15] = crc_byte; + return n_rem; } static void -ao_ms5607_init_chip(void) { +ao_ms5607_prom_read(struct ms5607_prom *prom) +{ uint8_t addr; - uint16_t *prom; + uint8_t crc; + uint16_t *r; + + r = (uint16_t *) prom; + for (addr = 0; addr < 8; addr++) { + uint8_t cmd = AO_MS5607_PROM_READ(addr); + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(r, 2, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + r++; + } + crc = ao_ms5607_crc((uint8_t *) prom); + if (crc != (((uint8_t *) prom)[15] & 0xf)) + printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* Byte swap */ + r = (uint16_t *) prom; + for (addr = 0; addr < 8; addr++) { + uint16_t t = *r; + *r++ = (t << 8) | (t >> 8); + } +#endif +} +static void +ao_ms5607_setup(void) +{ + if (ms5607_configured) + return; + ms5607_configured = 1; ao_ms5607_reset(); - prom = &ms5607_prom.reserved; - - for (addr = 0; addr <= 7; addr++) - prom[addr] = ao_ms5607_prom_read(addr); - printf ("reserved: 0x%x\n", ms5607_prom.reserved); - printf ("sens: 0x%x\n", ms5607_prom.sens); - printf ("off: 0x%x\n", ms5607_prom.off); - printf ("tcs: 0x%x\n", ms5607_prom.tcs); - printf ("tco: 0x%x\n", ms5607_prom.tco); - printf ("tref: 0x%x\n", ms5607_prom.tref); - printf ("tempsens: 0x%x\n", ms5607_prom.tempsens); - printf ("crc: 0x%x\n", ms5607_prom.crc); + ao_ms5607_prom_read(&ms5607_prom); } static uint32_t @@ -108,8 +128,8 @@ ao_ms5607_convert(uint8_t cmd) { return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; } -static void -ao_ms5607_dump(void) +void +ao_ms5607_sample(struct ao_ms5607_sample *sample) { uint8_t addr; uint32_t D1, D2; @@ -119,6 +139,8 @@ ao_ms5607_dump(void) int64_t SENS; int32_t P; + ao_ms5607_setup(); + D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); printf ("Conversion D2: %d\n", D2); D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); @@ -137,16 +159,33 @@ ao_ms5607_dump(void) int32_t TEMPM = TEMP - 2000; int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + if (TEMP < 1500) { + int32_t TEMPP = TEMP + 1500; + int64_t TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; } P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - - printf ("Temperature: %d\n", TEMP); - printf ("Pressure %d\n", P); + sample->temp = TEMP; + sample->pres = P; +} + +static void +ao_ms5607_dump(void) +{ + struct ao_ms5607_sample sample; + + ao_ms5607_sample(&sample); + printf ("Temperature: %d\n", sample.temp); + printf ("Pressure %d\n", sample.pres); } __code struct ao_cmds ao_ms5607_cmds[] = { - { ao_ms5607_init_chip, "i\0Init MS5607" }, { ao_ms5607_dump, "p\0Display MS5607 data" }, { 0, NULL }, }; @@ -154,6 +193,7 @@ __code struct ao_cmds ao_ms5607_cmds[] = { void ao_ms5607_init(void) { + ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 489190a4..29df25e4 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -35,4 +35,26 @@ #define AO_MS5607_ADC_READ 0x00 #define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) +struct ms5607_prom { + uint16_t reserved; + uint16_t sens; + uint16_t off; + uint16_t tcs; + uint16_t tco; + uint16_t tref; + uint16_t tempsens; + uint16_t crc; +}; + +struct ao_ms5607_sample { + int32_t temp; + int32_t pres; +}; + +void +ao_ms5607_init(void); + +void +ao_ms5607_sample(struct ao_ms5607_sample *sample); + #endif /* _AO_MS5607_H_ */ -- cgit v1.2.3 From 5d8b9d524d6424ff98dcc4155fe8b8bd892b6d8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:04:57 -0700 Subject: altos: Add conversion between Pa and meters To be used with the MS5607 which generates data in calibrated units. Signed-off-by: Keith Packard --- src/Makefile | 6 +- src/core/ao.h | 12 ++ src/core/ao_convert_pa.c | 72 +++++++++++ src/core/ao_convert_pa_test.c | 76 ++++++++++++ src/test/Makefile | 5 +- src/util/make-altitude-pa | 275 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 src/core/ao_convert_pa.c create mode 100644 src/core/ao_convert_pa_test.c create mode 100644 src/util/make-altitude-pa diff --git a/src/Makefile b/src/Makefile index db9bd508..c2e324c4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,7 @@ # vpath make-altitude util +vpath make-altitude-pa util vpath make-kalman util vpath kalman.5c kalman vpath kalman_filter.5c kalman @@ -45,11 +46,14 @@ uninstall: all-recursive: all-local -all-local: altitude.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h altitude.h: make-altitude nickle $< > $@ +altitude-pa.h: make-altitude-pa + nickle $< > $@ + ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c bash $< kalman > $@ diff --git a/src/core/ao.h b/src/core/ao.h index 27b9c5c4..a2092cfe 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -282,6 +282,18 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; +/* + * ao_convert_pa.c + * + * Convert between pressure in Pa and altitude in meters + */ + +int32_t +ao_pa_to_altitude(int32_t pa); + +int32_t +ao_altitude_to_pa(int32_t alt); + #if HAS_DBG #include #endif diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c new file mode 100644 index 00000000..0c93caea --- /dev/null +++ b/src/core/ao_convert_pa.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int32_t altitude_table[] = { +#include "altitude-pa.h" +}; + +#define ALT_SCALE (1 << ALT_SHIFT) +#define ALT_MASK (ALT_SCALE - 1) + +int32_t +ao_pa_to_altitude(int32_t pa) +{ + int16_t o; + int16_t part; + int32_t low, high; + + if (pa < 0) + pa = 0; + if (pa > 120000) + pa = 120000; + o = pa >> ALT_SHIFT; + part = pa & ALT_MASK; + + low = (int32_t) altitude_table[o] * (ALT_SCALE - part); + high = (int32_t) altitude_table[o+1] * part + (ALT_SCALE >> 1); + return (low + high) >> ALT_SHIFT; +} + +int32_t +ao_altitude_to_pa(int32_t alt) +{ + int32_t span, sub_span; + uint16_t l, h, m; + int32_t pa; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span; + if (pa > 120000) + pa = 120000; + if (pa < 0) + pa = 0; + return pa; +} diff --git a/src/core/ao_convert_pa_test.c b/src/core/ao_convert_pa_test.c new file mode 100644 index 00000000..972a4d4c --- /dev/null +++ b/src/core/ao_convert_pa_test.c @@ -0,0 +1,76 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert_pa.c" + +#define STEP_P 1 +#define STEP_A 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int32_t p_to_a, p_to_a_to_p; + int32_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 120000 + STEP_P; i += STEP_P) { + if (i > 120000) + i = 120000; + p_to_a = ao_pa_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pa(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pa %d alt %d pa %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1450; i < 74250 + STEP_A; i += STEP_A) { + if (i > 74250) + i = 74250; + a_to_p = ao_altitude_to_pa(i); + a_to_p_to_a = ao_pa_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pa %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/test/Makefile b/src/test/Makefile index 4e403da6..3c2b8732 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test KALMAN=make-kalman @@ -34,5 +34,8 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc $(CFLAGS) -o $@ $< +ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h + cc $(CFLAGS) -o $@ $< + ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) \ No newline at end of file diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa new file mode 100644 index 00000000..190b36fc --- /dev/null +++ b/src/util/make-altitude-pa @@ -0,0 +1,275 @@ +#!/usr/bin/nickle -f +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +real pressure_to_altitude(real pressure) { + + real next_base_temperature = LAYER0_BASE_TEMPERATURE; + real next_base_pressure = LAYER0_BASE_PRESSURE; + + real altitude; + real base_pressure; + real base_temperature; + real base; /* base for function to determine base pressure of next layer */ + real exponent; /* exponent for function to determine base pressure + of next layer */ + real coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +real feet_to_meters(real feet) +{ + return feet * (12 * 2.54 / 100); +} + +real meters_to_feet(real meters) +{ + return meters / (12 * 2.54 / 100); +} + +/* + * Values for our MS5607 + * + * From the data sheet: + * + * Pressure range: 10-1200 mbar (1000 - 120000 Pa) + * + * Pressure data is reported in units of Pa + */ + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real min_Pa = 0; +real max_Pa = 120000; + +/* Target is an array of < 2000 entries */ +int pa_sample_shift = 3; +int pa_part_shift = 3; + +int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift))); + +int num_samples = num_part << pa_part_shift; + +real sample_to_Pa(int sample) = sample << pa_sample_shift; + +real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample)); + +int part_to_sample(int part) = part << pa_part_shift; + +real[num_samples] alt = { [n] = sample_to_altitude(n) }; + +int seg_len = 1 << pa_part_shift; + +line_t [num_part] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real sample_to_fit_altitude(int sample) { + int sub = sample // seg_len; + int off = sample % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = sample * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_sample = 0; +real total_error = 0; + +for (int sample = 0; sample < num_samples; sample++) { + real Pa = sample_to_Pa(sample); + real meters = pressure_to_altitude(Pa); + + real meters_approx = sample_to_fit_altitude(sample); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_sample = sample; + } +# printf (" %7d, /* %6.2f kPa %5d sample approx %d */\n", +# floor (meters + 0.5), Pa / 1000, sample, floor(sample_to_fit_altitude(sample) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_sample / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); + +for (int part = 0; part < dim(alt_part); part++) { + real kPa = sample_to_Pa(part_to_sample(part)) / 1000; + printf ("%9d, /* %6.2f kPa */\n", + alt_part[part], kPa); +} -- cgit v1.2.3 From 34bb17bc1a3d8a1c95b5e57f059e7a1747e17a03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:16:35 -0700 Subject: altos: Finish ms5607 support This has the MS5607 polling once each tick for pressure and temperature and then saving that in a global variable. The command UI provides for dumping the prom data so that an eeprom file can have raw sensor data along with the conversion factors necessary to compute useful values. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/drivers/ao_ms5607.c | 114 +++++++++++++++++++++++++++++++++--------- src/drivers/ao_ms5607.h | 19 +++++-- src/megametrum-v0.1/Makefile | 3 +- src/megametrum-v0.1/ao_pins.h | 7 ++- 5 files changed, 115 insertions(+), 29 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index a2092cfe..da1fd67b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -115,6 +115,7 @@ ao_start_scheduler(void); #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ +#define AO_PANIC_SELF_TEST 14 /* Self test failure */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 4594f07c..f79c315a 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -16,10 +16,11 @@ */ #include +#include #include "ao_ms5607.h" -static struct ms5607_prom ms5607_prom; -static uint8_t ms5607_configured; +static struct ao_ms5607_prom ms5607_prom; +static uint8_t ms5607_configured; static void ao_ms5607_start(void) { @@ -69,7 +70,7 @@ ao_ms5607_crc(uint8_t *prom) } static void -ao_ms5607_prom_read(struct ms5607_prom *prom) +ao_ms5607_prom_read(struct ao_ms5607_prom *prom) { uint8_t addr; uint8_t crc; @@ -85,8 +86,12 @@ ao_ms5607_prom_read(struct ms5607_prom *prom) r++; } crc = ao_ms5607_crc((uint8_t *) prom); - if (crc != (((uint8_t *) prom)[15] & 0xf)) - printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); + if (crc != (((uint8_t *) prom)[15] & 0xf)) { + printf ("MS5607 PROM CRC error (computed %x actual %x)\n", + crc, (((uint8_t *) prom)[15] & 0xf)); + flush(); + ao_panic(AO_PANIC_SELF_TEST); + } #if __BYTE_ORDER == __LITTLE_ENDIAN /* Byte swap */ @@ -108,17 +113,33 @@ ao_ms5607_setup(void) ao_ms5607_prom_read(&ms5607_prom); } +static uint8_t ao_ms5607_done; + +static void +ao_ms5607_isr(void) +{ + ao_ms5607_done = 1; + ao_wakeup(&ao_ms5607_done); +} + static uint32_t -ao_ms5607_convert(uint8_t cmd) { +ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; + uint16_t now; + + ao_ms5607_done = 0; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_exti_enable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + cli(); + while (!ao_ms5607_done) + ao_sleep(&ao_ms5607_done); + sei(); + ao_exti_disable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(20)); - ao_ms5607_start(); read = AO_MS5607_ADC_READ; ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); @@ -130,23 +151,22 @@ ao_ms5607_convert(uint8_t cmd) { void ao_ms5607_sample(struct ao_ms5607_sample *sample) +{ + sample->pres = ao_ms5607_get_sample(AO_MS5607_CONVERT_D1_2048); + sample->temp = ao_ms5607_get_sample(AO_MS5607_CONVERT_D2_2048); +} + +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) { uint8_t addr; - uint32_t D1, D2; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; int32_t P; - ao_ms5607_setup(); - - D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); - printf ("Conversion D2: %d\n", D2); - D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); - printf ("Conversion D1: %d\n", D1); - - dT = D2 - ((int32_t) ms5607_prom.tref << 8); + dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); @@ -170,19 +190,49 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) SENS -= SENS2; } - P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - sample->temp = TEMP; - sample->pres = P; + value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + value->temp = TEMP; } +struct ao_ms5607_sample ao_ms5607_current; + +static void +ao_ms5607(void) +{ + ao_ms5607_setup(); + for (;;) + { + struct ao_ms5607_sample ao_ms5607_next; + ao_ms5607_sample(&ao_ms5607_next); + ao_arch_critical( + ao_ms5607_current = ao_ms5607_next; + ); + ao_delay(0); + } +} + +__xdata struct ao_task ao_ms5607_task; + static void ao_ms5607_dump(void) { struct ao_ms5607_sample sample; + struct ao_ms5607_value value; + + printf ("ms5607 reserved: %u\n", ms5607_prom.reserved); + printf ("ms5607 sens: %u\n", ms5607_prom.sens); + printf ("ms5607 off: %u\n", ms5607_prom.off); + printf ("ms5607 tcs: %u\n", ms5607_prom.tcs); + printf ("ms5607 tco: %u\n", ms5607_prom.tco); + printf ("ms5607 tref: %u\n", ms5607_prom.tref); + printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens); + printf ("ms5607 crc: %u\n", ms5607_prom.crc); - ao_ms5607_sample(&sample); - printf ("Temperature: %d\n", sample.temp); - printf ("Pressure %d\n", sample.pres); + sample = ao_ms5607_current; + ao_ms5607_convert(&sample, &value); + printf ("Pressure: %8u %8d\n", sample.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.temp, value.temp); + printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } __code struct ao_cmds ao_ms5607_cmds[] = { @@ -196,4 +246,22 @@ ao_ms5607_init(void) ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); + + ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); + + /* Configure the MISO pin as an interrupt; when the + * conversion is complete, the MS5607 will raise this + * pin as a signal + */ + ao_exti_setup(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + AO_EXTI_MODE_RISING, + ao_ms5607_isr); + + /* Reset the pin from INPUT to ALTERNATE so that SPI works + * This needs an abstraction at some point... + */ + stm_moder_set(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + STM_MODER_ALTERNATE); } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 29df25e4..fd5bc984 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -35,7 +35,7 @@ #define AO_MS5607_ADC_READ 0x00 #define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) -struct ms5607_prom { +struct ao_ms5607_prom { uint16_t reserved; uint16_t sens; uint16_t off; @@ -47,8 +47,15 @@ struct ms5607_prom { }; struct ao_ms5607_sample { - int32_t temp; - int32_t pres; + uint32_t pres; /* raw 24 bit sensor */ + uint32_t temp; /* raw 24 bit sensor */ +}; + +extern struct ao_ms5607_sample ao_ms5607_current; + +struct ao_ms5607_value { + int32_t pres; /* in Pa * 10 */ + int32_t temp; /* in °C * 100 */ }; void @@ -57,4 +64,10 @@ ao_ms5607_init(void); void ao_ms5607_sample(struct ao_ms5607_sample *sample); +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value); + +void +ao_ms5607_get_prom(struct ao_ms5607_prom *prom); + #endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 437e1a9e..6524d8b8 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -50,7 +50,8 @@ ALTOS_SRC = \ ao_packet_slave.c \ ao_i2c_stm.c \ ao_hmc5883.c \ - ao_mpu6000.c + ao_mpu6000.c \ + ao_convert_pa.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index cd270739..adc56151 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -182,6 +182,9 @@ struct ao_adc { #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_GPIO stm_gpioa +#define AO_MS5607_MISO 6 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) /* @@ -212,7 +215,7 @@ struct ao_adc { #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_SPI_INDEX(1) +#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) /* * mpu6000 @@ -220,6 +223,6 @@ struct ao_adc { #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 -#define AO_MPU6000_I2C_INDEX STM_SPI_INDEX(1) +#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 0239e4dfe587528524b6380bbf6d9583047e52d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 21:23:47 -0700 Subject: altos: Poll mpu6000 values every tick and stash them locally. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 28 +++++++++++++++++++++++----- src/drivers/ao_mpu6000.h | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index eb4044be..df400fcb 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -147,9 +147,9 @@ ao_mpu6000_setup(void) ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); - while (ao_mpu6000_reg_read(MPU6000_PWR_MGMT_1) & - (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)) - ao_yield(); + + /* Wait for it to reset. If we talk too quickly, it appears to get confused */ + ao_delay(AO_MS_TO_TICKS(100)); /* Reset signal conditioning */ ao_mpu6000_reg_write(MPU6000_USER_CONTROL, @@ -245,14 +245,31 @@ ao_mpu6000_setup(void) ao_mpu6000_configured = 1; } +struct ao_mpu6000_sample ao_mpu6000_current; + +static void +ao_mpu6000(void) +{ + ao_mpu6000_setup(); + for (;;) + { + struct ao_mpu6000_sample ao_mpu6000_next; + ao_mpu6000_sample(&ao_mpu6000_next); + ao_arch_critical( + ao_mpu6000_current = ao_mpu6000_next; + ); + ao_delay(0); + } +} + +static struct ao_task ao_mpu6000_task; static void ao_mpu6000_show(void) { struct ao_mpu6000_sample sample; - ao_mpu6000_setup(); - ao_mpu6000_sample(&sample); + sample = ao_mpu6000_current; printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", ao_mpu6000_accel(sample.accel_x), ao_mpu6000_accel(sample.accel_y), @@ -272,5 +289,6 @@ ao_mpu6000_init(void) { ao_mpu6000_configured = 0; + ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); } diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index ca76b081..5e52148d 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -155,6 +155,8 @@ struct ao_mpu6000_sample { int16_t gyro_z; }; +extern struct ao_mpu6000_sample ao_mpu6000_current; + void ao_mpu6000_init(void); -- cgit v1.2.3 From 78423f3fc5164ea9fd428606419784c1700ad5c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 May 2012 23:18:06 -0600 Subject: Get megametrum ready to at least log flight data Doesn't track flight state changes correctly. Signed-off-by: Keith Packard --- src/core/ao_adc.h | 5 ++- src/core/ao_config.c | 33 ++++++++++++++++---- src/core/ao_kalman.c | 3 ++ src/core/ao_log.c | 3 +- src/core/ao_log.h | 62 ++++++++++++++++++++++++++++++++++++- src/core/ao_sample.h | 19 +++++++----- src/megametrum-v0.1/Makefile | 19 +++++++++--- src/megametrum-v0.1/ao_megametrum.c | 8 +++-- src/megametrum-v0.1/ao_pins.h | 7 ++++- src/stm/ao_adc_stm.c | 42 ++++++++++++++++++------- 10 files changed, 164 insertions(+), 37 deletions(-) diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index db5bfab3..8ec740c4 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,13 +18,11 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ - - /* * One set of samples read from the A/D converter or telemetry */ - +#if AO_ADC_RING /* * ao_adc.c */ @@ -42,6 +40,7 @@ extern volatile __data uint8_t ao_adc_head; #if HAS_ACCEL_REF extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; #endif +#endif /* Trigger a conversion sequence (called from the timer interrupt) */ void diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55fb8590..55ec9f40 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#include "ao_log.h" +#include +#include __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; @@ -64,11 +67,13 @@ ao_config_put(void) } #endif +#if HAS_RADIO void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); } +#endif /* HAS_RADIO */ static void _ao_config_get(void) @@ -100,8 +105,10 @@ _ao_config_get(void) ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ +#if HAS_RADIO if (ao_config.minor < 3) ao_config.radio_cal = ao_radio_cal; +#endif /* Fixups for minor version 4 */ if (ao_config.minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; @@ -121,7 +128,9 @@ _ao_config_get(void) ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } +#if HAS_RADIO ao_config_set_radio(); +#endif ao_config_loaded = 1; } @@ -176,6 +185,7 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_RADIO void ao_config_frequency_show(void) __reentrant { @@ -195,6 +205,7 @@ ao_config_frequency_set(void) __reentrant _ao_config_edit_finish(); ao_radio_recv_abort(); } +#endif #if HAS_FLIGHT @@ -232,7 +243,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; - uint8_t cal_adc_ring; + uint8_t cal_data_ring; printf("Orient antenna %s and press a key...", orientation); flush(); @@ -241,12 +252,14 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_sample_adc; + cal_data_ring = ao_sample_data; while (i) { - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (i && cal_adc_ring != ao_sample_adc) { - accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; - cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (i && cal_data_ring != ao_sample_data) { + int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); + printf ("accel %d\n", accel); + accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); + cal_data_ring = ao_data_ring_next(cal_data_ring); i--; } } @@ -320,6 +333,7 @@ ao_config_apogee_lockout_set(void) __reentrant #endif /* HAS_FLIGHT */ +#if HAS_RADIO void ao_config_radio_cal_show(void) __reentrant { @@ -337,6 +351,7 @@ ao_config_radio_cal_set(void) __reentrant ao_config_set_radio(); _ao_config_edit_finish(); } +#endif #if HAS_LOG void @@ -413,6 +428,7 @@ ao_config_pad_orientation_set(void) __reentrant } #endif +#if HAS_RADIO void ao_config_radio_enable_show(void) __reentrant { @@ -429,6 +445,7 @@ ao_config_radio_enable_set(void) __reentrant ao_config.radio_enable = ao_cmd_lex_i; _ao_config_edit_finish(); } +#endif /* HAS_RADIO */ #if HAS_AES void @@ -481,18 +498,22 @@ __code struct ao_config_var ao_config_vars[] = { { "L \0Apogee detect lockout (s)", ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, #endif /* HAS_FLIGHT */ +#if HAS_RADIO { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, +#endif /* HAS_RADIO */ #if HAS_ACCEL { "a <+g> <-g>\0Accel calib (0 for auto)", ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, #endif /* HAS_ACCEL */ +#if HAS_RADIO { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, +#endif /* HAS_RADIO */ #if HAS_LOG { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index ee01949e..68725f69 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -17,10 +17,13 @@ #ifndef AO_FLIGHT_TEST #include "ao.h" +#include "ao_flight.h" #endif +#include "ao_sample.h" #include "ao_kalman.h" + static __pdata int32_t ao_k_height; static __pdata int32_t ao_k_speed; static __pdata int32_t ao_k_accel; diff --git a/src/core/ao_log.c b/src/core/ao_log.c index db60707d..d696625e 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -16,12 +16,13 @@ */ #include "ao.h" +#include __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; __pdata uint32_t ao_log_start_pos; __xdata uint8_t ao_log_running; -__pdata enum flight_state ao_log_state; +__pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; __code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 611c00d5..e585750f 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -18,6 +18,8 @@ #ifndef _AO_LOG_H_ #define _AO_LOG_H_ +#include + /* * ao_log.c */ @@ -32,7 +34,7 @@ extern __pdata uint32_t ao_log_current_pos; extern __pdata uint32_t ao_log_end_pos; extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; +extern __pdata enum ao_flight_state ao_log_state; /* required functions from the underlying log system */ @@ -41,6 +43,7 @@ extern __pdata enum flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_MEGAMETRUM 5 /* 32 byte typed megametrum records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -189,8 +192,65 @@ struct ao_log_record { } u; }; +struct ao_log_mega { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + struct { + uint16_t flight; /* 4 */ + int16_t ground_accel; /* 6 */ + uint32_t ground_pres; /* 8 */ + uint32_t ground_temp; /* 12 */ + } flight; /* 16 */ + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint32_t pres; /* 4 */ + uint32_t temp; /* 8 */ + int16_t accel_x; /* 12 */ + int16_t accel_y; /* 14 */ + int16_t accel_z; /* 16 */ + int16_t gyro_x; /* 18 */ + int16_t gyro_y; /* 20 */ + int16_t gyro_z; /* 22 */ + } sensor; /* 24 */ + struct { + int16_t v_batt; /* 4 */ + int16_t v_pbatt; /* 8 */ + int16_t n_sense; /* 10 */ + int16_t sense[10]; /* 12 */ + } volt; /* 32 */ + struct { + int32_t latitude; /* 4 */ + int32_t longitude; /* 8 */ + int16_t altitude; /* 12 */ + uint8_t hour; /* 14 */ + uint8_t minute; /* 15 */ + uint8_t second; /* 16 */ + uint8_t flags; /* 17 */ + uint8_t year; /* 18 */ + uint8_t month; /* 19 */ + uint8_t day; /* 20 */ + uint8_t pad; /* 21 */ + } gps; /* 22 */ + struct { + uint16_t channels; /* 4 */ + struct { + uint8_t svid; + uint8_t c_n; + } sats[12]; /* 6 */ + } gps_sat; /* 30 */ + } u; +}; + /* Write a record to the eeprom log */ uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; +uint8_t +ao_log_mega(__xdata struct ao_log_mega *log) __reentrant; + #endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index fb0e69e8..189b2019 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -18,6 +18,8 @@ #ifndef _AO_SAMPLE_H_ #define _AO_SAMPLE_H_ +#include + /* * ao_sample.c */ @@ -88,21 +90,22 @@ #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ +extern __data uint8_t ao_sample_data; /* Ring position of last processed sample */ #if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +extern __pdata pres_t ao_ground_pres; /* startup pressure */ +extern __pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata accel_t ao_ground_accel; /* startup acceleration */ +extern __pdata accel_t ao_accel_2g; /* factory accel calibration */ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6524d8b8..a07b25ee 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -9,6 +9,8 @@ INC = \ ao.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_data.h \ + ao_sample.h \ ao_pins.h \ altitude.h \ ao_kalman.h \ @@ -21,6 +23,11 @@ INC = \ # # Common AltOS sources # + +# ao_cc1120.c \ +# ao_packet.c \ +# ao_packet_slave.c \ + ALTOS_SRC = \ ao_interrupt.c \ ao_product.c \ @@ -35,7 +42,6 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ - ao_cc1120.c \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ @@ -46,12 +52,17 @@ ALTOS_SRC = \ ao_m25.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_packet.c \ - ao_packet_slave.c \ + ao_report.c \ ao_i2c_stm.c \ ao_hmc5883.c \ ao_mpu6000.c \ - ao_convert_pa.c + ao_convert_pa.c \ + ao_log.c \ + ao_log_mega.c \ + ao_sample_mm.c \ + ao_kalman.c \ + ao_flight_mm.c + PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 2e1f9298..19746d37 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -18,6 +18,7 @@ #include #include #include +#include #include void @@ -46,7 +47,6 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_gps_init(); - ao_config_init(); ao_dma_init(); ao_spi_init(); ao_ms5607_init(); @@ -55,10 +55,14 @@ main(void) ao_storage_init(); ao_usb_init(); ao_exti_init(); - ao_radio_init(); +// ao_radio_init(); ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_config_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index adc56151..3ab7e15a 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -94,9 +94,12 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define HAS_GPS 1 +#define HAS_FLIGHT 1 #define HAS_ADC 1 +#define HAS_ACCEL 1 -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 struct ao_adc { @@ -179,6 +182,7 @@ struct ao_adc { /* * Pressure sensor settings */ +#define HAS_MS5607 1 #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) @@ -221,6 +225,7 @@ struct ao_adc { * mpu6000 */ +#define HAS_MPU6000 1 #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index a2569908..af2968d6 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -16,10 +16,17 @@ */ #include +#include +#if HAS_MPU6000 +#include +#endif +#if HAS_MS5607 +#include +#endif +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; static uint8_t ao_adc_ready; #define AO_ADC_CR2_VAL ((0 << STM_ADC_CR2_SWSTART) | \ @@ -43,9 +50,15 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].adc.tick = ao_time(); +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; +#endif + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } @@ -62,7 +75,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_adc_ring[ao_adc_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].tick + 1), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -84,20 +97,27 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); +} + +void +ao_data_get(__xdata struct ao_data *packet) +{ + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - struct ao_adc packet; + struct ao_data packet; int16_t *d; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); printf("tick: %5u", packet.tick); - d = (int16_t *) (&packet.tick + 1); + d = (int16_t *) (&packet.adc); for (i = 0; i < AO_NUM_ADC; i++) printf (" %2d: %5d", i, d[i]); printf("\n"); -- cgit v1.2.3 From d01c10eff4b70af13347969a7cece8730cf1a3f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:44:38 -0600 Subject: altos: Data packet tick count does not live in adc structure It was moved to the global structure. Having two is confusing. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 1 - src/stm/ao_adc_stm.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 3ab7e15a..2ae3cea8 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -103,7 +103,6 @@ #define AO_ADC_NUM_SENSE 6 struct ao_adc { - uint16_t tick; int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index af2968d6..576dbf5d 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -50,7 +50,7 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - ao_data_ring[ao_data_head].adc.tick = ao_time(); + ao_data_ring[ao_data_head].tick = ao_time(); #if HAS_MPU6000 ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; #endif -- cgit v1.2.3 From 9eeba439ce8c9dc1def8528f96b6a67c6578d656 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:46:00 -0600 Subject: altos: Don't start ADC ring until the other sensors have a valid value Yes, this is still an ugly kludge, but it's easy. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 3 +++ src/drivers/ao_mpu6000.h | 1 + src/drivers/ao_ms5607.c | 3 +++ src/drivers/ao_ms5607.h | 1 + src/stm/ao_adc_stm.c | 11 +++++++++-- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index df400fcb..065ed221 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -246,6 +246,7 @@ ao_mpu6000_setup(void) } struct ao_mpu6000_sample ao_mpu6000_current; +uint8_t ao_mpu6000_valid; static void ao_mpu6000(void) @@ -257,6 +258,7 @@ ao_mpu6000(void) ao_mpu6000_sample(&ao_mpu6000_next); ao_arch_critical( ao_mpu6000_current = ao_mpu6000_next; + ao_mpu6000_valid = 1; ); ao_delay(0); } @@ -288,6 +290,7 @@ void ao_mpu6000_init(void) { ao_mpu6000_configured = 0; + ao_mpu6000_valid = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index 5e52148d..fc7af1e0 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -156,6 +156,7 @@ struct ao_mpu6000_sample { }; extern struct ao_mpu6000_sample ao_mpu6000_current; +extern uint8_t ao_mpu6000_valid; void ao_mpu6000_init(void); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index f79c315a..7db7022f 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -195,6 +195,7 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value } struct ao_ms5607_sample ao_ms5607_current; +uint8_t ao_ms5607_valid; static void ao_ms5607(void) @@ -206,6 +207,7 @@ ao_ms5607(void) ao_ms5607_sample(&ao_ms5607_next); ao_arch_critical( ao_ms5607_current = ao_ms5607_next; + ao_ms5607_valid = 1; ); ao_delay(0); } @@ -244,6 +246,7 @@ void ao_ms5607_init(void) { ms5607_configured = 0; + ao_ms5607_valid = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index fd5bc984..1384d3a2 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -51,6 +51,7 @@ struct ao_ms5607_sample { uint32_t temp; /* raw 24 bit sensor */ }; +extern uint8_t ao_ms5607_valid; extern struct ao_ms5607_sample ao_ms5607_current; struct ao_ms5607_value { diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 576dbf5d..02187205 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -50,15 +50,22 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { + uint8_t step = 1; ao_data_ring[ao_data_head].tick = ao_time(); #if HAS_MPU6000 + if (!ao_mpu6000_valid) + step = 0; ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; #endif #if HAS_MS5607 + if (!ao_ms5607_valid) + step = 0; ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; #endif - ao_data_head = ao_data_ring_next(ao_data_head); - ao_wakeup((void *) &ao_data_head); + if (step) { + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } -- cgit v1.2.3 From dd73c9b441f7672fb9982c4caeb5178df30f5d2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:47:30 -0600 Subject: altos: Split out mm-specific versions of sampling code Avoid breaking telemetrum (too much) by splitting this stuff apart. Signed-off-by: Keith Packard --- src/core/ao_data.h | 191 +++++++++++++++++++++++++ src/core/ao_flight_mm.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_log_mega.c | 174 +++++++++++++++++++++++ src/core/ao_sample_mm.c | 135 ++++++++++++++++++ 4 files changed, 862 insertions(+) create mode 100644 src/core/ao_data.h create mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_log_mega.c create mode 100644 src/core/ao_sample_mm.c diff --git a/src/core/ao_data.h b/src/core/ao_data.h new file mode 100644 index 00000000..d28730a8 --- /dev/null +++ b/src/core/ao_data.h @@ -0,0 +1,191 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_DATA_H_ +#define _AO_DATA_H_ + +#if HAS_MS5607 +#include +#endif + +#if HAS_MPU6000 +#include +#endif + +struct ao_data { + uint16_t tick; +#if HAS_ADC + struct ao_adc adc; +#endif +#if HAS_ACCEL_REF + uint16_t accel_ref; +#endif +#if HAS_MS5607 + struct ao_ms5607_sample ms5607; +#endif +#if HAS_MPU6000 + struct ao_mpu6000_sample mpu6000; +#endif +}; + +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) + +extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +extern volatile __data uint8_t ao_data_head; + +#if HAS_MS5607 + +typedef int32_t pres_t; +typedef int32_t alt_t; + +static inline pres_t ao_data_pres(struct ao_data *packet) +{ + struct ao_ms5607_value value; + + ao_ms5607_convert(&packet->ms5607, &value); + return value.pres; +} + +#define pres_to_altitude(p) ao_pa_to_altitude(p) + +#else + +typedef int16_t pres_t; +typedef int16_t alt_t; + +#define ao_data_pres(packet) ((packet)->adc.pres) +#define pres_to_altitude(p) ao_pres_to_altitude(p) + +#endif + +/* + * Need a few macros to pull data from the sensors: + * + * ao_data_accel_sample - pull raw sensor and convert to normalized values + * ao_data_accel - pull normalized value (lives in the same memory) + * ao_data_set_accel - store normalized value back in the sensor location + * ao_data_accel_invert - flip rocket ends for positive acceleration + */ + +#if HAS_MPU6000 + +typedef int16_t accel_t; + +/* MPU6000 is hooked up so that positive y is positive acceleration */ +#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) +#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) +#define ao_data_accel_invert(a) (-(a)) + +#else + +typedef int16_t accel_t; +#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_accel_invert(a) (0x7fff -(a)) + +/* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ +#if HAS_ACCEL_REF +#define ao_data_accel_sample(packet) \ + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) +#else +#define ao_data_accel(packet) ((packet)->adc.accel) +#endif /* HAS_ACCEL_REF */ + +#endif /* else some other pressure sensor */ + +#endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c new file mode 100644 index 00000000..27087e55 --- /dev/null +++ b/src/core/ao_flight_mm.c @@ -0,0 +1,362 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_RADIO + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_RADIO + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_RADIO + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c new file mode 100644 index 00000000..1763b9eb --- /dev/null +++ b/src/core/ao_log_mega.c @@ -0,0 +1,174 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_mega log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_mega); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_mega(__xdata struct ao_log_mega *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_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_mega)); + ao_log_current_pos += sizeof (struct ao_log_mega); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_megas fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_mega))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 +#endif + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + uint8_t i; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + +#if HAS_FLIGHT + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.ground_pres = ao_ground_pres; + log.u.flight.flight = ao_flight_number; + ao_log_mega(&log); +#endif + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; + log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; + log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; + log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; + log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; + log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + ao_log_mega(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; + log.u.volt.v_pbatt = ao_data_ring[ao_log_data_pos].adc.v_pbatt; + log.u.volt.n_sense = AO_ADC_NUM_SENSE; + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i]; + ao_log_mega(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } +#if HAS_FLIGHT + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_mega(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } +#endif + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_mega))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c new file mode 100644 index 00000000..8cfadc40 --- /dev/null +++ b/src/core/ao_sample_mm.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_sample(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} -- cgit v1.2.3 From ed635545e0b965901032ed2c3474ffe997c73de3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:52:45 -0600 Subject: ignore pa to altitude conversion file Signed-off-by: Keith Packard --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/.gitignore b/src/.gitignore index 7a5d6ef5..c6e1e353 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1 +1,2 @@ altitude.h +altitude-pa.h -- cgit v1.2.3 From ce8153472069ed56b24ac36f297ac569d1f767d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:24:09 -0600 Subject: altos: Make telemetrum-v1.1 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 36 ++++++++++++++++-------------------- src/cc1111/ao_arch.h | 3 +-- src/cc1111/ao_ignite.c | 9 +++++---- src/core/ao_adc.h | 28 +++------------------------- src/core/ao_data.h | 2 +- src/core/ao_log_big.c | 24 ++++++++++++------------ src/core/ao_telemetry.c | 28 ++++++++++++++-------------- src/product/Makefile.telemetrum | 4 ++-- src/stm/ao_adc_stm.c | 8 ++++++++ 9 files changed, 62 insertions(+), 80 deletions(-) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1688eceb..1e3d8cab 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -16,13 +16,9 @@ */ #include "ao.h" -#include "ao_pins.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -#if HAS_ACCEL_REF -volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; void ao_adc_poll(void) @@ -39,14 +35,14 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { #if HAS_FLIGHT - uint8_t i = ao_adc_ring_prev(ao_sample_adc); + uint8_t i = ao_data_ring_prev(ao_sample_data); #else - uint8_t i = ao_adc_ring_prev(ao_adc_head); + uint8_t i = ao_data_ring_prev(ao_data_head); #endif - ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, (void __xdata *) &ao_data_ring[i], sizeof (struct ao_data)); } void @@ -60,14 +56,14 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); sequence = 0; } else #endif { if (sequence == ADCCON3_ECH_TEMP) sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel + sequence); sequence++; } #define GOT_ADC @@ -87,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: @@ -149,20 +145,20 @@ ao_adc_isr(void) __interrupt 1 else { /* record this conversion series */ - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup(DATA_TO_XDATA(&ao_data_head)); } } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; - ao_adc_get(&packet); + static __xdata struct ao_data packet; + ao_data_get(&packet); printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", - packet.tick, packet.accel, packet.pres, packet.temp, - packet.v_batt, packet.sense_d, packet.sense_m); + packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, + packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); } __code struct ao_cmds ao_adc_cmds[] = { diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 9d0643b4..704ae4f9 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -199,7 +199,6 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t temp; /* temperature sensor */ @@ -208,7 +207,7 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 /* ao_button.c */ #ifdef HAS_BUTTON diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index dd529088..cf07dfe8 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include __xdata struct ao_ignition ao_ignition[2]; @@ -29,12 +30,12 @@ ao_ignite(enum ao_igniter igniter) __critical enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter) { - __xdata struct ao_adc adc; + __xdata struct ao_data packet; __pdata int16_t value; __pdata uint8_t request, firing, fired; __critical { - ao_adc_get(&adc); + ao_data_get(&packet); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; firing = ao_ignition[igniter].firing; @@ -45,10 +46,10 @@ ao_igniter_status(enum ao_igniter igniter) value = (AO_IGNITER_CLOSED>>1); switch (igniter) { case ao_igniter_drogue: - value = adc.sense_d; + value = packet.adc.sense_d; break; case ao_igniter_main: - value = adc.sense_m; + value = packet.adc.sense_m; break; } if (value < AO_IGNITER_OPEN) diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index 8ec740c4..0dd87080 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,29 +18,7 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ -/* - * One set of samples read from the A/D converter or telemetry - */ - -#if AO_ADC_RING -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -#endif +#include /* Trigger a conversion sequence (called from the timer interrupt) */ void @@ -50,9 +28,9 @@ ao_adc_poll(void); void ao_adc_sleep(void); -/* Get a copy of the last complete A/D sample set */ +/* Get a copy of the last complete sample set */ void -ao_adc_get(__xdata struct ao_adc *packet); +ao_data_get(__xdata struct ao_data *packet); /* Initialize the A/D converter */ void diff --git a/src/core/ao_data.h b/src/core/ao_data.h index d28730a8..bd7e2d54 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -96,7 +96,7 @@ typedef int16_t accel_t; typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) -#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_set_accel(packet, a) ((packet)->adc.accel = (a)) #define ao_data_accel_invert(a) (0x7fff -(a)) /* diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 43b3aa0c..50eca069 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -60,7 +60,7 @@ ao_log_dump_check_data(void) return 1; } -static __data uint8_t ao_log_adc_pos; +static __data uint8_t ao_log_data_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; @@ -94,17 +94,17 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); - next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_data_pos = ao_data_ring_next(ao_sample_data); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_sample_adc) { - log.tick = ao_adc_ring[ao_log_adc_pos].tick; + while (ao_log_data_pos != ao_sample_data) { + log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].adc.pres; ao_log_data(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; @@ -113,16 +113,16 @@ ao_log(void) } if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + log.u.temp_volt.temp = ao_data_ring[ao_log_data_pos].adc.temp; + log.u.temp_volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; ao_log_data(&log); log.type = AO_LOG_DEPLOY; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + log.u.deploy.drogue = ao_data_ring[ao_log_data_pos].adc.sense_d; + log.u.deploy.main = ao_data_ring[ao_log_data_pos].adc.sense_m; ao_log_data(&log); next_other = log.tick + AO_OTHER_INTERVAL; } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Write state change to EEPROM */ if (ao_flight_state != ao_log_state) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 46d72609..800adfcb 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_adc_ring_prev(ao_sample_adc); + uint8_t sample = ao_data_ring_prev(ao_sample_data); - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; + telemetry.sensor.accel = ao_data_ring[sample].adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; + telemetry.sensor.pres = ao_data_ring[sample].adc.pres; + telemetry.sensor.temp = ao_data_ring[sample].adc.temp; + telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; + telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; + telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; @@ -99,19 +99,19 @@ static uint8_t ao_baro_sample; static void ao_send_baro(void) { - uint8_t sample = ao_sample_adc; - uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + uint8_t sample = ao_sample_data; + uint8_t samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1); if (samples > 12) { - ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1); samples = 12; } - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_BARO; telemetry.baro.samples = samples; for (sample = 0; sample < samples; sample++) { - telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; - ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres; + ao_baro_sample = ao_data_ring_next(ao_baro_sample); } ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index e4f55f88..b1111053 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -34,8 +34,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight.c \ - ao_sample.c \ + ao_flight_mm.c \ + ao_sample_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 02187205..ea9e25e4 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -104,14 +104,22 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else uint8_t i = ao_data_ring_prev(ao_data_head); +#endif memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); } void ao_data_get(__xdata struct ao_data *packet) { +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else uint8_t i = ao_data_ring_prev(ao_data_head); +#endif memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } -- cgit v1.2.3 From 98e992b65d366d9f79d7d2dd2dd4d1886dd1d9c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:25:17 -0600 Subject: altos: Make telemetrum-v1.0 build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bd7e2d54..bb26c4c0 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -183,7 +183,7 @@ typedef int16_t accel_t; #define ao_data_accel_sample(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) #else -#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ #endif /* else some other pressure sensor */ -- cgit v1.2.3 From 090dc9aecdf4cfd1ac727325ae141d441c5b28aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:26:43 -0600 Subject: altos: Make telemini-v1.0 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/core/ao_log_tiny.c | 12 ++++++------ src/product/Makefile.telemini | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1e3d8cab..f34bc042 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -83,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c index d5a3b99f..492658ea 100644 --- a/src/core/ao_log_tiny.c +++ b/src/core/ao_log_tiny.c @@ -85,7 +85,7 @@ ao_log(void) enum ao_flight_state ao_log_tiny_state; int32_t sum; int16_t count; - uint8_t ao_log_adc; + uint8_t ao_log_data; uint8_t ao_log_started = 0; ao_storage_setup(); @@ -96,18 +96,18 @@ ao_log(void) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; sum = 0; count = 0; - ao_log_adc = ao_sample_adc; + ao_log_data = ao_sample_data; last_time = ao_time(); for (;;) { /* * Add in pending sample data */ - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (ao_log_adc != ao_sample_adc) { - sum += ao_adc_ring[ao_log_adc].pres; + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (ao_log_data != ao_sample_data) { + sum += ao_data_ring[ao_log_data].adc.pres; count++; - ao_log_adc = ao_adc_ring_next(ao_log_adc); + ao_log_data = ao_data_ring_next(ao_log_data); } if (ao_log_running) { if (!ao_log_started) { diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 82ec42a2..9506eb65 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -22,14 +22,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight.c \ + ao_flight_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 627b904b36e129ff2ead436a626699abfc3b3211 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:29:27 -0600 Subject: altos: Make stm-demo compile with new ao_data structure Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 8 ++++---- src/stm-demo/ao_pins.h | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 7bb53047..232c2313 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -119,7 +119,7 @@ ao_i2c_write(void) { for (i = 0; i < 10; i++) { ao_i2c_get(0); if (ao_i2c_start(0, 0x55)) - ao_i2c_send(data, 4, 0); + ao_i2c_send(data, 4, 0, TRUE); else { printf ("i2c start failed\n"); ao_i2c_put(0); @@ -135,16 +135,16 @@ ao_i2c_write(void) { static void ao_temp (void) { - struct ao_adc adc; + struct ao_data packet; int temp; - ao_adc_get(&adc); + ao_data_get(&packet); /* * r = (110 - 25) / (ts_cal_hot - ts_cal_cold) * 25 + (110 - 25) * (temp - ts_cal_cold) / (ts_cal_hot - ts_cal_cold) */ - temp = 25 + (110 - 25) * (adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); + temp = 25 + (110 - 25) * (packet.adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); printf ("temp: %d\n", temp); } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 1daab351..d02c071c 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -156,6 +156,7 @@ struct ao_adc { #define HAS_ADC_TEMP 1 +#define AO_DATA_RING 32 #define AO_NUM_ADC 3 #define AO_ADC_SQ1 AO_ADC_IDD -- cgit v1.2.3 From 5fd869b244f8f2b76258dc31a5507a73fd47cf1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:31:12 -0600 Subject: altos: Make telenano build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_flight_nano.c | 4 ++-- src/product/Makefile.telenano | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c index 2e332b12..406d81ad 100644 --- a/src/core/ao_flight_nano.c +++ b/src/core/ao_flight_nano.c @@ -27,8 +27,8 @@ __pdata uint16_t ao_launch_tick; /* time of launch detect */ * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +__pdata alt_t ao_interval_min_height; +__pdata alt_t ao_interval_max_height; __pdata uint8_t ao_flight_force_idle; diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index cf27527c..56db1c2c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -29,7 +29,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 29edf6d901432a1afc65900ff599c963edac5a2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:44:01 -0600 Subject: altos: Make telescience-v0.1 build with new ao_data struct Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 24 ++++++++--------- src/avr/ao_pins.h | 3 +-- src/core/ao_log_telescience.c | 14 +++++----- src/core/ao_stdio.c | 16 ++++++------ src/drivers/ao_science_slave.c | 2 +- src/test/Makefile | 4 +-- src/test/ao_flight_test.c | 58 ++++++++++++++++++++++-------------------- 7 files changed, 61 insertions(+), 60 deletions(-) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 4f6f0e60..928cd3e1 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; #ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { @@ -92,14 +92,14 @@ ISR(ADC_vect) /* Must read ADCL first or the value there will be lost */ value = ADCL; value |= (ADCH << 8); - ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = value; if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_cpu_sleep_disable = 0; } } @@ -113,18 +113,18 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; + static __xdata struct ao_data packet; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); #ifdef TELEPYRO printf("ADMUX: %02x\n", ADMUX); printf("ADCSRA: %02x\n", ADCSRA); @@ -137,7 +137,7 @@ ao_adc_dump(void) __reentrant #endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) - printf (" %2d: %5u", i, packet.adc[i]); + printf (" %2d: %5u", i, packet.adc.adc[i]); printf("\n"); diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index f2b40fb4..850a08ec 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -91,10 +91,9 @@ #define AO_TELESCIENCE_NUM_ADC 12 struct ao_adc { - uint16_t tick; /* tick when the sample was read */ uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ }; -#define AO_ADC_RING 16 +#define AO_DATA_RING 16 #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index ae045281..002a10bd 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -20,7 +20,7 @@ #include "ao_log.h" #include "ao_companion.h" -static uint8_t ao_log_adc_pos; +static uint8_t ao_log_data_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; @@ -62,20 +62,20 @@ ao_log_single(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_data_pos = ao_data_ring_next(ao_data_head); ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_adc_head) { - ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + while (ao_log_data_pos != ao_data_head) { + ao_log_single_write_data.telescience.tick = ao_data_ring[ao_log_data_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_data_ring[ao_log_data_pos].adc.adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); ao_log_telescience_csum(); ao_log_single_write(); - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Wait for more ADC data to arrive */ - ao_sleep((void *) &ao_adc_head); + ao_sleep((void *) &ao_data_head); } memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 9b4ea473..656b23c9 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -53,14 +53,14 @@ #endif #define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ - USE_SERIAL_1_STDIN | \ - USE_SERIAL_2_STDIN | \ - USE_SERIAL_3_STDIN | \ - USE_SERIAL_4_STDIN | \ - USE_SERIAL_5_STDIN | \ - USE_SERIAL_6_STDIN | \ - USE_SERIAL_7_STDIN | \ - USE_SERIAL_8_STDIN | \ + USE_SERIAL_1_STDIN + \ + USE_SERIAL_2_STDIN + \ + USE_SERIAL_3_STDIN + \ + USE_SERIAL_4_STDIN + \ + USE_SERIAL_5_STDIN + \ + USE_SERIAL_6_STDIN + \ + USE_SERIAL_7_STDIN + \ + USE_SERIAL_8_STDIN + \ USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index a86b5151..996e98d9 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -42,7 +42,7 @@ void ao_spi_slave(void) sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + ao_spi_slave_send((uint8_t *) &ao_data_ring[ao_data_ring_prev(ao_data_head)].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: diff --git a/src/test/Makefile b/src/test/Makefile index 3c2b8732..1e54f5e0 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 4a8625cf..baf2ad1d 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -26,9 +26,10 @@ #define AO_HERTZ 100 -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) +#define HAS_ADC 1 +#define AO_DATA_RING 64 +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) #define AO_M_TO_HEIGHT(m) ((int16_t) (m)) #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) @@ -38,7 +39,6 @@ * One set of samples read from the A/D converter */ struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t pres_real; /* unclipped */ @@ -54,6 +54,8 @@ struct ao_adc { #define __code #define __reentrant +#include + #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) #define from_fix(x) ((x) >> 16) @@ -90,8 +92,8 @@ extern enum ao_flight_state ao_flight_state; #define FALSE 0 #define TRUE 1 -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; +volatile struct ao_data ao_data_ring[AO_DATA_RING]; +volatile uint8_t ao_data_head; int ao_summary = 0; #define ao_led_on(l) @@ -110,7 +112,7 @@ enum ao_igniter { ao_igniter_main = 1 }; -struct ao_adc ao_adc_static; +struct ao_data ao_data_static; int drogue_height; double drogue_time; @@ -124,7 +126,7 @@ static int32_t ao_k_height; void ao_ignite(enum ao_igniter igniter) { - double time = (double) (ao_adc_static.tick + tick_offset) / 100; + double time = (double) (ao_data_static.tick + tick_offset) / 100; if (igniter == ao_igniter_drogue) { drogue_time = time; @@ -221,8 +223,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample.c" -#include "ao_flight.c" +#include "ao_sample_mm.c" +#include "ao_flight_mm.c" #define to_double(f) ((f) / 65536.0) @@ -282,19 +284,19 @@ ao_insert(void) { double time; - ao_adc_ring[ao_adc_head] = ao_adc_static; - ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_data_ring[ao_data_head] = ao_data_static; + ao_data_head = ao_data_ring_next(ao_data_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + double height = ao_pres_to_altitude(ao_data_static.adc.pres_real) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_data_static.adc.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); if (!tick_offset) - tick_offset = -ao_adc_static.tick; - if ((prev_tick - ao_adc_static.tick) > 0x400) + tick_offset = -ao_data_static.tick; + if ((prev_tick - ao_data_static.tick) > 0x400) tick_offset += 65536; - prev_tick = ao_adc_static.tick; - time = (double) (ao_adc_static.tick + tick_offset) / 100; + prev_tick = ao_data_static.tick; + time = (double) (ao_data_static.tick + tick_offset) / 100; if (ao_test_max_height < height) { ao_test_max_height = height; @@ -474,7 +476,7 @@ int16(uint8_t *bytes, int off) void ao_sleep(void *wchan) { - if (wchan == &ao_adc_head) { + if (wchan == &ao_data_head) { char type; uint16_t tick; uint16_t a, b; @@ -490,7 +492,7 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { - ao_adc_static.accel = ao_flight_ground_accel; + ao_data_static.adc.accel = ao_flight_ground_accel; ao_insert(); return; } @@ -501,7 +503,7 @@ ao_sleep(void *wchan) printf ("no more data, exiting simulation\n"); ao_test_exit(); } - ao_adc_static.tick += 10; + ao_data_static.tick += 10; ao_insert(); return; } @@ -639,19 +641,19 @@ ao_sleep(void *wchan) case 'S': break; case 'A': - ao_adc_static.tick = tick; - ao_adc_static.accel = a; - ao_adc_static.pres_real = b; + ao_data_static.tick = tick; + ao_data_static.adc.accel = a; + ao_data_static.adc.pres_real = b; if (b < AO_MIN_BARO_VALUE) b = AO_MIN_BARO_VALUE; - ao_adc_static.pres = b; + ao_data_static.adc.pres = b; ao_records_read++; ao_insert(); return; case 'T': - ao_adc_static.tick = tick; - ao_adc_static.temp = a; - ao_adc_static.v_batt = b; + ao_data_static.tick = tick; + ao_data_static.adc.temp = a; + ao_data_static.adc.v_batt = b; break; case 'D': case 'G': -- cgit v1.2.3 From 5dd5e0284c8b26b0d4ce69c64bb7864e0ae83db7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:45:09 -0600 Subject: altos: Make telepyro-v0.1 build with new ao_data struct Signed-off-by: Keith Packard --- src/drivers/ao_pyro_slave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 5a8ab922..70206a00 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -41,7 +41,7 @@ void ao_spi_slave(void) sizeof (ao_telepyro_setup)); break; case AO_COMPANION_FETCH: - ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + ao_spi_slave_send((uint8_t *) &ao_data_ring[ao_data_ring_prev(ao_data_head)].adc.adc, AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: -- cgit v1.2.3 From 9f5e4cf7d8204016e023cf439d93de1203dc406e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 18:23:39 -0600 Subject: altos: Make teleterra v0.2 compile with new ao_data struct Signed-off-by: Keith Packard --- src/teleterra-v0.2/ao_pins.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index bcabdfee..1c12c437 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -21,6 +21,7 @@ #ifdef TELETERRA_V_0_2 #define HAS_FLIGHT 0 #define HAS_USB 1 + #define HAS_RADIO 1 #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 -- cgit v1.2.3 From 43e558738c76afd72fc01660884be3158f44470d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:44:07 -0600 Subject: altos: Try to get hmc5883 working No joy yet Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 92 ++++++++++++++++++++++++++---------------------- src/drivers/ao_hmc5883.h | 7 ++++ 2 files changed, 57 insertions(+), 42 deletions(-) diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 43d04f70..9551df71 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,55 +19,64 @@ #include #include -static uint8_t ao_hmc5883_wake; static uint8_t ao_hmc5883_configured; static void -ao_hmc5883_isr(void) +ao_hmc5883_reg_write(uint8_t addr, uint8_t data) { - ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ao_hmc5883_wake = 1; - ao_wakeup(&ao_hmc5883_wake); -} - -static uint8_t ao_hmc5883_addr_reg; + uint8_t d[2]; -static void -ao_hmc5883_update_addr (uint8_t len) -{ - ao_hmc5883_addr_reg += len; - if (ao_hmc5883_addr_reg == 9) - ao_hmc5883_addr_reg = 3; - else if (ao_hmc5883_addr_reg > 12) - ao_hmc5883_addr_reg = 0; - + d[0] = addr; + d[1] = data; + ao_i2c_get(AO_HMC5883_I2C_INDEX); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(d, 2, AO_HMC5883_I2C_INDEX, TRUE); + ao_i2c_put(AO_HMC5883_I2C_INDEX); } static void -ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) +ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); - ao_hmc5883_addr_reg = addr; - ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX, TRUE); - ao_hmc5883_update_addr(len); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); } +static uint8_t ao_hmc5883_done; + static void -ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) +ao_hmc5883_isr(void) { - ao_i2c_get(AO_HMC5883_I2C_INDEX); - if (addr != ao_hmc5883_addr_reg) { - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); - ao_hmc5883_addr_reg = addr; + ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_done = 1; + ao_wakeup(&ao_hmc5883_done); +} + +void +ao_hmc5883_sample(struct ao_hmc5883_sample *sample) +{ + uint16_t *d = (uint16_t *) sample; + int i = sizeof (*sample) / 2; + uint8_t single = HMC5883_MODE_SINGLE; + + ao_hmc5883_done = 0; + ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + cli(); + while (!ao_hmc5883_done) + ao_sleep(&ao_hmc5883_done); + sei(); + ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* byte swap */ + while (i--) { + uint16_t t = *d; + *d++ = (t >> 8) | (t << 8); } - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); - ao_hmc5883_update_addr(len); - ao_i2c_put(AO_HMC5883_I2C_INDEX); +#endif } static uint8_t @@ -82,8 +91,6 @@ ao_hmc5883_setup(void) ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, AO_EXTI_MODE_FALLING, ao_hmc5883_isr); - ao_hmc5883_addr_reg = 0xff; - ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); @@ -98,25 +105,21 @@ static void ao_hmc5883_show(void) { uint8_t addr, data; + struct ao_hmc5883_sample sample; - for (addr = 0x00; addr <= 0x7f; addr++) - { - ao_i2c_get(AO_HMC5883_I2C_INDEX); - data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); - ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); - ao_i2c_put(AO_HMC5883_I2C_INDEX); - if (data) - printf("address %02x responds\n", addr << 1); - } if (!ao_hmc5883_setup()) { printf("hmc5883 not present\n"); return; } +#if 0 for (addr = 0; addr <= 12; addr++) { ao_hmc5883_read(addr, &data, 1); printf ("hmc5883 register %2d: %02x\n", addr, data); } +#endif + ao_hmc5883_sample(&sample); + printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); } static const struct ao_cmds ao_hmc5883_cmds[] = { @@ -129,5 +132,10 @@ ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_exti_setup(&AO_HMC5883_INT_PORT, + AO_HMC5883_INT_PIN, + AO_EXTI_MODE_FALLING, + ao_hmc5883_isr); + ao_cmd_register(&ao_hmc5883_cmds[0]); } diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 399ddcdd..2ec27dd9 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -24,6 +24,9 @@ #define HMC5883_CONFIG_A 0 #define HMC5883_CONFIG_B 1 #define HMC5883_MODE 2 +#define HMC5883_MODE_CONTINUOUS 0 +#define HMC5883_MODE_SINGLE 1 +#define HMC5883_MODE_IDLE 2 #define HMC5883_X_MSB 3 #define HMC5883_X_LSB 4 #define HMC5883_Y_MSB 5 @@ -35,6 +38,10 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 +struct ao_hmc5883_sample { + int16_t x, y, z; +}; + void ao_hmc5883_init(void); -- cgit v1.2.3 From a53b8b84283eb62157b0f8ecd8061f61a4b6bd6f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:44:45 -0600 Subject: altos: Shrink telemetry generation code otherwise TM doesn't build anymore Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 800adfcb..6e8fc02f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_data_ring_prev(ao_sample_data); + __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; - telemetry.generic.tick = ao_data_ring[sample].tick; + telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_data_ring[sample].adc.accel; + telemetry.sensor.accel = packet->adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_data_ring[sample].adc.pres; - telemetry.sensor.temp = ao_data_ring[sample].adc.temp; - telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; + telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.temp = packet->adc.temp; + telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; - telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; + telemetry.sensor.sense_d = packet->adc.sense_d; + telemetry.sensor.sense_m = packet->adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; -- cgit v1.2.3 From 2df9113a22f4f67707d9ee777bd6b23ff671b105 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:45:30 -0600 Subject: altos: All cc1111 products have a radio Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 4f6edd37..5eef0de4 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -18,6 +18,8 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +#define HAS_RADIO 1 + #if defined(TELEMETRUM_V_1_0) #define HAS_FLIGHT 1 #define HAS_USB 1 -- cgit v1.2.3 From ee61fb8ccb47f94b7c39e803f5a0248840d1eea6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:45:53 -0600 Subject: altos: Clean up ADC selection for cc1111 Depend directly on product defines instead of trying to guess Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index f34bc042..95643956 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -52,7 +52,7 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; -#if IGNITE_ON_P2 +#if TELEMETRUM_V_0_1 || TELEMETRUM_V_0_2 || TELEMETRUM_V_1_0 || TELEMETRUM_V_1_1 || TELEMETRUM_V_1_2 || TELELAUNCH_V_0_1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { @@ -81,10 +81,10 @@ ao_adc_isr(void) __interrupt 1 } #endif -#if IGNITE_ON_P0 +#if TELEMINI_V_1_0 || TELENANO_V_0_1 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.pres); -#ifdef TELEMINI_V_1_0 +#if TELEMINI_V_1_0 switch (sequence) { case 0: /* pressure */ @@ -138,7 +138,8 @@ ao_adc_isr(void) __interrupt 1 /* Start next conversion */ ADCCON3 = sequence; } -#endif +#endif /* telemini || telenano */ + #ifndef GOT_ADC #error No known ADC configuration set #endif -- cgit v1.2.3 From 8164cd95db62e4564b3a9ba5c06a74c870c03841 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:46:51 -0600 Subject: altos: Remove debug printf from accel auto-cal Otherwise, this goes way too slow Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55ec9f40..76a8ed4a 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -256,8 +256,6 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant while (i) { ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { - int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); - printf ("accel %d\n", accel); accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); cal_data_ring = ao_data_ring_next(cal_data_ring); i--; -- cgit v1.2.3 From 47bc9b2a39b7a8d3ef3fe8acc7fbf0512695e548 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:47:28 -0600 Subject: altos: Clear stm i2c transfer timeout alarm Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 763ae6cd..d82342db 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -250,10 +250,9 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_alarm(1 + len); cli(); while (!ao_dma_done[tx_dma_index]) - if (ao_sleep(&ao_dma_done[tx_dma_index])) { - printf ("send timeout\n"); + if (ao_sleep(&ao_dma_done[tx_dma_index])) break; - } + ao_clear_alarm(); ao_dma_done_transfer(tx_dma_index); out_cr2("send enable isr", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); -- cgit v1.2.3 From 7fce3ddf5e7e92a14cefb7fcf35e4014df744987 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:48:04 -0600 Subject: Bump to 1.0.9.5 Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index f8707056..f84387d2 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.4) +AC_INIT([altos], 1.0.9.5) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From e5aebfe0203de9e69712fac291c8cd0d3a96a385 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:33:18 -0700 Subject: altos: Mark full and mega logging correctly in 'v' command Make sure megametrum reports 'log format 5'. Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 -- src/core/ao_log_big.c | 2 ++ src/core/ao_log_mega.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/ao_log.c b/src/core/ao_log.c index d696625e..7884ec3c 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -25,8 +25,6 @@ __xdata uint8_t ao_log_running; __pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; -__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; - void ao_log_flush(void) { diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 50eca069..db01f46c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -20,6 +20,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_record log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 1763b9eb..404e6bf7 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -23,6 +23,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mega log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_MEGAMETRUM; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { -- cgit v1.2.3 From 6806103bad98385c0ec122d400f981eb81c59dd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:34:17 -0700 Subject: altos: add high-z accel and mag sensor to megametrum logging These nicely fill the 32-byte sensor log record Signed-off-by: Keith Packard --- src/core/ao_log.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/core/ao_log.h b/src/core/ao_log.h index e585750f..04abeb7e 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -216,13 +216,17 @@ struct ao_log_mega { int16_t gyro_x; /* 18 */ int16_t gyro_y; /* 20 */ int16_t gyro_z; /* 22 */ - } sensor; /* 24 */ + int16_t mag_x; /* 24 */ + int16_t mag_y; /* 26 */ + int16_t mag_z; /* 28 */ + int16_t accel; /* 30 */ + } sensor; /* 32 */ struct { int16_t v_batt; /* 4 */ - int16_t v_pbatt; /* 8 */ - int16_t n_sense; /* 10 */ - int16_t sense[10]; /* 12 */ - } volt; /* 32 */ + int16_t v_pbatt; /* 6 */ + int16_t n_sense; /* 8 */ + int16_t sense[10]; /* 10 */ + } volt; /* 30 */ struct { int32_t latitude; /* 4 */ int32_t longitude; /* 8 */ -- cgit v1.2.3 From ff4f3a56e09d595abbe32293cbdf1fe368633c49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:35:01 -0700 Subject: altos: megametrum has logging This makes sure the various other subsystems know about it, like the 'v' command. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2ae3cea8..ff0edaa9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -98,6 +98,7 @@ #define HAS_FLIGHT 1 #define HAS_ADC 1 #define HAS_ACCEL 1 +#define HAS_LOG 1 #define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 -- cgit v1.2.3 From ab85337aa942cb73a08bd3b783771179773b9a67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:35:33 -0700 Subject: altos: Timers clock base depends on perhipheral bus prescalers too For some weird reason, a non-unity perhipheral bus clock scaler affects the base of the various timers; this left the 100Hz tick running at 200Hz. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 099a0ece..0c44f352 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -69,7 +69,19 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif -#define TIMER_10kHz (AO_PCLK1 / 10000) +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) void ao_timer_init(void) -- cgit v1.2.3 From 1824761f5b98e92485e2dd347b1c4d043ec207e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:51:25 -0700 Subject: altosui: Quick hacks to download megametrum data and convert to CSV Very little useful data crunching is done, but at least we can save and convert files Signed-off-by: Keith Packard --- altosui/Altos.java | 12 + altosui/AltosCSV.java | 42 ++- altosui/AltosConfigData.java | 2 +- altosui/AltosDataChooser.java | 3 + altosui/AltosEepromChunk.java | 5 + altosui/AltosEepromDownload.java | 67 ++++- altosui/AltosEepromIterable.java | 26 +- altosui/AltosEepromList.java | 4 +- altosui/AltosEepromMega.java | 218 +++++++++++++++ altosui/AltosEepromMegaIterable.java | 523 +++++++++++++++++++++++++++++++++++ altosui/AltosIMU.java | 29 ++ altosui/AltosMag.java | 25 ++ altosui/AltosMs5607.java | 76 +++++ altosui/AltosRecord.java | 5 + altosui/AltosState.java | 5 + altosui/AltosUI.java | 2 + altosui/Makefile.am | 5 + 17 files changed, 1039 insertions(+), 10 deletions(-) create mode 100644 altosui/AltosEepromMega.java create mode 100644 altosui/AltosEepromMegaIterable.java create mode 100644 altosui/AltosIMU.java create mode 100644 altosui/AltosMag.java create mode 100644 altosui/AltosMs5607.java diff --git a/altosui/Altos.java b/altosui/Altos.java index aa2fd77a..1d393dbe 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -52,6 +52,17 @@ public class Altos { static final int AO_LOG_PRODUCT = 2001; static final int AO_LOG_SERIAL_NUMBER = 2002; static final int AO_LOG_LOG_FORMAT = 2003; + + /* Added for header fields in megametrum files */ + static final int AO_LOG_BARO_RESERVED = 3000; + static final int AO_LOG_BARO_SENS = 3001; + static final int AO_LOG_BARO_OFF = 3002; + static final int AO_LOG_BARO_TCS = 3004; + static final int AO_LOG_BARO_TCO = 3005; + static final int AO_LOG_BARO_TREF = 3006; + static final int AO_LOG_BARO_TEMPSENS = 3007; + static final int AO_LOG_BARO_CRC = 3008; + static final int AO_LOG_SOFTWARE_VERSION = 9999; /* Added to flag invalid records */ @@ -220,6 +231,7 @@ public class Altos { static final int AO_LOG_FORMAT_TINY = 2; static final int AO_LOG_FORMAT_TELEMETRY = 3; static final int AO_LOG_FORMAT_TELESCIENCE = 4; + static final int AO_LOG_FORMAT_MEGAMETRUM = 5; static final int AO_LOG_FORMAT_NONE = 127; static boolean isspace(int c) { diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index 9ec21bef..b88bedba 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -31,7 +31,7 @@ public class AltosCSV implements AltosWriter { LinkedList pad_records; AltosState state; - static final int ALTOS_CSV_VERSION = 4; + static final int ALTOS_CSV_VERSION = 5; /* Version 4 format: * @@ -61,6 +61,17 @@ public class AltosCSV implements AltosWriter { * drogue (V) * main (V) * + * Advanced sensors (if available) + * accel_x (m/s²) + * accel_y (m/s²) + * accel_z (m/s²) + * gyro_x (d/s) + * gyro_y (d/s) + * gyro_z (d/s) + * mag_x (g) + * mag_y (g) + * mag_z (g) + * * GPS data (if available) * connected (1/0) * locked (1/0) @@ -129,6 +140,24 @@ public class AltosCSV implements AltosWriter { record.main_voltage()); } + void write_advanced_header() { + out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z"); + } + + void write_advanced(AltosRecord record) { + AltosIMU imu = record.imu; + AltosMag mag = record.mag; + + if (imu == null) + imu = new AltosIMU(); + if (mag == null) + mag = new AltosMag(); + out.printf("%d,%d,%d,%d,%d,%d,%d,%d,%d", + imu.accel_x, imu.accel_y, imu.accel_z, + imu.gyro_x, imu.gyro_y, imu.gyro_z, + mag.x, mag.y, mag.z); + } + void write_gps_header() { out.printf("connected,locked,nsat,latitude,longitude,altitude,year,month,day,hour,minute,second,pad_dist,pad_range,pad_az,pad_el,hdop"); } @@ -212,10 +241,12 @@ public class AltosCSV implements AltosWriter { out.printf(",0"); } - void write_header(boolean gps, boolean companion) { + void write_header(boolean advanced, boolean gps, boolean companion) { out.printf("#"); write_general_header(); out.printf(","); write_flight_header(); out.printf(","); write_basic_header(); + if (advanced) + out.printf(","); write_advanced_header(); if (gps) { out.printf(","); write_gps_header(); out.printf(","); write_gps_sat_header(); @@ -230,7 +261,9 @@ public class AltosCSV implements AltosWriter { state = new AltosState(record, state); write_general(record); out.printf(","); write_flight(record); out.printf(","); - write_basic(record); + write_basic(record); out.printf(","); + if (record.imu != null || record.mag != null) + write_advanced(record); if (record.gps != null) { out.printf(","); write_gps(record); out.printf(","); @@ -253,7 +286,8 @@ public class AltosCSV implements AltosWriter { if (record.state == Altos.ao_flight_startup) return; if (!header_written) { - write_header(record.gps != null, record.companion != null); + write_header(record.imu != null || record.mag != null, + record.gps != null, record.companion != null); header_written = true; } if (!seen_boost) { diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 53509dfa..64d9f095 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -138,7 +138,7 @@ public class AltosConfigData implements Iterable { } public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { - serial_line.printf("c s\nf\nl\nv\n"); + serial_line.printf("c s\np\nf\nl\nv\n"); lines = new LinkedList(); radio_setting = 0; radio_frequency = 0; diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index d81ca6d1..488e1068 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -56,6 +56,9 @@ public class AltosDataChooser extends JFileChooser { } else if (filename.endsWith("telem")) { FileInputStream in = new FileInputStream(file); return new AltosTelemetryIterable(in); + } else if (filename.endsWith("mega")) { + FileInputStream in = new FileInputStream(file); + return new AltosEepromMegaIterable(in); } else { throw new FileNotFoundException(); } diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index 59767c2a..77707f7b 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -52,6 +52,11 @@ public class AltosEepromChunk { return data[offset] | (data[offset + 1] << 8); } + int data32(int offset) { + return data[offset] | (data[offset + 1] << 8) | + (data[offset+2] << 16) | (data[offset+3] << 24); + } + boolean erased(int start, int len) { for (int i = 0; i < len; i++) if (data[start+i] != 0xff) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 40c98bfd..8f7a8544 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -248,6 +248,64 @@ public class AltosEepromDownload implements Runnable { done = true; } + void LogMega(AltosEepromMega r) throws IOException { + if (r.cmd != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", + r.cmd, r.tick, + r.data8[0], r.data8[1], r.data8[2], r.data8[3], + r.data8[4], r.data8[5], r.data8[6], r.data8[7], + r.data8[8], r.data8[9], r.data8[10], r.data8[11], + r.data8[12], r.data8[13], r.data8[14], r.data8[15], + r.data8[16], r.data8[17], r.data8[18], r.data8[19], + r.data8[20], r.data8[21], r.data8[22], r.data8[23], + r.data8[24], r.data8[25], r.data8[26], r.data8[27]); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + } + } + + void CaptureMega(AltosEepromChunk eechunk) throws IOException { + boolean any_valid = false; + + extension = "mega"; + set_serial(flights.config_data.serial); + for (int i = 0; i < eechunk.chunk_size && !done; i += AltosEepromMega.record_length) { + try { + AltosEepromMega r = new AltosEepromMega(eechunk, i); + if (r.cmd == Altos.AO_LOG_FLIGHT) + set_flight(r.data16(0)); + + /* Monitor state transitions to update display */ + if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) <= Altos.ao_flight_landed) { + state = r.data16(0); + if (state > Altos.ao_flight_pad) + want_file = true; + } + + if (r.cmd == Altos.AO_LOG_GPS_TIME) { + year = 2000 + r.data8(14); + month = r.data8(15); + day = r.data8(14); + want_file = true; + } + + if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) == Altos.ao_flight_landed) + done = true; + any_valid = true; + LogMega(r); + } catch (ParseException pe) { + if (parse_exception == null) + parse_exception = pe; + } + } + if (!any_valid) + done = true; + + CheckFile(false); + } + void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { } @@ -260,9 +318,11 @@ public class AltosEepromDownload implements Runnable { done = false; start = true; - if (flights.config_data.serial == 0) - throw new IOException("no serial number found"); +// if (flights.config_data.serial == 0) +// throw new IOException("no serial number found"); + log_format = 5; + System.out.printf ("log format: %d\n", log_format); /* Reset per-capture variables */ flight = 0; year = 0; @@ -312,6 +372,9 @@ public class AltosEepromDownload implements Runnable { extension = "science"; CaptureTeleScience(eechunk); break; + case Altos.AO_LOG_FORMAT_MEGAMETRUM: + extension = "mega"; + CaptureMega(eechunk); } } CheckFile(true); diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index 6fdaf8e0..b8e21ece 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -268,7 +268,7 @@ public class AltosEepromIterable extends AltosRecordIterable { AltosRecord r = new AltosRecord(state); r.time = (r.tick - eeprom.boost_tick) / 100.0; list.add(r); - return list; + return list; } public Iterator iterator() { @@ -323,6 +323,30 @@ public class AltosEepromIterable extends AltosRecordIterable { case Altos.AO_LOG_SOFTWARE_VERSION: out.printf ("# Software version: %s\n", record.data); break; + case Altos.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.a); + break; } } } diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index da4b1166..945746dd 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -62,8 +62,8 @@ public class AltosEepromList extends ArrayList { if (remote) serial_line.start_remote(); config_data = new AltosConfigData (serial_line); - if (config_data.serial == 0) - throw new IOException("no serial number found"); +// if (config_data.serial == 0) +// throw new IOException("no serial number found"); ArrayList flights = new ArrayList(); diff --git a/altosui/AltosEepromMega.java b/altosui/AltosEepromMega.java new file mode 100644 index 00000000..8ae485cb --- /dev/null +++ b/altosui/AltosEepromMega.java @@ -0,0 +1,218 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; + +public class AltosEepromMega { + public int cmd; + public int tick; + public boolean valid; + public String data; + int a, b; + + public int data8[]; + + static final int record_length = 32; + static final int header_length = 4; + static final int data_length = record_length - header_length; + + public int data8(int i) { + return data8[i]; + } + + public int data16(int i) { + return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; + } + + public int data32(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); + } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int ground_accel() { return data16(2); } + public int ground_pres() { return data32(4); } + public int ground_temp() { return data32(8); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data32(0); } + public int temp() { return data32(4); } + public int accel_x() { return data16(8); } + public int accel_y() { return data16(10); } + public int accel_z() { return data16(12); } + public int gyro_x() { return data16(14); } + public int gyro_y() { return data16(16); } + public int gyro_z() { return data16(18); } + public int mag_x() { return data16(20); } + public int mag_y() { return data16(22); } + public int mag_z() { return data16(24); } + public int accel() { + int a = data16(26); + if (a != 0xffff) + return a; + return accel_y(); + } + + /* AO_LOG_VOLT elements */ + public int v_batt() { return data16(0); } + public int v_pbatt() { return data16(2); } + public int nsense() { return data16(4); } + public int sense(int i) { return data16(6 + i * 2); } + + public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException { + cmd = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + cmd = Altos.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = chunk.data(start + header_length + i); + } + + public AltosEepromMega (String line) { + valid = false; + tick = 0; + + if (line == null) { + cmd = Altos.AO_LOG_INVALID; + line = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + if (tokens[0].length() == 1) { + if (tokens.length != 2 + data_length) { + cmd = Altos.AO_LOG_INVALID; + data = line; + } else { + cmd = tokens[0].codePointAt(0); + tick = Integer.parseInt(tokens[1],16); + valid = true; + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = Integer.parseInt(tokens[2 + i],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("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = Altos.AO_LOG_MAX_FLIGHT_LOG; + a = Integer.parseInt(tokens[3]); + } 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("log-format")) { + cmd = Altos.AO_LOG_LOG_FORMAT; + 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].equals("ms5607")) { + if (tokens[1].equals("reserved:")) { + cmd = Altos.AO_LOG_BARO_RESERVED; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("sens:")) { + cmd = Altos.AO_LOG_BARO_SENS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("off:")) { + cmd = Altos.AO_LOG_BARO_OFF; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tcs:")) { + cmd = Altos.AO_LOG_BARO_TCS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tco:")) { + cmd = Altos.AO_LOG_BARO_TCO; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tref:")) { + cmd = Altos.AO_LOG_BARO_TREF; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tempsens:")) { + cmd = Altos.AO_LOG_BARO_TEMPSENS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("crc:")) { + cmd = Altos.AO_LOG_BARO_CRC; + a = Integer.parseInt(tokens[2]); + } else { + cmd = Altos.AO_LOG_INVALID; + data = line; + } + } else { + cmd = Altos.AO_LOG_INVALID; + data = line; + } + } catch (NumberFormatException ne) { + cmd = Altos.AO_LOG_INVALID; + data = line; + } + } + } + + public AltosEepromMega(int in_cmd, int in_tick) { + cmd = in_cmd; + tick = in_tick; + valid = true; + } +} diff --git a/altosui/AltosEepromMegaIterable.java b/altosui/AltosEepromMegaIterable.java new file mode 100644 index 00000000..e2cd2785 --- /dev/null +++ b/altosui/AltosEepromMegaIterable.java @@ -0,0 +1,523 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable { + + public int index; + + public AltosOrderedMegaRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + index = in_index; + } + + public AltosOrderedMegaRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) { + super(in_cmd, in_tick); + a = in_a; + b = in_b; + index = in_index; + } + + public String toString() { + return String.format("%d.%d %04x %04x %04x", + cmd, index, tick, a, b); + } + + public int compareTo(AltosOrderedMegaRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromMegaIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor; + + boolean has_accel; + boolean has_gps; + boolean has_ignite; + + AltosEepromMega flight_record; + AltosEepromMega gps_date_record; + + TreeSet records; + + AltosMs5607 baro; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + int sensor_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromMega record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case Altos.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.ground_accel(); + state.flight_accel = record.ground_accel(); + state.ground_pres = baro.set(record.ground_pres(), record.ground_temp()); + state.flight_pres = state.ground_pres; + state.flight = record.data16(0); + eeprom.boost_tick = record.tick; + break; + case Altos.AO_LOG_SENSOR: + state.accel = record.accel(); + state.pres = baro.set(record.pres(), record.temp()); + state.temp = baro.cc; + state.imu = new AltosIMU(); + state.imu.accel_x = record.accel_x(); + state.imu.accel_y = record.accel_y(); + state.imu.accel_z = record.accel_z(); + state.imu.gyro_x = record.gyro_x(); + state.imu.gyro_y = record.gyro_y(); + state.imu.gyro_z = record.gyro_z(); + state.mag = new AltosMag(); + state.mag.x = record.mag_x(); + state.mag.y = record.mag_y(); + state.mag.z = record.mag_z(); + if (state.state < Altos.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + } + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); + eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; + has_accel = true; + break; + case Altos.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } + eeprom.seen |= seen_sensor; + break; + case Altos.AO_LOG_TEMP_VOLT: + state.batt = record.v_batt(); + eeprom.seen |= seen_temp_volt; + break; + case Altos.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + has_ignite = true; + break; + case Altos.AO_LOG_STATE: + state.state = record.state(); + break; + case Altos.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; + state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> + Altos.AO_GPS_NUM_SAT_SHIFT; + state.new_gps = true; + has_gps = true; + break; + case Altos.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case Altos.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case Altos.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case Altos.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case Altos.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case Altos.AO_LOG_CONFIG_VERSION: + break; + case Altos.AO_LOG_MAIN_DEPLOY: + break; + case Altos.AO_LOG_APOGEE_DELAY: + break; + case Altos.AO_LOG_RADIO_CHANNEL: + break; + case Altos.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case Altos.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case Altos.AO_LOG_RADIO_CAL: + break; + case Altos.AO_LOG_MANUFACTURER: + 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; + case Altos.AO_LOG_BARO_RESERVED: + baro.reserved = record.a; + break; + case Altos.AO_LOG_BARO_SENS: + baro.sens =record.a; + break; + case Altos.AO_LOG_BARO_OFF: + baro.off =record.a; + break; + case Altos.AO_LOG_BARO_TCS: + baro.tcs =record.a; + break; + case Altos.AO_LOG_BARO_TCO: + baro.tco =record.a; + break; + case Altos.AO_LOG_BARO_TREF: + baro.tref =record.a; + break; + case Altos.AO_LOG_BARO_TEMPSENS: + baro.tempsens =record.a; + break; + case Altos.AO_LOG_BARO_CRC: + baro.crc =record.a; + break; + } + state.seen |= eeprom.seen; + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedMegaRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = Altos.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedMegaRecord record = iterator.next(); + switch (record.cmd) { + case Altos.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case Altos.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case Altos.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case Altos.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case Altos.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case Altos.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case Altos.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case Altos.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.a); + break; + case Altos.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case Altos.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case Altos.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case Altos.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + case Altos.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.a); + break; + } + } + } + + /* + * 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(AltosOrderedMegaRecord good, AltosOrderedMegaRecord 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; + + /* Make sure this looks like a good GPS value */ + if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); + flags |= Altos.AO_GPS_RUNNING; + flags |= Altos.AO_GPS_VALID; + + 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromMegaIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedMegaRecord last_gps_time = null; + + baro = new AltosMs5607(); + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedMegaRecord record = new AltosOrderedMegaRecord(line, index++, prev_tick, prev_tick_valid); + if (record == null) + break; + if (record.cmd == Altos.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == Altos.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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) { + gps_date_record = record; + continue; + } + + /* 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 iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedMegaRecord 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) { + AltosOrderedMegaRecord add_gps_time = new AltosOrderedMegaRecord(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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == Altos.AO_LOG_STATE && + record.a == Altos.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altosui/AltosIMU.java b/altosui/AltosIMU.java new file mode 100644 index 00000000..1f865a65 --- /dev/null +++ b/altosui/AltosIMU.java @@ -0,0 +1,29 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 AltosIMU { + int accel_x; + int accel_y; + int accel_z; + + int gyro_x; + int gyro_y; + int gyro_z; +} + \ No newline at end of file diff --git a/altosui/AltosMag.java b/altosui/AltosMag.java new file mode 100644 index 00000000..b3fc542b --- /dev/null +++ b/altosui/AltosMag.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 AltosMag { + int x; + int y; + int z; +} + \ No newline at end of file diff --git a/altosui/AltosMs5607.java b/altosui/AltosMs5607.java new file mode 100644 index 00000000..6f8bdbbe --- /dev/null +++ b/altosui/AltosMs5607.java @@ -0,0 +1,76 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 AltosMs5607 { + int reserved; + int sens; + int off; + int tcs; + int tco; + int tref; + int tempsens; + int crc; + + int raw_pres; + int raw_temp; + public int pa; + public int cc; + + void convert() { + int dT; + int TEMP; + long OFF; + long SENS; + int P; + + dT = raw_temp - ((int) tref << 8); + + TEMP = (int) (2000 + (((long) dT * tempsens) >> 23)); + + OFF = ((long) off << 17) + (((long) tco * dT) >> 6); + + SENS = ((long) sens << 16) + (((long) tcs * dT) >> 7); + + if (TEMP < 2000) { + int T2 = (int) (((long) dT * (long) dT) >> 31); + int TEMPM = TEMP - 2000; + long OFF2 = (61 * (long) TEMPM * (long) TEMPM) >> 4; + long SENS2 = 2 * (long) TEMPM * (long) TEMPM; + if (TEMP < 1500) { + int TEMPP = TEMP + 1500; + long TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; + } + + pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); + cc = TEMP; + } + + public int set(int in_pres, int in_temp) { + raw_pres = in_pres; + raw_temp = in_temp; + convert(); + return pa; + } +} diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 4dfa98be..4643d69a 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -67,6 +67,9 @@ public class AltosRecord implements Comparable { AltosGPS gps; boolean new_gps; + AltosIMU imu; + AltosMag mag; + double time; /* seconds since boost */ int device_type; @@ -277,6 +280,8 @@ public class AltosRecord implements Comparable { gps = new AltosGPS(old.gps); new_gps = false; companion = old.companion; + imu = old.imu; + mag = old.mag; } public AltosRecord() { diff --git a/altosui/AltosState.java b/altosui/AltosState.java index da498bc1..9c6f85eb 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -54,6 +54,9 @@ public class AltosState { AltosGPS gps; + AltosIMU imu; + AltosMag mag; + double pad_lat; double pad_lon; double pad_alt; @@ -107,6 +110,8 @@ public class AltosState { max_acceleration = prev_state.max_acceleration; max_speed = prev_state.max_speed; max_baro_speed = prev_state.max_baro_speed; + imu = prev_state.imu; + mag = prev_state.mag; /* make sure the clock is monotonic */ while (tick < prev_state.tick) diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 6993abab..7d4b2edb 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -365,6 +365,8 @@ public class AltosUI extends AltosFrame { in = new FileInputStream(file); if (filename.endsWith("eeprom")) return new AltosEepromIterable(in); + else if (filename.endsWith("mega")) + return new AltosEepromMegaIterable(in); else return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index d436c6a0..16b57d40 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -48,6 +48,11 @@ altosui_JAVA = \ AltosEepromIterable.java \ AltosEepromRecord.java \ AltosEepromTeleScience.java \ + AltosEepromMega.java \ + AltosEepromMegaIterable.java \ + AltosMs5607.java \ + AltosIMU.java \ + AltosMag.java \ AltosEepromSelect.java \ AltosFile.java \ AltosFlash.java \ -- cgit v1.2.3 From c04af7533bd3fd3f3260338c0753fde966131720 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 23:07:38 -0700 Subject: altos: Add support for MegaAccel daughter card. Switches all acceleration computation to using the MegaAccel accelerometer to ensure support for high-g flights. MPU6000 values continue to be logged as normal Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 1 + src/core/ao_data.h | 7 ++----- src/megametrum-v0.1/ao_pins.h | 28 ++++++++++++++++++++++++---- src/stm/ao_adc_stm.c | 25 +++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 95643956..ce827e25 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -56,7 +56,7 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel_ref); sequence = 0; } else #endif diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 704ae4f9..44116b81 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,6 +205,7 @@ struct ao_adc { int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ + int16_t accel_ref; /* acceleration reference */ }; #define AO_DATA_RING 32 diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bb26c4c0..83f8df59 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -31,9 +31,6 @@ struct ao_data { #if HAS_ADC struct ao_adc adc; #endif -#if HAS_ACCEL_REF - uint16_t accel_ref; -#endif #if HAS_MS5607 struct ao_ms5607_sample ms5607; #endif @@ -82,7 +79,7 @@ typedef int16_t alt_t; * ao_data_accel_invert - flip rocket ends for positive acceleration */ -#if HAS_MPU6000 +#if HAS_MPU6000 && !HAS_HIGHG_ACCEL typedef int16_t accel_t; @@ -181,7 +178,7 @@ typedef int16_t accel_t; */ #if HAS_ACCEL_REF #define ao_data_accel_sample(packet) \ - ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) #else #define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index ff0edaa9..75b22045 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -98,6 +98,7 @@ #define HAS_FLIGHT 1 #define HAS_ADC 1 #define HAS_ACCEL 1 +#define HAS_ACCEL_REF 1 #define HAS_LOG 1 #define AO_DATA_RING 32 @@ -107,6 +108,8 @@ struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; + int16_t accel_ref; + int16_t accel; int16_t temp; }; @@ -142,13 +145,22 @@ struct ao_adc { #define AO_ADC_V_PBATT_PORT stm_gpiob #define AO_ADC_V_PBATT_PIN 1 +#define AO_ADC_ACCEL_REF 10 +#define AO_ADC_ACCEL_REF_PORT stm_gpioc +#define AO_ADC_ACCEL_REF_PIN 0 + +#define AO_ADC_ACCEL 11 +#define AO_ADC_ACCEL_PORT stm_gpioc +#define AO_ADC_ACCEL_PIN 1 + #define AO_ADC_TEMP 16 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN)) + (1 << STM_RCC_AHBENR_GPIOBEN) | \ + (1 << STM_RCC_AHBENR_GPIOCEN)) -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) #define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT #define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN @@ -166,8 +178,12 @@ struct ao_adc { #define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN #define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT #define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN +#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT +#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN +#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT +#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) #define AO_ADC_SQ1 AO_ADC_SENSE_A #define AO_ADC_SQ2 AO_ADC_SENSE_B @@ -177,7 +193,9 @@ struct ao_adc { #define AO_ADC_SQ6 AO_ADC_SENSE_F #define AO_ADC_SQ7 AO_ADC_V_BATT #define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_TEMP +#define AO_ADC_SQ9 AO_ADC_ACCEL_REF +#define AO_ADC_SQ10 AO_ADC_ACCEL +#define AO_ADC_SQ11 AO_ADC_TEMP /* * Pressure sensor settings @@ -230,4 +248,6 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) +#define HAS_HIGHG_ACCEL 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index ea9e25e4..24a1fdd0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -82,7 +82,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_data_ring[ao_data_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].adc), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -180,6 +180,15 @@ ao_adc_init(void) #ifdef AO_ADC_PIN9_PORT stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); #endif +#ifdef AO_ADC_PIN10_PORT + stm_moder_set(&AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN11_PORT + stm_moder_set(&AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN12_PORT + stm_moder_set(&AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); +#endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); @@ -240,7 +249,19 @@ ao_adc_init(void) #if AO_NUM_ADC > 8 stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); #endif - +#if AO_NUM_ADC > 9 + stm_adc.sqr4 |= (AO_ADC_SQ10 << 15); +#endif +#if AO_NUM_ADC > 10 + stm_adc.sqr4 |= (AO_ADC_SQ11 << 20); +#endif +#if AO_NUM_ADC > 11 + stm_adc.sqr4 |= (AO_ADC_SQ12 << 25); +#endif +#if AO_NUM_ADC > 12 +#error "need to finish stm_adc.sqr settings" +#endif + /* Turn ADC on */ stm_adc.cr2 = AO_ADC_CR2_VAL; -- cgit v1.2.3 From 1353b277f8314fbddef81c743bd6ea229364fd18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 14:58:00 -0700 Subject: altos: Enable some debugging during flight mode on MM Until we've got the radio working, there's no way to see inside the MM state without using USB. Add a diagnostic command to dump out the internal flight state variables. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 27087e55..e812016e 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -108,7 +108,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ @@ -352,11 +352,59 @@ ao_flight(void) } } +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + static __xdata struct ao_task flight_task; void ao_flight_init(void) { ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif ao_add_task(&flight_task, ao_flight, "flight"); } -- cgit v1.2.3 From 8d425ffba84ec6f632e8c0d44105de73242a86a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:53:46 -0700 Subject: altos: Route correct GPIO line to interrupt controller Which GPIO a particular pin interrupt comes from is selected by the SYSCFG EXTICR registers; set these when an exti interrupt is configured. Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 6 +++++- src/stm/stm32l.h | 33 +++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 013d453b..2108e8b5 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -51,8 +51,12 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; - + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + stm_exticr_set(gpio, pin); + /* configure pin as input, setting selected pull-up/down mode */ stm_moder_set(gpio, pin, STM_MODER_INPUT); switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 0bc7483e..cb66df6c 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -855,10 +855,7 @@ isr(tim7) struct stm_syscfg { vuint32_t memrmp; vuint32_t pmc; - vuint32_t exticr1; - vuint32_t exticr2; - vuint32_t exticr3; - vuint32_t exticr4; + vuint32_t exticr[4]; }; extern struct stm_syscfg stm_syscfg; @@ -871,6 +868,34 @@ extern struct stm_syscfg stm_syscfg; #define STM_SYSCFG_PMC_USB_PU 0 +#define STM_SYSCFG_EXTICR_PA 0 +#define STM_SYSCFG_EXTICR_PB 1 +#define STM_SYSCFG_EXTICR_PC 2 +#define STM_SYSCFG_EXTICR_PD 3 +#define STM_SYSCFG_EXTICR_PE 4 +#define STM_SYSCFG_EXTICR_PH 5 + +static inline void +stm_exticr_set(struct stm_gpio *gpio, int pin) { + uint8_t reg = pin >> 2; + uint8_t shift = (pin & 3) << 2; + uint8_t val = 0; + + if (gpio == &stm_gpioa) + val = STM_SYSCFG_EXTICR_PA; + else if (gpio == &stm_gpiob) + val = STM_SYSCFG_EXTICR_PB; + else if (gpio == &stm_gpioc) + val = STM_SYSCFG_EXTICR_PC; + else if (gpio == &stm_gpiod) + val = STM_SYSCFG_EXTICR_PD; + else if (gpio == &stm_gpioe) + val = STM_SYSCFG_EXTICR_PE; + + stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift; +} + + struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; -- cgit v1.2.3 From 64e2e66a5239541b15f43172655cfb3560bec79b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:54:42 -0700 Subject: altos: Fix broken EXTI edge mode selections. Clear pending exti on enable Make sure the edge mode registers are set according to the requested mode. Clear any pending interrupt when enabling to avoid spurious isr call Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 2108e8b5..0fa24188 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -75,11 +75,14 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback /* Set interrupt mask and rising/falling mode */ stm_exti.imr &= ~mask; - stm_exti.rtsr |= mask; if (mode & AO_EXTI_MODE_RISING) stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; if (mode & AO_EXTI_MODE_FALLING) stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; if (pin <= 4) irq = STM_ISR_EXTI0_POS + pin; @@ -93,12 +96,16 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + stm_exti.pr = mask; stm_exti.imr |= (1 << pin); } void ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { - stm_exti.imr &= ~(1 << pin); + uint32_t mask = (1 << pin); + stm_exti.imr &= ~mask; + stm_exti.pr = mask; } void -- cgit v1.2.3 From 97317d332f21c42860747c4ecde633bd0228ef52 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:56:41 -0700 Subject: altos: Reset i2c controller at boot time In case it's wedged. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index d82342db..c205706d 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -362,8 +362,12 @@ void ao_i2c_channel_init(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + int i; /* Turn I2C off while configuring */ + stm_i2c->cr1 = (1 << STM_I2C_CR1_SWRST); + for (i = 0; i < 100; i++) + asm("nop"); stm_i2c->cr1 = 0; stm_i2c->cr2 = AO_STM_I2C_CR2; -- cgit v1.2.3 From 69a8907ecbb7ca0e8526aeea0dc7490a191a0f8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:57:22 -0700 Subject: altos: Get HMC5883 driver limping along Not pushing data into the ring yet, but the chip appears to work now. Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 37 +++++++++++++++++++++++++++---------- src/drivers/ao_hmc5883.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 9551df71..f50376c8 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -21,6 +21,8 @@ static uint8_t ao_hmc5883_configured; +static uint8_t ao_hmc5883_addr; + static void ao_hmc5883_reg_write(uint8_t addr, uint8_t data) { @@ -32,17 +34,21 @@ ao_hmc5883_reg_write(uint8_t addr, uint8_t data) ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); ao_i2c_send(d, 2, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr = addr + 1; } static void ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); + if (addr != ao_hmc5883_addr) { + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); + } ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr = 0xff; } static uint8_t ao_hmc5883_done; @@ -51,7 +57,7 @@ static void ao_hmc5883_isr(void) { ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ao_hmc5883_done = 1; + ++ao_hmc5883_done; ao_wakeup(&ao_hmc5883_done); } @@ -65,10 +71,14 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_hmc5883_done = 0; ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + cli(); while (!ao_hmc5883_done) ao_sleep(&ao_hmc5883_done); sei(); + + printf ("done %d\n", ao_hmc5883_done); + ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ @@ -82,21 +92,27 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) static uint8_t ao_hmc5883_setup(void) { + uint8_t d; uint8_t present; if (ao_hmc5883_configured) return 1; - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_HMC5883_INT_PORT); - ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, - AO_EXTI_MODE_FALLING, ao_hmc5883_isr); - ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); + ao_i2c_recv(&d, 1, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (!present) return 0; + + ao_hmc5883_reg_write(HMC5883_CONFIG_A, + (HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) | + (HMC5883_CONFIG_A_DO_15 << HMC5883_CONFIG_A_DO) | + (HMC5883_CONFIG_A_MS_NORMAL << HMC5883_CONFIG_A_MS)); + + ao_hmc5883_reg_write(HMC5883_CONFIG_B, + (HMC5883_CONFIG_B_GN_1_3 << HMC5883_CONFIG_B_GN)); + ao_hmc5883_configured = 1; return 1; } @@ -132,9 +148,10 @@ ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, - AO_EXTI_MODE_FALLING, + AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); ao_cmd_register(&ao_hmc5883_cmds[0]); diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 2ec27dd9..55690978 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -22,11 +22,48 @@ #define HMC5883_ADDR_READ 0x3d #define HMC5883_CONFIG_A 0 + +#define HMC5883_CONFIG_A_MA 5 +#define HMC5883_CONFIG_A_MA_1 0 +#define HMC5883_CONFIG_A_MA_2 1 +#define HMC5883_CONFIG_A_MA_4 2 +#define HMC5883_CONFIG_A_MA_8 3 +#define HMC5883_CONFIG_A_MA_MASK 3 + +#define HMC5883_CONFIG_A_DO 2 +#define HMC5883_CONFIG_A_DO_0_75 0 +#define HMC5883_CONFIG_A_DO_1_5 1 +#define HMC5883_CONFIG_A_DO_3 2 +#define HMC5883_CONFIG_A_DO_7_5 3 +#define HMC5883_CONFIG_A_DO_15 4 +#define HMC5883_CONFIG_A_DO_30 5 +#define HMC5883_CONFIG_A_DO_75 6 +#define HMC5883_CONFIG_A_DO_MASK 7 + +#define HMC5883_CONFIG_A_MS 0 +#define HMC5883_CONFIG_A_MS_NORMAL 0 +#define HMC5883_CONFIG_A_MS_POSITIVE_BIAS 1 +#define HMC5883_CONFIG_A_MS_NEGATIVE_BIAS 2 +#define HMC5883_CONFIG_A_MS_MASK 3 + #define HMC5883_CONFIG_B 1 + +#define HMC5883_CONFIG_B_GN 5 +#define HMC5883_CONFIG_B_GN_0_88 0 +#define HMC5883_CONFIG_B_GN_1_3 1 +#define HMC5883_CONFIG_B_GN_1_9 2 +#define HMC5883_CONFIG_B_GN_2_5 3 +#define HMC5883_CONFIG_B_GN_4_0 4 +#define HMC5883_CONFIG_B_GN_4_7 5 +#define HMC5883_CONFIG_B_GN_5_6 6 +#define HMC5883_CONFIG_B_GN_8_1 7 +#define HMC5883_CONFIG_B_GN_MASK 7 + #define HMC5883_MODE 2 #define HMC5883_MODE_CONTINUOUS 0 #define HMC5883_MODE_SINGLE 1 #define HMC5883_MODE_IDLE 2 + #define HMC5883_X_MSB 3 #define HMC5883_X_LSB 4 #define HMC5883_Y_MSB 5 -- cgit v1.2.3 From 9aa7993ee31bdfd6890ad7262a0375c07464ee76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 17:09:00 -0700 Subject: altos: Intgrate hmc5883 sensor into adc ring Creates a task to poll the mag sensor and place the data into the sensor data ring. Signed-off-by: Keith Packard --- src/core/ao_data.h | 7 +++++++ src/core/ao_log_mega.c | 4 ++++ src/drivers/ao_hmc5883.c | 47 ++++++++++++++++++++++++++----------------- src/drivers/ao_hmc5883.h | 4 ++++ src/megametrum-v0.1/ao_pins.h | 1 + src/stm/ao_adc_stm.c | 5 +++++ 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 83f8df59..502df6c9 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -26,6 +26,10 @@ #include #endif +#if HAS_HMC5883 +#include +#endif + struct ao_data { uint16_t tick; #if HAS_ADC @@ -37,6 +41,9 @@ struct ao_data { #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; #endif +#if HAS_HMC5883 + struct ao_hmc5883_sample hmc5883; +#endif }; #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 404e6bf7..68e2af49 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -120,6 +120,10 @@ ao_log(void) log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; + log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; + log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index f50376c8..1bc914e6 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,6 +19,8 @@ #include #include +uint8_t ao_hmc5883_valid; + static uint8_t ao_hmc5883_configured; static uint8_t ao_hmc5883_addr; @@ -57,7 +59,7 @@ static void ao_hmc5883_isr(void) { ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ++ao_hmc5883_done; + ao_hmc5883_done = 1; ao_wakeup(&ao_hmc5883_done); } @@ -77,8 +79,6 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_sleep(&ao_hmc5883_done); sei(); - printf ("done %d\n", ao_hmc5883_done); - ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ @@ -94,6 +94,7 @@ ao_hmc5883_setup(void) { uint8_t d; uint8_t present; + if (ao_hmc5883_configured) return 1; @@ -103,7 +104,7 @@ ao_hmc5883_setup(void) ao_i2c_put(AO_HMC5883_I2C_INDEX); if (!present) - return 0; + ao_panic(AO_PANIC_SELF_TEST); ao_hmc5883_reg_write(HMC5883_CONFIG_A, (HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) | @@ -117,24 +118,32 @@ ao_hmc5883_setup(void) return 1; } +struct ao_hmc5883_sample ao_hmc5883_current; + +static void +ao_hmc5883(void) +{ + ao_hmc5883_setup(); + for (;;) { + struct ao_hmc5883_sample ao_hmc5883_next; + + ao_hmc5883_sample(&ao_hmc5883_next); + ao_arch_critical( + ao_hmc5883_current = ao_hmc5883_next; + ao_hmc5883_valid = 1; + ); + ao_delay(0); + } +} + +static struct ao_task ao_hmc5883_task; + static void ao_hmc5883_show(void) { - uint8_t addr, data; - struct ao_hmc5883_sample sample; + struct ao_hmc5883_sample sample; - if (!ao_hmc5883_setup()) { - printf("hmc5883 not present\n"); - return; - } -#if 0 - for (addr = 0; addr <= 12; addr++) { - ao_hmc5883_read(addr, &data, 1); - printf ("hmc5883 register %2d: %02x\n", - addr, data); - } -#endif - ao_hmc5883_sample(&sample); + sample = ao_hmc5883_current; printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); } @@ -147,6 +156,7 @@ void ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(&AO_HMC5883_INT_PORT, @@ -154,5 +164,6 @@ ao_hmc5883_init(void) AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); + ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883"); ao_cmd_register(&ao_hmc5883_cmds[0]); } diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 55690978..8d726510 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,10 +75,14 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 +extern uint8_t ao_hmc5883_valid; + struct ao_hmc5883_sample { int16_t x, y, z; }; +extern struct ao_hmc5883_sample ao_hmc5883_current; + void ao_hmc5883_init(void); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 75b22045..d6394d9b 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -235,6 +235,7 @@ struct ao_adc { * Mag sensor (hmc5883) */ +#define HAS_HMC5883 1 #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 24a1fdd0..71299de9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -62,6 +62,11 @@ static void ao_adc_done(int index) step = 0; ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; #endif +#if HAS_HMC5883 + if (!ao_hmc5883_valid) + step = 0; + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif if (step) { ao_data_head = ao_data_ring_next(ao_data_head); ao_wakeup((void *) &ao_data_head); -- cgit v1.2.3 From c9e52287751867d9e451146ccde78109609d30d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 19:06:08 -0700 Subject: altosui: Fixed width format for new IMU values. Signed-off-by: Keith Packard --- altosui/AltosCSV.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index b88bedba..db398a61 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -152,7 +152,7 @@ public class AltosCSV implements AltosWriter { imu = new AltosIMU(); if (mag == null) mag = new AltosMag(); - out.printf("%d,%d,%d,%d,%d,%d,%d,%d,%d", + out.printf("%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d", imu.accel_x, imu.accel_y, imu.accel_z, imu.gyro_x, imu.gyro_y, imu.gyro_z, mag.x, mag.y, mag.z); -- cgit v1.2.3 From 97663f922e236f4ee7bd08277ca80d419b5cd10f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 15:45:14 -0800 Subject: altosui: Split out UI-specific preferences Prepare to create library shared with android application. Signed-off-by: Keith Packard --- altosui/AltosBTKnown.java | 6 +- altosui/AltosConfig.java | 2 +- altosui/AltosConfigFreqUI.java | 4 +- altosui/AltosConfigUI.java | 4 +- altosui/AltosConfigureUI.java | 26 +++---- altosui/AltosDataChooser.java | 2 +- altosui/AltosDialog.java | 8 +- altosui/AltosFile.java | 2 +- altosui/AltosFlashUI.java | 4 +- altosui/AltosFlightUI.java | 8 +- altosui/AltosFrame.java | 6 +- altosui/AltosFreqList.java | 4 +- altosui/AltosIdleMonitorUI.java | 8 +- altosui/AltosLaunchUI.java | 8 +- altosui/AltosPreferences.java | 127 +----------------------------- altosui/AltosScanUI.java | 6 +- altosui/AltosSerial.java | 4 +- altosui/AltosSiteMap.java | 2 +- altosui/AltosTelemetryReader.java | 10 +-- altosui/AltosUI.java | 8 +- altosui/AltosUIPreferences.java | 159 ++++++++++++++++++++++++++++++++++++++ altosui/AltosVoice.java | 2 +- altosui/Makefile.am | 4 +- 23 files changed, 227 insertions(+), 187 deletions(-) create mode 100644 altosui/AltosUIPreferences.java diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java index 95830637..e30be057 100644 --- a/altosui/AltosBTKnown.java +++ b/altosui/AltosBTKnown.java @@ -23,7 +23,7 @@ import java.util.prefs.*; public class AltosBTKnown implements Iterable { LinkedList devices = new LinkedList(); - Preferences bt_pref = AltosPreferences.bt_devices(); + Preferences bt_pref = AltosUIPreferences.bt_devices(); private String get_address(String name) { return bt_pref.get(name, ""); @@ -57,7 +57,7 @@ public class AltosBTKnown implements Iterable { } private void flush() { - AltosPreferences.flush_preferences(); + AltosUIPreferences.flush_preferences(); } public void set(Iterable new_devices) { @@ -91,7 +91,7 @@ public class AltosBTKnown implements Iterable { public AltosBTKnown() { devices = new LinkedList(); - bt_pref = AltosPreferences.bt_devices(); + bt_pref = AltosUIPreferences.bt_devices(); load(); } } \ No newline at end of file diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 58da405f..bd930206 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -299,7 +299,7 @@ public class AltosConfig implements ActionListener { if (remote) { serial_line.stop_remote(); serial_line.set_radio_frequency(frequency); - AltosPreferences.set_frequency(device.getSerial(), frequency); + AltosUIPreferences.set_frequency(device.getSerial(), frequency); serial_line.start_remote(); } serial_line.printf("c c %s\n", callsign.get()); diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index c6eabc53..ecb55449 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -246,7 +246,7 @@ public class AltosConfigFreqUI extends AltosDialog implements ActionListener { FrequencyList frequencies; void save_frequencies() { - AltosPreferences.set_common_frequencies(frequencies.frequencies()); + AltosUIPreferences.set_common_frequencies(frequencies.frequencies()); } JButton add, edit, remove; @@ -411,7 +411,7 @@ public class AltosConfigFreqUI extends AltosDialog implements ActionListener { Frame frame = JOptionPane.getFrameForComponent(frameComp); AltosConfigFreqUI dialog; - dialog = new AltosConfigFreqUI(frame, AltosPreferences.common_frequencies()); + dialog = new AltosConfigFreqUI(frame, AltosUIPreferences.common_frequencies()); dialog.setVisible(true); } diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index b0cd7f27..eddb223f 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -434,7 +434,7 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = ir; c.ipady = 5; - callsign_value = new JTextField(AltosPreferences.callsign()); + callsign_value = new JTextField(AltosUIPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); pane.add(callsign_value, c); callsign_value.setToolTipText("Callsign reported in telemetry data"); @@ -689,7 +689,7 @@ public class AltosConfigUI product_value.getText(), serial_value.getText()); AltosFrequency new_frequency = new AltosFrequency(new_radio_frequency, description); - AltosPreferences.add_common_frequency(new_frequency); + AltosUIPreferences.add_common_frequency(new_frequency); radio_frequency_value.insertItemAt(new_frequency, i); radio_frequency_value.setSelectedIndex(i); } diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 06b5745c..1789cd25 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -105,7 +105,7 @@ public class AltosConfigureUI /* DocumentListener interface methods */ public void changedUpdate(DocumentEvent e) { - AltosPreferences.set_callsign(callsign_value.getText()); + AltosUIPreferences.set_callsign(callsign_value.getText()); } public void insertUpdate(DocumentEvent e) { @@ -158,12 +158,12 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(new JLabel("Voice"), c); - enable_voice = new JRadioButton("Enable", AltosPreferences.voice()); + enable_voice = new JRadioButton("Enable", AltosUIPreferences.voice()); enable_voice.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); boolean enabled = item.isSelected(); - AltosPreferences.set_voice(enabled); + AltosUIPreferences.set_voice(enabled); if (enabled) voice.speak_always("Enable voice."); else @@ -202,11 +202,11 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(new JLabel("Log Directory"), c); - configure_log = new JButton(AltosPreferences.logdir().getPath()); + configure_log = new JButton(AltosUIPreferences.logdir().getPath()); configure_log.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - AltosPreferences.ConfigureLog(); - configure_log.setText(AltosPreferences.logdir().getPath()); + AltosUIPreferences.ConfigureLog(); + configure_log.setText(AltosUIPreferences.logdir().getPath()); } }); c.gridx = 1; @@ -225,7 +225,7 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(new JLabel("Callsign"), c); - callsign_value = new JTextField(AltosPreferences.callsign()); + callsign_value = new JTextField(AltosUIPreferences.callsign()); callsign_value.getDocument().addDocumentListener(this); c.gridx = 1; c.gridy = row++; @@ -244,13 +244,13 @@ public class AltosConfigureUI pane.add(new JLabel("Font size"), c); font_size_value = new JComboBox(font_size_names); - int font_size = AltosPreferences.font_size(); + int font_size = AltosUIPreferences.font_size(); font_size_value.setSelectedIndex(font_size - Altos.font_size_small); font_size_value.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int size = font_size_value.getSelectedIndex() + Altos.font_size_small; - AltosPreferences.set_font_size(size); + AltosUIPreferences.set_font_size(size); } }); c.gridx = 1; @@ -295,7 +295,7 @@ public class AltosConfigureUI DelegatingRenderer.install(look_and_feel_value); - String look_and_feel = AltosPreferences.look_and_feel(); + String look_and_feel = AltosUIPreferences.look_and_feel(); for (int i = 0; i < look_and_feels.length; i++) if (look_and_feel.equals(look_and_feels[i].getClassName())) look_and_feel_value.setSelectedIndex(i); @@ -304,7 +304,7 @@ public class AltosConfigureUI public void actionPerformed(ActionEvent e) { int id = look_and_feel_value.getSelectedIndex(); - AltosPreferences.set_look_and_feel(look_and_feels[id].getClassName()); + AltosUIPreferences.set_look_and_feel(look_and_feels[id].getClassName()); } }); c.gridx = 1; @@ -323,12 +323,12 @@ public class AltosConfigureUI c.anchor = GridBagConstraints.WEST; pane.add(new JLabel("Serial Debug"), c); - serial_debug = new JRadioButton("Enable", AltosPreferences.serial_debug()); + serial_debug = new JRadioButton("Enable", AltosUIPreferences.serial_debug()); serial_debug.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JRadioButton item = (JRadioButton) e.getSource(); boolean enabled = item.isSelected(); - AltosPreferences.set_serial_debug(enabled); + AltosUIPreferences.set_serial_debug(enabled); } }); serial_debug.setToolTipText("Enable/Disable USB I/O getting sent to the console"); diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 488e1068..c4a46d01 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -77,6 +77,6 @@ public class AltosDataChooser extends JFileChooser { setDialogTitle("Select Flight Record File"); setFileFilter(new FileNameExtensionFilter("Flight data file", "telem", "eeprom")); - setCurrentDirectory(AltosPreferences.logdir()); + setCurrentDirectory(AltosUIPreferences.logdir()); } } diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java index c30b5757..1e8e538c 100644 --- a/altosui/AltosDialog.java +++ b/altosui/AltosDialog.java @@ -32,7 +32,7 @@ import libaltosJNI.*; class AltosDialogListener extends WindowAdapter { public void windowClosing (WindowEvent e) { - AltosPreferences.unregister_ui_listener((AltosDialog) e.getWindow()); + AltosUIPreferences.unregister_ui_listener((AltosDialog) e.getWindow()); } } @@ -44,19 +44,19 @@ public class AltosDialog extends JDialog implements AltosUIListener { } public AltosDialog() { - AltosPreferences.register_ui_listener(this); + AltosUIPreferences.register_ui_listener(this); addWindowListener(new AltosDialogListener()); } public AltosDialog(Frame frame, String label, boolean modal) { super(frame, label, modal); - AltosPreferences.register_ui_listener(this); + AltosUIPreferences.register_ui_listener(this); addWindowListener(new AltosDialogListener()); } public AltosDialog(Frame frame, boolean modal) { super(frame, modal); - AltosPreferences.register_ui_listener(this); + AltosUIPreferences.register_ui_listener(this); addWindowListener(new AltosDialogListener()); } } diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java index 2e33b271..e2b6d5a6 100644 --- a/altosui/AltosFile.java +++ b/altosui/AltosFile.java @@ -24,7 +24,7 @@ import java.util.*; class AltosFile extends File { public AltosFile(int year, int month, int day, int serial, int flight, String extension) { - super (AltosPreferences.logdir(), + super (AltosUIPreferences.logdir(), String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", year, month, day, serial, flight, extension)); } diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 704ce35c..f91c542d 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -161,7 +161,7 @@ public class AltosFlashUI boolean select_source_file() { JFileChooser hexfile_chooser = new JFileChooser(); - File firmwaredir = AltosPreferences.firmwaredir(); + File firmwaredir = AltosUIPreferences.firmwaredir(); if (firmwaredir != null) hexfile_chooser.setCurrentDirectory(firmwaredir); @@ -174,7 +174,7 @@ public class AltosFlashUI file = hexfile_chooser.getSelectedFile(); if (file == null) return false; - AltosPreferences.set_firmwaredir(file.getParentFile()); + AltosUIPreferences.set_firmwaredir(file.getParentFile()); return true; } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index b2ae4858..5c6e0629 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -159,7 +159,7 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt ActionListener show_timer; public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) { - AltosPreferences.set_component(this); + AltosUIPreferences.set_component(this); voice = in_voice; reader = in_reader; @@ -178,7 +178,7 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt /* Stick channel selector at top of table for telemetry monitoring */ if (serial >= 0) { // Channel menu - frequencies = new AltosFreqList(AltosPreferences.frequency(serial)); + frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial)); frequencies.set_product("Monitor"); frequencies.set_serial(serial); frequencies.addActionListener(new ActionListener() { @@ -298,7 +298,7 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - AltosPreferences.register_font_listener(this); + AltosUIPreferences.register_font_listener(this); addWindowListener(new WindowAdapter() { @Override @@ -306,7 +306,7 @@ public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, Alt disconnect(); setVisible(false); dispose(); - AltosPreferences.unregister_font_listener(AltosFlightUI.this); + AltosUIPreferences.unregister_font_listener(AltosFlightUI.this); if (exit_on_close) System.exit(0); } diff --git a/altosui/AltosFrame.java b/altosui/AltosFrame.java index f8cc4f52..36ddcae9 100644 --- a/altosui/AltosFrame.java +++ b/altosui/AltosFrame.java @@ -32,7 +32,7 @@ import libaltosJNI.*; class AltosFrameListener extends WindowAdapter { public void windowClosing (WindowEvent e) { - AltosPreferences.unregister_ui_listener((AltosFrame) e.getWindow()); + AltosUIPreferences.unregister_ui_listener((AltosFrame) e.getWindow()); } } @@ -44,13 +44,13 @@ public class AltosFrame extends JFrame implements AltosUIListener { } public AltosFrame() { - AltosPreferences.register_ui_listener(this); + AltosUIPreferences.register_ui_listener(this); addWindowListener(new AltosFrameListener()); } public AltosFrame(String name) { super(name); - AltosPreferences.register_ui_listener(this); + AltosUIPreferences.register_ui_listener(this); addWindowListener(new AltosFrameListener()); } } diff --git a/altosui/AltosFreqList.java b/altosui/AltosFreqList.java index 59b0e127..e4135df7 100644 --- a/altosui/AltosFreqList.java +++ b/altosui/AltosFreqList.java @@ -52,7 +52,7 @@ public class AltosFreqList extends JComboBox { } String description = String.format("%s serial %d", product, serial); AltosFrequency frequency = new AltosFrequency(new_frequency, description); - AltosPreferences.add_common_frequency(frequency); + AltosUIPreferences.add_common_frequency(frequency); insertItemAt(frequency, i); setMaximumRowCount(getItemCount()); } @@ -73,7 +73,7 @@ public class AltosFreqList extends JComboBox { } public AltosFreqList () { - super(AltosPreferences.common_frequencies()); + super(AltosUIPreferences.common_frequencies()); setMaximumRowCount(getItemCount()); setEditable(false); product = "Unknown"; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index d877be4d..8eb0d520 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -342,12 +342,12 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay /* Stick frequency selector at top of table for telemetry monitoring */ if (remote && serial >= 0) { // Frequency menu - frequencies = new AltosFreqList(AltosPreferences.frequency(serial)); + frequencies = new AltosFreqList(AltosUIPreferences.frequency(serial)); frequencies.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { double frequency = frequencies.frequency(); thread.set_frequency(frequency); - AltosPreferences.set_frequency(device.getSerial(), + AltosUIPreferences.set_frequency(device.getSerial(), frequency); } }); @@ -391,7 +391,7 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - AltosPreferences.register_font_listener(this); + AltosUIPreferences.register_font_listener(this); addWindowListener(new WindowAdapter() { @Override @@ -399,7 +399,7 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay disconnect(); setVisible(false); dispose(); - AltosPreferences.unregister_font_listener(AltosIdleMonitorUI.this); + AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this); } }); diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index 73fae16b..a6c36604 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -316,7 +316,7 @@ public class AltosLaunchUI void set_serial() { try { launcher_serial = Integer.parseInt(launcher_serial_text.getText()); - AltosPreferences.set_launcher_serial(launcher_serial); + AltosUIPreferences.set_launcher_serial(launcher_serial); send_command("set_remote"); } catch (NumberFormatException ne) { launcher_serial_text.setText(String.format("%d", launcher_serial)); @@ -326,7 +326,7 @@ public class AltosLaunchUI void set_channel() { try { launcher_channel = Integer.parseInt(launcher_channel_text.getText()); - AltosPreferences.set_launcher_serial(launcher_channel); + AltosUIPreferences.set_launcher_serial(launcher_channel); send_command("set_remote"); } catch (NumberFormatException ne) { launcher_channel_text.setText(String.format("%d", launcher_channel)); @@ -388,8 +388,8 @@ public class AltosLaunchUI public AltosLaunchUI(JFrame in_owner) { - launcher_channel = AltosPreferences.launcher_channel(); - launcher_serial = AltosPreferences.launcher_serial(); + launcher_channel = AltosUIPreferences.launcher_channel(); + launcher_serial = AltosUIPreferences.launcher_serial(); owner = in_owner; armed_status = AltosLaunch.Unknown; igniter_status = AltosLaunch.Unknown; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index cc2b1a95..7510c7c2 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -26,7 +26,7 @@ import javax.swing.*; import javax.swing.filechooser.FileSystemView; class AltosPreferences { - static Preferences preferences; + public static Preferences preferences; /* logdir preference name */ final static String logdirPreference = "LOGDIR"; @@ -55,24 +55,15 @@ class AltosPreferences { /* scanning telemetry preferences name */ final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; - /* font size preferences name */ - final static String fontSizePreference = "FONT-SIZE"; - /* Launcher serial preference name */ final static String launcherSerialPreference = "LAUNCHER-SERIAL"; /* Launcher channel preference name */ final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; - /* Look&Feel preference name */ - final static String lookAndFeelPreference = "LOOK-AND-FEEL"; - /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; - /* UI Component to pop dialogs up */ - static Component component; - /* Log directory */ static File logdir; @@ -100,14 +91,6 @@ class AltosPreferences { /* Scanning telemetry */ static int scanning_telemetry; - static LinkedList font_listeners; - - static int font_size = Altos.font_size_medium; - - static LinkedList ui_listeners; - - static String look_and_feel = null; - /* List of frequencies */ final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; static AltosFrequency[] common_frequencies; @@ -187,11 +170,6 @@ class AltosPreferences { scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << Altos.ao_telemetry_standard)); - font_listeners = new LinkedList(); - - font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); - Altos.set_fonts(font_size); - launcher_serial = preferences.getInt(launcherSerialPreference, 0); launcher_channel = preferences.getInt(launcherChannelPreference, 0); @@ -207,27 +185,22 @@ class AltosPreferences { common_frequencies = load_common_frequencies(); - look_and_feel = preferences.get(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); - - ui_listeners = new LinkedList(); } static { init(); } - static void set_component(Component in_component) { - component = in_component; - } - static void flush_preferences() { try { preferences.flush(); } catch (BackingStoreException ee) { +/* if (component != null) JOptionPane.showMessageDialog(component, preferences.absolutePath(), "Cannot save prefernces", JOptionPane.ERROR_MESSAGE); else +*/ System.err.printf("Cannot save preferences\n"); } } @@ -243,41 +216,6 @@ class AltosPreferences { } } - private static boolean check_dir(File dir) { - if (!dir.exists()) { - if (!dir.mkdirs()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Cannot create directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - } else if (!dir.isDirectory()) { - JOptionPane.showMessageDialog(component, - dir.getName(), - "Is not a directory", - JOptionPane.ERROR_MESSAGE); - return false; - } - return true; - } - - /* Configure the log directory. This is where all telemetry and eeprom files - * will be written to, and where replay will look for telemetry files - */ - public static void ConfigureLog() { - JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); - - logdir_chooser.setDialogTitle("Configure Data Logging Directory"); - logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - - if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { - File dir = logdir_chooser.getSelectedFile(); - if (check_dir(dir)) - set_logdir(dir); - } - } - public static File logdir() { return logdir; } @@ -371,65 +309,6 @@ class AltosPreferences { return firmwaredir; } - public static int font_size() { - return font_size; - } - - static void set_fonts() { - } - - public static void set_font_size(int new_font_size) { - font_size = new_font_size; - synchronized (preferences) { - preferences.putInt(fontSizePreference, font_size); - flush_preferences(); - Altos.set_fonts(font_size); - for (AltosFontListener l : font_listeners) - l.font_size_changed(font_size); - } - } - - public static void register_font_listener(AltosFontListener l) { - synchronized (preferences) { - font_listeners.add(l); - } - } - - public static void unregister_font_listener(AltosFontListener l) { - synchronized (preferences) { - font_listeners.remove(l); - } - } - - public static void set_look_and_feel(String new_look_and_feel) { - look_and_feel = new_look_and_feel; - try { - UIManager.setLookAndFeel(look_and_feel); - } catch (Exception e) { - } - synchronized(preferences) { - preferences.put(lookAndFeelPreference, look_and_feel); - flush_preferences(); - for (AltosUIListener l : ui_listeners) - l.ui_changed(look_and_feel); - } - } - - public static String look_and_feel() { - return look_and_feel; - } - - public static void register_ui_listener(AltosUIListener l) { - synchronized(preferences) { - ui_listeners.add(l); - } - } - - public static void unregister_ui_listener(AltosUIListener l) { - synchronized (preferences) { - ui_listeners.remove(l); - } - } public static void set_serial_debug(boolean new_serial_debug) { serial_debug = new_serial_debug; AltosSerial.set_debug(serial_debug); diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index e188834e..2b9137d8 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -267,7 +267,7 @@ public class AltosScanUI scanning_telemetry |= (1 << Altos.ao_telemetry_standard); telemetry_boxes[Altos.ao_telemetry_standard - Altos.ao_telemetry_min].setSelected(true); } - AltosPreferences.set_scanning_telemetry(scanning_telemetry); + AltosUIPreferences.set_scanning_telemetry(scanning_telemetry); } if (cmd.equals("monitor")) { @@ -359,7 +359,7 @@ public class AltosScanUI owner = in_owner; - frequencies = AltosPreferences.common_frequencies(); + frequencies = AltosUIPreferences.common_frequencies(); frequency_index = 0; telemetry = Altos.ao_telemetry_min; @@ -400,7 +400,7 @@ public class AltosScanUI c.gridy = 2; pane.add(telemetry_label, c); - int scanning_telemetry = AltosPreferences.scanning_telemetry(); + int scanning_telemetry = AltosUIPreferences.scanning_telemetry(); telemetry_boxes = new JCheckBox[Altos.ao_telemetry_max - Altos.ao_telemetry_min + 1]; for (int k = Altos.ao_telemetry_min; k <= Altos.ao_telemetry_max; k++) { int j = k - Altos.ao_telemetry_min; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 77c926b1..afb9f21a 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -438,9 +438,9 @@ public class AltosSerial implements Runnable { if (debug) System.out.printf("start remote %7.3f\n", frequency); if (frequency == 0.0) - frequency = AltosPreferences.frequency(device.getSerial()); + frequency = AltosUIPreferences.frequency(device.getSerial()); set_radio_frequency(frequency); - set_callsign(AltosPreferences.callsign()); + set_callsign(AltosUIPreferences.callsign()); printf("p\nE 0\n"); flush_input(); remote = true; diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index 63995c40..93c54d02 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -250,7 +250,7 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { char chlng = lng < 0 ? 'W' : 'E'; if (lat < 0) lat = -lat; if (lng < 0) lng = -lng; - return new File(AltosPreferences.mapdir(), + return new File(AltosUIPreferences.mapdir(), String.format("map-%c%.6f,%c%.6f-%d.png", chlat, lat, chlng, lng, zoom)); } diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java index 85dc9cbc..dde60dc9 100644 --- a/altosui/AltosTelemetryReader.java +++ b/altosui/AltosTelemetryReader.java @@ -84,7 +84,7 @@ class AltosTelemetryReader extends AltosFlightReader { } void save_frequency() { - AltosPreferences.set_frequency(device.getSerial(), frequency); + AltosUIPreferences.set_frequency(device.getSerial(), frequency); } void set_telemetry(int in_telemetry) { @@ -93,7 +93,7 @@ class AltosTelemetryReader extends AltosFlightReader { } void save_telemetry() { - AltosPreferences.set_telemetry(device.getSerial(), telemetry); + AltosUIPreferences.set_telemetry(device.getSerial(), telemetry); } File backing_file() { @@ -109,11 +109,11 @@ class AltosTelemetryReader extends AltosFlightReader { previous = null; telem = new LinkedBlockingQueue(); - frequency = AltosPreferences.frequency(device.getSerial()); + frequency = AltosUIPreferences.frequency(device.getSerial()); set_frequency(frequency); - telemetry = AltosPreferences.telemetry(device.getSerial()); + telemetry = AltosUIPreferences.telemetry(device.getSerial()); set_telemetry(telemetry); - serial.set_callsign(AltosPreferences.callsign()); + serial.set_callsign(AltosUIPreferences.callsign()); serial.add_monitor(telem); } } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 7d4b2edb..a2816a3a 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -108,7 +108,7 @@ public class AltosUI extends AltosFrame { if (imgURL != null) setIconImage(new ImageIcon(imgURL).getImage()); - AltosPreferences.set_component(this); + AltosUIPreferences.set_component(this); pane = getContentPane(); gridbag = new GridBagLayout(); @@ -262,9 +262,9 @@ public class AltosUI extends AltosFrame { String result; result = JOptionPane.showInputDialog(AltosUI.this, "Configure Callsign", - AltosPreferences.callsign()); + AltosUIPreferences.callsign()); if (result != null) - AltosPreferences.set_callsign(result); + AltosUIPreferences.set_callsign(result); } void ConfigureTeleMetrum() { @@ -538,7 +538,7 @@ public class AltosUI extends AltosFrame { public static void main(final String[] args) { try { - UIManager.setLookAndFeel(AltosPreferences.look_and_feel()); + UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel()); } catch (Exception e) { } /* Handle batch-mode */ diff --git a/altosui/AltosUIPreferences.java b/altosui/AltosUIPreferences.java new file mode 100644 index 00000000..da6c3968 --- /dev/null +++ b/altosui/AltosUIPreferences.java @@ -0,0 +1,159 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.awt.Component; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; + +/* import org.altusmetrum.AltosLib.*; */ + +class AltosUIPreferences extends AltosPreferences { + + /* font size preferences name */ + final static String fontSizePreference = "FONT-SIZE"; + + /* Look&Feel preference name */ + final static String lookAndFeelPreference = "LOOK-AND-FEEL"; + + /* UI Component to pop dialogs up */ + static Component component; + + static LinkedList font_listeners; + + static int font_size = Altos.font_size_medium; + + static LinkedList ui_listeners; + + static String look_and_feel = null; + + public static void init() { + font_listeners = new LinkedList(); + + font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); + Altos.set_fonts(font_size); + look_and_feel = preferences.get(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); + + ui_listeners = new LinkedList(); + } + + static { init(); } + + static void set_component(Component in_component) { + component = in_component; + } + + private static boolean check_dir(File dir) { + if (!dir.exists()) { + if (!dir.mkdirs()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Cannot create directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + } else if (!dir.isDirectory()) { + JOptionPane.showMessageDialog(component, + dir.getName(), + "Is not a directory", + JOptionPane.ERROR_MESSAGE); + return false; + } + return true; + } + + /* Configure the log directory. This is where all telemetry and eeprom files + * will be written to, and where replay will look for telemetry files + */ + public static void ConfigureLog() { + JFileChooser logdir_chooser = new JFileChooser(logdir.getParentFile()); + + logdir_chooser.setDialogTitle("Configure Data Logging Directory"); + logdir_chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + if (logdir_chooser.showDialog(component, "Select Directory") == JFileChooser.APPROVE_OPTION) { + File dir = logdir_chooser.getSelectedFile(); + if (check_dir(dir)) + set_logdir(dir); + } + } + public static int font_size() { + return font_size; + } + + static void set_fonts() { + } + + public static void set_font_size(int new_font_size) { + font_size = new_font_size; + synchronized (preferences) { + preferences.putInt(fontSizePreference, font_size); + flush_preferences(); + Altos.set_fonts(font_size); + for (AltosFontListener l : font_listeners) + l.font_size_changed(font_size); + } + } + + public static void register_font_listener(AltosFontListener l) { + synchronized (preferences) { + font_listeners.add(l); + } + } + + public static void unregister_font_listener(AltosFontListener l) { + synchronized (preferences) { + font_listeners.remove(l); + } + } + + public static void set_look_and_feel(String new_look_and_feel) { + look_and_feel = new_look_and_feel; + try { + UIManager.setLookAndFeel(look_and_feel); + } catch (Exception e) { + } + synchronized(preferences) { + preferences.put(lookAndFeelPreference, look_and_feel); + flush_preferences(); + for (AltosUIListener l : ui_listeners) + l.ui_changed(look_and_feel); + } + } + + public static String look_and_feel() { + return look_and_feel; + } + + public static void register_ui_listener(AltosUIListener l) { + synchronized(preferences) { + ui_listeners.add(l); + } + } + + public static void unregister_ui_listener(AltosUIListener l) { + synchronized (preferences) { + ui_listeners.remove(l); + } + } +} \ No newline at end of file diff --git a/altosui/AltosVoice.java b/altosui/AltosVoice.java index ac13ee14..ab74e0b3 100644 --- a/altosui/AltosVoice.java +++ b/altosui/AltosVoice.java @@ -65,7 +65,7 @@ public class AltosVoice implements Runnable { } public void speak(String s) { - if (AltosPreferences.voice()) + if (AltosUIPreferences.voice()) speak_always(s); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 16b57d40..c3fd6bb6 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=libaltos +SUBDIRS=libaltos altoslib JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation @@ -87,7 +87,9 @@ altosui_JAVA = \ AltosLog.java \ AltosPad.java \ AltosParse.java \ + AltosUIPreferences.java \ AltosPreferences.java \ + AltosUIPreferences.java \ AltosReader.java \ AltosRecord.java \ AltosRecordCompanion.java \ -- cgit v1.2.3 From 6510e8495fc5e8057b6092963def4d78978625a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 16:09:29 -0800 Subject: altosui: Split out lots of the altosui code to a shared library To be shared with the Android application eventually Signed-off-by: Keith Packard --- altosui/Altos.java | 18 +- altosui/AltosCRCException.java | 26 - altosui/AltosConvert.java | 259 ---------- altosui/AltosFontListener.java | 22 - altosui/AltosFrequency.java | 57 --- altosui/AltosGPS.java | 248 ---------- altosui/AltosGPSSat.java | 32 -- altosui/AltosLine.java | 30 -- altosui/AltosParse.java | 79 ---- altosui/AltosRecord.java | 317 ------------- altosui/AltosRecordCompanion.java | 38 -- altosui/AltosRecordIterable.java | 37 -- altosui/AltosTelemetry.java | 241 ---------- altosui/AltosTelemetryIterable.java | 109 ----- altosui/AltosTelemetryMap.java | 63 --- altosui/AltosTelemetryReader.java | 119 ----- altosui/AltosTelemetryRecord.java | 128 ----- altosui/AltosTelemetryRecordCompanion.java | 52 -- altosui/AltosTelemetryRecordConfiguration.java | 64 --- altosui/AltosTelemetryRecordLegacy.java | 521 --------------------- altosui/AltosTelemetryRecordLocation.java | 93 ---- altosui/AltosTelemetryRecordRaw.java | 77 --- altosui/AltosTelemetryRecordSatellite.java | 52 -- altosui/AltosTelemetryRecordSensor.java | 104 ---- altosui/altoslib/Makefile.am | 56 +++ .../altusmetrum/AltosLib/AltosCRCException.java | 26 + .../src/org/altusmetrum/AltosLib/AltosConvert.java | 259 ++++++++++ .../altusmetrum/AltosLib/AltosFontListener.java | 22 + .../org/altusmetrum/AltosLib/AltosFrequency.java | 57 +++ .../src/org/altusmetrum/AltosLib/AltosGPS.java | 248 ++++++++++ .../src/org/altusmetrum/AltosLib/AltosGPSSat.java | 32 ++ .../src/org/altusmetrum/AltosLib/AltosLine.java | 30 ++ .../src/org/altusmetrum/AltosLib/AltosParse.java | 79 ++++ .../src/org/altusmetrum/AltosLib/AltosRecord.java | 317 +++++++++++++ .../altusmetrum/AltosLib/AltosRecordCompanion.java | 38 ++ .../altusmetrum/AltosLib/AltosRecordIterable.java | 37 ++ .../org/altusmetrum/AltosLib/AltosTelemetry.java | 241 ++++++++++ .../AltosLib/AltosTelemetryIterable.java | 109 +++++ .../altusmetrum/AltosLib/AltosTelemetryMap.java | 63 +++ .../altusmetrum/AltosLib/AltosTelemetryReader.java | 119 +++++ .../altusmetrum/AltosLib/AltosTelemetryRecord.java | 128 +++++ .../AltosLib/AltosTelemetryRecordCompanion.java | 52 ++ .../AltosTelemetryRecordConfiguration.java | 64 +++ .../AltosLib/AltosTelemetryRecordGeneral.java | 43 ++ .../AltosLib/AltosTelemetryRecordLegacy.java | 521 +++++++++++++++++++++ .../AltosLib/AltosTelemetryRecordLocation.java | 93 ++++ .../AltosLib/AltosTelemetryRecordRaw.java | 77 +++ .../AltosLib/AltosTelemetryRecordSatellite.java | 52 ++ .../AltosLib/AltosTelemetryRecordSensor.java | 104 ++++ configure.ac | 1 + 50 files changed, 2871 insertions(+), 2783 deletions(-) delete mode 100644 altosui/AltosCRCException.java delete mode 100644 altosui/AltosConvert.java delete mode 100644 altosui/AltosFontListener.java delete mode 100644 altosui/AltosFrequency.java delete mode 100644 altosui/AltosGPS.java delete mode 100644 altosui/AltosGPSSat.java delete mode 100644 altosui/AltosLine.java delete mode 100644 altosui/AltosParse.java delete mode 100644 altosui/AltosRecord.java delete mode 100644 altosui/AltosRecordCompanion.java delete mode 100644 altosui/AltosRecordIterable.java delete mode 100644 altosui/AltosTelemetry.java delete mode 100644 altosui/AltosTelemetryIterable.java delete mode 100644 altosui/AltosTelemetryMap.java delete mode 100644 altosui/AltosTelemetryReader.java delete mode 100644 altosui/AltosTelemetryRecord.java delete mode 100644 altosui/AltosTelemetryRecordCompanion.java delete mode 100644 altosui/AltosTelemetryRecordConfiguration.java delete mode 100644 altosui/AltosTelemetryRecordLegacy.java delete mode 100644 altosui/AltosTelemetryRecordLocation.java delete mode 100644 altosui/AltosTelemetryRecordRaw.java delete mode 100644 altosui/AltosTelemetryRecordSatellite.java delete mode 100644 altosui/AltosTelemetryRecordSensor.java create mode 100644 altosui/altoslib/Makefile.am create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 1d393dbe..3e2a7a40 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -24,20 +24,9 @@ import java.nio.charset.Charset; import libaltosJNI.*; -public class Altos { - /* EEProm command letters */ - static final int AO_LOG_FLIGHT = 'F'; - static final int AO_LOG_SENSOR = 'A'; - static final int AO_LOG_TEMP_VOLT = 'T'; - static final int AO_LOG_DEPLOY = 'D'; - static final int AO_LOG_STATE = 'S'; - static final int AO_LOG_GPS_TIME = 'G'; - static final int AO_LOG_GPS_LAT = 'N'; - static final int AO_LOG_GPS_LON = 'W'; - static final int AO_LOG_GPS_ALT = 'H'; - static final int AO_LOG_GPS_SAT = 'V'; - static final int AO_LOG_GPS_DATE = 'Y'; - static final int AO_LOG_PRESSURE = 'P'; +import org.altusmetrum.AltosLib.*; + +public class Altos extends AltosLib { /* Added for header fields in eeprom files */ static final int AO_LOG_CONFIG_VERSION = 1000; @@ -107,7 +96,6 @@ public class Altos { static boolean map_initialized = false; static final int tab_elt_pad = 5; - static Font label_font; static Font value_font; static Font status_font; diff --git a/altosui/AltosCRCException.java b/altosui/AltosCRCException.java deleted file mode 100644 index 4a529bcf..00000000 --- a/altosui/AltosCRCException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - } -} diff --git a/altosui/AltosConvert.java b/altosui/AltosConvert.java deleted file mode 100644 index df41a522..00000000 --- a/altosui/AltosConvert.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Sensor data conversion functions - */ -package altosui; - -public class AltosConvert { - /* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ - return 0; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted altitude */ - for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - base_pressure *= Math.pow(base, exponent); - } - base_temperature += delta_z * lapse_rate[layer_number]; - } - - /* calculate the pressure at the inputted altitude */ - delta_z = altitude - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - pressure = base_pressure * Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - pressure = base_pressure * Math.pow(base, exponent); - } - - return pressure; - } - - -/* outputs the altitude associated with the given pressure. the altitude - returned is measured with respect to the mean sea level */ - static double - pressure_to_altitude(double pressure) - { - - double next_base_temperature = LAYER0_BASE_TEMPERATURE; - double next_base_pressure = LAYER0_BASE_PRESSURE; - - double altitude; - double base_pressure; - double base_temperature; - double base; /* base for function to determine base pressure of next layer */ - double exponent; /* exponent for function to determine base pressure - of next layer */ - double coefficient; - int layer_number; /* identifies layer in the atmosphere */ - int delta_z; /* difference between two altitudes */ - - if (pressure < 0) /* illegal pressure */ - return -1; - if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ - return MAXIMUM_ALTITUDE; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted pressure. */ - layer_number = -1; - do { - layer_number++; - base_pressure = next_base_pressure; - base_temperature = next_base_temperature; - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - next_base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - next_base_pressure *= Math.pow(base, exponent); - } - next_base_temperature += delta_z * lapse_rate[layer_number]; - } - while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); - - /* calculate the altitude associated with the inputted pressure */ - if (lapse_rate[layer_number] == 0.0) { - coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) - * base_temperature; - altitude = base_altitude[layer_number] - + coefficient * Math.log(pressure / base_pressure); - } - else { - base = pressure / base_pressure; - exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] - / GRAVITATIONAL_ACCELERATION; - coefficient = base_temperature / lapse_rate[layer_number]; - altitude = base_altitude[layer_number] - + coefficient * (Math.pow(base, exponent) - 1); - } - - return altitude; - } - - static double - cc_battery_to_voltage(double battery) - { - return battery / 32767.0 * 5.0; - } - - static double - cc_ignitor_to_voltage(double ignite) - { - return ignite / 32767 * 15.0; - } - - static double radio_to_frequency(int freq, int setting, int cal, int channel) { - double f; - - if (freq > 0) - f = freq / 1000.0; - else { - if (setting <= 0) - setting = cal; - f = 434.550 * setting / cal; - /* Round to nearest 50KHz */ - f = Math.floor (20.0 * f + 0.5) / 20.0; - } - return f + channel * 0.100; - } - - static int radio_frequency_to_setting(double frequency, int cal) { - double set = frequency / 434.550 * cal; - - return (int) Math.floor (set + 0.5); - } - - static int radio_frequency_to_channel(double frequency) { - int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); - - if (channel < 0) - channel = 0; - if (channel > 9) - channel = 9; - return channel; - } - - static double radio_channel_to_frequency(int channel) { - return 434.550 + channel * 0.100; - } - - static int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - static double meters_to_feet(double meters) { - return meters * (100 / (2.54 * 12)); - } - - static double meters_to_mach(double meters) { - return meters / 343; /* something close to mach at usual rocket sites */ - } - - static double meters_to_g(double meters) { - return meters / 9.80665; - } - - static int checksum(int[] data, int start, int length) { - int csum = 0x5a; - for (int i = 0; i < length; i++) - csum += data[i + start]; - return csum & 0xff; - } -} diff --git a/altosui/AltosFontListener.java b/altosui/AltosFontListener.java deleted file mode 100644 index 0dda0f29..00000000 --- a/altosui/AltosFontListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 interface AltosFontListener { - void font_size_changed(int font_size); -} diff --git a/altosui/AltosFrequency.java b/altosui/AltosFrequency.java deleted file mode 100644 index b748e460..00000000 --- a/altosui/AltosFrequency.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 javax.swing.plaf.basic.*; -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; - -public class AltosFrequency { - double frequency; - String description; - - public String toString() { - return String.format("%7.3f MHz %-20s", - frequency, description); - } - - public String toShortString() { - return String.format("%7.3f MHz %s", - frequency, description); - } - - public boolean close(double f) { - double diff = Math.abs(frequency - f); - - return diff < 0.010; - } - - public AltosFrequency(double f, String d) { - frequency = f; - description = d; - } -} \ No newline at end of file diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java deleted file mode 100644 index b5df7c9a..00000000 --- a/altosui/AltosGPS.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; - -public class AltosGPS { - - final static int MISSING = AltosRecord.MISSING; - - int nsat; - boolean locked; - boolean connected; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - int year; - int month; - int day; - int hour; - int minute; - int second; - - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless */ - double vdop; /* unitless */ - int h_error; /* m */ - int v_error; /* m */ - - AltosGPSSat[] cc_gps_sat; /* tracking data */ - - 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 = AltosParse.parse_int(hms[0]); - minute = AltosParse.parse_int(hms[1]); - second = AltosParse.parse_int(hms[2]); - } - - void ClearGPSTime() { - year = month = day = 0; - hour = minute = second = 0; - } - - public AltosGPS(AltosTelemetryMap map) throws ParseException { - String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, - AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); - - nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); - if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { - connected = true; - locked = true; - lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); - lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); - alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); - year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); - if (year != MISSING) - year += 2000; - month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); - day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); - - hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); - minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); - second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); - - ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, - AltosRecord.MISSING, 1/100.0); - course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, - AltosRecord.MISSING); - hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); - vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); - h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); - v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); - } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { - connected = true; - locked = false; - } else { - connected = false; - locked = false; - } - } - - 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"); - - connected = false; - locked = false; - lat = lon = 0; - alt = 0; - ClearGPSTime(); - if ((words[i]).equals("unlocked")) { - connected = true; - i++; - } else if ((words[i]).equals("not-connected")) { - i++; - } else if (words.length >= 40) { - locked = true; - connected = true; - - 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(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++; - } - 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 AltosGPSSat[tracking_channels]; - for (int chan = 0; chan < tracking_channels; chan++) { - cc_gps_sat[chan] = new 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 AltosGPSSat[0]; - } - - public void set_latitude(int in_lat) { - lat = in_lat / 10.0e7; - } - - public void set_longitude(int in_lon) { - lon = in_lon / 10.0e7; - } - - public void set_time(int hour, int minute, int second) { - hour = hour; - minute = minute; - second = second; - } - - public void set_date(int year, int month, int day) { - year = year; - month = month; - day = day; - } - - public void set_flags(int flags) { - flags = flags; - } - - public void set_altitude(int altitude) { - altitude = altitude; - } - - public void add_sat(int svid, int c_n0) { - if (cc_gps_sat == null) { - cc_gps_sat = new AltosGPSSat[1]; - } else { - AltosGPSSat[] new_gps_sat = new AltosGPSSat[cc_gps_sat.length + 1]; - for (int i = 0; i < cc_gps_sat.length; i++) - new_gps_sat[i] = cc_gps_sat[i]; - cc_gps_sat = new_gps_sat; - } - AltosGPSSat sat = new AltosGPSSat(); - sat.svid = svid; - sat.c_n0 = c_n0; - cc_gps_sat[cc_gps_sat.length - 1] = sat; - } - - public AltosGPS() { - ClearGPSTime(); - cc_gps_sat = null; - } - - public AltosGPS(AltosGPS old) { - nsat = old.nsat; - locked = old.locked; - connected = old.connected; - lat = old.lat; /* degrees (+N -S) */ - lon = old.lon; /* degrees (+E -W) */ - alt = old.alt; /* m */ - year = old.year; - month = old.month; - day = old.day; - hour = old.hour; - minute = old.minute; - second = old.second; - - ground_speed = old.ground_speed; /* m/s */ - course = old.course; /* degrees */ - climb_rate = old.climb_rate; /* m/s */ - hdop = old.hdop; /* unitless? */ - h_error = old.h_error; /* m */ - v_error = old.v_error; /* m */ - - if (old.cc_gps_sat != null) { - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i] = new AltosGPSSat(); - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; - } - } - } -} diff --git a/altosui/AltosGPSSat.java b/altosui/AltosGPSSat.java deleted file mode 100644 index fb125651..00000000 --- a/altosui/AltosGPSSat.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosGPSSat { - int svid; - int c_n0; - - public AltosGPSSat(int s, int c) { - svid = s; - c_n0= c; - } - - public AltosGPSSat() { - } -} - diff --git a/altosui/AltosLine.java b/altosui/AltosLine.java deleted file mode 100644 index 86e9d4c6..00000000 --- a/altosui/AltosLine.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 diff --git a/altosui/AltosParse.java b/altosui/AltosParse.java deleted file mode 100644 index fbfcaaee..00000000 --- a/altosui/AltosParse.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.lang.*; - -public class AltosParse { - static boolean isdigit(char c) { - return '0' <= c && c <= '9'; - } - - static int parse_int(String v) throws ParseException { - try { - 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 Altos.fromhex(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing hex " + v, 0); - } - } - - static double parse_double(String v) throws ParseException { - try { - return Double.parseDouble(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing double " + v, 0); - } - } - - static double parse_coord(String coord) throws ParseException { - String[] dsf = coord.split("\\D+"); - - if (dsf.length != 3) { - throw new ParseException("error parsing coord " + coord, 0); - } - int deg = parse_int(dsf[0]); - int min = parse_int(dsf[1]); - int frac = parse_int(dsf[2]); - - double r = deg + (min + frac / 10000.0) / 60.0; - if (coord.endsWith("S") || coord.endsWith("W")) - r = -r; - return r; - } - - static String strip_suffix(String v, String suffix) { - if (v.endsWith(suffix)) - return v.substring(0, v.length() - suffix.length()); - return v; - } - - static void word(String v, String m) throws ParseException { - if (!v.equals(m)) { - throw new ParseException("error matching '" + v + "' '" + m + "'", 0); - } - } -} diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java deleted file mode 100644 index 4643d69a..00000000 --- a/altosui/AltosRecord.java +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.HashMap; -import java.io.*; - -public class AltosRecord implements Comparable { - final static int MISSING = 0x7fffffff; - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - static final int seen_companion = 128; - int seen; - - int version; - String callsign; - int serial; - int flight; - int rssi; - int status; - int state; - int tick; - - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - - int ground_accel; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - - double acceleration; - double speed; - double height; - - int flight_accel; - int flight_vel; - int flight_pres; - - AltosGPS gps; - boolean new_gps; - - AltosIMU imu; - AltosMag mag; - - double time; /* seconds since boost */ - - int device_type; - int config_major; - int config_minor; - int apogee_delay; - int main_deploy; - int flight_log_max; - String firmware_version; - - AltosRecordCompanion companion; - /* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - - static final double counts_per_kPa = 27 * 2047 / 3300; - static final double counts_at_101_3kPa = 1674.0; - - static double - barometer_to_pressure(double count) - { - return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; - } - - public double raw_pressure() { - if (pres == MISSING) - return MISSING; - return barometer_to_pressure(pres); - } - - public double filtered_pressure() { - if (flight_pres == MISSING) - return MISSING; - return barometer_to_pressure(flight_pres); - } - - public double ground_pressure() { - if (ground_pres == MISSING) - return MISSING; - return barometer_to_pressure(ground_pres); - } - - public double raw_altitude() { - double p = raw_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double ground_altitude() { - double p = ground_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double filtered_altitude() { - if (height != MISSING && ground_pres != MISSING) - return height + ground_altitude(); - - double p = filtered_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double filtered_height() { - if (height != MISSING) - return height; - - double f = filtered_altitude(); - double g = ground_altitude(); - if (f == MISSING || g == MISSING) - return MISSING; - return f - g; - } - - public double raw_height() { - double r = raw_altitude(); - double g = ground_altitude(); - - if (r == MISSING || g == MISSING) - return height; - return r - g; - } - - public double battery_voltage() { - if (batt == MISSING) - return MISSING; - return AltosConvert.cc_battery_to_voltage(batt); - } - - public double main_voltage() { - if (main == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(main); - } - - public double drogue_voltage() { - if (drogue == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(drogue); - } - - /* Value for the CC1111 built-in temperature sensor - * Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - */ - - static double - thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - - public double temperature() { - if (temp == MISSING) - return MISSING; - return thermometer_to_temperature(temp); - } - - double accel_counts_per_mss() { - double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; - - return counts_per_g / 9.80665; - } - - public double acceleration() { - if (acceleration != MISSING) - return acceleration; - - if (ground_accel == MISSING || accel == MISSING) - return MISSING; - return (ground_accel - accel) / accel_counts_per_mss(); - } - - public double accel_speed() { - if (speed != MISSING) - return speed; - if (flight_vel == MISSING) - return MISSING; - return flight_vel / (accel_counts_per_mss() * 100.0); - } - - public String state() { - return Altos.state_name(state); - } - - public static String gets(FileInputStream s) throws IOException { - int c; - String line = ""; - - while ((c = s.read()) != -1) { - if (c == '\r') - continue; - if (c == '\n') { - return line; - } - line = line + (char) c; - } - return null; - } - - public int compareTo(AltosRecord o) { - return tick - o.tick; - } - - public AltosRecord(AltosRecord old) { - version = old.version; - seen = old.seen; - callsign = old.callsign; - serial = old.serial; - flight = old.flight; - rssi = old.rssi; - status = old.status; - state = old.state; - tick = old.tick; - accel = old.accel; - pres = old.pres; - temp = old.temp; - batt = old.batt; - drogue = old.drogue; - main = old.main; - flight_accel = old.flight_accel; - ground_accel = old.ground_accel; - flight_vel = old.flight_vel; - flight_pres = old.flight_pres; - ground_pres = old.ground_pres; - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - acceleration = old.acceleration; - speed = old.speed; - height = old.height; - gps = new AltosGPS(old.gps); - new_gps = false; - companion = old.companion; - imu = old.imu; - mag = old.mag; - } - - public AltosRecord() { - version = 0; - seen = 0; - callsign = "N0CALL"; - serial = 0; - flight = 0; - rssi = 0; - status = 0; - state = Altos.ao_flight_startup; - tick = 0; - accel = MISSING; - pres = MISSING; - temp = MISSING; - batt = MISSING; - drogue = MISSING; - main = MISSING; - flight_accel = 0; - ground_accel = 0; - flight_vel = 0; - flight_pres = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; - acceleration = MISSING; - speed = MISSING; - height = MISSING; - gps = new AltosGPS(); - new_gps = false; - companion = null; - } -} diff --git a/altosui/AltosRecordCompanion.java b/altosui/AltosRecordCompanion.java deleted file mode 100644 index 0a8f9f4b..00000000 --- a/altosui/AltosRecordCompanion.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosRecordCompanion { - final static int board_id_telescience = 0x0a; - final static int MAX_CHANNELS = 12; - - int tick; - int board_id; - int update_period; - int channels; - int[] companion_data; - - public AltosRecordCompanion(int in_channels) { - channels = in_channels; - if (channels < 0) - channels = 0; - if (channels > MAX_CHANNELS) - channels = MAX_CHANNELS; - companion_data = new int[channels]; - } -} diff --git a/altosui/AltosRecordIterable.java b/altosui/AltosRecordIterable.java deleted file mode 100644 index 45843b92..00000000 --- a/altosui/AltosRecordIterable.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -public abstract class AltosRecordIterable implements Iterable { - public abstract Iterator iterator(); - public void write_comments(PrintStream out) { } - public boolean has_accel() { return false; } - public boolean has_gps() { return false; } - public boolean has_ignite() { return false; }; -} diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java deleted file mode 100644 index 0052ef04..00000000 --- a/altosui/AltosTelemetry.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -/* - * Telemetry data contents - */ - - -/* - * The packet format is a simple hex dump of the raw telemetry frame. - * It starts with 'TELEM', then contains hex digits with a checksum as the last - * byte on the line. - * - * Version 4 is a replacement with consistent syntax. Each telemetry line - * contains a sequence of space-separated names and values, the values are - * either integers or strings. The names are all unique. All values are - * optional - * - * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 - * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 - * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 - * - * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 - * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - * - * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports - * in 1/2dB increments while this protocol provides only integers. So, - * the syntax didn't change just the interpretation of the RSSI - * values. - * - * Version 2 of the telemetry data stream is a bit of a mess, with no - * consistent formatting. In particular, the GPS data is formatted for - * viewing instead of parsing. However, the key feature is that every - * telemetry line contains all of the information necessary to - * describe the current rocket state, including the calibration values - * for accelerometer and barometer. - * - * GPS unlocked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ - * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ - * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 - * - * GPS locked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ - * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ - * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ - * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ - * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ - * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 - * - */ - -public class AltosTelemetry extends AltosRecord { - - /* - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - - final static String AO_TELEM_VERSION = "VERSION"; - final static String AO_TELEM_CALL = "c"; - final static String AO_TELEM_SERIAL = "n"; - final static String AO_TELEM_FLIGHT = "f"; - final static String AO_TELEM_RSSI = "r"; - final static String AO_TELEM_STATE = "s"; - final static String AO_TELEM_TICK = "t"; - - /* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - - final static String AO_TELEM_RAW_ACCEL = "r_a"; - final static String AO_TELEM_RAW_BARO = "r_b"; - final static String AO_TELEM_RAW_THERMO = "r_t"; - final static String AO_TELEM_RAW_BATT = "r_v"; - final static String AO_TELEM_RAW_DROGUE = "r_d"; - final static String AO_TELEM_RAW_MAIN = "r_m"; - - /* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - - final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; - final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; - final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; - final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; - - /* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - - final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; - final static String AO_TELEM_KALMAN_SPEED = "k_s"; - final static String AO_TELEM_KALMAN_ACCEL = "k_a"; - - /* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - - final static String AO_TELEM_ADHOC_ACCEL = "a_a"; - final static String AO_TELEM_ADHOC_SPEED = "a_s"; - final static String AO_TELEM_ADHOC_BARO = "a_b"; - - /* - * GPS values - * - * Name Value - * g_s GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - - final static String AO_TELEM_GPS_STATE = "g"; - final static String AO_TELEM_GPS_STATE_LOCKED = "l"; - final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; - final static String AO_TELEM_GPS_STATE_ERROR = "e"; - final static String AO_TELEM_GPS_NUM_SAT = "g_n"; - final static String AO_TELEM_GPS_LATITUDE = "g_ns"; - final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; - final static String AO_TELEM_GPS_ALTITUDE = "g_a"; - final static String AO_TELEM_GPS_YEAR = "g_Y"; - final static String AO_TELEM_GPS_MONTH = "g_M"; - final static String AO_TELEM_GPS_DAY = "g_D"; - final static String AO_TELEM_GPS_HOUR = "g_h"; - final static String AO_TELEM_GPS_MINUTE = "g_m"; - final static String AO_TELEM_GPS_SECOND = "g_s"; - final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; - final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; - final static String AO_TELEM_GPS_COURSE = "g_c"; - final static String AO_TELEM_GPS_HDOP = "g_hd"; - final static String AO_TELEM_GPS_VDOP = "g_vd"; - final static String AO_TELEM_GPS_HERROR = "g_he"; - final static String AO_TELEM_GPS_VERROR = "g_ve"; - - /* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - - final static String AO_TELEM_SAT_NUM = "s_n"; - final static String AO_TELEM_SAT_SVID = "s_v"; - final static String AO_TELEM_SAT_C_N_0 = "s_c"; - - static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { - AltosTelemetryRecord r = AltosTelemetryRecord.parse(line); - - return r.update_state(previous); - } -} diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java deleted file mode 100644 index a1b25332..00000000 --- a/altosui/AltosTelemetryIterable.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; - -public class AltosTelemetryIterable extends AltosRecordIterable { - TreeSet records; - - public Iterator iterator () { - return records.iterator(); - } - - boolean has_gps = false; - boolean has_accel = false; - boolean has_ignite = false; - public boolean has_gps() { return has_gps; } - public boolean has_accel() { return has_accel; } - public boolean has_ignite() { return has_ignite; }; - - public AltosTelemetryIterable (FileInputStream input) { - boolean saw_boost = false; - int current_tick = 0; - int boost_tick = 0; - - AltosRecord previous = null; - records = new TreeSet (); - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) { - break; - } - try { - AltosRecord record = AltosTelemetry.parse(line, previous); - if (record == null) - break; - if (records.isEmpty()) { - current_tick = record.tick; - } else { - int tick = record.tick; - while (tick < current_tick - 0x1000) - tick += 0x10000; - current_tick = tick; - record.tick = current_tick; - } - if (!saw_boost && record.state >= Altos.ao_flight_boost) - { - saw_boost = true; - boost_tick = record.tick; - } - if (record.accel != AltosRecord.MISSING) - has_accel = true; - if (record.gps != null) - has_gps = true; - if (record.main != AltosRecord.MISSING) - has_ignite = true; - if (previous != null && previous.tick != record.tick) - records.add(previous); - previous = record; - } catch (ParseException pe) { - System.out.printf("parse exception %s\n", pe.getMessage()); - } catch (AltosCRCException ce) { - } - } - } catch (IOException io) { - System.out.printf("io exception\n"); - } - - if (previous != null) - records.add(previous); - - /* Adjust all tick counts to match expected eeprom values, - * which starts with a 16-bit tick count 16 samples before boost - */ - - int tick_adjust = (boost_tick - 16) & 0xffff0000; - for (AltosRecord r : this) - r.tick -= tick_adjust; - boost_tick -= tick_adjust; - - /* adjust all tick counts to be relative to boost time */ - for (AltosRecord r : this) - r.time = (r.tick - boost_tick) / 100.0; - - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/altosui/AltosTelemetryMap.java b/altosui/AltosTelemetryMap.java deleted file mode 100644 index d906100f..00000000 --- a/altosui/AltosTelemetryMap.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -public class AltosTelemetryMap extends HashMap { - public boolean has(String key) { - return containsKey(key); - } - - public String get_string(String key) throws ParseException { - if (!has(key)) - throw new ParseException ("missing " + key, 0); - return (String) get(key); - } - - public String get_string(String key, String def) { - if (has(key)) - return get(key); - else - return def; - } - - public int get_int(String key) throws ParseException { - return AltosParse.parse_int(get_string(key)); - } - - public int get_int(String key, int def) throws ParseException { - if (has(key)) - return get_int(key); - else - return def; - } - - public double get_double(String key, double def, double scale) throws ParseException { - if (has(key)) - return get_int(key) * scale; - else - return def; - } - - public AltosTelemetryMap(String[] words, int start) { - for (int i = start; i < words.length - 1; i += 2) - put(words[i], words[i+1]); - } -} diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java deleted file mode 100644 index dde60dc9..00000000 --- a/altosui/AltosTelemetryReader.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.io.*; -import java.util.concurrent.*; - -class AltosTelemetryReader extends AltosFlightReader { - AltosDevice device; - AltosSerial serial; - AltosLog log; - AltosRecord previous; - double frequency; - int telemetry; - - LinkedBlockingQueue telem; - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { - AltosLine l = telem.take(); - if (l.line == null) - throw new IOException("IO error"); - AltosRecord next = AltosTelemetry.parse(l.line, previous); - previous = next; - return next; - } - - void flush() { - telem.clear(); - } - - void close(boolean interrupted) { - serial.remove_monitor(telem); - log.close(); - serial.close(); - } - - public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - serial.set_radio_frequency(frequency); - } - - public boolean supports_telemetry(int telemetry) { - - try { - /* Version 1.0 or later firmware supports all telemetry formats */ - if (serial.config_data().compare_version("1.0") >= 0) - return true; - - /* Version 0.9 firmware only supports 0.9 telemetry */ - if (serial.config_data().compare_version("0.9") >= 0) { - if (telemetry == Altos.ao_telemetry_0_9) - return true; - else - return false; - } - - /* Version 0.8 firmware only supports 0.8 telemetry */ - if (telemetry == Altos.ao_telemetry_0_8) - return true; - else - return false; - } catch (InterruptedException ie) { - return true; - } catch (TimeoutException te) { - return true; - } - } - - void save_frequency() { - AltosUIPreferences.set_frequency(device.getSerial(), frequency); - } - - void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - serial.set_telemetry(telemetry); - } - - void save_telemetry() { - AltosUIPreferences.set_telemetry(device.getSerial(), telemetry); - } - - File backing_file() { - return log.file(); - } - - public AltosTelemetryReader (AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { - device = in_device; - serial = new AltosSerial(device); - log = new AltosLog(serial); - name = device.toShortString(); - previous = null; - - telem = new LinkedBlockingQueue(); - frequency = AltosUIPreferences.frequency(device.getSerial()); - set_frequency(frequency); - telemetry = AltosUIPreferences.telemetry(device.getSerial()); - set_telemetry(telemetry); - serial.set_callsign(AltosUIPreferences.callsign()); - serial.add_monitor(telem); - } -} diff --git a/altosui/AltosTelemetryRecord.java b/altosui/AltosTelemetryRecord.java deleted file mode 100644 index 2e6b5ead..00000000 --- a/altosui/AltosTelemetryRecord.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.text.*; - -public abstract class AltosTelemetryRecord { - - long received_time; - abstract public AltosRecord update_state(AltosRecord previous); - - static boolean cksum(int[] bytes) { - int sum = 0x5a; - for (int i = 1; i < bytes.length - 1; i++) - sum += bytes[i]; - sum &= 0xff; - return sum == bytes[bytes.length - 1]; - } - - final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); - final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); - final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; - - final static int packet_type_TM_sensor = 0x01; - final static int packet_type_Tm_sensor = 0x02; - final static int packet_type_Tn_sensor = 0x03; - final static int packet_type_configuration = 0x04; - final static int packet_type_location = 0x05; - final static int packet_type_satellite = 0x06; - final static int packet_type_companion = 0x07; - - static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - int[] bytes; - try { - bytes = Altos.hexbytes(hex); - } catch (NumberFormatException ne) { - throw new ParseException(ne.getMessage(), 0); - } - - /* one for length, one for checksum */ - if (bytes[0] != bytes.length - 2) - throw new ParseException(String.format("invalid length %d != %d\n", - bytes[0], - bytes.length - 2), 0); - if (!cksum(bytes)) - throw new ParseException(String.format("invalid line \"%s\"", hex), 0); - - int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; - int status = Altos.uint8(bytes, bytes.length - 2); - - if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) - throw new AltosCRCException(rssi); - - /* length, data ..., rssi, status, checksum -- 4 bytes extra */ - switch (bytes.length) { - case Altos.ao_telemetry_standard_len + 4: - int type = Altos.uint8(bytes, 4 + 1); - switch (type) { - case packet_type_TM_sensor: - case packet_type_Tm_sensor: - case packet_type_Tn_sensor: - r = new AltosTelemetryRecordSensor(bytes, rssi); - break; - case packet_type_configuration: - r = new AltosTelemetryRecordConfiguration(bytes); - break; - case packet_type_location: - r = new AltosTelemetryRecordLocation(bytes); - break; - case packet_type_satellite: - r = new AltosTelemetryRecordSatellite(bytes); - break; - case packet_type_companion: - r = new AltosTelemetryRecordCompanion(bytes); - break; - default: - r = new AltosTelemetryRecordRaw(bytes); - break; - } - break; - case Altos.ao_telemetry_0_9_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - case Altos.ao_telemetry_0_8_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - default: - throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); - } - r.received_time = System.currentTimeMillis(); - return r; - } - - public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - String[] word = line.split("\\s+"); - int i =0; - if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(word[i++], "RSSI"); - throw new AltosCRCException(AltosParse.parse_int(word[i++])); - } - - if (word[i].equals("TELEM")) - r = parse_hex(word[i+1]); - else - r = new AltosTelemetryRecordLegacy(line); - return r; - } -} diff --git a/altosui/AltosTelemetryRecordCompanion.java b/altosui/AltosTelemetryRecordCompanion.java deleted file mode 100644 index 52d7f4cf..00000000 --- a/altosui/AltosTelemetryRecordCompanion.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { - - AltosRecordCompanion companion; - - public AltosTelemetryRecordCompanion(int[] in_bytes) { - super(in_bytes); - - int off = 0; - if (uint8(6) == 0) - off = 1; - int channels = uint8(7+off); - - if (off != 0 && channels >= 12) - channels = 11; - - companion = new AltosRecordCompanion(channels); - companion.tick = tick; - companion.board_id = uint8(5); - companion.update_period = uint8(6+off); - for (int i = 0; i < companion.companion_data.length; i++) - companion.companion_data[i] = uint16(8 + off + i * 2); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.companion = companion; - next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; - - companion.tick = tick; - return next; - } -} diff --git a/altosui/AltosTelemetryRecordConfiguration.java b/altosui/AltosTelemetryRecordConfiguration.java deleted file mode 100644 index b029d120..00000000 --- a/altosui/AltosTelemetryRecordConfiguration.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { - int device_type; - int flight; - int config_major; - int config_minor; - int apogee_delay; - int main_deploy; - int flight_log_max; - String callsign; - String version; - - public AltosTelemetryRecordConfiguration(int[] in_bytes) { - super(in_bytes); - - device_type = uint8(5); - flight = uint16(6); - config_major = uint8(8); - config_minor = uint8(9); - apogee_delay = uint16(10); - main_deploy = uint16(12); - flight_log_max = uint16(14); - callsign = string(16, 8); - version = string(24, 8); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.device_type = device_type; - next.flight = flight; - next.config_major = config_major; - next.config_minor = config_minor; - next.apogee_delay = apogee_delay; - next.main_deploy = main_deploy; - next.flight_log_max = flight_log_max; - - next.callsign = callsign; - next.firmware_version = version; - - next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight; - - return next; - } -} diff --git a/altosui/AltosTelemetryRecordLegacy.java b/altosui/AltosTelemetryRecordLegacy.java deleted file mode 100644 index a72ebb0f..00000000 --- a/altosui/AltosTelemetryRecordLegacy.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -/* - * Telemetry data contents - */ - - -/* - * The packet format is a simple hex dump of the raw telemetry frame. - * It starts with 'TELEM', then contains hex digits with a checksum as the last - * byte on the line. - * - * Version 4 is a replacement with consistent syntax. Each telemetry line - * contains a sequence of space-separated names and values, the values are - * either integers or strings. The names are all unique. All values are - * optional - * - * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 - * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 - * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 - * - * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 - * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - * - * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports - * in 1/2dB increments while this protocol provides only integers. So, - * the syntax didn't change just the interpretation of the RSSI - * values. - * - * Version 2 of the telemetry data stream is a bit of a mess, with no - * consistent formatting. In particular, the GPS data is formatted for - * viewing instead of parsing. However, the key feature is that every - * telemetry line contains all of the information necessary to - * describe the current rocket state, including the calibration values - * for accelerometer and barometer. - * - * GPS unlocked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ - * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ - * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 - * - * GPS locked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ - * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ - * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ - * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ - * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ - * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 - * - */ - -public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { - /* - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - - final static String AO_TELEM_VERSION = "VERSION"; - final static String AO_TELEM_CALL = "c"; - final static String AO_TELEM_SERIAL = "n"; - final static String AO_TELEM_FLIGHT = "f"; - final static String AO_TELEM_RSSI = "r"; - final static String AO_TELEM_STATE = "s"; - final static String AO_TELEM_TICK = "t"; - - /* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - - final static String AO_TELEM_RAW_ACCEL = "r_a"; - final static String AO_TELEM_RAW_BARO = "r_b"; - final static String AO_TELEM_RAW_THERMO = "r_t"; - final static String AO_TELEM_RAW_BATT = "r_v"; - final static String AO_TELEM_RAW_DROGUE = "r_d"; - final static String AO_TELEM_RAW_MAIN = "r_m"; - - /* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - - final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; - final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; - final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; - final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; - - /* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - - final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; - final static String AO_TELEM_KALMAN_SPEED = "k_s"; - final static String AO_TELEM_KALMAN_ACCEL = "k_a"; - - /* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - - final static String AO_TELEM_ADHOC_ACCEL = "a_a"; - final static String AO_TELEM_ADHOC_SPEED = "a_s"; - final static String AO_TELEM_ADHOC_BARO = "a_b"; - - /* - * GPS values - * - * Name Value - * g_s GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - - final static String AO_TELEM_GPS_STATE = "g"; - final static String AO_TELEM_GPS_STATE_LOCKED = "l"; - final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; - final static String AO_TELEM_GPS_STATE_ERROR = "e"; - final static String AO_TELEM_GPS_NUM_SAT = "g_n"; - final static String AO_TELEM_GPS_LATITUDE = "g_ns"; - final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; - final static String AO_TELEM_GPS_ALTITUDE = "g_a"; - final static String AO_TELEM_GPS_YEAR = "g_Y"; - final static String AO_TELEM_GPS_MONTH = "g_M"; - final static String AO_TELEM_GPS_DAY = "g_D"; - final static String AO_TELEM_GPS_HOUR = "g_h"; - final static String AO_TELEM_GPS_MINUTE = "g_m"; - final static String AO_TELEM_GPS_SECOND = "g_s"; - final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; - final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; - final static String AO_TELEM_GPS_COURSE = "g_c"; - final static String AO_TELEM_GPS_HDOP = "g_hd"; - final static String AO_TELEM_GPS_VDOP = "g_vd"; - final static String AO_TELEM_GPS_HERROR = "g_he"; - final static String AO_TELEM_GPS_VERROR = "g_ve"; - - /* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - - final static String AO_TELEM_SAT_NUM = "s_n"; - final static String AO_TELEM_SAT_SVID = "s_v"; - final static String AO_TELEM_SAT_C_N_0 = "s_c"; - - AltosRecord record; - - private void parse_v4(String[] words, int i) throws ParseException { - AltosTelemetryMap map = new AltosTelemetryMap(words, i); - - record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); - record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); - record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); - record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); - record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); - record.tick = map.get_int(AO_TELEM_TICK, 0); - - /* raw sensor values */ - record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING); - record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING); - record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING); - record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING); - record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING); - record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING); - - /* sensor calibration information */ - record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING); - record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING); - record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING); - record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); - - /* flight computer values */ - record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); - record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); - record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); - - record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); - record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); - record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING); - - if (map.has(AO_TELEM_GPS_STATE)) { - record.gps = new AltosGPS(map); - record.new_gps = true; - } - else - record.gps = null; - } - - private void parse_legacy(String[] words, int i) throws ParseException { - - AltosParse.word (words[i++], "CALL"); - record.callsign = words[i++]; - - AltosParse.word (words[i++], "SERIAL"); - record.serial = AltosParse.parse_int(words[i++]); - - if (record.version >= 2) { - AltosParse.word (words[i++], "FLIGHT"); - record.flight = AltosParse.parse_int(words[i++]); - } else - record.flight = 0; - - AltosParse.word(words[i++], "RSSI"); - record.rssi = AltosParse.parse_int(words[i++]); - - /* Older telemetry data had mis-computed RSSI value */ - if (record.version <= 2) - record.rssi = (record.rssi + 74) / 2 - 74; - - AltosParse.word(words[i++], "STATUS"); - record.status = AltosParse.parse_hex(words[i++]); - - AltosParse.word(words[i++], "STATE"); - record.state = Altos.state(words[i++]); - - record.tick = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a:"); - record.accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "p:"); - record.pres = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "t:"); - record.temp = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "v:"); - record.batt = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "d:"); - record.drogue = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "m:"); - record.main = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fa:"); - record.flight_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "ga:"); - record.ground_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fv:"); - record.flight_vel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fp:"); - record.flight_pres = AltosParse.parse_int(words[i++]); - - /* Old TeleDongle code with kalman-reporting TeleMetrum code */ - if ((record.flight_vel & 0xffff0000) == 0x80000000) { - record.speed = ((short) record.flight_vel) / 16.0; - record.acceleration = record.flight_accel / 16.0; - record.height = record.flight_pres; - record.flight_vel = AltosRecord.MISSING; - record.flight_pres = AltosRecord.MISSING; - record.flight_accel = AltosRecord.MISSING; - } - - AltosParse.word(words[i++], "gp:"); - record.ground_pres = AltosParse.parse_int(words[i++]); - - if (record.version >= 1) { - AltosParse.word(words[i++], "a+:"); - record.accel_plus_g = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a-:"); - record.accel_minus_g = AltosParse.parse_int(words[i++]); - } else { - record.accel_plus_g = record.ground_accel; - record.accel_minus_g = record.ground_accel + 530; - } - - record.gps = new AltosGPS(words, i, record.version); - record.new_gps = true; - } - - public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; - - record = new AltosRecord(); - - if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(words[i++], "RSSI"); - record.rssi = AltosParse.parse_int(words[i++]); - throw new AltosCRCException(record.rssi); - } - if (words[i].equals("CALL")) { - record.version = 0; - } else { - AltosParse.word (words[i++], "VERSION"); - record.version = AltosParse.parse_int(words[i++]); - } - - if (record.version < 4) - parse_legacy(words, i); - else - parse_v4(words, i); - } - - /* - * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that - */ - - int[] bytes; - int adjust; - - private int int8(int i) { - return Altos.int8(bytes, i + 1 + adjust); - } - private int uint8(int i) { - return Altos.uint8(bytes, i + 1 + adjust); - } - private int int16(int i) { - return Altos.int16(bytes, i + 1 + adjust); - } - private int uint16(int i) { - return Altos.uint16(bytes, i + 1 + adjust); - } - private int uint32(int i) { - return Altos.uint32(bytes, i + 1 + adjust); - } - private String string(int i, int l) { - return Altos.string(bytes, i + 1 + adjust, l); - } - - static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); - static final int AO_GPS_NUM_SAT_SHIFT = (0); - - static final int AO_GPS_VALID = (1 << 4); - static final int AO_GPS_RUNNING = (1 << 5); - static final int AO_GPS_DATE_VALID = (1 << 6); - static final int AO_GPS_COURSE_VALID = (1 << 7); - - public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { - record = new AltosRecord(); - - bytes = in_bytes; - record.version = 4; - adjust = 0; - - if (bytes.length == Altos.ao_telemetry_0_8_len + 4) { - record.serial = uint8(0); - adjust = -1; - } else - record.serial = uint16(0); - - record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy; - - record.callsign = string(62, 8); - record.flight = uint16(2); - record.rssi = in_rssi; - record.status = in_status; - record.state = uint8(4); - record.tick = uint16(21); - record.accel = int16(23); - record.pres = int16(25); - record.temp = int16(27); - record.batt = int16(29); - record.drogue = int16(31); - record.main = int16(33); - - record.ground_accel = int16(7); - record.ground_pres = int16(15); - record.accel_plus_g = int16(17); - record.accel_minus_g = int16(19); - - if (uint16(11) == 0x8000) { - record.acceleration = int16(5); - record.speed = int16(9); - record.height = int16(13); - record.flight_accel = AltosRecord.MISSING; - record.flight_vel = AltosRecord.MISSING; - record.flight_pres = AltosRecord.MISSING; - } else { - record.flight_accel = int16(5); - record.flight_vel = uint32(9); - record.flight_pres = int16(13); - record.acceleration = AltosRecord.MISSING; - record.speed = AltosRecord.MISSING; - record.height = AltosRecord.MISSING; - } - - record.gps = null; - - int gps_flags = uint8(41); - - if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { - record.gps = new AltosGPS(); - record.new_gps = true; - - record.seen |= record.seen_gps_time | record.seen_gps_lat | record.seen_gps_lon; - record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); - record.gps.locked = (gps_flags & AO_GPS_VALID) != 0; - record.gps.connected = true; - record.gps.lat = uint32(42) / 1.0e7; - record.gps.lon = uint32(46) / 1.0e7; - record.gps.alt = int16(50); - record.gps.ground_speed = uint16(52) / 100.0; - record.gps.course = uint8(54) * 2; - record.gps.hdop = uint8(55) / 5.0; - record.gps.h_error = uint16(58); - record.gps.v_error = uint16(60); - - int n_tracking_reported = uint8(70); - if (n_tracking_reported > 12) - n_tracking_reported = 12; - int n_tracking_actual = 0; - for (int i = 0; i < n_tracking_reported; i++) { - if (uint8(71 + i*2) != 0) - n_tracking_actual++; - } - if (n_tracking_actual > 0) { - record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; - - n_tracking_actual = 0; - for (int i = 0; i < n_tracking_reported; i++) { - int svid = uint8(71 + i*2); - int c_n0 = uint8(72 + i*2); - if (svid != 0) - record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); - } - } - } - - record.time = 0.0; - } - - public AltosRecord update_state(AltosRecord previous) { - return record; - } -} diff --git a/altosui/AltosTelemetryRecordLocation.java b/altosui/AltosTelemetryRecordLocation.java deleted file mode 100644 index 80db454d..00000000 --- a/altosui/AltosTelemetryRecordLocation.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { - int flags; - int altitude; - int latitude; - int longitude; - int year; - int month; - int day; - int hour; - int minute; - int second; - int pdop; - int hdop; - int vdop; - int mode; - int ground_speed; - int climb_rate; - int course; - - public AltosTelemetryRecordLocation(int[] in_bytes) { - super(in_bytes); - - flags = uint8(5); - altitude = int16(6); - latitude = uint32(8); - longitude = uint32(12); - year = uint8(16); - month = uint8(17); - day = uint8(18); - hour = uint8(19); - minute = uint8(20); - second = uint8(21); - pdop = uint8(22); - hdop = uint8(23); - vdop = uint8(24); - mode = uint8(25); - ground_speed = uint16(26); - climb_rate = int16(28); - course = uint8(30); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - if (next.gps == null) - next.gps = new AltosGPS(); - - next.gps.nsat = flags & 0xf; - next.gps.locked = (flags & (1 << 4)) != 0; - next.gps.connected = (flags & (1 << 5)) != 0; - - if (next.gps.locked) { - next.gps.lat = latitude * 1.0e-7; - next.gps.lon = longitude * 1.0e-7; - next.gps.alt = altitude; - next.gps.year = 2000 + year; - next.gps.month = month; - next.gps.day = day; - next.gps.hour = hour; - next.gps.minute = minute; - next.gps.second = second; - next.gps.ground_speed = ground_speed * 1.0e-2; - next.gps.course = course * 2; - next.gps.climb_rate = climb_rate * 1.0e-2; - next.gps.hdop = hdop; - next.gps.vdop = vdop; - next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; - next.new_gps = true; - } - - return next; - } -} diff --git a/altosui/AltosTelemetryRecordRaw.java b/altosui/AltosTelemetryRecordRaw.java deleted file mode 100644 index 08c85e85..00000000 --- a/altosui/AltosTelemetryRecordRaw.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.text.*; -import java.util.HashMap; - -public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { - int[] bytes; - int serial; - int tick; - int type; - - long received_time; - - public int int8(int off) { - return Altos.int8(bytes, off + 1); - } - - public int uint8(int off) { - return Altos.uint8(bytes, off + 1); - } - - public int int16(int off) { - return Altos.int16(bytes, off + 1); - } - - public int uint16(int off) { - return Altos.uint16(bytes, off + 1); - } - - public int uint32(int off) { - return Altos.uint32(bytes, off + 1); - } - - public String string(int off, int l) { - return Altos.string(bytes, off + 1, l); - } - - public AltosTelemetryRecordRaw(int[] in_bytes) { - bytes = in_bytes; - serial = uint16(0); - tick = uint16(2); - type = uint8(4); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next; - if (previous != null) - next = new AltosRecord(previous); - else - next = new AltosRecord(); - next.serial = serial; - next.tick = tick; - return next; - } - - public long received_time() { - return received_time; - } -} diff --git a/altosui/AltosTelemetryRecordSatellite.java b/altosui/AltosTelemetryRecordSatellite.java deleted file mode 100644 index 2dd782ad..00000000 --- a/altosui/AltosTelemetryRecordSatellite.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { - int channels; - AltosGPSSat[] sats; - - public AltosTelemetryRecordSatellite(int[] in_bytes) { - super(in_bytes); - - channels = uint8(5); - if (channels > 12) - channels = 12; - if (channels == 0) - sats = null; - else { - sats = new AltosGPSSat[channels]; - for (int i = 0; i < channels; i++) { - int svid = uint8(6 + i * 2 + 0); - int c_n_1 = uint8(6 + i * 2 + 1); - sats[i] = new AltosGPSSat(svid, c_n_1); - } - } - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - if (next.gps == null) - next.gps = new AltosGPS(); - - next.gps.cc_gps_sat = sats; - - return next; - } -} diff --git a/altosui/AltosTelemetryRecordSensor.java b/altosui/AltosTelemetryRecordSensor.java deleted file mode 100644 index 96fee81f..00000000 --- a/altosui/AltosTelemetryRecordSensor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { - int state; - int accel; - int pres; - int temp; - int v_batt; - int sense_d; - int sense_m; - - int acceleration; - int speed; - int height; - - int ground_accel; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - - int rssi; - - public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { - super(in_bytes); - state = uint8(5); - - accel = int16(6); - pres = int16(8); - temp = int16(10); - v_batt = int16(12); - sense_d = int16(14); - sense_m = int16(16); - - acceleration = int16(18); - speed = int16(20); - height = int16(22); - - ground_pres = int16(24); - ground_accel = int16(26); - accel_plus_g = int16(28); - accel_minus_g = int16(30); - - rssi = in_rssi; - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.state = state; - if (type == packet_type_TM_sensor) - next.accel = accel; - else - next.accel = AltosRecord.MISSING; - next.pres = pres; - next.temp = temp; - next.batt = v_batt; - if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { - next.drogue = sense_d; - next.main = sense_m; - } else { - next.drogue = AltosRecord.MISSING; - next.main = AltosRecord.MISSING; - } - - next.acceleration = acceleration / 16.0; - next.speed = speed / 16.0; - next.height = height; - - next.ground_pres = ground_pres; - if (type == packet_type_TM_sensor) { - next.ground_accel = ground_accel; - next.accel_plus_g = accel_plus_g; - next.accel_minus_g = accel_minus_g; - } else { - next.ground_accel = AltosRecord.MISSING; - next.accel_plus_g = AltosRecord.MISSING; - next.accel_minus_g = AltosRecord.MISSING; - } - - next.rssi = rssi; - - next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; - - return next; - } -} diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am new file mode 100644 index 00000000..9c655131 --- /dev/null +++ b/altosui/altoslib/Makefile.am @@ -0,0 +1,56 @@ +AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation + +JAVAROOT=bin + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/*" + +SRC=src/org/altusmetrum/AltosLib +BIN=bin/org/altusmetrum/AltosLib + +AltosLibdir = $(datadir)/java + +AltosLib_JAVA = \ + $(SRC)/AltosLib.java \ + $(SRC)/AltosConvert.java \ + $(SRC)/AltosCRCException.java \ + $(SRC)/AltosFrequency.java \ + $(SRC)/AltosGPS.java \ + $(SRC)/AltosGPSSat.java \ + $(SRC)/AltosLine.java \ + $(SRC)/AltosParse.java \ + $(SRC)/AltosRecordCompanion.java \ + $(SRC)/AltosRecordIterable.java \ + $(SRC)/AltosRecord.java \ + $(SRC)/AltosTelemetryIterable.java \ + $(SRC)/AltosTelemetry.java \ + $(SRC)/AltosTelemetryMap.java \ + $(SRC)/AltosTelemetryRecordCompanion.java \ + $(SRC)/AltosTelemetryRecordConfiguration.java \ + $(SRC)/AltosTelemetryRecordGeneral.java \ + $(SRC)/AltosTelemetryRecord.java \ + $(SRC)/AltosTelemetryRecordLegacy.java \ + $(SRC)/AltosTelemetryRecordLocation.java \ + $(SRC)/AltosTelemetryRecordRaw.java \ + $(SRC)/AltosTelemetryRecordSatellite.java \ + $(SRC)/AltosTelemetryRecordSensor.java + +JAR=AltosLib.jar + +all-local: $(JAR) + +clean-local: + -rm -rf bin $(JAR) + +altosuidir=$(datadir)/java + +install-altosuiJAVA: $(JAR) + @$(NORMAL_INSTALL) + test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)" + +bin: + mkdir -p bin + +$(JAR): classAltosLib.stamp + jar cf $@ -C bin org diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java new file mode 100644 index 00000000..4a529bcf --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java new file mode 100644 index 00000000..df41a522 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java @@ -0,0 +1,259 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Sensor data conversion functions + */ +package altosui; + +public class AltosConvert { + /* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= Math.pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * Math.pow(base, exponent); + } + + return pressure; + } + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ + static double + pressure_to_altitude(double pressure) + { + + double next_base_temperature = LAYER0_BASE_TEMPERATURE; + double next_base_pressure = LAYER0_BASE_PRESSURE; + + double altitude; + double base_pressure; + double base_temperature; + double base; /* base for function to determine base pressure of next layer */ + double exponent; /* exponent for function to determine base pressure + of next layer */ + double coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= Math.pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * Math.log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (Math.pow(base, exponent) - 1); + } + + return altitude; + } + + static double + cc_battery_to_voltage(double battery) + { + return battery / 32767.0 * 5.0; + } + + static double + cc_ignitor_to_voltage(double ignite) + { + return ignite / 32767 * 15.0; + } + + static double radio_to_frequency(int freq, int setting, int cal, int channel) { + double f; + + if (freq > 0) + f = freq / 1000.0; + else { + if (setting <= 0) + setting = cal; + f = 434.550 * setting / cal; + /* Round to nearest 50KHz */ + f = Math.floor (20.0 * f + 0.5) / 20.0; + } + return f + channel * 0.100; + } + + static int radio_frequency_to_setting(double frequency, int cal) { + double set = frequency / 434.550 * cal; + + return (int) Math.floor (set + 0.5); + } + + static int radio_frequency_to_channel(double frequency) { + int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); + + if (channel < 0) + channel = 0; + if (channel > 9) + channel = 9; + return channel; + } + + static double radio_channel_to_frequency(int channel) { + return 434.550 + channel * 0.100; + } + + static int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + static double meters_to_feet(double meters) { + return meters * (100 / (2.54 * 12)); + } + + static double meters_to_mach(double meters) { + return meters / 343; /* something close to mach at usual rocket sites */ + } + + static double meters_to_g(double meters) { + return meters / 9.80665; + } + + static int checksum(int[] data, int start, int length) { + int csum = 0x5a; + for (int i = 0; i < length; i++) + csum += data[i + start]; + return csum & 0xff; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java new file mode 100644 index 00000000..0dda0f29 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 interface AltosFontListener { + void font_size_changed(int font_size); +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java new file mode 100644 index 00000000..b748e460 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 javax.swing.plaf.basic.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosFrequency { + double frequency; + String description; + + public String toString() { + return String.format("%7.3f MHz %-20s", + frequency, description); + } + + public String toShortString() { + return String.format("%7.3f MHz %s", + frequency, description); + } + + public boolean close(double f) { + double diff = Math.abs(frequency - f); + + return diff < 0.010; + } + + public AltosFrequency(double f, String d) { + frequency = f; + description = d; + } +} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java new file mode 100644 index 00000000..b5df7c9a --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java @@ -0,0 +1,248 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; + +public class AltosGPS { + + final static int MISSING = AltosRecord.MISSING; + + int nsat; + boolean locked; + boolean connected; + double lat; /* degrees (+N -S) */ + double lon; /* degrees (+E -W) */ + int alt; /* m */ + int year; + int month; + int day; + int hour; + int minute; + int second; + + double ground_speed; /* m/s */ + int course; /* degrees */ + double climb_rate; /* m/s */ + double hdop; /* unitless */ + double vdop; /* unitless */ + int h_error; /* m */ + int v_error; /* m */ + + AltosGPSSat[] cc_gps_sat; /* tracking data */ + + 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 = AltosParse.parse_int(hms[0]); + minute = AltosParse.parse_int(hms[1]); + second = AltosParse.parse_int(hms[2]); + } + + void ClearGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } + + public AltosGPS(AltosTelemetryMap map) throws ParseException { + String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, + AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); + + nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); + if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { + connected = true; + locked = true; + lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); + lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); + alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); + year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); + if (year != MISSING) + year += 2000; + month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); + day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); + + hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); + minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); + second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); + + ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, + AltosRecord.MISSING, 1/100.0); + course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, + AltosRecord.MISSING); + hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); + vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); + h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); + v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); + } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { + connected = true; + locked = false; + } else { + connected = false; + locked = false; + } + } + + 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"); + + connected = false; + locked = false; + lat = lon = 0; + alt = 0; + ClearGPSTime(); + if ((words[i]).equals("unlocked")) { + connected = true; + i++; + } else if ((words[i]).equals("not-connected")) { + i++; + } else if (words.length >= 40) { + locked = true; + connected = true; + + 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(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++; + } + 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 AltosGPSSat[tracking_channels]; + for (int chan = 0; chan < tracking_channels; chan++) { + cc_gps_sat[chan] = new 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 AltosGPSSat[0]; + } + + public void set_latitude(int in_lat) { + lat = in_lat / 10.0e7; + } + + public void set_longitude(int in_lon) { + lon = in_lon / 10.0e7; + } + + public void set_time(int hour, int minute, int second) { + hour = hour; + minute = minute; + second = second; + } + + public void set_date(int year, int month, int day) { + year = year; + month = month; + day = day; + } + + public void set_flags(int flags) { + flags = flags; + } + + public void set_altitude(int altitude) { + altitude = altitude; + } + + public void add_sat(int svid, int c_n0) { + if (cc_gps_sat == null) { + cc_gps_sat = new AltosGPSSat[1]; + } else { + AltosGPSSat[] new_gps_sat = new AltosGPSSat[cc_gps_sat.length + 1]; + for (int i = 0; i < cc_gps_sat.length; i++) + new_gps_sat[i] = cc_gps_sat[i]; + cc_gps_sat = new_gps_sat; + } + AltosGPSSat sat = new AltosGPSSat(); + sat.svid = svid; + sat.c_n0 = c_n0; + cc_gps_sat[cc_gps_sat.length - 1] = sat; + } + + public AltosGPS() { + ClearGPSTime(); + cc_gps_sat = null; + } + + public AltosGPS(AltosGPS old) { + nsat = old.nsat; + locked = old.locked; + connected = old.connected; + lat = old.lat; /* degrees (+N -S) */ + lon = old.lon; /* degrees (+E -W) */ + alt = old.alt; /* m */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } + } + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java new file mode 100644 index 00000000..fb125651 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosGPSSat { + int svid; + int c_n0; + + public AltosGPSSat(int s, int c) { + svid = s; + c_n0= c; + } + + public AltosGPSSat() { + } +} + diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java new file mode 100644 index 00000000..86e9d4c6 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java new file mode 100644 index 00000000..fbfcaaee --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.lang.*; + +public class AltosParse { + static boolean isdigit(char c) { + return '0' <= c && c <= '9'; + } + + static int parse_int(String v) throws ParseException { + try { + 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 Altos.fromhex(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing hex " + v, 0); + } + } + + static double parse_double(String v) throws ParseException { + try { + return Double.parseDouble(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing double " + v, 0); + } + } + + static double parse_coord(String coord) throws ParseException { + String[] dsf = coord.split("\\D+"); + + if (dsf.length != 3) { + throw new ParseException("error parsing coord " + coord, 0); + } + int deg = parse_int(dsf[0]); + int min = parse_int(dsf[1]); + int frac = parse_int(dsf[2]); + + double r = deg + (min + frac / 10000.0) / 60.0; + if (coord.endsWith("S") || coord.endsWith("W")) + r = -r; + return r; + } + + static String strip_suffix(String v, String suffix) { + if (v.endsWith(suffix)) + return v.substring(0, v.length() - suffix.length()); + return v; + } + + static void word(String v, String m) throws ParseException { + if (!v.equals(m)) { + throw new ParseException("error matching '" + v + "' '" + m + "'", 0); + } + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java new file mode 100644 index 00000000..4643d69a --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java @@ -0,0 +1,317 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; +import java.io.*; + +public class AltosRecord implements Comparable { + final static int MISSING = 0x7fffffff; + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + static final int seen_companion = 128; + int seen; + + int version; + String callsign; + int serial; + int flight; + int rssi; + int status; + int state; + int tick; + + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + + int ground_accel; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + + double acceleration; + double speed; + double height; + + int flight_accel; + int flight_vel; + int flight_pres; + + AltosGPS gps; + boolean new_gps; + + AltosIMU imu; + AltosMag mag; + + double time; /* seconds since boost */ + + int device_type; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String firmware_version; + + AltosRecordCompanion companion; + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + static final double counts_per_kPa = 27 * 2047 / 3300; + static final double counts_at_101_3kPa = 1674.0; + + static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + public double raw_pressure() { + if (pres == MISSING) + return MISSING; + return barometer_to_pressure(pres); + } + + public double filtered_pressure() { + if (flight_pres == MISSING) + return MISSING; + return barometer_to_pressure(flight_pres); + } + + public double ground_pressure() { + if (ground_pres == MISSING) + return MISSING; + return barometer_to_pressure(ground_pres); + } + + public double raw_altitude() { + double p = raw_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double ground_altitude() { + double p = ground_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_altitude() { + if (height != MISSING && ground_pres != MISSING) + return height + ground_altitude(); + + double p = filtered_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_height() { + if (height != MISSING) + return height; + + double f = filtered_altitude(); + double g = ground_altitude(); + if (f == MISSING || g == MISSING) + return MISSING; + return f - g; + } + + public double raw_height() { + double r = raw_altitude(); + double g = ground_altitude(); + + if (r == MISSING || g == MISSING) + return height; + return r - g; + } + + public double battery_voltage() { + if (batt == MISSING) + return MISSING; + return AltosConvert.cc_battery_to_voltage(batt); + } + + public double main_voltage() { + if (main == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(main); + } + + public double drogue_voltage() { + if (drogue == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(drogue); + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public double temperature() { + if (temp == MISSING) + return MISSING; + return thermometer_to_temperature(temp); + } + + double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + + public double acceleration() { + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; + return (ground_accel - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + if (speed != MISSING) + return speed; + if (flight_vel == MISSING) + return MISSING; + return flight_vel / (accel_counts_per_mss() * 100.0); + } + + public String state() { + return Altos.state_name(state); + } + + public static String gets(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') { + return line; + } + line = line + (char) c; + } + return null; + } + + public int compareTo(AltosRecord o) { + return tick - o.tick; + } + + public AltosRecord(AltosRecord old) { + version = old.version; + seen = old.seen; + callsign = old.callsign; + serial = old.serial; + flight = old.flight; + rssi = old.rssi; + status = old.status; + state = old.state; + tick = old.tick; + accel = old.accel; + pres = old.pres; + temp = old.temp; + batt = old.batt; + drogue = old.drogue; + main = old.main; + flight_accel = old.flight_accel; + ground_accel = old.ground_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + acceleration = old.acceleration; + speed = old.speed; + height = old.height; + gps = new AltosGPS(old.gps); + new_gps = false; + companion = old.companion; + imu = old.imu; + mag = old.mag; + } + + public AltosRecord() { + version = 0; + seen = 0; + callsign = "N0CALL"; + serial = 0; + flight = 0; + rssi = 0; + status = 0; + state = Altos.ao_flight_startup; + tick = 0; + accel = MISSING; + pres = MISSING; + temp = MISSING; + batt = MISSING; + drogue = MISSING; + main = MISSING; + flight_accel = 0; + ground_accel = 0; + flight_vel = 0; + flight_pres = 0; + ground_pres = 0; + accel_plus_g = 0; + accel_minus_g = 0; + acceleration = MISSING; + speed = MISSING; + height = MISSING; + gps = new AltosGPS(); + new_gps = false; + companion = null; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java new file mode 100644 index 00000000..0a8f9f4b --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosRecordCompanion { + final static int board_id_telescience = 0x0a; + final static int MAX_CHANNELS = 12; + + int tick; + int board_id; + int update_period; + int channels; + int[] companion_data; + + public AltosRecordCompanion(int in_channels) { + channels = in_channels; + if (channels < 0) + channels = 0; + if (channels > MAX_CHANNELS) + channels = MAX_CHANNELS; + companion_data = new int[channels]; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java new file mode 100644 index 00000000..45843b92 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java @@ -0,0 +1,37 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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; + +public abstract class AltosRecordIterable implements Iterable { + public abstract Iterator iterator(); + public void write_comments(PrintStream out) { } + public boolean has_accel() { return false; } + public boolean has_gps() { return false; } + public boolean has_ignite() { return false; }; +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java new file mode 100644 index 00000000..0052ef04 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java @@ -0,0 +1,241 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * + */ + +public class AltosTelemetry extends AltosRecord { + + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { + AltosTelemetryRecord r = AltosTelemetryRecord.parse(line); + + return r.update_state(previous); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java new file mode 100644 index 00000000..a1b25332 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 java.util.*; +import java.text.*; + +public class AltosTelemetryIterable extends AltosRecordIterable { + TreeSet records; + + public Iterator iterator () { + return records.iterator(); + } + + boolean has_gps = false; + boolean has_accel = false; + boolean has_ignite = false; + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; }; + + public AltosTelemetryIterable (FileInputStream input) { + boolean saw_boost = false; + int current_tick = 0; + int boost_tick = 0; + + AltosRecord previous = null; + records = new TreeSet (); + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) { + break; + } + try { + AltosRecord record = AltosTelemetry.parse(line, previous); + if (record == null) + break; + if (records.isEmpty()) { + current_tick = record.tick; + } else { + int tick = record.tick; + while (tick < current_tick - 0x1000) + tick += 0x10000; + current_tick = tick; + record.tick = current_tick; + } + if (!saw_boost && record.state >= Altos.ao_flight_boost) + { + saw_boost = true; + boost_tick = record.tick; + } + if (record.accel != AltosRecord.MISSING) + has_accel = true; + if (record.gps != null) + has_gps = true; + if (record.main != AltosRecord.MISSING) + has_ignite = true; + if (previous != null && previous.tick != record.tick) + records.add(previous); + previous = record; + } catch (ParseException pe) { + System.out.printf("parse exception %s\n", pe.getMessage()); + } catch (AltosCRCException ce) { + } + } + } catch (IOException io) { + System.out.printf("io exception\n"); + } + + if (previous != null) + records.add(previous); + + /* Adjust all tick counts to match expected eeprom values, + * which starts with a 16-bit tick count 16 samples before boost + */ + + int tick_adjust = (boost_tick - 16) & 0xffff0000; + for (AltosRecord r : this) + r.tick -= tick_adjust; + boost_tick -= tick_adjust; + + /* adjust all tick counts to be relative to boost time */ + for (AltosRecord r : this) + r.time = (r.tick - boost_tick) / 100.0; + + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java new file mode 100644 index 00000000..d906100f --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryMap extends HashMap { + public boolean has(String key) { + return containsKey(key); + } + + public String get_string(String key) throws ParseException { + if (!has(key)) + throw new ParseException ("missing " + key, 0); + return (String) get(key); + } + + public String get_string(String key, String def) { + if (has(key)) + return get(key); + else + return def; + } + + public int get_int(String key) throws ParseException { + return AltosParse.parse_int(get_string(key)); + } + + public int get_int(String key, int def) throws ParseException { + if (has(key)) + return get_int(key); + else + return def; + } + + public double get_double(String key, double def, double scale) throws ParseException { + if (has(key)) + return get_int(key) * scale; + else + return def; + } + + public AltosTelemetryMap(String[] words, int start) { + for (int i = start; i < words.length - 1; i += 2) + put(words[i], words[i+1]); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java new file mode 100644 index 00000000..dde60dc9 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java @@ -0,0 +1,119 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; +import java.util.concurrent.*; + +class AltosTelemetryReader extends AltosFlightReader { + AltosDevice device; + AltosSerial serial; + AltosLog log; + AltosRecord previous; + double frequency; + int telemetry; + + LinkedBlockingQueue telem; + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { + AltosLine l = telem.take(); + if (l.line == null) + throw new IOException("IO error"); + AltosRecord next = AltosTelemetry.parse(l.line, previous); + previous = next; + return next; + } + + void flush() { + telem.clear(); + } + + void close(boolean interrupted) { + serial.remove_monitor(telem); + log.close(); + serial.close(); + } + + public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + serial.set_radio_frequency(frequency); + } + + public boolean supports_telemetry(int telemetry) { + + try { + /* Version 1.0 or later firmware supports all telemetry formats */ + if (serial.config_data().compare_version("1.0") >= 0) + return true; + + /* Version 0.9 firmware only supports 0.9 telemetry */ + if (serial.config_data().compare_version("0.9") >= 0) { + if (telemetry == Altos.ao_telemetry_0_9) + return true; + else + return false; + } + + /* Version 0.8 firmware only supports 0.8 telemetry */ + if (telemetry == Altos.ao_telemetry_0_8) + return true; + else + return false; + } catch (InterruptedException ie) { + return true; + } catch (TimeoutException te) { + return true; + } + } + + void save_frequency() { + AltosUIPreferences.set_frequency(device.getSerial(), frequency); + } + + void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + serial.set_telemetry(telemetry); + } + + void save_telemetry() { + AltosUIPreferences.set_telemetry(device.getSerial(), telemetry); + } + + File backing_file() { + return log.file(); + } + + public AltosTelemetryReader (AltosDevice in_device) + throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { + device = in_device; + serial = new AltosSerial(device); + log = new AltosLog(serial); + name = device.toShortString(); + previous = null; + + telem = new LinkedBlockingQueue(); + frequency = AltosUIPreferences.frequency(device.getSerial()); + set_frequency(frequency); + telemetry = AltosUIPreferences.telemetry(device.getSerial()); + set_telemetry(telemetry); + serial.set_callsign(AltosUIPreferences.callsign()); + serial.add_monitor(telem); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java new file mode 100644 index 00000000..2e6b5ead --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java @@ -0,0 +1,128 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; + +public abstract class AltosTelemetryRecord { + + long received_time; + abstract public AltosRecord update_state(AltosRecord previous); + + static boolean cksum(int[] bytes) { + int sum = 0x5a; + for (int i = 1; i < bytes.length - 1; i++) + sum += bytes[i]; + sum &= 0xff; + return sum == bytes[bytes.length - 1]; + } + + final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); + final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); + final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; + + final static int packet_type_TM_sensor = 0x01; + final static int packet_type_Tm_sensor = 0x02; + final static int packet_type_Tn_sensor = 0x03; + final static int packet_type_configuration = 0x04; + final static int packet_type_location = 0x05; + final static int packet_type_satellite = 0x06; + final static int packet_type_companion = 0x07; + + static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + int[] bytes; + try { + bytes = Altos.hexbytes(hex); + } catch (NumberFormatException ne) { + throw new ParseException(ne.getMessage(), 0); + } + + /* one for length, one for checksum */ + if (bytes[0] != bytes.length - 2) + throw new ParseException(String.format("invalid length %d != %d\n", + bytes[0], + bytes.length - 2), 0); + if (!cksum(bytes)) + throw new ParseException(String.format("invalid line \"%s\"", hex), 0); + + int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; + int status = Altos.uint8(bytes, bytes.length - 2); + + if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) + throw new AltosCRCException(rssi); + + /* length, data ..., rssi, status, checksum -- 4 bytes extra */ + switch (bytes.length) { + case Altos.ao_telemetry_standard_len + 4: + int type = Altos.uint8(bytes, 4 + 1); + switch (type) { + case packet_type_TM_sensor: + case packet_type_Tm_sensor: + case packet_type_Tn_sensor: + r = new AltosTelemetryRecordSensor(bytes, rssi); + break; + case packet_type_configuration: + r = new AltosTelemetryRecordConfiguration(bytes); + break; + case packet_type_location: + r = new AltosTelemetryRecordLocation(bytes); + break; + case packet_type_satellite: + r = new AltosTelemetryRecordSatellite(bytes); + break; + case packet_type_companion: + r = new AltosTelemetryRecordCompanion(bytes); + break; + default: + r = new AltosTelemetryRecordRaw(bytes); + break; + } + break; + case Altos.ao_telemetry_0_9_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + case Altos.ao_telemetry_0_8_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + default: + throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); + } + r.received_time = System.currentTimeMillis(); + return r; + } + + public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + if (word[i].equals("TELEM")) + r = parse_hex(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java new file mode 100644 index 00000000..52d7f4cf --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { + + AltosRecordCompanion companion; + + public AltosTelemetryRecordCompanion(int[] in_bytes) { + super(in_bytes); + + int off = 0; + if (uint8(6) == 0) + off = 1; + int channels = uint8(7+off); + + if (off != 0 && channels >= 12) + channels = 11; + + companion = new AltosRecordCompanion(channels); + companion.tick = tick; + companion.board_id = uint8(5); + companion.update_period = uint8(6+off); + for (int i = 0; i < companion.companion_data.length; i++) + companion.companion_data[i] = uint16(8 + off + i * 2); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.companion = companion; + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + companion.tick = tick; + return next; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java new file mode 100644 index 00000000..b029d120 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { + int device_type; + int flight; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String callsign; + String version; + + public AltosTelemetryRecordConfiguration(int[] in_bytes) { + super(in_bytes); + + device_type = uint8(5); + flight = uint16(6); + config_major = uint8(8); + config_minor = uint8(9); + apogee_delay = uint16(10); + main_deploy = uint16(12); + flight_log_max = uint16(14); + callsign = string(16, 8); + version = string(24, 8); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.device_type = device_type; + next.flight = flight; + next.config_major = config_major; + next.config_minor = config_minor; + next.apogee_delay = apogee_delay; + next.main_deploy = main_deploy; + next.flight_log_max = flight_log_max; + + next.callsign = callsign; + next.firmware_version = version; + + next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight; + + return next; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java new file mode 100644 index 00000000..722baba3 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordGeneral { + + static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + if (word[i].equals("TELEM")) + r = AltosTelemetryRecordRaw.parse(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java new file mode 100644 index 00000000..a72ebb0f --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java @@ -0,0 +1,521 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * + */ + +public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + AltosRecord record; + + private void parse_v4(String[] words, int i) throws ParseException { + AltosTelemetryMap map = new AltosTelemetryMap(words, i); + + record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); + record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); + record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); + record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + record.tick = map.get_int(AO_TELEM_TICK, 0); + + /* raw sensor values */ + record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING); + record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING); + record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING); + record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING); + record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING); + record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING); + + /* sensor calibration information */ + record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING); + record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING); + record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING); + record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); + + /* flight computer values */ + record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); + record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); + record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); + + record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); + record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); + record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING); + + if (map.has(AO_TELEM_GPS_STATE)) { + record.gps = new AltosGPS(map); + record.new_gps = true; + } + else + record.gps = null; + } + + private void parse_legacy(String[] words, int i) throws ParseException { + + AltosParse.word (words[i++], "CALL"); + record.callsign = words[i++]; + + AltosParse.word (words[i++], "SERIAL"); + record.serial = AltosParse.parse_int(words[i++]); + + if (record.version >= 2) { + AltosParse.word (words[i++], "FLIGHT"); + record.flight = AltosParse.parse_int(words[i++]); + } else + record.flight = 0; + + AltosParse.word(words[i++], "RSSI"); + record.rssi = AltosParse.parse_int(words[i++]); + + /* Older telemetry data had mis-computed RSSI value */ + if (record.version <= 2) + record.rssi = (record.rssi + 74) / 2 - 74; + + AltosParse.word(words[i++], "STATUS"); + record.status = AltosParse.parse_hex(words[i++]); + + AltosParse.word(words[i++], "STATE"); + record.state = Altos.state(words[i++]); + + record.tick = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a:"); + record.accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "p:"); + record.pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "t:"); + record.temp = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "v:"); + record.batt = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "d:"); + record.drogue = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "m:"); + record.main = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fa:"); + record.flight_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "ga:"); + record.ground_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fv:"); + record.flight_vel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fp:"); + record.flight_pres = AltosParse.parse_int(words[i++]); + + /* Old TeleDongle code with kalman-reporting TeleMetrum code */ + if ((record.flight_vel & 0xffff0000) == 0x80000000) { + record.speed = ((short) record.flight_vel) / 16.0; + record.acceleration = record.flight_accel / 16.0; + record.height = record.flight_pres; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; + record.flight_accel = AltosRecord.MISSING; + } + + AltosParse.word(words[i++], "gp:"); + record.ground_pres = AltosParse.parse_int(words[i++]); + + if (record.version >= 1) { + AltosParse.word(words[i++], "a+:"); + record.accel_plus_g = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a-:"); + record.accel_minus_g = AltosParse.parse_int(words[i++]); + } else { + record.accel_plus_g = record.ground_accel; + record.accel_minus_g = record.ground_accel + 530; + } + + record.gps = new AltosGPS(words, i, record.version); + record.new_gps = true; + } + + public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + record = new AltosRecord(); + + if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(words[i++], "RSSI"); + record.rssi = AltosParse.parse_int(words[i++]); + throw new AltosCRCException(record.rssi); + } + if (words[i].equals("CALL")) { + record.version = 0; + } else { + AltosParse.word (words[i++], "VERSION"); + record.version = AltosParse.parse_int(words[i++]); + } + + if (record.version < 4) + parse_legacy(words, i); + else + parse_v4(words, i); + } + + /* + * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that + */ + + int[] bytes; + int adjust; + + private int int8(int i) { + return Altos.int8(bytes, i + 1 + adjust); + } + private int uint8(int i) { + return Altos.uint8(bytes, i + 1 + adjust); + } + private int int16(int i) { + return Altos.int16(bytes, i + 1 + adjust); + } + private int uint16(int i) { + return Altos.uint16(bytes, i + 1 + adjust); + } + private int uint32(int i) { + return Altos.uint32(bytes, i + 1 + adjust); + } + private String string(int i, int l) { + return Altos.string(bytes, i + 1 + adjust, l); + } + + static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); + static final int AO_GPS_NUM_SAT_SHIFT = (0); + + static final int AO_GPS_VALID = (1 << 4); + static final int AO_GPS_RUNNING = (1 << 5); + static final int AO_GPS_DATE_VALID = (1 << 6); + static final int AO_GPS_COURSE_VALID = (1 << 7); + + public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { + record = new AltosRecord(); + + bytes = in_bytes; + record.version = 4; + adjust = 0; + + if (bytes.length == Altos.ao_telemetry_0_8_len + 4) { + record.serial = uint8(0); + adjust = -1; + } else + record.serial = uint16(0); + + record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy; + + record.callsign = string(62, 8); + record.flight = uint16(2); + record.rssi = in_rssi; + record.status = in_status; + record.state = uint8(4); + record.tick = uint16(21); + record.accel = int16(23); + record.pres = int16(25); + record.temp = int16(27); + record.batt = int16(29); + record.drogue = int16(31); + record.main = int16(33); + + record.ground_accel = int16(7); + record.ground_pres = int16(15); + record.accel_plus_g = int16(17); + record.accel_minus_g = int16(19); + + if (uint16(11) == 0x8000) { + record.acceleration = int16(5); + record.speed = int16(9); + record.height = int16(13); + record.flight_accel = AltosRecord.MISSING; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; + } else { + record.flight_accel = int16(5); + record.flight_vel = uint32(9); + record.flight_pres = int16(13); + record.acceleration = AltosRecord.MISSING; + record.speed = AltosRecord.MISSING; + record.height = AltosRecord.MISSING; + } + + record.gps = null; + + int gps_flags = uint8(41); + + if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { + record.gps = new AltosGPS(); + record.new_gps = true; + + record.seen |= record.seen_gps_time | record.seen_gps_lat | record.seen_gps_lon; + record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); + record.gps.locked = (gps_flags & AO_GPS_VALID) != 0; + record.gps.connected = true; + record.gps.lat = uint32(42) / 1.0e7; + record.gps.lon = uint32(46) / 1.0e7; + record.gps.alt = int16(50); + record.gps.ground_speed = uint16(52) / 100.0; + record.gps.course = uint8(54) * 2; + record.gps.hdop = uint8(55) / 5.0; + record.gps.h_error = uint16(58); + record.gps.v_error = uint16(60); + + int n_tracking_reported = uint8(70); + if (n_tracking_reported > 12) + n_tracking_reported = 12; + int n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + if (uint8(71 + i*2) != 0) + n_tracking_actual++; + } + if (n_tracking_actual > 0) { + record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; + + n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + int svid = uint8(71 + i*2); + int c_n0 = uint8(72 + i*2); + if (svid != 0) + record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); + } + } + } + + record.time = 0.0; + } + + public AltosRecord update_state(AltosRecord previous) { + return record; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java new file mode 100644 index 00000000..80db454d --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java @@ -0,0 +1,93 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { + int flags; + int altitude; + int latitude; + int longitude; + int year; + int month; + int day; + int hour; + int minute; + int second; + int pdop; + int hdop; + int vdop; + int mode; + int ground_speed; + int climb_rate; + int course; + + public AltosTelemetryRecordLocation(int[] in_bytes) { + super(in_bytes); + + flags = uint8(5); + altitude = int16(6); + latitude = uint32(8); + longitude = uint32(12); + year = uint8(16); + month = uint8(17); + day = uint8(18); + hour = uint8(19); + minute = uint8(20); + second = uint8(21); + pdop = uint8(22); + hdop = uint8(23); + vdop = uint8(24); + mode = uint8(25); + ground_speed = uint16(26); + climb_rate = int16(28); + course = uint8(30); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.nsat = flags & 0xf; + next.gps.locked = (flags & (1 << 4)) != 0; + next.gps.connected = (flags & (1 << 5)) != 0; + + if (next.gps.locked) { + next.gps.lat = latitude * 1.0e-7; + next.gps.lon = longitude * 1.0e-7; + next.gps.alt = altitude; + next.gps.year = 2000 + year; + next.gps.month = month; + next.gps.day = day; + next.gps.hour = hour; + next.gps.minute = minute; + next.gps.second = second; + next.gps.ground_speed = ground_speed * 1.0e-2; + next.gps.course = course * 2; + next.gps.climb_rate = climb_rate * 1.0e-2; + next.gps.hdop = hdop; + next.gps.vdop = vdop; + next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; + next.new_gps = true; + } + + return next; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java new file mode 100644 index 00000000..08c85e85 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { + int[] bytes; + int serial; + int tick; + int type; + + long received_time; + + public int int8(int off) { + return Altos.int8(bytes, off + 1); + } + + public int uint8(int off) { + return Altos.uint8(bytes, off + 1); + } + + public int int16(int off) { + return Altos.int16(bytes, off + 1); + } + + public int uint16(int off) { + return Altos.uint16(bytes, off + 1); + } + + public int uint32(int off) { + return Altos.uint32(bytes, off + 1); + } + + public String string(int off, int l) { + return Altos.string(bytes, off + 1, l); + } + + public AltosTelemetryRecordRaw(int[] in_bytes) { + bytes = in_bytes; + serial = uint16(0); + tick = uint16(2); + type = uint8(4); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next; + if (previous != null) + next = new AltosRecord(previous); + else + next = new AltosRecord(); + next.serial = serial; + next.tick = tick; + return next; + } + + public long received_time() { + return received_time; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java new file mode 100644 index 00000000..2dd782ad --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { + int channels; + AltosGPSSat[] sats; + + public AltosTelemetryRecordSatellite(int[] in_bytes) { + super(in_bytes); + + channels = uint8(5); + if (channels > 12) + channels = 12; + if (channels == 0) + sats = null; + else { + sats = new AltosGPSSat[channels]; + for (int i = 0; i < channels; i++) { + int svid = uint8(6 + i * 2 + 0); + int c_n_1 = uint8(6 + i * 2 + 1); + sats[i] = new AltosGPSSat(svid, c_n_1); + } + } + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.cc_gps_sat = sats; + + return next; + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java new file mode 100644 index 00000000..96fee81f --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { + int state; + int accel; + int pres; + int temp; + int v_batt; + int sense_d; + int sense_m; + + int acceleration; + int speed; + int height; + + int ground_accel; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + + int rssi; + + public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { + super(in_bytes); + state = uint8(5); + + accel = int16(6); + pres = int16(8); + temp = int16(10); + v_batt = int16(12); + sense_d = int16(14); + sense_m = int16(16); + + acceleration = int16(18); + speed = int16(20); + height = int16(22); + + ground_pres = int16(24); + ground_accel = int16(26); + accel_plus_g = int16(28); + accel_minus_g = int16(30); + + rssi = in_rssi; + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.state = state; + if (type == packet_type_TM_sensor) + next.accel = accel; + else + next.accel = AltosRecord.MISSING; + next.pres = pres; + next.temp = temp; + next.batt = v_batt; + if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { + next.drogue = sense_d; + next.main = sense_m; + } else { + next.drogue = AltosRecord.MISSING; + next.main = AltosRecord.MISSING; + } + + next.acceleration = acceleration / 16.0; + next.speed = speed / 16.0; + next.height = height; + + next.ground_pres = ground_pres; + if (type == packet_type_TM_sensor) { + next.ground_accel = ground_accel; + next.accel_plus_g = accel_plus_g; + next.accel_minus_g = accel_minus_g; + } else { + next.ground_accel = AltosRecord.MISSING; + next.accel_plus_g = AltosRecord.MISSING; + next.accel_minus_g = AltosRecord.MISSING; + } + + next.rssi = rssi; + + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + return next; + } +} diff --git a/configure.ac b/configure.ac index f84387d2..efccf714 100644 --- a/configure.ac +++ b/configure.ac @@ -113,6 +113,7 @@ AC_OUTPUT([ Makefile altosui/Makefile altosui/AltosVersion.java +altosui/altoslib/Makefile altosui/libaltos/Makefile ao-tools/Makefile ao-tools/lib/Makefile -- cgit v1.2.3 From 71636c1ed7cbe075921391605d1ac4edaa6ee52b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 16:13:46 -0800 Subject: move a file back --- altosui/AltosFontListener.java | 22 ++++++++++++++++++++++ .../altusmetrum/AltosLib/AltosCRCException.java | 2 +- .../src/org/altusmetrum/AltosLib/AltosConvert.java | 2 +- .../altusmetrum/AltosLib/AltosFontListener.java | 22 ---------------------- .../org/altusmetrum/AltosLib/AltosFrequency.java | 2 +- .../src/org/altusmetrum/AltosLib/AltosGPS.java | 2 +- .../src/org/altusmetrum/AltosLib/AltosGPSSat.java | 2 +- .../src/org/altusmetrum/AltosLib/AltosLine.java | 2 +- .../src/org/altusmetrum/AltosLib/AltosParse.java | 6 +++--- .../src/org/altusmetrum/AltosLib/AltosRecord.java | 6 +++--- .../altusmetrum/AltosLib/AltosRecordCompanion.java | 2 +- .../altusmetrum/AltosLib/AltosRecordIterable.java | 2 +- .../org/altusmetrum/AltosLib/AltosTelemetry.java | 2 +- .../AltosLib/AltosTelemetryIterable.java | 4 ++-- .../altusmetrum/AltosLib/AltosTelemetryMap.java | 2 +- .../altusmetrum/AltosLib/AltosTelemetryReader.java | 2 +- .../altusmetrum/AltosLib/AltosTelemetryRecord.java | 4 +--- .../AltosLib/AltosTelemetryRecordCompanion.java | 2 +- .../AltosTelemetryRecordConfiguration.java | 2 +- .../AltosLib/AltosTelemetryRecordGeneral.java | 2 +- .../AltosLib/AltosTelemetryRecordLegacy.java | 16 ++++++++-------- .../AltosLib/AltosTelemetryRecordLocation.java | 2 +- .../AltosLib/AltosTelemetryRecordRaw.java | 14 +++++++------- .../AltosLib/AltosTelemetryRecordSatellite.java | 2 +- .../AltosLib/AltosTelemetryRecordSensor.java | 2 +- 25 files changed, 63 insertions(+), 65 deletions(-) create mode 100644 altosui/AltosFontListener.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java diff --git a/altosui/AltosFontListener.java b/altosui/AltosFontListener.java new file mode 100644 index 00000000..6fc214bc --- /dev/null +++ b/altosui/AltosFontListener.java @@ -0,0 +1,22 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public interface AltosFontListener { + void font_size_changed(int font_size); +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java index 4a529bcf..101c5363 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosCRCException extends Exception { public int rssi; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java index df41a522..6773ab7e 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java @@ -18,7 +18,7 @@ /* * Sensor data conversion functions */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosConvert { /* diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java deleted file mode 100644 index 0dda0f29..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFontListener.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 interface AltosFontListener { - void font_size_changed(int font_size); -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java index b748e460..4c0c7baa 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.awt.*; import java.awt.event.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java index b5df7c9a..8cc7aa69 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java index fb125651..5fa8f987 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosGPSSat { int svid; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java index 86e9d4c6..5627795a 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosLine { public String line; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java index fbfcaaee..4c0a59cb 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.text.*; import java.lang.*; @@ -27,7 +27,7 @@ public class AltosParse { static int parse_int(String v) throws ParseException { try { - return Altos.fromdec(v); + return AltosLib.fromdec(v); } catch (NumberFormatException e) { throw new ParseException("error parsing int " + v, 0); } @@ -35,7 +35,7 @@ public class AltosParse { static int parse_hex(String v) throws ParseException { try { - return Altos.fromhex(v); + return AltosLib.fromhex(v); } catch (NumberFormatException e) { throw new ParseException("error parsing hex " + v, 0); } diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java index 4643d69a..120004a7 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; @@ -229,7 +229,7 @@ public class AltosRecord implements Comparable { } public String state() { - return Altos.state_name(state); + return AltosLib.state_name(state); } public static String gets(FileInputStream s) throws IOException { @@ -292,7 +292,7 @@ public class AltosRecord implements Comparable { flight = 0; rssi = 0; status = 0; - state = Altos.ao_flight_startup; + state = AltosLib.ao_flight_startup; tick = 0; accel = MISSING; pres = MISSING; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java index 0a8f9f4b..4f8e80dc 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosRecordCompanion { final static int board_id_telescience = 0x0a; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java index 45843b92..abe67aaa 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.awt.*; import java.awt.event.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java index 0052ef04..04abb1f3 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java index a1b25332..f4b4029f 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.io.*; import java.util.*; @@ -62,7 +62,7 @@ public class AltosTelemetryIterable extends AltosRecordIterable { current_tick = tick; record.tick = current_tick; } - if (!saw_boost && record.state >= Altos.ao_flight_boost) + if (!saw_boost && record.state >= AltosLib.ao_flight_boost) { saw_boost = true; boost_tick = record.tick; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java index d906100f..003cb6a9 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; import java.util.HashMap; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java index dde60dc9..bd94ee36 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java index 2e6b5ead..367c148d 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java @@ -15,9 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; -import java.lang.*; -import java.text.*; +package org.altusmetrum.AltosLib; public abstract class AltosTelemetryRecord { diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java index 52d7f4cf..6ad17244 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java index b029d120..25242edc 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java index 722baba3..5e157a54 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java index a72ebb0f..8e3713cc 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; @@ -395,22 +395,22 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { int adjust; private int int8(int i) { - return Altos.int8(bytes, i + 1 + adjust); + return AltosLib.int8(bytes, i + 1 + adjust); } private int uint8(int i) { - return Altos.uint8(bytes, i + 1 + adjust); + return AltosLib.uint8(bytes, i + 1 + adjust); } private int int16(int i) { - return Altos.int16(bytes, i + 1 + adjust); + return AltosLib.int16(bytes, i + 1 + adjust); } private int uint16(int i) { - return Altos.uint16(bytes, i + 1 + adjust); + return AltosLib.uint16(bytes, i + 1 + adjust); } private int uint32(int i) { - return Altos.uint32(bytes, i + 1 + adjust); + return AltosLib.uint32(bytes, i + 1 + adjust); } private String string(int i, int l) { - return Altos.string(bytes, i + 1 + adjust, l); + return AltosLib.string(bytes, i + 1 + adjust, l); } static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); @@ -428,7 +428,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.version = 4; adjust = 0; - if (bytes.length == Altos.ao_telemetry_0_8_len + 4) { + if (bytes.length == AltosLib.ao_telemetry_0_8_len + 4) { record.serial = uint8(0); adjust = -1; } else diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java index 80db454d..cddb773d 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java index 08c85e85..43d0f17a 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.lang.*; import java.text.*; @@ -30,27 +30,27 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { long received_time; public int int8(int off) { - return Altos.int8(bytes, off + 1); + return AltosLib.int8(bytes, off + 1); } public int uint8(int off) { - return Altos.uint8(bytes, off + 1); + return AltosLib.uint8(bytes, off + 1); } public int int16(int off) { - return Altos.int16(bytes, off + 1); + return AltosLib.int16(bytes, off + 1); } public int uint16(int off) { - return Altos.uint16(bytes, off + 1); + return AltosLib.uint16(bytes, off + 1); } public int uint32(int off) { - return Altos.uint32(bytes, off + 1); + return AltosLib.uint32(bytes, off + 1); } public String string(int off, int l) { - return Altos.string(bytes, off + 1, l); + return AltosLib.string(bytes, off + 1, l); } public AltosTelemetryRecordRaw(int[] in_bytes) { diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java index 2dd782ad..2526afb6 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { int channels; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java index 96fee81f..cfaf90b0 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { -- cgit v1.2.3 From 40ee170753f4fd422c848e34a8da104683b7c8a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 16:16:51 -0800 Subject: altosui: Clean swing/awt bits out of altoslib Signed-off-by: Keith Packard --- .../altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java | 9 --------- .../src/org/altusmetrum/AltosLib/AltosRecordIterable.java | 8 -------- 2 files changed, 17 deletions(-) diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java index 4c0c7baa..6fd26dfd 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java @@ -17,18 +17,9 @@ package org.altusmetrum.AltosLib; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.*; -import javax.swing.event.*; -import javax.swing.plaf.basic.*; import java.io.*; import java.util.*; import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; public class AltosFrequency { double frequency; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java index abe67aaa..ed1787ed 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java @@ -17,16 +17,8 @@ package org.altusmetrum.AltosLib; -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; public abstract class AltosRecordIterable implements Iterable { public abstract Iterator iterator(); -- cgit v1.2.3 From 3c2f601139d36761de6a8a2210545d082ef16133 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 17:26:59 -0800 Subject: altosui: Complete split out of separate java library Signed-off-by: Keith Packard --- altosui/Altos.java | 1 + altosui/AltosAscent.java | 1 + altosui/AltosBTManage.java | 1 + altosui/AltosCSV.java | 1 + altosui/AltosCSVUI.java | 1 + altosui/AltosChannelMenu.java | 1 + altosui/AltosCompanionInfo.java | 1 + altosui/AltosConfig.java | 1 + altosui/AltosConfigData.java | 1 + altosui/AltosConfigFreqUI.java | 1 + altosui/AltosConfigUI.java | 1 + altosui/AltosConfigureUI.java | 1 + altosui/AltosDataChooser.java | 1 + altosui/AltosDataPointReader.java | 1 + altosui/AltosDebug.java | 1 + altosui/AltosDescent.java | 1 + altosui/AltosDialog.java | 1 + altosui/AltosDisplayThread.java | 1 + altosui/AltosEepromChunk.java | 1 + altosui/AltosEepromDelete.java | 1 + altosui/AltosEepromDownload.java | 1 + altosui/AltosEepromIterable.java | 1 + altosui/AltosEepromList.java | 1 + altosui/AltosEepromLog.java | 1 + altosui/AltosEepromManage.java | 1 + altosui/AltosEepromMonitor.java | 1 + altosui/AltosEepromRecord.java | 1 + altosui/AltosEepromTeleScience.java | 1 + altosui/AltosFile.java | 1 + altosui/AltosFlash.java | 1 + altosui/AltosFlashUI.java | 1 + altosui/AltosFlightInfoTableModel.java | 1 + altosui/AltosFlightReader.java | 1 + altosui/AltosFlightStats.java | 1 + altosui/AltosFlightStatsTable.java | 1 + altosui/AltosFlightStatus.java | 1 + altosui/AltosFlightStatusTableModel.java | 1 + altosui/AltosFlightUI.java | 1 + altosui/AltosFrame.java | 1 + altosui/AltosFreqList.java | 1 + altosui/AltosGraph.java | 1 + altosui/AltosGraphTime.java | 1 + altosui/AltosGraphUI.java | 1 + altosui/AltosGreatCircle.java | 1 + altosui/AltosHexfile.java | 1 + altosui/AltosIdleMonitorUI.java | 1 + altosui/AltosIgnite.java | 1 + altosui/AltosIgniteUI.java | 1 + altosui/AltosInfoTable.java | 1 + altosui/AltosKML.java | 1 + altosui/AltosLanded.java | 1 + altosui/AltosLaunch.java | 1 + altosui/AltosLaunchUI.java | 1 + altosui/AltosLed.java | 1 + altosui/AltosLights.java | 1 + altosui/AltosLog.java | 1 + altosui/AltosPad.java | 1 + altosui/AltosPreferences.java | 383 --------------------- altosui/AltosReader.java | 1 + altosui/AltosReplayReader.java | 1 + altosui/AltosRomconfig.java | 1 + altosui/AltosRomconfigUI.java | 1 + altosui/AltosScanUI.java | 1 + altosui/AltosSerial.java | 1 + altosui/AltosSiteMap.java | 1 + altosui/AltosSiteMapCache.java | 1 + altosui/AltosSiteMapPreload.java | 1 + altosui/AltosSiteMapTile.java | 1 + altosui/AltosState.java | 2 + altosui/AltosTelemetryReader.java | 120 +++++++ altosui/AltosUI.java | 1 + altosui/AltosUIPreferences.java | 23 +- altosui/AltosWriter.java | 2 + altosui/GrabNDrag.java | 1 + altosui/Makefile.am | 53 ++- altosui/altoslib/Makefile.am | 3 +- .../src/org/altusmetrum/AltosLib/AltosConvert.java | 44 +-- .../org/altusmetrum/AltosLib/AltosFrequency.java | 4 +- .../src/org/altusmetrum/AltosLib/AltosGPS.java | 56 +-- .../src/org/altusmetrum/AltosLib/AltosGPSSat.java | 4 +- .../src/org/altusmetrum/AltosLib/AltosParse.java | 14 +- .../org/altusmetrum/AltosLib/AltosPreferences.java | 365 ++++++++++++++++++++ .../src/org/altusmetrum/AltosLib/AltosRecord.java | 128 +++---- .../altusmetrum/AltosLib/AltosRecordCompanion.java | 14 +- .../altusmetrum/AltosLib/AltosTelemetryReader.java | 119 ------- 85 files changed, 734 insertions(+), 669 deletions(-) delete mode 100644 altosui/AltosPreferences.java create mode 100644 altosui/AltosTelemetryReader.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java diff --git a/altosui/Altos.java b/altosui/Altos.java index 3e2a7a40..380796cc 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -96,6 +96,7 @@ public class Altos extends AltosLib { static boolean map_initialized = false; static final int tab_elt_pad = 5; + static Font label_font; static Font value_font; static Font status_font; diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index c8e5f3af..38b3b30f 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosAscent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index 6d460701..d2899d65 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -29,6 +29,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index db398a61..be86a454 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -21,6 +21,7 @@ import java.lang.*; import java.io.*; import java.text.*; import java.util.*; +import org.altusmetrum.AltosLib.*; public class AltosCSV implements AltosWriter { File name; diff --git a/altosui/AltosCSVUI.java b/altosui/AltosCSVUI.java index 6d3e9065..2702668b 100644 --- a/altosui/AltosCSVUI.java +++ b/altosui/AltosCSVUI.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosCSVUI extends AltosDialog diff --git a/altosui/AltosChannelMenu.java b/altosui/AltosChannelMenu.java index abbb86f4..0249a0bd 100644 --- a/altosui/AltosChannelMenu.java +++ b/altosui/AltosChannelMenu.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosChannelMenu extends JComboBox implements ActionListener { int channel; diff --git a/altosui/AltosCompanionInfo.java b/altosui/AltosCompanionInfo.java index 82bde623..4ba8fe98 100644 --- a/altosui/AltosCompanionInfo.java +++ b/altosui/AltosCompanionInfo.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosCompanionInfo extends JTable { private AltosFlightInfoTableModel model; diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index bd930206..35fef080 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 64d9f095..ef34dd3e 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosConfigFreqUI.java b/altosui/AltosConfigFreqUI.java index ecb55449..7958a21c 100644 --- a/altosui/AltosConfigFreqUI.java +++ b/altosui/AltosConfigFreqUI.java @@ -29,6 +29,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; class AltosEditFreqUI extends AltosDialog implements ActionListener { Frame frame; diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index eddb223f..62394fa6 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -28,6 +28,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index 1789cd25..deb179d6 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -30,6 +30,7 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; import javax.swing.plaf.basic.*; +import org.altusmetrum.AltosLib.*; class DelegatingRenderer implements ListCellRenderer { diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index c4a46d01..0d629b3c 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -26,6 +26,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; +import org.altusmetrum.AltosLib.*; public class AltosDataChooser extends JFileChooser { JFrame frame; diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index c3aabb0c..821b0771 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -9,6 +9,7 @@ import java.text.ParseException; import java.lang.UnsupportedOperationException; import java.util.NoSuchElementException; import java.util.Iterator; +import org.altusmetrum.AltosLib.*; class AltosDataPointReader implements Iterable { Iterator iter; diff --git a/altosui/AltosDebug.java b/altosui/AltosDebug.java index ce1cf5dd..23e38bc0 100644 --- a/altosui/AltosDebug.java +++ b/altosui/AltosDebug.java @@ -21,6 +21,7 @@ import java.lang.*; import java.io.*; import java.util.concurrent.*; import java.util.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 0fcd690b..664c5ea6 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosDescent extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosDialog.java b/altosui/AltosDialog.java index 1e8e538c..ff38c3e4 100644 --- a/altosui/AltosDialog.java +++ b/altosui/AltosDialog.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index ce8d9159..03ce4efd 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosDisplayThread extends Thread { diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java index 77707f7b..e4d11658 100644 --- a/altosui/AltosEepromChunk.java +++ b/altosui/AltosEepromChunk.java @@ -21,6 +21,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosEepromChunk { diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index fcce8155..73f3a00f 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 8f7a8544..080bfc99 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index b8e21ece..11cb97e4 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; /* * AltosRecords with an index field so they can be sorted by tick while preserving diff --git a/altosui/AltosEepromList.java b/altosui/AltosEepromList.java index 945746dd..6a656215 100644 --- a/altosui/AltosEepromList.java +++ b/altosui/AltosEepromList.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java index 475d7f12..a24e82c0 100644 --- a/altosui/AltosEepromLog.java +++ b/altosui/AltosEepromLog.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromManage.java b/altosui/AltosEepromManage.java index 1e06f4ca..563c90b3 100644 --- a/altosui/AltosEepromManage.java +++ b/altosui/AltosEepromManage.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromMonitor.java b/altosui/AltosEepromMonitor.java index 34f5b891..75643442 100644 --- a/altosui/AltosEepromMonitor.java +++ b/altosui/AltosEepromMonitor.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosEepromMonitor extends AltosDialog { diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index d8a07951..ea003a1e 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosEepromTeleScience.java b/altosui/AltosEepromTeleScience.java index ee1840b0..0c237e11 100644 --- a/altosui/AltosEepromTeleScience.java +++ b/altosui/AltosEepromTeleScience.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosEepromTeleScience { int type; diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java index e2b6d5a6..4cf7de3c 100644 --- a/altosui/AltosFile.java +++ b/altosui/AltosFile.java @@ -20,6 +20,7 @@ package altosui; import java.lang.*; import java.io.File; import java.util.*; +import org.altusmetrum.AltosLib.*; class AltosFile extends File { diff --git a/altosui/AltosFlash.java b/altosui/AltosFlash.java index e91e9806..bd0c8a50 100644 --- a/altosui/AltosFlash.java +++ b/altosui/AltosFlash.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosFlash { File file; diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index f91c542d..4ab73a6d 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlashUI extends AltosDialog diff --git a/altosui/AltosFlightInfoTableModel.java b/altosui/AltosFlightInfoTableModel.java index e23eff68..77969a89 100644 --- a/altosui/AltosFlightInfoTableModel.java +++ b/altosui/AltosFlightInfoTableModel.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosFlightInfoTableModel extends AbstractTableModel { final static private String[] columnNames = {"Field", "Value"}; diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java index 3ddf171d..1ac9f848 100644 --- a/altosui/AltosFlightReader.java +++ b/altosui/AltosFlightReader.java @@ -21,6 +21,7 @@ import java.lang.*; import java.text.*; import java.io.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlightReader { String name; diff --git a/altosui/AltosFlightStats.java b/altosui/AltosFlightStats.java index 578be3f9..ab094c80 100644 --- a/altosui/AltosFlightStats.java +++ b/altosui/AltosFlightStats.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlightStats { double max_height; diff --git a/altosui/AltosFlightStatsTable.java b/altosui/AltosFlightStatsTable.java index 2d34c6e2..c311b231 100644 --- a/altosui/AltosFlightStatsTable.java +++ b/altosui/AltosFlightStatsTable.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlightStatsTable extends JComponent { GridBagLayout layout; diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 45e55b4b..6a351004 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosFlightStatus extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosFlightStatusTableModel.java b/altosui/AltosFlightStatusTableModel.java index 4c24b6ac..75bf16eb 100644 --- a/altosui/AltosFlightStatusTableModel.java +++ b/altosui/AltosFlightStatusTableModel.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosFlightStatusTableModel extends AbstractTableModel { private String[] columnNames = {"Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 5c6e0629..ddc54cbd 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlightUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { AltosVoice voice; diff --git a/altosui/AltosFrame.java b/altosui/AltosFrame.java index 36ddcae9..70598634 100644 --- a/altosui/AltosFrame.java +++ b/altosui/AltosFrame.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosFreqList.java b/altosui/AltosFreqList.java index e4135df7..1bbc97c6 100644 --- a/altosui/AltosFreqList.java +++ b/altosui/AltosFreqList.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosFreqList extends JComboBox { diff --git a/altosui/AltosGraph.java b/altosui/AltosGraph.java index fbcefd61..54d2bb0b 100644 --- a/altosui/AltosGraph.java +++ b/altosui/AltosGraph.java @@ -8,6 +8,7 @@ import java.io.*; import org.jfree.chart.JFreeChart; import org.jfree.chart.ChartUtilities; +import org.altusmetrum.AltosLib.*; abstract class AltosGraph { public String filename; diff --git a/altosui/AltosGraphTime.java b/altosui/AltosGraphTime.java index 6a084b2c..0955f6e6 100644 --- a/altosui/AltosGraphTime.java +++ b/altosui/AltosGraphTime.java @@ -12,6 +12,7 @@ import java.text.*; import java.awt.Color; import java.util.ArrayList; import java.util.HashMap; +import org.altusmetrum.AltosLib.*; import org.jfree.chart.ChartUtilities; import org.jfree.chart.JFreeChart; diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index c30dc476..527a7d28 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -12,6 +12,7 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; +import org.altusmetrum.AltosLib.*; import org.jfree.chart.ChartPanel; import org.jfree.chart.ChartUtilities; diff --git a/altosui/AltosGreatCircle.java b/altosui/AltosGreatCircle.java index fb1b6ab3..e4af3c18 100644 --- a/altosui/AltosGreatCircle.java +++ b/altosui/AltosGreatCircle.java @@ -18,6 +18,7 @@ package altosui; import java.lang.Math; +import org.altusmetrum.AltosLib.*; public class AltosGreatCircle { double distance; diff --git a/altosui/AltosHexfile.java b/altosui/AltosHexfile.java index 19e35ae1..d52b46c3 100644 --- a/altosui/AltosHexfile.java +++ b/altosui/AltosHexfile.java @@ -23,6 +23,7 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.LinkedList; import java.util.Iterator; import java.util.Arrays; +import org.altusmetrum.AltosLib.*; class HexFileInputStream extends PushbackInputStream { public int line; diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 8eb0d520..02295ea9 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; class AltosADC { int tick; diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index 3e52ea36..c0cd44f1 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -25,6 +25,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; import javax.swing.event.*; +import org.altusmetrum.AltosLib.*; public class AltosIgnite { AltosDevice device; diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 8623cbef..076d99b2 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -28,6 +28,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosIgniteUI extends AltosDialog diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index c023369e..aa6a6d4e 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosInfoTable extends JTable { private AltosFlightInfoTableModel model; diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java index 6bdbecca..2993607b 100644 --- a/altosui/AltosKML.java +++ b/altosui/AltosKML.java @@ -21,6 +21,7 @@ import java.lang.*; import java.io.*; import java.text.*; import java.util.*; +import org.altusmetrum.AltosLib.*; public class AltosKML implements AltosWriter { diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 4dd9a2dd..a47e1cbd 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosLanded extends JComponent implements AltosFlightDisplay, ActionListener { GridBagLayout layout; diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java index 77f681b8..0e493b91 100644 --- a/altosui/AltosLaunch.java +++ b/altosui/AltosLaunch.java @@ -25,6 +25,7 @@ import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; import javax.swing.event.*; +import org.altusmetrum.AltosLib.*; public class AltosLaunch { AltosDevice device; diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index a6c36604..eb76243d 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -28,6 +28,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; class FireButton extends JButton { protected void processMouseEvent(MouseEvent e) { diff --git a/altosui/AltosLed.java b/altosui/AltosLed.java index e08e9960..1358cd48 100644 --- a/altosui/AltosLed.java +++ b/altosui/AltosLed.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosLed extends JLabel { ImageIcon on, off; diff --git a/altosui/AltosLights.java b/altosui/AltosLights.java index 2fa38412..8bd9e7de 100644 --- a/altosui/AltosLights.java +++ b/altosui/AltosLights.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosLights extends JComponent { diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java index a5f1830d..740f0be6 100644 --- a/altosui/AltosLog.java +++ b/altosui/AltosLog.java @@ -22,6 +22,7 @@ import java.lang.*; import java.util.*; import java.text.ParseException; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; /* * This creates a thread to capture telemetry data and write it to diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index 6ef66f7a..0a3f3d65 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; public class AltosPad extends JComponent implements AltosFlightDisplay { GridBagLayout layout; diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java deleted file mode 100644 index 7510c7c2..00000000 --- a/altosui/AltosPreferences.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.awt.Component; -import javax.swing.*; -import javax.swing.filechooser.FileSystemView; - -class AltosPreferences { - public static Preferences preferences; - - /* logdir preference name */ - final static String logdirPreference = "LOGDIR"; - - /* channel preference name */ - final static String channelPreferenceFormat = "CHANNEL-%d"; - - /* frequency preference name */ - final static String frequencyPreferenceFormat = "FREQUENCY-%d"; - - /* telemetry format preference name */ - final static String telemetryPreferenceFormat = "TELEMETRY-%d"; - - /* voice preference name */ - final static String voicePreference = "VOICE"; - - /* callsign preference name */ - final static String callsignPreference = "CALLSIGN"; - - /* firmware directory preference name */ - final static String firmwaredirPreference = "FIRMWARE"; - - /* serial debug preference name */ - final static String serialDebugPreference = "SERIAL-DEBUG"; - - /* scanning telemetry preferences name */ - final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; - - /* Launcher serial preference name */ - final static String launcherSerialPreference = "LAUNCHER-SERIAL"; - - /* Launcher channel preference name */ - final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; - - /* Default logdir is ~/TeleMetrum */ - final static String logdirName = "TeleMetrum"; - - /* Log directory */ - static File logdir; - - /* Map directory -- hangs of logdir */ - static File mapdir; - - /* Frequency (map serial to frequency) */ - static Hashtable frequencies; - - /* Telemetry (map serial to telemetry format) */ - static Hashtable telemetries; - - /* Voice preference */ - static boolean voice; - - /* Callsign preference */ - static String callsign; - - /* Firmware directory */ - static File firmwaredir; - - /* Serial debug */ - static boolean serial_debug; - - /* Scanning telemetry */ - static int scanning_telemetry; - - /* List of frequencies */ - final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; - static AltosFrequency[] common_frequencies; - - final static String frequency_count = "COUNT"; - final static String frequency_format = "FREQUENCY-%d"; - final static String description_format = "DESCRIPTION-%d"; - - static AltosFrequency[] load_common_frequencies() { - AltosFrequency[] frequencies = null; - boolean existing = false; - try { - existing = preferences.nodeExists(common_frequencies_node_name); - } catch (BackingStoreException be) { - existing = false; - } - if (existing) { - Preferences node = preferences.node(common_frequencies_node_name); - int count = node.getInt(frequency_count, 0); - - frequencies = new AltosFrequency[count]; - for (int i = 0; i < count; i++) { - double frequency; - String description; - - frequency = node.getDouble(String.format(frequency_format, i), 0.0); - description = node.get(String.format(description_format, i), null); - frequencies[i] = new AltosFrequency(frequency, description); - } - } else { - frequencies = new AltosFrequency[10]; - for (int i = 0; i < 10; i++) { - frequencies[i] = new AltosFrequency(434.550 + i * .1, - String.format("Channel %d", i)); - } - } - return frequencies; - } - - static void save_common_frequencies(AltosFrequency[] frequencies) { - Preferences node = preferences.node(common_frequencies_node_name); - - node.putInt(frequency_count, frequencies.length); - for (int i = 0; i < frequencies.length; i++) { - node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); - node.put(String.format(description_format, i), frequencies[i].description); - } - } - static int launcher_serial; - - static int launcher_channel; - - public static void init() { - preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - - /* Initialize logdir from preferences */ - String logdir_string = preferences.get(logdirPreference, null); - if (logdir_string != null) - logdir = new File(logdir_string); - else { - /* Use the file system view default directory */ - logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); - if (!logdir.exists()) - logdir.mkdirs(); - } - mapdir = new File(logdir, "maps"); - if (!mapdir.exists()) - mapdir.mkdirs(); - - frequencies = new Hashtable(); - - telemetries = new Hashtable(); - - voice = preferences.getBoolean(voicePreference, true); - - callsign = preferences.get(callsignPreference,"N0CALL"); - - scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << Altos.ao_telemetry_standard)); - - launcher_serial = preferences.getInt(launcherSerialPreference, 0); - - launcher_channel = preferences.getInt(launcherChannelPreference, 0); - - String firmwaredir_string = preferences.get(firmwaredirPreference, null); - if (firmwaredir_string != null) - firmwaredir = new File(firmwaredir_string); - else - firmwaredir = null; - - serial_debug = preferences.getBoolean(serialDebugPreference, false); - AltosSerial.set_debug(serial_debug); - - common_frequencies = load_common_frequencies(); - - } - - static { init(); } - - static void flush_preferences() { - try { - preferences.flush(); - } catch (BackingStoreException ee) { -/* - if (component != null) - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); - else -*/ - System.err.printf("Cannot save preferences\n"); - } - } - - public static void set_logdir(File new_logdir) { - logdir = new_logdir; - mapdir = new File(logdir, "maps"); - if (!mapdir.exists()) - mapdir.mkdirs(); - synchronized (preferences) { - preferences.put(logdirPreference, logdir.getPath()); - flush_preferences(); - } - } - - public static File logdir() { - return logdir; - } - - public static File mapdir() { - return mapdir; - } - - public static void set_frequency(int serial, double new_frequency) { - frequencies.put(serial, new_frequency); - synchronized (preferences) { - preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); - flush_preferences(); - } - } - - public static double frequency(int serial) { - if (frequencies.containsKey(serial)) - return frequencies.get(serial); - double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); - if (frequency == 0.0) { - int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); - frequency = AltosConvert.radio_channel_to_frequency(channel); - } - frequencies.put(serial, frequency); - return frequency; - } - - public static void set_telemetry(int serial, int new_telemetry) { - telemetries.put(serial, new_telemetry); - synchronized (preferences) { - preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); - flush_preferences(); - } - } - - public static int telemetry(int serial) { - if (telemetries.containsKey(serial)) - return telemetries.get(serial); - int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - Altos.ao_telemetry_standard); - telemetries.put(serial, telemetry); - return telemetry; - } - - public static void set_scanning_telemetry(int new_scanning_telemetry) { - scanning_telemetry = new_scanning_telemetry; - synchronized (preferences) { - preferences.putInt(scanningTelemetryPreference, scanning_telemetry); - flush_preferences(); - } - } - - public static int scanning_telemetry() { - return scanning_telemetry; - } - - public static void set_voice(boolean new_voice) { - voice = new_voice; - synchronized (preferences) { - preferences.putBoolean(voicePreference, voice); - flush_preferences(); - } - } - - public static boolean voice() { - return voice; - } - - public static void set_callsign(String new_callsign) { - callsign = new_callsign; - synchronized(preferences) { - preferences.put(callsignPreference, callsign); - flush_preferences(); - } - } - - public static String callsign() { - return callsign; - } - - public static void set_firmwaredir(File new_firmwaredir) { - firmwaredir = new_firmwaredir; - synchronized (preferences) { - preferences.put(firmwaredirPreference, firmwaredir.getPath()); - flush_preferences(); - } - } - - public static File firmwaredir() { - return firmwaredir; - } - - public static void set_serial_debug(boolean new_serial_debug) { - serial_debug = new_serial_debug; - AltosSerial.set_debug(serial_debug); - synchronized (preferences) { - preferences.putBoolean(serialDebugPreference, serial_debug); - flush_preferences(); - } - } - - public static boolean serial_debug() { - return serial_debug; - } - - public static void set_launcher_serial(int new_launcher_serial) { - launcher_serial = new_launcher_serial; - System.out.printf("set launcher serial to %d\n", new_launcher_serial); - synchronized (preferences) { - preferences.putInt(launcherSerialPreference, launcher_serial); - flush_preferences(); - } - } - - public static int launcher_serial() { - return launcher_serial; - } - - public static void set_launcher_channel(int new_launcher_channel) { - launcher_channel = new_launcher_channel; - System.out.printf("set launcher channel to %d\n", new_launcher_channel); - synchronized (preferences) { - preferences.putInt(launcherChannelPreference, launcher_channel); - flush_preferences(); - } - } - - public static int launcher_channel() { - return launcher_channel; - } - - public static Preferences bt_devices() { - return preferences.node("bt_devices"); - } - - public static AltosFrequency[] common_frequencies() { - return common_frequencies; - } - - public static void set_common_frequencies(AltosFrequency[] frequencies) { - common_frequencies = frequencies; - synchronized(preferences) { - save_common_frequencies(frequencies); - flush_preferences(); - } - } - - public static void add_common_frequency(AltosFrequency frequency) { - AltosFrequency[] new_frequencies = new AltosFrequency[common_frequencies.length + 1]; - int i; - - for (i = 0; i < common_frequencies.length; i++) { - if (frequency.frequency == common_frequencies[i].frequency) - return; - if (frequency.frequency < common_frequencies[i].frequency) - break; - new_frequencies[i] = common_frequencies[i]; - } - new_frequencies[i] = frequency; - for (; i < common_frequencies.length; i++) - new_frequencies[i+1] = common_frequencies[i]; - set_common_frequencies(new_frequencies); - } -} diff --git a/altosui/AltosReader.java b/altosui/AltosReader.java index b9280a0c..aafd5f81 100644 --- a/altosui/AltosReader.java +++ b/altosui/AltosReader.java @@ -20,6 +20,7 @@ package altosui; import java.io.*; import java.util.*; import java.text.*; +import org.altusmetrum.AltosLib.*; public class AltosReader { public AltosRecord read() throws IOException, ParseException { return null; } diff --git a/altosui/AltosReplayReader.java b/altosui/AltosReplayReader.java index eed56cff..f92c0328 100644 --- a/altosui/AltosReplayReader.java +++ b/altosui/AltosReplayReader.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; +import org.altusmetrum.AltosLib.*; /* * Open an existing telemetry file and replay it in realtime diff --git a/altosui/AltosRomconfig.java b/altosui/AltosRomconfig.java index 55056b5e..0a283e51 100644 --- a/altosui/AltosRomconfig.java +++ b/altosui/AltosRomconfig.java @@ -17,6 +17,7 @@ package altosui; import java.io.*; +import org.altusmetrum.AltosLib.*; public class AltosRomconfig { public boolean valid; diff --git a/altosui/AltosRomconfigUI.java b/altosui/AltosRomconfigUI.java index e4e38c9c..306b8623 100644 --- a/altosui/AltosRomconfigUI.java +++ b/altosui/AltosRomconfigUI.java @@ -27,6 +27,7 @@ import java.io.*; import java.util.*; import java.text.*; import java.util.prefs.*; +import org.altusmetrum.AltosLib.*; public class AltosRomconfigUI extends AltosDialog diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 2b9137d8..1be8aa26 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -28,6 +28,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; class AltosScanResult { String callsign; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index afb9f21a..74e945f3 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -31,6 +31,7 @@ import java.awt.event.*; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; import javax.swing.table.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index 93c54d02..b57edcab 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -32,6 +32,7 @@ import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { // preferred vertical step in a tile in naut. miles diff --git a/altosui/AltosSiteMapCache.java b/altosui/AltosSiteMapCache.java index 2e62cc45..f729a298 100644 --- a/altosui/AltosSiteMapCache.java +++ b/altosui/AltosSiteMapCache.java @@ -29,6 +29,7 @@ import java.text.*; import java.util.prefs.*; import java.net.URL; import java.net.URLConnection; +import org.altusmetrum.AltosLib.*; public class AltosSiteMapCache extends JLabel { public static boolean fetchMap(File file, String url) { diff --git a/altosui/AltosSiteMapPreload.java b/altosui/AltosSiteMapPreload.java index 5de7a05e..676b0790 100644 --- a/altosui/AltosSiteMapPreload.java +++ b/altosui/AltosSiteMapPreload.java @@ -33,6 +33,7 @@ import java.awt.geom.Point2D; import java.awt.geom.Line2D; import java.net.URL; import java.net.URLConnection; +import org.altusmetrum.AltosLib.*; class AltosMapPos extends Box { AltosUI owner; diff --git a/altosui/AltosSiteMapTile.java b/altosui/AltosSiteMapTile.java index 9e62bb47..34550219 100644 --- a/altosui/AltosSiteMapTile.java +++ b/altosui/AltosSiteMapTile.java @@ -30,6 +30,7 @@ import java.util.prefs.*; import java.lang.Math; import java.awt.geom.Point2D; import java.awt.geom.Line2D; +import org.altusmetrum.AltosLib.*; public class AltosSiteMapTile extends JLayeredPane { JLabel mapLabel; diff --git a/altosui/AltosState.java b/altosui/AltosState.java index 9c6f85eb..403c74be 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -21,6 +21,8 @@ package altosui; +import org.altusmetrum.AltosLib.*; + public class AltosState { AltosRecord data; diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java new file mode 100644 index 00000000..dc7e4a75 --- /dev/null +++ b/altosui/AltosTelemetryReader.java @@ -0,0 +1,120 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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.text.*; +import java.io.*; +import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; + +class AltosTelemetryReader extends AltosFlightReader { + AltosDevice device; + AltosSerial serial; + AltosLog log; + AltosRecord previous; + double frequency; + int telemetry; + + LinkedBlockingQueue telem; + + AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { + AltosLine l = telem.take(); + if (l.line == null) + throw new IOException("IO error"); + AltosRecord next = AltosTelemetry.parse(l.line, previous); + previous = next; + return next; + } + + void flush() { + telem.clear(); + } + + void close(boolean interrupted) { + serial.remove_monitor(telem); + log.close(); + serial.close(); + } + + public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + serial.set_radio_frequency(frequency); + } + + public boolean supports_telemetry(int telemetry) { + + try { + /* Version 1.0 or later firmware supports all telemetry formats */ + if (serial.config_data().compare_version("1.0") >= 0) + return true; + + /* Version 0.9 firmware only supports 0.9 telemetry */ + if (serial.config_data().compare_version("0.9") >= 0) { + if (telemetry == Altos.ao_telemetry_0_9) + return true; + else + return false; + } + + /* Version 0.8 firmware only supports 0.8 telemetry */ + if (telemetry == Altos.ao_telemetry_0_8) + return true; + else + return false; + } catch (InterruptedException ie) { + return true; + } catch (TimeoutException te) { + return true; + } + } + + void save_frequency() { + AltosPreferences.set_frequency(device.getSerial(), frequency); + } + + void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + serial.set_telemetry(telemetry); + } + + void save_telemetry() { + AltosPreferences.set_telemetry(device.getSerial(), telemetry); + } + + File backing_file() { + return log.file(); + } + + public AltosTelemetryReader (AltosDevice in_device) + throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { + device = in_device; + serial = new AltosSerial(device); + log = new AltosLog(serial); + name = device.toShortString(); + previous = null; + + telem = new LinkedBlockingQueue(); + frequency = AltosPreferences.frequency(device.getSerial()); + set_frequency(frequency); + telemetry = AltosPreferences.telemetry(device.getSerial()); + set_telemetry(telemetry); + serial.set_callsign(AltosUIPreferences.callsign()); + serial.add_monitor(telem); + } +} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index a2816a3a..25c6c36b 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; import libaltosJNI.*; diff --git a/altosui/AltosUIPreferences.java b/altosui/AltosUIPreferences.java index da6c3968..38af734e 100644 --- a/altosui/AltosUIPreferences.java +++ b/altosui/AltosUIPreferences.java @@ -25,10 +25,9 @@ import java.util.concurrent.LinkedBlockingQueue; import java.awt.Component; import javax.swing.*; import javax.swing.filechooser.FileSystemView; +import org.altusmetrum.AltosLib.*; -/* import org.altusmetrum.AltosLib.*; */ - -class AltosUIPreferences extends AltosPreferences { +public class AltosUIPreferences extends AltosPreferences { /* font size preferences name */ final static String fontSizePreference = "FONT-SIZE"; @@ -47,6 +46,9 @@ class AltosUIPreferences extends AltosPreferences { static String look_and_feel = null; + /* Serial debug */ + static boolean serial_debug; + public static void init() { font_listeners = new LinkedList(); @@ -55,6 +57,8 @@ class AltosUIPreferences extends AltosPreferences { look_and_feel = preferences.get(lookAndFeelPreference, UIManager.getSystemLookAndFeelClassName()); ui_listeners = new LinkedList(); + serial_debug = preferences.getBoolean(serialDebugPreference, false); + AltosSerial.set_debug(serial_debug); } static { init(); } @@ -156,4 +160,17 @@ class AltosUIPreferences extends AltosPreferences { ui_listeners.remove(l); } } + public static void set_serial_debug(boolean new_serial_debug) { + serial_debug = new_serial_debug; + AltosSerial.set_debug(serial_debug); + synchronized (preferences) { + preferences.putBoolean(serialDebugPreference, serial_debug); + flush_preferences(); + } + } + + public static boolean serial_debug() { + return serial_debug; + } + } \ No newline at end of file diff --git a/altosui/AltosWriter.java b/altosui/AltosWriter.java index a172dff0..b7375204 100644 --- a/altosui/AltosWriter.java +++ b/altosui/AltosWriter.java @@ -21,6 +21,8 @@ import java.lang.*; import java.io.*; import java.text.*; import java.util.*; +import org.altusmetrum.AltosLib.*; + public interface AltosWriter { diff --git a/altosui/GrabNDrag.java b/altosui/GrabNDrag.java index e6b87b58..c350efec 100644 --- a/altosui/GrabNDrag.java +++ b/altosui/GrabNDrag.java @@ -27,6 +27,7 @@ import javax.swing.table.*; import java.io.*; import java.util.*; import java.text.*; +import org.altusmetrum.AltosLib.*; class GrabNDrag extends MouseInputAdapter { private JComponent scroll; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index c3fd6bb6..cfe45302 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:altoslib/bin:libaltos:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -66,10 +66,7 @@ altosui_JAVA = \ AltosFlightStatusUpdate.java \ AltosFlightUI.java \ AltosFontListener.java \ - AltosFrequency.java \ AltosFreqList.java \ - AltosGPS.java \ - AltosGPSSat.java \ AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ @@ -83,27 +80,11 @@ altosui_JAVA = \ AltosLanded.java \ AltosLed.java \ AltosLights.java \ - AltosLine.java \ AltosLog.java \ AltosPad.java \ - AltosParse.java \ - AltosUIPreferences.java \ - AltosPreferences.java \ AltosUIPreferences.java \ AltosReader.java \ - AltosRecord.java \ - AltosRecordCompanion.java \ - AltosRecordIterable.java \ AltosTelemetryReader.java \ - AltosTelemetryRecord.java \ - AltosTelemetryRecordRaw.java \ - AltosTelemetryRecordSensor.java \ - AltosTelemetryRecordConfiguration.java \ - AltosTelemetryRecordLocation.java \ - AltosTelemetryRecordSatellite.java \ - AltosTelemetryRecordCompanion.java \ - AltosTelemetryRecordLegacy.java \ - AltosTelemetryMap.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ @@ -116,8 +97,7 @@ altosui_JAVA = \ AltosSiteMapCache.java \ AltosSiteMapTile.java \ AltosState.java \ - AltosTelemetry.java \ - AltosTelemetryIterable.java \ + AltosTelemetryReader.java \ AltosUI.java \ AltosUIListener.java \ AltosFrame.java \ @@ -148,6 +128,9 @@ FREETTS_CLASS= \ en_us.jar \ freetts.jar +ALTOSLIB_CLASS=\ + AltosLib.jar + LIBALTOS= \ libaltos.so \ libaltos.dylib \ @@ -200,7 +183,7 @@ 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) $(JFREECHART_CLASS) $(JCOMMON_CLASS) +FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=altosui-fat @@ -214,7 +197,7 @@ all-local: classes/altosui $(JAR) altosui altosui-test altosui-jdb clean-local: -rm -rf classes $(JAR) $(FATJAR) \ - $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(FREETTS_CLASS) \ + $(LINUX_DIST) $(MACOSX_DIST) windows $(WINDOWS_DIST) $(ALTOSLIB_CLASS) $(FREETTS_CLASS) \ $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) Manifest.txt Manifest-fat.txt altos-windows.log \ altosui altosui-test altosui-jdb macosx linux @@ -256,13 +239,13 @@ install-altosuiJAVA: altosui.jar classes/altosui: mkdir -p classes/altosui -$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) +$(JAR): classaltosui.stamp Manifest.txt $(JAVA_ICON) $(ALTOSLIB_CLASS) jar cfm $@ Manifest.txt \ $(ICONJAR) \ -C classes altosui \ -C libaltos libaltosJNI -$(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) +$(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCOMMON_CLASS) $(LIBALTOS) $(JAVA_ICON) jar cfm $@ Manifest-fat.txt \ $(ICONJAR) \ -C classes altosui \ @@ -270,11 +253,11 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(FREETTS_CLASS) $(JFREECHART_CLA Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ + echo "Class-Path: altoslib.jar $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: freetts.jar jfreechart.jar jcommon.jar" >> $@ + echo "Class-Path: altoslib.jar freetts.jar jfreechart.jar jcommon.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@ @@ -283,7 +266,7 @@ altosui: Makefile altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp "$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + echo 'exec java -cp ":altoslib/*:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ altosui-jdb: Makefile @@ -317,6 +300,10 @@ build-altos-dll: build-altos64-dll: +cd libaltos && make altos64.dll +$(ALTOSLIB_CLASS): + -rm -f "$@" + $(LN_S) altoslib/"$@" . + $(FREETTS_CLASS): -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . @@ -345,9 +332,11 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) 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 $(JFREECHART_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java - cp -p $(JCOMMON_CLASS) libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java + cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java + cp -p $(ALTOSLIB_CLASS) macosx/AltosUI.app/Contents/Resources/Java + cp -p $(FREETTS_CLASS) macosx/AltosUI.app/Contents/Resources/Java + cp -p $(JFREECHART_CLASS) macosx/AltosUI.app/Contents/Resources/Java + cp -p $(JCOMMON_CLASS) macosx/AltosUI.app/Contents/Resources/Java cp -p $(MACOSX_EXTRA) macosx/AltOS cd macosx && zip -r ../$@ AltosUI.app AltOS diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index 9c655131..967c8d06 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -18,11 +18,12 @@ AltosLib_JAVA = \ $(SRC)/AltosGPSSat.java \ $(SRC)/AltosLine.java \ $(SRC)/AltosParse.java \ + $(SRC)/AltosPreferences.java \ $(SRC)/AltosRecordCompanion.java \ $(SRC)/AltosRecordIterable.java \ $(SRC)/AltosRecord.java \ - $(SRC)/AltosTelemetryIterable.java \ $(SRC)/AltosTelemetry.java \ + $(SRC)/AltosTelemetryIterable.java \ $(SRC)/AltosTelemetryMap.java \ $(SRC)/AltosTelemetryRecordCompanion.java \ $(SRC)/AltosTelemetryRecordConfiguration.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java index 6773ab7e..3527b575 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java @@ -41,27 +41,27 @@ public class AltosConvert { * in Joules/(kilogram-Kelvin). */ - static final double GRAVITATIONAL_ACCELERATION = -9.80665; - static final double AIR_GAS_CONSTANT = 287.053; - static final double NUMBER_OF_LAYERS = 7; - static final double MAXIMUM_ALTITUDE = 84852.0; - static final double MINIMUM_PRESSURE = 0.3734; - static final double LAYER0_BASE_TEMPERATURE = 288.15; - static final double LAYER0_BASE_PRESSURE = 101325; + public static final double GRAVITATIONAL_ACCELERATION = -9.80665; + public static final double AIR_GAS_CONSTANT = 287.053; + public static final double NUMBER_OF_LAYERS = 7; + public static final double MAXIMUM_ALTITUDE = 84852.0; + public static final double MINIMUM_PRESSURE = 0.3734; + public static final double LAYER0_BASE_TEMPERATURE = 288.15; + public static final double LAYER0_BASE_PRESSURE = 101325; /* lapse rate and base altitude for each layer in the atmosphere */ - static final double[] lapse_rate = { + public static final double[] lapse_rate = { -0.0065, 0.0, 0.001, 0.0028, 0.0, -0.0028, -0.002 }; - static final int[] base_altitude = { + public static final int[] base_altitude = { 0, 11000, 20000, 32000, 47000, 51000, 71000 }; /* outputs atmospheric pressure associated with the given altitude. * altitudes are measured with respect to the mean sea level */ - static double + public static double altitude_to_pressure(double altitude) { double base_temperature = LAYER0_BASE_TEMPERATURE; @@ -114,7 +114,7 @@ public class AltosConvert { /* outputs the altitude associated with the given pressure. the altitude returned is measured with respect to the mean sea level */ - static double + public static double pressure_to_altitude(double pressure) { @@ -178,19 +178,19 @@ public class AltosConvert { return altitude; } - static double + public static double cc_battery_to_voltage(double battery) { return battery / 32767.0 * 5.0; } - static double + public static double cc_ignitor_to_voltage(double ignite) { return ignite / 32767 * 15.0; } - static double radio_to_frequency(int freq, int setting, int cal, int channel) { + public static double radio_to_frequency(int freq, int setting, int cal, int channel) { double f; if (freq > 0) @@ -205,13 +205,13 @@ public class AltosConvert { return f + channel * 0.100; } - static int radio_frequency_to_setting(double frequency, int cal) { + public static int radio_frequency_to_setting(double frequency, int cal) { double set = frequency / 434.550 * cal; return (int) Math.floor (set + 0.5); } - static int radio_frequency_to_channel(double frequency) { + public static int radio_frequency_to_channel(double frequency) { int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); if (channel < 0) @@ -221,11 +221,11 @@ public class AltosConvert { return channel; } - static double radio_channel_to_frequency(int channel) { + public static double radio_channel_to_frequency(int channel) { return 434.550 + channel * 0.100; } - static int[] ParseHex(String line) { + public static int[] ParseHex(String line) { String[] tokens = line.split("\\s+"); int[] array = new int[tokens.length]; @@ -238,19 +238,19 @@ public class AltosConvert { return array; } - static double meters_to_feet(double meters) { + public static double meters_to_feet(double meters) { return meters * (100 / (2.54 * 12)); } - static double meters_to_mach(double meters) { + public static double meters_to_mach(double meters) { return meters / 343; /* something close to mach at usual rocket sites */ } - static double meters_to_g(double meters) { + public static double meters_to_g(double meters) { return meters / 9.80665; } - static int checksum(int[] data, int start, int length) { + public static int checksum(int[] data, int start, int length) { int csum = 0x5a; for (int i = 0; i < length; i++) csum += data[i + start]; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java index 6fd26dfd..f08ff116 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java @@ -22,8 +22,8 @@ import java.util.*; import java.text.*; public class AltosFrequency { - double frequency; - String description; + public double frequency; + public String description; public String toString() { return String.format("%7.3f MHz %-20s", diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java index 8cc7aa69..f078a469 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java @@ -22,32 +22,32 @@ import java.text.*; public class AltosGPS { - final static int MISSING = AltosRecord.MISSING; - - int nsat; - boolean locked; - boolean connected; - double lat; /* degrees (+N -S) */ - double lon; /* degrees (+E -W) */ - int alt; /* m */ - int year; - int month; - int day; - int hour; - int minute; - int second; - - double ground_speed; /* m/s */ - int course; /* degrees */ - double climb_rate; /* m/s */ - double hdop; /* unitless */ - double vdop; /* unitless */ - int h_error; /* m */ - int v_error; /* m */ - - AltosGPSSat[] cc_gps_sat; /* tracking data */ - - void ParseGPSDate(String date) throws ParseException { + public final static int MISSING = AltosRecord.MISSING; + + public int nsat; + public boolean locked; + public boolean connected; + public double lat; /* degrees (+N -S) */ + public double lon; /* degrees (+E -W) */ + public int alt; /* m */ + public int year; + public int month; + public int day; + public int hour; + public int minute; + public int second; + + public double ground_speed; /* m/s */ + public int course; /* degrees */ + public double climb_rate; /* m/s */ + public double hdop; /* unitless */ + public double vdop; /* unitless */ + public int h_error; /* m */ + public int v_error; /* m */ + + public AltosGPSSat[] cc_gps_sat; /* tracking data */ + + public 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); @@ -56,7 +56,7 @@ public class AltosGPS { day = AltosParse.parse_int(ymd[2]); } - void ParseGPSTime(String time) throws ParseException { + public 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); @@ -65,7 +65,7 @@ public class AltosGPS { second = AltosParse.parse_int(hms[2]); } - void ClearGPSTime() { + public void ClearGPSTime() { year = month = day = 0; hour = minute = second = 0; } diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java index 5fa8f987..faa1ec8d 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java @@ -18,8 +18,8 @@ package org.altusmetrum.AltosLib; public class AltosGPSSat { - int svid; - int c_n0; + public int svid; + public int c_n0; public AltosGPSSat(int s, int c) { svid = s; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java index 4c0a59cb..7d832f1a 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java @@ -21,11 +21,11 @@ import java.text.*; import java.lang.*; public class AltosParse { - static boolean isdigit(char c) { + public static boolean isdigit(char c) { return '0' <= c && c <= '9'; } - static int parse_int(String v) throws ParseException { + public static int parse_int(String v) throws ParseException { try { return AltosLib.fromdec(v); } catch (NumberFormatException e) { @@ -33,7 +33,7 @@ public class AltosParse { } } - static int parse_hex(String v) throws ParseException { + public static int parse_hex(String v) throws ParseException { try { return AltosLib.fromhex(v); } catch (NumberFormatException e) { @@ -41,7 +41,7 @@ public class AltosParse { } } - static double parse_double(String v) throws ParseException { + public static double parse_double(String v) throws ParseException { try { return Double.parseDouble(v); } catch (NumberFormatException e) { @@ -49,7 +49,7 @@ public class AltosParse { } } - static double parse_coord(String coord) throws ParseException { + public static double parse_coord(String coord) throws ParseException { String[] dsf = coord.split("\\D+"); if (dsf.length != 3) { @@ -65,13 +65,13 @@ public class AltosParse { return r; } - static String strip_suffix(String v, String suffix) { + public static String strip_suffix(String v, String suffix) { if (v.endsWith(suffix)) return v.substring(0, v.length() - suffix.length()); return v; } - static void word(String v, String m) throws ParseException { + public static void word(String v, String m) throws ParseException { if (!v.equals(m)) { throw new ParseException("error matching '" + v + "' '" + m + "'", 0); } diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java new file mode 100644 index 00000000..43c7088d --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java @@ -0,0 +1,365 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.awt.Component; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; + +public class AltosPreferences { + public static Preferences preferences; + + /* logdir preference name */ + public final static String logdirPreference = "LOGDIR"; + + /* channel preference name */ + public final static String channelPreferenceFormat = "CHANNEL-%d"; + + /* frequency preference name */ + public final static String frequencyPreferenceFormat = "FREQUENCY-%d"; + + /* telemetry format preference name */ + public final static String telemetryPreferenceFormat = "TELEMETRY-%d"; + + /* voice preference name */ + public final static String voicePreference = "VOICE"; + + /* callsign preference name */ + public final static String callsignPreference = "CALLSIGN"; + + /* firmware directory preference name */ + public final static String firmwaredirPreference = "FIRMWARE"; + + /* serial debug preference name */ + public final static String serialDebugPreference = "SERIAL-DEBUG"; + + /* scanning telemetry preferences name */ + public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; + + /* Launcher serial preference name */ + public final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + + /* Launcher channel preference name */ + public final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + + /* Default logdir is ~/TeleMetrum */ + public final static String logdirName = "TeleMetrum"; + + /* Log directory */ + public static File logdir; + + /* Map directory -- hangs of logdir */ + public static File mapdir; + + /* Frequency (map serial to frequency) */ + public static Hashtable frequencies; + + /* Telemetry (map serial to telemetry format) */ + public static Hashtable telemetries; + + /* Voice preference */ + public static boolean voice; + + /* Callsign preference */ + public static String callsign; + + /* Firmware directory */ + public static File firmwaredir; + + /* Scanning telemetry */ + public static int scanning_telemetry; + + /* List of frequencies */ + public final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; + public static AltosFrequency[] common_frequencies; + + public final static String frequency_count = "COUNT"; + public final static String frequency_format = "FREQUENCY-%d"; + public final static String description_format = "DESCRIPTION-%d"; + + public static AltosFrequency[] load_common_frequencies() { + AltosFrequency[] frequencies = null; + boolean existing = false; + try { + existing = preferences.nodeExists(common_frequencies_node_name); + } catch (BackingStoreException be) { + existing = false; + } + if (existing) { + Preferences node = preferences.node(common_frequencies_node_name); + int count = node.getInt(frequency_count, 0); + + frequencies = new AltosFrequency[count]; + for (int i = 0; i < count; i++) { + double frequency; + String description; + + frequency = node.getDouble(String.format(frequency_format, i), 0.0); + description = node.get(String.format(description_format, i), null); + frequencies[i] = new AltosFrequency(frequency, description); + } + } else { + frequencies = new AltosFrequency[10]; + for (int i = 0; i < 10; i++) { + frequencies[i] = new AltosFrequency(434.550 + i * .1, + String.format("Channel %d", i)); + } + } + return frequencies; + } + + public static void save_common_frequencies(AltosFrequency[] frequencies) { + Preferences node = preferences.node(common_frequencies_node_name); + + node.putInt(frequency_count, frequencies.length); + for (int i = 0; i < frequencies.length; i++) { + node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); + node.put(String.format(description_format, i), frequencies[i].description); + } + } + public static int launcher_serial; + + public static int launcher_channel; + + public static void init() { + preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + + /* Initialize logdir from preferences */ + String logdir_string = preferences.get(logdirPreference, null); + if (logdir_string != null) + logdir = new File(logdir_string); + else { + /* Use the file system view default directory */ + logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); + if (!logdir.exists()) + logdir.mkdirs(); + } + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); + + frequencies = new Hashtable(); + + telemetries = new Hashtable(); + + voice = preferences.getBoolean(voicePreference, true); + + callsign = preferences.get(callsignPreference,"N0CALL"); + + scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard)); + + launcher_serial = preferences.getInt(launcherSerialPreference, 0); + + launcher_channel = preferences.getInt(launcherChannelPreference, 0); + + String firmwaredir_string = preferences.get(firmwaredirPreference, null); + if (firmwaredir_string != null) + firmwaredir = new File(firmwaredir_string); + else + firmwaredir = null; + + common_frequencies = load_common_frequencies(); + + } + + static { init(); } + + public static void flush_preferences() { + try { + preferences.flush(); + } catch (BackingStoreException ee) { +/* + if (component != null) + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + else +*/ + System.err.printf("Cannot save preferences\n"); + } + } + + public static void set_logdir(File new_logdir) { + logdir = new_logdir; + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); + synchronized (preferences) { + preferences.put(logdirPreference, logdir.getPath()); + flush_preferences(); + } + } + + public static File logdir() { + return logdir; + } + + public static File mapdir() { + return mapdir; + } + + public static void set_frequency(int serial, double new_frequency) { + frequencies.put(serial, new_frequency); + synchronized (preferences) { + preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); + flush_preferences(); + } + } + + public static double frequency(int serial) { + if (frequencies.containsKey(serial)) + return frequencies.get(serial); + double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); + if (frequency == 0.0) { + int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + frequency = AltosConvert.radio_channel_to_frequency(channel); + } + frequencies.put(serial, frequency); + return frequency; + } + + public static void set_telemetry(int serial, int new_telemetry) { + telemetries.put(serial, new_telemetry); + synchronized (preferences) { + preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); + flush_preferences(); + } + } + + public static int telemetry(int serial) { + if (telemetries.containsKey(serial)) + return telemetries.get(serial); + int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), + AltosLib.ao_telemetry_standard); + telemetries.put(serial, telemetry); + return telemetry; + } + + public static void set_scanning_telemetry(int new_scanning_telemetry) { + scanning_telemetry = new_scanning_telemetry; + synchronized (preferences) { + preferences.putInt(scanningTelemetryPreference, scanning_telemetry); + flush_preferences(); + } + } + + public static int scanning_telemetry() { + return scanning_telemetry; + } + + public static void set_voice(boolean new_voice) { + voice = new_voice; + synchronized (preferences) { + preferences.putBoolean(voicePreference, voice); + flush_preferences(); + } + } + + public static boolean voice() { + return voice; + } + + public static void set_callsign(String new_callsign) { + callsign = new_callsign; + synchronized(preferences) { + preferences.put(callsignPreference, callsign); + flush_preferences(); + } + } + + public static String callsign() { + return callsign; + } + + public static void set_firmwaredir(File new_firmwaredir) { + firmwaredir = new_firmwaredir; + synchronized (preferences) { + preferences.put(firmwaredirPreference, firmwaredir.getPath()); + flush_preferences(); + } + } + + public static File firmwaredir() { + return firmwaredir; + } + + public static void set_launcher_serial(int new_launcher_serial) { + launcher_serial = new_launcher_serial; + System.out.printf("set launcher serial to %d\n", new_launcher_serial); + synchronized (preferences) { + preferences.putInt(launcherSerialPreference, launcher_serial); + flush_preferences(); + } + } + + public static int launcher_serial() { + return launcher_serial; + } + + public static void set_launcher_channel(int new_launcher_channel) { + launcher_channel = new_launcher_channel; + System.out.printf("set launcher channel to %d\n", new_launcher_channel); + synchronized (preferences) { + preferences.putInt(launcherChannelPreference, launcher_channel); + flush_preferences(); + } + } + + public static int launcher_channel() { + return launcher_channel; + } + + public static Preferences bt_devices() { + return preferences.node("bt_devices"); + } + + public static AltosFrequency[] common_frequencies() { + return common_frequencies; + } + + public static void set_common_frequencies(AltosFrequency[] frequencies) { + common_frequencies = frequencies; + synchronized(preferences) { + save_common_frequencies(frequencies); + flush_preferences(); + } + } + + public static void add_common_frequency(AltosFrequency frequency) { + AltosFrequency[] new_frequencies = new AltosFrequency[common_frequencies.length + 1]; + int i; + + for (i = 0; i < common_frequencies.length; i++) { + if (frequency.frequency == common_frequencies[i].frequency) + return; + if (frequency.frequency < common_frequencies[i].frequency) + break; + new_frequencies[i] = common_frequencies[i]; + } + new_frequencies[i] = frequency; + for (; i < common_frequencies.length; i++) + new_frequencies[i+1] = common_frequencies[i]; + set_common_frequencies(new_frequencies); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java index 120004a7..e4915af0 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java @@ -23,64 +23,66 @@ import java.util.HashMap; import java.io.*; public class AltosRecord implements Comparable { - final static int MISSING = 0x7fffffff; - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - static final int seen_companion = 128; - int seen; - - int version; - String callsign; - int serial; - int flight; - int rssi; - int status; - int state; - int tick; - - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - - int ground_accel; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - - double acceleration; - double speed; - double height; - - int flight_accel; - int flight_vel; - int flight_pres; - - AltosGPS gps; - boolean new_gps; - - AltosIMU imu; - AltosMag mag; - - double time; /* seconds since boost */ - - int device_type; - int config_major; - int config_minor; - int apogee_delay; - int main_deploy; - int flight_log_max; - String firmware_version; - - AltosRecordCompanion companion; + public final static int MISSING = 0x7fffffff; + + public static final int seen_flight = 1; + public static final int seen_sensor = 2; + public static final int seen_temp_volt = 4; + public static final int seen_deploy = 8; + public static final int seen_gps_time = 16; + public static final int seen_gps_lat = 32; + public static final int seen_gps_lon = 64; + public static final int seen_companion = 128; + public int seen; + + public int version; + public String callsign; + public int serial; + public int flight; + public int rssi; + public int status; + public int state; + public int tick; + + public int accel; + public int pres; + public int temp; + public int batt; + public int drogue; + public int main; + + public int ground_accel; + public int ground_pres; + public int accel_plus_g; + public int accel_minus_g; + + public double acceleration; + public double speed; + public double height; + + public int flight_accel; + public int flight_vel; + public int flight_pres; + + public AltosGPS gps; + public boolean new_gps; + + public AltosIMU imu; + public AltosMag mag; + + public double time; /* seconds since boost */ + + public int device_type; + public int config_major; + public int config_minor; + public int apogee_delay; + public int main_deploy; + public int flight_log_max; + public String firmware_version; + + public AltosRecordCompanion companion; + +>>>>>>> 5a249bc... altosui: Complete split out of separate java library /* * Values for our MP3H6115A pressure sensor * @@ -95,10 +97,10 @@ public class AltosRecord implements Comparable { * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa */ - static final double counts_per_kPa = 27 * 2047 / 3300; - static final double counts_at_101_3kPa = 1674.0; + public static final double counts_per_kPa = 27 * 2047 / 3300; + public static final double counts_at_101_3kPa = 1674.0; - static double + public static double barometer_to_pressure(double count) { return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; @@ -193,7 +195,7 @@ public class AltosRecord implements Comparable { * = (value - 19791.268) / 32768 * 1.25 / 0.00247 */ - static double + public static double thermometer_to_temperature(double thermo) { return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; @@ -205,7 +207,7 @@ public class AltosRecord implements Comparable { return thermometer_to_temperature(temp); } - double accel_counts_per_mss() { + public double accel_counts_per_mss() { double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; return counts_per_g / 9.80665; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java index 4f8e80dc..c8cc6cac 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java @@ -18,14 +18,14 @@ package org.altusmetrum.AltosLib; public class AltosRecordCompanion { - final static int board_id_telescience = 0x0a; - final static int MAX_CHANNELS = 12; + public final static int board_id_telescience = 0x0a; + public final static int MAX_CHANNELS = 12; - int tick; - int board_id; - int update_period; - int channels; - int[] companion_data; + public int tick; + public int board_id; + public int update_period; + public int channels; + public int[] companion_data; public AltosRecordCompanion(int in_channels) { channels = in_channels; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java deleted file mode 100644 index bd94ee36..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.io.*; -import java.util.concurrent.*; - -class AltosTelemetryReader extends AltosFlightReader { - AltosDevice device; - AltosSerial serial; - AltosLog log; - AltosRecord previous; - double frequency; - int telemetry; - - LinkedBlockingQueue telem; - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { - AltosLine l = telem.take(); - if (l.line == null) - throw new IOException("IO error"); - AltosRecord next = AltosTelemetry.parse(l.line, previous); - previous = next; - return next; - } - - void flush() { - telem.clear(); - } - - void close(boolean interrupted) { - serial.remove_monitor(telem); - log.close(); - serial.close(); - } - - public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - serial.set_radio_frequency(frequency); - } - - public boolean supports_telemetry(int telemetry) { - - try { - /* Version 1.0 or later firmware supports all telemetry formats */ - if (serial.config_data().compare_version("1.0") >= 0) - return true; - - /* Version 0.9 firmware only supports 0.9 telemetry */ - if (serial.config_data().compare_version("0.9") >= 0) { - if (telemetry == Altos.ao_telemetry_0_9) - return true; - else - return false; - } - - /* Version 0.8 firmware only supports 0.8 telemetry */ - if (telemetry == Altos.ao_telemetry_0_8) - return true; - else - return false; - } catch (InterruptedException ie) { - return true; - } catch (TimeoutException te) { - return true; - } - } - - void save_frequency() { - AltosUIPreferences.set_frequency(device.getSerial(), frequency); - } - - void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - serial.set_telemetry(telemetry); - } - - void save_telemetry() { - AltosUIPreferences.set_telemetry(device.getSerial(), telemetry); - } - - File backing_file() { - return log.file(); - } - - public AltosTelemetryReader (AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { - device = in_device; - serial = new AltosSerial(device); - log = new AltosLog(serial); - name = device.toShortString(); - previous = null; - - telem = new LinkedBlockingQueue(); - frequency = AltosUIPreferences.frequency(device.getSerial()); - set_frequency(frequency); - telemetry = AltosUIPreferences.telemetry(device.getSerial()); - set_telemetry(telemetry); - serial.set_callsign(AltosUIPreferences.callsign()); - serial.add_monitor(telem); - } -} -- cgit v1.2.3 From ead8f1cfca2c454d18dce56479899f2b423d8bdd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 20:32:35 -0800 Subject: altosui: Add back in the split-out Altos constants as AltosLib These were pulled out of Altos.java, but not added back to git Signed-off-by: Keith Packard --- altosui/AltosConfigData.java | 191 ----------- .../org/altusmetrum/AltosLib/AltosConfigData.java | 191 +++++++++++ .../src/org/altusmetrum/AltosLib/AltosLib.java | 348 +++++++++++++++++++++ 3 files changed, 539 insertions(+), 191 deletions(-) delete mode 100644 altosui/AltosConfigData.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java deleted file mode 100644 index ef34dd3e..00000000 --- a/altosui/AltosConfigData.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.*; -import org.altusmetrum.AltosLib.*; - -import libaltosJNI.*; - -public class AltosConfigData implements Iterable { - - /* Version information */ - String manufacturer; - String product; - String version; - int log_format; - int serial; - - /* Strings returned */ - LinkedList lines; - - /* Config information */ - int config_major; - int config_minor; - int main_deploy; - int apogee_delay; - int radio_channel; - int radio_setting; - int radio_frequency; - String callsign; - int accel_cal_plus, accel_cal_minus; - int radio_calibration; - int flight_log_max; - int ignite_mode; - int stored_flight; - int storage_size; - int storage_erase_unit; - - static String get_string(String line, String label) throws ParseException { - if (line.startsWith(label)) { - String quoted = line.substring(label.length()).trim(); - - if (quoted.startsWith("\"")) - quoted = quoted.substring(1); - if (quoted.endsWith("\"")) - quoted = quoted.substring(0,quoted.length()-1); - return quoted; - } - throw new ParseException("mismatch", 0); - } - - static int get_int(String line, String label) throws NumberFormatException, ParseException { - if (line.startsWith(label)) { - String tail = line.substring(label.length()).trim(); - String[] tokens = tail.split("\\s+"); - if (tokens.length > 0) - return Integer.parseInt(tokens[0]); - } - throw new ParseException("mismatch", 0); - } - - public Iterator iterator() { - return lines.iterator(); - } - - public int log_available() { - switch (log_format) { - case Altos.AO_LOG_FORMAT_TINY: - if (stored_flight == 0) - return 1; - return 0; - default: - if (flight_log_max <= 0) - return 1; - int log_space = storage_size - storage_erase_unit; - int log_used = stored_flight * flight_log_max; - - if (log_used >= log_space) - return 0; - return (log_space - log_used) / flight_log_max; - } - } - - int[] parse_version(String v) { - String[] parts = v.split("\\."); - int r[] = new int[parts.length]; - - for (int i = 0; i < parts.length; i++) { - try { - r[i] = Altos.fromdec(parts[i]); - } catch (NumberFormatException n) { - r[i] = 0; - } - } - - return r; - } - - public int compare_version(String other) { - int[] me = parse_version(version); - int[] them = parse_version(other); - - int l = Math.min(me.length, them.length); - - for (int i = 0; i < l; i++) { - int d = me[i] - them[i]; - if (d != 0) - return d; - } - if (me.length > l) - return 1; - if (them.length > l) - return -1; - return 0; - } - - public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { - serial_line.printf("c s\np\nf\nl\nv\n"); - lines = new LinkedList(); - radio_setting = 0; - radio_frequency = 0; - stored_flight = 0; - for (;;) { - String line = serial_line.get_reply(); - if (line == null) - throw new TimeoutException(); - if (line.contains("Syntax error")) - continue; - lines.add(line); - try { serial = get_int(line, "serial-number"); } catch (Exception e) {} - try { log_format = get_int(line, "log-format"); } catch (Exception e) {} - try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} - try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} - try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} - try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} - try { - radio_frequency = get_int(line, "Frequency:"); - if (radio_frequency < 0) - radio_frequency = 434550; - } catch (Exception e) {} - try { - if (line.startsWith("Accel cal")) { - String[] bits = line.split("\\s+"); - if (bits.length >= 6) { - accel_cal_plus = Integer.parseInt(bits[3]); - accel_cal_minus = Integer.parseInt(bits[5]); - } - } - } catch (Exception e) {} - try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} - try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} - try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} - try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} - try { version = get_string(line,"software-version"); } catch (Exception e) {} - try { product = get_string(line,"product"); } catch (Exception e) {} - - try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} - try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} - try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } - } - -} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java new file mode 100644 index 00000000..ef34dd3e --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java @@ -0,0 +1,191 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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.*; +import org.altusmetrum.AltosLib.*; + +import libaltosJNI.*; + +public class AltosConfigData implements Iterable { + + /* Version information */ + String manufacturer; + String product; + String version; + int log_format; + int serial; + + /* Strings returned */ + LinkedList lines; + + /* Config information */ + int config_major; + int config_minor; + int main_deploy; + int apogee_delay; + int radio_channel; + int radio_setting; + int radio_frequency; + String callsign; + int accel_cal_plus, accel_cal_minus; + int radio_calibration; + int flight_log_max; + int ignite_mode; + int stored_flight; + int storage_size; + int storage_erase_unit; + + static String get_string(String line, String label) throws ParseException { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + return quoted; + } + throw new ParseException("mismatch", 0); + } + + static int get_int(String line, String label) throws NumberFormatException, ParseException { + if (line.startsWith(label)) { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) + return Integer.parseInt(tokens[0]); + } + throw new ParseException("mismatch", 0); + } + + public Iterator iterator() { + return lines.iterator(); + } + + public int log_available() { + switch (log_format) { + case Altos.AO_LOG_FORMAT_TINY: + if (stored_flight == 0) + return 1; + return 0; + default: + if (flight_log_max <= 0) + return 1; + int log_space = storage_size - storage_erase_unit; + int log_used = stored_flight * flight_log_max; + + if (log_used >= log_space) + return 0; + return (log_space - log_used) / flight_log_max; + } + } + + int[] parse_version(String v) { + String[] parts = v.split("\\."); + int r[] = new int[parts.length]; + + for (int i = 0; i < parts.length; i++) { + try { + r[i] = Altos.fromdec(parts[i]); + } catch (NumberFormatException n) { + r[i] = 0; + } + } + + return r; + } + + public int compare_version(String other) { + int[] me = parse_version(version); + int[] them = parse_version(other); + + int l = Math.min(me.length, them.length); + + for (int i = 0; i < l; i++) { + int d = me[i] - them[i]; + if (d != 0) + return d; + } + if (me.length > l) + return 1; + if (them.length > l) + return -1; + return 0; + } + + public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { + serial_line.printf("c s\np\nf\nl\nv\n"); + lines = new LinkedList(); + radio_setting = 0; + radio_frequency = 0; + stored_flight = 0; + for (;;) { + String line = serial_line.get_reply(); + if (line == null) + throw new TimeoutException(); + if (line.contains("Syntax error")) + continue; + lines.add(line); + try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { log_format = get_int(line, "log-format"); } catch (Exception e) {} + try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} + try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} + try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} + try { + radio_frequency = get_int(line, "Frequency:"); + if (radio_frequency < 0) + radio_frequency = 434550; + } catch (Exception e) {} + try { + if (line.startsWith("Accel cal")) { + String[] bits = line.split("\\s+"); + if (bits.length >= 6) { + accel_cal_plus = Integer.parseInt(bits[3]); + accel_cal_minus = Integer.parseInt(bits[5]); + } + } + } catch (Exception e) {} + try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} + try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} + try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} + try { version = get_string(line,"software-version"); } catch (Exception e) {} + try { product = get_string(line,"product"); } catch (Exception e) {} + + try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} + try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} + try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + } + +} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java new file mode 100644 index 00000000..2921d040 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java @@ -0,0 +1,348 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.awt.*; +import java.util.*; +import java.text.*; +import java.nio.charset.Charset; + +public class AltosLib { + /* EEProm command letters */ + public static final int AO_LOG_FLIGHT = 'F'; + public static final int AO_LOG_SENSOR = 'A'; + public static final int AO_LOG_TEMP_VOLT = 'T'; + public static final int AO_LOG_DEPLOY = 'D'; + public static final int AO_LOG_STATE = 'S'; + public static final int AO_LOG_GPS_TIME = 'G'; + public static final int AO_LOG_GPS_LAT = 'N'; + public static final int AO_LOG_GPS_LON = 'W'; + public static final int AO_LOG_GPS_ALT = 'H'; + public static final int AO_LOG_GPS_SAT = 'V'; + public static final int AO_LOG_GPS_DATE = 'Y'; + public static final int AO_LOG_PRESSURE = 'P'; + + /* Added for header fields in eeprom files */ + public static final int AO_LOG_CONFIG_VERSION = 1000; + public static final int AO_LOG_MAIN_DEPLOY = 1001; + public static final int AO_LOG_APOGEE_DELAY = 1002; + public static final int AO_LOG_RADIO_CHANNEL = 1003; + public static final int AO_LOG_CALLSIGN = 1004; + public static final int AO_LOG_ACCEL_CAL = 1005; + public static final int AO_LOG_RADIO_CAL = 1006; + public static final int AO_LOG_MAX_FLIGHT_LOG = 1007; + public static final int AO_LOG_MANUFACTURER = 2000; + public static final int AO_LOG_PRODUCT = 2001; + public static final int AO_LOG_SERIAL_NUMBER = 2002; + public static final int AO_LOG_LOG_FORMAT = 2003; + public static final int AO_LOG_SOFTWARE_VERSION = 9999; + + /* Added to flag invalid records */ + public static final int AO_LOG_INVALID = -1; + + /* Flight state numbers and names */ + public static final int ao_flight_startup = 0; + public static final int ao_flight_idle = 1; + public static final int ao_flight_pad = 2; + public static final int ao_flight_boost = 3; + public static final int ao_flight_fast = 4; + public static final int ao_flight_coast = 5; + public static final int ao_flight_drogue = 6; + public static final int ao_flight_main = 7; + public static final int ao_flight_landed = 8; + public static final int ao_flight_invalid = 9; + + /* Telemetry modes */ + public static final int ao_telemetry_off = 0; + public static final int ao_telemetry_min = 1; + public static final int ao_telemetry_standard = 1; + public static final int ao_telemetry_0_9 = 2; + public static final int ao_telemetry_0_8 = 3; + public static final int ao_telemetry_max = 3; + + public static final String[] ao_telemetry_name = { + "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" + }; + + public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt"; + + public static final int ao_telemetry_standard_len = 32; + public static final int ao_telemetry_0_9_len = 95; + public static final int ao_telemetry_0_8_len = 94; + + public static final int[] ao_telemetry_len = { + 0, 32, 95, 94 + }; + + public static HashMap string_to_state = new HashMap(); + + public static boolean map_initialized = false; + + public static void initialize_map() + { + string_to_state.put("startup", ao_flight_startup); + string_to_state.put("idle", ao_flight_idle); + string_to_state.put("pad", ao_flight_pad); + string_to_state.put("boost", ao_flight_boost); + string_to_state.put("fast", ao_flight_fast); + string_to_state.put("coast", ao_flight_coast); + string_to_state.put("drogue", ao_flight_drogue); + string_to_state.put("apogee", ao_flight_coast); + string_to_state.put("main", ao_flight_main); + string_to_state.put("landed", ao_flight_landed); + string_to_state.put("invalid", ao_flight_invalid); + map_initialized = true; + } + + public static int telemetry_len(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_len[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + public static String telemetry_name(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_name[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + public static String[] state_to_string = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + public static String[] state_to_string_capital = { + "Startup", + "Idle", + "Pad", + "Boost", + "Fast", + "Coast", + "Drogue", + "Main", + "Landed", + "Invalid", + }; + + public static int state(String state) { + if (!map_initialized) + initialize_map(); + if (string_to_state.containsKey(state)) + return string_to_state.get(state); + return ao_flight_invalid; + } + + public static String state_name(int state) { + if (state < 0 || state_to_string.length <= state) + return "invalid"; + return state_to_string[state]; + } + + public static final int AO_GPS_VALID = (1 << 4); + public static final int AO_GPS_RUNNING = (1 << 5); + public static final int AO_GPS_DATE_VALID = (1 << 6); + public static final int AO_GPS_NUM_SAT_SHIFT = 0; + public static final int AO_GPS_NUM_SAT_MASK = 0xf; + + public static final int AO_LOG_FORMAT_UNKNOWN = 0; + public static final int AO_LOG_FORMAT_FULL = 1; + public static final int AO_LOG_FORMAT_TINY = 2; + public static final int AO_LOG_FORMAT_TELEMETRY = 3; + public static final int AO_LOG_FORMAT_TELESCIENCE = 4; + public static final int AO_LOG_FORMAT_NONE = 127; + + public static boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + public 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; + } + + public static boolean ishex(String s) { + for (int i = 0; i < s.length(); i++) + if (!ishex(s.charAt(i))) + return false; + return true; + } + + public 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; + } + + public 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; + } + + public static boolean isdec(int c) { + if ('0' <= c && c <= '9') + return true; + return false; + } + + public static boolean isdec(String s) { + for (int i = 0; i < s.length(); i++) + if (!isdec(s.charAt(i))) + return false; + return true; + } + + public static int fromdec(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + return -1; + } + + public static int int8(int[] bytes, int i) { + return (int) (byte) bytes[i]; + } + + public static int uint8(int[] bytes, int i) { + return bytes[i]; + } + + public static int int16(int[] bytes, int i) { + return (int) (short) (bytes[i] + (bytes[i+1] << 8)); + } + + public static int uint16(int[] bytes, int i) { + return bytes[i] + (bytes[i+1] << 8); + } + + public static int uint32(int[] bytes, int i) { + return bytes[i] + + (bytes[i+1] << 8) + + (bytes[i+2] << 16) + + (bytes[i+3] << 24); + } + + public static final Charset unicode_set = Charset.forName("UTF-8"); + + public static String string(int[] bytes, int s, int l) { + if (s + l > bytes.length) { + if (s > bytes.length) { + s = bytes.length; + l = 0; + } else { + l = bytes.length - s; + } + } + + int i; + for (i = l - 1; i >= 0; i--) + if (bytes[s+i] != 0) + break; + + l = i + 1; + byte[] b = new byte[l]; + + for (i = 0; i < l; i++) + b[i] = (byte) bytes[s+i]; + String n = new String(b, unicode_set); + return n; + } + + public static int hexbyte(String s, int i) { + int c0, c1; + + if (s.length() < i + 2) + throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); + c0 = s.charAt(i); + if (!ishex(c0)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c0)); + c1 = s.charAt(i+1); + if (!ishex(c1)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c1)); + return fromhex(c0) * 16 + fromhex(c1); + } + + public static int[] hexbytes(String s) { + int n; + int[] r; + int i; + + if ((s.length() & 1) != 0) + throw new NumberFormatException(String.format("invalid line \"%s\"", s)); + n = s.length() / 2; + r = new int[n]; + for (i = 0; i < n; i++) + r[i] = hexbyte(s, i * 2); + return r; + } + + public 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; + } + + public static String replace_extension(String input, String extension) { + int dot = input.lastIndexOf("."); + if (dot > 0) + input = input.substring(0,dot); + return input.concat(extension); + } +} -- cgit v1.2.3 From 4c88b0ca96758b663c82395e63b338043d1c1a10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 20:34:38 -0800 Subject: altosui: Move AltosConfigData.java to library Create a new 'AltosLink' which exposes how to talk to the remote device abstractly via 'get_reply' and 'printf' methods. Signed-off-by: Keith Packard --- altosui/AltosSerial.java | 2 +- altosui/altoslib/Makefile.am | 2 ++ .../org/altusmetrum/AltosLib/AltosConfigData.java | 13 +++-------- .../src/org/altusmetrum/AltosLib/AltosLink.java | 26 ++++++++++++++++++++++ 4 files changed, 32 insertions(+), 11 deletions(-) create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 74e945f3..161f0e90 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -41,7 +41,7 @@ import libaltosJNI.*; * threads. */ -public class AltosSerial implements Runnable { +public class AltosSerial implements Runnable, AltosLink { static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index 967c8d06..cbf716b0 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -11,12 +11,14 @@ AltosLibdir = $(datadir)/java AltosLib_JAVA = \ $(SRC)/AltosLib.java \ + $(SRC)/AltosConfigData.java \ $(SRC)/AltosConvert.java \ $(SRC)/AltosCRCException.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ $(SRC)/AltosLine.java \ + $(SRC)/AltosLink.java \ $(SRC)/AltosParse.java \ $(SRC)/AltosPreferences.java \ $(SRC)/AltosRecordCompanion.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java index ef34dd3e..0bc5d5a8 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java @@ -17,11 +17,6 @@ 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.*; @@ -29,8 +24,6 @@ import java.util.prefs.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; -import libaltosJNI.*; - public class AltosConfigData implements Iterable { /* Version information */ @@ -138,14 +131,14 @@ public class AltosConfigData implements Iterable { return 0; } - public AltosConfigData(AltosSerial serial_line) throws InterruptedException, TimeoutException { - serial_line.printf("c s\np\nf\nl\nv\n"); + public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { + link.printf("c s\np\nf\nl\nv\n"); lines = new LinkedList(); radio_setting = 0; radio_frequency = 0; stored_flight = 0; for (;;) { - String line = serial_line.get_reply(); + String line = link.get_reply(); if (line == null) throw new TimeoutException(); if (line.contains("Syntax error")) diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java new file mode 100644 index 00000000..80f3d712 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public interface AltosLink { + public void printf(String format, Object ... arguments) throws InterruptedException; + + public String get_reply() throws InterruptedException; + + public String get_reply(int timeout) throws InterruptedException; +} -- cgit v1.2.3 From b273b8b298540b1a6d0a87b1cf61df1fbf62e013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 20:39:16 -0800 Subject: altosui: Finish moving AltosConfigData to altoslib Signed-off-by: Keith Packard --- altosui/Makefile.am | 1 - altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/altosui/Makefile.am b/altosui/Makefile.am index cfe45302..4005d16d 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -22,7 +22,6 @@ altosui_JAVA = \ AltosChannelMenu.java \ AltosCompanionInfo.java \ AltosConfig.java \ - AltosConfigData.java \ AltosConfigFreqUI.java \ AltosConfigUI.java \ AltosConfigureUI.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java index 0bc5d5a8..fec1a042 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altosui; +package org.altusmetrum.AltosLib; import java.io.*; import java.util.*; @@ -82,7 +82,7 @@ public class AltosConfigData implements Iterable { public int log_available() { switch (log_format) { - case Altos.AO_LOG_FORMAT_TINY: + case AltosLib.AO_LOG_FORMAT_TINY: if (stored_flight == 0) return 1; return 0; -- cgit v1.2.3 From 89aa06cfdcb02de1894ccb01aed97782f9eec9b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 20:47:16 -0800 Subject: altosui: Move AltosEepromChunk.java to lib Also fixes install issues with split lib Signed-off-by: Keith Packard --- altosui/AltosEepromChunk.java | 103 --------------------- altosui/Makefile.am | 3 +- altosui/altoslib/Makefile.am | 11 +-- .../org/altusmetrum/AltosLib/AltosEepromChunk.java | 102 ++++++++++++++++++++ .../src/org/altusmetrum/AltosLib/AltosLink.java | 2 + 5 files changed, 110 insertions(+), 111 deletions(-) delete mode 100644 altosui/AltosEepromChunk.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java diff --git a/altosui/AltosEepromChunk.java b/altosui/AltosEepromChunk.java deleted file mode 100644 index e4d11658..00000000 --- a/altosui/AltosEepromChunk.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 java.util.*; -import java.text.*; -import java.util.concurrent.*; -import org.altusmetrum.AltosLib.*; - -public class AltosEepromChunk { - - static final int chunk_size = 256; - static final int per_line = 8; - - public int data[]; - public int address; - public ParseException parse_exception = null; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - int data(int offset) { - return data[offset]; - } - - int data16(int offset) { - return data[offset] | (data[offset + 1] << 8); - } - - int data32(int offset) { - return data[offset] | (data[offset + 1] << 8) | - (data[offset+2] << 16) | (data[offset+3] << 24); - } - - boolean erased(int start, int len) { - for (int i = 0; i < len; i++) - if (data[start+i] != 0xff) - return false; - return true; - } - - public AltosEepromChunk(AltosSerial serial_line, int block, boolean flush) - throws TimeoutException, InterruptedException { - - int offset; - - data = new int[chunk_size]; - address = block * chunk_size; - if (flush) - serial_line.flush_input(); - serial_line.printf("e %x\n", block); - - for (offset = 0; offset < chunk_size; offset += per_line) { - try { - String line = serial_line.get_reply(5000); - - if (line == null) - throw new TimeoutException(); - - int[] values = ParseHex(line); - - if (values == null || values.length != per_line + 1) - throw new ParseException(String.format("invalid line %s", line), 0); - if (values[0] != offset) - throw new ParseException(String.format("data address out of sync at 0x%x", - address + offset), 0); - for (int i = 0; i < per_line; i++) - data[offset + i] = values[1 + i]; - } catch (ParseException pe) { - for (int i = 0; i < per_line; i++) - data[offset + i] = 0xff; - if (parse_exception == null) - parse_exception = pe; - } - } - } -} \ No newline at end of file diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 4005d16d..01732749 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -37,7 +37,6 @@ altosui_JAVA = \ AltosDevice.java \ AltosUSBDevice.java \ AltosDisplayThread.java \ - AltosEepromChunk.java \ AltosEepromDelete.java \ AltosEepromDownload.java \ AltosEepromList.java \ @@ -265,7 +264,7 @@ altosui: Makefile altosui-test: Makefile echo "#!/bin/sh" > $@ - echo 'exec java -cp ":altoslib/*:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ + echo 'exec java -cp "./*:$(FREETTS)/*:$(JFREECHART)/*:$(JCOMMON)/*" -Djava.library.path="libaltos/.libs" -jar altosui.jar "$$@"' >> $@ chmod +x $@ altosui-jdb: Makefile diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index cbf716b0..cce9b4c4 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -14,6 +14,7 @@ AltosLib_JAVA = \ $(SRC)/AltosConfigData.java \ $(SRC)/AltosConvert.java \ $(SRC)/AltosCRCException.java \ + $(SRC)/AltosEepromChunk.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ @@ -44,13 +45,11 @@ all-local: $(JAR) clean-local: -rm -rf bin $(JAR) -altosuidir=$(datadir)/java - -install-altosuiJAVA: $(JAR) +install-AltosLibJAVA: $(JAR) @$(NORMAL_INSTALL) - test -z "$(altosuidir)" || $(MKDIR_P) "$(DESTDIR)$(altosuidir)" - echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(altosuidir)/$(JAR)"; \ - $(INSTALL_DATA) "$<" "$(DESTDIR)$(altosuidir)" + test -z "$(AltosLibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosLibdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosLibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosLibdir)" bin: mkdir -p bin diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java new file mode 100644 index 00000000..4a9a2679 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java @@ -0,0 +1,102 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.concurrent.*; + +public class AltosEepromChunk { + + static final int chunk_size = 256; + static final int per_line = 8; + + public int data[]; + public int address; + public ParseException parse_exception = null; + + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + int data(int offset) { + return data[offset]; + } + + int data16(int offset) { + return data[offset] | (data[offset + 1] << 8); + } + + int data32(int offset) { + return data[offset] | (data[offset + 1] << 8) | + (data[offset+2] << 16) | (data[offset+3] << 24); + } + + boolean erased(int start, int len) { + for (int i = 0; i < len; i++) + if (data[start+i] != 0xff) + return false; + return true; + } + + public AltosEepromChunk(AltosLink link, int block, boolean flush) + throws TimeoutException, InterruptedException { + + int offset; + + data = new int[chunk_size]; + address = block * chunk_size; + if (flush) + link.flush_input(); + link.printf("e %x\n", block); + + for (offset = 0; offset < chunk_size; offset += per_line) { + try { + String line = link.get_reply(5000); + + if (line == null) + throw new TimeoutException(); + + int[] values = ParseHex(line); + + if (values == null || values.length != per_line + 1) + throw new ParseException(String.format("invalid line %s", line), 0); + if (values[0] != offset) + throw new ParseException(String.format("data address out of sync at 0x%x", + address + offset), 0); + for (int i = 0; i < per_line; i++) + data[offset + i] = values[1 + i]; + } catch (ParseException pe) { + for (int i = 0; i < per_line; i++) + data[offset + i] = 0xff; + if (parse_exception == null) + parse_exception = pe; + } + } + } +} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java index 80f3d712..9a23b306 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java @@ -23,4 +23,6 @@ public interface AltosLink { public String get_reply() throws InterruptedException; public String get_reply(int timeout) throws InterruptedException; + + public void flush_input() throws InterruptedException; } -- cgit v1.2.3 From a4ccdd253a9873c16f194a63a79f0c26feaafa29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 20:57:57 -0800 Subject: altosui: Move eeprom managment code to library Signed-off-by: Keith Packard --- altosui/AltosEepromIterable.java | 481 --------------------- altosui/AltosEepromRecord.java | 147 ------- altosui/Makefile.am | 2 - altosui/altoslib/Makefile.am | 2 + .../altusmetrum/AltosLib/AltosEepromIterable.java | 475 ++++++++++++++++++++ .../altusmetrum/AltosLib/AltosEepromRecord.java | 139 ++++++ 6 files changed, 616 insertions(+), 630 deletions(-) delete mode 100644 altosui/AltosEepromIterable.java delete mode 100644 altosui/AltosEepromRecord.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java deleted file mode 100644 index 11cb97e4..00000000 --- a/altosui/AltosEepromIterable.java +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 org.altusmetrum.AltosLib.*; - -/* - * AltosRecords with an index field so they can be sorted by tick while preserving - * the original ordering for elements with matching ticks - */ -class AltosOrderedRecord extends AltosEepromRecord implements Comparable { - - public int index; - - public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) - throws ParseException { - super(line); - if (prev_tick_valid) { - tick |= (prev_tick & ~0xffff); - if (tick < prev_tick) { - if (prev_tick - tick > 0x8000) - tick += 0x10000; - } else { - if (tick - prev_tick > 0x8000) - tick -= 0x10000; - } - } - 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 String toString() { - return String.format("%d.%d %04x %04x %04x", - cmd, index, tick, a, b); - } - - public int compareTo(AltosOrderedRecord o) { - int tick_diff = tick - o.tick; - if (tick_diff != 0) - return tick_diff; - return index - o.index; - } -} - -public class AltosEepromIterable extends AltosRecordIterable { - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - - static final int seen_basic = seen_flight|seen_sensor; - - boolean has_accel; - boolean has_gps; - boolean has_ignite; - - AltosEepromRecord flight_record; - AltosEepromRecord gps_date_record; - - TreeSet records; - - LinkedList list; - - class EepromState { - int seen; - int n_pad_samples; - double ground_pres; - int gps_tick; - int boost_tick; - int sensor_tick; - - EepromState() { - seen = 0; - n_pad_samples = 0; - ground_pres = 0.0; - gps_tick = 0; - } - } - - void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { - state.tick = record.tick; - switch (record.cmd) { - case Altos.AO_LOG_FLIGHT: - eeprom.seen |= seen_flight; - state.ground_accel = record.a; - state.flight_accel = record.a; - state.flight = record.b; - eeprom.boost_tick = record.tick; - break; - case Altos.AO_LOG_SENSOR: - state.accel = record.a; - state.pres = record.b; - if (state.state < Altos.ao_flight_boost) { - eeprom.n_pad_samples++; - eeprom.ground_pres += state.pres; - state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); - state.flight_pres = state.ground_pres; - } else { - state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - } - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - if ((eeprom.seen & seen_sensor) == 0) - eeprom.sensor_tick = record.tick - 1; - state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); - eeprom.seen |= seen_sensor; - eeprom.sensor_tick = record.tick; - has_accel = true; - break; - case Altos.AO_LOG_PRESSURE: - state.pres = record.b; - state.flight_pres = state.pres; - if (eeprom.n_pad_samples == 0) { - eeprom.n_pad_samples++; - state.ground_pres = state.pres; - } - eeprom.seen |= seen_sensor; - break; - case Altos.AO_LOG_TEMP_VOLT: - state.temp = record.a; - state.batt = record.b; - eeprom.seen |= seen_temp_volt; - break; - case Altos.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - eeprom.seen |= seen_deploy; - has_ignite = true; - break; - case Altos.AO_LOG_STATE: - state.state = record.a; - break; - case Altos.AO_LOG_GPS_TIME: - eeprom.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); - - int flags = (record.b >> 8); - state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; - state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; - state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> - Altos.AO_GPS_NUM_SAT_SHIFT; - state.new_gps = true; - has_gps = true; - break; - case Altos.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case Altos.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case Altos.AO_LOG_GPS_ALT: - state.gps.alt = record.a; - break; - case Altos.AO_LOG_GPS_SAT: - if (state.tick == eeprom.gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); - } - break; - case Altos.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - - case Altos.AO_LOG_CONFIG_VERSION: - break; - case Altos.AO_LOG_MAIN_DEPLOY: - break; - case Altos.AO_LOG_APOGEE_DELAY: - break; - case Altos.AO_LOG_RADIO_CHANNEL: - break; - case Altos.AO_LOG_CALLSIGN: - state.callsign = record.data; - break; - case Altos.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; - break; - case Altos.AO_LOG_RADIO_CAL: - break; - case Altos.AO_LOG_MANUFACTURER: - 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; - } - state.seen |= eeprom.seen; - } - - LinkedList make_list() { - LinkedList list = new LinkedList(); - Iterator iterator = records.iterator(); - AltosOrderedRecord record = null; - AltosRecord state = new AltosRecord(); - boolean last_reported = false; - EepromState eeprom = new EepromState(); - - state.state = Altos.ao_flight_pad; - state.accel_plus_g = 15758; - state.accel_minus_g = 16294; - - /* Pull in static data from the flight and gps_date records */ - if (flight_record != null) - update_state(state, flight_record, eeprom); - if (gps_date_record != null) - update_state(state, gps_date_record, eeprom); - - while (iterator.hasNext()) { - record = iterator.next(); - if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - } - update_state(state, record, eeprom); - } - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - return list; - } - - public Iterator iterator() { - if (list == null) - list = make_list(); - return list.iterator(); - } - - public boolean has_gps() { return has_gps; } - public boolean has_accel() { return has_accel; } - public boolean has_ignite() { return has_ignite; } - - public void write_comments(PrintStream out) { - Iterator iterator = records.iterator(); - out.printf("# Comments\n"); - while (iterator.hasNext()) { - AltosOrderedRecord record = iterator.next(); - switch (record.cmd) { - case Altos.AO_LOG_CONFIG_VERSION: - out.printf("# Config version: %s\n", record.data); - break; - case Altos.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); - break; - case Altos.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); - break; - case Altos.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); - break; - case Altos.AO_LOG_CALLSIGN: - out.printf("# Callsign: %s\n", record.data); - break; - case Altos.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); - break; - case Altos.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); - break; - case Altos.AO_LOG_MAX_FLIGHT_LOG: - out.printf ("# Max flight log: %d\n", record.a); - break; - case Altos.AO_LOG_MANUFACTURER: - out.printf ("# Manufacturer: %s\n", record.data); - break; - case Altos.AO_LOG_PRODUCT: - out.printf ("# Product: %s\n", record.data); - break; - case Altos.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); - break; - case Altos.AO_LOG_SOFTWARE_VERSION: - out.printf ("# Software version: %s\n", record.data); - break; - case Altos.AO_LOG_BARO_RESERVED: - out.printf ("# Baro reserved: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_SENS: - out.printf ("# Baro sens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_OFF: - out.printf ("# Baro off: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCS: - out.printf ("# Baro tcs: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCO: - out.printf ("# Baro tco: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TREF: - out.printf ("# Baro tref: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TEMPSENS: - out.printf ("# Baro tempsens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_CRC: - out.printf ("# Baro crc: %d\n", record.a); - break; - } - } - } - - /* - * 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; - - /* Make sure this looks like a good GPS value */ - if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) - flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); - flags |= Altos.AO_GPS_RUNNING; - flags |= Altos.AO_GPS_VALID; - - 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 - * are sometimes out of order with GPS data getting timestamps - * matching the first packet out of the GPS unit but not - * written until the final GPS packet has been received. - */ - public AltosEepromIterable (FileInputStream input) { - records = new TreeSet(); - - AltosOrderedRecord last_gps_time = null; - - int index = 0; - int prev_tick = 0; - boolean prev_tick_valid = false; - boolean missing_time = false; - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) - break; - AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); - if (record == null) - break; - if (record.cmd == Altos.AO_LOG_INVALID) - continue; - prev_tick = record.tick; - if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) - prev_tick_valid = true; - if (record.cmd == Altos.AO_LOG_FLIGHT) { - flight_record = record; - continue; - } - - /* 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) { - gps_date_record = record; - continue; - } - - /* 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 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); - - /* Bail after reading the 'landed' record; we're all done */ - if (record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_landed) - break; - } - } catch (IOException io) { - } catch (ParseException pe) { - } - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java deleted file mode 100644 index ea003a1e..00000000 --- a/altosui/AltosEepromRecord.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.*; -import org.altusmetrum.AltosLib.*; - -import libaltosJNI.*; - -public class AltosEepromRecord { - public int cmd; - public int tick; - public int a; - public int b; - public String data; - public boolean tick_valid; - - static final int record_length = 8; - - public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { - - cmd = chunk.data(start); - tick_valid = true; - - tick_valid = !chunk.erased(start, record_length); - if (tick_valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - cmd = Altos.AO_LOG_INVALID; - } - - tick = chunk.data16(start + 2); - a = chunk.data16(start + 4); - b = chunk.data16(start + 6); - - data = null; - } - - public AltosEepromRecord (String line) { - tick_valid = false; - tick = 0; - a = 0; - b = 0; - data = null; - if (line == null) { - cmd = Altos.AO_LOG_INVALID; - data = ""; - } else { - try { - String[] tokens = line.split("\\s+"); - - 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("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { - cmd = Altos.AO_LOG_MAX_FLIGHT_LOG; - a = Integer.parseInt(tokens[3]); - } 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("log-format")) { - cmd = Altos.AO_LOG_LOG_FORMAT; - 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; - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 01732749..a168b6fc 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -43,8 +43,6 @@ altosui_JAVA = \ AltosEepromLog.java \ AltosEepromManage.java \ AltosEepromMonitor.java \ - AltosEepromIterable.java \ - AltosEepromRecord.java \ AltosEepromTeleScience.java \ AltosEepromMega.java \ AltosEepromMegaIterable.java \ diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index cce9b4c4..ad4d2d98 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -15,6 +15,8 @@ AltosLib_JAVA = \ $(SRC)/AltosConvert.java \ $(SRC)/AltosCRCException.java \ $(SRC)/AltosEepromChunk.java \ + $(SRC)/AltosEepromIterable.java \ + $(SRC)/AltosEepromRecord.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java new file mode 100644 index 00000000..f1397c7b --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java @@ -0,0 +1,475 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedRecord extends AltosEepromRecord implements Comparable { + + public int index; + + public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + 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 String toString() { + return String.format("%d.%d %04x %04x %04x", + cmd, index, tick, a, b); + } + + public int compareTo(AltosOrderedRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor; + + boolean has_accel; + boolean has_gps; + boolean has_ignite; + + AltosEepromRecord flight_record; + AltosEepromRecord gps_date_record; + + TreeSet records; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + int sensor_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case AltosLib.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.a; + state.flight_accel = record.a; + state.flight = record.b; + eeprom.boost_tick = record.tick; + break; + case AltosLib.AO_LOG_SENSOR: + state.accel = record.a; + state.pres = record.b; + if (state.state < AltosLib.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + } + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); + eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; + has_accel = true; + break; + case AltosLib.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } + eeprom.seen |= seen_sensor; + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.temp = record.a; + state.batt = record.b; + eeprom.seen |= seen_temp_volt; + break; + case AltosLib.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + has_ignite = true; + break; + case AltosLib.AO_LOG_STATE: + state.state = record.a; + break; + case AltosLib.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + state.new_gps = true; + has_gps = true; + break; + case AltosLib.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case AltosLib.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case AltosLib.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case AltosLib.AO_LOG_CONFIG_VERSION: + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + break; + case AltosLib.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case AltosLib.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case AltosLib.AO_LOG_RADIO_CAL: + break; + case AltosLib.AO_LOG_MANUFACTURER: + break; + case AltosLib.AO_LOG_PRODUCT: + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + state.serial = record.a; + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + break; + } + state.seen |= eeprom.seen; + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = AltosLib.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedRecord record = iterator.next(); + switch (record.cmd) { + case AltosLib.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case AltosLib.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case AltosLib.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case AltosLib.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case AltosLib.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.a); + break; + case AltosLib.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case AltosLib.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + case Altos.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.a); + break; + } + } + } + + /* + * 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; + + /* Make sure this looks like a good GPS value */ + if ((flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT); + flags |= AltosLib.AO_GPS_RUNNING; + flags |= AltosLib.AO_GPS_VALID; + + 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedRecord last_gps_time = null; + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); + if (record == null) + break; + if (record.cmd == AltosLib.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == AltosLib.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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 == AltosLib.AO_LOG_GPS_DATE) { + gps_date_record = record; + continue; + } + + /* go back and fix up any missing time values */ + if (record.cmd == AltosLib.AO_LOG_GPS_TIME) { + last_gps_time = record; + if (missing_time) { + Iterator iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedRecord old = iterator.next(); + if (old.cmd == AltosLib.AO_LOG_GPS_TIME && + old.a == -1 && old.b == -1) + { + update_time(record, old); + } + } + missing_time = false; + } + } + + if (record.cmd == AltosLib.AO_LOG_GPS_LAT) { + if (last_gps_time == null || last_gps_time.tick != record.tick) { + AltosOrderedRecord add_gps_time = new AltosOrderedRecord(AltosLib.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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == AltosLib.AO_LOG_STATE && + record.a == AltosLib.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java new file mode 100644 index 00000000..b2f23c52 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java @@ -0,0 +1,139 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosEepromRecord { + public int cmd; + public int tick; + public int a; + public int b; + public String data; + public boolean tick_valid; + + static final int record_length = 8; + + public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { + + cmd = chunk.data(start); + tick_valid = true; + + tick_valid = !chunk.erased(start, record_length); + if (tick_valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + cmd = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start + 2); + a = chunk.data16(start + 4); + b = chunk.data16(start + 6); + + data = null; + } + + public AltosEepromRecord (String line) { + tick_valid = false; + tick = 0; + a = 0; + b = 0; + data = null; + if (line == null) { + cmd = AltosLib.AO_LOG_INVALID; + data = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + if (tokens[0].length() == 1) { + if (tokens.length != 4) { + cmd = AltosLib.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 = AltosLib.AO_LOG_CONFIG_VERSION; + data = tokens[2]; + } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { + cmd = AltosLib.AO_LOG_MAIN_DEPLOY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { + cmd = AltosLib.AO_LOG_APOGEE_DELAY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { + cmd = AltosLib.AO_LOG_RADIO_CHANNEL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Callsign:")) { + cmd = AltosLib.AO_LOG_CALLSIGN; + data = tokens[1].replaceAll("\"",""); + } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { + cmd = AltosLib.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 = AltosLib.AO_LOG_RADIO_CAL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; + a = Integer.parseInt(tokens[3]); + } else if (tokens[0].equals("manufacturer")) { + cmd = AltosLib.AO_LOG_MANUFACTURER; + data = tokens[1]; + } else if (tokens[0].equals("product")) { + cmd = AltosLib.AO_LOG_PRODUCT; + data = tokens[1]; + } else if (tokens[0].equals("serial-number")) { + cmd = AltosLib.AO_LOG_SERIAL_NUMBER; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = AltosLib.AO_LOG_LOG_FORMAT; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("software-version")) { + cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; + data = tokens[1]; + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } catch (NumberFormatException ne) { + cmd = AltosLib.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; + } +} -- cgit v1.2.3 From 346df410f570a67cda057550a067fa2b451b785d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 21:05:02 -0800 Subject: altosui: Move more eeprom stuff to altoslib Signed-off-by: Keith Packard --- altosui/AltosEepromLog.java | 108 --------------------- altosui/AltosEepromSelect.java | 1 + altosui/Makefile.am | 1 - altosui/altoslib/Makefile.am | 1 + .../org/altusmetrum/AltosLib/AltosConfigData.java | 48 ++++----- .../org/altusmetrum/AltosLib/AltosEepromChunk.java | 12 +-- .../org/altusmetrum/AltosLib/AltosEepromLog.java | 100 +++++++++++++++++++ .../altusmetrum/AltosLib/AltosEepromRecord.java | 2 +- 8 files changed, 133 insertions(+), 140 deletions(-) delete mode 100644 altosui/AltosEepromLog.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java diff --git a/altosui/AltosEepromLog.java b/altosui/AltosEepromLog.java deleted file mode 100644 index a24e82c0..00000000 --- a/altosui/AltosEepromLog.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.*; -import org.altusmetrum.AltosLib.*; - -import libaltosJNI.*; - -/* - * Extract a bit of information from an eeprom-stored flight log. - */ - -public class AltosEepromLog { - int serial; - boolean has_flight; - int flight; - int start_block; - int end_block; - - int year, month, day; - - boolean selected; - - public AltosEepromLog(AltosConfigData config_data, - AltosSerial serial_line, - int in_flight, int in_start_block, - int in_end_block) - throws InterruptedException, TimeoutException { - - int block; - boolean has_date = false; - - flight = in_flight; - if (flight != 0) - has_flight = true; - start_block = in_start_block; - end_block = in_end_block; - serial = config_data.serial; - - /* - * Select all flights for download - */ - selected = true; - - /* - * Look in TeleMetrum log data for date - */ - if (config_data.log_format == Altos.AO_LOG_FORMAT_UNKNOWN || - config_data.log_format == Altos.AO_LOG_FORMAT_FULL) - { - /* - * Only look in the first two blocks so that this - * process doesn't take a long time - */ - if (in_end_block > in_start_block + 2) - in_end_block = in_start_block + 2; - - for (block = in_start_block; block < in_end_block; block++) { - AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block, block == in_start_block); - - for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { - try { - AltosEepromRecord r = new AltosEepromRecord(eechunk, i); - - if (r.cmd == Altos.AO_LOG_FLIGHT) { - flight = r.b; - has_flight = true; - } - if (r.cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (r.a & 0xff); - month = (r.a >> 8) & 0xff; - day = (r.b & 0xff); - has_date = true; - } - } catch (ParseException pe) { - } - } - if (has_date && has_flight) - break; - } - } - } -} diff --git a/altosui/AltosEepromSelect.java b/altosui/AltosEepromSelect.java index e0fbeead..4ad78896 100644 --- a/altosui/AltosEepromSelect.java +++ b/altosui/AltosEepromSelect.java @@ -27,6 +27,7 @@ import libaltosJNI.libaltos; import libaltosJNI.altos_device; import libaltosJNI.SWIGTYPE_p_altos_file; import libaltosJNI.SWIGTYPE_p_altos_list; +import org.altusmetrum.AltosLib.*; class AltosEepromItem implements ActionListener { AltosEepromLog log; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index a168b6fc..84482dc2 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -40,7 +40,6 @@ altosui_JAVA = \ AltosEepromDelete.java \ AltosEepromDownload.java \ AltosEepromList.java \ - AltosEepromLog.java \ AltosEepromManage.java \ AltosEepromMonitor.java \ AltosEepromTeleScience.java \ diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index ad4d2d98..32f0ecfb 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -16,6 +16,7 @@ AltosLib_JAVA = \ $(SRC)/AltosCRCException.java \ $(SRC)/AltosEepromChunk.java \ $(SRC)/AltosEepromIterable.java \ + $(SRC)/AltosEepromLog.java \ $(SRC)/AltosEepromRecord.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java index fec1a042..4ad4e58a 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java @@ -27,33 +27,33 @@ import org.altusmetrum.AltosLib.*; public class AltosConfigData implements Iterable { /* Version information */ - String manufacturer; - String product; - String version; - int log_format; - int serial; + public String manufacturer; + public String product; + public String version; + public int log_format; + public int serial; /* Strings returned */ - LinkedList lines; + public LinkedList lines; /* Config information */ - int config_major; - int config_minor; - int main_deploy; - int apogee_delay; - int radio_channel; - int radio_setting; - int radio_frequency; - String callsign; - int accel_cal_plus, accel_cal_minus; - int radio_calibration; - int flight_log_max; - int ignite_mode; - int stored_flight; - int storage_size; - int storage_erase_unit; - - static String get_string(String line, String label) throws ParseException { + public int config_major; + public int config_minor; + public int main_deploy; + public int apogee_delay; + public int radio_channel; + public int radio_setting; + public int radio_frequency; + public String callsign; + public int accel_cal_plus, accel_cal_minus; + public int radio_calibration; + public int flight_log_max; + public int ignite_mode; + public int stored_flight; + public int storage_size; + public int storage_erase_unit; + + public static String get_string(String line, String label) throws ParseException { if (line.startsWith(label)) { String quoted = line.substring(label.length()).trim(); @@ -66,7 +66,7 @@ public class AltosConfigData implements Iterable { throw new ParseException("mismatch", 0); } - static int get_int(String line, String label) throws NumberFormatException, ParseException { + public static int get_int(String line, String label) throws NumberFormatException, ParseException { if (line.startsWith(label)) { String tail = line.substring(label.length()).trim(); String[] tokens = tail.split("\\s+"); diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java index 4a9a2679..6d889723 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java @@ -24,8 +24,8 @@ import java.util.concurrent.*; public class AltosEepromChunk { - static final int chunk_size = 256; - static final int per_line = 8; + public static final int chunk_size = 256; + public static final int per_line = 8; public int data[]; public int address; @@ -44,20 +44,20 @@ public class AltosEepromChunk { return array; } - int data(int offset) { + public int data(int offset) { return data[offset]; } - int data16(int offset) { + public int data16(int offset) { return data[offset] | (data[offset + 1] << 8); } - int data32(int offset) { + public int data32(int offset) { return data[offset] | (data[offset + 1] << 8) | (data[offset+2] << 16) | (data[offset+3] << 24); } - boolean erased(int start, int len) { + public boolean erased(int start, int len) { for (int i = 0; i < len; i++) if (data[start+i] != 0xff) return false; diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java new file mode 100644 index 00000000..7fca4bd9 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java @@ -0,0 +1,100 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +/* + * Extract a bit of information from an eeprom-stored flight log. + */ + +public class AltosEepromLog { + public int serial; + public boolean has_flight; + public int flight; + public int start_block; + public int end_block; + + public int year, month, day; + + public boolean selected; + + public AltosEepromLog(AltosConfigData config_data, + AltosLink link, + int in_flight, int in_start_block, + int in_end_block) + throws InterruptedException, TimeoutException { + + int block; + boolean has_date = false; + + flight = in_flight; + if (flight != 0) + has_flight = true; + start_block = in_start_block; + end_block = in_end_block; + serial = config_data.serial; + + /* + * Select all flights for download + */ + selected = true; + + /* + * Look in TeleMetrum log data for date + */ + if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN || + config_data.log_format == AltosLib.AO_LOG_FORMAT_FULL) + { + /* + * Only look in the first two blocks so that this + * process doesn't take a long time + */ + if (in_end_block > in_start_block + 2) + in_end_block = in_start_block + 2; + + for (block = in_start_block; block < in_end_block; block++) { + AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == in_start_block); + + for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { + try { + AltosEepromRecord r = new AltosEepromRecord(eechunk, i); + + if (r.cmd == AltosLib.AO_LOG_FLIGHT) { + flight = r.b; + has_flight = true; + } + if (r.cmd == AltosLib.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + has_date = true; + } + } catch (ParseException pe) { + } + } + if (has_date && has_flight) + break; + } + } + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java index b2f23c52..1e845f46 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java @@ -31,7 +31,7 @@ public class AltosEepromRecord { public String data; public boolean tick_valid; - static final int record_length = 8; + public static final int record_length = 8; public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { -- cgit v1.2.3 From 027863b737190bccc3b5cd032d77587396d0c5c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 21:08:34 -0800 Subject: altosui: Move AltosEepromTeleScience.java to altoslib Signed-off-by: Keith Packard --- altosui/AltosEepromTeleScience.java | 65 ---------------------- altosui/altoslib/Makefile.am | 1 + .../AltosLib/AltosEepromTeleScience.java | 59 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 65 deletions(-) delete mode 100644 altosui/AltosEepromTeleScience.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java diff --git a/altosui/AltosEepromTeleScience.java b/altosui/AltosEepromTeleScience.java deleted file mode 100644 index 0c237e11..00000000 --- a/altosui/AltosEepromTeleScience.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.*; -import org.altusmetrum.AltosLib.*; - -public class AltosEepromTeleScience { - int type; - int tick; - int tm_state; - int tm_tick; - int[] data; - boolean valid; - - static final int AO_LOG_TELESCIENCE_START = 's'; - static final int AO_LOG_TELESCIENCE_DATA = 'd'; - - static final int max_data = 12; - static final int record_length = 32; - - public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { - type = chunk.data(start); - - valid = !chunk.erased(start, record_length); - if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - type = Altos.AO_LOG_INVALID; - } - - tick = chunk.data16(start+2); - tm_tick = chunk.data16(start+4); - tm_state = chunk.data(start+6); - data = new int[max_data]; - for (int i = 0; i < max_data; i++) - data[i] = chunk.data16(start + 8 + i * 2); - } -} diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index 32f0ecfb..6f8c028a 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -18,6 +18,7 @@ AltosLib_JAVA = \ $(SRC)/AltosEepromIterable.java \ $(SRC)/AltosEepromLog.java \ $(SRC)/AltosEepromRecord.java \ + $(SRC)/AltosEepromTeleScience.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java new file mode 100644 index 00000000..1758fa34 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosEepromTeleScience { + public int type; + public int tick; + public int tm_state; + public int tm_tick; + public int[] data; + public boolean valid; + + public static final int AO_LOG_TELESCIENCE_START = 's'; + public static final int AO_LOG_TELESCIENCE_DATA = 'd'; + + static final int max_data = 12; + public static final int record_length = 32; + + public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { + type = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + type = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + tm_tick = chunk.data16(start+4); + tm_state = chunk.data(start+6); + data = new int[max_data]; + for (int i = 0; i < max_data; i++) + data[i] = chunk.data16(start + 8 + i * 2); + } +} -- cgit v1.2.3 From 18914b9a84bbd8c4364a1568bb07dcc2b04ad7ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 21:12:45 -0800 Subject: altosui: Move AltosGreatCircle.java to altoslib Signed-off-by: Keith Packard --- altosui/AltosGreatCircle.java | 101 --------------------- altosui/Makefile.am | 1 - altosui/altoslib/Makefile.am | 1 + .../org/altusmetrum/AltosLib/AltosGreatCircle.java | 101 +++++++++++++++++++++ 4 files changed, 102 insertions(+), 102 deletions(-) delete mode 100644 altosui/AltosGreatCircle.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java diff --git a/altosui/AltosGreatCircle.java b/altosui/AltosGreatCircle.java deleted file mode 100644 index e4af3c18..00000000 --- a/altosui/AltosGreatCircle.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.Math; -import org.altusmetrum.AltosLib.*; - -public class AltosGreatCircle { - double distance; - double bearing; - - double sqr(double a) { return a * a; } - - static final double rad = Math.PI / 180; - static final double earth_radius = 6371.2 * 1000; /* in meters */ - - static int BEARING_LONG = 0; - static int BEARING_SHORT = 1; - static int BEARING_VOICE = 2; - String bearing_words(int length) { - String [][] bearing_string = { - { - "North", "North North East", "North East", "East North East", - "East", "East South East", "South East", "South South East", - "South", "South South West", "South West", "West South West", - "West", "West North West", "North West", "North North West" - }, { - "N", "NNE", "NE", "ENE", - "E", "ESE", "SE", "SSE", - "S", "SSW", "SW", "WSW", - "W", "WNW", "NW", "NNW" - }, { - "north", "nor nor east", "north east", "east nor east", - "east", "east sow east", "south east", "sow sow east", - "south", "sow sow west", "south west", "west sow west", - "west", "west nor west", "north west", "nor nor west " - } - }; - return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; - } - - public AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) - { - double lat1 = rad * start_lat; - double lon1 = rad * -start_lon; - double lat2 = rad * end_lat; - double lon2 = rad * -end_lon; - - double d_lon = lon2 - lon1; - - /* From http://en.wikipedia.org/wiki/Great-circle_distance */ - double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + - sqr(Math.cos(lat1) * Math.sin(lat2) - - Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); - double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); - double d = Math.atan2(vdn,vdd); - double course; - - if (Math.cos(lat1) < 1e-20) { - if (lat1 > 0) - course = Math.PI; - else - course = -Math.PI; - } else { - if (d < 1e-10) - course = 0; - else - course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / - (Math.sin(d)*Math.cos(lat1))); - if (Math.sin(lon2-lon1) > 0) - course = 2 * Math.PI-course; - } - 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; - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 84482dc2..f8a886ba 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -62,7 +62,6 @@ altosui_JAVA = \ AltosFlightUI.java \ AltosFontListener.java \ AltosFreqList.java \ - AltosGreatCircle.java \ AltosHexfile.java \ Altos.java \ AltosIdleMonitorUI.java \ diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index 6f8c028a..e0647bd4 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -22,6 +22,7 @@ AltosLib_JAVA = \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ + $(SRC)/AltosGreatCircle.java \ $(SRC)/AltosLine.java \ $(SRC)/AltosLink.java \ $(SRC)/AltosParse.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java new file mode 100644 index 00000000..76b71859 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.Math; + +public class AltosGreatCircle { + public double distance; + public double bearing; + + double sqr(double a) { return a * a; } + + static final double rad = Math.PI / 180; + static final double earth_radius = 6371.2 * 1000; /* in meters */ + + public static final int BEARING_LONG = 0; + public static final int BEARING_SHORT = 1; + public static final int BEARING_VOICE = 2; + + public String bearing_words(int length) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } + + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) + { + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + + sqr(Math.cos(lat1) * Math.sin(lat2) - + Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); + double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); + double d = Math.atan2(vdn,vdd); + double course; + + if (Math.cos(lat1) < 1e-20) { + if (lat1 > 0) + course = Math.PI; + else + course = -Math.PI; + } else { + if (d < 1e-10) + course = 0; + else + course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / + (Math.sin(d)*Math.cos(lat1))); + if (Math.sin(lon2-lon1) > 0) + course = 2 * Math.PI-course; + } + 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; + } +} -- cgit v1.2.3 From a5ac5c37ea385e3a2b2703c6f125b4e3b55e867a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:05:47 -0800 Subject: altosui: Pull most of AltosSerial into AltosLink Share basic command processing across java users Signed-off-by: Keith Packard --- altosui/AltosFontListener.java | 2 +- altosui/AltosSerial.java | 103 ++-------- altosui/AltosUIPreferences.java | 4 +- altosui/Makefile.am | 4 +- .../src/org/altusmetrum/AltosLib/AltosLink.java | 219 ++++++++++++++++++++- 5 files changed, 233 insertions(+), 99 deletions(-) diff --git a/altosui/AltosFontListener.java b/altosui/AltosFontListener.java index 6fc214bc..0dda0f29 100644 --- a/altosui/AltosFontListener.java +++ b/altosui/AltosFontListener.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.AltosLib; +package altosui; public interface AltosFontListener { void font_size_changed(int font_size); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 161f0e90..cc384586 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -41,33 +41,22 @@ import libaltosJNI.*; * threads. */ -public class AltosSerial implements Runnable, AltosLink { +public class AltosSerial extends AltosLink implements Runnable { static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); AltosDevice device; SWIGTYPE_p_altos_file altos; - LinkedList> monitors; - LinkedBlockingQueue reply_queue; Thread input_thread; String line; byte[] line_bytes; int line_count; - boolean monitor_mode; - int telemetry; - double frequency; - public static boolean debug; - boolean remote; - LinkedList pending_output = new LinkedList(); Frame frame; - AltosConfigData config_data; - - static void set_debug(boolean new_debug) { - debug = new_debug; - } public void run () { int c; + byte[] line_bytes = null; + int line_count = 0; try { for (;;) { @@ -75,11 +64,8 @@ public class AltosSerial implements Runnable, AltosLink { if (Thread.interrupted()) break; if (c == libaltosConstants.LIBALTOS_ERROR) { - for (int e = 0; e < monitors.size(); e++) { - LinkedBlockingQueue q = monitors.get(e); - q.put(new AltosLine()); - } - reply_queue.put (new AltosLine()); + add_telem (new AltosLine()); + add_reply (new AltosLine()); break; } if (c == libaltosConstants.LIBALTOS_TIMEOUT) @@ -89,25 +75,8 @@ public class AltosSerial implements Runnable, AltosLink { synchronized(this) { if (c == '\n') { 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 (debug) - System.out.printf("\t\t\t\t\t%s\n", line); - if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { - for (int e = 0; e < monitors.size(); e++) { - LinkedBlockingQueue q = monitors.get(e); - q.put(new AltosLine (line)); - } - } else { - reply_queue.put(new AltosLine (line)); - } + add_bytes(line_bytes, line_count); line_count = 0; - line = ""; } } else { if (line_bytes == null) { @@ -127,10 +96,8 @@ public class AltosSerial implements Runnable, AltosLink { } public void flush_output() { + super.flush_output(); if (altos != null) { - for (String s : pending_output) - System.out.print(s); - pending_output.clear(); libaltos.altos_flush(altos); } } @@ -189,22 +156,10 @@ public class AltosSerial implements Runnable, AltosLink { } public void flush_input() throws InterruptedException { - flush_output(); - boolean got_some; - - int timeout = 100; if (remote) - timeout = 500; - do { - Thread.sleep(timeout); - got_some = !reply_queue.isEmpty(); - synchronized(this) { - if (!"VERSION".startsWith(line) && - !line.startsWith("VERSION")) - line = ""; - reply_queue.clear(); - } - } while (got_some); + flush_input(500); + else + flush_input(100); } int in_reply; @@ -245,29 +200,6 @@ public class AltosSerial implements Runnable, AltosLink { return reply; } - public String get_reply() throws InterruptedException { - return get_reply(5000); - } - - public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { - flush_output(); - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line != null) - return line.line; - return null; - } - - public void add_monitor(LinkedBlockingQueue q) { - set_monitor(true); - monitors.add(q); - } - - public void remove_monitor(LinkedBlockingQueue q) { - monitors.remove(q); - if (monitors.isEmpty()) - set_monitor(false); - } - public void close() { if (remote) { try { @@ -306,16 +238,10 @@ public class AltosSerial implements Runnable, AltosLink { } public void print(String data) { - if (debug) - pending_output.add(data); for (int i = 0; i < data.length(); i++) putc(data.charAt(i)); } - public void printf(String format, Object ... arguments) { - print(String.format(format, arguments)); - } - private void open() throws FileNotFoundException, AltosSerialInUseException { synchronized (devices_opened) { if (devices_opened.contains(device.getPath())) @@ -338,6 +264,7 @@ public class AltosSerial implements Runnable, AltosLink { flush_output(); } +<<<<<<< HEAD private int telemetry_len() { return Altos.telemetry_len(telemetry); } @@ -459,18 +386,16 @@ public class AltosSerial implements Runnable, AltosLink { remote = false; } +======= +>>>>>>> bc5e669... altosui: Pull most of AltosSerial into AltosLink public void set_frame(Frame in_frame) { frame = in_frame; } public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { device = in_device; - line = ""; - monitor_mode = false; frame = null; - telemetry = Altos.ao_telemetry_standard; - monitors = new LinkedList> (); - reply_queue = new LinkedBlockingQueue (); + serial = device.getSerial(); open(); } } diff --git a/altosui/AltosUIPreferences.java b/altosui/AltosUIPreferences.java index 38af734e..10ab26c3 100644 --- a/altosui/AltosUIPreferences.java +++ b/altosui/AltosUIPreferences.java @@ -58,7 +58,7 @@ public class AltosUIPreferences extends AltosPreferences { ui_listeners = new LinkedList(); serial_debug = preferences.getBoolean(serialDebugPreference, false); - AltosSerial.set_debug(serial_debug); + AltosLink.set_debug(serial_debug); } static { init(); } @@ -162,7 +162,7 @@ public class AltosUIPreferences extends AltosPreferences { } public static void set_serial_debug(boolean new_serial_debug) { serial_debug = new_serial_debug; - AltosSerial.set_debug(serial_debug); + AltosLink.set_debug(serial_debug); synchronized (preferences) { preferences.putBoolean(serialDebugPreference, serial_debug); flush_preferences(); diff --git a/altosui/Makefile.am b/altosui/Makefile.am index f8a886ba..913a8df1 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -247,11 +247,11 @@ $(FATJAR): classaltosui.stamp Manifest-fat.txt $(ALTOSLIB_CLASS) $(FREETTS_CLASS Manifest.txt: Makefile echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: altoslib.jar $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ + echo "Class-Path: AltosLib.jar $(FREETTS)/freetts.jar $(JFREECHART)/jfreechart.jar $(JCOMMON)/jcommon.jar" >> $@ Manifest-fat.txt: echo 'Main-Class: altosui.AltosUI' > $@ - echo "Class-Path: altoslib.jar freetts.jar jfreechart.jar jcommon.jar" >> $@ + echo "Class-Path: AltosLib.jar freetts.jar jfreechart.jar jcommon.jar" >> $@ altosui: Makefile echo "#!/bin/sh" > $@ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java index 9a23b306..49585975 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java @@ -17,12 +17,221 @@ package org.altusmetrum.AltosLib; -public interface AltosLink { - public void printf(String format, Object ... arguments) throws InterruptedException; +import java.lang.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import java.text.*; - public String get_reply() throws InterruptedException; +public abstract class AltosLink { - public String get_reply(int timeout) throws InterruptedException; + public static boolean debug = false; + public static void set_debug(boolean in_debug) { debug = in_debug; } + LinkedList pending_output = new LinkedList(); - public void flush_input() throws InterruptedException; + public LinkedList> monitors = new LinkedList> ();; + public LinkedBlockingQueue reply_queue = new LinkedBlockingQueue(); + + public void add_monitor(LinkedBlockingQueue q) { + set_monitor(true); + monitors.add(q); + } + + public void remove_monitor(LinkedBlockingQueue q) { + monitors.remove(q); + if (monitors.isEmpty()) + set_monitor(false); + } + + public abstract void print(String data); + + public void printf(String format, Object ... arguments) { + String line = String.format(format, arguments); + if (debug) + pending_output.add(line); + print(line); + } + + public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { + flush_output(); + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) + return line.line; + return null; + } + + public String get_reply(int timeout) throws InterruptedException { + try { + return get_reply_no_dialog(timeout); + } catch (TimeoutException te) { + return null; + } + } + + public String get_reply() throws InterruptedException { + return get_reply(5000); + } + + public void add_telem(AltosLine line) throws InterruptedException { + for (int e = 0; e < monitors.size(); e++) { + LinkedBlockingQueue q = monitors.get(e); + q.put(line); + } + } + + public void add_reply(AltosLine line) throws InterruptedException { + reply_queue.put (line); + } + + public void add_string(String line) throws InterruptedException { + if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { + add_telem(new AltosLine(line)); + } else { + add_reply(new AltosLine(line)); + } + } + + public void add_bytes(byte[] bytes, int len) throws InterruptedException { + String line; + try { + line = new String(bytes, 0, len, "UTF-8"); + } catch (UnsupportedEncodingException ue) { + line = ""; + for (int i = 0; i < len; i++) + line = line + bytes[i]; + } + if (debug) + System.out.printf("\t\t\t\t\t%s\n", line); + add_string(line); + } + + public void flush_output() { + for (String s : pending_output) + System.out.print(s); + pending_output.clear(); + } + + public void flush_input(int timeout) throws InterruptedException { + flush_output(); + boolean got_some; + + do { + Thread.sleep(timeout); + got_some = !reply_queue.isEmpty(); + reply_queue.clear(); + } while (got_some); + } + + + public void flush_input() throws InterruptedException { + flush_input(100); + } + + + /* + * Various command-level operations on + * the link + */ + public boolean monitor_mode = false; + public int telemetry = AltosLib.ao_telemetry_standard; + public double frequency; + AltosConfigData config_data; + + private int telemetry_len() { + return AltosLib.telemetry_len(telemetry); + } + + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + if (monitor_mode) + printf("m 0\nm %x\n", telemetry_len()); + flush_output(); + } + + public void set_monitor(boolean monitor) { + monitor_mode = monitor; + if (monitor) + printf("m %x\n", telemetry_len()); + else + printf("m 0\n"); + flush_output(); + } + + private void set_channel(int channel) { + if (monitor_mode) + printf("m 0\nc r %d\nm %x\n", + channel, telemetry_len()); + else + printf("c r %d\n", channel); + flush_output(); + } + + private void set_radio_setting(int setting) { + if (monitor_mode) + printf("m 0\nc R %d\nm %x\n", + setting, telemetry_len()); + else + printf("c R %d\n", setting); + flush_output(); + } + + public void set_radio_frequency(double frequency, + boolean has_setting, + int cal) { + if (debug) + System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); + if (has_setting) + set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); + else + set_channel(AltosConvert.radio_frequency_to_channel(frequency)); + } + + public AltosConfigData config_data() throws InterruptedException, TimeoutException { + if (config_data == null) + config_data = new AltosConfigData(this); + return config_data; + } + + public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + config_data(); + set_radio_frequency(frequency, + config_data.radio_setting != 0, + config_data.radio_calibration); + } + + public void set_callsign(String callsign) { + printf ("c c %s\n", callsign); + flush_output(); + } + + public boolean remote; + public int serial; + + public void start_remote() throws TimeoutException, InterruptedException { + if (debug) + System.out.printf("start remote %7.3f\n", frequency); + if (frequency == 0.0) + frequency = AltosPreferences.frequency(serial); + set_radio_frequency(frequency); + set_callsign(AltosPreferences.callsign()); + printf("p\nE 0\n"); + flush_input(); + remote = true; + } + + public void stop_remote() throws InterruptedException { + if (debug) + System.out.printf("stop remote\n"); + try { + flush_input(); + } finally { + printf ("~\n"); + flush_output(); + } + remote = false; + } + + public AltosLink() { + } } -- cgit v1.2.3 From 93305717ac4c993c88d9144d797ca64d26db97c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:13:38 -0800 Subject: altosui: Move AltosState.java to altoslib Signed-off-by: Keith Packard --- altosui/AltosFlightDisplay.java | 2 + altosui/AltosState.java | 216 --------------------- altosui/Makefile.am | 1 - altosui/altoslib/Makefile.am | 1 + .../src/org/altusmetrum/AltosLib/AltosState.java | 210 ++++++++++++++++++++ 5 files changed, 213 insertions(+), 217 deletions(-) delete mode 100644 altosui/AltosState.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java diff --git a/altosui/AltosFlightDisplay.java b/altosui/AltosFlightDisplay.java index f633c8e6..826f9522 100644 --- a/altosui/AltosFlightDisplay.java +++ b/altosui/AltosFlightDisplay.java @@ -17,6 +17,8 @@ package altosui; +import org.altusmetrum.AltosLib.*; + public interface AltosFlightDisplay { void reset(); diff --git a/altosui/AltosState.java b/altosui/AltosState.java deleted file mode 100644 index 403c74be..00000000 --- a/altosui/AltosState.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Track flight state from telemetry or eeprom data stream - */ - -package altosui; - -import org.altusmetrum.AltosLib.*; - -public class AltosState { - AltosRecord data; - - /* derived data */ - - long report_time; - - double time; - double time_change; - int tick; - - int state; - boolean landed; - boolean ascent; /* going up? */ - boolean boost; /* under power */ - - double ground_altitude; - double height; - double speed; - double acceleration; - double battery; - double temperature; - double main_sense; - double drogue_sense; - double baro_speed; - - double max_height; - double max_acceleration; - double max_speed; - double max_baro_speed; - - AltosGPS gps; - - AltosIMU imu; - AltosMag mag; - - double pad_lat; - double pad_lon; - double pad_alt; - - static final int MIN_PAD_SAMPLES = 10; - - int npad; - int ngps; - int gps_waiting; - boolean gps_ready; - - AltosGreatCircle from_pad; - double elevation; /* from pad */ - double range; /* total distance */ - - double gps_height; - - int speak_tick; - double speak_altitude; - - void init (AltosRecord cur, AltosState prev_state) { - int i; - AltosRecord prev; - - data = cur; - - ground_altitude = data.ground_altitude(); - height = data.filtered_height(); - - report_time = System.currentTimeMillis(); - - acceleration = data.acceleration(); - speed = data.accel_speed(); - temperature = data.temperature(); - drogue_sense = data.drogue_voltage(); - main_sense = data.main_voltage(); - battery = data.battery_voltage(); - tick = data.tick; - state = data.state; - - if (prev_state != null) { - - /* Preserve any existing gps data */ - npad = prev_state.npad; - ngps = prev_state.ngps; - gps = prev_state.gps; - pad_lat = prev_state.pad_lat; - pad_lon = prev_state.pad_lon; - pad_alt = prev_state.pad_alt; - max_height = prev_state.max_height; - max_acceleration = prev_state.max_acceleration; - max_speed = prev_state.max_speed; - max_baro_speed = prev_state.max_baro_speed; - imu = prev_state.imu; - mag = prev_state.mag; - - /* make sure the clock is monotonic */ - while (tick < prev_state.tick) - tick += 65536; - - time_change = (tick - prev_state.tick) / 100.0; - - /* compute barometric speed */ - - double height_change = height - prev_state.height; - if (data.speed != AltosRecord.MISSING) - baro_speed = data.speed; - else { - if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; - } - } else { - npad = 0; - ngps = 0; - gps = null; - baro_speed = 0; - time_change = 0; - } - - time = tick / 100.0; - - if (cur.new_gps && (state == Altos.ao_flight_pad || state == Altos.ao_flight_idle)) { - - /* Track consecutive 'good' gps reports, waiting for 10 of them */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) - npad++; - else - npad = 0; - - /* Average GPS data while on the pad */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { - if (ngps > 1) { - /* filter pad position */ - pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; - pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; - pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; - } else { - pad_lat = data.gps.lat; - pad_lon = data.gps.lon; - pad_alt = data.gps.alt; - } - ngps++; - } - } - - gps_waiting = MIN_PAD_SAMPLES - npad; - if (gps_waiting < 0) - gps_waiting = 0; - - gps_ready = gps_waiting == 0; - - ascent = (Altos.ao_flight_boost <= state && - state <= Altos.ao_flight_coast); - boost = (Altos.ao_flight_boost == state); - - /* Only look at accelerometer data under boost */ - if (boost && acceleration > max_acceleration) - max_acceleration = acceleration; - if (boost && speed > max_speed) - max_speed = speed; - if (boost && baro_speed > max_baro_speed) - max_baro_speed = baro_speed; - - if (height > max_height) - max_height = height; - if (data.gps != null) { - if (gps == null || !gps.locked || data.gps.locked) - gps = data.gps; - if (ngps > 0 && gps.locked) { - from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); - } - } - elevation = 0; - range = -1; - if (ngps > 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; - } - } - - public AltosState(AltosRecord cur) { - init(cur, null); - } - - public AltosState (AltosRecord cur, AltosState prev) { - init(cur, prev); - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 913a8df1..270fe114 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -90,7 +90,6 @@ altosui_JAVA = \ AltosSiteMapPreload.java \ AltosSiteMapCache.java \ AltosSiteMapTile.java \ - AltosState.java \ AltosTelemetryReader.java \ AltosUI.java \ AltosUIListener.java \ diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index e0647bd4..40ec3af8 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -30,6 +30,7 @@ AltosLib_JAVA = \ $(SRC)/AltosRecordCompanion.java \ $(SRC)/AltosRecordIterable.java \ $(SRC)/AltosRecord.java \ + $(SRC)/AltosState.java \ $(SRC)/AltosTelemetry.java \ $(SRC)/AltosTelemetryIterable.java \ $(SRC)/AltosTelemetryMap.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java new file mode 100644 index 00000000..0645e448 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java @@ -0,0 +1,210 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Track flight state from telemetry or eeprom data stream + */ + +package org.altusmetrum.AltosLib; + +public class AltosState { + public AltosRecord data; + + /* derived data */ + + public long report_time; + + public double time; + public double time_change; + public int tick; + + public int state; + public boolean landed; + public boolean ascent; /* going up? */ + public boolean boost; /* under power */ + + public double ground_altitude; + public double height; + public double speed; + public double acceleration; + public double battery; + public double temperature; + public double main_sense; + public double drogue_sense; + public double baro_speed; + + public double max_height; + public double max_acceleration; + public double max_speed; + public double max_baro_speed; + + public AltosGPS gps; + + public AltosIMU imu; + public AltosMag mag; + + public static final int MIN_PAD_SAMPLES = 10; + + public int npad; + public int ngps; + public int gps_waiting; + public boolean gps_ready; + + public AltosGreatCircle from_pad; + public double elevation; /* from pad */ + public double range; /* total distance */ + + public double gps_height; + + public int speak_tick; + public double speak_altitude; + + public void init (AltosRecord cur, AltosState prev_state) { + int i; + AltosRecord prev; + + data = cur; + + ground_altitude = data.ground_altitude(); + height = data.filtered_height(); + + report_time = System.currentTimeMillis(); + + acceleration = data.acceleration(); + speed = data.accel_speed(); + temperature = data.temperature(); + drogue_sense = data.drogue_voltage(); + main_sense = data.main_voltage(); + battery = data.battery_voltage(); + tick = data.tick; + state = data.state; + + if (prev_state != null) { + + /* Preserve any existing gps data */ + npad = prev_state.npad; + ngps = prev_state.ngps; + gps = prev_state.gps; + pad_lat = prev_state.pad_lat; + pad_lon = prev_state.pad_lon; + pad_alt = prev_state.pad_alt; + max_height = prev_state.max_height; + max_acceleration = prev_state.max_acceleration; + max_speed = prev_state.max_speed; + max_baro_speed = prev_state.max_baro_speed; + imu = prev_state.imu; + mag = prev_state.mag; + + /* make sure the clock is monotonic */ + while (tick < prev_state.tick) + tick += 65536; + + time_change = (tick - prev_state.tick) / 100.0; + + /* compute barometric speed */ + + double height_change = height - prev_state.height; + if (data.speed != AltosRecord.MISSING) + baro_speed = data.speed; + else { + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } + } else { + npad = 0; + ngps = 0; + gps = null; + baro_speed = 0; + time_change = 0; + } + + time = tick / 100.0; + + if (cur.new_gps && (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_idle)) { + + /* Track consecutive 'good' gps reports, waiting for 10 of them */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) + npad++; + else + npad = 0; + + /* Average GPS data while on the pad */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { + if (ngps > 1) { + /* filter pad position */ + pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; + pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; + pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; + } else { + pad_lat = data.gps.lat; + pad_lon = data.gps.lon; + pad_alt = data.gps.alt; + } + ngps++; + } + } + + gps_waiting = MIN_PAD_SAMPLES - npad; + if (gps_waiting < 0) + gps_waiting = 0; + + gps_ready = gps_waiting == 0; + + ascent = (AltosLib.ao_flight_boost <= state && + state <= AltosLib.ao_flight_coast); + boost = (AltosLib.ao_flight_boost == state); + + /* Only look at accelerometer data under boost */ + if (boost && acceleration > max_acceleration) + max_acceleration = acceleration; + if (boost && speed > max_speed) + max_speed = speed; + if (boost && baro_speed > max_baro_speed) + max_baro_speed = baro_speed; + + if (height > max_height) + max_height = height; + if (data.gps != null) { + if (gps == null || !gps.locked || data.gps.locked) + gps = data.gps; + if (ngps > 0 && gps.locked) { + from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); + } + } + elevation = 0; + range = -1; + if (ngps > 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; + } + } + + public AltosState(AltosRecord cur) { + init(cur, null); + } + + public AltosState (AltosRecord cur, AltosState prev) { + init(cur, prev); + } +} -- cgit v1.2.3 From 5270a0f1416baef5fde08547c6c98d97f973ae95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:35:41 -0800 Subject: altosui: Move telemetry reader &c to altoslib Move all of the device and file reading code into altoslib Signed-off-by: Keith Packard --- altosui/AltosFile.java | 45 -------- altosui/AltosFlightReader.java | 50 -------- altosui/AltosLog.java | 127 --------------------- altosui/AltosReplayReader.java | 62 ---------- altosui/AltosScanUI.java | 6 +- altosui/AltosSerial.java | 1 + altosui/AltosTelemetryReader.java | 120 ------------------- altosui/AltosUI.java | 2 +- altosui/Makefile.am | 6 - altosui/altoslib/Makefile.am | 5 + .../src/org/altusmetrum/AltosLib/AltosFile.java | 44 +++++++ .../altusmetrum/AltosLib/AltosFlightReader.java | 49 ++++++++ .../src/org/altusmetrum/AltosLib/AltosLink.java | 5 +- .../src/org/altusmetrum/AltosLib/AltosLog.java | 126 ++++++++++++++++++++ .../altusmetrum/AltosLib/AltosReplayReader.java | 56 +++++++++ .../altusmetrum/AltosLib/AltosTelemetryReader.java | 118 +++++++++++++++++++ 16 files changed, 406 insertions(+), 416 deletions(-) delete mode 100644 altosui/AltosFile.java delete mode 100644 altosui/AltosFlightReader.java delete mode 100644 altosui/AltosLog.java delete mode 100644 altosui/AltosReplayReader.java delete mode 100644 altosui/AltosTelemetryReader.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java create mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java diff --git a/altosui/AltosFile.java b/altosui/AltosFile.java deleted file mode 100644 index 4cf7de3c..00000000 --- a/altosui/AltosFile.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.File; -import java.util.*; -import org.altusmetrum.AltosLib.*; - -class AltosFile extends File { - - public AltosFile(int year, int month, int day, int serial, int flight, String extension) { - super (AltosUIPreferences.logdir(), - String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - year, month, day, serial, flight, extension)); - } - - public AltosFile(int serial, int flight, String extension) { - this(Calendar.getInstance().get(Calendar.YEAR), - Calendar.getInstance().get(Calendar.MONTH) + 1, - Calendar.getInstance().get(Calendar.DAY_OF_MONTH), - serial, - flight, - extension); - } - - public AltosFile(AltosRecord telem) { - this(telem.serial, telem.flight, "telem"); - } -} diff --git a/altosui/AltosFlightReader.java b/altosui/AltosFlightReader.java deleted file mode 100644 index 1ac9f848..00000000 --- a/altosui/AltosFlightReader.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.io.*; -import java.util.concurrent.*; -import org.altusmetrum.AltosLib.*; - -public class AltosFlightReader { - String name; - - int serial; - - void init() { } - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } - - void close(boolean interrupted) { } - - void set_frequency(double frequency) throws InterruptedException, TimeoutException { } - - void save_frequency() { } - - void set_telemetry(int telemetry) { } - - void save_telemetry() { } - - void update(AltosState state) throws InterruptedException { } - - boolean supports_telemetry(int telemetry) { return false; } - - File backing_file() { return null; } -} diff --git a/altosui/AltosLog.java b/altosui/AltosLog.java deleted file mode 100644 index 740f0be6..00000000 --- a/altosui/AltosLog.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.lang.*; -import java.util.*; -import java.text.ParseException; -import java.util.concurrent.LinkedBlockingQueue; -import org.altusmetrum.AltosLib.*; - -/* - * This creates a thread to capture telemetry data and write it to - * a log file - */ -class AltosLog implements Runnable { - - LinkedBlockingQueue input_queue; - LinkedBlockingQueue pending_queue; - int serial; - int flight; - FileWriter log_file; - Thread log_thread; - AltosFile file; - - private void close_log_file() { - if (log_file != null) { - try { - log_file.close(); - } catch (IOException io) { - } - log_file = null; - } - } - - void close() { - close_log_file(); - if (log_thread != null) { - log_thread.interrupt(); - log_thread = null; - } - } - - File file() { - return file; - } - - boolean open (AltosRecord telem) throws IOException { - AltosFile a = new AltosFile(telem); - - System.out.printf("open %s\n", a.toString()); - log_file = new FileWriter(a, true); - if (log_file != null) { - while (!pending_queue.isEmpty()) { - try { - String s = pending_queue.take(); - log_file.write(s); - log_file.write('\n'); - } catch (InterruptedException ie) { - } - } - log_file.flush(); - file = a; - } - return log_file != null; - } - - public void run () { - try { - AltosRecord previous = null; - for (;;) { - AltosLine line = input_queue.take(); - if (line.line == null) - continue; - try { - AltosRecord telem = AltosTelemetry.parse(line.line, previous); - if (telem.serial != 0 && telem.flight != 0 && - (telem.serial != serial || telem.flight != flight || log_file == null)) - { - close_log_file(); - serial = telem.serial; - flight = telem.flight; - open(telem); - } - previous = telem; - } catch (ParseException pe) { - } catch (AltosCRCException ce) { - } - if (log_file != null) { - log_file.write(line.line); - log_file.write('\n'); - log_file.flush(); - } else - pending_queue.put(line.line); - } - } catch (InterruptedException ie) { - } catch (IOException ie) { - } - close(); - } - - public AltosLog (AltosSerial s) { - pending_queue = new LinkedBlockingQueue (); - input_queue = new LinkedBlockingQueue (); - s.add_monitor(input_queue); - serial = -1; - flight = -1; - log_file = null; - log_thread = new Thread(this); - log_thread.start(); - } -} diff --git a/altosui/AltosReplayReader.java b/altosui/AltosReplayReader.java deleted file mode 100644 index f92c0328..00000000 --- a/altosui/AltosReplayReader.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 org.altusmetrum.AltosLib.*; - -/* - * Open an existing telemetry file and replay it in realtime - */ - -public class AltosReplayReader extends AltosFlightReader { - Iterator iterator; - File file; - - public AltosRecord read() { - if (iterator.hasNext()) - return iterator.next(); - return null; - } - - public void close (boolean interrupted) { - } - - void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > Altos.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - } - - public File backing_file() { return file; } - - public AltosReplayReader(Iterator in_iterator, File in_file) { - iterator = in_iterator; - file = in_file; - name = file.getName(); - } -} diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 1be8aa26..44eeda6d 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -208,7 +208,7 @@ public class AltosScanUI } void next() throws InterruptedException, TimeoutException { - reader.serial.set_monitor(false); + reader.set_monitor(false); Thread.sleep(100); ++frequency_index; if (frequency_index >= frequencies.length || @@ -224,7 +224,7 @@ public class AltosScanUI } set_frequency(); set_label(); - reader.serial.set_monitor(true); + reader.set_monitor(true); } @@ -312,7 +312,7 @@ public class AltosScanUI if (device == null) return false; try { - reader = new AltosTelemetryReader(device); + reader = new AltosTelemetryReader(new AltosSerial(device)); set_frequency(); set_telemetry(); try { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index cc384586..54cdcba7 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -396,6 +396,7 @@ public class AltosSerial extends AltosLink implements Runnable { device = in_device; frame = null; serial = device.getSerial(); + name = device.toShortString(); open(); } } diff --git a/altosui/AltosTelemetryReader.java b/altosui/AltosTelemetryReader.java deleted file mode 100644 index dc7e4a75..00000000 --- a/altosui/AltosTelemetryReader.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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.text.*; -import java.io.*; -import java.util.concurrent.*; -import org.altusmetrum.AltosLib.*; - -class AltosTelemetryReader extends AltosFlightReader { - AltosDevice device; - AltosSerial serial; - AltosLog log; - AltosRecord previous; - double frequency; - int telemetry; - - LinkedBlockingQueue telem; - - AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { - AltosLine l = telem.take(); - if (l.line == null) - throw new IOException("IO error"); - AltosRecord next = AltosTelemetry.parse(l.line, previous); - previous = next; - return next; - } - - void flush() { - telem.clear(); - } - - void close(boolean interrupted) { - serial.remove_monitor(telem); - log.close(); - serial.close(); - } - - public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - serial.set_radio_frequency(frequency); - } - - public boolean supports_telemetry(int telemetry) { - - try { - /* Version 1.0 or later firmware supports all telemetry formats */ - if (serial.config_data().compare_version("1.0") >= 0) - return true; - - /* Version 0.9 firmware only supports 0.9 telemetry */ - if (serial.config_data().compare_version("0.9") >= 0) { - if (telemetry == Altos.ao_telemetry_0_9) - return true; - else - return false; - } - - /* Version 0.8 firmware only supports 0.8 telemetry */ - if (telemetry == Altos.ao_telemetry_0_8) - return true; - else - return false; - } catch (InterruptedException ie) { - return true; - } catch (TimeoutException te) { - return true; - } - } - - void save_frequency() { - AltosPreferences.set_frequency(device.getSerial(), frequency); - } - - void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - serial.set_telemetry(telemetry); - } - - void save_telemetry() { - AltosPreferences.set_telemetry(device.getSerial(), telemetry); - } - - File backing_file() { - return log.file(); - } - - public AltosTelemetryReader (AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, IOException, InterruptedException, TimeoutException { - device = in_device; - serial = new AltosSerial(device); - log = new AltosLog(serial); - name = device.toShortString(); - previous = null; - - telem = new LinkedBlockingQueue(); - frequency = AltosPreferences.frequency(device.getSerial()); - set_frequency(frequency); - telemetry = AltosPreferences.telemetry(device.getSerial()); - set_telemetry(telemetry); - serial.set_callsign(AltosUIPreferences.callsign()); - serial.add_monitor(telem); - } -} diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 25c6c36b..538f8734 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -48,7 +48,7 @@ public class AltosUI extends AltosFrame { void telemetry_window(AltosDevice device) { try { - AltosFlightReader reader = new AltosTelemetryReader(device); + AltosFlightReader reader = new AltosTelemetryReader(new AltosSerial(device)); if (reader != null) new AltosFlightUI(voice, reader, device.getSerial()); } catch (FileNotFoundException ee) { diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 270fe114..2946890b 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -49,12 +49,10 @@ altosui_JAVA = \ AltosIMU.java \ AltosMag.java \ AltosEepromSelect.java \ - AltosFile.java \ AltosFlash.java \ AltosFlashUI.java \ AltosFlightDisplay.java \ AltosFlightInfoTableModel.java \ - AltosFlightReader.java \ AltosFlightStats.java \ AltosFlightStatsTable.java \ AltosFlightStatus.java \ @@ -74,12 +72,9 @@ altosui_JAVA = \ AltosLanded.java \ AltosLed.java \ AltosLights.java \ - AltosLog.java \ AltosPad.java \ AltosUIPreferences.java \ AltosReader.java \ - AltosTelemetryReader.java \ - AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ AltosScanUI.java \ @@ -90,7 +85,6 @@ altosui_JAVA = \ AltosSiteMapPreload.java \ AltosSiteMapCache.java \ AltosSiteMapTile.java \ - AltosTelemetryReader.java \ AltosUI.java \ AltosUIListener.java \ AltosFrame.java \ diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am index 40ec3af8..2ddd24e6 100644 --- a/altosui/altoslib/Makefile.am +++ b/altosui/altoslib/Makefile.am @@ -19,21 +19,26 @@ AltosLib_JAVA = \ $(SRC)/AltosEepromLog.java \ $(SRC)/AltosEepromRecord.java \ $(SRC)/AltosEepromTeleScience.java \ + $(SRC)/AltosFile.java \ + $(SRC)/AltosFlightReader.java \ $(SRC)/AltosFrequency.java \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ $(SRC)/AltosGreatCircle.java \ $(SRC)/AltosLine.java \ $(SRC)/AltosLink.java \ + $(SRC)/AltosLog.java \ $(SRC)/AltosParse.java \ $(SRC)/AltosPreferences.java \ $(SRC)/AltosRecordCompanion.java \ $(SRC)/AltosRecordIterable.java \ $(SRC)/AltosRecord.java \ + $(SRC)/AltosReplayReader.java \ $(SRC)/AltosState.java \ $(SRC)/AltosTelemetry.java \ $(SRC)/AltosTelemetryIterable.java \ $(SRC)/AltosTelemetryMap.java \ + $(SRC)/AltosTelemetryReader.java \ $(SRC)/AltosTelemetryRecordCompanion.java \ $(SRC)/AltosTelemetryRecordConfiguration.java \ $(SRC)/AltosTelemetryRecordGeneral.java \ diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java new file mode 100644 index 00000000..d2e4f2f7 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.io.File; +import java.util.*; + +public class AltosFile extends File { + + public AltosFile(int year, int month, int day, int serial, int flight, String extension) { + super (AltosPreferences.logdir(), + String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + year, month, day, serial, flight, extension)); + } + + public AltosFile(int serial, int flight, String extension) { + this(Calendar.getInstance().get(Calendar.YEAR), + Calendar.getInstance().get(Calendar.MONTH) + 1, + Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + serial, + flight, + extension); + } + + public AltosFile(AltosRecord telem) { + this(telem.serial, telem.flight, "telem"); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java new file mode 100644 index 00000000..3fdea469 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java @@ -0,0 +1,49 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.io.*; +import java.util.concurrent.*; + +public class AltosFlightReader { + public String name; + + public int serial; + + public void init() { } + + public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + + public void close(boolean interrupted) { } + + public void set_frequency(double frequency) throws InterruptedException, TimeoutException { } + + public void save_frequency() { } + + public void set_telemetry(int telemetry) { } + + public void save_telemetry() { } + + public void update(AltosState state) throws InterruptedException { } + + public boolean supports_telemetry(int telemetry) { return false; } + + public File backing_file() { return null; } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java index 49585975..9b80e916 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java @@ -24,6 +24,8 @@ import java.util.*; import java.text.*; public abstract class AltosLink { + public abstract void print(String data); + public abstract void close(); public static boolean debug = false; public static void set_debug(boolean in_debug) { debug = in_debug; } @@ -43,8 +45,6 @@ public abstract class AltosLink { set_monitor(false); } - public abstract void print(String data); - public void printf(String format, Object ... arguments) { String line = String.format(format, arguments); if (debug) @@ -207,6 +207,7 @@ public abstract class AltosLink { public boolean remote; public int serial; + public String name; public void start_remote() throws TimeoutException, InterruptedException { if (debug) diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java new file mode 100644 index 00000000..08c45ca8 --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java @@ -0,0 +1,126 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.lang.*; +import java.util.*; +import java.text.ParseException; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * This creates a thread to capture telemetry data and write it to + * a log file + */ +class AltosLog implements Runnable { + + LinkedBlockingQueue input_queue; + LinkedBlockingQueue pending_queue; + int serial; + int flight; + FileWriter log_file; + Thread log_thread; + AltosFile file; + + private void close_log_file() { + if (log_file != null) { + try { + log_file.close(); + } catch (IOException io) { + } + log_file = null; + } + } + + void close() { + close_log_file(); + if (log_thread != null) { + log_thread.interrupt(); + log_thread = null; + } + } + + File file() { + return file; + } + + boolean open (AltosRecord telem) throws IOException { + AltosFile a = new AltosFile(telem); + + System.out.printf("open %s\n", a.toString()); + log_file = new FileWriter(a, true); + if (log_file != null) { + while (!pending_queue.isEmpty()) { + try { + String s = pending_queue.take(); + log_file.write(s); + log_file.write('\n'); + } catch (InterruptedException ie) { + } + } + log_file.flush(); + file = a; + } + return log_file != null; + } + + public void run () { + try { + AltosRecord previous = null; + for (;;) { + AltosLine line = input_queue.take(); + if (line.line == null) + continue; + try { + AltosRecord telem = AltosTelemetry.parse(line.line, previous); + if (telem.serial != 0 && telem.flight != 0 && + (telem.serial != serial || telem.flight != flight || log_file == null)) + { + close_log_file(); + serial = telem.serial; + flight = telem.flight; + open(telem); + } + previous = telem; + } catch (ParseException pe) { + } catch (AltosCRCException ce) { + } + if (log_file != null) { + log_file.write(line.line); + log_file.write('\n'); + log_file.flush(); + } else + pending_queue.put(line.line); + } + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + close(); + } + + public AltosLog (AltosLink link) { + pending_queue = new LinkedBlockingQueue (); + input_queue = new LinkedBlockingQueue (); + link.add_monitor(input_queue); + serial = -1; + flight = -1; + log_file = null; + log_thread = new Thread(this); + log_thread.start(); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java new file mode 100644 index 00000000..1585f9eb --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * Open an existing telemetry file and replay it in realtime + */ + +public class AltosReplayReader extends AltosFlightReader { + Iterator iterator; + File file; + + public AltosRecord read() { + if (iterator.hasNext()) + return iterator.next(); + return null; + } + + public void close (boolean interrupted) { + } + + public void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > AltosLib.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + } + + public File backing_file() { return file; } + + public AltosReplayReader(Iterator in_iterator, File in_file) { + iterator = in_iterator; + file = in_file; + name = file.getName(); + } +} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java new file mode 100644 index 00000000..2cc2822a --- /dev/null +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.io.*; +import java.util.concurrent.*; + +public class AltosTelemetryReader extends AltosFlightReader { + AltosLink link; + AltosLog log; + AltosRecord previous; + double frequency; + int telemetry; + + LinkedBlockingQueue telem; + + public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { + AltosLine l = telem.take(); + if (l.line == null) + throw new IOException("IO error"); + AltosRecord next = AltosTelemetry.parse(l.line, previous); + previous = next; + return next; + } + + public void flush() { + telem.clear(); + } + + public void close(boolean interrupted) { + link.remove_monitor(telem); + log.close(); + link.close(); + } + + public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + link.set_radio_frequency(frequency); + } + + public boolean supports_telemetry(int telemetry) { + + try { + /* Version 1.0 or later firmware supports all telemetry formats */ + if (serial.config_data().compare_version("1.0") >= 0) + return true; + + /* Version 0.9 firmware only supports 0.9 telemetry */ + if (serial.config_data().compare_version("0.9") >= 0) { + if (telemetry == Altos.ao_telemetry_0_9) + return true; + else + return false; + } + + /* Version 0.8 firmware only supports 0.8 telemetry */ + if (telemetry == Altos.ao_telemetry_0_8) + return true; + else + return false; + } catch (InterruptedException ie) { + return true; + } catch (TimeoutException te) { + return true; + } + } + + public void save_frequency() { + AltosPreferences.set_frequency(link.serial, frequency); + } + + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + link.set_telemetry(telemetry); + } + + public void save_telemetry() { + AltosPreferences.set_telemetry(link.serial, telemetry); + } + + public void set_monitor(boolean monitor) { + link.set_monitor(monitor); + } + + public File backing_file() { + return log.file(); + } + + public AltosTelemetryReader (AltosLink in_link) + throws IOException, InterruptedException, TimeoutException { + log = new AltosLog(link); + name = link.name; + previous = null; + telem = new LinkedBlockingQueue(); + frequency = AltosPreferences.frequency(link.serial); + set_frequency(frequency); + telemetry = AltosPreferences.telemetry(link.serial); + set_telemetry(telemetry); + link.add_monitor(telem); + } +} -- cgit v1.2.3 From 9fb15d397890c7e78bf3c1438f142f62bfc2bd35 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:41:48 -0800 Subject: altosui: Remove unused files Left around from development, these aren't useful. Signed-off-by: Keith Packard --- altosui/AltosReader.java | 29 ----------------------------- altosui/AltosSerialMonitor.java | 22 ---------------------- altosui/Makefile.am | 2 -- 3 files changed, 53 deletions(-) delete mode 100644 altosui/AltosReader.java delete mode 100644 altosui/AltosSerialMonitor.java diff --git a/altosui/AltosReader.java b/altosui/AltosReader.java deleted file mode 100644 index aafd5f81..00000000 --- a/altosui/AltosReader.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.*; -import java.text.*; -import org.altusmetrum.AltosLib.*; - -public class AltosReader { - public AltosRecord read() throws IOException, ParseException { return null; } - public void close() { } - public void write_comments(PrintStream out) { } -} diff --git a/altosui/AltosSerialMonitor.java b/altosui/AltosSerialMonitor.java deleted file mode 100644 index ad0e9295..00000000 --- a/altosui/AltosSerialMonitor.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 interface AltosSerialMonitor { - void data(String data); -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 2946890b..7a3c53e7 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -74,13 +74,11 @@ altosui_JAVA = \ AltosLights.java \ AltosPad.java \ AltosUIPreferences.java \ - AltosReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ AltosScanUI.java \ AltosSerial.java \ AltosSerialInUseException.java \ - AltosSerialMonitor.java \ AltosSiteMap.java \ AltosSiteMapPreload.java \ AltosSiteMapCache.java \ -- cgit v1.2.3 From 02b53b7f592b78b2fec4f4a17b6b3e114d2bf3c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:42:18 -0800 Subject: altosui: Fix AltosTelemetryReader move Lost the provided link value causing a crash. Signed-off-by: Keith Packard --- altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java index 2cc2822a..67ac1b65 100644 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java +++ b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java @@ -105,6 +105,7 @@ public class AltosTelemetryReader extends AltosFlightReader { public AltosTelemetryReader (AltosLink in_link) throws IOException, InterruptedException, TimeoutException { + link = in_link; log = new AltosLog(link); name = link.name; previous = null; -- cgit v1.2.3 From d6df16525927d8096d1c0cccf4c86bf4c6599d53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jan 2012 22:43:48 -0800 Subject: Add altoslib/.gitignore --- altosui/altoslib/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 altosui/altoslib/.gitignore diff --git a/altosui/altoslib/.gitignore b/altosui/altoslib/.gitignore new file mode 100644 index 00000000..ad2f8cbf --- /dev/null +++ b/altosui/altoslib/.gitignore @@ -0,0 +1 @@ +classAltosLib.stamp -- cgit v1.2.3 From 81465a20049da40cd8d3cda920d6585ffe87bfe3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jan 2012 20:28:42 -0800 Subject: altosui: Move java altoslib to top level This will be shared with other (android) java code. Signed-off-by: Keith Packard --- Makefile.am | 2 +- altoslib/.gitignore | 1 + altoslib/Makefile.am | 69 +++ .../altusmetrum/AltosLib/AltosCRCException.java | 26 + .../org/altusmetrum/AltosLib/AltosConfigData.java | 184 ++++++++ .../src/org/altusmetrum/AltosLib/AltosConvert.java | 259 ++++++++++ .../org/altusmetrum/AltosLib/AltosEepromChunk.java | 102 ++++ .../altusmetrum/AltosLib/AltosEepromIterable.java | 475 +++++++++++++++++++ .../org/altusmetrum/AltosLib/AltosEepromLog.java | 100 ++++ .../altusmetrum/AltosLib/AltosEepromRecord.java | 139 ++++++ .../AltosLib/AltosEepromTeleScience.java | 59 +++ .../src/org/altusmetrum/AltosLib/AltosFile.java | 44 ++ .../altusmetrum/AltosLib/AltosFlightReader.java | 49 ++ .../org/altusmetrum/AltosLib/AltosFrequency.java | 48 ++ .../src/org/altusmetrum/AltosLib/AltosGPS.java | 248 ++++++++++ .../src/org/altusmetrum/AltosLib/AltosGPSSat.java | 32 ++ .../org/altusmetrum/AltosLib/AltosGreatCircle.java | 101 ++++ .../src/org/altusmetrum/AltosLib/AltosLib.java | 348 ++++++++++++++ .../src/org/altusmetrum/AltosLib/AltosLine.java | 30 ++ .../src/org/altusmetrum/AltosLib/AltosLink.java | 238 ++++++++++ .../src/org/altusmetrum/AltosLib/AltosLog.java | 126 +++++ .../src/org/altusmetrum/AltosLib/AltosParse.java | 79 ++++ .../org/altusmetrum/AltosLib/AltosPreferences.java | 365 +++++++++++++++ .../src/org/altusmetrum/AltosLib/AltosRecord.java | 319 +++++++++++++ .../altusmetrum/AltosLib/AltosRecordCompanion.java | 38 ++ .../altusmetrum/AltosLib/AltosRecordIterable.java | 29 ++ .../altusmetrum/AltosLib/AltosReplayReader.java | 56 +++ .../src/org/altusmetrum/AltosLib/AltosState.java | 210 +++++++++ .../org/altusmetrum/AltosLib/AltosTelemetry.java | 241 ++++++++++ .../AltosLib/AltosTelemetryIterable.java | 109 +++++ .../altusmetrum/AltosLib/AltosTelemetryMap.java | 63 +++ .../altusmetrum/AltosLib/AltosTelemetryReader.java | 119 +++++ .../altusmetrum/AltosLib/AltosTelemetryRecord.java | 126 +++++ .../AltosLib/AltosTelemetryRecordCompanion.java | 52 ++ .../AltosTelemetryRecordConfiguration.java | 64 +++ .../AltosLib/AltosTelemetryRecordGeneral.java | 43 ++ .../AltosLib/AltosTelemetryRecordLegacy.java | 521 +++++++++++++++++++++ .../AltosLib/AltosTelemetryRecordLocation.java | 93 ++++ .../AltosLib/AltosTelemetryRecordRaw.java | 77 +++ .../AltosLib/AltosTelemetryRecordSatellite.java | 52 ++ .../AltosLib/AltosTelemetryRecordSensor.java | 104 ++++ altosui/Makefile.am | 8 +- altosui/altoslib/.gitignore | 1 - altosui/altoslib/Makefile.am | 69 --- .../altusmetrum/AltosLib/AltosCRCException.java | 26 - .../org/altusmetrum/AltosLib/AltosConfigData.java | 184 -------- .../src/org/altusmetrum/AltosLib/AltosConvert.java | 259 ---------- .../org/altusmetrum/AltosLib/AltosEepromChunk.java | 102 ---- .../altusmetrum/AltosLib/AltosEepromIterable.java | 475 ------------------- .../org/altusmetrum/AltosLib/AltosEepromLog.java | 100 ---- .../altusmetrum/AltosLib/AltosEepromRecord.java | 139 ------ .../AltosLib/AltosEepromTeleScience.java | 59 --- .../src/org/altusmetrum/AltosLib/AltosFile.java | 44 -- .../altusmetrum/AltosLib/AltosFlightReader.java | 49 -- .../org/altusmetrum/AltosLib/AltosFrequency.java | 48 -- .../src/org/altusmetrum/AltosLib/AltosGPS.java | 248 ---------- .../src/org/altusmetrum/AltosLib/AltosGPSSat.java | 32 -- .../org/altusmetrum/AltosLib/AltosGreatCircle.java | 101 ---- .../src/org/altusmetrum/AltosLib/AltosLib.java | 348 -------------- .../src/org/altusmetrum/AltosLib/AltosLine.java | 30 -- .../src/org/altusmetrum/AltosLib/AltosLink.java | 238 ---------- .../src/org/altusmetrum/AltosLib/AltosLog.java | 126 ----- .../src/org/altusmetrum/AltosLib/AltosParse.java | 79 ---- .../org/altusmetrum/AltosLib/AltosPreferences.java | 365 --------------- .../src/org/altusmetrum/AltosLib/AltosRecord.java | 319 ------------- .../altusmetrum/AltosLib/AltosRecordCompanion.java | 38 -- .../altusmetrum/AltosLib/AltosRecordIterable.java | 29 -- .../altusmetrum/AltosLib/AltosReplayReader.java | 56 --- .../src/org/altusmetrum/AltosLib/AltosState.java | 210 --------- .../org/altusmetrum/AltosLib/AltosTelemetry.java | 241 ---------- .../AltosLib/AltosTelemetryIterable.java | 109 ----- .../altusmetrum/AltosLib/AltosTelemetryMap.java | 63 --- .../altusmetrum/AltosLib/AltosTelemetryReader.java | 119 ----- .../altusmetrum/AltosLib/AltosTelemetryRecord.java | 126 ----- .../AltosLib/AltosTelemetryRecordCompanion.java | 52 -- .../AltosTelemetryRecordConfiguration.java | 64 --- .../AltosLib/AltosTelemetryRecordGeneral.java | 43 -- .../AltosLib/AltosTelemetryRecordLegacy.java | 521 --------------------- .../AltosLib/AltosTelemetryRecordLocation.java | 93 ---- .../AltosLib/AltosTelemetryRecordRaw.java | 77 --- .../AltosLib/AltosTelemetryRecordSatellite.java | 52 -- .../AltosLib/AltosTelemetryRecordSensor.java | 104 ---- configure.ac | 2 +- 83 files changed, 5444 insertions(+), 5444 deletions(-) create mode 100644 altoslib/.gitignore create mode 100644 altoslib/Makefile.am create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosFile.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosLib.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosLine.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosLink.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosLog.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosParse.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosState.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java create mode 100644 altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java delete mode 100644 altosui/altoslib/.gitignore delete mode 100644 altosui/altoslib/Makefile.am delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java delete mode 100644 altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java diff --git a/Makefile.am b/Makefile.am index e1ee30a3..18845551 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src doc altosui ao-tools ao-utils +SUBDIRS=src doc altoslib altosui ao-tools ao-utils EXTRA_DIST = ChangeLog diff --git a/altoslib/.gitignore b/altoslib/.gitignore new file mode 100644 index 00000000..ad2f8cbf --- /dev/null +++ b/altoslib/.gitignore @@ -0,0 +1 @@ +classAltosLib.stamp diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am new file mode 100644 index 00000000..2ddd24e6 --- /dev/null +++ b/altoslib/Makefile.am @@ -0,0 +1,69 @@ +AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation + +JAVAROOT=bin + +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/*" + +SRC=src/org/altusmetrum/AltosLib +BIN=bin/org/altusmetrum/AltosLib + +AltosLibdir = $(datadir)/java + +AltosLib_JAVA = \ + $(SRC)/AltosLib.java \ + $(SRC)/AltosConfigData.java \ + $(SRC)/AltosConvert.java \ + $(SRC)/AltosCRCException.java \ + $(SRC)/AltosEepromChunk.java \ + $(SRC)/AltosEepromIterable.java \ + $(SRC)/AltosEepromLog.java \ + $(SRC)/AltosEepromRecord.java \ + $(SRC)/AltosEepromTeleScience.java \ + $(SRC)/AltosFile.java \ + $(SRC)/AltosFlightReader.java \ + $(SRC)/AltosFrequency.java \ + $(SRC)/AltosGPS.java \ + $(SRC)/AltosGPSSat.java \ + $(SRC)/AltosGreatCircle.java \ + $(SRC)/AltosLine.java \ + $(SRC)/AltosLink.java \ + $(SRC)/AltosLog.java \ + $(SRC)/AltosParse.java \ + $(SRC)/AltosPreferences.java \ + $(SRC)/AltosRecordCompanion.java \ + $(SRC)/AltosRecordIterable.java \ + $(SRC)/AltosRecord.java \ + $(SRC)/AltosReplayReader.java \ + $(SRC)/AltosState.java \ + $(SRC)/AltosTelemetry.java \ + $(SRC)/AltosTelemetryIterable.java \ + $(SRC)/AltosTelemetryMap.java \ + $(SRC)/AltosTelemetryReader.java \ + $(SRC)/AltosTelemetryRecordCompanion.java \ + $(SRC)/AltosTelemetryRecordConfiguration.java \ + $(SRC)/AltosTelemetryRecordGeneral.java \ + $(SRC)/AltosTelemetryRecord.java \ + $(SRC)/AltosTelemetryRecordLegacy.java \ + $(SRC)/AltosTelemetryRecordLocation.java \ + $(SRC)/AltosTelemetryRecordRaw.java \ + $(SRC)/AltosTelemetryRecordSatellite.java \ + $(SRC)/AltosTelemetryRecordSensor.java + +JAR=AltosLib.jar + +all-local: $(JAR) + +clean-local: + -rm -rf bin $(JAR) + +install-AltosLibJAVA: $(JAR) + @$(NORMAL_INSTALL) + test -z "$(AltosLibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosLibdir)" + echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosLibdir)/$(JAR)"; \ + $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosLibdir)" + +bin: + mkdir -p bin + +$(JAR): classAltosLib.stamp + jar cf $@ -C bin org diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java b/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java new file mode 100644 index 00000000..101c5363 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosCRCException extends Exception { + public int rssi; + + public AltosCRCException (int in_rssi) { + rssi = in_rssi; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java new file mode 100644 index 00000000..4ad4e58a --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java @@ -0,0 +1,184 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; + +public class AltosConfigData implements Iterable { + + /* Version information */ + public String manufacturer; + public String product; + public String version; + public int log_format; + public int serial; + + /* Strings returned */ + public LinkedList lines; + + /* Config information */ + public int config_major; + public int config_minor; + public int main_deploy; + public int apogee_delay; + public int radio_channel; + public int radio_setting; + public int radio_frequency; + public String callsign; + public int accel_cal_plus, accel_cal_minus; + public int radio_calibration; + public int flight_log_max; + public int ignite_mode; + public int stored_flight; + public int storage_size; + public int storage_erase_unit; + + public static String get_string(String line, String label) throws ParseException { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + return quoted; + } + throw new ParseException("mismatch", 0); + } + + public static int get_int(String line, String label) throws NumberFormatException, ParseException { + if (line.startsWith(label)) { + String tail = line.substring(label.length()).trim(); + String[] tokens = tail.split("\\s+"); + if (tokens.length > 0) + return Integer.parseInt(tokens[0]); + } + throw new ParseException("mismatch", 0); + } + + public Iterator iterator() { + return lines.iterator(); + } + + public int log_available() { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_TINY: + if (stored_flight == 0) + return 1; + return 0; + default: + if (flight_log_max <= 0) + return 1; + int log_space = storage_size - storage_erase_unit; + int log_used = stored_flight * flight_log_max; + + if (log_used >= log_space) + return 0; + return (log_space - log_used) / flight_log_max; + } + } + + int[] parse_version(String v) { + String[] parts = v.split("\\."); + int r[] = new int[parts.length]; + + for (int i = 0; i < parts.length; i++) { + try { + r[i] = Altos.fromdec(parts[i]); + } catch (NumberFormatException n) { + r[i] = 0; + } + } + + return r; + } + + public int compare_version(String other) { + int[] me = parse_version(version); + int[] them = parse_version(other); + + int l = Math.min(me.length, them.length); + + for (int i = 0; i < l; i++) { + int d = me[i] - them[i]; + if (d != 0) + return d; + } + if (me.length > l) + return 1; + if (them.length > l) + return -1; + return 0; + } + + public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { + link.printf("c s\np\nf\nl\nv\n"); + lines = new LinkedList(); + radio_setting = 0; + radio_frequency = 0; + stored_flight = 0; + for (;;) { + String line = link.get_reply(); + if (line == null) + throw new TimeoutException(); + if (line.contains("Syntax error")) + continue; + lines.add(line); + try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { log_format = get_int(line, "log-format"); } catch (Exception e) {} + try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} + try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} + try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} + try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} + try { + radio_frequency = get_int(line, "Frequency:"); + if (radio_frequency < 0) + radio_frequency = 434550; + } catch (Exception e) {} + try { + if (line.startsWith("Accel cal")) { + String[] bits = line.split("\\s+"); + if (bits.length >= 6) { + accel_cal_plus = Integer.parseInt(bits[3]); + accel_cal_minus = Integer.parseInt(bits[5]); + } + } + } catch (Exception e) {} + try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} + try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} + try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} + try { version = get_string(line,"software-version"); } catch (Exception e) {} + try { product = get_string(line,"product"); } catch (Exception e) {} + + try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} + try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} + try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} + + /* signals the end of the version info */ + if (line.startsWith("software-version")) + break; + } + } + +} \ No newline at end of file diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java b/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java new file mode 100644 index 00000000..3527b575 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java @@ -0,0 +1,259 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Sensor data conversion functions + */ +package org.altusmetrum.AltosLib; + +public class AltosConvert { + /* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= Math.pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * Math.pow(base, exponent); + } + + return pressure; + } + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ + public static double + pressure_to_altitude(double pressure) + { + + double next_base_temperature = LAYER0_BASE_TEMPERATURE; + double next_base_pressure = LAYER0_BASE_PRESSURE; + + double altitude; + double base_pressure; + double base_temperature; + double base; /* base for function to determine base pressure of next layer */ + double exponent; /* exponent for function to determine base pressure + of next layer */ + double coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= Math.exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= Math.pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * Math.log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (Math.pow(base, exponent) - 1); + } + + return altitude; + } + + public static double + cc_battery_to_voltage(double battery) + { + return battery / 32767.0 * 5.0; + } + + public static double + cc_ignitor_to_voltage(double ignite) + { + return ignite / 32767 * 15.0; + } + + public static double radio_to_frequency(int freq, int setting, int cal, int channel) { + double f; + + if (freq > 0) + f = freq / 1000.0; + else { + if (setting <= 0) + setting = cal; + f = 434.550 * setting / cal; + /* Round to nearest 50KHz */ + f = Math.floor (20.0 * f + 0.5) / 20.0; + } + return f + channel * 0.100; + } + + public static int radio_frequency_to_setting(double frequency, int cal) { + double set = frequency / 434.550 * cal; + + return (int) Math.floor (set + 0.5); + } + + public static int radio_frequency_to_channel(double frequency) { + int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); + + if (channel < 0) + channel = 0; + if (channel > 9) + channel = 9; + return channel; + } + + public static double radio_channel_to_frequency(int channel) { + return 434.550 + channel * 0.100; + } + + public static int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + public static double meters_to_feet(double meters) { + return meters * (100 / (2.54 * 12)); + } + + public static double meters_to_mach(double meters) { + return meters / 343; /* something close to mach at usual rocket sites */ + } + + public static double meters_to_g(double meters) { + return meters / 9.80665; + } + + public static int checksum(int[] data, int start, int length) { + int csum = 0x5a; + for (int i = 0; i < length; i++) + csum += data[i + start]; + return csum & 0xff; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java new file mode 100644 index 00000000..6d889723 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java @@ -0,0 +1,102 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.concurrent.*; + +public class AltosEepromChunk { + + public static final int chunk_size = 256; + public static final int per_line = 8; + + public int data[]; + public int address; + public ParseException parse_exception = null; + + int[] ParseHex(String line) { + String[] tokens = line.split("\\s+"); + int[] array = new int[tokens.length]; + + for (int i = 0; i < tokens.length; i++) + try { + array[i] = Integer.parseInt(tokens[i], 16); + } catch (NumberFormatException ne) { + return null; + } + return array; + } + + public int data(int offset) { + return data[offset]; + } + + public int data16(int offset) { + return data[offset] | (data[offset + 1] << 8); + } + + public int data32(int offset) { + return data[offset] | (data[offset + 1] << 8) | + (data[offset+2] << 16) | (data[offset+3] << 24); + } + + public boolean erased(int start, int len) { + for (int i = 0; i < len; i++) + if (data[start+i] != 0xff) + return false; + return true; + } + + public AltosEepromChunk(AltosLink link, int block, boolean flush) + throws TimeoutException, InterruptedException { + + int offset; + + data = new int[chunk_size]; + address = block * chunk_size; + if (flush) + link.flush_input(); + link.printf("e %x\n", block); + + for (offset = 0; offset < chunk_size; offset += per_line) { + try { + String line = link.get_reply(5000); + + if (line == null) + throw new TimeoutException(); + + int[] values = ParseHex(line); + + if (values == null || values.length != per_line + 1) + throw new ParseException(String.format("invalid line %s", line), 0); + if (values[0] != offset) + throw new ParseException(String.format("data address out of sync at 0x%x", + address + offset), 0); + for (int i = 0; i < per_line; i++) + data[offset + i] = values[1 + i]; + } catch (ParseException pe) { + for (int i = 0; i < per_line; i++) + data[offset + i] = 0xff; + if (parse_exception == null) + parse_exception = pe; + } + } + } +} \ No newline at end of file diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java new file mode 100644 index 00000000..f1397c7b --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java @@ -0,0 +1,475 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedRecord extends AltosEepromRecord implements Comparable { + + public int index; + + public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + 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 String toString() { + return String.format("%d.%d %04x %04x %04x", + cmd, index, tick, a, b); + } + + public int compareTo(AltosOrderedRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor; + + boolean has_accel; + boolean has_gps; + boolean has_ignite; + + AltosEepromRecord flight_record; + AltosEepromRecord gps_date_record; + + TreeSet records; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + int sensor_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case AltosLib.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.a; + state.flight_accel = record.a; + state.flight = record.b; + eeprom.boost_tick = record.tick; + break; + case AltosLib.AO_LOG_SENSOR: + state.accel = record.a; + state.pres = record.b; + if (state.state < AltosLib.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + } + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); + eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; + has_accel = true; + break; + case AltosLib.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } + eeprom.seen |= seen_sensor; + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.temp = record.a; + state.batt = record.b; + eeprom.seen |= seen_temp_volt; + break; + case AltosLib.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + has_ignite = true; + break; + case AltosLib.AO_LOG_STATE: + state.state = record.a; + break; + case AltosLib.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + state.new_gps = true; + has_gps = true; + break; + case AltosLib.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case AltosLib.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case AltosLib.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case AltosLib.AO_LOG_CONFIG_VERSION: + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + break; + case AltosLib.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case AltosLib.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case AltosLib.AO_LOG_RADIO_CAL: + break; + case AltosLib.AO_LOG_MANUFACTURER: + break; + case AltosLib.AO_LOG_PRODUCT: + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + state.serial = record.a; + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + break; + } + state.seen |= eeprom.seen; + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = AltosLib.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedRecord record = iterator.next(); + switch (record.cmd) { + case AltosLib.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case AltosLib.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case AltosLib.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case AltosLib.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case AltosLib.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.a); + break; + case AltosLib.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case AltosLib.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + case Altos.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.a); + break; + case Altos.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.a); + break; + } + } + } + + /* + * 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; + + /* Make sure this looks like a good GPS value */ + if ((flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT); + flags |= AltosLib.AO_GPS_RUNNING; + flags |= AltosLib.AO_GPS_VALID; + + 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedRecord last_gps_time = null; + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); + if (record == null) + break; + if (record.cmd == AltosLib.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == AltosLib.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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 == AltosLib.AO_LOG_GPS_DATE) { + gps_date_record = record; + continue; + } + + /* go back and fix up any missing time values */ + if (record.cmd == AltosLib.AO_LOG_GPS_TIME) { + last_gps_time = record; + if (missing_time) { + Iterator iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedRecord old = iterator.next(); + if (old.cmd == AltosLib.AO_LOG_GPS_TIME && + old.a == -1 && old.b == -1) + { + update_time(record, old); + } + } + missing_time = false; + } + } + + if (record.cmd == AltosLib.AO_LOG_GPS_LAT) { + if (last_gps_time == null || last_gps_time.tick != record.tick) { + AltosOrderedRecord add_gps_time = new AltosOrderedRecord(AltosLib.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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == AltosLib.AO_LOG_STATE && + record.a == AltosLib.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java new file mode 100644 index 00000000..7fca4bd9 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java @@ -0,0 +1,100 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +/* + * Extract a bit of information from an eeprom-stored flight log. + */ + +public class AltosEepromLog { + public int serial; + public boolean has_flight; + public int flight; + public int start_block; + public int end_block; + + public int year, month, day; + + public boolean selected; + + public AltosEepromLog(AltosConfigData config_data, + AltosLink link, + int in_flight, int in_start_block, + int in_end_block) + throws InterruptedException, TimeoutException { + + int block; + boolean has_date = false; + + flight = in_flight; + if (flight != 0) + has_flight = true; + start_block = in_start_block; + end_block = in_end_block; + serial = config_data.serial; + + /* + * Select all flights for download + */ + selected = true; + + /* + * Look in TeleMetrum log data for date + */ + if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN || + config_data.log_format == AltosLib.AO_LOG_FORMAT_FULL) + { + /* + * Only look in the first two blocks so that this + * process doesn't take a long time + */ + if (in_end_block > in_start_block + 2) + in_end_block = in_start_block + 2; + + for (block = in_start_block; block < in_end_block; block++) { + AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == in_start_block); + + for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { + try { + AltosEepromRecord r = new AltosEepromRecord(eechunk, i); + + if (r.cmd == AltosLib.AO_LOG_FLIGHT) { + flight = r.b; + has_flight = true; + } + if (r.cmd == AltosLib.AO_LOG_GPS_DATE) { + year = 2000 + (r.a & 0xff); + month = (r.a >> 8) & 0xff; + day = (r.b & 0xff); + has_date = true; + } + } catch (ParseException pe) { + } + } + if (has_date && has_flight) + break; + } + } + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java new file mode 100644 index 00000000..1e845f46 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java @@ -0,0 +1,139 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosEepromRecord { + public int cmd; + public int tick; + public int a; + public int b; + public String data; + public boolean tick_valid; + + public static final int record_length = 8; + + public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { + + cmd = chunk.data(start); + tick_valid = true; + + tick_valid = !chunk.erased(start, record_length); + if (tick_valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + cmd = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start + 2); + a = chunk.data16(start + 4); + b = chunk.data16(start + 6); + + data = null; + } + + public AltosEepromRecord (String line) { + tick_valid = false; + tick = 0; + a = 0; + b = 0; + data = null; + if (line == null) { + cmd = AltosLib.AO_LOG_INVALID; + data = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + if (tokens[0].length() == 1) { + if (tokens.length != 4) { + cmd = AltosLib.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 = AltosLib.AO_LOG_CONFIG_VERSION; + data = tokens[2]; + } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { + cmd = AltosLib.AO_LOG_MAIN_DEPLOY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { + cmd = AltosLib.AO_LOG_APOGEE_DELAY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { + cmd = AltosLib.AO_LOG_RADIO_CHANNEL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Callsign:")) { + cmd = AltosLib.AO_LOG_CALLSIGN; + data = tokens[1].replaceAll("\"",""); + } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { + cmd = AltosLib.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 = AltosLib.AO_LOG_RADIO_CAL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; + a = Integer.parseInt(tokens[3]); + } else if (tokens[0].equals("manufacturer")) { + cmd = AltosLib.AO_LOG_MANUFACTURER; + data = tokens[1]; + } else if (tokens[0].equals("product")) { + cmd = AltosLib.AO_LOG_PRODUCT; + data = tokens[1]; + } else if (tokens[0].equals("serial-number")) { + cmd = AltosLib.AO_LOG_SERIAL_NUMBER; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = AltosLib.AO_LOG_LOG_FORMAT; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("software-version")) { + cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; + data = tokens[1]; + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } catch (NumberFormatException ne) { + cmd = AltosLib.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; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java new file mode 100644 index 00000000..1758fa34 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java @@ -0,0 +1,59 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosEepromTeleScience { + public int type; + public int tick; + public int tm_state; + public int tm_tick; + public int[] data; + public boolean valid; + + public static final int AO_LOG_TELESCIENCE_START = 's'; + public static final int AO_LOG_TELESCIENCE_DATA = 'd'; + + static final int max_data = 12; + public static final int record_length = 32; + + public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { + type = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + type = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + tm_tick = chunk.data16(start+4); + tm_state = chunk.data(start+6); + data = new int[max_data]; + for (int i = 0; i < max_data; i++) + data[i] = chunk.data16(start + 8 + i * 2); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java b/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java new file mode 100644 index 00000000..d2e4f2f7 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java @@ -0,0 +1,44 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.io.File; +import java.util.*; + +public class AltosFile extends File { + + public AltosFile(int year, int month, int day, int serial, int flight, String extension) { + super (AltosPreferences.logdir(), + String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", + year, month, day, serial, flight, extension)); + } + + public AltosFile(int serial, int flight, String extension) { + this(Calendar.getInstance().get(Calendar.YEAR), + Calendar.getInstance().get(Calendar.MONTH) + 1, + Calendar.getInstance().get(Calendar.DAY_OF_MONTH), + serial, + flight, + extension); + } + + public AltosFile(AltosRecord telem) { + this(telem.serial, telem.flight, "telem"); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java b/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java new file mode 100644 index 00000000..3fdea469 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java @@ -0,0 +1,49 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.io.*; +import java.util.concurrent.*; + +public class AltosFlightReader { + public String name; + + public int serial; + + public void init() { } + + public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } + + public void close(boolean interrupted) { } + + public void set_frequency(double frequency) throws InterruptedException, TimeoutException { } + + public void save_frequency() { } + + public void set_telemetry(int telemetry) { } + + public void save_telemetry() { } + + public void update(AltosState state) throws InterruptedException { } + + public boolean supports_telemetry(int telemetry) { return false; } + + public File backing_file() { return null; } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java new file mode 100644 index 00000000..f08ff116 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java @@ -0,0 +1,48 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosFrequency { + public double frequency; + public String description; + + public String toString() { + return String.format("%7.3f MHz %-20s", + frequency, description); + } + + public String toShortString() { + return String.format("%7.3f MHz %s", + frequency, description); + } + + public boolean close(double f) { + double diff = Math.abs(frequency - f); + + return diff < 0.010; + } + + public AltosFrequency(double f, String d) { + frequency = f; + description = d; + } +} \ No newline at end of file diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java b/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java new file mode 100644 index 00000000..f078a469 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java @@ -0,0 +1,248 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; + +public class AltosGPS { + + public final static int MISSING = AltosRecord.MISSING; + + public int nsat; + public boolean locked; + public boolean connected; + public double lat; /* degrees (+N -S) */ + public double lon; /* degrees (+E -W) */ + public int alt; /* m */ + public int year; + public int month; + public int day; + public int hour; + public int minute; + public int second; + + public double ground_speed; /* m/s */ + public int course; /* degrees */ + public double climb_rate; /* m/s */ + public double hdop; /* unitless */ + public double vdop; /* unitless */ + public int h_error; /* m */ + public int v_error; /* m */ + + public AltosGPSSat[] cc_gps_sat; /* tracking data */ + + public 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]); + } + + public 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 = AltosParse.parse_int(hms[0]); + minute = AltosParse.parse_int(hms[1]); + second = AltosParse.parse_int(hms[2]); + } + + public void ClearGPSTime() { + year = month = day = 0; + hour = minute = second = 0; + } + + public AltosGPS(AltosTelemetryMap map) throws ParseException { + String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, + AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); + + nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); + if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { + connected = true; + locked = true; + lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); + lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); + alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); + year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); + if (year != MISSING) + year += 2000; + month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); + day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); + + hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); + minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); + second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); + + ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, + AltosRecord.MISSING, 1/100.0); + course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, + AltosRecord.MISSING); + hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); + vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); + h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); + v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); + } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { + connected = true; + locked = false; + } else { + connected = false; + locked = false; + } + } + + 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"); + + connected = false; + locked = false; + lat = lon = 0; + alt = 0; + ClearGPSTime(); + if ((words[i]).equals("unlocked")) { + connected = true; + i++; + } else if ((words[i]).equals("not-connected")) { + i++; + } else if (words.length >= 40) { + locked = true; + connected = true; + + 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(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++; + } + 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 AltosGPSSat[tracking_channels]; + for (int chan = 0; chan < tracking_channels; chan++) { + cc_gps_sat[chan] = new 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 AltosGPSSat[0]; + } + + public void set_latitude(int in_lat) { + lat = in_lat / 10.0e7; + } + + public void set_longitude(int in_lon) { + lon = in_lon / 10.0e7; + } + + public void set_time(int hour, int minute, int second) { + hour = hour; + minute = minute; + second = second; + } + + public void set_date(int year, int month, int day) { + year = year; + month = month; + day = day; + } + + public void set_flags(int flags) { + flags = flags; + } + + public void set_altitude(int altitude) { + altitude = altitude; + } + + public void add_sat(int svid, int c_n0) { + if (cc_gps_sat == null) { + cc_gps_sat = new AltosGPSSat[1]; + } else { + AltosGPSSat[] new_gps_sat = new AltosGPSSat[cc_gps_sat.length + 1]; + for (int i = 0; i < cc_gps_sat.length; i++) + new_gps_sat[i] = cc_gps_sat[i]; + cc_gps_sat = new_gps_sat; + } + AltosGPSSat sat = new AltosGPSSat(); + sat.svid = svid; + sat.c_n0 = c_n0; + cc_gps_sat[cc_gps_sat.length - 1] = sat; + } + + public AltosGPS() { + ClearGPSTime(); + cc_gps_sat = null; + } + + public AltosGPS(AltosGPS old) { + nsat = old.nsat; + locked = old.locked; + connected = old.connected; + lat = old.lat; /* degrees (+N -S) */ + lon = old.lon; /* degrees (+E -W) */ + alt = old.alt; /* m */ + year = old.year; + month = old.month; + day = old.day; + hour = old.hour; + minute = old.minute; + second = old.second; + + ground_speed = old.ground_speed; /* m/s */ + course = old.course; /* degrees */ + climb_rate = old.climb_rate; /* m/s */ + hdop = old.hdop; /* unitless? */ + h_error = old.h_error; /* m */ + v_error = old.v_error; /* m */ + + if (old.cc_gps_sat != null) { + cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; + for (int i = 0; i < old.cc_gps_sat.length; i++) { + cc_gps_sat[i] = new AltosGPSSat(); + cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; + cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; + } + } + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java b/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java new file mode 100644 index 00000000..faa1ec8d --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java @@ -0,0 +1,32 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosGPSSat { + public int svid; + public int c_n0; + + public AltosGPSSat(int s, int c) { + svid = s; + c_n0= c; + } + + public AltosGPSSat() { + } +} + diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java b/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java new file mode 100644 index 00000000..76b71859 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.Math; + +public class AltosGreatCircle { + public double distance; + public double bearing; + + double sqr(double a) { return a * a; } + + static final double rad = Math.PI / 180; + static final double earth_radius = 6371.2 * 1000; /* in meters */ + + public static final int BEARING_LONG = 0; + public static final int BEARING_SHORT = 1; + public static final int BEARING_VOICE = 2; + + public String bearing_words(int length) { + String [][] bearing_string = { + { + "North", "North North East", "North East", "East North East", + "East", "East South East", "South East", "South South East", + "South", "South South West", "South West", "West South West", + "West", "West North West", "North West", "North North West" + }, { + "N", "NNE", "NE", "ENE", + "E", "ESE", "SE", "SSE", + "S", "SSW", "SW", "WSW", + "W", "WNW", "NW", "NNW" + }, { + "north", "nor nor east", "north east", "east nor east", + "east", "east sow east", "south east", "sow sow east", + "south", "sow sow west", "south west", "west sow west", + "west", "west nor west", "north west", "nor nor west " + } + }; + return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; + } + + public AltosGreatCircle (double start_lat, double start_lon, + double end_lat, double end_lon) + { + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + + sqr(Math.cos(lat1) * Math.sin(lat2) - + Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); + double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); + double d = Math.atan2(vdn,vdd); + double course; + + if (Math.cos(lat1) < 1e-20) { + if (lat1 > 0) + course = Math.PI; + else + course = -Math.PI; + } else { + if (d < 1e-10) + course = 0; + else + course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / + (Math.sin(d)*Math.cos(lat1))); + if (Math.sin(lon2-lon1) > 0) + course = 2 * Math.PI-course; + } + 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; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java b/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java new file mode 100644 index 00000000..2921d040 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java @@ -0,0 +1,348 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.awt.*; +import java.util.*; +import java.text.*; +import java.nio.charset.Charset; + +public class AltosLib { + /* EEProm command letters */ + public static final int AO_LOG_FLIGHT = 'F'; + public static final int AO_LOG_SENSOR = 'A'; + public static final int AO_LOG_TEMP_VOLT = 'T'; + public static final int AO_LOG_DEPLOY = 'D'; + public static final int AO_LOG_STATE = 'S'; + public static final int AO_LOG_GPS_TIME = 'G'; + public static final int AO_LOG_GPS_LAT = 'N'; + public static final int AO_LOG_GPS_LON = 'W'; + public static final int AO_LOG_GPS_ALT = 'H'; + public static final int AO_LOG_GPS_SAT = 'V'; + public static final int AO_LOG_GPS_DATE = 'Y'; + public static final int AO_LOG_PRESSURE = 'P'; + + /* Added for header fields in eeprom files */ + public static final int AO_LOG_CONFIG_VERSION = 1000; + public static final int AO_LOG_MAIN_DEPLOY = 1001; + public static final int AO_LOG_APOGEE_DELAY = 1002; + public static final int AO_LOG_RADIO_CHANNEL = 1003; + public static final int AO_LOG_CALLSIGN = 1004; + public static final int AO_LOG_ACCEL_CAL = 1005; + public static final int AO_LOG_RADIO_CAL = 1006; + public static final int AO_LOG_MAX_FLIGHT_LOG = 1007; + public static final int AO_LOG_MANUFACTURER = 2000; + public static final int AO_LOG_PRODUCT = 2001; + public static final int AO_LOG_SERIAL_NUMBER = 2002; + public static final int AO_LOG_LOG_FORMAT = 2003; + public static final int AO_LOG_SOFTWARE_VERSION = 9999; + + /* Added to flag invalid records */ + public static final int AO_LOG_INVALID = -1; + + /* Flight state numbers and names */ + public static final int ao_flight_startup = 0; + public static final int ao_flight_idle = 1; + public static final int ao_flight_pad = 2; + public static final int ao_flight_boost = 3; + public static final int ao_flight_fast = 4; + public static final int ao_flight_coast = 5; + public static final int ao_flight_drogue = 6; + public static final int ao_flight_main = 7; + public static final int ao_flight_landed = 8; + public static final int ao_flight_invalid = 9; + + /* Telemetry modes */ + public static final int ao_telemetry_off = 0; + public static final int ao_telemetry_min = 1; + public static final int ao_telemetry_standard = 1; + public static final int ao_telemetry_0_9 = 2; + public static final int ao_telemetry_0_8 = 3; + public static final int ao_telemetry_max = 3; + + public static final String[] ao_telemetry_name = { + "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" + }; + + public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt"; + + public static final int ao_telemetry_standard_len = 32; + public static final int ao_telemetry_0_9_len = 95; + public static final int ao_telemetry_0_8_len = 94; + + public static final int[] ao_telemetry_len = { + 0, 32, 95, 94 + }; + + public static HashMap string_to_state = new HashMap(); + + public static boolean map_initialized = false; + + public static void initialize_map() + { + string_to_state.put("startup", ao_flight_startup); + string_to_state.put("idle", ao_flight_idle); + string_to_state.put("pad", ao_flight_pad); + string_to_state.put("boost", ao_flight_boost); + string_to_state.put("fast", ao_flight_fast); + string_to_state.put("coast", ao_flight_coast); + string_to_state.put("drogue", ao_flight_drogue); + string_to_state.put("apogee", ao_flight_coast); + string_to_state.put("main", ao_flight_main); + string_to_state.put("landed", ao_flight_landed); + string_to_state.put("invalid", ao_flight_invalid); + map_initialized = true; + } + + public static int telemetry_len(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_len[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + public static String telemetry_name(int telemetry) { + if (telemetry <= ao_telemetry_max) + return ao_telemetry_name[telemetry]; + throw new IllegalArgumentException(String.format("Invalid telemetry %d", + telemetry)); + } + + public static String[] state_to_string = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid", + }; + + public static String[] state_to_string_capital = { + "Startup", + "Idle", + "Pad", + "Boost", + "Fast", + "Coast", + "Drogue", + "Main", + "Landed", + "Invalid", + }; + + public static int state(String state) { + if (!map_initialized) + initialize_map(); + if (string_to_state.containsKey(state)) + return string_to_state.get(state); + return ao_flight_invalid; + } + + public static String state_name(int state) { + if (state < 0 || state_to_string.length <= state) + return "invalid"; + return state_to_string[state]; + } + + public static final int AO_GPS_VALID = (1 << 4); + public static final int AO_GPS_RUNNING = (1 << 5); + public static final int AO_GPS_DATE_VALID = (1 << 6); + public static final int AO_GPS_NUM_SAT_SHIFT = 0; + public static final int AO_GPS_NUM_SAT_MASK = 0xf; + + public static final int AO_LOG_FORMAT_UNKNOWN = 0; + public static final int AO_LOG_FORMAT_FULL = 1; + public static final int AO_LOG_FORMAT_TINY = 2; + public static final int AO_LOG_FORMAT_TELEMETRY = 3; + public static final int AO_LOG_FORMAT_TELESCIENCE = 4; + public static final int AO_LOG_FORMAT_NONE = 127; + + public static boolean isspace(int c) { + switch (c) { + case ' ': + case '\t': + return true; + } + return false; + } + + public 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; + } + + public static boolean ishex(String s) { + for (int i = 0; i < s.length(); i++) + if (!ishex(s.charAt(i))) + return false; + return true; + } + + public 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; + } + + public 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; + } + + public static boolean isdec(int c) { + if ('0' <= c && c <= '9') + return true; + return false; + } + + public static boolean isdec(String s) { + for (int i = 0; i < s.length(); i++) + if (!isdec(s.charAt(i))) + return false; + return true; + } + + public static int fromdec(int c) { + if ('0' <= c && c <= '9') + return c - '0'; + return -1; + } + + public static int int8(int[] bytes, int i) { + return (int) (byte) bytes[i]; + } + + public static int uint8(int[] bytes, int i) { + return bytes[i]; + } + + public static int int16(int[] bytes, int i) { + return (int) (short) (bytes[i] + (bytes[i+1] << 8)); + } + + public static int uint16(int[] bytes, int i) { + return bytes[i] + (bytes[i+1] << 8); + } + + public static int uint32(int[] bytes, int i) { + return bytes[i] + + (bytes[i+1] << 8) + + (bytes[i+2] << 16) + + (bytes[i+3] << 24); + } + + public static final Charset unicode_set = Charset.forName("UTF-8"); + + public static String string(int[] bytes, int s, int l) { + if (s + l > bytes.length) { + if (s > bytes.length) { + s = bytes.length; + l = 0; + } else { + l = bytes.length - s; + } + } + + int i; + for (i = l - 1; i >= 0; i--) + if (bytes[s+i] != 0) + break; + + l = i + 1; + byte[] b = new byte[l]; + + for (i = 0; i < l; i++) + b[i] = (byte) bytes[s+i]; + String n = new String(b, unicode_set); + return n; + } + + public static int hexbyte(String s, int i) { + int c0, c1; + + if (s.length() < i + 2) + throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); + c0 = s.charAt(i); + if (!ishex(c0)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c0)); + c1 = s.charAt(i+1); + if (!ishex(c1)) + throw new NumberFormatException(String.format("invalid hex \"%c\"", c1)); + return fromhex(c0) * 16 + fromhex(c1); + } + + public static int[] hexbytes(String s) { + int n; + int[] r; + int i; + + if ((s.length() & 1) != 0) + throw new NumberFormatException(String.format("invalid line \"%s\"", s)); + n = s.length() / 2; + r = new int[n]; + for (i = 0; i < n; i++) + r[i] = hexbyte(s, i * 2); + return r; + } + + public 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; + } + + public static String replace_extension(String input, String extension) { + int dot = input.lastIndexOf("."); + if (dot > 0) + input = input.substring(0,dot); + return input.concat(extension); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java b/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java new file mode 100644 index 00000000..5627795a --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java @@ -0,0 +1,30 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosLine { + public String line; + + public AltosLine() { + line = null; + } + + public AltosLine(String s) { + line = s; + } +} \ No newline at end of file diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java new file mode 100644 index 00000000..9b80e916 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java @@ -0,0 +1,238 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.io.*; +import java.util.concurrent.*; +import java.util.*; +import java.text.*; + +public abstract class AltosLink { + public abstract void print(String data); + public abstract void close(); + + public static boolean debug = false; + public static void set_debug(boolean in_debug) { debug = in_debug; } + LinkedList pending_output = new LinkedList(); + + public LinkedList> monitors = new LinkedList> ();; + public LinkedBlockingQueue reply_queue = new LinkedBlockingQueue(); + + public void add_monitor(LinkedBlockingQueue q) { + set_monitor(true); + monitors.add(q); + } + + public void remove_monitor(LinkedBlockingQueue q) { + monitors.remove(q); + if (monitors.isEmpty()) + set_monitor(false); + } + + public void printf(String format, Object ... arguments) { + String line = String.format(format, arguments); + if (debug) + pending_output.add(line); + print(line); + } + + public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { + flush_output(); + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) + return line.line; + return null; + } + + public String get_reply(int timeout) throws InterruptedException { + try { + return get_reply_no_dialog(timeout); + } catch (TimeoutException te) { + return null; + } + } + + public String get_reply() throws InterruptedException { + return get_reply(5000); + } + + public void add_telem(AltosLine line) throws InterruptedException { + for (int e = 0; e < monitors.size(); e++) { + LinkedBlockingQueue q = monitors.get(e); + q.put(line); + } + } + + public void add_reply(AltosLine line) throws InterruptedException { + reply_queue.put (line); + } + + public void add_string(String line) throws InterruptedException { + if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { + add_telem(new AltosLine(line)); + } else { + add_reply(new AltosLine(line)); + } + } + + public void add_bytes(byte[] bytes, int len) throws InterruptedException { + String line; + try { + line = new String(bytes, 0, len, "UTF-8"); + } catch (UnsupportedEncodingException ue) { + line = ""; + for (int i = 0; i < len; i++) + line = line + bytes[i]; + } + if (debug) + System.out.printf("\t\t\t\t\t%s\n", line); + add_string(line); + } + + public void flush_output() { + for (String s : pending_output) + System.out.print(s); + pending_output.clear(); + } + + public void flush_input(int timeout) throws InterruptedException { + flush_output(); + boolean got_some; + + do { + Thread.sleep(timeout); + got_some = !reply_queue.isEmpty(); + reply_queue.clear(); + } while (got_some); + } + + + public void flush_input() throws InterruptedException { + flush_input(100); + } + + + /* + * Various command-level operations on + * the link + */ + public boolean monitor_mode = false; + public int telemetry = AltosLib.ao_telemetry_standard; + public double frequency; + AltosConfigData config_data; + + private int telemetry_len() { + return AltosLib.telemetry_len(telemetry); + } + + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + if (monitor_mode) + printf("m 0\nm %x\n", telemetry_len()); + flush_output(); + } + + public void set_monitor(boolean monitor) { + monitor_mode = monitor; + if (monitor) + printf("m %x\n", telemetry_len()); + else + printf("m 0\n"); + flush_output(); + } + + private void set_channel(int channel) { + if (monitor_mode) + printf("m 0\nc r %d\nm %x\n", + channel, telemetry_len()); + else + printf("c r %d\n", channel); + flush_output(); + } + + private void set_radio_setting(int setting) { + if (monitor_mode) + printf("m 0\nc R %d\nm %x\n", + setting, telemetry_len()); + else + printf("c R %d\n", setting); + flush_output(); + } + + public void set_radio_frequency(double frequency, + boolean has_setting, + int cal) { + if (debug) + System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); + if (has_setting) + set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); + else + set_channel(AltosConvert.radio_frequency_to_channel(frequency)); + } + + public AltosConfigData config_data() throws InterruptedException, TimeoutException { + if (config_data == null) + config_data = new AltosConfigData(this); + return config_data; + } + + public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + config_data(); + set_radio_frequency(frequency, + config_data.radio_setting != 0, + config_data.radio_calibration); + } + + public void set_callsign(String callsign) { + printf ("c c %s\n", callsign); + flush_output(); + } + + public boolean remote; + public int serial; + public String name; + + public void start_remote() throws TimeoutException, InterruptedException { + if (debug) + System.out.printf("start remote %7.3f\n", frequency); + if (frequency == 0.0) + frequency = AltosPreferences.frequency(serial); + set_radio_frequency(frequency); + set_callsign(AltosPreferences.callsign()); + printf("p\nE 0\n"); + flush_input(); + remote = true; + } + + public void stop_remote() throws InterruptedException { + if (debug) + System.out.printf("stop remote\n"); + try { + flush_input(); + } finally { + printf ("~\n"); + flush_output(); + } + remote = false; + } + + public AltosLink() { + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java b/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java new file mode 100644 index 00000000..08c45ca8 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java @@ -0,0 +1,126 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.lang.*; +import java.util.*; +import java.text.ParseException; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * This creates a thread to capture telemetry data and write it to + * a log file + */ +class AltosLog implements Runnable { + + LinkedBlockingQueue input_queue; + LinkedBlockingQueue pending_queue; + int serial; + int flight; + FileWriter log_file; + Thread log_thread; + AltosFile file; + + private void close_log_file() { + if (log_file != null) { + try { + log_file.close(); + } catch (IOException io) { + } + log_file = null; + } + } + + void close() { + close_log_file(); + if (log_thread != null) { + log_thread.interrupt(); + log_thread = null; + } + } + + File file() { + return file; + } + + boolean open (AltosRecord telem) throws IOException { + AltosFile a = new AltosFile(telem); + + System.out.printf("open %s\n", a.toString()); + log_file = new FileWriter(a, true); + if (log_file != null) { + while (!pending_queue.isEmpty()) { + try { + String s = pending_queue.take(); + log_file.write(s); + log_file.write('\n'); + } catch (InterruptedException ie) { + } + } + log_file.flush(); + file = a; + } + return log_file != null; + } + + public void run () { + try { + AltosRecord previous = null; + for (;;) { + AltosLine line = input_queue.take(); + if (line.line == null) + continue; + try { + AltosRecord telem = AltosTelemetry.parse(line.line, previous); + if (telem.serial != 0 && telem.flight != 0 && + (telem.serial != serial || telem.flight != flight || log_file == null)) + { + close_log_file(); + serial = telem.serial; + flight = telem.flight; + open(telem); + } + previous = telem; + } catch (ParseException pe) { + } catch (AltosCRCException ce) { + } + if (log_file != null) { + log_file.write(line.line); + log_file.write('\n'); + log_file.flush(); + } else + pending_queue.put(line.line); + } + } catch (InterruptedException ie) { + } catch (IOException ie) { + } + close(); + } + + public AltosLog (AltosLink link) { + pending_queue = new LinkedBlockingQueue (); + input_queue = new LinkedBlockingQueue (); + link.add_monitor(input_queue); + serial = -1; + flight = -1; + log_file = null; + log_thread = new Thread(this); + log_thread.start(); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java b/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java new file mode 100644 index 00000000..7d832f1a --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java @@ -0,0 +1,79 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.text.*; +import java.lang.*; + +public class AltosParse { + public static boolean isdigit(char c) { + return '0' <= c && c <= '9'; + } + + public static int parse_int(String v) throws ParseException { + try { + return AltosLib.fromdec(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing int " + v, 0); + } + } + + public static int parse_hex(String v) throws ParseException { + try { + return AltosLib.fromhex(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing hex " + v, 0); + } + } + + public static double parse_double(String v) throws ParseException { + try { + return Double.parseDouble(v); + } catch (NumberFormatException e) { + throw new ParseException("error parsing double " + v, 0); + } + } + + public static double parse_coord(String coord) throws ParseException { + String[] dsf = coord.split("\\D+"); + + if (dsf.length != 3) { + throw new ParseException("error parsing coord " + coord, 0); + } + int deg = parse_int(dsf[0]); + int min = parse_int(dsf[1]); + int frac = parse_int(dsf[2]); + + double r = deg + (min + frac / 10000.0) / 60.0; + if (coord.endsWith("S") || coord.endsWith("W")) + r = -r; + return r; + } + + public static String strip_suffix(String v, String suffix) { + if (v.endsWith(suffix)) + return v.substring(0, v.length() - suffix.length()); + return v; + } + + public static void word(String v, String m) throws ParseException { + if (!v.equals(m)) { + throw new ParseException("error matching '" + v + "' '" + m + "'", 0); + } + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java b/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java new file mode 100644 index 00000000..43c7088d --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java @@ -0,0 +1,365 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; +import java.awt.Component; +import javax.swing.*; +import javax.swing.filechooser.FileSystemView; + +public class AltosPreferences { + public static Preferences preferences; + + /* logdir preference name */ + public final static String logdirPreference = "LOGDIR"; + + /* channel preference name */ + public final static String channelPreferenceFormat = "CHANNEL-%d"; + + /* frequency preference name */ + public final static String frequencyPreferenceFormat = "FREQUENCY-%d"; + + /* telemetry format preference name */ + public final static String telemetryPreferenceFormat = "TELEMETRY-%d"; + + /* voice preference name */ + public final static String voicePreference = "VOICE"; + + /* callsign preference name */ + public final static String callsignPreference = "CALLSIGN"; + + /* firmware directory preference name */ + public final static String firmwaredirPreference = "FIRMWARE"; + + /* serial debug preference name */ + public final static String serialDebugPreference = "SERIAL-DEBUG"; + + /* scanning telemetry preferences name */ + public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; + + /* Launcher serial preference name */ + public final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + + /* Launcher channel preference name */ + public final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + + /* Default logdir is ~/TeleMetrum */ + public final static String logdirName = "TeleMetrum"; + + /* Log directory */ + public static File logdir; + + /* Map directory -- hangs of logdir */ + public static File mapdir; + + /* Frequency (map serial to frequency) */ + public static Hashtable frequencies; + + /* Telemetry (map serial to telemetry format) */ + public static Hashtable telemetries; + + /* Voice preference */ + public static boolean voice; + + /* Callsign preference */ + public static String callsign; + + /* Firmware directory */ + public static File firmwaredir; + + /* Scanning telemetry */ + public static int scanning_telemetry; + + /* List of frequencies */ + public final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; + public static AltosFrequency[] common_frequencies; + + public final static String frequency_count = "COUNT"; + public final static String frequency_format = "FREQUENCY-%d"; + public final static String description_format = "DESCRIPTION-%d"; + + public static AltosFrequency[] load_common_frequencies() { + AltosFrequency[] frequencies = null; + boolean existing = false; + try { + existing = preferences.nodeExists(common_frequencies_node_name); + } catch (BackingStoreException be) { + existing = false; + } + if (existing) { + Preferences node = preferences.node(common_frequencies_node_name); + int count = node.getInt(frequency_count, 0); + + frequencies = new AltosFrequency[count]; + for (int i = 0; i < count; i++) { + double frequency; + String description; + + frequency = node.getDouble(String.format(frequency_format, i), 0.0); + description = node.get(String.format(description_format, i), null); + frequencies[i] = new AltosFrequency(frequency, description); + } + } else { + frequencies = new AltosFrequency[10]; + for (int i = 0; i < 10; i++) { + frequencies[i] = new AltosFrequency(434.550 + i * .1, + String.format("Channel %d", i)); + } + } + return frequencies; + } + + public static void save_common_frequencies(AltosFrequency[] frequencies) { + Preferences node = preferences.node(common_frequencies_node_name); + + node.putInt(frequency_count, frequencies.length); + for (int i = 0; i < frequencies.length; i++) { + node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); + node.put(String.format(description_format, i), frequencies[i].description); + } + } + public static int launcher_serial; + + public static int launcher_channel; + + public static void init() { + preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); + + /* Initialize logdir from preferences */ + String logdir_string = preferences.get(logdirPreference, null); + if (logdir_string != null) + logdir = new File(logdir_string); + else { + /* Use the file system view default directory */ + logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); + if (!logdir.exists()) + logdir.mkdirs(); + } + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); + + frequencies = new Hashtable(); + + telemetries = new Hashtable(); + + voice = preferences.getBoolean(voicePreference, true); + + callsign = preferences.get(callsignPreference,"N0CALL"); + + scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard)); + + launcher_serial = preferences.getInt(launcherSerialPreference, 0); + + launcher_channel = preferences.getInt(launcherChannelPreference, 0); + + String firmwaredir_string = preferences.get(firmwaredirPreference, null); + if (firmwaredir_string != null) + firmwaredir = new File(firmwaredir_string); + else + firmwaredir = null; + + common_frequencies = load_common_frequencies(); + + } + + static { init(); } + + public static void flush_preferences() { + try { + preferences.flush(); + } catch (BackingStoreException ee) { +/* + if (component != null) + JOptionPane.showMessageDialog(component, + preferences.absolutePath(), + "Cannot save prefernces", + JOptionPane.ERROR_MESSAGE); + else +*/ + System.err.printf("Cannot save preferences\n"); + } + } + + public static void set_logdir(File new_logdir) { + logdir = new_logdir; + mapdir = new File(logdir, "maps"); + if (!mapdir.exists()) + mapdir.mkdirs(); + synchronized (preferences) { + preferences.put(logdirPreference, logdir.getPath()); + flush_preferences(); + } + } + + public static File logdir() { + return logdir; + } + + public static File mapdir() { + return mapdir; + } + + public static void set_frequency(int serial, double new_frequency) { + frequencies.put(serial, new_frequency); + synchronized (preferences) { + preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); + flush_preferences(); + } + } + + public static double frequency(int serial) { + if (frequencies.containsKey(serial)) + return frequencies.get(serial); + double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); + if (frequency == 0.0) { + int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); + frequency = AltosConvert.radio_channel_to_frequency(channel); + } + frequencies.put(serial, frequency); + return frequency; + } + + public static void set_telemetry(int serial, int new_telemetry) { + telemetries.put(serial, new_telemetry); + synchronized (preferences) { + preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); + flush_preferences(); + } + } + + public static int telemetry(int serial) { + if (telemetries.containsKey(serial)) + return telemetries.get(serial); + int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), + AltosLib.ao_telemetry_standard); + telemetries.put(serial, telemetry); + return telemetry; + } + + public static void set_scanning_telemetry(int new_scanning_telemetry) { + scanning_telemetry = new_scanning_telemetry; + synchronized (preferences) { + preferences.putInt(scanningTelemetryPreference, scanning_telemetry); + flush_preferences(); + } + } + + public static int scanning_telemetry() { + return scanning_telemetry; + } + + public static void set_voice(boolean new_voice) { + voice = new_voice; + synchronized (preferences) { + preferences.putBoolean(voicePreference, voice); + flush_preferences(); + } + } + + public static boolean voice() { + return voice; + } + + public static void set_callsign(String new_callsign) { + callsign = new_callsign; + synchronized(preferences) { + preferences.put(callsignPreference, callsign); + flush_preferences(); + } + } + + public static String callsign() { + return callsign; + } + + public static void set_firmwaredir(File new_firmwaredir) { + firmwaredir = new_firmwaredir; + synchronized (preferences) { + preferences.put(firmwaredirPreference, firmwaredir.getPath()); + flush_preferences(); + } + } + + public static File firmwaredir() { + return firmwaredir; + } + + public static void set_launcher_serial(int new_launcher_serial) { + launcher_serial = new_launcher_serial; + System.out.printf("set launcher serial to %d\n", new_launcher_serial); + synchronized (preferences) { + preferences.putInt(launcherSerialPreference, launcher_serial); + flush_preferences(); + } + } + + public static int launcher_serial() { + return launcher_serial; + } + + public static void set_launcher_channel(int new_launcher_channel) { + launcher_channel = new_launcher_channel; + System.out.printf("set launcher channel to %d\n", new_launcher_channel); + synchronized (preferences) { + preferences.putInt(launcherChannelPreference, launcher_channel); + flush_preferences(); + } + } + + public static int launcher_channel() { + return launcher_channel; + } + + public static Preferences bt_devices() { + return preferences.node("bt_devices"); + } + + public static AltosFrequency[] common_frequencies() { + return common_frequencies; + } + + public static void set_common_frequencies(AltosFrequency[] frequencies) { + common_frequencies = frequencies; + synchronized(preferences) { + save_common_frequencies(frequencies); + flush_preferences(); + } + } + + public static void add_common_frequency(AltosFrequency frequency) { + AltosFrequency[] new_frequencies = new AltosFrequency[common_frequencies.length + 1]; + int i; + + for (i = 0; i < common_frequencies.length; i++) { + if (frequency.frequency == common_frequencies[i].frequency) + return; + if (frequency.frequency < common_frequencies[i].frequency) + break; + new_frequencies[i] = common_frequencies[i]; + } + new_frequencies[i] = frequency; + for (; i < common_frequencies.length; i++) + new_frequencies[i+1] = common_frequencies[i]; + set_common_frequencies(new_frequencies); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java b/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java new file mode 100644 index 00000000..e4915af0 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java @@ -0,0 +1,319 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.util.HashMap; +import java.io.*; + +public class AltosRecord implements Comparable { + public final static int MISSING = 0x7fffffff; + + public static final int seen_flight = 1; + public static final int seen_sensor = 2; + public static final int seen_temp_volt = 4; + public static final int seen_deploy = 8; + public static final int seen_gps_time = 16; + public static final int seen_gps_lat = 32; + public static final int seen_gps_lon = 64; + public static final int seen_companion = 128; + public int seen; + + public int version; + public String callsign; + public int serial; + public int flight; + public int rssi; + public int status; + public int state; + public int tick; + + public int accel; + public int pres; + public int temp; + public int batt; + public int drogue; + public int main; + + public int ground_accel; + public int ground_pres; + public int accel_plus_g; + public int accel_minus_g; + + public double acceleration; + public double speed; + public double height; + + public int flight_accel; + public int flight_vel; + public int flight_pres; + + public AltosGPS gps; + public boolean new_gps; + + public AltosIMU imu; + public AltosMag mag; + + public double time; /* seconds since boost */ + + public int device_type; + public int config_major; + public int config_minor; + public int apogee_delay; + public int main_deploy; + public int flight_log_max; + public String firmware_version; + + public AltosRecordCompanion companion; + +>>>>>>> 5a249bc... altosui: Complete split out of separate java library + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + public static final double counts_per_kPa = 27 * 2047 / 3300; + public static final double counts_at_101_3kPa = 1674.0; + + public static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + public double raw_pressure() { + if (pres == MISSING) + return MISSING; + return barometer_to_pressure(pres); + } + + public double filtered_pressure() { + if (flight_pres == MISSING) + return MISSING; + return barometer_to_pressure(flight_pres); + } + + public double ground_pressure() { + if (ground_pres == MISSING) + return MISSING; + return barometer_to_pressure(ground_pres); + } + + public double raw_altitude() { + double p = raw_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double ground_altitude() { + double p = ground_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_altitude() { + if (height != MISSING && ground_pres != MISSING) + return height + ground_altitude(); + + double p = filtered_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_height() { + if (height != MISSING) + return height; + + double f = filtered_altitude(); + double g = ground_altitude(); + if (f == MISSING || g == MISSING) + return MISSING; + return f - g; + } + + public double raw_height() { + double r = raw_altitude(); + double g = ground_altitude(); + + if (r == MISSING || g == MISSING) + return height; + return r - g; + } + + public double battery_voltage() { + if (batt == MISSING) + return MISSING; + return AltosConvert.cc_battery_to_voltage(batt); + } + + public double main_voltage() { + if (main == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(main); + } + + public double drogue_voltage() { + if (drogue == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(drogue); + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + public static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public double temperature() { + if (temp == MISSING) + return MISSING; + return thermometer_to_temperature(temp); + } + + public double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + + public double acceleration() { + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; + return (ground_accel - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + if (speed != MISSING) + return speed; + if (flight_vel == MISSING) + return MISSING; + return flight_vel / (accel_counts_per_mss() * 100.0); + } + + public String state() { + return AltosLib.state_name(state); + } + + public static String gets(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') { + return line; + } + line = line + (char) c; + } + return null; + } + + public int compareTo(AltosRecord o) { + return tick - o.tick; + } + + public AltosRecord(AltosRecord old) { + version = old.version; + seen = old.seen; + callsign = old.callsign; + serial = old.serial; + flight = old.flight; + rssi = old.rssi; + status = old.status; + state = old.state; + tick = old.tick; + accel = old.accel; + pres = old.pres; + temp = old.temp; + batt = old.batt; + drogue = old.drogue; + main = old.main; + flight_accel = old.flight_accel; + ground_accel = old.ground_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + acceleration = old.acceleration; + speed = old.speed; + height = old.height; + gps = new AltosGPS(old.gps); + new_gps = false; + companion = old.companion; + imu = old.imu; + mag = old.mag; + } + + public AltosRecord() { + version = 0; + seen = 0; + callsign = "N0CALL"; + serial = 0; + flight = 0; + rssi = 0; + status = 0; + state = AltosLib.ao_flight_startup; + tick = 0; + accel = MISSING; + pres = MISSING; + temp = MISSING; + batt = MISSING; + drogue = MISSING; + main = MISSING; + flight_accel = 0; + ground_accel = 0; + flight_vel = 0; + flight_pres = 0; + ground_pres = 0; + accel_plus_g = 0; + accel_minus_g = 0; + acceleration = MISSING; + speed = MISSING; + height = MISSING; + gps = new AltosGPS(); + new_gps = false; + companion = null; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java b/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java new file mode 100644 index 00000000..c8cc6cac --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java @@ -0,0 +1,38 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosRecordCompanion { + public final static int board_id_telescience = 0x0a; + public final static int MAX_CHANNELS = 12; + + public int tick; + public int board_id; + public int update_period; + public int channels; + public int[] companion_data; + + public AltosRecordCompanion(int in_channels) { + channels = in_channels; + if (channels < 0) + channels = 0; + if (channels > MAX_CHANNELS) + channels = MAX_CHANNELS; + companion_data = new int[channels]; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java b/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java new file mode 100644 index 00000000..ed1787ed --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java @@ -0,0 +1,29 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; + +public abstract class AltosRecordIterable implements Iterable { + public abstract Iterator iterator(); + public void write_comments(PrintStream out) { } + public boolean has_accel() { return false; } + public boolean has_gps() { return false; } + public boolean has_ignite() { return false; }; +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java b/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java new file mode 100644 index 00000000..1585f9eb --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java @@ -0,0 +1,56 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * Open an existing telemetry file and replay it in realtime + */ + +public class AltosReplayReader extends AltosFlightReader { + Iterator iterator; + File file; + + public AltosRecord read() { + if (iterator.hasNext()) + return iterator.next(); + return null; + } + + public void close (boolean interrupted) { + } + + public void update(AltosState state) throws InterruptedException { + /* Make it run in realtime after the rocket leaves the pad */ + if (state.state > AltosLib.ao_flight_pad) + Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); + } + + public File backing_file() { return file; } + + public AltosReplayReader(Iterator in_iterator, File in_file) { + iterator = in_iterator; + file = in_file; + name = file.getName(); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosState.java b/altoslib/src/org/altusmetrum/AltosLib/AltosState.java new file mode 100644 index 00000000..0645e448 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosState.java @@ -0,0 +1,210 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Track flight state from telemetry or eeprom data stream + */ + +package org.altusmetrum.AltosLib; + +public class AltosState { + public AltosRecord data; + + /* derived data */ + + public long report_time; + + public double time; + public double time_change; + public int tick; + + public int state; + public boolean landed; + public boolean ascent; /* going up? */ + public boolean boost; /* under power */ + + public double ground_altitude; + public double height; + public double speed; + public double acceleration; + public double battery; + public double temperature; + public double main_sense; + public double drogue_sense; + public double baro_speed; + + public double max_height; + public double max_acceleration; + public double max_speed; + public double max_baro_speed; + + public AltosGPS gps; + + public AltosIMU imu; + public AltosMag mag; + + public static final int MIN_PAD_SAMPLES = 10; + + public int npad; + public int ngps; + public int gps_waiting; + public boolean gps_ready; + + public AltosGreatCircle from_pad; + public double elevation; /* from pad */ + public double range; /* total distance */ + + public double gps_height; + + public int speak_tick; + public double speak_altitude; + + public void init (AltosRecord cur, AltosState prev_state) { + int i; + AltosRecord prev; + + data = cur; + + ground_altitude = data.ground_altitude(); + height = data.filtered_height(); + + report_time = System.currentTimeMillis(); + + acceleration = data.acceleration(); + speed = data.accel_speed(); + temperature = data.temperature(); + drogue_sense = data.drogue_voltage(); + main_sense = data.main_voltage(); + battery = data.battery_voltage(); + tick = data.tick; + state = data.state; + + if (prev_state != null) { + + /* Preserve any existing gps data */ + npad = prev_state.npad; + ngps = prev_state.ngps; + gps = prev_state.gps; + pad_lat = prev_state.pad_lat; + pad_lon = prev_state.pad_lon; + pad_alt = prev_state.pad_alt; + max_height = prev_state.max_height; + max_acceleration = prev_state.max_acceleration; + max_speed = prev_state.max_speed; + max_baro_speed = prev_state.max_baro_speed; + imu = prev_state.imu; + mag = prev_state.mag; + + /* make sure the clock is monotonic */ + while (tick < prev_state.tick) + tick += 65536; + + time_change = (tick - prev_state.tick) / 100.0; + + /* compute barometric speed */ + + double height_change = height - prev_state.height; + if (data.speed != AltosRecord.MISSING) + baro_speed = data.speed; + else { + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } + } else { + npad = 0; + ngps = 0; + gps = null; + baro_speed = 0; + time_change = 0; + } + + time = tick / 100.0; + + if (cur.new_gps && (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_idle)) { + + /* Track consecutive 'good' gps reports, waiting for 10 of them */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) + npad++; + else + npad = 0; + + /* Average GPS data while on the pad */ + if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { + if (ngps > 1) { + /* filter pad position */ + pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; + pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; + pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; + } else { + pad_lat = data.gps.lat; + pad_lon = data.gps.lon; + pad_alt = data.gps.alt; + } + ngps++; + } + } + + gps_waiting = MIN_PAD_SAMPLES - npad; + if (gps_waiting < 0) + gps_waiting = 0; + + gps_ready = gps_waiting == 0; + + ascent = (AltosLib.ao_flight_boost <= state && + state <= AltosLib.ao_flight_coast); + boost = (AltosLib.ao_flight_boost == state); + + /* Only look at accelerometer data under boost */ + if (boost && acceleration > max_acceleration) + max_acceleration = acceleration; + if (boost && speed > max_speed) + max_speed = speed; + if (boost && baro_speed > max_baro_speed) + max_baro_speed = baro_speed; + + if (height > max_height) + max_height = height; + if (data.gps != null) { + if (gps == null || !gps.locked || data.gps.locked) + gps = data.gps; + if (ngps > 0 && gps.locked) { + from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); + } + } + elevation = 0; + range = -1; + if (ngps > 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; + } + } + + public AltosState(AltosRecord cur) { + init(cur, null); + } + + public AltosState (AltosRecord cur, AltosState prev) { + init(cur, prev); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java new file mode 100644 index 00000000..04abb1f3 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java @@ -0,0 +1,241 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * + */ + +public class AltosTelemetry extends AltosRecord { + + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { + AltosTelemetryRecord r = AltosTelemetryRecord.parse(line); + + return r.update_state(previous); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java new file mode 100644 index 00000000..f4b4029f --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java @@ -0,0 +1,109 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosTelemetryIterable extends AltosRecordIterable { + TreeSet records; + + public Iterator iterator () { + return records.iterator(); + } + + boolean has_gps = false; + boolean has_accel = false; + boolean has_ignite = false; + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; }; + + public AltosTelemetryIterable (FileInputStream input) { + boolean saw_boost = false; + int current_tick = 0; + int boost_tick = 0; + + AltosRecord previous = null; + records = new TreeSet (); + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) { + break; + } + try { + AltosRecord record = AltosTelemetry.parse(line, previous); + if (record == null) + break; + if (records.isEmpty()) { + current_tick = record.tick; + } else { + int tick = record.tick; + while (tick < current_tick - 0x1000) + tick += 0x10000; + current_tick = tick; + record.tick = current_tick; + } + if (!saw_boost && record.state >= AltosLib.ao_flight_boost) + { + saw_boost = true; + boost_tick = record.tick; + } + if (record.accel != AltosRecord.MISSING) + has_accel = true; + if (record.gps != null) + has_gps = true; + if (record.main != AltosRecord.MISSING) + has_ignite = true; + if (previous != null && previous.tick != record.tick) + records.add(previous); + previous = record; + } catch (ParseException pe) { + System.out.printf("parse exception %s\n", pe.getMessage()); + } catch (AltosCRCException ce) { + } + } + } catch (IOException io) { + System.out.printf("io exception\n"); + } + + if (previous != null) + records.add(previous); + + /* Adjust all tick counts to match expected eeprom values, + * which starts with a 16-bit tick count 16 samples before boost + */ + + int tick_adjust = (boost_tick - 16) & 0xffff0000; + for (AltosRecord r : this) + r.tick -= tick_adjust; + boost_tick -= tick_adjust; + + /* adjust all tick counts to be relative to boost time */ + for (AltosRecord r : this) + r.time = (r.tick - boost_tick) / 100.0; + + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java new file mode 100644 index 00000000..003cb6a9 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; +import java.lang.*; +import java.text.*; +import java.util.HashMap; + +public class AltosTelemetryMap extends HashMap { + public boolean has(String key) { + return containsKey(key); + } + + public String get_string(String key) throws ParseException { + if (!has(key)) + throw new ParseException ("missing " + key, 0); + return (String) get(key); + } + + public String get_string(String key, String def) { + if (has(key)) + return get(key); + else + return def; + } + + public int get_int(String key) throws ParseException { + return AltosParse.parse_int(get_string(key)); + } + + public int get_int(String key, int def) throws ParseException { + if (has(key)) + return get_int(key); + else + return def; + } + + public double get_double(String key, double def, double scale) throws ParseException { + if (has(key)) + return get_int(key) * scale; + else + return def; + } + + public AltosTelemetryMap(String[] words, int start) { + for (int i = start; i < words.length - 1; i += 2) + put(words[i], words[i+1]); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java new file mode 100644 index 00000000..67ac1b65 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java @@ -0,0 +1,119 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.io.*; +import java.util.concurrent.*; + +public class AltosTelemetryReader extends AltosFlightReader { + AltosLink link; + AltosLog log; + AltosRecord previous; + double frequency; + int telemetry; + + LinkedBlockingQueue telem; + + public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { + AltosLine l = telem.take(); + if (l.line == null) + throw new IOException("IO error"); + AltosRecord next = AltosTelemetry.parse(l.line, previous); + previous = next; + return next; + } + + public void flush() { + telem.clear(); + } + + public void close(boolean interrupted) { + link.remove_monitor(telem); + log.close(); + link.close(); + } + + public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + link.set_radio_frequency(frequency); + } + + public boolean supports_telemetry(int telemetry) { + + try { + /* Version 1.0 or later firmware supports all telemetry formats */ + if (serial.config_data().compare_version("1.0") >= 0) + return true; + + /* Version 0.9 firmware only supports 0.9 telemetry */ + if (serial.config_data().compare_version("0.9") >= 0) { + if (telemetry == Altos.ao_telemetry_0_9) + return true; + else + return false; + } + + /* Version 0.8 firmware only supports 0.8 telemetry */ + if (telemetry == Altos.ao_telemetry_0_8) + return true; + else + return false; + } catch (InterruptedException ie) { + return true; + } catch (TimeoutException te) { + return true; + } + } + + public void save_frequency() { + AltosPreferences.set_frequency(link.serial, frequency); + } + + public void set_telemetry(int in_telemetry) { + telemetry = in_telemetry; + link.set_telemetry(telemetry); + } + + public void save_telemetry() { + AltosPreferences.set_telemetry(link.serial, telemetry); + } + + public void set_monitor(boolean monitor) { + link.set_monitor(monitor); + } + + public File backing_file() { + return log.file(); + } + + public AltosTelemetryReader (AltosLink in_link) + throws IOException, InterruptedException, TimeoutException { + link = in_link; + log = new AltosLog(link); + name = link.name; + previous = null; + telem = new LinkedBlockingQueue(); + frequency = AltosPreferences.frequency(link.serial); + set_frequency(frequency); + telemetry = AltosPreferences.telemetry(link.serial); + set_telemetry(telemetry); + link.add_monitor(telem); + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java new file mode 100644 index 00000000..367c148d --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java @@ -0,0 +1,126 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public abstract class AltosTelemetryRecord { + + long received_time; + abstract public AltosRecord update_state(AltosRecord previous); + + static boolean cksum(int[] bytes) { + int sum = 0x5a; + for (int i = 1; i < bytes.length - 1; i++) + sum += bytes[i]; + sum &= 0xff; + return sum == bytes[bytes.length - 1]; + } + + final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); + final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); + final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; + + final static int packet_type_TM_sensor = 0x01; + final static int packet_type_Tm_sensor = 0x02; + final static int packet_type_Tn_sensor = 0x03; + final static int packet_type_configuration = 0x04; + final static int packet_type_location = 0x05; + final static int packet_type_satellite = 0x06; + final static int packet_type_companion = 0x07; + + static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + int[] bytes; + try { + bytes = Altos.hexbytes(hex); + } catch (NumberFormatException ne) { + throw new ParseException(ne.getMessage(), 0); + } + + /* one for length, one for checksum */ + if (bytes[0] != bytes.length - 2) + throw new ParseException(String.format("invalid length %d != %d\n", + bytes[0], + bytes.length - 2), 0); + if (!cksum(bytes)) + throw new ParseException(String.format("invalid line \"%s\"", hex), 0); + + int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; + int status = Altos.uint8(bytes, bytes.length - 2); + + if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) + throw new AltosCRCException(rssi); + + /* length, data ..., rssi, status, checksum -- 4 bytes extra */ + switch (bytes.length) { + case Altos.ao_telemetry_standard_len + 4: + int type = Altos.uint8(bytes, 4 + 1); + switch (type) { + case packet_type_TM_sensor: + case packet_type_Tm_sensor: + case packet_type_Tn_sensor: + r = new AltosTelemetryRecordSensor(bytes, rssi); + break; + case packet_type_configuration: + r = new AltosTelemetryRecordConfiguration(bytes); + break; + case packet_type_location: + r = new AltosTelemetryRecordLocation(bytes); + break; + case packet_type_satellite: + r = new AltosTelemetryRecordSatellite(bytes); + break; + case packet_type_companion: + r = new AltosTelemetryRecordCompanion(bytes); + break; + default: + r = new AltosTelemetryRecordRaw(bytes); + break; + } + break; + case Altos.ao_telemetry_0_9_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + case Altos.ao_telemetry_0_8_len + 4: + r = new AltosTelemetryRecordLegacy(bytes, rssi, status); + break; + default: + throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); + } + r.received_time = System.currentTimeMillis(); + return r; + } + + public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + if (word[i].equals("TELEM")) + r = parse_hex(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java new file mode 100644 index 00000000..6ad17244 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { + + AltosRecordCompanion companion; + + public AltosTelemetryRecordCompanion(int[] in_bytes) { + super(in_bytes); + + int off = 0; + if (uint8(6) == 0) + off = 1; + int channels = uint8(7+off); + + if (off != 0 && channels >= 12) + channels = 11; + + companion = new AltosRecordCompanion(channels); + companion.tick = tick; + companion.board_id = uint8(5); + companion.update_period = uint8(6+off); + for (int i = 0; i < companion.companion_data.length; i++) + companion.companion_data[i] = uint16(8 + off + i * 2); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.companion = companion; + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + companion.tick = tick; + return next; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java new file mode 100644 index 00000000..25242edc --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + + +public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { + int device_type; + int flight; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String callsign; + String version; + + public AltosTelemetryRecordConfiguration(int[] in_bytes) { + super(in_bytes); + + device_type = uint8(5); + flight = uint16(6); + config_major = uint8(8); + config_minor = uint8(9); + apogee_delay = uint16(10); + main_deploy = uint16(12); + flight_log_max = uint16(14); + callsign = string(16, 8); + version = string(24, 8); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.device_type = device_type; + next.flight = flight; + next.config_major = config_major; + next.config_minor = config_minor; + next.apogee_delay = apogee_delay; + next.main_deploy = main_deploy; + next.flight_log_max = flight_log_max; + + next.callsign = callsign; + next.firmware_version = version; + + next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight; + + return next; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java new file mode 100644 index 00000000..5e157a54 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordGeneral { + + static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { + AltosTelemetryRecord r; + + String[] word = line.split("\\s+"); + int i =0; + if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(word[i++], "RSSI"); + throw new AltosCRCException(AltosParse.parse_int(word[i++])); + } + + if (word[i].equals("TELEM")) + r = AltosTelemetryRecordRaw.parse(word[i+1]); + else + r = new AltosTelemetryRecordLegacy(line); + return r; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java new file mode 100644 index 00000000..8e3713cc --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java @@ -0,0 +1,521 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.util.HashMap; + +/* + * Telemetry data contents + */ + + +/* + * The packet format is a simple hex dump of the raw telemetry frame. + * It starts with 'TELEM', then contains hex digits with a checksum as the last + * byte on the line. + * + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values + * for accelerometer and barometer. + * + * GPS unlocked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ + * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ + * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 + * + * GPS locked: + * + * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ + * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ + * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ + * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ + * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ + * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * + */ + +public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + AltosRecord record; + + private void parse_v4(String[] words, int i) throws ParseException { + AltosTelemetryMap map = new AltosTelemetryMap(words, i); + + record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); + record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); + record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); + record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + record.tick = map.get_int(AO_TELEM_TICK, 0); + + /* raw sensor values */ + record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING); + record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING); + record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING); + record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING); + record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING); + record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING); + + /* sensor calibration information */ + record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING); + record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING); + record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING); + record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); + + /* flight computer values */ + record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); + record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); + record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); + + record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); + record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); + record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING); + + if (map.has(AO_TELEM_GPS_STATE)) { + record.gps = new AltosGPS(map); + record.new_gps = true; + } + else + record.gps = null; + } + + private void parse_legacy(String[] words, int i) throws ParseException { + + AltosParse.word (words[i++], "CALL"); + record.callsign = words[i++]; + + AltosParse.word (words[i++], "SERIAL"); + record.serial = AltosParse.parse_int(words[i++]); + + if (record.version >= 2) { + AltosParse.word (words[i++], "FLIGHT"); + record.flight = AltosParse.parse_int(words[i++]); + } else + record.flight = 0; + + AltosParse.word(words[i++], "RSSI"); + record.rssi = AltosParse.parse_int(words[i++]); + + /* Older telemetry data had mis-computed RSSI value */ + if (record.version <= 2) + record.rssi = (record.rssi + 74) / 2 - 74; + + AltosParse.word(words[i++], "STATUS"); + record.status = AltosParse.parse_hex(words[i++]); + + AltosParse.word(words[i++], "STATE"); + record.state = Altos.state(words[i++]); + + record.tick = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a:"); + record.accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "p:"); + record.pres = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "t:"); + record.temp = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "v:"); + record.batt = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "d:"); + record.drogue = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "m:"); + record.main = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fa:"); + record.flight_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "ga:"); + record.ground_accel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fv:"); + record.flight_vel = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "fp:"); + record.flight_pres = AltosParse.parse_int(words[i++]); + + /* Old TeleDongle code with kalman-reporting TeleMetrum code */ + if ((record.flight_vel & 0xffff0000) == 0x80000000) { + record.speed = ((short) record.flight_vel) / 16.0; + record.acceleration = record.flight_accel / 16.0; + record.height = record.flight_pres; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; + record.flight_accel = AltosRecord.MISSING; + } + + AltosParse.word(words[i++], "gp:"); + record.ground_pres = AltosParse.parse_int(words[i++]); + + if (record.version >= 1) { + AltosParse.word(words[i++], "a+:"); + record.accel_plus_g = AltosParse.parse_int(words[i++]); + + AltosParse.word(words[i++], "a-:"); + record.accel_minus_g = AltosParse.parse_int(words[i++]); + } else { + record.accel_plus_g = record.ground_accel; + record.accel_minus_g = record.ground_accel + 530; + } + + record.gps = new AltosGPS(words, i, record.version); + record.new_gps = true; + } + + public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + record = new AltosRecord(); + + if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(words[i++], "RSSI"); + record.rssi = AltosParse.parse_int(words[i++]); + throw new AltosCRCException(record.rssi); + } + if (words[i].equals("CALL")) { + record.version = 0; + } else { + AltosParse.word (words[i++], "VERSION"); + record.version = AltosParse.parse_int(words[i++]); + } + + if (record.version < 4) + parse_legacy(words, i); + else + parse_v4(words, i); + } + + /* + * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that + */ + + int[] bytes; + int adjust; + + private int int8(int i) { + return AltosLib.int8(bytes, i + 1 + adjust); + } + private int uint8(int i) { + return AltosLib.uint8(bytes, i + 1 + adjust); + } + private int int16(int i) { + return AltosLib.int16(bytes, i + 1 + adjust); + } + private int uint16(int i) { + return AltosLib.uint16(bytes, i + 1 + adjust); + } + private int uint32(int i) { + return AltosLib.uint32(bytes, i + 1 + adjust); + } + private String string(int i, int l) { + return AltosLib.string(bytes, i + 1 + adjust, l); + } + + static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); + static final int AO_GPS_NUM_SAT_SHIFT = (0); + + static final int AO_GPS_VALID = (1 << 4); + static final int AO_GPS_RUNNING = (1 << 5); + static final int AO_GPS_DATE_VALID = (1 << 6); + static final int AO_GPS_COURSE_VALID = (1 << 7); + + public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { + record = new AltosRecord(); + + bytes = in_bytes; + record.version = 4; + adjust = 0; + + if (bytes.length == AltosLib.ao_telemetry_0_8_len + 4) { + record.serial = uint8(0); + adjust = -1; + } else + record.serial = uint16(0); + + record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy; + + record.callsign = string(62, 8); + record.flight = uint16(2); + record.rssi = in_rssi; + record.status = in_status; + record.state = uint8(4); + record.tick = uint16(21); + record.accel = int16(23); + record.pres = int16(25); + record.temp = int16(27); + record.batt = int16(29); + record.drogue = int16(31); + record.main = int16(33); + + record.ground_accel = int16(7); + record.ground_pres = int16(15); + record.accel_plus_g = int16(17); + record.accel_minus_g = int16(19); + + if (uint16(11) == 0x8000) { + record.acceleration = int16(5); + record.speed = int16(9); + record.height = int16(13); + record.flight_accel = AltosRecord.MISSING; + record.flight_vel = AltosRecord.MISSING; + record.flight_pres = AltosRecord.MISSING; + } else { + record.flight_accel = int16(5); + record.flight_vel = uint32(9); + record.flight_pres = int16(13); + record.acceleration = AltosRecord.MISSING; + record.speed = AltosRecord.MISSING; + record.height = AltosRecord.MISSING; + } + + record.gps = null; + + int gps_flags = uint8(41); + + if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { + record.gps = new AltosGPS(); + record.new_gps = true; + + record.seen |= record.seen_gps_time | record.seen_gps_lat | record.seen_gps_lon; + record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); + record.gps.locked = (gps_flags & AO_GPS_VALID) != 0; + record.gps.connected = true; + record.gps.lat = uint32(42) / 1.0e7; + record.gps.lon = uint32(46) / 1.0e7; + record.gps.alt = int16(50); + record.gps.ground_speed = uint16(52) / 100.0; + record.gps.course = uint8(54) * 2; + record.gps.hdop = uint8(55) / 5.0; + record.gps.h_error = uint16(58); + record.gps.v_error = uint16(60); + + int n_tracking_reported = uint8(70); + if (n_tracking_reported > 12) + n_tracking_reported = 12; + int n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + if (uint8(71 + i*2) != 0) + n_tracking_actual++; + } + if (n_tracking_actual > 0) { + record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; + + n_tracking_actual = 0; + for (int i = 0; i < n_tracking_reported; i++) { + int svid = uint8(71 + i*2); + int c_n0 = uint8(72 + i*2); + if (svid != 0) + record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); + } + } + } + + record.time = 0.0; + } + + public AltosRecord update_state(AltosRecord previous) { + return record; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java new file mode 100644 index 00000000..cddb773d --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java @@ -0,0 +1,93 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + + +public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { + int flags; + int altitude; + int latitude; + int longitude; + int year; + int month; + int day; + int hour; + int minute; + int second; + int pdop; + int hdop; + int vdop; + int mode; + int ground_speed; + int climb_rate; + int course; + + public AltosTelemetryRecordLocation(int[] in_bytes) { + super(in_bytes); + + flags = uint8(5); + altitude = int16(6); + latitude = uint32(8); + longitude = uint32(12); + year = uint8(16); + month = uint8(17); + day = uint8(18); + hour = uint8(19); + minute = uint8(20); + second = uint8(21); + pdop = uint8(22); + hdop = uint8(23); + vdop = uint8(24); + mode = uint8(25); + ground_speed = uint16(26); + climb_rate = int16(28); + course = uint8(30); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.nsat = flags & 0xf; + next.gps.locked = (flags & (1 << 4)) != 0; + next.gps.connected = (flags & (1 << 5)) != 0; + + if (next.gps.locked) { + next.gps.lat = latitude * 1.0e-7; + next.gps.lon = longitude * 1.0e-7; + next.gps.alt = altitude; + next.gps.year = 2000 + year; + next.gps.month = month; + next.gps.day = day; + next.gps.hour = hour; + next.gps.minute = minute; + next.gps.second = second; + next.gps.ground_speed = ground_speed * 1.0e-2; + next.gps.course = course * 2; + next.gps.climb_rate = climb_rate * 1.0e-2; + next.gps.hdop = hdop; + next.gps.vdop = vdop; + next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; + next.new_gps = true; + } + + return next; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java new file mode 100644 index 00000000..43d0f17a --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java @@ -0,0 +1,77 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.lang.*; +import java.text.*; +import java.util.HashMap; + +public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { + int[] bytes; + int serial; + int tick; + int type; + + long received_time; + + public int int8(int off) { + return AltosLib.int8(bytes, off + 1); + } + + public int uint8(int off) { + return AltosLib.uint8(bytes, off + 1); + } + + public int int16(int off) { + return AltosLib.int16(bytes, off + 1); + } + + public int uint16(int off) { + return AltosLib.uint16(bytes, off + 1); + } + + public int uint32(int off) { + return AltosLib.uint32(bytes, off + 1); + } + + public String string(int off, int l) { + return AltosLib.string(bytes, off + 1, l); + } + + public AltosTelemetryRecordRaw(int[] in_bytes) { + bytes = in_bytes; + serial = uint16(0); + tick = uint16(2); + type = uint8(4); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next; + if (previous != null) + next = new AltosRecord(previous); + else + next = new AltosRecord(); + next.serial = serial; + next.tick = tick; + return next; + } + + public long received_time() { + return received_time; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java new file mode 100644 index 00000000..2526afb6 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { + int channels; + AltosGPSSat[] sats; + + public AltosTelemetryRecordSatellite(int[] in_bytes) { + super(in_bytes); + + channels = uint8(5); + if (channels > 12) + channels = 12; + if (channels == 0) + sats = null; + else { + sats = new AltosGPSSat[channels]; + for (int i = 0; i < channels; i++) { + int svid = uint8(6 + i * 2 + 0); + int c_n_1 = uint8(6 + i * 2 + 1); + sats[i] = new AltosGPSSat(svid, c_n_1); + } + } + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + if (next.gps == null) + next.gps = new AltosGPS(); + + next.gps.cc_gps_sat = sats; + + return next; + } +} diff --git a/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java new file mode 100644 index 00000000..cfaf90b0 --- /dev/null +++ b/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java @@ -0,0 +1,104 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + + +public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { + int state; + int accel; + int pres; + int temp; + int v_batt; + int sense_d; + int sense_m; + + int acceleration; + int speed; + int height; + + int ground_accel; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + + int rssi; + + public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { + super(in_bytes); + state = uint8(5); + + accel = int16(6); + pres = int16(8); + temp = int16(10); + v_batt = int16(12); + sense_d = int16(14); + sense_m = int16(16); + + acceleration = int16(18); + speed = int16(20); + height = int16(22); + + ground_pres = int16(24); + ground_accel = int16(26); + accel_plus_g = int16(28); + accel_minus_g = int16(30); + + rssi = in_rssi; + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord next = super.update_state(previous); + + next.state = state; + if (type == packet_type_TM_sensor) + next.accel = accel; + else + next.accel = AltosRecord.MISSING; + next.pres = pres; + next.temp = temp; + next.batt = v_batt; + if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { + next.drogue = sense_d; + next.main = sense_m; + } else { + next.drogue = AltosRecord.MISSING; + next.main = AltosRecord.MISSING; + } + + next.acceleration = acceleration / 16.0; + next.speed = speed / 16.0; + next.height = height; + + next.ground_pres = ground_pres; + if (type == packet_type_TM_sensor) { + next.ground_accel = ground_accel; + next.accel_plus_g = accel_plus_g; + next.accel_minus_g = accel_minus_g; + } else { + next.ground_accel = AltosRecord.MISSING; + next.accel_plus_g = AltosRecord.MISSING; + next.accel_minus_g = AltosRecord.MISSING; + } + + next.rssi = rssi; + + next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; + + return next; + } +} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 7a3c53e7..d494547b 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=libaltos altoslib +SUBDIRS=libaltos JAVAROOT=classes AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation @@ -6,7 +6,7 @@ man_MANS=altosui.1 altoslibdir=$(libdir)/altos -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:altoslib/bin:libaltos:$(FREETTS)/*:/usr/share/java/*" +CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH=".:classes:../altoslib/*:libaltos:$(FREETTS)/*:/usr/share/java/*" bin_SCRIPTS=altosui @@ -287,9 +287,9 @@ build-altos64-dll: $(ALTOSLIB_CLASS): -rm -f "$@" - $(LN_S) altoslib/"$@" . + $(LN_S) ../altoslib/"$@" . -$(FREETTS_CLASS): +$(FREETTS_CLASS): ../altoslib/"$@" -rm -f "$@" $(LN_S) "$(FREETTS)"/"$@" . diff --git a/altosui/altoslib/.gitignore b/altosui/altoslib/.gitignore deleted file mode 100644 index ad2f8cbf..00000000 --- a/altosui/altoslib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -classAltosLib.stamp diff --git a/altosui/altoslib/Makefile.am b/altosui/altoslib/Makefile.am deleted file mode 100644 index 2ddd24e6..00000000 --- a/altosui/altoslib/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ -AM_JAVACFLAGS=-encoding UTF-8 -Xlint:deprecation - -JAVAROOT=bin - -CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="bin:$(FREETTS)/*:/usr/share/java/*" - -SRC=src/org/altusmetrum/AltosLib -BIN=bin/org/altusmetrum/AltosLib - -AltosLibdir = $(datadir)/java - -AltosLib_JAVA = \ - $(SRC)/AltosLib.java \ - $(SRC)/AltosConfigData.java \ - $(SRC)/AltosConvert.java \ - $(SRC)/AltosCRCException.java \ - $(SRC)/AltosEepromChunk.java \ - $(SRC)/AltosEepromIterable.java \ - $(SRC)/AltosEepromLog.java \ - $(SRC)/AltosEepromRecord.java \ - $(SRC)/AltosEepromTeleScience.java \ - $(SRC)/AltosFile.java \ - $(SRC)/AltosFlightReader.java \ - $(SRC)/AltosFrequency.java \ - $(SRC)/AltosGPS.java \ - $(SRC)/AltosGPSSat.java \ - $(SRC)/AltosGreatCircle.java \ - $(SRC)/AltosLine.java \ - $(SRC)/AltosLink.java \ - $(SRC)/AltosLog.java \ - $(SRC)/AltosParse.java \ - $(SRC)/AltosPreferences.java \ - $(SRC)/AltosRecordCompanion.java \ - $(SRC)/AltosRecordIterable.java \ - $(SRC)/AltosRecord.java \ - $(SRC)/AltosReplayReader.java \ - $(SRC)/AltosState.java \ - $(SRC)/AltosTelemetry.java \ - $(SRC)/AltosTelemetryIterable.java \ - $(SRC)/AltosTelemetryMap.java \ - $(SRC)/AltosTelemetryReader.java \ - $(SRC)/AltosTelemetryRecordCompanion.java \ - $(SRC)/AltosTelemetryRecordConfiguration.java \ - $(SRC)/AltosTelemetryRecordGeneral.java \ - $(SRC)/AltosTelemetryRecord.java \ - $(SRC)/AltosTelemetryRecordLegacy.java \ - $(SRC)/AltosTelemetryRecordLocation.java \ - $(SRC)/AltosTelemetryRecordRaw.java \ - $(SRC)/AltosTelemetryRecordSatellite.java \ - $(SRC)/AltosTelemetryRecordSensor.java - -JAR=AltosLib.jar - -all-local: $(JAR) - -clean-local: - -rm -rf bin $(JAR) - -install-AltosLibJAVA: $(JAR) - @$(NORMAL_INSTALL) - test -z "$(AltosLibdir)" || $(MKDIR_P) "$(DESTDIR)$(AltosLibdir)" - echo " $(INSTALL_DATA)" "$<" "'$(DESTDIR)$(AltosLibdir)/$(JAR)"; \ - $(INSTALL_DATA) "$<" "$(DESTDIR)$(AltosLibdir)" - -bin: - mkdir -p bin - -$(JAR): classAltosLib.stamp - jar cf $@ -C bin org diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java deleted file mode 100644 index 101c5363..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosCRCException.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosCRCException extends Exception { - public int rssi; - - public AltosCRCException (int in_rssi) { - rssi = in_rssi; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java deleted file mode 100644 index 4ad4e58a..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConfigData.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; -import org.altusmetrum.AltosLib.*; - -public class AltosConfigData implements Iterable { - - /* Version information */ - public String manufacturer; - public String product; - public String version; - public int log_format; - public int serial; - - /* Strings returned */ - public LinkedList lines; - - /* Config information */ - public int config_major; - public int config_minor; - public int main_deploy; - public int apogee_delay; - public int radio_channel; - public int radio_setting; - public int radio_frequency; - public String callsign; - public int accel_cal_plus, accel_cal_minus; - public int radio_calibration; - public int flight_log_max; - public int ignite_mode; - public int stored_flight; - public int storage_size; - public int storage_erase_unit; - - public static String get_string(String line, String label) throws ParseException { - if (line.startsWith(label)) { - String quoted = line.substring(label.length()).trim(); - - if (quoted.startsWith("\"")) - quoted = quoted.substring(1); - if (quoted.endsWith("\"")) - quoted = quoted.substring(0,quoted.length()-1); - return quoted; - } - throw new ParseException("mismatch", 0); - } - - public static int get_int(String line, String label) throws NumberFormatException, ParseException { - if (line.startsWith(label)) { - String tail = line.substring(label.length()).trim(); - String[] tokens = tail.split("\\s+"); - if (tokens.length > 0) - return Integer.parseInt(tokens[0]); - } - throw new ParseException("mismatch", 0); - } - - public Iterator iterator() { - return lines.iterator(); - } - - public int log_available() { - switch (log_format) { - case AltosLib.AO_LOG_FORMAT_TINY: - if (stored_flight == 0) - return 1; - return 0; - default: - if (flight_log_max <= 0) - return 1; - int log_space = storage_size - storage_erase_unit; - int log_used = stored_flight * flight_log_max; - - if (log_used >= log_space) - return 0; - return (log_space - log_used) / flight_log_max; - } - } - - int[] parse_version(String v) { - String[] parts = v.split("\\."); - int r[] = new int[parts.length]; - - for (int i = 0; i < parts.length; i++) { - try { - r[i] = Altos.fromdec(parts[i]); - } catch (NumberFormatException n) { - r[i] = 0; - } - } - - return r; - } - - public int compare_version(String other) { - int[] me = parse_version(version); - int[] them = parse_version(other); - - int l = Math.min(me.length, them.length); - - for (int i = 0; i < l; i++) { - int d = me[i] - them[i]; - if (d != 0) - return d; - } - if (me.length > l) - return 1; - if (them.length > l) - return -1; - return 0; - } - - public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { - link.printf("c s\np\nf\nl\nv\n"); - lines = new LinkedList(); - radio_setting = 0; - radio_frequency = 0; - stored_flight = 0; - for (;;) { - String line = link.get_reply(); - if (line == null) - throw new TimeoutException(); - if (line.contains("Syntax error")) - continue; - lines.add(line); - try { serial = get_int(line, "serial-number"); } catch (Exception e) {} - try { log_format = get_int(line, "log-format"); } catch (Exception e) {} - try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} - try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} - try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} - try { radio_setting = get_int(line, "Radio setting:"); } catch (Exception e) {} - try { - radio_frequency = get_int(line, "Frequency:"); - if (radio_frequency < 0) - radio_frequency = 434550; - } catch (Exception e) {} - try { - if (line.startsWith("Accel cal")) { - String[] bits = line.split("\\s+"); - if (bits.length >= 6) { - accel_cal_plus = Integer.parseInt(bits[3]); - accel_cal_minus = Integer.parseInt(bits[5]); - } - } - } catch (Exception e) {} - try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} - try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} - try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} - try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} - try { version = get_string(line,"software-version"); } catch (Exception e) {} - try { product = get_string(line,"product"); } catch (Exception e) {} - - try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {} - try { storage_size = get_int(line, "Storage size:"); } catch (Exception e) {} - try { storage_erase_unit = get_int(line, "Storage erase unit"); } catch (Exception e) {} - - /* signals the end of the version info */ - if (line.startsWith("software-version")) - break; - } - } - -} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java deleted file mode 100644 index 3527b575..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosConvert.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Sensor data conversion functions - */ -package org.altusmetrum.AltosLib; - -public class AltosConvert { - /* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ - return 0; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted altitude */ - for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - base_pressure *= Math.pow(base, exponent); - } - base_temperature += delta_z * lapse_rate[layer_number]; - } - - /* calculate the pressure at the inputted altitude */ - delta_z = altitude - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - pressure = base_pressure * Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - pressure = base_pressure * Math.pow(base, exponent); - } - - return pressure; - } - - -/* outputs the altitude associated with the given pressure. the altitude - returned is measured with respect to the mean sea level */ - public static double - pressure_to_altitude(double pressure) - { - - double next_base_temperature = LAYER0_BASE_TEMPERATURE; - double next_base_pressure = LAYER0_BASE_PRESSURE; - - double altitude; - double base_pressure; - double base_temperature; - double base; /* base for function to determine base pressure of next layer */ - double exponent; /* exponent for function to determine base pressure - of next layer */ - double coefficient; - int layer_number; /* identifies layer in the atmosphere */ - int delta_z; /* difference between two altitudes */ - - if (pressure < 0) /* illegal pressure */ - return -1; - if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ - return MAXIMUM_ALTITUDE; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted pressure. */ - layer_number = -1; - do { - layer_number++; - base_pressure = next_base_pressure; - base_temperature = next_base_temperature; - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - next_base_pressure *= Math.exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - next_base_pressure *= Math.pow(base, exponent); - } - next_base_temperature += delta_z * lapse_rate[layer_number]; - } - while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); - - /* calculate the altitude associated with the inputted pressure */ - if (lapse_rate[layer_number] == 0.0) { - coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) - * base_temperature; - altitude = base_altitude[layer_number] - + coefficient * Math.log(pressure / base_pressure); - } - else { - base = pressure / base_pressure; - exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] - / GRAVITATIONAL_ACCELERATION; - coefficient = base_temperature / lapse_rate[layer_number]; - altitude = base_altitude[layer_number] - + coefficient * (Math.pow(base, exponent) - 1); - } - - return altitude; - } - - public static double - cc_battery_to_voltage(double battery) - { - return battery / 32767.0 * 5.0; - } - - public static double - cc_ignitor_to_voltage(double ignite) - { - return ignite / 32767 * 15.0; - } - - public static double radio_to_frequency(int freq, int setting, int cal, int channel) { - double f; - - if (freq > 0) - f = freq / 1000.0; - else { - if (setting <= 0) - setting = cal; - f = 434.550 * setting / cal; - /* Round to nearest 50KHz */ - f = Math.floor (20.0 * f + 0.5) / 20.0; - } - return f + channel * 0.100; - } - - public static int radio_frequency_to_setting(double frequency, int cal) { - double set = frequency / 434.550 * cal; - - return (int) Math.floor (set + 0.5); - } - - public static int radio_frequency_to_channel(double frequency) { - int channel = (int) Math.floor ((frequency - 434.550) / 0.100 + 0.5); - - if (channel < 0) - channel = 0; - if (channel > 9) - channel = 9; - return channel; - } - - public static double radio_channel_to_frequency(int channel) { - return 434.550 + channel * 0.100; - } - - public static int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - public static double meters_to_feet(double meters) { - return meters * (100 / (2.54 * 12)); - } - - public static double meters_to_mach(double meters) { - return meters / 343; /* something close to mach at usual rocket sites */ - } - - public static double meters_to_g(double meters) { - return meters / 9.80665; - } - - public static int checksum(int[] data, int start, int length) { - int csum = 0x5a; - for (int i = 0; i < length; i++) - csum += data[i + start]; - return csum & 0xff; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java deleted file mode 100644 index 6d889723..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromChunk.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.concurrent.*; - -public class AltosEepromChunk { - - public static final int chunk_size = 256; - public static final int per_line = 8; - - public int data[]; - public int address; - public ParseException parse_exception = null; - - int[] ParseHex(String line) { - String[] tokens = line.split("\\s+"); - int[] array = new int[tokens.length]; - - for (int i = 0; i < tokens.length; i++) - try { - array[i] = Integer.parseInt(tokens[i], 16); - } catch (NumberFormatException ne) { - return null; - } - return array; - } - - public int data(int offset) { - return data[offset]; - } - - public int data16(int offset) { - return data[offset] | (data[offset + 1] << 8); - } - - public int data32(int offset) { - return data[offset] | (data[offset + 1] << 8) | - (data[offset+2] << 16) | (data[offset+3] << 24); - } - - public boolean erased(int start, int len) { - for (int i = 0; i < len; i++) - if (data[start+i] != 0xff) - return false; - return true; - } - - public AltosEepromChunk(AltosLink link, int block, boolean flush) - throws TimeoutException, InterruptedException { - - int offset; - - data = new int[chunk_size]; - address = block * chunk_size; - if (flush) - link.flush_input(); - link.printf("e %x\n", block); - - for (offset = 0; offset < chunk_size; offset += per_line) { - try { - String line = link.get_reply(5000); - - if (line == null) - throw new TimeoutException(); - - int[] values = ParseHex(line); - - if (values == null || values.length != per_line + 1) - throw new ParseException(String.format("invalid line %s", line), 0); - if (values[0] != offset) - throw new ParseException(String.format("data address out of sync at 0x%x", - address + offset), 0); - for (int i = 0; i < per_line; i++) - data[offset + i] = values[1 + i]; - } catch (ParseException pe) { - for (int i = 0; i < per_line; i++) - data[offset + i] = 0xff; - if (parse_exception == null) - parse_exception = pe; - } - } - } -} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java deleted file mode 100644 index f1397c7b..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromIterable.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; - -/* - * AltosRecords with an index field so they can be sorted by tick while preserving - * the original ordering for elements with matching ticks - */ -class AltosOrderedRecord extends AltosEepromRecord implements Comparable { - - public int index; - - public AltosOrderedRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) - throws ParseException { - super(line); - if (prev_tick_valid) { - tick |= (prev_tick & ~0xffff); - if (tick < prev_tick) { - if (prev_tick - tick > 0x8000) - tick += 0x10000; - } else { - if (tick - prev_tick > 0x8000) - tick -= 0x10000; - } - } - 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 String toString() { - return String.format("%d.%d %04x %04x %04x", - cmd, index, tick, a, b); - } - - public int compareTo(AltosOrderedRecord o) { - int tick_diff = tick - o.tick; - if (tick_diff != 0) - return tick_diff; - return index - o.index; - } -} - -public class AltosEepromIterable extends AltosRecordIterable { - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - - static final int seen_basic = seen_flight|seen_sensor; - - boolean has_accel; - boolean has_gps; - boolean has_ignite; - - AltosEepromRecord flight_record; - AltosEepromRecord gps_date_record; - - TreeSet records; - - LinkedList list; - - class EepromState { - int seen; - int n_pad_samples; - double ground_pres; - int gps_tick; - int boost_tick; - int sensor_tick; - - EepromState() { - seen = 0; - n_pad_samples = 0; - ground_pres = 0.0; - gps_tick = 0; - } - } - - void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { - state.tick = record.tick; - switch (record.cmd) { - case AltosLib.AO_LOG_FLIGHT: - eeprom.seen |= seen_flight; - state.ground_accel = record.a; - state.flight_accel = record.a; - state.flight = record.b; - eeprom.boost_tick = record.tick; - break; - case AltosLib.AO_LOG_SENSOR: - state.accel = record.a; - state.pres = record.b; - if (state.state < AltosLib.ao_flight_boost) { - eeprom.n_pad_samples++; - eeprom.ground_pres += state.pres; - state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); - state.flight_pres = state.ground_pres; - } else { - state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - } - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - if ((eeprom.seen & seen_sensor) == 0) - eeprom.sensor_tick = record.tick - 1; - state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); - eeprom.seen |= seen_sensor; - eeprom.sensor_tick = record.tick; - has_accel = true; - break; - case AltosLib.AO_LOG_PRESSURE: - state.pres = record.b; - state.flight_pres = state.pres; - if (eeprom.n_pad_samples == 0) { - eeprom.n_pad_samples++; - state.ground_pres = state.pres; - } - eeprom.seen |= seen_sensor; - break; - case AltosLib.AO_LOG_TEMP_VOLT: - state.temp = record.a; - state.batt = record.b; - eeprom.seen |= seen_temp_volt; - break; - case AltosLib.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - eeprom.seen |= seen_deploy; - has_ignite = true; - break; - case AltosLib.AO_LOG_STATE: - state.state = record.a; - break; - case AltosLib.AO_LOG_GPS_TIME: - eeprom.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); - - int flags = (record.b >> 8); - state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; - state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; - state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> - AltosLib.AO_GPS_NUM_SAT_SHIFT; - state.new_gps = true; - has_gps = true; - break; - case AltosLib.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case AltosLib.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case AltosLib.AO_LOG_GPS_ALT: - state.gps.alt = record.a; - break; - case AltosLib.AO_LOG_GPS_SAT: - if (state.tick == eeprom.gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); - } - break; - case AltosLib.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - - case AltosLib.AO_LOG_CONFIG_VERSION: - break; - case AltosLib.AO_LOG_MAIN_DEPLOY: - break; - case AltosLib.AO_LOG_APOGEE_DELAY: - break; - case AltosLib.AO_LOG_RADIO_CHANNEL: - break; - case AltosLib.AO_LOG_CALLSIGN: - state.callsign = record.data; - break; - case AltosLib.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; - break; - case AltosLib.AO_LOG_RADIO_CAL: - break; - case AltosLib.AO_LOG_MANUFACTURER: - break; - case AltosLib.AO_LOG_PRODUCT: - break; - case AltosLib.AO_LOG_SERIAL_NUMBER: - state.serial = record.a; - break; - case AltosLib.AO_LOG_SOFTWARE_VERSION: - break; - } - state.seen |= eeprom.seen; - } - - LinkedList make_list() { - LinkedList list = new LinkedList(); - Iterator iterator = records.iterator(); - AltosOrderedRecord record = null; - AltosRecord state = new AltosRecord(); - boolean last_reported = false; - EepromState eeprom = new EepromState(); - - state.state = AltosLib.ao_flight_pad; - state.accel_plus_g = 15758; - state.accel_minus_g = 16294; - - /* Pull in static data from the flight and gps_date records */ - if (flight_record != null) - update_state(state, flight_record, eeprom); - if (gps_date_record != null) - update_state(state, gps_date_record, eeprom); - - while (iterator.hasNext()) { - record = iterator.next(); - if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - } - update_state(state, record, eeprom); - } - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - return list; - } - - public Iterator iterator() { - if (list == null) - list = make_list(); - return list.iterator(); - } - - public boolean has_gps() { return has_gps; } - public boolean has_accel() { return has_accel; } - public boolean has_ignite() { return has_ignite; } - - public void write_comments(PrintStream out) { - Iterator iterator = records.iterator(); - out.printf("# Comments\n"); - while (iterator.hasNext()) { - AltosOrderedRecord record = iterator.next(); - switch (record.cmd) { - case AltosLib.AO_LOG_CONFIG_VERSION: - out.printf("# Config version: %s\n", record.data); - break; - case AltosLib.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); - break; - case AltosLib.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); - break; - case AltosLib.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); - break; - case AltosLib.AO_LOG_CALLSIGN: - out.printf("# Callsign: %s\n", record.data); - break; - case AltosLib.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); - break; - case AltosLib.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); - break; - case AltosLib.AO_LOG_MAX_FLIGHT_LOG: - out.printf ("# Max flight log: %d\n", record.a); - break; - case AltosLib.AO_LOG_MANUFACTURER: - out.printf ("# Manufacturer: %s\n", record.data); - break; - case AltosLib.AO_LOG_PRODUCT: - out.printf ("# Product: %s\n", record.data); - break; - case AltosLib.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); - break; - case AltosLib.AO_LOG_SOFTWARE_VERSION: - out.printf ("# Software version: %s\n", record.data); - break; - case Altos.AO_LOG_BARO_RESERVED: - out.printf ("# Baro reserved: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_SENS: - out.printf ("# Baro sens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_OFF: - out.printf ("# Baro off: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCS: - out.printf ("# Baro tcs: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCO: - out.printf ("# Baro tco: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TREF: - out.printf ("# Baro tref: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TEMPSENS: - out.printf ("# Baro tempsens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_CRC: - out.printf ("# Baro crc: %d\n", record.a); - break; - } - } - } - - /* - * 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; - - /* Make sure this looks like a good GPS value */ - if ((flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4) - flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT); - flags |= AltosLib.AO_GPS_RUNNING; - flags |= AltosLib.AO_GPS_VALID; - - 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 - * are sometimes out of order with GPS data getting timestamps - * matching the first packet out of the GPS unit but not - * written until the final GPS packet has been received. - */ - public AltosEepromIterable (FileInputStream input) { - records = new TreeSet(); - - AltosOrderedRecord last_gps_time = null; - - int index = 0; - int prev_tick = 0; - boolean prev_tick_valid = false; - boolean missing_time = false; - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) - break; - AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); - if (record == null) - break; - if (record.cmd == AltosLib.AO_LOG_INVALID) - continue; - prev_tick = record.tick; - if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION) - prev_tick_valid = true; - if (record.cmd == AltosLib.AO_LOG_FLIGHT) { - flight_record = record; - continue; - } - - /* 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 == AltosLib.AO_LOG_GPS_DATE) { - gps_date_record = record; - continue; - } - - /* go back and fix up any missing time values */ - if (record.cmd == AltosLib.AO_LOG_GPS_TIME) { - last_gps_time = record; - if (missing_time) { - Iterator iterator = records.iterator(); - while (iterator.hasNext()) { - AltosOrderedRecord old = iterator.next(); - if (old.cmd == AltosLib.AO_LOG_GPS_TIME && - old.a == -1 && old.b == -1) - { - update_time(record, old); - } - } - missing_time = false; - } - } - - if (record.cmd == AltosLib.AO_LOG_GPS_LAT) { - if (last_gps_time == null || last_gps_time.tick != record.tick) { - AltosOrderedRecord add_gps_time = new AltosOrderedRecord(AltosLib.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); - - /* Bail after reading the 'landed' record; we're all done */ - if (record.cmd == AltosLib.AO_LOG_STATE && - record.a == AltosLib.ao_flight_landed) - break; - } - } catch (IOException io) { - } catch (ParseException pe) { - } - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java deleted file mode 100644 index 7fca4bd9..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromLog.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; - -/* - * Extract a bit of information from an eeprom-stored flight log. - */ - -public class AltosEepromLog { - public int serial; - public boolean has_flight; - public int flight; - public int start_block; - public int end_block; - - public int year, month, day; - - public boolean selected; - - public AltosEepromLog(AltosConfigData config_data, - AltosLink link, - int in_flight, int in_start_block, - int in_end_block) - throws InterruptedException, TimeoutException { - - int block; - boolean has_date = false; - - flight = in_flight; - if (flight != 0) - has_flight = true; - start_block = in_start_block; - end_block = in_end_block; - serial = config_data.serial; - - /* - * Select all flights for download - */ - selected = true; - - /* - * Look in TeleMetrum log data for date - */ - if (config_data.log_format == AltosLib.AO_LOG_FORMAT_UNKNOWN || - config_data.log_format == AltosLib.AO_LOG_FORMAT_FULL) - { - /* - * Only look in the first two blocks so that this - * process doesn't take a long time - */ - if (in_end_block > in_start_block + 2) - in_end_block = in_start_block + 2; - - for (block = in_start_block; block < in_end_block; block++) { - AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == in_start_block); - - for (int i = 0; i < eechunk.chunk_size; i += AltosEepromRecord.record_length) { - try { - AltosEepromRecord r = new AltosEepromRecord(eechunk, i); - - if (r.cmd == AltosLib.AO_LOG_FLIGHT) { - flight = r.b; - has_flight = true; - } - if (r.cmd == AltosLib.AO_LOG_GPS_DATE) { - year = 2000 + (r.a & 0xff); - month = (r.a >> 8) & 0xff; - day = (r.b & 0xff); - has_date = true; - } - } catch (ParseException pe) { - } - } - if (has_date && has_flight) - break; - } - } - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java deleted file mode 100644 index 1e845f46..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromRecord.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; - -public class AltosEepromRecord { - public int cmd; - public int tick; - public int a; - public int b; - public String data; - public boolean tick_valid; - - public static final int record_length = 8; - - public AltosEepromRecord (AltosEepromChunk chunk, int start) throws ParseException { - - cmd = chunk.data(start); - tick_valid = true; - - tick_valid = !chunk.erased(start, record_length); - if (tick_valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - cmd = AltosLib.AO_LOG_INVALID; - } - - tick = chunk.data16(start + 2); - a = chunk.data16(start + 4); - b = chunk.data16(start + 6); - - data = null; - } - - public AltosEepromRecord (String line) { - tick_valid = false; - tick = 0; - a = 0; - b = 0; - data = null; - if (line == null) { - cmd = AltosLib.AO_LOG_INVALID; - data = ""; - } else { - try { - String[] tokens = line.split("\\s+"); - - if (tokens[0].length() == 1) { - if (tokens.length != 4) { - cmd = AltosLib.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 = AltosLib.AO_LOG_CONFIG_VERSION; - data = tokens[2]; - } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { - cmd = AltosLib.AO_LOG_MAIN_DEPLOY; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { - cmd = AltosLib.AO_LOG_APOGEE_DELAY; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { - cmd = AltosLib.AO_LOG_RADIO_CHANNEL; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Callsign:")) { - cmd = AltosLib.AO_LOG_CALLSIGN; - data = tokens[1].replaceAll("\"",""); - } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { - cmd = AltosLib.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 = AltosLib.AO_LOG_RADIO_CAL; - a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { - cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; - a = Integer.parseInt(tokens[3]); - } else if (tokens[0].equals("manufacturer")) { - cmd = AltosLib.AO_LOG_MANUFACTURER; - data = tokens[1]; - } else if (tokens[0].equals("product")) { - cmd = AltosLib.AO_LOG_PRODUCT; - data = tokens[1]; - } else if (tokens[0].equals("serial-number")) { - cmd = AltosLib.AO_LOG_SERIAL_NUMBER; - a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("log-format")) { - cmd = AltosLib.AO_LOG_LOG_FORMAT; - a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("software-version")) { - cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; - data = tokens[1]; - } else { - cmd = AltosLib.AO_LOG_INVALID; - data = line; - } - } catch (NumberFormatException ne) { - cmd = AltosLib.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; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java deleted file mode 100644 index 1758fa34..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosEepromTeleScience.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.*; - -public class AltosEepromTeleScience { - public int type; - public int tick; - public int tm_state; - public int tm_tick; - public int[] data; - public boolean valid; - - public static final int AO_LOG_TELESCIENCE_START = 's'; - public static final int AO_LOG_TELESCIENCE_DATA = 'd'; - - static final int max_data = 12; - public static final int record_length = 32; - - public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { - type = chunk.data(start); - - valid = !chunk.erased(start, record_length); - if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - type = AltosLib.AO_LOG_INVALID; - } - - tick = chunk.data16(start+2); - tm_tick = chunk.data16(start+4); - tm_state = chunk.data(start+6); - data = new int[max_data]; - for (int i = 0; i < max_data; i++) - data[i] = chunk.data16(start + 8 + i * 2); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java deleted file mode 100644 index d2e4f2f7..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFile.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.io.File; -import java.util.*; - -public class AltosFile extends File { - - public AltosFile(int year, int month, int day, int serial, int flight, String extension) { - super (AltosPreferences.logdir(), - String.format("%04d-%02d-%02d-serial-%03d-flight-%03d.%s", - year, month, day, serial, flight, extension)); - } - - public AltosFile(int serial, int flight, String extension) { - this(Calendar.getInstance().get(Calendar.YEAR), - Calendar.getInstance().get(Calendar.MONTH) + 1, - Calendar.getInstance().get(Calendar.DAY_OF_MONTH), - serial, - flight, - extension); - } - - public AltosFile(AltosRecord telem) { - this(telem.serial, telem.flight, "telem"); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java deleted file mode 100644 index 3fdea469..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFlightReader.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.io.*; -import java.util.concurrent.*; - -public class AltosFlightReader { - public String name; - - public int serial; - - public void init() { } - - public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; } - - public void close(boolean interrupted) { } - - public void set_frequency(double frequency) throws InterruptedException, TimeoutException { } - - public void save_frequency() { } - - public void set_telemetry(int telemetry) { } - - public void save_telemetry() { } - - public void update(AltosState state) throws InterruptedException { } - - public boolean supports_telemetry(int telemetry) { return false; } - - public File backing_file() { return null; } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java deleted file mode 100644 index f08ff116..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosFrequency.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosFrequency { - public double frequency; - public String description; - - public String toString() { - return String.format("%7.3f MHz %-20s", - frequency, description); - } - - public String toShortString() { - return String.format("%7.3f MHz %s", - frequency, description); - } - - public boolean close(double f) { - double diff = Math.abs(frequency - f); - - return diff < 0.010; - } - - public AltosFrequency(double f, String d) { - frequency = f; - description = d; - } -} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java deleted file mode 100644 index f078a469..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPS.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; - -public class AltosGPS { - - public final static int MISSING = AltosRecord.MISSING; - - public int nsat; - public boolean locked; - public boolean connected; - public double lat; /* degrees (+N -S) */ - public double lon; /* degrees (+E -W) */ - public int alt; /* m */ - public int year; - public int month; - public int day; - public int hour; - public int minute; - public int second; - - public double ground_speed; /* m/s */ - public int course; /* degrees */ - public double climb_rate; /* m/s */ - public double hdop; /* unitless */ - public double vdop; /* unitless */ - public int h_error; /* m */ - public int v_error; /* m */ - - public AltosGPSSat[] cc_gps_sat; /* tracking data */ - - public 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]); - } - - public 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 = AltosParse.parse_int(hms[0]); - minute = AltosParse.parse_int(hms[1]); - second = AltosParse.parse_int(hms[2]); - } - - public void ClearGPSTime() { - year = month = day = 0; - hour = minute = second = 0; - } - - public AltosGPS(AltosTelemetryMap map) throws ParseException { - String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, - AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); - - nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); - if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { - connected = true; - locked = true; - lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); - lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); - alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); - year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); - if (year != MISSING) - year += 2000; - month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); - day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); - - hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); - minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); - second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); - - ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, - AltosRecord.MISSING, 1/100.0); - course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, - AltosRecord.MISSING); - hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); - vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); - h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); - v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); - } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { - connected = true; - locked = false; - } else { - connected = false; - locked = false; - } - } - - 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"); - - connected = false; - locked = false; - lat = lon = 0; - alt = 0; - ClearGPSTime(); - if ((words[i]).equals("unlocked")) { - connected = true; - i++; - } else if ((words[i]).equals("not-connected")) { - i++; - } else if (words.length >= 40) { - locked = true; - connected = true; - - 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(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++; - } - 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 AltosGPSSat[tracking_channels]; - for (int chan = 0; chan < tracking_channels; chan++) { - cc_gps_sat[chan] = new 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 AltosGPSSat[0]; - } - - public void set_latitude(int in_lat) { - lat = in_lat / 10.0e7; - } - - public void set_longitude(int in_lon) { - lon = in_lon / 10.0e7; - } - - public void set_time(int hour, int minute, int second) { - hour = hour; - minute = minute; - second = second; - } - - public void set_date(int year, int month, int day) { - year = year; - month = month; - day = day; - } - - public void set_flags(int flags) { - flags = flags; - } - - public void set_altitude(int altitude) { - altitude = altitude; - } - - public void add_sat(int svid, int c_n0) { - if (cc_gps_sat == null) { - cc_gps_sat = new AltosGPSSat[1]; - } else { - AltosGPSSat[] new_gps_sat = new AltosGPSSat[cc_gps_sat.length + 1]; - for (int i = 0; i < cc_gps_sat.length; i++) - new_gps_sat[i] = cc_gps_sat[i]; - cc_gps_sat = new_gps_sat; - } - AltosGPSSat sat = new AltosGPSSat(); - sat.svid = svid; - sat.c_n0 = c_n0; - cc_gps_sat[cc_gps_sat.length - 1] = sat; - } - - public AltosGPS() { - ClearGPSTime(); - cc_gps_sat = null; - } - - public AltosGPS(AltosGPS old) { - nsat = old.nsat; - locked = old.locked; - connected = old.connected; - lat = old.lat; /* degrees (+N -S) */ - lon = old.lon; /* degrees (+E -W) */ - alt = old.alt; /* m */ - year = old.year; - month = old.month; - day = old.day; - hour = old.hour; - minute = old.minute; - second = old.second; - - ground_speed = old.ground_speed; /* m/s */ - course = old.course; /* degrees */ - climb_rate = old.climb_rate; /* m/s */ - hdop = old.hdop; /* unitless? */ - h_error = old.h_error; /* m */ - v_error = old.v_error; /* m */ - - if (old.cc_gps_sat != null) { - cc_gps_sat = new AltosGPSSat[old.cc_gps_sat.length]; - for (int i = 0; i < old.cc_gps_sat.length; i++) { - cc_gps_sat[i] = new AltosGPSSat(); - cc_gps_sat[i].svid = old.cc_gps_sat[i].svid; - cc_gps_sat[i].c_n0 = old.cc_gps_sat[i].c_n0; - } - } - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java deleted file mode 100644 index faa1ec8d..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGPSSat.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosGPSSat { - public int svid; - public int c_n0; - - public AltosGPSSat(int s, int c) { - svid = s; - c_n0= c; - } - - public AltosGPSSat() { - } -} - diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java deleted file mode 100644 index 76b71859..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosGreatCircle.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.Math; - -public class AltosGreatCircle { - public double distance; - public double bearing; - - double sqr(double a) { return a * a; } - - static final double rad = Math.PI / 180; - static final double earth_radius = 6371.2 * 1000; /* in meters */ - - public static final int BEARING_LONG = 0; - public static final int BEARING_SHORT = 1; - public static final int BEARING_VOICE = 2; - - public String bearing_words(int length) { - String [][] bearing_string = { - { - "North", "North North East", "North East", "East North East", - "East", "East South East", "South East", "South South East", - "South", "South South West", "South West", "West South West", - "West", "West North West", "North West", "North North West" - }, { - "N", "NNE", "NE", "ENE", - "E", "ESE", "SE", "SSE", - "S", "SSW", "SW", "WSW", - "W", "WNW", "NW", "NNW" - }, { - "north", "nor nor east", "north east", "east nor east", - "east", "east sow east", "south east", "sow sow east", - "south", "sow sow west", "south west", "west sow west", - "west", "west nor west", "north west", "nor nor west " - } - }; - return bearing_string[length][(int)((bearing / 90 * 8 + 1) / 2)%16]; - } - - public AltosGreatCircle (double start_lat, double start_lon, - double end_lat, double end_lon) - { - double lat1 = rad * start_lat; - double lon1 = rad * -start_lon; - double lat2 = rad * end_lat; - double lon2 = rad * -end_lon; - - double d_lon = lon2 - lon1; - - /* From http://en.wikipedia.org/wiki/Great-circle_distance */ - double vdn = Math.sqrt(sqr(Math.cos(lat2) * Math.sin(d_lon)) + - sqr(Math.cos(lat1) * Math.sin(lat2) - - Math.sin(lat1) * Math.cos(lat2) * Math.cos(d_lon))); - double vdd = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos(d_lon); - double d = Math.atan2(vdn,vdd); - double course; - - if (Math.cos(lat1) < 1e-20) { - if (lat1 > 0) - course = Math.PI; - else - course = -Math.PI; - } else { - if (d < 1e-10) - course = 0; - else - course = Math.acos((Math.sin(lat2)-Math.sin(lat1)*Math.cos(d)) / - (Math.sin(d)*Math.cos(lat1))); - if (Math.sin(lon2-lon1) > 0) - course = 2 * Math.PI-course; - } - 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; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java deleted file mode 100644 index 2921d040..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLib.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.awt.*; -import java.util.*; -import java.text.*; -import java.nio.charset.Charset; - -public class AltosLib { - /* EEProm command letters */ - public static final int AO_LOG_FLIGHT = 'F'; - public static final int AO_LOG_SENSOR = 'A'; - public static final int AO_LOG_TEMP_VOLT = 'T'; - public static final int AO_LOG_DEPLOY = 'D'; - public static final int AO_LOG_STATE = 'S'; - public static final int AO_LOG_GPS_TIME = 'G'; - public static final int AO_LOG_GPS_LAT = 'N'; - public static final int AO_LOG_GPS_LON = 'W'; - public static final int AO_LOG_GPS_ALT = 'H'; - public static final int AO_LOG_GPS_SAT = 'V'; - public static final int AO_LOG_GPS_DATE = 'Y'; - public static final int AO_LOG_PRESSURE = 'P'; - - /* Added for header fields in eeprom files */ - public static final int AO_LOG_CONFIG_VERSION = 1000; - public static final int AO_LOG_MAIN_DEPLOY = 1001; - public static final int AO_LOG_APOGEE_DELAY = 1002; - public static final int AO_LOG_RADIO_CHANNEL = 1003; - public static final int AO_LOG_CALLSIGN = 1004; - public static final int AO_LOG_ACCEL_CAL = 1005; - public static final int AO_LOG_RADIO_CAL = 1006; - public static final int AO_LOG_MAX_FLIGHT_LOG = 1007; - public static final int AO_LOG_MANUFACTURER = 2000; - public static final int AO_LOG_PRODUCT = 2001; - public static final int AO_LOG_SERIAL_NUMBER = 2002; - public static final int AO_LOG_LOG_FORMAT = 2003; - public static final int AO_LOG_SOFTWARE_VERSION = 9999; - - /* Added to flag invalid records */ - public static final int AO_LOG_INVALID = -1; - - /* Flight state numbers and names */ - public static final int ao_flight_startup = 0; - public static final int ao_flight_idle = 1; - public static final int ao_flight_pad = 2; - public static final int ao_flight_boost = 3; - public static final int ao_flight_fast = 4; - public static final int ao_flight_coast = 5; - public static final int ao_flight_drogue = 6; - public static final int ao_flight_main = 7; - public static final int ao_flight_landed = 8; - public static final int ao_flight_invalid = 9; - - /* Telemetry modes */ - public static final int ao_telemetry_off = 0; - public static final int ao_telemetry_min = 1; - public static final int ao_telemetry_standard = 1; - public static final int ao_telemetry_0_9 = 2; - public static final int ao_telemetry_0_8 = 3; - public static final int ao_telemetry_max = 3; - - public static final String[] ao_telemetry_name = { - "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" - }; - - public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt"; - - public static final int ao_telemetry_standard_len = 32; - public static final int ao_telemetry_0_9_len = 95; - public static final int ao_telemetry_0_8_len = 94; - - public static final int[] ao_telemetry_len = { - 0, 32, 95, 94 - }; - - public static HashMap string_to_state = new HashMap(); - - public static boolean map_initialized = false; - - public static void initialize_map() - { - string_to_state.put("startup", ao_flight_startup); - string_to_state.put("idle", ao_flight_idle); - string_to_state.put("pad", ao_flight_pad); - string_to_state.put("boost", ao_flight_boost); - string_to_state.put("fast", ao_flight_fast); - string_to_state.put("coast", ao_flight_coast); - string_to_state.put("drogue", ao_flight_drogue); - string_to_state.put("apogee", ao_flight_coast); - string_to_state.put("main", ao_flight_main); - string_to_state.put("landed", ao_flight_landed); - string_to_state.put("invalid", ao_flight_invalid); - map_initialized = true; - } - - public static int telemetry_len(int telemetry) { - if (telemetry <= ao_telemetry_max) - return ao_telemetry_len[telemetry]; - throw new IllegalArgumentException(String.format("Invalid telemetry %d", - telemetry)); - } - - public static String telemetry_name(int telemetry) { - if (telemetry <= ao_telemetry_max) - return ao_telemetry_name[telemetry]; - throw new IllegalArgumentException(String.format("Invalid telemetry %d", - telemetry)); - } - - public static String[] state_to_string = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - public static String[] state_to_string_capital = { - "Startup", - "Idle", - "Pad", - "Boost", - "Fast", - "Coast", - "Drogue", - "Main", - "Landed", - "Invalid", - }; - - public static int state(String state) { - if (!map_initialized) - initialize_map(); - if (string_to_state.containsKey(state)) - return string_to_state.get(state); - return ao_flight_invalid; - } - - public static String state_name(int state) { - if (state < 0 || state_to_string.length <= state) - return "invalid"; - return state_to_string[state]; - } - - public static final int AO_GPS_VALID = (1 << 4); - public static final int AO_GPS_RUNNING = (1 << 5); - public static final int AO_GPS_DATE_VALID = (1 << 6); - public static final int AO_GPS_NUM_SAT_SHIFT = 0; - public static final int AO_GPS_NUM_SAT_MASK = 0xf; - - public static final int AO_LOG_FORMAT_UNKNOWN = 0; - public static final int AO_LOG_FORMAT_FULL = 1; - public static final int AO_LOG_FORMAT_TINY = 2; - public static final int AO_LOG_FORMAT_TELEMETRY = 3; - public static final int AO_LOG_FORMAT_TELESCIENCE = 4; - public static final int AO_LOG_FORMAT_NONE = 127; - - public static boolean isspace(int c) { - switch (c) { - case ' ': - case '\t': - return true; - } - return false; - } - - public 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; - } - - public static boolean ishex(String s) { - for (int i = 0; i < s.length(); i++) - if (!ishex(s.charAt(i))) - return false; - return true; - } - - public 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; - } - - public 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; - } - - public static boolean isdec(int c) { - if ('0' <= c && c <= '9') - return true; - return false; - } - - public static boolean isdec(String s) { - for (int i = 0; i < s.length(); i++) - if (!isdec(s.charAt(i))) - return false; - return true; - } - - public static int fromdec(int c) { - if ('0' <= c && c <= '9') - return c - '0'; - return -1; - } - - public static int int8(int[] bytes, int i) { - return (int) (byte) bytes[i]; - } - - public static int uint8(int[] bytes, int i) { - return bytes[i]; - } - - public static int int16(int[] bytes, int i) { - return (int) (short) (bytes[i] + (bytes[i+1] << 8)); - } - - public static int uint16(int[] bytes, int i) { - return bytes[i] + (bytes[i+1] << 8); - } - - public static int uint32(int[] bytes, int i) { - return bytes[i] + - (bytes[i+1] << 8) + - (bytes[i+2] << 16) + - (bytes[i+3] << 24); - } - - public static final Charset unicode_set = Charset.forName("UTF-8"); - - public static String string(int[] bytes, int s, int l) { - if (s + l > bytes.length) { - if (s > bytes.length) { - s = bytes.length; - l = 0; - } else { - l = bytes.length - s; - } - } - - int i; - for (i = l - 1; i >= 0; i--) - if (bytes[s+i] != 0) - break; - - l = i + 1; - byte[] b = new byte[l]; - - for (i = 0; i < l; i++) - b[i] = (byte) bytes[s+i]; - String n = new String(b, unicode_set); - return n; - } - - public static int hexbyte(String s, int i) { - int c0, c1; - - if (s.length() < i + 2) - throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); - c0 = s.charAt(i); - if (!ishex(c0)) - throw new NumberFormatException(String.format("invalid hex \"%c\"", c0)); - c1 = s.charAt(i+1); - if (!ishex(c1)) - throw new NumberFormatException(String.format("invalid hex \"%c\"", c1)); - return fromhex(c0) * 16 + fromhex(c1); - } - - public static int[] hexbytes(String s) { - int n; - int[] r; - int i; - - if ((s.length() & 1) != 0) - throw new NumberFormatException(String.format("invalid line \"%s\"", s)); - n = s.length() / 2; - r = new int[n]; - for (i = 0; i < n; i++) - r[i] = hexbyte(s, i * 2); - return r; - } - - public 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; - } - - public static String replace_extension(String input, String extension) { - int dot = input.lastIndexOf("."); - if (dot > 0) - input = input.substring(0,dot); - return input.concat(extension); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java deleted file mode 100644 index 5627795a..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLine.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosLine { - public String line; - - public AltosLine() { - line = null; - } - - public AltosLine(String s) { - line = s; - } -} \ No newline at end of file diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java deleted file mode 100644 index 9b80e916..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLink.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.io.*; -import java.util.concurrent.*; -import java.util.*; -import java.text.*; - -public abstract class AltosLink { - public abstract void print(String data); - public abstract void close(); - - public static boolean debug = false; - public static void set_debug(boolean in_debug) { debug = in_debug; } - LinkedList pending_output = new LinkedList(); - - public LinkedList> monitors = new LinkedList> ();; - public LinkedBlockingQueue reply_queue = new LinkedBlockingQueue(); - - public void add_monitor(LinkedBlockingQueue q) { - set_monitor(true); - monitors.add(q); - } - - public void remove_monitor(LinkedBlockingQueue q) { - monitors.remove(q); - if (monitors.isEmpty()) - set_monitor(false); - } - - public void printf(String format, Object ... arguments) { - String line = String.format(format, arguments); - if (debug) - pending_output.add(line); - print(line); - } - - public String get_reply_no_dialog(int timeout) throws InterruptedException, TimeoutException { - flush_output(); - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line != null) - return line.line; - return null; - } - - public String get_reply(int timeout) throws InterruptedException { - try { - return get_reply_no_dialog(timeout); - } catch (TimeoutException te) { - return null; - } - } - - public String get_reply() throws InterruptedException { - return get_reply(5000); - } - - public void add_telem(AltosLine line) throws InterruptedException { - for (int e = 0; e < monitors.size(); e++) { - LinkedBlockingQueue q = monitors.get(e); - q.put(line); - } - } - - public void add_reply(AltosLine line) throws InterruptedException { - reply_queue.put (line); - } - - public void add_string(String line) throws InterruptedException { - if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { - add_telem(new AltosLine(line)); - } else { - add_reply(new AltosLine(line)); - } - } - - public void add_bytes(byte[] bytes, int len) throws InterruptedException { - String line; - try { - line = new String(bytes, 0, len, "UTF-8"); - } catch (UnsupportedEncodingException ue) { - line = ""; - for (int i = 0; i < len; i++) - line = line + bytes[i]; - } - if (debug) - System.out.printf("\t\t\t\t\t%s\n", line); - add_string(line); - } - - public void flush_output() { - for (String s : pending_output) - System.out.print(s); - pending_output.clear(); - } - - public void flush_input(int timeout) throws InterruptedException { - flush_output(); - boolean got_some; - - do { - Thread.sleep(timeout); - got_some = !reply_queue.isEmpty(); - reply_queue.clear(); - } while (got_some); - } - - - public void flush_input() throws InterruptedException { - flush_input(100); - } - - - /* - * Various command-level operations on - * the link - */ - public boolean monitor_mode = false; - public int telemetry = AltosLib.ao_telemetry_standard; - public double frequency; - AltosConfigData config_data; - - private int telemetry_len() { - return AltosLib.telemetry_len(telemetry); - } - - public void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - if (monitor_mode) - printf("m 0\nm %x\n", telemetry_len()); - flush_output(); - } - - public void set_monitor(boolean monitor) { - monitor_mode = monitor; - if (monitor) - printf("m %x\n", telemetry_len()); - else - printf("m 0\n"); - flush_output(); - } - - private void set_channel(int channel) { - if (monitor_mode) - printf("m 0\nc r %d\nm %x\n", - channel, telemetry_len()); - else - printf("c r %d\n", channel); - flush_output(); - } - - private void set_radio_setting(int setting) { - if (monitor_mode) - printf("m 0\nc R %d\nm %x\n", - setting, telemetry_len()); - else - printf("c R %d\n", setting); - flush_output(); - } - - public void set_radio_frequency(double frequency, - boolean has_setting, - int cal) { - if (debug) - System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); - if (has_setting) - set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); - else - set_channel(AltosConvert.radio_frequency_to_channel(frequency)); - } - - public AltosConfigData config_data() throws InterruptedException, TimeoutException { - if (config_data == null) - config_data = new AltosConfigData(this); - return config_data; - } - - public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - config_data(); - set_radio_frequency(frequency, - config_data.radio_setting != 0, - config_data.radio_calibration); - } - - public void set_callsign(String callsign) { - printf ("c c %s\n", callsign); - flush_output(); - } - - public boolean remote; - public int serial; - public String name; - - public void start_remote() throws TimeoutException, InterruptedException { - if (debug) - System.out.printf("start remote %7.3f\n", frequency); - if (frequency == 0.0) - frequency = AltosPreferences.frequency(serial); - set_radio_frequency(frequency); - set_callsign(AltosPreferences.callsign()); - printf("p\nE 0\n"); - flush_input(); - remote = true; - } - - public void stop_remote() throws InterruptedException { - if (debug) - System.out.printf("stop remote\n"); - try { - flush_input(); - } finally { - printf ("~\n"); - flush_output(); - } - remote = false; - } - - public AltosLink() { - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java deleted file mode 100644 index 08c45ca8..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosLog.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.lang.*; -import java.util.*; -import java.text.ParseException; -import java.util.concurrent.LinkedBlockingQueue; - -/* - * This creates a thread to capture telemetry data and write it to - * a log file - */ -class AltosLog implements Runnable { - - LinkedBlockingQueue input_queue; - LinkedBlockingQueue pending_queue; - int serial; - int flight; - FileWriter log_file; - Thread log_thread; - AltosFile file; - - private void close_log_file() { - if (log_file != null) { - try { - log_file.close(); - } catch (IOException io) { - } - log_file = null; - } - } - - void close() { - close_log_file(); - if (log_thread != null) { - log_thread.interrupt(); - log_thread = null; - } - } - - File file() { - return file; - } - - boolean open (AltosRecord telem) throws IOException { - AltosFile a = new AltosFile(telem); - - System.out.printf("open %s\n", a.toString()); - log_file = new FileWriter(a, true); - if (log_file != null) { - while (!pending_queue.isEmpty()) { - try { - String s = pending_queue.take(); - log_file.write(s); - log_file.write('\n'); - } catch (InterruptedException ie) { - } - } - log_file.flush(); - file = a; - } - return log_file != null; - } - - public void run () { - try { - AltosRecord previous = null; - for (;;) { - AltosLine line = input_queue.take(); - if (line.line == null) - continue; - try { - AltosRecord telem = AltosTelemetry.parse(line.line, previous); - if (telem.serial != 0 && telem.flight != 0 && - (telem.serial != serial || telem.flight != flight || log_file == null)) - { - close_log_file(); - serial = telem.serial; - flight = telem.flight; - open(telem); - } - previous = telem; - } catch (ParseException pe) { - } catch (AltosCRCException ce) { - } - if (log_file != null) { - log_file.write(line.line); - log_file.write('\n'); - log_file.flush(); - } else - pending_queue.put(line.line); - } - } catch (InterruptedException ie) { - } catch (IOException ie) { - } - close(); - } - - public AltosLog (AltosLink link) { - pending_queue = new LinkedBlockingQueue (); - input_queue = new LinkedBlockingQueue (); - link.add_monitor(input_queue); - serial = -1; - flight = -1; - log_file = null; - log_thread = new Thread(this); - log_thread.start(); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java deleted file mode 100644 index 7d832f1a..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosParse.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.text.*; -import java.lang.*; - -public class AltosParse { - public static boolean isdigit(char c) { - return '0' <= c && c <= '9'; - } - - public static int parse_int(String v) throws ParseException { - try { - return AltosLib.fromdec(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing int " + v, 0); - } - } - - public static int parse_hex(String v) throws ParseException { - try { - return AltosLib.fromhex(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing hex " + v, 0); - } - } - - public static double parse_double(String v) throws ParseException { - try { - return Double.parseDouble(v); - } catch (NumberFormatException e) { - throw new ParseException("error parsing double " + v, 0); - } - } - - public static double parse_coord(String coord) throws ParseException { - String[] dsf = coord.split("\\D+"); - - if (dsf.length != 3) { - throw new ParseException("error parsing coord " + coord, 0); - } - int deg = parse_int(dsf[0]); - int min = parse_int(dsf[1]); - int frac = parse_int(dsf[2]); - - double r = deg + (min + frac / 10000.0) / 60.0; - if (coord.endsWith("S") || coord.endsWith("W")) - r = -r; - return r; - } - - public static String strip_suffix(String v, String suffix) { - if (v.endsWith(suffix)) - return v.substring(0, v.length() - suffix.length()); - return v; - } - - public static void word(String v, String m) throws ParseException { - if (!v.equals(m)) { - throw new ParseException("error matching '" + v + "' '" + m + "'", 0); - } - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java deleted file mode 100644 index 43c7088d..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosPreferences.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; -import java.awt.Component; -import javax.swing.*; -import javax.swing.filechooser.FileSystemView; - -public class AltosPreferences { - public static Preferences preferences; - - /* logdir preference name */ - public final static String logdirPreference = "LOGDIR"; - - /* channel preference name */ - public final static String channelPreferenceFormat = "CHANNEL-%d"; - - /* frequency preference name */ - public final static String frequencyPreferenceFormat = "FREQUENCY-%d"; - - /* telemetry format preference name */ - public final static String telemetryPreferenceFormat = "TELEMETRY-%d"; - - /* voice preference name */ - public final static String voicePreference = "VOICE"; - - /* callsign preference name */ - public final static String callsignPreference = "CALLSIGN"; - - /* firmware directory preference name */ - public final static String firmwaredirPreference = "FIRMWARE"; - - /* serial debug preference name */ - public final static String serialDebugPreference = "SERIAL-DEBUG"; - - /* scanning telemetry preferences name */ - public final static String scanningTelemetryPreference = "SCANNING-TELEMETRY"; - - /* Launcher serial preference name */ - public final static String launcherSerialPreference = "LAUNCHER-SERIAL"; - - /* Launcher channel preference name */ - public final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; - - /* Default logdir is ~/TeleMetrum */ - public final static String logdirName = "TeleMetrum"; - - /* Log directory */ - public static File logdir; - - /* Map directory -- hangs of logdir */ - public static File mapdir; - - /* Frequency (map serial to frequency) */ - public static Hashtable frequencies; - - /* Telemetry (map serial to telemetry format) */ - public static Hashtable telemetries; - - /* Voice preference */ - public static boolean voice; - - /* Callsign preference */ - public static String callsign; - - /* Firmware directory */ - public static File firmwaredir; - - /* Scanning telemetry */ - public static int scanning_telemetry; - - /* List of frequencies */ - public final static String common_frequencies_node_name = "COMMON-FREQUENCIES"; - public static AltosFrequency[] common_frequencies; - - public final static String frequency_count = "COUNT"; - public final static String frequency_format = "FREQUENCY-%d"; - public final static String description_format = "DESCRIPTION-%d"; - - public static AltosFrequency[] load_common_frequencies() { - AltosFrequency[] frequencies = null; - boolean existing = false; - try { - existing = preferences.nodeExists(common_frequencies_node_name); - } catch (BackingStoreException be) { - existing = false; - } - if (existing) { - Preferences node = preferences.node(common_frequencies_node_name); - int count = node.getInt(frequency_count, 0); - - frequencies = new AltosFrequency[count]; - for (int i = 0; i < count; i++) { - double frequency; - String description; - - frequency = node.getDouble(String.format(frequency_format, i), 0.0); - description = node.get(String.format(description_format, i), null); - frequencies[i] = new AltosFrequency(frequency, description); - } - } else { - frequencies = new AltosFrequency[10]; - for (int i = 0; i < 10; i++) { - frequencies[i] = new AltosFrequency(434.550 + i * .1, - String.format("Channel %d", i)); - } - } - return frequencies; - } - - public static void save_common_frequencies(AltosFrequency[] frequencies) { - Preferences node = preferences.node(common_frequencies_node_name); - - node.putInt(frequency_count, frequencies.length); - for (int i = 0; i < frequencies.length; i++) { - node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); - node.put(String.format(description_format, i), frequencies[i].description); - } - } - public static int launcher_serial; - - public static int launcher_channel; - - public static void init() { - preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); - - /* Initialize logdir from preferences */ - String logdir_string = preferences.get(logdirPreference, null); - if (logdir_string != null) - logdir = new File(logdir_string); - else { - /* Use the file system view default directory */ - logdir = new File(FileSystemView.getFileSystemView().getDefaultDirectory(), logdirName); - if (!logdir.exists()) - logdir.mkdirs(); - } - mapdir = new File(logdir, "maps"); - if (!mapdir.exists()) - mapdir.mkdirs(); - - frequencies = new Hashtable(); - - telemetries = new Hashtable(); - - voice = preferences.getBoolean(voicePreference, true); - - callsign = preferences.get(callsignPreference,"N0CALL"); - - scanning_telemetry = preferences.getInt(scanningTelemetryPreference,(1 << AltosLib.ao_telemetry_standard)); - - launcher_serial = preferences.getInt(launcherSerialPreference, 0); - - launcher_channel = preferences.getInt(launcherChannelPreference, 0); - - String firmwaredir_string = preferences.get(firmwaredirPreference, null); - if (firmwaredir_string != null) - firmwaredir = new File(firmwaredir_string); - else - firmwaredir = null; - - common_frequencies = load_common_frequencies(); - - } - - static { init(); } - - public static void flush_preferences() { - try { - preferences.flush(); - } catch (BackingStoreException ee) { -/* - if (component != null) - JOptionPane.showMessageDialog(component, - preferences.absolutePath(), - "Cannot save prefernces", - JOptionPane.ERROR_MESSAGE); - else -*/ - System.err.printf("Cannot save preferences\n"); - } - } - - public static void set_logdir(File new_logdir) { - logdir = new_logdir; - mapdir = new File(logdir, "maps"); - if (!mapdir.exists()) - mapdir.mkdirs(); - synchronized (preferences) { - preferences.put(logdirPreference, logdir.getPath()); - flush_preferences(); - } - } - - public static File logdir() { - return logdir; - } - - public static File mapdir() { - return mapdir; - } - - public static void set_frequency(int serial, double new_frequency) { - frequencies.put(serial, new_frequency); - synchronized (preferences) { - preferences.putDouble(String.format(frequencyPreferenceFormat, serial), new_frequency); - flush_preferences(); - } - } - - public static double frequency(int serial) { - if (frequencies.containsKey(serial)) - return frequencies.get(serial); - double frequency = preferences.getDouble(String.format(frequencyPreferenceFormat, serial), 0); - if (frequency == 0.0) { - int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0); - frequency = AltosConvert.radio_channel_to_frequency(channel); - } - frequencies.put(serial, frequency); - return frequency; - } - - public static void set_telemetry(int serial, int new_telemetry) { - telemetries.put(serial, new_telemetry); - synchronized (preferences) { - preferences.putInt(String.format(telemetryPreferenceFormat, serial), new_telemetry); - flush_preferences(); - } - } - - public static int telemetry(int serial) { - if (telemetries.containsKey(serial)) - return telemetries.get(serial); - int telemetry = preferences.getInt(String.format(telemetryPreferenceFormat, serial), - AltosLib.ao_telemetry_standard); - telemetries.put(serial, telemetry); - return telemetry; - } - - public static void set_scanning_telemetry(int new_scanning_telemetry) { - scanning_telemetry = new_scanning_telemetry; - synchronized (preferences) { - preferences.putInt(scanningTelemetryPreference, scanning_telemetry); - flush_preferences(); - } - } - - public static int scanning_telemetry() { - return scanning_telemetry; - } - - public static void set_voice(boolean new_voice) { - voice = new_voice; - synchronized (preferences) { - preferences.putBoolean(voicePreference, voice); - flush_preferences(); - } - } - - public static boolean voice() { - return voice; - } - - public static void set_callsign(String new_callsign) { - callsign = new_callsign; - synchronized(preferences) { - preferences.put(callsignPreference, callsign); - flush_preferences(); - } - } - - public static String callsign() { - return callsign; - } - - public static void set_firmwaredir(File new_firmwaredir) { - firmwaredir = new_firmwaredir; - synchronized (preferences) { - preferences.put(firmwaredirPreference, firmwaredir.getPath()); - flush_preferences(); - } - } - - public static File firmwaredir() { - return firmwaredir; - } - - public static void set_launcher_serial(int new_launcher_serial) { - launcher_serial = new_launcher_serial; - System.out.printf("set launcher serial to %d\n", new_launcher_serial); - synchronized (preferences) { - preferences.putInt(launcherSerialPreference, launcher_serial); - flush_preferences(); - } - } - - public static int launcher_serial() { - return launcher_serial; - } - - public static void set_launcher_channel(int new_launcher_channel) { - launcher_channel = new_launcher_channel; - System.out.printf("set launcher channel to %d\n", new_launcher_channel); - synchronized (preferences) { - preferences.putInt(launcherChannelPreference, launcher_channel); - flush_preferences(); - } - } - - public static int launcher_channel() { - return launcher_channel; - } - - public static Preferences bt_devices() { - return preferences.node("bt_devices"); - } - - public static AltosFrequency[] common_frequencies() { - return common_frequencies; - } - - public static void set_common_frequencies(AltosFrequency[] frequencies) { - common_frequencies = frequencies; - synchronized(preferences) { - save_common_frequencies(frequencies); - flush_preferences(); - } - } - - public static void add_common_frequency(AltosFrequency frequency) { - AltosFrequency[] new_frequencies = new AltosFrequency[common_frequencies.length + 1]; - int i; - - for (i = 0; i < common_frequencies.length; i++) { - if (frequency.frequency == common_frequencies[i].frequency) - return; - if (frequency.frequency < common_frequencies[i].frequency) - break; - new_frequencies[i] = common_frequencies[i]; - } - new_frequencies[i] = frequency; - for (; i < common_frequencies.length; i++) - new_frequencies[i+1] = common_frequencies[i]; - set_common_frequencies(new_frequencies); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java deleted file mode 100644 index e4915af0..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecord.java +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.util.HashMap; -import java.io.*; - -public class AltosRecord implements Comparable { - public final static int MISSING = 0x7fffffff; - - public static final int seen_flight = 1; - public static final int seen_sensor = 2; - public static final int seen_temp_volt = 4; - public static final int seen_deploy = 8; - public static final int seen_gps_time = 16; - public static final int seen_gps_lat = 32; - public static final int seen_gps_lon = 64; - public static final int seen_companion = 128; - public int seen; - - public int version; - public String callsign; - public int serial; - public int flight; - public int rssi; - public int status; - public int state; - public int tick; - - public int accel; - public int pres; - public int temp; - public int batt; - public int drogue; - public int main; - - public int ground_accel; - public int ground_pres; - public int accel_plus_g; - public int accel_minus_g; - - public double acceleration; - public double speed; - public double height; - - public int flight_accel; - public int flight_vel; - public int flight_pres; - - public AltosGPS gps; - public boolean new_gps; - - public AltosIMU imu; - public AltosMag mag; - - public double time; /* seconds since boost */ - - public int device_type; - public int config_major; - public int config_minor; - public int apogee_delay; - public int main_deploy; - public int flight_log_max; - public String firmware_version; - - public AltosRecordCompanion companion; - ->>>>>>> 5a249bc... altosui: Complete split out of separate java library - /* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - - public static final double counts_per_kPa = 27 * 2047 / 3300; - public static final double counts_at_101_3kPa = 1674.0; - - public static double - barometer_to_pressure(double count) - { - return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; - } - - public double raw_pressure() { - if (pres == MISSING) - return MISSING; - return barometer_to_pressure(pres); - } - - public double filtered_pressure() { - if (flight_pres == MISSING) - return MISSING; - return barometer_to_pressure(flight_pres); - } - - public double ground_pressure() { - if (ground_pres == MISSING) - return MISSING; - return barometer_to_pressure(ground_pres); - } - - public double raw_altitude() { - double p = raw_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double ground_altitude() { - double p = ground_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double filtered_altitude() { - if (height != MISSING && ground_pres != MISSING) - return height + ground_altitude(); - - double p = filtered_pressure(); - if (p == MISSING) - return MISSING; - return AltosConvert.pressure_to_altitude(p); - } - - public double filtered_height() { - if (height != MISSING) - return height; - - double f = filtered_altitude(); - double g = ground_altitude(); - if (f == MISSING || g == MISSING) - return MISSING; - return f - g; - } - - public double raw_height() { - double r = raw_altitude(); - double g = ground_altitude(); - - if (r == MISSING || g == MISSING) - return height; - return r - g; - } - - public double battery_voltage() { - if (batt == MISSING) - return MISSING; - return AltosConvert.cc_battery_to_voltage(batt); - } - - public double main_voltage() { - if (main == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(main); - } - - public double drogue_voltage() { - if (drogue == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(drogue); - } - - /* Value for the CC1111 built-in temperature sensor - * Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - */ - - public static double - thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - - public double temperature() { - if (temp == MISSING) - return MISSING; - return thermometer_to_temperature(temp); - } - - public double accel_counts_per_mss() { - double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; - - return counts_per_g / 9.80665; - } - - public double acceleration() { - if (acceleration != MISSING) - return acceleration; - - if (ground_accel == MISSING || accel == MISSING) - return MISSING; - return (ground_accel - accel) / accel_counts_per_mss(); - } - - public double accel_speed() { - if (speed != MISSING) - return speed; - if (flight_vel == MISSING) - return MISSING; - return flight_vel / (accel_counts_per_mss() * 100.0); - } - - public String state() { - return AltosLib.state_name(state); - } - - public static String gets(FileInputStream s) throws IOException { - int c; - String line = ""; - - while ((c = s.read()) != -1) { - if (c == '\r') - continue; - if (c == '\n') { - return line; - } - line = line + (char) c; - } - return null; - } - - public int compareTo(AltosRecord o) { - return tick - o.tick; - } - - public AltosRecord(AltosRecord old) { - version = old.version; - seen = old.seen; - callsign = old.callsign; - serial = old.serial; - flight = old.flight; - rssi = old.rssi; - status = old.status; - state = old.state; - tick = old.tick; - accel = old.accel; - pres = old.pres; - temp = old.temp; - batt = old.batt; - drogue = old.drogue; - main = old.main; - flight_accel = old.flight_accel; - ground_accel = old.ground_accel; - flight_vel = old.flight_vel; - flight_pres = old.flight_pres; - ground_pres = old.ground_pres; - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; - acceleration = old.acceleration; - speed = old.speed; - height = old.height; - gps = new AltosGPS(old.gps); - new_gps = false; - companion = old.companion; - imu = old.imu; - mag = old.mag; - } - - public AltosRecord() { - version = 0; - seen = 0; - callsign = "N0CALL"; - serial = 0; - flight = 0; - rssi = 0; - status = 0; - state = AltosLib.ao_flight_startup; - tick = 0; - accel = MISSING; - pres = MISSING; - temp = MISSING; - batt = MISSING; - drogue = MISSING; - main = MISSING; - flight_accel = 0; - ground_accel = 0; - flight_vel = 0; - flight_pres = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; - acceleration = MISSING; - speed = MISSING; - height = MISSING; - gps = new AltosGPS(); - new_gps = false; - companion = null; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java deleted file mode 100644 index c8cc6cac..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordCompanion.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosRecordCompanion { - public final static int board_id_telescience = 0x0a; - public final static int MAX_CHANNELS = 12; - - public int tick; - public int board_id; - public int update_period; - public int channels; - public int[] companion_data; - - public AltosRecordCompanion(int in_channels) { - channels = in_channels; - if (channels < 0) - channels = 0; - if (channels > MAX_CHANNELS) - channels = MAX_CHANNELS; - companion_data = new int[channels]; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java deleted file mode 100644 index ed1787ed..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosRecordIterable.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; - -public abstract class AltosRecordIterable implements Iterable { - public abstract Iterator iterator(); - public void write_comments(PrintStream out) { } - public boolean has_accel() { return false; } - public boolean has_gps() { return false; } - public boolean has_ignite() { return false; }; -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java deleted file mode 100644 index 1585f9eb..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosReplayReader.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; -import java.util.prefs.*; -import java.util.concurrent.LinkedBlockingQueue; - -/* - * Open an existing telemetry file and replay it in realtime - */ - -public class AltosReplayReader extends AltosFlightReader { - Iterator iterator; - File file; - - public AltosRecord read() { - if (iterator.hasNext()) - return iterator.next(); - return null; - } - - public void close (boolean interrupted) { - } - - public void update(AltosState state) throws InterruptedException { - /* Make it run in realtime after the rocket leaves the pad */ - if (state.state > AltosLib.ao_flight_pad) - Thread.sleep((int) (Math.min(state.time_change,10) * 1000)); - } - - public File backing_file() { return file; } - - public AltosReplayReader(Iterator in_iterator, File in_file) { - iterator = in_iterator; - file = in_file; - name = file.getName(); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java deleted file mode 100644 index 0645e448..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosState.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Track flight state from telemetry or eeprom data stream - */ - -package org.altusmetrum.AltosLib; - -public class AltosState { - public AltosRecord data; - - /* derived data */ - - public long report_time; - - public double time; - public double time_change; - public int tick; - - public int state; - public boolean landed; - public boolean ascent; /* going up? */ - public boolean boost; /* under power */ - - public double ground_altitude; - public double height; - public double speed; - public double acceleration; - public double battery; - public double temperature; - public double main_sense; - public double drogue_sense; - public double baro_speed; - - public double max_height; - public double max_acceleration; - public double max_speed; - public double max_baro_speed; - - public AltosGPS gps; - - public AltosIMU imu; - public AltosMag mag; - - public static final int MIN_PAD_SAMPLES = 10; - - public int npad; - public int ngps; - public int gps_waiting; - public boolean gps_ready; - - public AltosGreatCircle from_pad; - public double elevation; /* from pad */ - public double range; /* total distance */ - - public double gps_height; - - public int speak_tick; - public double speak_altitude; - - public void init (AltosRecord cur, AltosState prev_state) { - int i; - AltosRecord prev; - - data = cur; - - ground_altitude = data.ground_altitude(); - height = data.filtered_height(); - - report_time = System.currentTimeMillis(); - - acceleration = data.acceleration(); - speed = data.accel_speed(); - temperature = data.temperature(); - drogue_sense = data.drogue_voltage(); - main_sense = data.main_voltage(); - battery = data.battery_voltage(); - tick = data.tick; - state = data.state; - - if (prev_state != null) { - - /* Preserve any existing gps data */ - npad = prev_state.npad; - ngps = prev_state.ngps; - gps = prev_state.gps; - pad_lat = prev_state.pad_lat; - pad_lon = prev_state.pad_lon; - pad_alt = prev_state.pad_alt; - max_height = prev_state.max_height; - max_acceleration = prev_state.max_acceleration; - max_speed = prev_state.max_speed; - max_baro_speed = prev_state.max_baro_speed; - imu = prev_state.imu; - mag = prev_state.mag; - - /* make sure the clock is monotonic */ - while (tick < prev_state.tick) - tick += 65536; - - time_change = (tick - prev_state.tick) / 100.0; - - /* compute barometric speed */ - - double height_change = height - prev_state.height; - if (data.speed != AltosRecord.MISSING) - baro_speed = data.speed; - else { - if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; - } - } else { - npad = 0; - ngps = 0; - gps = null; - baro_speed = 0; - time_change = 0; - } - - time = tick / 100.0; - - if (cur.new_gps && (state == AltosLib.ao_flight_pad || state == AltosLib.ao_flight_idle)) { - - /* Track consecutive 'good' gps reports, waiting for 10 of them */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) - npad++; - else - npad = 0; - - /* Average GPS data while on the pad */ - if (data.gps != null && data.gps.locked && data.gps.nsat >= 4) { - if (ngps > 1) { - /* filter pad position */ - pad_lat = (pad_lat * 31.0 + data.gps.lat) / 32.0; - pad_lon = (pad_lon * 31.0 + data.gps.lon) / 32.0; - pad_alt = (pad_alt * 31.0 + data.gps.alt) / 32.0; - } else { - pad_lat = data.gps.lat; - pad_lon = data.gps.lon; - pad_alt = data.gps.alt; - } - ngps++; - } - } - - gps_waiting = MIN_PAD_SAMPLES - npad; - if (gps_waiting < 0) - gps_waiting = 0; - - gps_ready = gps_waiting == 0; - - ascent = (AltosLib.ao_flight_boost <= state && - state <= AltosLib.ao_flight_coast); - boost = (AltosLib.ao_flight_boost == state); - - /* Only look at accelerometer data under boost */ - if (boost && acceleration > max_acceleration) - max_acceleration = acceleration; - if (boost && speed > max_speed) - max_speed = speed; - if (boost && baro_speed > max_baro_speed) - max_baro_speed = baro_speed; - - if (height > max_height) - max_height = height; - if (data.gps != null) { - if (gps == null || !gps.locked || data.gps.locked) - gps = data.gps; - if (ngps > 0 && gps.locked) { - from_pad = new AltosGreatCircle(pad_lat, pad_lon, gps.lat, gps.lon); - } - } - elevation = 0; - range = -1; - if (ngps > 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; - } - } - - public AltosState(AltosRecord cur) { - init(cur, null); - } - - public AltosState (AltosRecord cur, AltosState prev) { - init(cur, prev); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java deleted file mode 100644 index 04abb1f3..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetry.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.util.HashMap; - -/* - * Telemetry data contents - */ - - -/* - * The packet format is a simple hex dump of the raw telemetry frame. - * It starts with 'TELEM', then contains hex digits with a checksum as the last - * byte on the line. - * - * Version 4 is a replacement with consistent syntax. Each telemetry line - * contains a sequence of space-separated names and values, the values are - * either integers or strings. The names are all unique. All values are - * optional - * - * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 - * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 - * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 - * - * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 - * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - * - * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports - * in 1/2dB increments while this protocol provides only integers. So, - * the syntax didn't change just the interpretation of the RSSI - * values. - * - * Version 2 of the telemetry data stream is a bit of a mess, with no - * consistent formatting. In particular, the GPS data is formatted for - * viewing instead of parsing. However, the key feature is that every - * telemetry line contains all of the information necessary to - * describe the current rocket state, including the calibration values - * for accelerometer and barometer. - * - * GPS unlocked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ - * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ - * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 - * - * GPS locked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ - * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ - * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ - * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ - * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ - * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 - * - */ - -public class AltosTelemetry extends AltosRecord { - - /* - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - - final static String AO_TELEM_VERSION = "VERSION"; - final static String AO_TELEM_CALL = "c"; - final static String AO_TELEM_SERIAL = "n"; - final static String AO_TELEM_FLIGHT = "f"; - final static String AO_TELEM_RSSI = "r"; - final static String AO_TELEM_STATE = "s"; - final static String AO_TELEM_TICK = "t"; - - /* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - - final static String AO_TELEM_RAW_ACCEL = "r_a"; - final static String AO_TELEM_RAW_BARO = "r_b"; - final static String AO_TELEM_RAW_THERMO = "r_t"; - final static String AO_TELEM_RAW_BATT = "r_v"; - final static String AO_TELEM_RAW_DROGUE = "r_d"; - final static String AO_TELEM_RAW_MAIN = "r_m"; - - /* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - - final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; - final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; - final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; - final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; - - /* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - - final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; - final static String AO_TELEM_KALMAN_SPEED = "k_s"; - final static String AO_TELEM_KALMAN_ACCEL = "k_a"; - - /* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - - final static String AO_TELEM_ADHOC_ACCEL = "a_a"; - final static String AO_TELEM_ADHOC_SPEED = "a_s"; - final static String AO_TELEM_ADHOC_BARO = "a_b"; - - /* - * GPS values - * - * Name Value - * g_s GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - - final static String AO_TELEM_GPS_STATE = "g"; - final static String AO_TELEM_GPS_STATE_LOCKED = "l"; - final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; - final static String AO_TELEM_GPS_STATE_ERROR = "e"; - final static String AO_TELEM_GPS_NUM_SAT = "g_n"; - final static String AO_TELEM_GPS_LATITUDE = "g_ns"; - final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; - final static String AO_TELEM_GPS_ALTITUDE = "g_a"; - final static String AO_TELEM_GPS_YEAR = "g_Y"; - final static String AO_TELEM_GPS_MONTH = "g_M"; - final static String AO_TELEM_GPS_DAY = "g_D"; - final static String AO_TELEM_GPS_HOUR = "g_h"; - final static String AO_TELEM_GPS_MINUTE = "g_m"; - final static String AO_TELEM_GPS_SECOND = "g_s"; - final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; - final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; - final static String AO_TELEM_GPS_COURSE = "g_c"; - final static String AO_TELEM_GPS_HDOP = "g_hd"; - final static String AO_TELEM_GPS_VDOP = "g_vd"; - final static String AO_TELEM_GPS_HERROR = "g_he"; - final static String AO_TELEM_GPS_VERROR = "g_ve"; - - /* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - - final static String AO_TELEM_SAT_NUM = "s_n"; - final static String AO_TELEM_SAT_SVID = "s_v"; - final static String AO_TELEM_SAT_C_N_0 = "s_c"; - - static public AltosRecord parse(String line, AltosRecord previous) throws ParseException, AltosCRCException { - AltosTelemetryRecord r = AltosTelemetryRecord.parse(line); - - return r.update_state(previous); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java deleted file mode 100644 index f4b4029f..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryIterable.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.io.*; -import java.util.*; -import java.text.*; - -public class AltosTelemetryIterable extends AltosRecordIterable { - TreeSet records; - - public Iterator iterator () { - return records.iterator(); - } - - boolean has_gps = false; - boolean has_accel = false; - boolean has_ignite = false; - public boolean has_gps() { return has_gps; } - public boolean has_accel() { return has_accel; } - public boolean has_ignite() { return has_ignite; }; - - public AltosTelemetryIterable (FileInputStream input) { - boolean saw_boost = false; - int current_tick = 0; - int boost_tick = 0; - - AltosRecord previous = null; - records = new TreeSet (); - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) { - break; - } - try { - AltosRecord record = AltosTelemetry.parse(line, previous); - if (record == null) - break; - if (records.isEmpty()) { - current_tick = record.tick; - } else { - int tick = record.tick; - while (tick < current_tick - 0x1000) - tick += 0x10000; - current_tick = tick; - record.tick = current_tick; - } - if (!saw_boost && record.state >= AltosLib.ao_flight_boost) - { - saw_boost = true; - boost_tick = record.tick; - } - if (record.accel != AltosRecord.MISSING) - has_accel = true; - if (record.gps != null) - has_gps = true; - if (record.main != AltosRecord.MISSING) - has_ignite = true; - if (previous != null && previous.tick != record.tick) - records.add(previous); - previous = record; - } catch (ParseException pe) { - System.out.printf("parse exception %s\n", pe.getMessage()); - } catch (AltosCRCException ce) { - } - } - } catch (IOException io) { - System.out.printf("io exception\n"); - } - - if (previous != null) - records.add(previous); - - /* Adjust all tick counts to match expected eeprom values, - * which starts with a 16-bit tick count 16 samples before boost - */ - - int tick_adjust = (boost_tick - 16) & 0xffff0000; - for (AltosRecord r : this) - r.tick -= tick_adjust; - boost_tick -= tick_adjust; - - /* adjust all tick counts to be relative to boost time */ - for (AltosRecord r : this) - r.time = (r.tick - boost_tick) / 100.0; - - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java deleted file mode 100644 index 003cb6a9..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryMap.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; -import java.lang.*; -import java.text.*; -import java.util.HashMap; - -public class AltosTelemetryMap extends HashMap { - public boolean has(String key) { - return containsKey(key); - } - - public String get_string(String key) throws ParseException { - if (!has(key)) - throw new ParseException ("missing " + key, 0); - return (String) get(key); - } - - public String get_string(String key, String def) { - if (has(key)) - return get(key); - else - return def; - } - - public int get_int(String key) throws ParseException { - return AltosParse.parse_int(get_string(key)); - } - - public int get_int(String key, int def) throws ParseException { - if (has(key)) - return get_int(key); - else - return def; - } - - public double get_double(String key, double def, double scale) throws ParseException { - if (has(key)) - return get_int(key) * scale; - else - return def; - } - - public AltosTelemetryMap(String[] words, int start) { - for (int i = start; i < words.length - 1; i += 2) - put(words[i], words[i+1]); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java deleted file mode 100644 index 67ac1b65..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryReader.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.io.*; -import java.util.concurrent.*; - -public class AltosTelemetryReader extends AltosFlightReader { - AltosLink link; - AltosLog log; - AltosRecord previous; - double frequency; - int telemetry; - - LinkedBlockingQueue telem; - - public AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { - AltosLine l = telem.take(); - if (l.line == null) - throw new IOException("IO error"); - AltosRecord next = AltosTelemetry.parse(l.line, previous); - previous = next; - return next; - } - - public void flush() { - telem.clear(); - } - - public void close(boolean interrupted) { - link.remove_monitor(telem); - log.close(); - link.close(); - } - - public void set_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - link.set_radio_frequency(frequency); - } - - public boolean supports_telemetry(int telemetry) { - - try { - /* Version 1.0 or later firmware supports all telemetry formats */ - if (serial.config_data().compare_version("1.0") >= 0) - return true; - - /* Version 0.9 firmware only supports 0.9 telemetry */ - if (serial.config_data().compare_version("0.9") >= 0) { - if (telemetry == Altos.ao_telemetry_0_9) - return true; - else - return false; - } - - /* Version 0.8 firmware only supports 0.8 telemetry */ - if (telemetry == Altos.ao_telemetry_0_8) - return true; - else - return false; - } catch (InterruptedException ie) { - return true; - } catch (TimeoutException te) { - return true; - } - } - - public void save_frequency() { - AltosPreferences.set_frequency(link.serial, frequency); - } - - public void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - link.set_telemetry(telemetry); - } - - public void save_telemetry() { - AltosPreferences.set_telemetry(link.serial, telemetry); - } - - public void set_monitor(boolean monitor) { - link.set_monitor(monitor); - } - - public File backing_file() { - return log.file(); - } - - public AltosTelemetryReader (AltosLink in_link) - throws IOException, InterruptedException, TimeoutException { - link = in_link; - log = new AltosLog(link); - name = link.name; - previous = null; - telem = new LinkedBlockingQueue(); - frequency = AltosPreferences.frequency(link.serial); - set_frequency(frequency); - telemetry = AltosPreferences.telemetry(link.serial); - set_telemetry(telemetry); - link.add_monitor(telem); - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java deleted file mode 100644 index 367c148d..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecord.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public abstract class AltosTelemetryRecord { - - long received_time; - abstract public AltosRecord update_state(AltosRecord previous); - - static boolean cksum(int[] bytes) { - int sum = 0x5a; - for (int i = 1; i < bytes.length - 1; i++) - sum += bytes[i]; - sum &= 0xff; - return sum == bytes[bytes.length - 1]; - } - - final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); - final static int PKT_APPEND_STATUS_1_LQI_MASK = (0x7f); - final static int PKT_APPEND_STATUS_1_LQI_SHIFT = 0; - - final static int packet_type_TM_sensor = 0x01; - final static int packet_type_Tm_sensor = 0x02; - final static int packet_type_Tn_sensor = 0x03; - final static int packet_type_configuration = 0x04; - final static int packet_type_location = 0x05; - final static int packet_type_satellite = 0x06; - final static int packet_type_companion = 0x07; - - static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - int[] bytes; - try { - bytes = Altos.hexbytes(hex); - } catch (NumberFormatException ne) { - throw new ParseException(ne.getMessage(), 0); - } - - /* one for length, one for checksum */ - if (bytes[0] != bytes.length - 2) - throw new ParseException(String.format("invalid length %d != %d\n", - bytes[0], - bytes.length - 2), 0); - if (!cksum(bytes)) - throw new ParseException(String.format("invalid line \"%s\"", hex), 0); - - int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; - int status = Altos.uint8(bytes, bytes.length - 2); - - if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) - throw new AltosCRCException(rssi); - - /* length, data ..., rssi, status, checksum -- 4 bytes extra */ - switch (bytes.length) { - case Altos.ao_telemetry_standard_len + 4: - int type = Altos.uint8(bytes, 4 + 1); - switch (type) { - case packet_type_TM_sensor: - case packet_type_Tm_sensor: - case packet_type_Tn_sensor: - r = new AltosTelemetryRecordSensor(bytes, rssi); - break; - case packet_type_configuration: - r = new AltosTelemetryRecordConfiguration(bytes); - break; - case packet_type_location: - r = new AltosTelemetryRecordLocation(bytes); - break; - case packet_type_satellite: - r = new AltosTelemetryRecordSatellite(bytes); - break; - case packet_type_companion: - r = new AltosTelemetryRecordCompanion(bytes); - break; - default: - r = new AltosTelemetryRecordRaw(bytes); - break; - } - break; - case Altos.ao_telemetry_0_9_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - case Altos.ao_telemetry_0_8_len + 4: - r = new AltosTelemetryRecordLegacy(bytes, rssi, status); - break; - default: - throw new ParseException(String.format("Invalid packet length %d", bytes.length), 0); - } - r.received_time = System.currentTimeMillis(); - return r; - } - - public static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - String[] word = line.split("\\s+"); - int i =0; - if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(word[i++], "RSSI"); - throw new AltosCRCException(AltosParse.parse_int(word[i++])); - } - - if (word[i].equals("TELEM")) - r = parse_hex(word[i+1]); - else - r = new AltosTelemetryRecordLegacy(line); - return r; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java deleted file mode 100644 index 6ad17244..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordCompanion.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosTelemetryRecordCompanion extends AltosTelemetryRecordRaw { - - AltosRecordCompanion companion; - - public AltosTelemetryRecordCompanion(int[] in_bytes) { - super(in_bytes); - - int off = 0; - if (uint8(6) == 0) - off = 1; - int channels = uint8(7+off); - - if (off != 0 && channels >= 12) - channels = 11; - - companion = new AltosRecordCompanion(channels); - companion.tick = tick; - companion.board_id = uint8(5); - companion.update_period = uint8(6+off); - for (int i = 0; i < companion.companion_data.length; i++) - companion.companion_data[i] = uint16(8 + off + i * 2); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.companion = companion; - next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; - - companion.tick = tick; - return next; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java deleted file mode 100644 index 25242edc..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordConfiguration.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - - -public class AltosTelemetryRecordConfiguration extends AltosTelemetryRecordRaw { - int device_type; - int flight; - int config_major; - int config_minor; - int apogee_delay; - int main_deploy; - int flight_log_max; - String callsign; - String version; - - public AltosTelemetryRecordConfiguration(int[] in_bytes) { - super(in_bytes); - - device_type = uint8(5); - flight = uint16(6); - config_major = uint8(8); - config_minor = uint8(9); - apogee_delay = uint16(10); - main_deploy = uint16(12); - flight_log_max = uint16(14); - callsign = string(16, 8); - version = string(24, 8); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.device_type = device_type; - next.flight = flight; - next.config_major = config_major; - next.config_minor = config_minor; - next.apogee_delay = apogee_delay; - next.main_deploy = main_deploy; - next.flight_log_max = flight_log_max; - - next.callsign = callsign; - next.firmware_version = version; - - next.seen |= AltosRecord.seen_deploy | AltosRecord.seen_flight; - - return next; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java deleted file mode 100644 index 5e157a54..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordGeneral.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.util.HashMap; - -public class AltosTelemetryRecordGeneral { - - static AltosTelemetryRecord parse(String line) throws ParseException, AltosCRCException { - AltosTelemetryRecord r; - - String[] word = line.split("\\s+"); - int i =0; - if (word[i].equals("CRC") && word[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(word[i++], "RSSI"); - throw new AltosCRCException(AltosParse.parse_int(word[i++])); - } - - if (word[i].equals("TELEM")) - r = AltosTelemetryRecordRaw.parse(word[i+1]); - else - r = new AltosTelemetryRecordLegacy(line); - return r; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java deleted file mode 100644 index 8e3713cc..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLegacy.java +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.util.HashMap; - -/* - * Telemetry data contents - */ - - -/* - * The packet format is a simple hex dump of the raw telemetry frame. - * It starts with 'TELEM', then contains hex digits with a checksum as the last - * byte on the line. - * - * Version 4 is a replacement with consistent syntax. Each telemetry line - * contains a sequence of space-separated names and values, the values are - * either integers or strings. The names are all unique. All values are - * optional - * - * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 - * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 - * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 - * - * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 - * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - * - * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports - * in 1/2dB increments while this protocol provides only integers. So, - * the syntax didn't change just the interpretation of the RSSI - * values. - * - * Version 2 of the telemetry data stream is a bit of a mess, with no - * consistent formatting. In particular, the GPS data is formatted for - * viewing instead of parsing. However, the key feature is that every - * telemetry line contains all of the information necessary to - * describe the current rocket state, including the calibration values - * for accelerometer and barometer. - * - * GPS unlocked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -68 STATUS ff STATE pad 1001 \ - * a: 16032 p: 21232 t: 20284 v: 25160 d: 204 m: 204 fa: 16038 ga: 16032 fv: 0 \ - * fp: 21232 gp: 21230 a+: 16049 a-: 16304 GPS 0 sat unlocked SAT 1 15 30 - * - * GPS locked: - * - * VERSION 2 CALL KB0G SERIAL 51 FLIGHT 2 RSSI -71 STATUS ff STATE pad 2504 \ - * a: 16028 p: 21220 t: 20360 v: 25004 d: 208 m: 200 fa: 16031 ga: 16032 fv: 330 \ - * fp: 21231 gp: 21230 a+: 16049 a-: 16304 \ - * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ - * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ - * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 - * - */ - -public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { - /* - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - - final static String AO_TELEM_VERSION = "VERSION"; - final static String AO_TELEM_CALL = "c"; - final static String AO_TELEM_SERIAL = "n"; - final static String AO_TELEM_FLIGHT = "f"; - final static String AO_TELEM_RSSI = "r"; - final static String AO_TELEM_STATE = "s"; - final static String AO_TELEM_TICK = "t"; - - /* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - - final static String AO_TELEM_RAW_ACCEL = "r_a"; - final static String AO_TELEM_RAW_BARO = "r_b"; - final static String AO_TELEM_RAW_THERMO = "r_t"; - final static String AO_TELEM_RAW_BATT = "r_v"; - final static String AO_TELEM_RAW_DROGUE = "r_d"; - final static String AO_TELEM_RAW_MAIN = "r_m"; - - /* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - - final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; - final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; - final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; - final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; - - /* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - - final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; - final static String AO_TELEM_KALMAN_SPEED = "k_s"; - final static String AO_TELEM_KALMAN_ACCEL = "k_a"; - - /* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - - final static String AO_TELEM_ADHOC_ACCEL = "a_a"; - final static String AO_TELEM_ADHOC_SPEED = "a_s"; - final static String AO_TELEM_ADHOC_BARO = "a_b"; - - /* - * GPS values - * - * Name Value - * g_s GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - - final static String AO_TELEM_GPS_STATE = "g"; - final static String AO_TELEM_GPS_STATE_LOCKED = "l"; - final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; - final static String AO_TELEM_GPS_STATE_ERROR = "e"; - final static String AO_TELEM_GPS_NUM_SAT = "g_n"; - final static String AO_TELEM_GPS_LATITUDE = "g_ns"; - final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; - final static String AO_TELEM_GPS_ALTITUDE = "g_a"; - final static String AO_TELEM_GPS_YEAR = "g_Y"; - final static String AO_TELEM_GPS_MONTH = "g_M"; - final static String AO_TELEM_GPS_DAY = "g_D"; - final static String AO_TELEM_GPS_HOUR = "g_h"; - final static String AO_TELEM_GPS_MINUTE = "g_m"; - final static String AO_TELEM_GPS_SECOND = "g_s"; - final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; - final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; - final static String AO_TELEM_GPS_COURSE = "g_c"; - final static String AO_TELEM_GPS_HDOP = "g_hd"; - final static String AO_TELEM_GPS_VDOP = "g_vd"; - final static String AO_TELEM_GPS_HERROR = "g_he"; - final static String AO_TELEM_GPS_VERROR = "g_ve"; - - /* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - - final static String AO_TELEM_SAT_NUM = "s_n"; - final static String AO_TELEM_SAT_SVID = "s_v"; - final static String AO_TELEM_SAT_C_N_0 = "s_c"; - - AltosRecord record; - - private void parse_v4(String[] words, int i) throws ParseException { - AltosTelemetryMap map = new AltosTelemetryMap(words, i); - - record.callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); - record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); - record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); - record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); - record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); - record.tick = map.get_int(AO_TELEM_TICK, 0); - - /* raw sensor values */ - record.accel = map.get_int(AO_TELEM_RAW_ACCEL, AltosRecord.MISSING); - record.pres = map.get_int(AO_TELEM_RAW_BARO, AltosRecord.MISSING); - record.temp = map.get_int(AO_TELEM_RAW_THERMO, AltosRecord.MISSING); - record.batt = map.get_int(AO_TELEM_RAW_BATT, AltosRecord.MISSING); - record.drogue = map.get_int(AO_TELEM_RAW_DROGUE, AltosRecord.MISSING); - record.main = map.get_int(AO_TELEM_RAW_MAIN, AltosRecord.MISSING); - - /* sensor calibration information */ - record.ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, AltosRecord.MISSING); - record.ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, AltosRecord.MISSING); - record.accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, AltosRecord.MISSING); - record.accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, AltosRecord.MISSING); - - /* flight computer values */ - record.acceleration = map.get_double(AO_TELEM_KALMAN_ACCEL, AltosRecord.MISSING, 1/16.0); - record.speed = map.get_double(AO_TELEM_KALMAN_SPEED, AltosRecord.MISSING, 1/16.0); - record.height = map.get_int(AO_TELEM_KALMAN_HEIGHT, AltosRecord.MISSING); - - record.flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, AltosRecord.MISSING); - record.flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, AltosRecord.MISSING); - record.flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, AltosRecord.MISSING); - - if (map.has(AO_TELEM_GPS_STATE)) { - record.gps = new AltosGPS(map); - record.new_gps = true; - } - else - record.gps = null; - } - - private void parse_legacy(String[] words, int i) throws ParseException { - - AltosParse.word (words[i++], "CALL"); - record.callsign = words[i++]; - - AltosParse.word (words[i++], "SERIAL"); - record.serial = AltosParse.parse_int(words[i++]); - - if (record.version >= 2) { - AltosParse.word (words[i++], "FLIGHT"); - record.flight = AltosParse.parse_int(words[i++]); - } else - record.flight = 0; - - AltosParse.word(words[i++], "RSSI"); - record.rssi = AltosParse.parse_int(words[i++]); - - /* Older telemetry data had mis-computed RSSI value */ - if (record.version <= 2) - record.rssi = (record.rssi + 74) / 2 - 74; - - AltosParse.word(words[i++], "STATUS"); - record.status = AltosParse.parse_hex(words[i++]); - - AltosParse.word(words[i++], "STATE"); - record.state = Altos.state(words[i++]); - - record.tick = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a:"); - record.accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "p:"); - record.pres = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "t:"); - record.temp = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "v:"); - record.batt = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "d:"); - record.drogue = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "m:"); - record.main = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fa:"); - record.flight_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "ga:"); - record.ground_accel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fv:"); - record.flight_vel = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "fp:"); - record.flight_pres = AltosParse.parse_int(words[i++]); - - /* Old TeleDongle code with kalman-reporting TeleMetrum code */ - if ((record.flight_vel & 0xffff0000) == 0x80000000) { - record.speed = ((short) record.flight_vel) / 16.0; - record.acceleration = record.flight_accel / 16.0; - record.height = record.flight_pres; - record.flight_vel = AltosRecord.MISSING; - record.flight_pres = AltosRecord.MISSING; - record.flight_accel = AltosRecord.MISSING; - } - - AltosParse.word(words[i++], "gp:"); - record.ground_pres = AltosParse.parse_int(words[i++]); - - if (record.version >= 1) { - AltosParse.word(words[i++], "a+:"); - record.accel_plus_g = AltosParse.parse_int(words[i++]); - - AltosParse.word(words[i++], "a-:"); - record.accel_minus_g = AltosParse.parse_int(words[i++]); - } else { - record.accel_plus_g = record.ground_accel; - record.accel_minus_g = record.ground_accel + 530; - } - - record.gps = new AltosGPS(words, i, record.version); - record.new_gps = true; - } - - public AltosTelemetryRecordLegacy(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; - - record = new AltosRecord(); - - if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(words[i++], "RSSI"); - record.rssi = AltosParse.parse_int(words[i++]); - throw new AltosCRCException(record.rssi); - } - if (words[i].equals("CALL")) { - record.version = 0; - } else { - AltosParse.word (words[i++], "VERSION"); - record.version = AltosParse.parse_int(words[i++]); - } - - if (record.version < 4) - parse_legacy(words, i); - else - parse_v4(words, i); - } - - /* - * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that - */ - - int[] bytes; - int adjust; - - private int int8(int i) { - return AltosLib.int8(bytes, i + 1 + adjust); - } - private int uint8(int i) { - return AltosLib.uint8(bytes, i + 1 + adjust); - } - private int int16(int i) { - return AltosLib.int16(bytes, i + 1 + adjust); - } - private int uint16(int i) { - return AltosLib.uint16(bytes, i + 1 + adjust); - } - private int uint32(int i) { - return AltosLib.uint32(bytes, i + 1 + adjust); - } - private String string(int i, int l) { - return AltosLib.string(bytes, i + 1 + adjust, l); - } - - static final int AO_GPS_NUM_SAT_MASK = (0xf << 0); - static final int AO_GPS_NUM_SAT_SHIFT = (0); - - static final int AO_GPS_VALID = (1 << 4); - static final int AO_GPS_RUNNING = (1 << 5); - static final int AO_GPS_DATE_VALID = (1 << 6); - static final int AO_GPS_COURSE_VALID = (1 << 7); - - public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { - record = new AltosRecord(); - - bytes = in_bytes; - record.version = 4; - adjust = 0; - - if (bytes.length == AltosLib.ao_telemetry_0_8_len + 4) { - record.serial = uint8(0); - adjust = -1; - } else - record.serial = uint16(0); - - record.seen = AltosRecord.seen_flight | AltosRecord.seen_sensor | AltosRecord.seen_temp_volt | AltosRecord.seen_deploy; - - record.callsign = string(62, 8); - record.flight = uint16(2); - record.rssi = in_rssi; - record.status = in_status; - record.state = uint8(4); - record.tick = uint16(21); - record.accel = int16(23); - record.pres = int16(25); - record.temp = int16(27); - record.batt = int16(29); - record.drogue = int16(31); - record.main = int16(33); - - record.ground_accel = int16(7); - record.ground_pres = int16(15); - record.accel_plus_g = int16(17); - record.accel_minus_g = int16(19); - - if (uint16(11) == 0x8000) { - record.acceleration = int16(5); - record.speed = int16(9); - record.height = int16(13); - record.flight_accel = AltosRecord.MISSING; - record.flight_vel = AltosRecord.MISSING; - record.flight_pres = AltosRecord.MISSING; - } else { - record.flight_accel = int16(5); - record.flight_vel = uint32(9); - record.flight_pres = int16(13); - record.acceleration = AltosRecord.MISSING; - record.speed = AltosRecord.MISSING; - record.height = AltosRecord.MISSING; - } - - record.gps = null; - - int gps_flags = uint8(41); - - if ((gps_flags & (AO_GPS_VALID|AO_GPS_RUNNING)) != 0) { - record.gps = new AltosGPS(); - record.new_gps = true; - - record.seen |= record.seen_gps_time | record.seen_gps_lat | record.seen_gps_lon; - record.gps.nsat = (gps_flags & AO_GPS_NUM_SAT_MASK); - record.gps.locked = (gps_flags & AO_GPS_VALID) != 0; - record.gps.connected = true; - record.gps.lat = uint32(42) / 1.0e7; - record.gps.lon = uint32(46) / 1.0e7; - record.gps.alt = int16(50); - record.gps.ground_speed = uint16(52) / 100.0; - record.gps.course = uint8(54) * 2; - record.gps.hdop = uint8(55) / 5.0; - record.gps.h_error = uint16(58); - record.gps.v_error = uint16(60); - - int n_tracking_reported = uint8(70); - if (n_tracking_reported > 12) - n_tracking_reported = 12; - int n_tracking_actual = 0; - for (int i = 0; i < n_tracking_reported; i++) { - if (uint8(71 + i*2) != 0) - n_tracking_actual++; - } - if (n_tracking_actual > 0) { - record.gps.cc_gps_sat = new AltosGPSSat[n_tracking_actual]; - - n_tracking_actual = 0; - for (int i = 0; i < n_tracking_reported; i++) { - int svid = uint8(71 + i*2); - int c_n0 = uint8(72 + i*2); - if (svid != 0) - record.gps.cc_gps_sat[n_tracking_actual++] = new AltosGPSSat(svid, c_n0); - } - } - } - - record.time = 0.0; - } - - public AltosRecord update_state(AltosRecord previous) { - return record; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java deleted file mode 100644 index cddb773d..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordLocation.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - - -public class AltosTelemetryRecordLocation extends AltosTelemetryRecordRaw { - int flags; - int altitude; - int latitude; - int longitude; - int year; - int month; - int day; - int hour; - int minute; - int second; - int pdop; - int hdop; - int vdop; - int mode; - int ground_speed; - int climb_rate; - int course; - - public AltosTelemetryRecordLocation(int[] in_bytes) { - super(in_bytes); - - flags = uint8(5); - altitude = int16(6); - latitude = uint32(8); - longitude = uint32(12); - year = uint8(16); - month = uint8(17); - day = uint8(18); - hour = uint8(19); - minute = uint8(20); - second = uint8(21); - pdop = uint8(22); - hdop = uint8(23); - vdop = uint8(24); - mode = uint8(25); - ground_speed = uint16(26); - climb_rate = int16(28); - course = uint8(30); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - if (next.gps == null) - next.gps = new AltosGPS(); - - next.gps.nsat = flags & 0xf; - next.gps.locked = (flags & (1 << 4)) != 0; - next.gps.connected = (flags & (1 << 5)) != 0; - - if (next.gps.locked) { - next.gps.lat = latitude * 1.0e-7; - next.gps.lon = longitude * 1.0e-7; - next.gps.alt = altitude; - next.gps.year = 2000 + year; - next.gps.month = month; - next.gps.day = day; - next.gps.hour = hour; - next.gps.minute = minute; - next.gps.second = second; - next.gps.ground_speed = ground_speed * 1.0e-2; - next.gps.course = course * 2; - next.gps.climb_rate = climb_rate * 1.0e-2; - next.gps.hdop = hdop; - next.gps.vdop = vdop; - next.seen |= AltosRecord.seen_gps_time | AltosRecord.seen_gps_lat | AltosRecord.seen_gps_lon; - next.new_gps = true; - } - - return next; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java deleted file mode 100644 index 43d0f17a..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordRaw.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -import java.lang.*; -import java.text.*; -import java.util.HashMap; - -public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { - int[] bytes; - int serial; - int tick; - int type; - - long received_time; - - public int int8(int off) { - return AltosLib.int8(bytes, off + 1); - } - - public int uint8(int off) { - return AltosLib.uint8(bytes, off + 1); - } - - public int int16(int off) { - return AltosLib.int16(bytes, off + 1); - } - - public int uint16(int off) { - return AltosLib.uint16(bytes, off + 1); - } - - public int uint32(int off) { - return AltosLib.uint32(bytes, off + 1); - } - - public String string(int off, int l) { - return AltosLib.string(bytes, off + 1, l); - } - - public AltosTelemetryRecordRaw(int[] in_bytes) { - bytes = in_bytes; - serial = uint16(0); - tick = uint16(2); - type = uint8(4); - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next; - if (previous != null) - next = new AltosRecord(previous); - else - next = new AltosRecord(); - next.serial = serial; - next.tick = tick; - return next; - } - - public long received_time() { - return received_time; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java deleted file mode 100644 index 2526afb6..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSatellite.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - -public class AltosTelemetryRecordSatellite extends AltosTelemetryRecordRaw { - int channels; - AltosGPSSat[] sats; - - public AltosTelemetryRecordSatellite(int[] in_bytes) { - super(in_bytes); - - channels = uint8(5); - if (channels > 12) - channels = 12; - if (channels == 0) - sats = null; - else { - sats = new AltosGPSSat[channels]; - for (int i = 0; i < channels; i++) { - int svid = uint8(6 + i * 2 + 0); - int c_n_1 = uint8(6 + i * 2 + 1); - sats[i] = new AltosGPSSat(svid, c_n_1); - } - } - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - if (next.gps == null) - next.gps = new AltosGPS(); - - next.gps.cc_gps_sat = sats; - - return next; - } -} diff --git a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java b/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java deleted file mode 100644 index cfaf90b0..00000000 --- a/altosui/altoslib/src/org/altusmetrum/AltosLib/AltosTelemetryRecordSensor.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -package org.altusmetrum.AltosLib; - - -public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { - int state; - int accel; - int pres; - int temp; - int v_batt; - int sense_d; - int sense_m; - - int acceleration; - int speed; - int height; - - int ground_accel; - int ground_pres; - int accel_plus_g; - int accel_minus_g; - - int rssi; - - public AltosTelemetryRecordSensor(int[] in_bytes, int in_rssi) { - super(in_bytes); - state = uint8(5); - - accel = int16(6); - pres = int16(8); - temp = int16(10); - v_batt = int16(12); - sense_d = int16(14); - sense_m = int16(16); - - acceleration = int16(18); - speed = int16(20); - height = int16(22); - - ground_pres = int16(24); - ground_accel = int16(26); - accel_plus_g = int16(28); - accel_minus_g = int16(30); - - rssi = in_rssi; - } - - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); - - next.state = state; - if (type == packet_type_TM_sensor) - next.accel = accel; - else - next.accel = AltosRecord.MISSING; - next.pres = pres; - next.temp = temp; - next.batt = v_batt; - if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { - next.drogue = sense_d; - next.main = sense_m; - } else { - next.drogue = AltosRecord.MISSING; - next.main = AltosRecord.MISSING; - } - - next.acceleration = acceleration / 16.0; - next.speed = speed / 16.0; - next.height = height; - - next.ground_pres = ground_pres; - if (type == packet_type_TM_sensor) { - next.ground_accel = ground_accel; - next.accel_plus_g = accel_plus_g; - next.accel_minus_g = accel_minus_g; - } else { - next.ground_accel = AltosRecord.MISSING; - next.accel_plus_g = AltosRecord.MISSING; - next.accel_minus_g = AltosRecord.MISSING; - } - - next.rssi = rssi; - - next.seen |= AltosRecord.seen_sensor | AltosRecord.seen_temp_volt; - - return next; - } -} diff --git a/configure.ac b/configure.ac index efccf714..fb078e80 100644 --- a/configure.ac +++ b/configure.ac @@ -111,9 +111,9 @@ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) AC_OUTPUT([ Makefile +altoslib/Makefile altosui/Makefile altosui/AltosVersion.java -altosui/altoslib/Makefile altosui/libaltos/Makefile ao-tools/Makefile ao-tools/lib/Makefile -- cgit v1.2.3 From a48e4d40729e736929632ec422fd189ecdfba33b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Jan 2012 20:33:06 -0800 Subject: altosdroid: import code from mjb Signed-off-by: Keith Packard --- altosdroid/.classpath | 7 + altosdroid/.project | 33 ++ altosdroid/.settings/org.eclipse.jdt.core.prefs | 5 + altosdroid/AndroidManifest.xml | 38 +++ altosdroid/default.properties | 11 + altosdroid/keystore | Bin 0 -> 1270 bytes altosdroid/res/drawable-hdpi/app_icon.png | Bin 0 -> 5589 bytes altosdroid/res/drawable/app_icon.png | Bin 0 -> 4182 bytes altosdroid/res/layout/custom_title.xml | 39 +++ altosdroid/res/layout/device_list.xml | 56 ++++ altosdroid/res/layout/device_name.xml | 21 ++ altosdroid/res/layout/main.xml | 46 +++ altosdroid/res/layout/message.xml | 21 ++ altosdroid/res/menu/option_menu.xml | 26 ++ altosdroid/res/values/strings.xml | 41 +++ .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 357 ++++++++++++++++++++ .../AltosDroid/BluetoothChatService.java | 370 +++++++++++++++++++++ .../altusmetrum/AltosDroid/DeviceListActivity.java | 203 +++++++++++ 18 files changed, 1274 insertions(+) create mode 100644 altosdroid/.classpath create mode 100644 altosdroid/.project create mode 100644 altosdroid/.settings/org.eclipse.jdt.core.prefs create mode 100644 altosdroid/AndroidManifest.xml create mode 100644 altosdroid/default.properties create mode 100644 altosdroid/keystore create mode 100644 altosdroid/res/drawable-hdpi/app_icon.png create mode 100644 altosdroid/res/drawable/app_icon.png create mode 100644 altosdroid/res/layout/custom_title.xml create mode 100644 altosdroid/res/layout/device_list.xml create mode 100644 altosdroid/res/layout/device_name.xml create mode 100644 altosdroid/res/layout/main.xml create mode 100644 altosdroid/res/layout/message.xml create mode 100644 altosdroid/res/menu/option_menu.xml create mode 100644 altosdroid/res/values/strings.xml create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/DeviceListActivity.java diff --git a/altosdroid/.classpath b/altosdroid/.classpath new file mode 100644 index 00000000..6efcbb73 --- /dev/null +++ b/altosdroid/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/altosdroid/.project b/altosdroid/.project new file mode 100644 index 00000000..7b56596a --- /dev/null +++ b/altosdroid/.project @@ -0,0 +1,33 @@ + + + AltosDroid + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + diff --git a/altosdroid/.settings/org.eclipse.jdt.core.prefs b/altosdroid/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000..e5d1cd30 --- /dev/null +++ b/altosdroid/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +#Wed Sep 28 19:51:24 NZDT 2011 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/altosdroid/AndroidManifest.xml b/altosdroid/AndroidManifest.xml new file mode 100644 index 00000000..b72f0384 --- /dev/null +++ b/altosdroid/AndroidManifest.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/altosdroid/default.properties b/altosdroid/default.properties new file mode 100644 index 00000000..66db0d15 --- /dev/null +++ b/altosdroid/default.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "build.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=android-10 diff --git a/altosdroid/keystore b/altosdroid/keystore new file mode 100644 index 00000000..00739d03 Binary files /dev/null and b/altosdroid/keystore differ diff --git a/altosdroid/res/drawable-hdpi/app_icon.png b/altosdroid/res/drawable-hdpi/app_icon.png new file mode 100644 index 00000000..8836ff65 Binary files /dev/null and b/altosdroid/res/drawable-hdpi/app_icon.png differ diff --git a/altosdroid/res/drawable/app_icon.png b/altosdroid/res/drawable/app_icon.png new file mode 100644 index 00000000..d3e09a5b Binary files /dev/null and b/altosdroid/res/drawable/app_icon.png differ diff --git a/altosdroid/res/layout/custom_title.xml b/altosdroid/res/layout/custom_title.xml new file mode 100644 index 00000000..57eb6b4a --- /dev/null +++ b/altosdroid/res/layout/custom_title.xml @@ -0,0 +1,39 @@ + + + + + + \ No newline at end of file diff --git a/altosdroid/res/layout/device_list.xml b/altosdroid/res/layout/device_list.xml new file mode 100644 index 00000000..395695f8 --- /dev/null +++ b/altosdroid/res/layout/device_list.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + diff --git a/altosdroid/res/layout/telemetry_service_controller.xml b/altosdroid/res/layout/telemetry_service_controller.xml new file mode 100644 index 00000000..189d2f6c --- /dev/null +++ b/altosdroid/res/layout/telemetry_service_controller.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index 18de725c..27625e9c 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -14,6 +14,12 @@ limitations under the License. --> + + diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 60823b12..0b2f9227 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -38,4 +38,30 @@ Connect a device - Secure Connect a device - Insecure Make discoverable + + + AltOS Telemetry Service + Telemetry Service Started + Telemetry Service Stopped + + + + Start/Stop Service + Bind/Unbind Service + + App/Service/Local Service Controller + This demonstrates how you can implement persistent services that + may be started and stopped as desired. + Start Service + Stop Service + + App/Service/Local Service Binding + This demonstrates how you can connect with a persistent + service. Notice how it automatically starts for you, and play around with the + interaction between this and Local Service Controller. + Bind Service + Unbind Service + Connected to local service + Disconnected from local service + diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 87f89cf9..b4a3227c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -339,6 +339,14 @@ public class AltosDroid extends Activity { public boolean onOptionsItemSelected(MenuItem item) { Intent serverIntent = null; switch (item.getItemId()) { + case R.id.telemetry_service_control: + serverIntent = new Intent(this, TelemetryServiceActivities.Controller.class); + startActivity(serverIntent); + return true; + case R.id.telemetry_service_bind: + serverIntent = new Intent(this, TelemetryServiceActivities.Binding.class); + startActivity(serverIntent); + return true; case R.id.secure_connect_scan: // Launch the DeviceListActivity to see devices and do scan serverIntent = new Intent(this, DeviceListActivity.class); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java new file mode 100644 index 00000000..40dff354 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.altusmetrum.AltosDroid; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Intent; +import android.os.Binder; +import android.os.IBinder; +import android.util.Log; +import android.widget.Toast; + +// Need the following import to get access to the app resources, since this +// class is in a sub-package. +import org.altusmetrum.AltosDroid.R; + + + +public class TelemetryService extends Service { + private NotificationManager mNM; + + // Unique Identification Number for the Notification. + // We use it on Notification start, and to cancel it. + private int NOTIFICATION = R.string.telemetry_service_started; + + /** + * Class for clients to access. Because we know this service always + * runs in the same process as its clients, we don't need to deal with + * IPC. + */ + public class TelemetryBinder extends Binder { + TelemetryService getService() { + return TelemetryService.this; + } + } + + @Override + public void onCreate() { + mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + + // Display a notification about us starting. We put an icon in the status bar. + showNotification(); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.i("TelemetryService", "Received start id " + startId + ": " + intent); + // We want this service to continue running until it is explicitly + // stopped, so return sticky. + return START_STICKY; + } + + @Override + public void onDestroy() { + // Cancel the persistent notification. + mNM.cancel(NOTIFICATION); + + // Tell the user we stopped. + Toast.makeText(this, R.string.telemetry_service_stopped, Toast.LENGTH_SHORT).show(); + } + + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + // This is the object that receives interactions from clients. See + // RemoteService for a more complete example. + private final IBinder mBinder = new TelemetryBinder(); + + /** + * Show a notification while this service is running. + */ + private void showNotification() { + // In this sample, we'll use the same text for the ticker and the expanded notification + CharSequence text = getText(R.string.telemetry_service_started); + + // Set the icon, scrolling text and timestamp + Notification notification = new Notification(R.drawable.am_status, text, + System.currentTimeMillis()); + + // The PendingIntent to launch our activity if the user selects this notification + PendingIntent contentIntent = PendingIntent.getActivity(this, 0, + new Intent(this, TelemetryServiceActivities.Controller.class), 0); + + // Set the info for the views that show in the notification panel. + notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label), + text, contentIntent); + + // Send the notification. + mNM.notify(NOTIFICATION, notification); + } +} diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java new file mode 100644 index 00000000..5191cfa9 --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.altusmetrum.AltosDroid; + +import org.altusmetrum.AltosDroid.R; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.Button; +import android.widget.Toast; + +public class TelemetryServiceActivities { + /** + *

Example of explicitly starting and stopping the local service. + * This demonstrates the implementation of a service that runs in the same + * process as the rest of the application, which is explicitly started and stopped + * as desired.

+ * + *

Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + public static class Controller extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.telemetry_service_controller); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.start); + button.setOnClickListener(mStartListener); + button = (Button)findViewById(R.id.stop); + button.setOnClickListener(mStopListener); + } + + private OnClickListener mStartListener = new OnClickListener() { + public void onClick(View v) { + // Make sure the service is started. It will continue running + // until someone calls stopService(). The Intent we use to find + // the service explicitly specifies our service component, because + // we want it running in our own process and don't want other + // applications to replace it. + startService(new Intent(Controller.this, + TelemetryService.class)); + } + }; + + private OnClickListener mStopListener = new OnClickListener() { + public void onClick(View v) { + // Cancel a previous call to startService(). Note that the + // service will not actually stop at this point if there are + // still bound clients. + stopService(new Intent(Controller.this, + TelemetryService.class)); + } + }; + } + + // ---------------------------------------------------------------------- + + /** + * Example of binding and unbinding to the local service. + * This demonstrates the implementation of a service which the client will + * bind to, receiving an object through which it can communicate with the service.

+ * + *

Note that this is implemented as an inner class only keep the sample + * all together; typically this code would appear in some separate class. + */ + public static class Binding extends Activity { + private boolean mIsBound; + + + private TelemetryService mBoundService; + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + // This is called when the connection with the service has been + // established, giving us the service object we can use to + // interact with the service. Because we have bound to a explicit + // service that we know is running in our own process, we can + // cast its IBinder to a concrete class and directly access it. + mBoundService = ((TelemetryService.TelemetryBinder)service).getService(); + + // Tell the user about this for our demo. + Toast.makeText(Binding.this, R.string.telemetry_service_connected, + Toast.LENGTH_SHORT).show(); + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been + // unexpectedly disconnected -- that is, its process crashed. + // Because it is running in our same process, we should never + // see this happen. + mBoundService = null; + Toast.makeText(Binding.this, R.string.telemetry_service_disconnected, + Toast.LENGTH_SHORT).show(); + } + }; + + void doBindService() { + // Establish a connection with the service. We use an explicit + // class name because we want a specific service implementation that + // we know will be running in our own process (and thus won't be + // supporting component replacement by other applications). + bindService(new Intent(Binding.this, + TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + doUnbindService(); + } + + + private OnClickListener mBindListener = new OnClickListener() { + public void onClick(View v) { + doBindService(); + } + }; + + private OnClickListener mUnbindListener = new OnClickListener() { + public void onClick(View v) { + doUnbindService(); + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.telemetry_service_binding); + + // Watch for button clicks. + Button button = (Button)findViewById(R.id.bind); + button.setOnClickListener(mBindListener); + button = (Button)findViewById(R.id.unbind); + button.setOnClickListener(mUnbindListener); + } + } +} -- cgit v1.2.3 From e81163ed875dc93a618baf9278f43ed7dd0f730e Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 23 Feb 2012 16:43:04 +1300 Subject: Add local.properties to .gitignore Signed-off-by: Mike Beattie --- altosdroid/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore index 1a6498b3..44f249ee 100644 --- a/altosdroid/.gitignore +++ b/altosdroid/.gitignore @@ -1,3 +1,4 @@ +local.properties bin gen local.properties -- cgit v1.2.3 From 0772020c969a69c3b0a705de7362340a9732daab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:27:45 -0700 Subject: Build altosdroid --- Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 18845551..aaa0ae14 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS=src doc altoslib altosui ao-tools ao-utils +SUBDIRS=src doc altoslib altosui ao-tools ao-utils altosdroid EXTRA_DIST = ChangeLog -- cgit v1.2.3 From dd43a2ae7594f062a8980d1756a07488ee54b447 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 19:42:47 -0700 Subject: altoslib: Move new sensor library code into altoslib Signed-off-by: Keith Packard --- altoslib/AltosIMU.java | 29 ++++++++++++++++++ altoslib/AltosMag.java | 25 ++++++++++++++++ altoslib/AltosMs5607.java | 76 +++++++++++++++++++++++++++++++++++++++++++++++ altoslib/Makefile.am | 5 +++- altosui/AltosIMU.java | 29 ------------------ altosui/AltosMag.java | 25 ---------------- altosui/AltosMs5607.java | 76 ----------------------------------------------- altosui/Makefile.am | 3 -- 8 files changed, 134 insertions(+), 134 deletions(-) create mode 100644 altoslib/AltosIMU.java create mode 100644 altoslib/AltosMag.java create mode 100644 altoslib/AltosMs5607.java delete mode 100644 altosui/AltosIMU.java delete mode 100644 altosui/AltosMag.java delete mode 100644 altosui/AltosMs5607.java diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java new file mode 100644 index 00000000..88e36544 --- /dev/null +++ b/altoslib/AltosIMU.java @@ -0,0 +1,29 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 altoslib; + +public class AltosIMU { + public int accel_x; + public int accel_y; + public int accel_z; + + public int gyro_x; + public int gyro_y; + public int gyro_z; +} + \ No newline at end of file diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java new file mode 100644 index 00000000..45f1924c --- /dev/null +++ b/altoslib/AltosMag.java @@ -0,0 +1,25 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 altoslib; + +public class AltosMag { + public int x; + public int y; + public int z; +} + \ No newline at end of file diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java new file mode 100644 index 00000000..253e2f9b --- /dev/null +++ b/altoslib/AltosMs5607.java @@ -0,0 +1,76 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 altoslib; + +public class AltosMs5607 { + public int reserved; + public int sens; + public int off; + public int tcs; + public int tco; + public int tref; + public int tempsens; + public int crc; + + public int raw_pres; + public int raw_temp; + public int pa; + public int cc; + + void convert() { + int dT; + int TEMP; + long OFF; + long SENS; + int P; + + dT = raw_temp - ((int) tref << 8); + + TEMP = (int) (2000 + (((long) dT * tempsens) >> 23)); + + OFF = ((long) off << 17) + (((long) tco * dT) >> 6); + + SENS = ((long) sens << 16) + (((long) tcs * dT) >> 7); + + if (TEMP < 2000) { + int T2 = (int) (((long) dT * (long) dT) >> 31); + int TEMPM = TEMP - 2000; + long OFF2 = (61 * (long) TEMPM * (long) TEMPM) >> 4; + long SENS2 = 2 * (long) TEMPM * (long) TEMPM; + if (TEMP < 1500) { + int TEMPP = TEMP + 1500; + long TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; + } + + pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); + cc = TEMP; + } + + public int set(int in_pres, int in_temp) { + raw_pres = in_pres; + raw_temp = in_temp; + convert(); + return pa; + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 4262daca..2e4a795a 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -47,7 +47,10 @@ AltosLib_JAVA = \ $(SRC)/AltosTelemetryRecordLocation.java \ $(SRC)/AltosTelemetryRecordRaw.java \ $(SRC)/AltosTelemetryRecordSatellite.java \ - $(SRC)/AltosTelemetryRecordSensor.java + $(SRC)/AltosTelemetryRecordSensor.java \ + $(SRC)/AltosMs5607.java \ + $(SRC)/AltosIMU.java \ + $(SRC)/AltosMag.java JAR=AltosLib.jar diff --git a/altosui/AltosIMU.java b/altosui/AltosIMU.java deleted file mode 100644 index 1f865a65..00000000 --- a/altosui/AltosIMU.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 AltosIMU { - int accel_x; - int accel_y; - int accel_z; - - int gyro_x; - int gyro_y; - int gyro_z; -} - \ No newline at end of file diff --git a/altosui/AltosMag.java b/altosui/AltosMag.java deleted file mode 100644 index b3fc542b..00000000 --- a/altosui/AltosMag.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 AltosMag { - int x; - int y; - int z; -} - \ No newline at end of file diff --git a/altosui/AltosMs5607.java b/altosui/AltosMs5607.java deleted file mode 100644 index 6f8bdbbe..00000000 --- a/altosui/AltosMs5607.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 AltosMs5607 { - int reserved; - int sens; - int off; - int tcs; - int tco; - int tref; - int tempsens; - int crc; - - int raw_pres; - int raw_temp; - public int pa; - public int cc; - - void convert() { - int dT; - int TEMP; - long OFF; - long SENS; - int P; - - dT = raw_temp - ((int) tref << 8); - - TEMP = (int) (2000 + (((long) dT * tempsens) >> 23)); - - OFF = ((long) off << 17) + (((long) tco * dT) >> 6); - - SENS = ((long) sens << 16) + (((long) tcs * dT) >> 7); - - if (TEMP < 2000) { - int T2 = (int) (((long) dT * (long) dT) >> 31); - int TEMPM = TEMP - 2000; - long OFF2 = (61 * (long) TEMPM * (long) TEMPM) >> 4; - long SENS2 = 2 * (long) TEMPM * (long) TEMPM; - if (TEMP < 1500) { - int TEMPP = TEMP + 1500; - long TEMPP2 = TEMPP * TEMPP; - OFF2 = OFF2 + 15 * TEMPP2; - SENS2 = SENS2 + 8 * TEMPP2; - } - TEMP -= T2; - OFF -= OFF2; - SENS -= SENS2; - } - - pa = (int) (((((long) raw_pres * SENS) >> 21) - OFF) >> 15); - cc = TEMP; - } - - public int set(int in_pres, int in_temp) { - raw_pres = in_pres; - raw_temp = in_temp; - convert(); - return pa; - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 1ec45c5f..0a6ae59e 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -45,9 +45,6 @@ altosui_JAVA = \ AltosEepromTeleScience.java \ AltosEepromMega.java \ AltosEepromMegaIterable.java \ - AltosMs5607.java \ - AltosIMU.java \ - AltosMag.java \ AltosEepromSelect.java \ AltosFlash.java \ AltosFlashUI.java \ -- cgit v1.2.3 From f86dac643081987c8994ab57a96640d5e91b342a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 19:59:40 -0700 Subject: altoslib: Clean up random rebase failures Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 2 +- altoslib/AltosEepromIterable.java | 16 ++++---- altoslib/AltosIMU.java | 2 +- altoslib/AltosLib.java | 11 ++++++ altoslib/AltosMag.java | 2 +- altoslib/AltosMs5607.java | 2 +- altoslib/AltosRecord.java | 1 - altoslib/AltosState.java | 2 + altoslib/AltosTelemetryReader.java | 8 ++-- altoslib/AltosTelemetryRecord.java | 15 +++---- altoslib/AltosTelemetryRecordLegacy.java | 4 +- altosui/Altos.java | 67 -------------------------------- altosui/AltosSerial.java | 3 -- altosui/Makefile.am | 3 -- 14 files changed, 39 insertions(+), 99 deletions(-) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index 4ad4e58a..fa6a72b5 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -104,7 +104,7 @@ public class AltosConfigData implements Iterable { for (int i = 0; i < parts.length; i++) { try { - r[i] = Altos.fromdec(parts[i]); + r[i] = AltosLib.fromdec(parts[i]); } catch (NumberFormatException n) { r[i] = 0; } diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index f1397c7b..a923d63b 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -318,28 +318,28 @@ public class AltosEepromIterable extends AltosRecordIterable { case AltosLib.AO_LOG_SOFTWARE_VERSION: out.printf ("# Software version: %s\n", record.data); break; - case Altos.AO_LOG_BARO_RESERVED: + case AltosLib.AO_LOG_BARO_RESERVED: out.printf ("# Baro reserved: %d\n", record.a); break; - case Altos.AO_LOG_BARO_SENS: + case AltosLib.AO_LOG_BARO_SENS: out.printf ("# Baro sens: %d\n", record.a); break; - case Altos.AO_LOG_BARO_OFF: + case AltosLib.AO_LOG_BARO_OFF: out.printf ("# Baro off: %d\n", record.a); break; - case Altos.AO_LOG_BARO_TCS: + case AltosLib.AO_LOG_BARO_TCS: out.printf ("# Baro tcs: %d\n", record.a); break; - case Altos.AO_LOG_BARO_TCO: + case AltosLib.AO_LOG_BARO_TCO: out.printf ("# Baro tco: %d\n", record.a); break; - case Altos.AO_LOG_BARO_TREF: + case AltosLib.AO_LOG_BARO_TREF: out.printf ("# Baro tref: %d\n", record.a); break; - case Altos.AO_LOG_BARO_TEMPSENS: + case AltosLib.AO_LOG_BARO_TEMPSENS: out.printf ("# Baro tempsens: %d\n", record.a); break; - case Altos.AO_LOG_BARO_CRC: + case AltosLib.AO_LOG_BARO_CRC: out.printf ("# Baro crc: %d\n", record.a); break; } diff --git a/altoslib/AltosIMU.java b/altoslib/AltosIMU.java index 88e36544..c0eaf139 100644 --- a/altoslib/AltosIMU.java +++ b/altoslib/AltosIMU.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altoslib; +package org.altusmetrum.AltosLib; public class AltosIMU { public int accel_x; diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 2921d040..27d72079 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -50,6 +50,17 @@ public class AltosLib { public static final int AO_LOG_PRODUCT = 2001; public static final int AO_LOG_SERIAL_NUMBER = 2002; public static final int AO_LOG_LOG_FORMAT = 2003; + + /* Added for header fields in megametrum files */ + public static final int AO_LOG_BARO_RESERVED = 3000; + public static final int AO_LOG_BARO_SENS = 3001; + public static final int AO_LOG_BARO_OFF = 3002; + public static final int AO_LOG_BARO_TCS = 3004; + public static final int AO_LOG_BARO_TCO = 3005; + public static final int AO_LOG_BARO_TREF = 3006; + public static final int AO_LOG_BARO_TEMPSENS = 3007; + public static final int AO_LOG_BARO_CRC = 3008; + public static final int AO_LOG_SOFTWARE_VERSION = 9999; /* Added to flag invalid records */ diff --git a/altoslib/AltosMag.java b/altoslib/AltosMag.java index 45f1924c..0f8399ab 100644 --- a/altoslib/AltosMag.java +++ b/altoslib/AltosMag.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altoslib; +package org.altusmetrum.AltosLib; public class AltosMag { public int x; diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index 253e2f9b..a7b902e2 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package altoslib; +package org.altusmetrum.AltosLib; public class AltosMs5607 { public int reserved; diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index e4915af0..10ef3061 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -82,7 +82,6 @@ public class AltosRecord implements Comparable { public AltosRecordCompanion companion; ->>>>>>> 5a249bc... altosui: Complete split out of separate java library /* * Values for our MP3H6115A pressure sensor * diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 0645e448..68c7611f 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -70,6 +70,8 @@ public class AltosState { public double gps_height; + public double pad_lat, pad_lon, pad_alt; + public int speak_tick; public double speak_altitude; diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 67ac1b65..112e008e 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -59,19 +59,19 @@ public class AltosTelemetryReader extends AltosFlightReader { try { /* Version 1.0 or later firmware supports all telemetry formats */ - if (serial.config_data().compare_version("1.0") >= 0) + if (link.config_data().compare_version("1.0") >= 0) return true; /* Version 0.9 firmware only supports 0.9 telemetry */ - if (serial.config_data().compare_version("0.9") >= 0) { - if (telemetry == Altos.ao_telemetry_0_9) + if (link.config_data().compare_version("0.9") >= 0) { + if (telemetry == AltosLib.ao_telemetry_0_9) return true; else return false; } /* Version 0.8 firmware only supports 0.8 telemetry */ - if (telemetry == Altos.ao_telemetry_0_8) + if (telemetry == AltosLib.ao_telemetry_0_8) return true; else return false; diff --git a/altoslib/AltosTelemetryRecord.java b/altoslib/AltosTelemetryRecord.java index 367c148d..4292dae8 100644 --- a/altoslib/AltosTelemetryRecord.java +++ b/altoslib/AltosTelemetryRecord.java @@ -16,6 +16,7 @@ */ package org.altusmetrum.AltosLib; +import java.text.*; public abstract class AltosTelemetryRecord { @@ -47,7 +48,7 @@ public abstract class AltosTelemetryRecord { int[] bytes; try { - bytes = Altos.hexbytes(hex); + bytes = AltosLib.hexbytes(hex); } catch (NumberFormatException ne) { throw new ParseException(ne.getMessage(), 0); } @@ -60,16 +61,16 @@ public abstract class AltosTelemetryRecord { if (!cksum(bytes)) throw new ParseException(String.format("invalid line \"%s\"", hex), 0); - int rssi = Altos.int8(bytes, bytes.length - 3) / 2 - 74; - int status = Altos.uint8(bytes, bytes.length - 2); + int rssi = AltosLib.int8(bytes, bytes.length - 3) / 2 - 74; + int status = AltosLib.uint8(bytes, bytes.length - 2); if ((status & PKT_APPEND_STATUS_1_CRC_OK) == 0) throw new AltosCRCException(rssi); /* length, data ..., rssi, status, checksum -- 4 bytes extra */ switch (bytes.length) { - case Altos.ao_telemetry_standard_len + 4: - int type = Altos.uint8(bytes, 4 + 1); + case AltosLib.ao_telemetry_standard_len + 4: + int type = AltosLib.uint8(bytes, 4 + 1); switch (type) { case packet_type_TM_sensor: case packet_type_Tm_sensor: @@ -93,10 +94,10 @@ public abstract class AltosTelemetryRecord { break; } break; - case Altos.ao_telemetry_0_9_len + 4: + case AltosLib.ao_telemetry_0_9_len + 4: r = new AltosTelemetryRecordLegacy(bytes, rssi, status); break; - case Altos.ao_telemetry_0_8_len + 4: + case AltosLib.ao_telemetry_0_8_len + 4: r = new AltosTelemetryRecordLegacy(bytes, rssi, status); break; default: diff --git a/altoslib/AltosTelemetryRecordLegacy.java b/altoslib/AltosTelemetryRecordLegacy.java index 8e3713cc..85071d9c 100644 --- a/altoslib/AltosTelemetryRecordLegacy.java +++ b/altoslib/AltosTelemetryRecordLegacy.java @@ -241,7 +241,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.serial = map.get_int(AO_TELEM_SERIAL, AltosRecord.MISSING); record.flight = map.get_int(AO_TELEM_FLIGHT, AltosRecord.MISSING); record.rssi = map.get_int(AO_TELEM_RSSI, AltosRecord.MISSING); - record.state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + record.state = AltosLib.state(map.get_string(AO_TELEM_STATE, "invalid")); record.tick = map.get_int(AO_TELEM_TICK, 0); /* raw sensor values */ @@ -300,7 +300,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { record.status = AltosParse.parse_hex(words[i++]); AltosParse.word(words[i++], "STATE"); - record.state = Altos.state(words[i++]); + record.state = AltosLib.state(words[i++]); record.tick = AltosParse.parse_int(words[i++]); diff --git a/altosui/Altos.java b/altosui/Altos.java index 380796cc..334ddb07 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -28,73 +28,6 @@ import org.altusmetrum.AltosLib.*; public class Altos extends AltosLib { - /* Added for header fields in eeprom files */ - static final int AO_LOG_CONFIG_VERSION = 1000; - static final int AO_LOG_MAIN_DEPLOY = 1001; - static final int AO_LOG_APOGEE_DELAY = 1002; - static final int AO_LOG_RADIO_CHANNEL = 1003; - static final int AO_LOG_CALLSIGN = 1004; - static final int AO_LOG_ACCEL_CAL = 1005; - static final int AO_LOG_RADIO_CAL = 1006; - static final int AO_LOG_MAX_FLIGHT_LOG = 1007; - static final int AO_LOG_MANUFACTURER = 2000; - static final int AO_LOG_PRODUCT = 2001; - static final int AO_LOG_SERIAL_NUMBER = 2002; - static final int AO_LOG_LOG_FORMAT = 2003; - - /* Added for header fields in megametrum files */ - static final int AO_LOG_BARO_RESERVED = 3000; - static final int AO_LOG_BARO_SENS = 3001; - static final int AO_LOG_BARO_OFF = 3002; - static final int AO_LOG_BARO_TCS = 3004; - static final int AO_LOG_BARO_TCO = 3005; - static final int AO_LOG_BARO_TREF = 3006; - static final int AO_LOG_BARO_TEMPSENS = 3007; - static final int AO_LOG_BARO_CRC = 3008; - - static final int AO_LOG_SOFTWARE_VERSION = 9999; - - /* Added to flag invalid records */ - static final int AO_LOG_INVALID = -1; - - /* Flight state numbers and names */ - static final int ao_flight_startup = 0; - static final int ao_flight_idle = 1; - static final int ao_flight_pad = 2; - static final int ao_flight_boost = 3; - static final int ao_flight_fast = 4; - static final int ao_flight_coast = 5; - static final int ao_flight_drogue = 6; - static final int ao_flight_main = 7; - static final int ao_flight_landed = 8; - static final int ao_flight_invalid = 9; - - /* Telemetry modes */ - static final int ao_telemetry_off = 0; - static final int ao_telemetry_min = 1; - static final int ao_telemetry_standard = 1; - static final int ao_telemetry_0_9 = 2; - static final int ao_telemetry_0_8 = 3; - static final int ao_telemetry_max = 3; - - static final String[] ao_telemetry_name = { - "Off", "Standard Telemetry", "TeleMetrum v0.9", "TeleMetrum v0.8" - }; - - static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt"; - - static final int ao_telemetry_standard_len = 32; - static final int ao_telemetry_0_9_len = 95; - static final int ao_telemetry_0_8_len = 94; - - static final int[] ao_telemetry_len = { - 0, 32, 95, 94 - }; - - static HashMap string_to_state = new HashMap(); - - static boolean map_initialized = false; - static final int tab_elt_pad = 5; static Font label_font; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 54cdcba7..3abdb645 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -264,7 +264,6 @@ public class AltosSerial extends AltosLink implements Runnable { flush_output(); } -<<<<<<< HEAD private int telemetry_len() { return Altos.telemetry_len(telemetry); } @@ -386,8 +385,6 @@ public class AltosSerial extends AltosLink implements Runnable { remote = false; } -======= ->>>>>>> bc5e669... altosui: Pull most of AltosSerial into AltosLink public void set_frame(Frame in_frame) { frame = in_frame; } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 0a6ae59e..9fc7b5b3 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -27,8 +27,6 @@ altosui_JAVA = \ AltosConfigureUI.java \ AltosConfigTD.java \ AltosConfigTDUI.java \ - AltosConvert.java \ - AltosCRCException.java \ AltosCSV.java \ AltosCSVUI.java \ AltosDebug.java \ @@ -42,7 +40,6 @@ altosui_JAVA = \ AltosEepromList.java \ AltosEepromManage.java \ AltosEepromMonitor.java \ - AltosEepromTeleScience.java \ AltosEepromMega.java \ AltosEepromMegaIterable.java \ AltosEepromSelect.java \ -- cgit v1.2.3 From 7a19d6790a9800f925c8de24aac71796351e2c04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 19:28:58 -0700 Subject: altos: More cleanups for moving files to altoslib Signed-off-by: Keith Packard --- altoslib/AltosEepromMega.java | 213 ++++++++++++++ altoslib/AltosEepromMegaIterable.java | 518 +++++++++++++++++++++++++++++++++ altoslib/AltosLink.java | 25 ++ altoslib/Makefile.am | 2 + altosui/Altos.java | 56 ---- altosui/AltosConfigTD.java | 2 + altosui/AltosConfigTDUI.java | 2 + altosui/AltosEepromMega.java | 218 -------------- altosui/AltosEepromMegaIterable.java | 523 ---------------------------------- altosui/AltosFlightStatusUpdate.java | 1 + altosui/AltosSerial.java | 68 ----- altosui/Makefile.am | 2 - 12 files changed, 763 insertions(+), 867 deletions(-) create mode 100644 altoslib/AltosEepromMega.java create mode 100644 altoslib/AltosEepromMegaIterable.java delete mode 100644 altosui/AltosEepromMega.java delete mode 100644 altosui/AltosEepromMegaIterable.java diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java new file mode 100644 index 00000000..2628279e --- /dev/null +++ b/altoslib/AltosEepromMega.java @@ -0,0 +1,213 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public class AltosEepromMega { + public int cmd; + public int tick; + public boolean valid; + public String data; + public int a, b; + + public int data8[]; + + public static final int record_length = 32; + static final int header_length = 4; + static final int data_length = record_length - header_length; + + public int data8(int i) { + return data8[i]; + } + + public int data16(int i) { + return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; + } + + public int data32(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); + } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int ground_accel() { return data16(2); } + public int ground_pres() { return data32(4); } + public int ground_temp() { return data32(8); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data32(0); } + public int temp() { return data32(4); } + public int accel_x() { return data16(8); } + public int accel_y() { return data16(10); } + public int accel_z() { return data16(12); } + public int gyro_x() { return data16(14); } + public int gyro_y() { return data16(16); } + public int gyro_z() { return data16(18); } + public int mag_x() { return data16(20); } + public int mag_y() { return data16(22); } + public int mag_z() { return data16(24); } + public int accel() { + int a = data16(26); + if (a != 0xffff) + return a; + return accel_y(); + } + + /* AO_LOG_VOLT elements */ + public int v_batt() { return data16(0); } + public int v_pbatt() { return data16(2); } + public int nsense() { return data16(4); } + public int sense(int i) { return data16(6 + i * 2); } + + public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException { + cmd = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + cmd = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = chunk.data(start + header_length + i); + } + + public AltosEepromMega (String line) { + valid = false; + tick = 0; + + if (line == null) { + cmd = AltosLib.AO_LOG_INVALID; + line = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + if (tokens[0].length() == 1) { + if (tokens.length != 2 + data_length) { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } else { + cmd = tokens[0].codePointAt(0); + tick = Integer.parseInt(tokens[1],16); + valid = true; + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = Integer.parseInt(tokens[2 + i],16); + } + } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) { + cmd = AltosLib.AO_LOG_CONFIG_VERSION; + data = tokens[2]; + } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { + cmd = AltosLib.AO_LOG_MAIN_DEPLOY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { + cmd = AltosLib.AO_LOG_APOGEE_DELAY; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { + cmd = AltosLib.AO_LOG_RADIO_CHANNEL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Callsign:")) { + cmd = AltosLib.AO_LOG_CALLSIGN; + data = tokens[1].replaceAll("\"",""); + } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { + cmd = AltosLib.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 = AltosLib.AO_LOG_RADIO_CAL; + a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; + a = Integer.parseInt(tokens[3]); + } else if (tokens[0].equals("manufacturer")) { + cmd = AltosLib.AO_LOG_MANUFACTURER; + data = tokens[1]; + } else if (tokens[0].equals("product")) { + cmd = AltosLib.AO_LOG_PRODUCT; + data = tokens[1]; + } else if (tokens[0].equals("serial-number")) { + cmd = AltosLib.AO_LOG_SERIAL_NUMBER; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = AltosLib.AO_LOG_LOG_FORMAT; + a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("software-version")) { + cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; + data = tokens[1]; + } else if (tokens[0].equals("ms5607")) { + if (tokens[1].equals("reserved:")) { + cmd = AltosLib.AO_LOG_BARO_RESERVED; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("sens:")) { + cmd = AltosLib.AO_LOG_BARO_SENS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("off:")) { + cmd = AltosLib.AO_LOG_BARO_OFF; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tcs:")) { + cmd = AltosLib.AO_LOG_BARO_TCS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tco:")) { + cmd = AltosLib.AO_LOG_BARO_TCO; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tref:")) { + cmd = AltosLib.AO_LOG_BARO_TREF; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tempsens:")) { + cmd = AltosLib.AO_LOG_BARO_TEMPSENS; + a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("crc:")) { + cmd = AltosLib.AO_LOG_BARO_CRC; + a = Integer.parseInt(tokens[2]); + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } catch (NumberFormatException ne) { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } + } + + public AltosEepromMega(int in_cmd, int in_tick) { + cmd = in_cmd; + tick = in_tick; + valid = true; + } +} diff --git a/altoslib/AltosEepromMegaIterable.java b/altoslib/AltosEepromMegaIterable.java new file mode 100644 index 00000000..28a298b3 --- /dev/null +++ b/altoslib/AltosEepromMegaIterable.java @@ -0,0 +1,518 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.LinkedBlockingQueue; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable { + + public int index; + + public AltosOrderedMegaRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + index = in_index; + } + + public AltosOrderedMegaRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) { + super(in_cmd, in_tick); + a = in_a; + b = in_b; + index = in_index; + } + + public String toString() { + return String.format("%d.%d %04x %04x %04x", + cmd, index, tick, a, b); + } + + public int compareTo(AltosOrderedMegaRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} + +public class AltosEepromMegaIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + static final int seen_temp_volt = 4; + static final int seen_deploy = 8; + static final int seen_gps_time = 16; + static final int seen_gps_lat = 32; + static final int seen_gps_lon = 64; + + static final int seen_basic = seen_flight|seen_sensor; + + boolean has_accel; + boolean has_gps; + boolean has_ignite; + + AltosEepromMega flight_record; + AltosEepromMega gps_date_record; + + TreeSet records; + + AltosMs5607 baro; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int gps_tick; + int boost_tick; + int sensor_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + gps_tick = 0; + } + } + + void update_state(AltosRecord state, AltosEepromMega record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case AltosLib.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_accel = record.ground_accel(); + state.flight_accel = record.ground_accel(); + state.ground_pres = baro.set(record.ground_pres(), record.ground_temp()); + state.flight_pres = state.ground_pres; + state.flight = record.data16(0); + eeprom.boost_tick = record.tick; + break; + case AltosLib.AO_LOG_SENSOR: + state.accel = record.accel(); + state.pres = baro.set(record.pres(), record.temp()); + state.temp = baro.cc; + state.imu = new AltosIMU(); + state.imu.accel_x = record.accel_x(); + state.imu.accel_y = record.accel_y(); + state.imu.accel_z = record.accel_z(); + state.imu.gyro_x = record.gyro_x(); + state.imu.gyro_y = record.gyro_y(); + state.imu.gyro_z = record.gyro_z(); + state.mag = new AltosMag(); + state.mag.x = record.mag_x(); + state.mag.y = record.mag_y(); + state.mag.z = record.mag_z(); + if (state.state < AltosLib.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + } + state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); + eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; + has_accel = true; + break; + case AltosLib.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } + eeprom.seen |= seen_sensor; + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.batt = record.v_batt(); + eeprom.seen |= seen_temp_volt; + break; + case AltosLib.AO_LOG_DEPLOY: + state.drogue = record.a; + state.main = record.b; + eeprom.seen |= seen_deploy; + has_ignite = true; + break; + case AltosLib.AO_LOG_STATE: + state.state = record.state(); + break; + case AltosLib.AO_LOG_GPS_TIME: + eeprom.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); + + int flags = (record.b >> 8); + state.gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + state.gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + state.gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + state.new_gps = true; + has_gps = true; + break; + case AltosLib.AO_LOG_GPS_LAT: + int lat32 = record.a | (record.b << 16); + state.gps.lat = (double) lat32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_LON: + int lon32 = record.a | (record.b << 16); + state.gps.lon = (double) lon32 / 1e7; + break; + case AltosLib.AO_LOG_GPS_ALT: + state.gps.alt = record.a; + break; + case AltosLib.AO_LOG_GPS_SAT: + if (state.tick == eeprom.gps_tick) { + int svid = record.a; + int c_n0 = record.b >> 8; + state.gps.add_sat(svid, c_n0); + } + break; + case AltosLib.AO_LOG_GPS_DATE: + state.gps.year = (record.a & 0xff) + 2000; + state.gps.month = record.a >> 8; + state.gps.day = record.b & 0xff; + break; + + case AltosLib.AO_LOG_CONFIG_VERSION: + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + break; + case AltosLib.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case AltosLib.AO_LOG_ACCEL_CAL: + state.accel_plus_g = record.a; + state.accel_minus_g = record.b; + break; + case AltosLib.AO_LOG_RADIO_CAL: + break; + case AltosLib.AO_LOG_MANUFACTURER: + break; + case AltosLib.AO_LOG_PRODUCT: + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + state.serial = record.a; + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + break; + case AltosLib.AO_LOG_BARO_RESERVED: + baro.reserved = record.a; + break; + case AltosLib.AO_LOG_BARO_SENS: + baro.sens =record.a; + break; + case AltosLib.AO_LOG_BARO_OFF: + baro.off =record.a; + break; + case AltosLib.AO_LOG_BARO_TCS: + baro.tcs =record.a; + break; + case AltosLib.AO_LOG_BARO_TCO: + baro.tco =record.a; + break; + case AltosLib.AO_LOG_BARO_TREF: + baro.tref =record.a; + break; + case AltosLib.AO_LOG_BARO_TEMPSENS: + baro.tempsens =record.a; + break; + case AltosLib.AO_LOG_BARO_CRC: + baro.crc =record.a; + break; + } + state.seen |= eeprom.seen; + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedMegaRecord record = null; + AltosRecord state = new AltosRecord(); + boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = AltosLib.ao_flight_pad; + state.accel_plus_g = 15758; + state.accel_minus_g = 16294; + + /* Pull in static data from the flight and gps_date records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + if (gps_date_record != null) + update_state(state, gps_date_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecord r = new AltosRecord(state); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedMegaRecord record = iterator.next(); + switch (record.cmd) { + case AltosLib.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.a); + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.a); + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.a); + break; + case AltosLib.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case AltosLib.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.a, record.b); + break; + case AltosLib.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.a); + break; + case AltosLib.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.a); + break; + case AltosLib.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case AltosLib.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.a); + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + case AltosLib.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.a); + break; + case AltosLib.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.a); + break; + } + } + } + + /* + * 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(AltosOrderedMegaRecord good, AltosOrderedMegaRecord 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; + + /* Make sure this looks like a good GPS value */ + if ((flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> AltosLib.AO_GPS_NUM_SAT_SHIFT < 4) + flags = (flags & ~AltosLib.AO_GPS_NUM_SAT_MASK) | (4 << AltosLib.AO_GPS_NUM_SAT_SHIFT); + flags |= AltosLib.AO_GPS_RUNNING; + flags |= AltosLib.AO_GPS_VALID; + + 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 + * are sometimes out of order with GPS data getting timestamps + * matching the first packet out of the GPS unit but not + * written until the final GPS packet has been received. + */ + public AltosEepromMegaIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedMegaRecord last_gps_time = null; + + baro = new AltosMs5607(); + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosRecord.gets(input); + if (line == null) + break; + AltosOrderedMegaRecord record = new AltosOrderedMegaRecord(line, index++, prev_tick, prev_tick_valid); + if (record == null) + break; + if (record.cmd == AltosLib.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == AltosLib.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + /* 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 == AltosLib.AO_LOG_GPS_DATE) { + gps_date_record = record; + continue; + } + + /* go back and fix up any missing time values */ + if (record.cmd == AltosLib.AO_LOG_GPS_TIME) { + last_gps_time = record; + if (missing_time) { + Iterator iterator = records.iterator(); + while (iterator.hasNext()) { + AltosOrderedMegaRecord old = iterator.next(); + if (old.cmd == AltosLib.AO_LOG_GPS_TIME && + old.a == -1 && old.b == -1) + { + update_time(record, old); + } + } + missing_time = false; + } + } + + if (record.cmd == AltosLib.AO_LOG_GPS_LAT) { + if (last_gps_time == null || last_gps_time.tick != record.tick) { + AltosOrderedMegaRecord add_gps_time = new AltosOrderedMegaRecord(AltosLib.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); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == AltosLib.AO_LOG_STATE && + record.a == AltosLib.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 9b80e916..77b400fc 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -141,6 +141,31 @@ public abstract class AltosLink { return AltosLib.telemetry_len(telemetry); } + private void set_radio_freq(int frequency) { + if (monitor_mode) + printf("m 0\nc F %d\nm %x\n", + frequency, telemetry_len()); + else + printf("c F %d\n", frequency); + flush_output(); + } + + public void set_radio_frequency(double frequency, + boolean has_frequency, + boolean has_setting, + int cal) { + if (debug) + System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal); + if (frequency == 0) + return; + if (has_frequency) + set_radio_freq((int) Math.floor (frequency * 1000)); + else if (has_setting) + set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); + else + set_channel(AltosConvert.radio_frequency_to_channel(frequency)); + } + public void set_telemetry(int in_telemetry) { telemetry = in_telemetry; if (monitor_mode) diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 2e4a795a..f644d46a 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -17,6 +17,8 @@ AltosLib_JAVA = \ $(SRC)/AltosEepromChunk.java \ $(SRC)/AltosEepromIterable.java \ $(SRC)/AltosEepromLog.java \ + $(SRC)/AltosEepromMega.java \ + $(SRC)/AltosEepromMegaIterable.java \ $(SRC)/AltosEepromRecord.java \ $(SRC)/AltosEepromTeleScience.java \ $(SRC)/AltosFile.java \ diff --git a/altosui/Altos.java b/altosui/Altos.java index 334ddb07..351927ee 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -72,62 +72,6 @@ public class Altos extends AltosLib { static final int text_width = 20; - static void initialize_map() - { - string_to_state.put("startup", ao_flight_startup); - string_to_state.put("idle", ao_flight_idle); - string_to_state.put("pad", ao_flight_pad); - string_to_state.put("boost", ao_flight_boost); - string_to_state.put("fast", ao_flight_fast); - string_to_state.put("coast", ao_flight_coast); - string_to_state.put("drogue", ao_flight_drogue); - string_to_state.put("apogee", ao_flight_coast); - string_to_state.put("main", ao_flight_main); - string_to_state.put("landed", ao_flight_landed); - string_to_state.put("invalid", ao_flight_invalid); - map_initialized = true; - } - - static int telemetry_len(int telemetry) { - if (telemetry <= ao_telemetry_max) - return ao_telemetry_len[telemetry]; - throw new IllegalArgumentException(String.format("Invalid telemetry %d", - telemetry)); - } - - static String telemetry_name(int telemetry) { - if (telemetry <= ao_telemetry_max) - return ao_telemetry_name[telemetry]; - throw new IllegalArgumentException(String.format("Invalid telemetry %d", - telemetry)); - } - - static String[] state_to_string = { - "startup", - "idle", - "pad", - "boost", - "fast", - "coast", - "drogue", - "main", - "landed", - "invalid", - }; - - static String[] state_to_string_capital = { - "Startup", - "Idle", - "Pad", - "Boost", - "Fast", - "Coast", - "Drogue", - "Main", - "Landed", - "Invalid", - }; - static public int state(String state) { if (!map_initialized) initialize_map(); diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index d3c452e1..4048166c 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -30,6 +30,8 @@ import java.util.concurrent.*; import libaltosJNI.*; +import org.altusmetrum.AltosLib.*; + public class AltosConfigTD implements ActionListener { class int_ref { diff --git a/altosui/AltosConfigTDUI.java b/altosui/AltosConfigTDUI.java index 9f6badc7..f2058f69 100644 --- a/altosui/AltosConfigTDUI.java +++ b/altosui/AltosConfigTDUI.java @@ -31,6 +31,8 @@ import java.util.concurrent.LinkedBlockingQueue; import libaltosJNI.*; +import org.altusmetrum.AltosLib.*; + public class AltosConfigTDUI extends AltosDialog implements ActionListener, ItemListener, DocumentListener diff --git a/altosui/AltosEepromMega.java b/altosui/AltosEepromMega.java deleted file mode 100644 index 8ae485cb..00000000 --- a/altosui/AltosEepromMega.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.*; - -public class AltosEepromMega { - public int cmd; - public int tick; - public boolean valid; - public String data; - int a, b; - - public int data8[]; - - static final int record_length = 32; - static final int header_length = 4; - static final int data_length = record_length - header_length; - - public int data8(int i) { - return data8[i]; - } - - public int data16(int i) { - return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; - } - - public int data32(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); - } - - /* AO_LOG_FLIGHT elements */ - public int flight() { return data16(0); } - public int ground_accel() { return data16(2); } - public int ground_pres() { return data32(4); } - public int ground_temp() { return data32(8); } - - /* AO_LOG_STATE elements */ - public int state() { return data16(0); } - public int reason() { return data16(2); } - - /* AO_LOG_SENSOR elements */ - public int pres() { return data32(0); } - public int temp() { return data32(4); } - public int accel_x() { return data16(8); } - public int accel_y() { return data16(10); } - public int accel_z() { return data16(12); } - public int gyro_x() { return data16(14); } - public int gyro_y() { return data16(16); } - public int gyro_z() { return data16(18); } - public int mag_x() { return data16(20); } - public int mag_y() { return data16(22); } - public int mag_z() { return data16(24); } - public int accel() { - int a = data16(26); - if (a != 0xffff) - return a; - return accel_y(); - } - - /* AO_LOG_VOLT elements */ - public int v_batt() { return data16(0); } - public int v_pbatt() { return data16(2); } - public int nsense() { return data16(4); } - public int sense(int i) { return data16(6 + i * 2); } - - public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException { - cmd = chunk.data(start); - - valid = !chunk.erased(start, record_length); - if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - cmd = Altos.AO_LOG_INVALID; - } - - tick = chunk.data16(start+2); - - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = chunk.data(start + header_length + i); - } - - public AltosEepromMega (String line) { - valid = false; - tick = 0; - - if (line == null) { - cmd = Altos.AO_LOG_INVALID; - line = ""; - } else { - try { - String[] tokens = line.split("\\s+"); - - if (tokens[0].length() == 1) { - if (tokens.length != 2 + data_length) { - cmd = Altos.AO_LOG_INVALID; - data = line; - } else { - cmd = tokens[0].codePointAt(0); - tick = Integer.parseInt(tokens[1],16); - valid = true; - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = Integer.parseInt(tokens[2 + i],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("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { - cmd = Altos.AO_LOG_MAX_FLIGHT_LOG; - a = Integer.parseInt(tokens[3]); - } 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("log-format")) { - cmd = Altos.AO_LOG_LOG_FORMAT; - 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].equals("ms5607")) { - if (tokens[1].equals("reserved:")) { - cmd = Altos.AO_LOG_BARO_RESERVED; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("sens:")) { - cmd = Altos.AO_LOG_BARO_SENS; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("off:")) { - cmd = Altos.AO_LOG_BARO_OFF; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tcs:")) { - cmd = Altos.AO_LOG_BARO_TCS; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tco:")) { - cmd = Altos.AO_LOG_BARO_TCO; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tref:")) { - cmd = Altos.AO_LOG_BARO_TREF; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tempsens:")) { - cmd = Altos.AO_LOG_BARO_TEMPSENS; - a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("crc:")) { - cmd = Altos.AO_LOG_BARO_CRC; - a = Integer.parseInt(tokens[2]); - } else { - cmd = Altos.AO_LOG_INVALID; - data = line; - } - } else { - cmd = Altos.AO_LOG_INVALID; - data = line; - } - } catch (NumberFormatException ne) { - cmd = Altos.AO_LOG_INVALID; - data = line; - } - } - } - - public AltosEepromMega(int in_cmd, int in_tick) { - cmd = in_cmd; - tick = in_tick; - valid = true; - } -} diff --git a/altosui/AltosEepromMegaIterable.java b/altosui/AltosEepromMegaIterable.java deleted file mode 100644 index e2cd2785..00000000 --- a/altosui/AltosEepromMegaIterable.java +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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; - -/* - * AltosRecords with an index field so they can be sorted by tick while preserving - * the original ordering for elements with matching ticks - */ -class AltosOrderedMegaRecord extends AltosEepromMega implements Comparable { - - public int index; - - public AltosOrderedMegaRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) - throws ParseException { - super(line); - if (prev_tick_valid) { - tick |= (prev_tick & ~0xffff); - if (tick < prev_tick) { - if (prev_tick - tick > 0x8000) - tick += 0x10000; - } else { - if (tick - prev_tick > 0x8000) - tick -= 0x10000; - } - } - index = in_index; - } - - public AltosOrderedMegaRecord(int in_cmd, int in_tick, int in_a, int in_b, int in_index) { - super(in_cmd, in_tick); - a = in_a; - b = in_b; - index = in_index; - } - - public String toString() { - return String.format("%d.%d %04x %04x %04x", - cmd, index, tick, a, b); - } - - public int compareTo(AltosOrderedMegaRecord o) { - int tick_diff = tick - o.tick; - if (tick_diff != 0) - return tick_diff; - return index - o.index; - } -} - -public class AltosEepromMegaIterable extends AltosRecordIterable { - - static final int seen_flight = 1; - static final int seen_sensor = 2; - static final int seen_temp_volt = 4; - static final int seen_deploy = 8; - static final int seen_gps_time = 16; - static final int seen_gps_lat = 32; - static final int seen_gps_lon = 64; - - static final int seen_basic = seen_flight|seen_sensor; - - boolean has_accel; - boolean has_gps; - boolean has_ignite; - - AltosEepromMega flight_record; - AltosEepromMega gps_date_record; - - TreeSet records; - - AltosMs5607 baro; - - LinkedList list; - - class EepromState { - int seen; - int n_pad_samples; - double ground_pres; - int gps_tick; - int boost_tick; - int sensor_tick; - - EepromState() { - seen = 0; - n_pad_samples = 0; - ground_pres = 0.0; - gps_tick = 0; - } - } - - void update_state(AltosRecord state, AltosEepromMega record, EepromState eeprom) { - state.tick = record.tick; - switch (record.cmd) { - case Altos.AO_LOG_FLIGHT: - eeprom.seen |= seen_flight; - state.ground_accel = record.ground_accel(); - state.flight_accel = record.ground_accel(); - state.ground_pres = baro.set(record.ground_pres(), record.ground_temp()); - state.flight_pres = state.ground_pres; - state.flight = record.data16(0); - eeprom.boost_tick = record.tick; - break; - case Altos.AO_LOG_SENSOR: - state.accel = record.accel(); - state.pres = baro.set(record.pres(), record.temp()); - state.temp = baro.cc; - state.imu = new AltosIMU(); - state.imu.accel_x = record.accel_x(); - state.imu.accel_y = record.accel_y(); - state.imu.accel_z = record.accel_z(); - state.imu.gyro_x = record.gyro_x(); - state.imu.gyro_y = record.gyro_y(); - state.imu.gyro_z = record.gyro_z(); - state.mag = new AltosMag(); - state.mag.x = record.mag_x(); - state.mag.y = record.mag_y(); - state.mag.z = record.mag_z(); - if (state.state < Altos.ao_flight_boost) { - eeprom.n_pad_samples++; - eeprom.ground_pres += state.pres; - state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); - state.flight_pres = state.ground_pres; - } else { - state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; - } - state.flight_accel = (state.flight_accel * 15 + state.accel) / 16; - if ((eeprom.seen & seen_sensor) == 0) - eeprom.sensor_tick = record.tick - 1; - state.flight_vel += (state.accel_plus_g - state.accel) * (record.tick - eeprom.sensor_tick); - eeprom.seen |= seen_sensor; - eeprom.sensor_tick = record.tick; - has_accel = true; - break; - case Altos.AO_LOG_PRESSURE: - state.pres = record.b; - state.flight_pres = state.pres; - if (eeprom.n_pad_samples == 0) { - eeprom.n_pad_samples++; - state.ground_pres = state.pres; - } - eeprom.seen |= seen_sensor; - break; - case Altos.AO_LOG_TEMP_VOLT: - state.batt = record.v_batt(); - eeprom.seen |= seen_temp_volt; - break; - case Altos.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - eeprom.seen |= seen_deploy; - has_ignite = true; - break; - case Altos.AO_LOG_STATE: - state.state = record.state(); - break; - case Altos.AO_LOG_GPS_TIME: - eeprom.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); - - int flags = (record.b >> 8); - state.gps.connected = (flags & Altos.AO_GPS_RUNNING) != 0; - state.gps.locked = (flags & Altos.AO_GPS_VALID) != 0; - state.gps.nsat = (flags & Altos.AO_GPS_NUM_SAT_MASK) >> - Altos.AO_GPS_NUM_SAT_SHIFT; - state.new_gps = true; - has_gps = true; - break; - case Altos.AO_LOG_GPS_LAT: - int lat32 = record.a | (record.b << 16); - state.gps.lat = (double) lat32 / 1e7; - break; - case Altos.AO_LOG_GPS_LON: - int lon32 = record.a | (record.b << 16); - state.gps.lon = (double) lon32 / 1e7; - break; - case Altos.AO_LOG_GPS_ALT: - state.gps.alt = record.a; - break; - case Altos.AO_LOG_GPS_SAT: - if (state.tick == eeprom.gps_tick) { - int svid = record.a; - int c_n0 = record.b >> 8; - state.gps.add_sat(svid, c_n0); - } - break; - case Altos.AO_LOG_GPS_DATE: - state.gps.year = (record.a & 0xff) + 2000; - state.gps.month = record.a >> 8; - state.gps.day = record.b & 0xff; - break; - - case Altos.AO_LOG_CONFIG_VERSION: - break; - case Altos.AO_LOG_MAIN_DEPLOY: - break; - case Altos.AO_LOG_APOGEE_DELAY: - break; - case Altos.AO_LOG_RADIO_CHANNEL: - break; - case Altos.AO_LOG_CALLSIGN: - state.callsign = record.data; - break; - case Altos.AO_LOG_ACCEL_CAL: - state.accel_plus_g = record.a; - state.accel_minus_g = record.b; - break; - case Altos.AO_LOG_RADIO_CAL: - break; - case Altos.AO_LOG_MANUFACTURER: - 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; - case Altos.AO_LOG_BARO_RESERVED: - baro.reserved = record.a; - break; - case Altos.AO_LOG_BARO_SENS: - baro.sens =record.a; - break; - case Altos.AO_LOG_BARO_OFF: - baro.off =record.a; - break; - case Altos.AO_LOG_BARO_TCS: - baro.tcs =record.a; - break; - case Altos.AO_LOG_BARO_TCO: - baro.tco =record.a; - break; - case Altos.AO_LOG_BARO_TREF: - baro.tref =record.a; - break; - case Altos.AO_LOG_BARO_TEMPSENS: - baro.tempsens =record.a; - break; - case Altos.AO_LOG_BARO_CRC: - baro.crc =record.a; - break; - } - state.seen |= eeprom.seen; - } - - LinkedList make_list() { - LinkedList list = new LinkedList(); - Iterator iterator = records.iterator(); - AltosOrderedMegaRecord record = null; - AltosRecord state = new AltosRecord(); - boolean last_reported = false; - EepromState eeprom = new EepromState(); - - state.state = Altos.ao_flight_pad; - state.accel_plus_g = 15758; - state.accel_minus_g = 16294; - - /* Pull in static data from the flight and gps_date records */ - if (flight_record != null) - update_state(state, flight_record, eeprom); - if (gps_date_record != null) - update_state(state, gps_date_record, eeprom); - - while (iterator.hasNext()) { - record = iterator.next(); - if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - } - update_state(state, record, eeprom); - } - AltosRecord r = new AltosRecord(state); - r.time = (r.tick - eeprom.boost_tick) / 100.0; - list.add(r); - return list; - } - - public Iterator iterator() { - if (list == null) - list = make_list(); - return list.iterator(); - } - - public boolean has_gps() { return has_gps; } - public boolean has_accel() { return has_accel; } - public boolean has_ignite() { return has_ignite; } - - public void write_comments(PrintStream out) { - Iterator iterator = records.iterator(); - out.printf("# Comments\n"); - while (iterator.hasNext()) { - AltosOrderedMegaRecord record = iterator.next(); - switch (record.cmd) { - case Altos.AO_LOG_CONFIG_VERSION: - out.printf("# Config version: %s\n", record.data); - break; - case Altos.AO_LOG_MAIN_DEPLOY: - out.printf("# Main deploy: %s\n", record.a); - break; - case Altos.AO_LOG_APOGEE_DELAY: - out.printf("# Apogee delay: %s\n", record.a); - break; - case Altos.AO_LOG_RADIO_CHANNEL: - out.printf("# Radio channel: %s\n", record.a); - break; - case Altos.AO_LOG_CALLSIGN: - out.printf("# Callsign: %s\n", record.data); - break; - case Altos.AO_LOG_ACCEL_CAL: - out.printf ("# Accel cal: %d %d\n", record.a, record.b); - break; - case Altos.AO_LOG_RADIO_CAL: - out.printf ("# Radio cal: %d\n", record.a); - break; - case Altos.AO_LOG_MAX_FLIGHT_LOG: - out.printf ("# Max flight log: %d\n", record.a); - break; - case Altos.AO_LOG_MANUFACTURER: - out.printf ("# Manufacturer: %s\n", record.data); - break; - case Altos.AO_LOG_PRODUCT: - out.printf ("# Product: %s\n", record.data); - break; - case Altos.AO_LOG_SERIAL_NUMBER: - out.printf ("# Serial number: %d\n", record.a); - break; - case Altos.AO_LOG_SOFTWARE_VERSION: - out.printf ("# Software version: %s\n", record.data); - break; - case Altos.AO_LOG_BARO_RESERVED: - out.printf ("# Baro reserved: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_SENS: - out.printf ("# Baro sens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_OFF: - out.printf ("# Baro off: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCS: - out.printf ("# Baro tcs: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TCO: - out.printf ("# Baro tco: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TREF: - out.printf ("# Baro tref: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_TEMPSENS: - out.printf ("# Baro tempsens: %d\n", record.a); - break; - case Altos.AO_LOG_BARO_CRC: - out.printf ("# Baro crc: %d\n", record.a); - break; - } - } - } - - /* - * 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(AltosOrderedMegaRecord good, AltosOrderedMegaRecord 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; - - /* Make sure this looks like a good GPS value */ - if ((flags & Altos.AO_GPS_NUM_SAT_MASK) >> Altos.AO_GPS_NUM_SAT_SHIFT < 4) - flags = (flags & ~Altos.AO_GPS_NUM_SAT_MASK) | (4 << Altos.AO_GPS_NUM_SAT_SHIFT); - flags |= Altos.AO_GPS_RUNNING; - flags |= Altos.AO_GPS_VALID; - - 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 - * are sometimes out of order with GPS data getting timestamps - * matching the first packet out of the GPS unit but not - * written until the final GPS packet has been received. - */ - public AltosEepromMegaIterable (FileInputStream input) { - records = new TreeSet(); - - AltosOrderedMegaRecord last_gps_time = null; - - baro = new AltosMs5607(); - - int index = 0; - int prev_tick = 0; - boolean prev_tick_valid = false; - boolean missing_time = false; - - try { - for (;;) { - String line = AltosRecord.gets(input); - if (line == null) - break; - AltosOrderedMegaRecord record = new AltosOrderedMegaRecord(line, index++, prev_tick, prev_tick_valid); - if (record == null) - break; - if (record.cmd == Altos.AO_LOG_INVALID) - continue; - prev_tick = record.tick; - if (record.cmd < Altos.AO_LOG_CONFIG_VERSION) - prev_tick_valid = true; - if (record.cmd == Altos.AO_LOG_FLIGHT) { - flight_record = record; - continue; - } - - /* 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) { - gps_date_record = record; - continue; - } - - /* 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 iterator = records.iterator(); - while (iterator.hasNext()) { - AltosOrderedMegaRecord 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) { - AltosOrderedMegaRecord add_gps_time = new AltosOrderedMegaRecord(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); - - /* Bail after reading the 'landed' record; we're all done */ - if (record.cmd == Altos.AO_LOG_STATE && - record.a == Altos.ao_flight_landed) - break; - } - } catch (IOException io) { - } catch (ParseException pe) { - } - try { - input.close(); - } catch (IOException ie) { - } - } -} diff --git a/altosui/AltosFlightStatusUpdate.java b/altosui/AltosFlightStatusUpdate.java index a600bd02..d70fc7f8 100644 --- a/altosui/AltosFlightStatusUpdate.java +++ b/altosui/AltosFlightStatusUpdate.java @@ -27,6 +27,7 @@ import java.util.*; import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; +import org.altusmetrum.AltosLib.*; public class AltosFlightStatusUpdate implements ActionListener { diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 3abdb645..5768ba71 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -317,74 +317,6 @@ public class AltosSerial extends AltosLink implements Runnable { set_channel(AltosConvert.radio_frequency_to_channel(frequency)); } - public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - if (frequency == 0.0) - frequency = AltosPreferences.frequency(device.getSerial()); - config_data(); - set_radio_frequency(frequency, - config_data.radio_frequency != 0, - config_data.radio_setting != 0, - config_data.radio_calibration); - } - - public void set_telemetry(int in_telemetry) { - telemetry = in_telemetry; - if (altos != null) { - if (monitor_mode) - printf("m 0\nm %x\n", telemetry_len()); - flush_output(); - } - } - - void set_monitor(boolean monitor) { - monitor_mode = monitor; - if (altos != null) { - if (monitor) - printf("m %x\n", telemetry_len()); - else - printf("m 0\n"); - flush_output(); - } - } - - public void set_callsign(String callsign) { - if (altos != null) { - printf ("c c %s\n", callsign); - flush_output(); - } - } - - public AltosConfigData config_data() throws InterruptedException, TimeoutException { - if (config_data == null) - config_data = new AltosConfigData(this); - return config_data; - } - - public void start_remote() throws TimeoutException, InterruptedException { - if (debug) - System.out.printf("start remote %7.3f\n", frequency); - if (frequency == 0.0) - frequency = AltosUIPreferences.frequency(device.getSerial()); - set_radio_frequency(frequency); - set_callsign(AltosUIPreferences.callsign()); - printf("p\nE 0\n"); - flush_input(); - remote = true; - } - - public void stop_remote() throws InterruptedException { - if (debug) - System.out.printf("stop remote\n"); - try { - flush_input(); - } finally { - printf ("~\n"); - flush_output(); - } - remote = false; - } - public void set_frame(Frame in_frame) { frame = in_frame; } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 9fc7b5b3..feda00c7 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -40,8 +40,6 @@ altosui_JAVA = \ AltosEepromList.java \ AltosEepromManage.java \ AltosEepromMonitor.java \ - AltosEepromMega.java \ - AltosEepromMegaIterable.java \ AltosEepromSelect.java \ AltosFlash.java \ AltosFlashUI.java \ -- cgit v1.2.3 From 718a8affe1df98eacfd707b5c8c34f9456dcff14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:47:14 -0700 Subject: altos: Remove accel_ref from pre v1.1 TM firmware V1.0 needs RAM space for flash buffer, leaving too little room for this extra data. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 44116b81..cece09eb 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,7 +205,9 @@ struct ao_adc { int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ +#if HAS_ACCEL_REF int16_t accel_ref; /* acceleration reference */ +#endif }; #define AO_DATA_RING 32 -- cgit v1.2.3 From f1b14932149153a096961fff94191778f88581d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:49:15 -0700 Subject: altos: Remove unused AES code from teledongle and tidongle Leave this out as neither of these products need it. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 10 +++++----- src/product/Makefile.telebt | 4 ++-- src/product/Makefile.teledongle | 4 ++-- src/product/ao_teledongle.c | 2 -- src/product/ao_tidongle.c | 2 -- src/tidongle/Makefile | 2 -- 6 files changed, 9 insertions(+), 15 deletions(-) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 5eef0de4..0923e75d 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -150,7 +150,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEMINI_V_1_0) @@ -259,7 +259,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TIDONGLE) @@ -286,7 +286,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEBT_V_0_0) @@ -322,7 +322,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 0 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEBT_V_0_1) @@ -365,7 +365,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 0 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELELAUNCH_V_0_1) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index e53aa2c4..90525d63 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h \ $(TELEBT_INC) @@ -32,14 +34,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_string.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 27e7d24b..fbf14a04 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -18,6 +18,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h @@ -35,14 +37,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 49b80500..0c829e97 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,8 +35,6 @@ main(void) #if HAS_DBG ao_dbg_init(); #endif - ao_aes_init(); - ao_radio_cmac_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index a504a747..cba0b122 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -34,8 +34,6 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); - ao_aes_init(); - ao_radio_cmac_init(); ao_config_init(); /* Bring up the USB link */ P1DIR |= 1; diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 149b00c5..0bb2ce32 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -30,14 +30,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ -- cgit v1.2.3 From 06afa2c3e78ea5bc9f1eb4913ee35c0eab0ac1bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:50:10 -0700 Subject: altos: Legacy telemetry needs original ADC record The legacy telemetry packets included the raw ADC structure directly, so make sure that doesn't change further, allowing teledongle firmware to remain compatible with old TM firmware. Signed-off-by: Keith Packard --- src/core/ao.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/ao.h b/src/core/ao.h index da1fd67b..a4136a9b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -574,6 +574,16 @@ ao_gps_report_init(void); * ao_telemetry_orig.c */ +struct ao_adc_orig { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + struct ao_telemetry_orig { uint16_t serial; uint16_t flight; @@ -591,7 +601,7 @@ struct ao_telemetry_orig { int16_t ground_pres; int16_t accel_plus_g; int16_t accel_minus_g; - struct ao_adc adc; + struct ao_adc_orig adc; struct ao_gps_orig gps; char callsign[AO_MAX_CALLSIGN]; struct ao_gps_tracking_orig gps_tracking; -- cgit v1.2.3 From 1832e2f76c844e97a2bd11226b003fb2af8057db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:51:35 -0700 Subject: altos: fix test builds of non-accel flight code Remove references to accel variables when building baro-only flight test code. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index e812016e..2bc5c36a 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -359,9 +359,11 @@ static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } static void ao_flight_dump(void) { +#if HAS_ACCEL int16_t accel; accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif printf ("sample:\n"); printf (" tick %d\n", ao_sample_tick); @@ -378,7 +380,9 @@ ao_flight_dump(void) printf (" alt %d\n", ao_sample_alt); printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif printf ("kalman:\n"); -- cgit v1.2.3 From e687a9bafc696998b47fd0300fbc89dece09509c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:52:38 -0700 Subject: altos: Make 'v' command dump pressure sensor ROM values Avoids needing a new command Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fdc70007..40bb476c 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -251,6 +251,9 @@ version(void) printf("serial-number %u\n", ao_serial_number); #if HAS_LOG printf("log-format %u\n", ao_log_format); +#endif +#if HAS_MS5607 + ao_ms5607_info(); #endif printf("software-version %s\n", ao_version); } -- cgit v1.2.3 From dec5cbee22f13c47690b0c6bf7ca724ef132fe5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:53:06 -0700 Subject: altos: typo in ao_monitor prevented ground station from including code This created ground station software that couldn't actually receive and report telemetry packets. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 830464d8..4ca641b7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_telem.h" +#include "ao_flight.h" #if !HAS_MONITOR #error Must define HAS_MONITOR to 1 @@ -27,7 +28,7 @@ #endif #ifndef HAS_MONITOR_PUT -#define HAS_MONIOTOR_PUT 1 +#define HAS_MONITOR_PUT 1 #endif #ifndef AO_MONITOR_LED -- cgit v1.2.3 From a9ad342ae4c34626df4f2891da4c7f6d2c14d73e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:53:53 -0700 Subject: altos: Other half of the ms5607 prom reporting patch Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 16 ++++++++++------ src/drivers/ao_ms5607.h | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 7db7022f..0f0625d0 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -215,12 +215,9 @@ ao_ms5607(void) __xdata struct ao_task ao_ms5607_task; -static void -ao_ms5607_dump(void) +void +ao_ms5607_info(void) { - struct ao_ms5607_sample sample; - struct ao_ms5607_value value; - printf ("ms5607 reserved: %u\n", ms5607_prom.reserved); printf ("ms5607 sens: %u\n", ms5607_prom.sens); printf ("ms5607 off: %u\n", ms5607_prom.off); @@ -229,6 +226,13 @@ ao_ms5607_dump(void) printf ("ms5607 tref: %u\n", ms5607_prom.tref); printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens); printf ("ms5607 crc: %u\n", ms5607_prom.crc); +} + +static void +ao_ms5607_dump(void) +{ + struct ao_ms5607_sample sample; + struct ao_ms5607_value value; sample = ao_ms5607_current; ao_ms5607_convert(&sample, &value); @@ -238,7 +242,7 @@ ao_ms5607_dump(void) } __code struct ao_cmds ao_ms5607_cmds[] = { - { ao_ms5607_dump, "p\0Display MS5607 data" }, + { ao_ms5607_dump, "B\0Display MS5607 data" }, { 0, NULL }, }; diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 1384d3a2..fa3b1c5b 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -62,6 +62,9 @@ struct ao_ms5607_value { void ao_ms5607_init(void); +void +ao_ms5607_info(void); + void ao_ms5607_sample(struct ao_ms5607_sample *sample); -- cgit v1.2.3 From 705891be53e298ac6ced4ba02b87d2f6d1085b34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:54:36 -0700 Subject: altos: Make cc1111 products all depend on ao_arch.h and ao_arch_func.h Ensures that files get recompiled as needed Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 2 ++ src/product/Makefile.telemetrum | 2 ++ src/product/Makefile.telemini | 2 ++ src/product/Makefile.telenano | 2 ++ 4 files changed, 8 insertions(+) diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 688ac5f3..3753f3c9 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index b1111053..fba2c19a 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -18,6 +18,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ altitude.h \ ao_kalman.h \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 9506eb65..f0ab2b14 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 56db1c2c..a55bcf95 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h -- cgit v1.2.3 From 5634192a6036c6c7b47d224e2988e81bb71a4557 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:55:33 -0700 Subject: altosui: attempt to get ms5607 data into .mega files was misinformed The ms5607 'p' command also means 'go into packet mode', which nicely broke attempts to communicate with teledongle Signed-off-by: Keith Packard --- altoslib/AltosConfigData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index fa6a72b5..ecc2d0aa 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -132,7 +132,7 @@ public class AltosConfigData implements Iterable { } public AltosConfigData(AltosLink link) throws InterruptedException, TimeoutException { - link.printf("c s\np\nf\nl\nv\n"); + link.printf("c s\nf\nl\nv\n"); lines = new LinkedList(); radio_setting = 0; radio_frequency = 0; -- cgit v1.2.3 From b8c363d9411fd5e79e3f806894dbc12bcc106b88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:56:25 -0700 Subject: altosui: More changes to migrate code to altoslib Signed-off-by: Keith Packard --- altoslib/AltosLib.java | 1 + altosui/Altos.java | 184 --------------------------------------- altosui/AltosEepromDownload.java | 10 +-- 3 files changed, 6 insertions(+), 189 deletions(-) diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 27d72079..e74eaf99 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -185,6 +185,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TINY = 2; public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; + public static final int AO_LOG_FORMAT_MEGAMETRUM = 5; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altosui/Altos.java b/altosui/Altos.java index 351927ee..78e56970 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -86,190 +86,6 @@ public class Altos extends AltosLib { return state_to_string[state]; } - static final int AO_GPS_VALID = (1 << 4); - static final int AO_GPS_RUNNING = (1 << 5); - 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 final int AO_LOG_FORMAT_UNKNOWN = 0; - static final int AO_LOG_FORMAT_FULL = 1; - static final int AO_LOG_FORMAT_TINY = 2; - static final int AO_LOG_FORMAT_TELEMETRY = 3; - static final int AO_LOG_FORMAT_TELESCIENCE = 4; - static final int AO_LOG_FORMAT_MEGAMETRUM = 5; - static final int AO_LOG_FORMAT_NONE = 127; - - 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 int8(int[] bytes, int i) { - return (int) (byte) bytes[i]; - } - - static int uint8(int[] bytes, int i) { - return bytes[i]; - } - - static int int16(int[] bytes, int i) { - return (int) (short) (bytes[i] + (bytes[i+1] << 8)); - } - - static int uint16(int[] bytes, int i) { - return bytes[i] + (bytes[i+1] << 8); - } - - static int uint32(int[] bytes, int i) { - return bytes[i] + - (bytes[i+1] << 8) + - (bytes[i+2] << 16) + - (bytes[i+3] << 24); - } - - static final Charset unicode_set = Charset.forName("UTF-8"); - - static String string(int[] bytes, int s, int l) { - if (s + l > bytes.length) { - if (s > bytes.length) { - s = bytes.length; - l = 0; - } else { - l = bytes.length - s; - } - } - - int i; - for (i = l - 1; i >= 0; i--) - if (bytes[s+i] != 0) - break; - - l = i + 1; - byte[] b = new byte[l]; - - for (i = 0; i < l; i++) - b[i] = (byte) bytes[s+i]; - String n = new String(b, unicode_set); - return n; - } - - static int hexbyte(String s, int i) { - int c0, c1; - - if (s.length() < i + 2) - throw new NumberFormatException(String.format("invalid hex \"%s\"", s)); - c0 = s.charAt(i); - if (!Altos.ishex(c0)) - throw new NumberFormatException(String.format("invalid hex \"%c\"", c0)); - c1 = s.charAt(i+1); - if (!Altos.ishex(c1)) - throw new NumberFormatException(String.format("invalid hex \"%c\"", c1)); - return Altos.fromhex(c0) * 16 + Altos.fromhex(c1); - } - - static int[] hexbytes(String s) { - int n; - int[] r; - int i; - - if ((s.length() & 1) != 0) - throw new NumberFormatException(String.format("invalid line \"%s\"", s)); - n = s.length() / 2; - r = new int[n]; - for (i = 0; i < n; i++) - r[i] = Altos.hexbyte(s, i * 2); - return r; - } - - 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; - } - - 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 public boolean initialized = false; static public boolean loaded_library = false; diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 080bfc99..d1e5fdf0 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -357,23 +357,23 @@ public class AltosEepromDownload implements Runnable { } switch (log_format) { - case Altos.AO_LOG_FORMAT_FULL: + case AltosLib.AO_LOG_FORMAT_FULL: extension = "eeprom"; CaptureFull(eechunk); break; - case Altos.AO_LOG_FORMAT_TINY: + case AltosLib.AO_LOG_FORMAT_TINY: extension = "eeprom"; CaptureTiny(eechunk); break; - case Altos.AO_LOG_FORMAT_TELEMETRY: + case AltosLib.AO_LOG_FORMAT_TELEMETRY: extension = "telem"; CaptureTelemetry(eechunk); break; - case Altos.AO_LOG_FORMAT_TELESCIENCE: + case AltosLib.AO_LOG_FORMAT_TELESCIENCE: extension = "science"; CaptureTeleScience(eechunk); break; - case Altos.AO_LOG_FORMAT_MEGAMETRUM: + case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: extension = "mega"; CaptureMega(eechunk); } -- cgit v1.2.3 From bfbd1d82f4c25120a97840a1bd4787680823afd8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jun 2012 15:15:25 -0700 Subject: altosdroid: Add files necessary to build application Signed-off-by: Keith Packard --- altosdroid/build.properties | 1 + altosdroid/build.xml | 85 +++++++++++++++++++++++++++++++++++++++++++ altosdroid/project.properties | 11 ++++++ 3 files changed, 97 insertions(+) create mode 100644 altosdroid/build.properties create mode 100644 altosdroid/build.xml create mode 100644 altosdroid/project.properties diff --git a/altosdroid/build.properties b/altosdroid/build.properties new file mode 100644 index 00000000..63d080cc --- /dev/null +++ b/altosdroid/build.properties @@ -0,0 +1 @@ +jar.libs.dir=../altoslib \ No newline at end of file diff --git a/altosdroid/build.xml b/altosdroid/build.xml new file mode 100644 index 00000000..6a89edbe --- /dev/null +++ b/altosdroid/build.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/altosdroid/project.properties b/altosdroid/project.properties new file mode 100644 index 00000000..0a80e644 --- /dev/null +++ b/altosdroid/project.properties @@ -0,0 +1,11 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system use, +# "ant.properties", and override values to adapt the script to your +# project structure. + +# Project target. +target=Google Inc.:Google APIs:10 -- cgit v1.2.3 From baf1be1def01266512e67068948bf19b04ead6aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:23:10 -0700 Subject: Allow product to override maximum number of command lists (NUM_CMDS) Just in case some product wants to save memory, or have more. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 40bb476c..fbf0c347 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -258,7 +258,9 @@ version(void) printf("software-version %s\n", ao_version); } +#ifndef NUM_CMDS #define NUM_CMDS 11 +#endif static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); static __pdata uint8_t ao_ncmds; -- cgit v1.2.3 From a5a7df405c242593cbc828d5b66bbfc141a35947 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:26:06 -0700 Subject: Temporarily disable packet and telem on MM While work on the radio code progresses Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 2bc5c36a..c2a7cd64 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -94,7 +94,7 @@ ao_flight(void) */ ao_flight_state = ao_flight_invalid; -#if HAS_RADIO +#if HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in invalid mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -120,7 +120,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined (MEGAMETRUM) /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -131,7 +131,7 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; -#if HAS_ACCEL && HAS_RADIO +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in idle mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -171,7 +171,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +259,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); -- cgit v1.2.3 From 97d163c88ed8c8f64a9714018863d0b6eedab38f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:27:48 -0700 Subject: altos: Configure cc1120 frequency Set default conversion value, and pull the selected frequency calibration data out of the config block. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 95b21170..5156b7b2 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -25,7 +25,7 @@ uint8_t ao_radio_abort; #define CC1120_DEBUG 1 -uint32_t ao_radio_cal = 1186611; +uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -492,6 +492,9 @@ ao_radio_get(uint8_t len) ao_mutex_get(&ao_radio_mutex); if (!ao_radio_configured) ao_radio_setup(); + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); ao_radio_reg_write(CC1120_PKT_LEN, len); } -- cgit v1.2.3 From c96e60bedeb00d28c36436c12b803fd8cbadce26 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:28:55 -0700 Subject: altos: Actually write cc1120 register values Helps to not use 'read' mode when writing. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5156b7b2..d2820e51 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -77,13 +77,13 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | CC1120_EXTENDED); data[1] = addr; d = 2; } else { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | addr); d = 1; -- cgit v1.2.3 From 93e6d0a2c0b60e7bedd34f06ba63b468dcc8e013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:30:03 -0700 Subject: altos: Fix RDF mode data rate and PKT_CFG0 value Changes tone to the desired 1kHz frequency and ensures the PKT_CFG0 has the right value. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index d2820e51..37dc67db 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -197,8 +197,8 @@ ao_radio_recv_abort(void) * * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ -#define RDF_DRATE_E 6 -#define RDF_DRATE_M 511705 +#define RDF_DRATE_E 5 +#define RDF_DRATE_M 25166 #define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { @@ -216,6 +216,11 @@ static const uint16_t rdf_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; #define int_pin(w) printf("\t%s: %d\n", \ -- cgit v1.2.3 From 27c95adf35e646840b9bd562497eea0dc96bb9bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:31:36 -0700 Subject: altos: use 'b' command for radio beep 'B' is used by the baro data dumper. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 37dc67db..5fe314c9 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -725,7 +725,7 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, - { ao_radio_beep, "B\0Emit an RDF beacon" }, + { ao_radio_beep, "b\0Emit an RDF beacon" }, #endif { 0, NULL } }; -- cgit v1.2.3 From 1b7e4c29bf9608bfc972ae28b53cc823f4c37f92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:32:10 -0700 Subject: altos: Make sure cc1120 is initialized correctly at startup time Check to make sure it pulls down MISO when CS is enabled. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5fe314c9..63f7cd89 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -733,8 +733,18 @@ static const struct ao_cmds ao_radio_cmds[] = { void ao_radio_init(void) { + int i; + ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + for (i = 0; i < 10000; i++) { + if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + break; + } + AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + if (i == 10000) + ao_panic(AO_PANIC_SELF_TEST); ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From c2949ea15c59215834fedac7646f50c8a09f716f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:38:37 -0700 Subject: altos: Fix cc1120 packet mode datarate and config Was using the wrong function Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 63f7cd89..68f7e736 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -406,17 +406,16 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* * For our packet data, set the symbol rate to 38360 Baud * - * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * (2**20 + DATARATE_M) * 2 ** DATARATE_E * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 405002 - * DATARATE_E = 10 * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + * DATARATE_M = 239914 + * DATARATE_E = 9 */ -#define PACKET_DRATE_E 10 -#define PACKET_DRATE_M 405002 +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 static const uint16_t packet_setup[] = { CC1120_DEVIATION_M, PACKET_DEV_M, @@ -433,6 +432,11 @@ static const uint16_t packet_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (1 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; void -- cgit v1.2.3 From e09e35471e788b88909ff01037fb8e0e4eabcd7d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:40:30 -0700 Subject: altos: Start making cc1120 radio work RDF tones and radio calibration work now. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 31 ++++++++++++++++++++++++++----- src/drivers/ao_cc1120.h | 1 + src/drivers/ao_cc1120_CC1120.h | 5 +---- src/megametrum-v0.1/Makefile | 2 +- src/megametrum-v0.1/ao_megametrum.c | 18 +----------------- src/megametrum-v0.1/ao_pins.h | 9 ++++++++- 6 files changed, 38 insertions(+), 28 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 68f7e736..a1d78d9c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -106,7 +106,7 @@ ao_radio_strobe(uint8_t addr) ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); #if CC1120_DEBUG - printf("%02x\n", in); + printf("%02x\n", in); flush(); #endif return in; } @@ -254,15 +254,33 @@ ao_radio_rdf(uint8_t len) ao_radio_abort = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_reg_write(CC1120_PKT_LEN, len); + +#if 0 int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); int_pin ("After CFG"); +#endif + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + + ao_radio_reg_write(CC1120_PKT_LEN, len); + + printf ("packet length: %d\n", ao_radio_reg_read(CC1120_PKT_LEN)); + ao_radio_strobe(CC1120_STX); + + for (i = 0; i < 20; i++) { + printf ("%d ", i); flush(); + printf ("Status %02x ", ao_radio_status()); flush(); + printf ("num_tx_bytes %d ", ao_radio_reg_read(CC1120_NUM_TXBYTES)); flush(); + printf ("marc status %x\n", ao_radio_marc_status()); flush(); + ao_delay(AO_MS_TO_TICKS(50)); + } + +#if 0 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); int_pin ("After strobe"); ao_delay(AO_MS_TO_TICKS(100)); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); int_pin ("After delay"); cli(); for (i = 0; i < 20; i++) { @@ -278,11 +296,14 @@ ao_radio_rdf(uint8_t len) #endif } sei(); +#endif printf ("num_tx_bytes %d marc status %x\n", ao_radio_reg_read(CC1120_NUM_TXBYTES), ao_radio_marc_status()); +#if 0 if (!ao_radio_tx_done()) ao_radio_idle(); +#endif ao_radio_set_packet(); ao_radio_put(); } @@ -488,8 +509,8 @@ ao_radio_setup(void) ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); +// ao_enable_port(AO_CC1120_INT_PORT); +// ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); ao_radio_set_packet(); ao_radio_configured = 1; diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 0f03f2c7..5822a21a 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -281,6 +281,7 @@ #define CC1120_PKT_CFG1_APPEND_STATUS 0 #define CC1120_PKT_CFG0 0x28 +#define CC1120_PKT_CFG0_RESERVED7 7 #define CC1120_PKT_CFG0_LENGTH_CONFIG 5 #define CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED 0 #define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 1799c274..f86fd384 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -68,7 +68,7 @@ CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ #endif - CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ + CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ @@ -87,9 +87,6 @@ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ CC1120_FREQOFF1, 0x00, /* Frequency Offset (MSB) */ CC1120_FREQOFF0, 0x00, /* Frequency Offset (LSB) */ - CC1120_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ - CC1120_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ - CC1120_FREQ0, 0x33, /* Frequency Configuration [7:0] */ CC1120_IF_ADC2, 0x02, /* Analog to Digital Converter Configuration, Reg 2 */ CC1120_IF_ADC1, 0xa6, /* Analog to Digital Converter Configuration, Reg 1 */ CC1120_IF_ADC0, 0x04, /* Analog to Digital Converter Configuration, Reg 0 */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a07b25ee..5761fed7 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -24,7 +24,6 @@ INC = \ # Common AltOS sources # -# ao_cc1120.c \ # ao_packet.c \ # ao_packet_slave.c \ @@ -45,6 +44,7 @@ ALTOS_SRC = \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ + ao_cc1120.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 19746d37..628c5538 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -21,21 +21,6 @@ #include #include -void -beep(void) -{ - ao_beep(AO_BEEP_MID); - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - ao_beep(0); -} - -const struct ao_cmds ao_mm_cmds[] = { - { beep, "b\0Beep" }, - { 0, NULL }, -}; - int main(void) { @@ -55,7 +40,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_exti_init(); -// ao_radio_init(); + ao_radio_init(); ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); @@ -64,7 +49,6 @@ main(void) ao_report_init(); ao_config_init(); - ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); return 0; } diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index d6394d9b..5121ad58 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -65,6 +65,7 @@ #define USE_INTERNAL_FLASH 0 #define HAS_USB 1 #define HAS_BEEP 1 +#define HAS_RADIO 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 @@ -74,6 +75,10 @@ #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 #define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO stm_gpiob +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 @@ -81,7 +86,7 @@ #define HAS_I2C_2 1 #define I2C_2_PB10_PB11 1 -#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_SLAVE 0 #define LOW_LEVEL_DEBUG 1 @@ -251,4 +256,6 @@ struct ao_adc { #define HAS_HIGHG_ACCEL 1 +#define NUM_CMDS 16 + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From e856df474c386b8df3d2bd9e87b766ae0439efbf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:41:17 -0700 Subject: altos: Reduce STM SPI data rate to 4MHz cc1120 doesn't want more than 6.1MHz, otherwise it gets very angry. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 8bb0d8e8..8784d985 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -282,7 +282,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_8 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 5df94f74522357e062f4ec2786ff825381b2fb10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 12:42:32 -0700 Subject: altos: Crank cc1120 power down to 0dBm to avoid crashing CPU Looks like RFI from the transmitter is confusing the CPU; lower the 1120 power output from +14dBm to +0dBm to keep the CPU happy. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120_CC1120.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index f86fd384..c900b7f9 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -71,7 +71,8 @@ CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ - CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x23, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ -- cgit v1.2.3 From 58e005375ca29dec6091d87159055004e7f19605 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 12:43:43 -0700 Subject: altos: Use interrupts to wake up after RDF transmission. Also clean up the debug output Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 72 ++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 52 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index a1d78d9c..f06d52ca 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -24,6 +24,7 @@ uint8_t ao_radio_mutex; uint8_t ao_radio_abort; #define CC1120_DEBUG 1 +#define CC1120_TRACE 0 uint32_t ao_radio_cal = 0x6ca333; @@ -42,7 +43,7 @@ ao_radio_reg_read(uint16_t addr) uint8_t data[2]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); #endif if (CC1120_IS_EXTENDED(addr)) { @@ -61,7 +62,7 @@ ao_radio_reg_read(uint16_t addr) ao_radio_spi_send(data, d); ao_radio_spi_recv(data, 1); ao_radio_deselect(); -#if CC1120_DEBUG +#if CC1120_TRACE printf (" %02x\n", data[0]); #endif return data[0]; @@ -73,7 +74,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) uint8_t data[3]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { @@ -99,13 +100,13 @@ ao_radio_strobe(uint8_t addr) { uint8_t in; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_strobe (%02x): ", addr); flush(); #endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); -#if CC1120_DEBUG +#if CC1120_TRACE printf("%02x\n", in); flush(); #endif return in; @@ -149,12 +150,10 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) CC1120_FIFO); uint8_t status; - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); ao_radio_select(); ao_radio_duplex(&addr, &status, 1); ao_radio_spi_send_fixed(data, len); ao_radio_deselect(); - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); return status; } @@ -223,10 +222,6 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -#define int_pin(w) printf("\t%s: %d\n", \ - w,\ - (AO_CC1120_INT_PORT.idr >> AO_CC1120_INT_PIN) & 1) - static uint8_t ao_radio_marc_status(void) { @@ -252,58 +247,27 @@ ao_radio_rdf(uint8_t len) ao_radio_get(len); ao_radio_abort = 0; + ao_radio_wake = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); -#if 0 - int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - int_pin ("After CFG"); -#endif ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); ao_radio_reg_write(CC1120_PKT_LEN, len); - printf ("packet length: %d\n", ao_radio_reg_read(CC1120_PKT_LEN)); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); - for (i = 0; i < 20; i++) { - printf ("%d ", i); flush(); - printf ("Status %02x ", ao_radio_status()); flush(); - printf ("num_tx_bytes %d ", ao_radio_reg_read(CC1120_NUM_TXBYTES)); flush(); - printf ("marc status %x\n", ao_radio_marc_status()); flush(); - ao_delay(AO_MS_TO_TICKS(50)); - } - -#if 0 - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - int_pin ("After strobe"); - ao_delay(AO_MS_TO_TICKS(100)); - int_pin ("After delay"); cli(); - for (i = 0; i < 20; i++) { -#if CC1120_DEBUG - ao_delay(AO_MS_TO_TICKS(50)); - int_pin ("Waited"); - printf ("Status %02x num_tx_bytes %d marc status %x\n", - ao_radio_status(), - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); -#else + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); -#endif - } + sei(); -#endif - printf ("num_tx_bytes %d marc status %x\n", - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); -#if 0 if (!ao_radio_tx_done()) ao_radio_idle(); -#endif ao_radio_set_packet(); ao_radio_put(); } @@ -335,7 +299,7 @@ ao_radio_test(void) #endif ao_radio_get(0xff); ao_radio_strobe(CC1120_STX); -#if CC1120_DEBUG +#if CC1120_TRACE { int t; for (t = 0; t < 10; t++) { printf ("status: %02x\n", ao_radio_status()); @@ -508,11 +472,10 @@ ao_radio_setup(void) /* Enable marc status interrupt on gpio 2 pin */ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); - /* Enable the EXTI interrupt for the appropriate pin */ -// ao_enable_port(AO_CC1120_INT_PORT); -// ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); - ao_radio_set_packet(); + + ao_config_get(); + ao_radio_configured = 1; } @@ -741,7 +704,7 @@ static void ao_radio_show(void) { } static void ao_radio_beep(void) { - ao_radio_rdf(120); + ao_radio_rdf(RDF_PACKET_LEN); } #endif @@ -771,5 +734,10 @@ ao_radio_init(void) AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST); + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1120_INT_PORT); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From ca310342d7b0bd1b78318cae38d920b8690dfd36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:09:43 -0700 Subject: altosui: Catch timeout errors when setting up TD telem monitoring Close the port in this case so it can be used for other things. Signed-off-by: Keith Packard --- altoslib/AltosTelemetryReader.java | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 112e008e..911a099a 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -106,14 +106,22 @@ public class AltosTelemetryReader extends AltosFlightReader { public AltosTelemetryReader (AltosLink in_link) throws IOException, InterruptedException, TimeoutException { link = in_link; - log = new AltosLog(link); - name = link.name; - previous = null; - telem = new LinkedBlockingQueue(); - frequency = AltosPreferences.frequency(link.serial); - set_frequency(frequency); - telemetry = AltosPreferences.telemetry(link.serial); - set_telemetry(telemetry); - link.add_monitor(telem); + try { + log = new AltosLog(link); + name = link.name; + previous = null; + telem = new LinkedBlockingQueue(); + frequency = AltosPreferences.frequency(link.serial); + set_frequency(frequency); + telemetry = AltosPreferences.telemetry(link.serial); + set_telemetry(telemetry); + link.add_monitor(telem); + } catch (TimeoutException e) { + close(true); + throw(e); + } catch (InterruptedException e) { + close(true); + throw(e); + } } } -- cgit v1.2.3 From 4e6d96816e6604ee8d9bb49345a1c1211699a655 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:11:23 -0700 Subject: altos: ao_storage_read already calls ao_storage_setup No need to call twice. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 76a8ed4a..a4877b06 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,7 +81,6 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM - ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From 9d3fe2a80d0925e3eded6d738d05c5b4ea61504c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:12:18 -0700 Subject: altos: Don't lose IRQ disabled state in ao_sleep Using ao_arch_critical around the wchan setting will force interrupts to be re-enabled before ao_yield records the state of that bit, potentially causing problems with functions not atomically testing and sleeping. Tasks that need to set wchan with interrupts disabled should have interrupts disabled when entering ao_sleep already. Signed-off-by: Keith Packard --- src/core/ao_task.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/core/ao_task.c b/src/core/ao_task.c index d7d0e8a2..910f1587 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -103,9 +103,7 @@ ao_yield(void) ao_arch_naked_define uint8_t ao_sleep(__xdata void *wchan) { - ao_arch_critical( - ao_cur_task->wchan = wchan; - ); + ao_cur_task->wchan = wchan; ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; -- cgit v1.2.3 From 1a294852b3607947f0f86bf236785456d8719e5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:14:33 -0700 Subject: altos: Be more careful about register save/restore in ao_yield Make sure the general registers are all saved before messing with any of them. Then, explicitly use r0 to save/restore apsr and primask. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 62af86f7..bbd1b3b1 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -74,12 +74,6 @@ extern const uint16_t ao_serial_number; uint32_t a = (uint32_t) start; \ int i; \ \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ - \ - /* PRIMASK with interrupts enabled */ \ - ARM_PUSH32(sp, 0); \ - \ /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ @@ -88,23 +82,29 @@ extern const uint16_t ao_serial_number; while (i--) \ ARM_PUSH32(sp, 0); \ \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ + \ + /* PRIMASK with interrupts enabled */ \ + ARM_PUSH32(sp, 0); \ + \ task->sp = sp; \ } while (0); #define ao_arch_save_regs() do { \ - uint32_t apsr; \ - uint32_t primask; \ + /* Save general registers */ \ + asm("push {r0-r12,lr}\n"); \ \ /* Save APSR */ \ - asm("mrs %0,apsr" : "=&r" (apsr)); \ - asm("push {%0}" : : "r" (apsr)); \ + asm("mrs r0,apsr"); \ + asm("push {r0}"); \ \ /* Save PRIMASK */ \ - asm("mrs %0,primask" : "=&r" (primask)); \ - asm("push {%0}" : : "r" (primask)); \ + asm("mrs r0,primask"); \ + asm("push {r0}"); \ \ - /* Save general registers */ \ - asm("push {r0-r12,lr}\n"); \ + /* Enable interrupts */ \ + sei(); \ } while (0) #define ao_arch_save_stack() do { \ @@ -123,23 +123,21 @@ extern const uint16_t ao_serial_number; #define ao_arch_restore_stack() do { \ uint32_t sp; \ - uint32_t primask; \ - uint32_t apsr; \ sp = (uint32_t) ao_cur_task->sp; \ \ /* Switch stacks */ \ asm("mov sp, %0" : : "r" (sp) ); \ \ - /* Restore general registers */ \ - asm("pop {r0-r12,lr}\n"); \ - \ /* Restore PRIMASK */ \ - asm("pop {%0}" : "=&r" (primask) ); \ - asm("msr primask,%0" : : "r" (primask) ); \ + asm("pop {r0}"); \ + asm("msr primask,r0"); \ \ /* Restore APSR */ \ - asm("pop {%0}" : "=&r" (apsr) ); \ - asm("msr apsr,%0" : : "r" (apsr) ); \ + asm("pop {r0}"); \ + asm("msr apsr,r0"); \ + \ + /* Restore general registers */ \ + asm("pop {r0-r12,lr}\n"); \ \ /* Return to calling function */ \ asm("bx lr"); \ -- cgit v1.2.3 From e6d236fdc615625fbbf28377453f920729e49b0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:17:00 -0700 Subject: altos: Software implemenation of CC1111 radio encoding Add CRC, whitening, FEC and interleaving routines for transmission path to allow cc1120 to send telem packets to cc1111. Signed-off-by: Keith Packard --- src/.gitignore | 1 + src/Makefile | 6 +- src/drivers/ao_cc1120.c | 87 ++++++++++++++++++-------- src/drivers/ao_cc1120_CC1120.h | 28 ++++----- src/drivers/ao_fec.h | 60 ++++++++++++++++++ src/drivers/ao_fec_tx.c | 139 +++++++++++++++++++++++++++++++++++++++++ src/megametrum-v0.1/Makefile | 3 + src/test/Makefile | 7 ++- src/test/ao_fec_tx_test.c | 47 ++++++++++++++ src/util/make-whiten | 37 +++++++++++ 10 files changed, 372 insertions(+), 43 deletions(-) create mode 100644 src/drivers/ao_fec.h create mode 100644 src/drivers/ao_fec_tx.c create mode 100644 src/test/ao_fec_tx_test.c create mode 100644 src/util/make-whiten diff --git a/src/.gitignore b/src/.gitignore index c6e1e353..cae36ae6 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ altitude.h altitude-pa.h +ao_whiten.h diff --git a/src/Makefile b/src/Makefile index c2e324c4..3fca2ab2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@ vpath make-altitude util vpath make-altitude-pa util vpath make-kalman util +vpath make-whiten util vpath kalman.5c kalman vpath kalman_filter.5c kalman vpath load_csv.5c kalman @@ -46,7 +47,7 @@ uninstall: all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h altitude.h: make-altitude nickle $< > $@ @@ -57,5 +58,8 @@ altitude-pa.h: make-altitude-pa ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c bash $< kalman > $@ +ao_whiten.h: make-whiten + nickle $< > $@ + clean-local: rm -f altitude.h ao_kalman.h diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index f06d52ca..231d14d4 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -18,6 +18,7 @@ #include #include #include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; @@ -240,26 +241,27 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_start_tx(void) +{ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + void ao_radio_rdf(uint8_t len) { int i; ao_radio_get(len); - ao_radio_abort = 0; ao_radio_wake = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); - ao_radio_reg_write(CC1120_PKT_LEN, len); - - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - - ao_radio_strobe(CC1120_STX); + ao_radio_start_tx(); cli(); while (!ao_radio_wake && !ao_radio_abort) @@ -327,24 +329,45 @@ ao_radio_test(void) void ao_radio_send(void *d, uint8_t size) { - uint8_t marc_status; - + uint8_t marc_status; + static uint8_t prepare[128]; + uint8_t prepare_len; + static uint8_t encode[256]; + uint8_t encode_len; + static uint8_t interleave[256]; + uint8_t interleave_len; + + ao_fec_dump_bytes(d, size, "Input"); + +#if 1 + prepare_len = ao_fec_prepare(d, size, prepare); + ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + + ao_fec_whiten(prepare, prepare_len, prepare); + ao_fec_dump_bytes(prepare, prepare_len, "Whiten"); + + encode_len = ao_fec_encode(prepare, prepare_len, encode); + ao_fec_dump_bytes(encode, encode_len, "Encode"); + + interleave_len = ao_fec_interleave(encode, encode_len, interleave); + ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + ao_radio_get(interleave_len); + ao_radio_fifo_write(interleave, interleave_len); +#else ao_radio_get(size); - ao_radio_wake = 0; ao_radio_fifo_write(d, size); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); +#endif + + ao_radio_wake = 0; + + ao_radio_start_tx(); + cli(); - for (;;) { - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); + if (!ao_radio_tx_done()) + ao_radio_idle(); ao_radio_put(); } @@ -361,6 +384,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) cli(); for (;;) { if (ao_radio_abort) + break; if (ao_radio_wake) { marc_status = ao_radio_marc_status(); @@ -413,7 +437,7 @@ static const uint16_t packet_setup[] = { CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((1 << CC1120_PKT_CFG1_WHITE_DATA) | + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (1 << CC1120_PKT_CFG1_APPEND_STATUS)), @@ -469,9 +493,6 @@ ao_radio_setup(void) for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - /* Enable marc status interrupt on gpio 2 pin */ - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); - ao_radio_set_packet(); ao_config_get(); @@ -707,6 +728,21 @@ static void ao_radio_beep(void) { ao_radio_rdf(RDF_PACKET_LEN); } +static void ao_radio_packet(void) { + static uint8_t packet[] = { +#if 1 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#else + 3, 1, 2, 3 +#endif + }; + + ao_radio_send(packet, sizeof (packet)); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { @@ -714,6 +750,7 @@ static const struct ao_cmds ao_radio_cmds[] = { #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, + { ao_radio_packet, "p\0Send a test packet" }, #endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c900b7f9..c0f35a23 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -21,29 +21,27 @@ * ***************************************************************/ - CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ - CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ - CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ - CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ + CC1120_SYNC3, 0xD3, /* Sync Word Configuration [31:24] */ + CC1120_SYNC2, 0x91, /* Sync Word Configuration [23:16] */ + CC1120_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ + CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ + CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ - CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ -#if 0 - CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ - CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ -#endif + CC1120_SYNC_CFG0, + (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) | + (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR), CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ - CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ + CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */ + (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD), CC1120_PREAMBLE_CFG0, 0x2a, /* */ CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ + CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ -#if 0 - CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ - CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ - CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ -#endif + CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/drivers/ao_fec.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FEC_H_ +#define _AO_FEC_H_ + +#include + +#define AO_FEC_CRC_INIT 0xffff +#define AO_FEC_TRELLIS_TERMINATOR 0x0b +#define AO_FEC_PREPARE_EXTRA 4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c new file mode 100644 index 00000000..b8933956 --- /dev/null +++ b/src/drivers/ao_fec_tx.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ + uint8_t i; + + printf ("%s (%d):", name, len); + for (i = 0; i < len; i++) { + if ((i & 7) == 0) + printf ("\n\t%02x:", i); + printf(" %02x", bytes[i]); + } + printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = crc_byte(*bytes++, crc); + return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t crc = ao_fec_crc (in, len); + uint8_t i; + uint8_t num_fec; + + /* Copy data */ + for (i = 0; i < len; i++) + out[i] = in[i]; + + /* Append CRC */ + out[i++] = crc >> 8; + out[i++] = crc; + + /* Append FEC -- 1 byte if odd, two bytes if even */ + num_fec = 2 - (i & 1); + while (num_fec--) + out[i++] = AO_FEC_TRELLIS_TERMINATOR; + return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ + const uint8_t *w = whiten; + + while (len--) + *out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { + 0, 3, 1, 2, + 3, 0, 2, 1, + 3, 0, 2, 1, + 0, 3, 1, 2 +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t fec = 0, output; + uint8_t byte, bit; + + for (byte = 0; byte < len; byte++) { + fec = (fec & 0x700) | in[byte]; + output = 0; + for (bit = 0; bit < 8; bit++) { + output = output << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } + out[byte * 2] = output >> 8; + out[byte * 2 + 1] = output; + } + return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + out[i+0] = interleaved >> 24; + out[i+1] = interleaved >> 16; + out[i+2] = interleaved >> 8; + out[i+3] = interleaved; + } + return len; +} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5761fed7..054855ba 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -18,6 +18,8 @@ INC = \ ao_ms5607.h \ ao_hmc5883.h \ ao_mpu6000.h \ + ao_cc1120_CC1120.h \ + ao_whiten.h \ stm32l.h # @@ -45,6 +47,7 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_cc1120.c \ + ao_fec_tx.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 1e54f5e0..3e308dd7 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test KALMAN=make-kalman @@ -38,4 +38,7 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h cc $(CFLAGS) -o $@ $< ao_kalman.h: $(KALMAN) - (cd .. && make ao_kalman.h) \ No newline at end of file + (cd .. && make ao_kalman.h) + +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c + cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c new file mode 100644 index 00000000..b8dc9308 --- /dev/null +++ b/src/test/ao_fec_tx_test.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +int +main(int argc, char **argv) +{ + uint8_t input[4] = { 3, 1, 2, 3 }; + uint8_t prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; + uint8_t encode[sizeof(prepare) * 2]; + uint8_t interleave[sizeof(encode)]; + uint8_t prepare_len; + uint8_t encode_len; + uint8_t interleave_len; + + ao_fec_dump_bytes(input, sizeof(input), "Input"); + + prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + + ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + + encode_len = ao_fec_encode(prepare, prepare_len, encode); + + ao_fec_dump_bytes(encode, encode_len, "Encode"); + + interleave_len = ao_fec_interleave(encode, encode_len, interleave); + + ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); +} + diff --git a/src/util/make-whiten b/src/util/make-whiten new file mode 100644 index 00000000..d68a02af --- /dev/null +++ b/src/util/make-whiten @@ -0,0 +1,37 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +/* Generate the data whitening array used by the CC11* radios */ + +int pn9 = 0x1ff; + +void +pn9_step() { + pn9 = (pn9 >> 1) | (((pn9 ^ (pn9 >> 5)) & 1) << 8); +} + +int val() +{ + int ret = pn9 & 0xff; + + for (int i = 0; i < 8; i++) + pn9_step(); + return ret; +} + +for (int i = 0; i < 128; i++) + printf (" /* %3d */ 0x%02x,\n", i + 1, val()); -- cgit v1.2.3 From 55747ce210d7d80d5b4fdaaf9dc7ee0f7bc8b0a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 18:58:56 -0700 Subject: altosui: Move product definitions from AltosUI to AltosLib Signed-off-by: Keith Packard --- altoslib/AltosLib.java | 24 ++++++++++++ altosui/Altos.java | 85 ------------------------------------------ altosui/AltosBTDevice.java | 1 + altosui/AltosBTKnown.java | 10 ++++- altosui/AltosConfig.java | 2 +- altosui/AltosConfigureUI.java | 2 +- altosui/AltosDeviceDialog.java | 4 +- altosui/AltosUI.java | 1 + 8 files changed, 39 insertions(+), 90 deletions(-) diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index e74eaf99..4a779c55 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -78,6 +78,30 @@ public class AltosLib { public static final int ao_flight_landed = 8; public static final int ao_flight_invalid = 9; + /* USB product IDs */ + public final static int vendor_altusmetrum = 0xfffe; + + public final static int product_altusmetrum = 0x000a; + public final static int product_telemetrum = 0x000b; + public final static int product_teledongle = 0x000c; + public final static int product_teleterra = 0x000d; + public final static int product_telebt = 0x000e; + public final static int product_telelaunch = 0x000f; + public final static int product_telelco = 0x0010; + public final static int product_telescience = 0x0011; + public final static int product_telepyro =0x0012; + public final static int product_megametrum = 0x0023; + public final static int product_megadongle = 0x0024; + public final static int product_altusmetrum_min = 0x000a; + public final static int product_altusmetrum_max = 0x0024; + + public final static int product_any = 0x10000; + public final static int product_basestation = 0x10000 + 1; + public final static int product_altimeter = 0x10000 + 2; + + /* Bluetooth "identifier" (bluetooth sucks) */ + public final static String bt_product_telebt = "TeleBT"; + /* Telemetry modes */ public static final int ao_telemetry_off = 0; public static final int ao_telemetry_min = 1; diff --git a/altosui/Altos.java b/altosui/Altos.java index 78e56970..e60b3aaa 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -108,89 +108,4 @@ public class Altos extends AltosLib { } return loaded_library; } - - static int usb_vendor_altusmetrum() { - load_library(); - return 0xfffe; - } - - static int usb_product_altusmetrum() { - load_library(); - return 0x000a; - } - - static int usb_product_altusmetrum_min() { - load_library(); - return 0x000a; - } - - static int usb_product_altusmetrum_max() { - load_library(); - return 0x0013; - } - - static int usb_product_telemetrum() { - load_library(); - return 0x000b; - } - - static int usb_product_teledongle() { - load_library(); - return 0x000c; - } - - static int usb_product_teleterra() { - load_library(); - return 0x000d; - } - - static int usb_product_telebt() { - load_library(); - return 0x000e; - } - - static int usb_product_telelaunch() { - load_library(); - return 0x000f; - } - - static int usb_product_telelco() { - load_library(); - return 0x0010; - } - - static int usb_product_telescience() { - load_library(); - return 0x0011; - } - - static int usb_product_telepyro() { - load_library(); - return 0x0012; - } - - public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); - public final static int product_altusmetrum = usb_product_altusmetrum(); - public final static int product_telemetrum = usb_product_telemetrum(); - public final static int product_teledongle = usb_product_teledongle(); - public final static int product_teleterra = usb_product_teleterra(); - public final static int product_telebt = usb_product_telebt(); - public final static int product_telelaunch = usb_product_telelaunch(); - public final static int product_tele10 = usb_product_telelco(); - public final static int product_telescience = usb_product_telescience(); - public final static int product_telepyro = usb_product_telepyro(); - public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); - public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); - - public final static int product_any = 0x10000; - public final static int product_basestation = 0x10000 + 1; - - static String bt_product_telebt() { - load_library(); - return "TeleBT"; - } - - public final static String bt_product_telebt = bt_product_telebt(); - - public static AltosBTKnown bt_known = new AltosBTKnown(); } diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index 55b8f8fc..f6926b10 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -116,6 +116,7 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { } public AltosBTDevice(String name, String addr) { + Altos.load_library(); libaltos.altos_bt_fill_in(name, addr,this); } diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java index e30be057..021e4d0b 100644 --- a/altosui/AltosBTKnown.java +++ b/altosui/AltosBTKnown.java @@ -94,4 +94,12 @@ public class AltosBTKnown implements Iterable { bt_pref = AltosUIPreferences.bt_devices(); load(); } -} \ No newline at end of file + + static AltosBTKnown known; + + static public AltosBTKnown bt_known() { + if (known == null) + known = new AltosBTKnown(); + return known; + } +} diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 35fef080..cae41858 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -491,7 +491,7 @@ public class AltosConfig implements ActionListener { try { serial_line = new AltosSerial(device); try { - if (!device.matchProduct(Altos.product_telemetrum)) + if (!device.matchProduct(Altos.product_altimeter)) remote = true; init_ui(); } catch (InterruptedException ie) { diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index deb179d6..d0ed9325 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -344,7 +344,7 @@ public class AltosConfigureUI manage_bluetooth = new JButton("Manage Bluetooth"); manage_bluetooth.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - AltosBTManage.show(owner, Altos.bt_known); + AltosBTManage.show(owner, AltosBTKnown.bt_known()); } }); c.gridx = 0; diff --git a/altosui/AltosDeviceDialog.java b/altosui/AltosDeviceDialog.java index e53e75c1..fa9d0013 100644 --- a/altosui/AltosDeviceDialog.java +++ b/altosui/AltosDeviceDialog.java @@ -41,7 +41,7 @@ public class AltosDeviceDialog extends AltosDialog implements ActionListener { private AltosDevice[] devices() { java.util.List usb_devices = AltosUSBDevice.list(product); int num_devices = usb_devices.size(); - java.util.List bt_devices = Altos.bt_known.list(product); + java.util.List bt_devices = AltosBTKnown.bt_known().list(product); num_devices += bt_devices.size(); AltosDevice[] devices = new AltosDevice[num_devices]; @@ -169,7 +169,7 @@ public class AltosDeviceDialog extends AltosDialog implements ActionListener { if ("select".equals(e.getActionCommand())) value = (AltosDevice)(list.getSelectedValue()); if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, Altos.bt_known); + AltosBTManage.show(frame, AltosBTKnown.bt_known()); update_devices(); return; } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 538f8734..926d66f0 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -538,6 +538,7 @@ public class AltosUI extends AltosFrame { } public static void main(final String[] args) { + load_library(null); try { UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel()); } catch (Exception e) { -- cgit v1.2.3 From 4cb46b8a84a0dd5b8fcb479d7aa5157480e1bc67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:01:24 -0700 Subject: altosui: Add rudimentary MM support to altosui Decoded the MM sensor packets as if they were TM packets. Add the USB ids. Add class of 'altimeter' devices and match those instead of just telemetrum as appropriate. Signed-off-by: Keith Packard --- altoslib/AltosTelemetryRecord.java | 2 ++ altosui/AltosIdleMonitorUI.java | 2 +- altosui/AltosIgnite.java | 2 +- altosui/AltosUSBDevice.java | 7 ++++++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/altoslib/AltosTelemetryRecord.java b/altoslib/AltosTelemetryRecord.java index 4292dae8..6b6a252d 100644 --- a/altoslib/AltosTelemetryRecord.java +++ b/altoslib/AltosTelemetryRecord.java @@ -42,6 +42,7 @@ public abstract class AltosTelemetryRecord { final static int packet_type_location = 0x05; final static int packet_type_satellite = 0x06; final static int packet_type_companion = 0x07; + final static int packet_type_MM_sensor = 0x08; static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { AltosTelemetryRecord r; @@ -75,6 +76,7 @@ public abstract class AltosTelemetryRecord { case packet_type_TM_sensor: case packet_type_Tm_sensor: case packet_type_Tn_sensor: + case packet_type_MM_sensor: r = new AltosTelemetryRecordSensor(bytes, rssi); break; case packet_type_configuration: diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 02295ea9..2ee90937 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -325,7 +325,7 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay device = AltosDeviceDialog.show(in_owner, Altos.product_any); remote = false; - if (!device.matchProduct(Altos.product_telemetrum)) + if (!device.matchProduct(Altos.product_altimeter)) remote = true; serial = device.getSerial(); diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index c0cd44f1..45d37d16 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -178,7 +178,7 @@ public class AltosIgnite { serial = new AltosSerial(device); remote = false; - if (!device.matchProduct(Altos.product_telemetrum)) + if (!device.matchProduct(Altos.product_altimeter)) remote = true; } } \ No newline at end of file diff --git a/altosui/AltosUSBDevice.java b/altosui/AltosUSBDevice.java index b11a3934..ed5f8307 100644 --- a/altosui/AltosUSBDevice.java +++ b/altosui/AltosUSBDevice.java @@ -71,7 +71,12 @@ public class AltosUSBDevice extends altos_device implements AltosDevice { if (want_product == Altos.product_basestation) return matchProduct(Altos.product_teledongle) || matchProduct(Altos.product_teleterra) || - matchProduct(Altos.product_telebt); + matchProduct(Altos.product_telebt) || + matchProduct(Altos.product_megadongle); + + if (want_product == Altos.product_altimeter) + return matchProduct(Altos.product_telemetrum) || + matchProduct(Altos.product_megametrum); int have_product = getProduct(); -- cgit v1.2.3 From 9b24f413da0b6d989b32e8654a91c8deee4c81dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:02:50 -0700 Subject: ao-tools: add rudimentary support for MM telemetry to ao-telem Just pretends they're TM packets for now Signed-off-by: Keith Packard --- ao-tools/ao-telem/ao-telem.c | 1 + ao-tools/lib/cc-telemetry.h | 1 + 2 files changed, 2 insertions(+) diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c index 6207d433..384b2fc8 100644 --- a/ao-tools/ao-telem/ao-telem.c +++ b/ao-tools/ao-telem/ao-telem.c @@ -82,6 +82,7 @@ main (int argc, char **argv) case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: case AO_TELEMETRY_SENSOR_TELENANO: + case AO_TELEMETRY_SENSOR_MEGAMETRUM: printf ("state %1d accel %5d pres %5d ", telem.sensor.state, telem.sensor.accel, telem.sensor.pres); printf ("accel %6.2f speed %6.2f height %5d ", diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h index 71f6844d..4e064a97 100644 --- a/ao-tools/lib/cc-telemetry.h +++ b/ao-tools/lib/cc-telemetry.h @@ -37,6 +37,7 @@ struct ao_telemetry_generic { #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 #define AO_TELEMETRY_SENSOR_TELEMINI 0x02 #define AO_TELEMETRY_SENSOR_TELENANO 0x03 +#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 struct ao_telemetry_sensor { uint16_t serial; /* 0 */ -- cgit v1.2.3 From 629f43e7c7abbff33e14b168a08a4b6a9c88b937 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:04:22 -0700 Subject: altos: Add telemetry to megametrum Now that the radio works Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_flight_mm.c | 16 ++++++++++------ src/core/ao_telemetry.c | 8 ++++++-- src/megametrum-v0.1/Makefile | 5 +++-- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 1 + 6 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index a4136a9b..3dae8b40 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -347,6 +347,7 @@ struct ao_telemetry_generic { #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 #define AO_TELEMETRY_SENSOR_TELEMINI 0x02 #define AO_TELEMETRY_SENSOR_TELENANO 0x03 +#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 struct ao_telemetry_sensor { uint16_t serial; /* 0 */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index c2a7cd64..28b9869f 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -32,6 +32,10 @@ #error Please define HAS_USB #endif +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ @@ -83,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL +#if HAS_ACCEL && 0 if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -101,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL +#if HAS_ACCEL && 0 && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && 0 /* Disable the USB controller in flight mode * to save power */ @@ -120,7 +124,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO && !defined (MEGAMETRUM) +#if HAS_TELEMETRY /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -171,7 +175,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +263,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 6e8fc02f..5857c44d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,6 +35,10 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 +#if defined(MEGAMETRUM) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#endif + #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif @@ -53,7 +57,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; @@ -64,7 +68,7 @@ ao_send_sensor(void) #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.pres = ao_data_pres(packet); telemetry.sensor.temp = packet->adc.temp; telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 054855ba..5c641e9a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -64,12 +64,13 @@ ALTOS_SRC = \ ao_log_mega.c \ ao_sample_mm.c \ ao_kalman.c \ - ao_flight_mm.c + ao_flight_mm.c \ + ao_telemetry.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM -IDPRODUCT=0x000a +IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 628c5538..dc9c0d19 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -47,6 +47,7 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); + ao_telemetry_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5121ad58..5c5c5972 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -66,6 +66,7 @@ #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 +#define HAS_TELEMETRY 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 -- cgit v1.2.3 From 976a8375932ddb46ca3100863b0a892732c0923e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:04:53 -0700 Subject: altos: make cc1120 ao_radio_send re-entrant It gets called from multiple tasks, so put local data on the stack. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 231d14d4..67a36c5c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -27,6 +27,12 @@ uint8_t ao_radio_abort; #define CC1120_DEBUG 1 #define CC1120_TRACE 0 +#if CC1120_TRACE +#define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n) +#else +#define fec_dump_bytes(b,l,n) +#endif + uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -330,33 +336,29 @@ void ao_radio_send(void *d, uint8_t size) { uint8_t marc_status; - static uint8_t prepare[128]; + uint8_t prepare[size + AO_FEC_PREPARE_EXTRA]; uint8_t prepare_len; - static uint8_t encode[256]; + uint8_t encode[sizeof(prepare) * 2]; uint8_t encode_len; - static uint8_t interleave[256]; + uint8_t interleave[sizeof(encode)]; uint8_t interleave_len; - ao_fec_dump_bytes(d, size, "Input"); + fec_dump_bytes(d, size, "Input"); -#if 1 prepare_len = ao_fec_prepare(d, size, prepare); - ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + fec_dump_bytes(prepare, prepare_len, "Prepare"); ao_fec_whiten(prepare, prepare_len, prepare); - ao_fec_dump_bytes(prepare, prepare_len, "Whiten"); + fec_dump_bytes(prepare, prepare_len, "Whiten"); encode_len = ao_fec_encode(prepare, prepare_len, encode); - ao_fec_dump_bytes(encode, encode_len, "Encode"); + fec_dump_bytes(encode, encode_len, "Encode"); interleave_len = ao_fec_interleave(encode, encode_len, interleave); - ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + fec_dump_bytes(interleave, interleave_len, "Interleave"); + ao_radio_get(interleave_len); ao_radio_fifo_write(interleave, interleave_len); -#else - ao_radio_get(size); - ao_radio_fifo_write(d, size); -#endif ao_radio_wake = 0; -- cgit v1.2.3 From ae3662c56effda9f0516c7d6ffd2d5f56b859593 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:06:08 -0700 Subject: altos: hack STM serial number to 58 otherwise altosui won't record telemetry Signed-off-by: Keith Packard --- src/stm/ao_romconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index bbb677e2..84317458 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -17,4 +17,4 @@ #include "ao.h" -const uint16_t ao_serial_number = 0; +const uint16_t ao_serial_number = 58; -- cgit v1.2.3 From 611f37607fadcdc9908d67456f844a452ad4a87a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:11:35 -0700 Subject: altos: Make sure ao_storage_config is set before reading config block ao_storage_read does in fact call ao_storage_setup, but we need the value of ao_storage_config *before* calling ao_storage_read, so call ao_storage_setup first. Signed-off-by: Keith Packard --- src/core/ao_config.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a4877b06..cc580d66 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,6 +81,11 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM + /* Yes, I know ao_storage_read calls ao_storage_setup, + * but ao_storage_setup *also* sets ao_storage_config, which we + * need before calling ao_storage_read here + */ + ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From 419a801131c1034f1fa149a67850290431cbda72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:39:10 -0700 Subject: altos: Configure STM LCD driver for giant LCD digits These devices require static mode. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 2 +- src/stm/ao_lcd_stm.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 232c2313..73ace558 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -166,7 +166,7 @@ main(void) ao_timer_init(); ao_dma_init(); ao_cmd_init(); -// ao_lcd_stm_init(); + ao_lcd_stm_init(); // ao_lcd_font_init(); ao_spi_init(); ao_i2c_init(); diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index f68cf165..b1909444 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -328,10 +328,14 @@ ao_lcd_stm_init(void) } } + /* Disable the LCD */ + stm_lcd.cr = 0; + /* duty cycle 1/3, radio 352, frame rate about 33Hz */ - stm_lcd.fcr = ((STM_LCD_FCR_PS_1 << STM_LCD_FCR_PS) | - (STM_LCD_FCR_DIV_31 << STM_LCD_FCR_DIV) | + stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) | + (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) | (4 << STM_LCD_FCR_CC) | + (0 << STM_LCD_FCR_DEAD) | (4 << STM_LCD_FCR_PON) | (0 << STM_LCD_FCR_UDDIE) | (0 << STM_LCD_FCR_SOFIE) | @@ -343,8 +347,8 @@ ao_lcd_stm_init(void) /* Program desired BIAS in LCD_CR */ /* Enable mux seg */ /* Internal voltage source */ - stm_lcd.cr = ((STM_LCD_CR_DUTY_1_4 << STM_LCD_CR_DUTY) | - (STM_LCD_CR_BIAS_1_3 << STM_LCD_CR_BIAS) | + stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) | + (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) | (0 << STM_LCD_CR_VSEL) | (1 << STM_LCD_CR_MUX_SEG)); -- cgit v1.2.3 From d2bd95edb6f77daeb1e8f043c4a239c248728e0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:45:42 -0700 Subject: altos: Add full MM telemetry Create two new telemetry packets to hold all of the MM data. This patch also splits the telemetry structures out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 177 +----------------------------------------------- src/core/ao_data.h | 33 +++++---- src/core/ao_log_mega.c | 4 +- src/core/ao_sample_mm.c | 5 +- src/core/ao_telemetry.c | 135 +++++++++++++++++++++++++++++------- src/stm/ao_adc_stm.c | 2 +- 6 files changed, 138 insertions(+), 218 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index 3dae8b40..204c8530 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -325,182 +325,7 @@ ao_spi_slave_init(void); void ao_spi_slave(void); -/* - * ao_telemetry.c - */ -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#if LEGACY_MONITOR -#define AO_MAX_TELEMETRY 128 -#else -#define AO_MAX_TELEMETRY 32 -#endif - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 -#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10â·) */ - int32_t longitude; /* 12 longitude (degrees * 10â·) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -#define AO_TELEMETRY_COMPANION 0x07 - -#define AO_COMPANION_MAX_CHANNELS 12 - -struct ao_telemetry_companion { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t board_id; /* 5 */ - - uint8_t update_period; /* 6 */ - uint8_t channels; /* 7 */ - uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ - /* 32 */ -}; - -/* #define AO_SEND_ALL_BARO */ - -#define AO_TELEMETRY_BARO 0x80 - -/* - * This packet allows the full sampling rate baro - * data to be captured over the RF link so that the - * flight software can be tested using 'real' data. - * - * Along with this telemetry packet, the flight - * code is modified to send full-rate telemetry all the time - * and never send an RDF tone; this ensure that the full radio - * link is available. - */ -struct ao_telemetry_baro { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t samples; /* 5 number samples */ - - int16_t baro[12]; /* 6 samples */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; - struct ao_telemetry_companion companion; - struct ao_telemetry_baro baro; -}; - -struct ao_telemetry_all_recv { - union ao_telemetry_all telemetry; - int8_t rssi; - uint8_t status; -}; - +#include /* * ao_gps.c */ diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 502df6c9..fdc49ca2 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -36,7 +36,8 @@ struct ao_data { struct ao_adc adc; #endif #if HAS_MS5607 - struct ao_ms5607_sample ms5607; + struct ao_ms5607_sample ms5607_raw; + struct ao_ms5607_value ms5607_cooked; #endif #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; @@ -57,25 +58,24 @@ extern volatile __data uint8_t ao_data_head; typedef int32_t pres_t; typedef int32_t alt_t; -static inline pres_t ao_data_pres(struct ao_data *packet) -{ - struct ao_ms5607_value value; +#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked) - ao_ms5607_convert(&packet->ms5607, &value); - return value.pres; -} +#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres) +#define ao_data_temp(packet) ((packet)->ms5607_cooked.temp) #define pres_to_altitude(p) ao_pa_to_altitude(p) -#else +#else /* HAS_MS5607 */ typedef int16_t pres_t; typedef int16_t alt_t; #define ao_data_pres(packet) ((packet)->adc.pres) +#define ao_data_temp(packet) ((packet)->adc.temp) #define pres_to_altitude(p) ao_pres_to_altitude(p) +#define ao_data_pres_cook(p) -#endif +#endif /* else HAS_MS5607 */ /* * Need a few macros to pull data from the sensors: @@ -92,11 +92,11 @@ typedef int16_t accel_t; /* MPU6000 is hooked up so that positive y is positive acceleration */ #define ao_data_accel(packet) ((packet)->mpu6000.accel_y) -#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) #define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) #define ao_data_accel_invert(a) (-(a)) -#else +#else /* HAS_MPU6000 && !HAS_HIGHG_ACCEL */ typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) @@ -183,13 +183,18 @@ typedef int16_t accel_t; * provides 11 bits of data, we haven't actually lost any precision, * just dropped a bit of noise off the low end. */ + #if HAS_ACCEL_REF -#define ao_data_accel_sample(packet) \ + +#define ao_data_accel_cook(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) + #else -#define ao_data_accel_sample(packet) ((packet)->adc.accel) + +#define ao_data_accel_cook(packet) ((packet)->adc.accel) + #endif /* HAS_ACCEL_REF */ -#endif /* else some other pressure sensor */ +#endif /* else some other accel sensor */ #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 68e2af49..e7c2b0d9 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,8 +112,8 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; - log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c index 8cfadc40..ac11eef0 100644 --- a/src/core/ao_sample_mm.c +++ b/src/core/ao_sample_mm.c @@ -101,11 +101,14 @@ ao_sample(void) /* Capture a sample */ ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); ao_sample_pres = ao_data_pres(ao_data); ao_sample_alt = pres_to_altitude(ao_sample_pres); ao_sample_height = ao_sample_alt - ao_ground_height; + #if HAS_ACCEL - ao_sample_accel = ao_data_accel_sample(ao_data); + ao_sample_accel = ao_data_accel_cook(ao_data); if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = ao_data_accel_invert(ao_sample_accel); ao_data_set_accel(ao_data, ao_sample_accel); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 5857c44d..9000a149 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -19,16 +19,6 @@ #include "ao_product.h" static __pdata uint16_t ao_telemetry_interval; -static __pdata int8_t ao_telemetry_config_max; -static __pdata int8_t ao_telemetry_config_cur; -#if HAS_GPS -static __pdata int8_t ao_telemetry_loc_cur; -static __pdata int8_t ao_telemetry_sat_cur; -#endif -#if HAS_COMPANION -static __pdata int8_t ao_telemetry_companion_max; -static __pdata int8_t ao_telemetry_companion_cur; -#endif static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; @@ -36,7 +26,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_LENGTH_MS 500 #if defined(MEGAMETRUM) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#define AO_SEND_MEGA 1 #endif #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) @@ -53,6 +43,7 @@ static __pdata uint16_t ao_rdf_time; static __xdata union ao_telemetry_all telemetry; +#if defined AO_TELEMETRY_SENSOR /* Send sensor packet */ static void ao_send_sensor(void) @@ -96,10 +87,78 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +#endif -static uint8_t ao_baro_sample; + +#ifdef AO_SEND_MEGA +/* Send mega sensor packet */ +static void +ao_send_mega_sensor(void) +{ + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; + + telemetry.mega_sensor.accel = ao_data_accel(packet); + telemetry.mega_sensor.pres = ao_data_pres(packet); + telemetry.mega_sensor.temp = ao_data_temp(packet); + + telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; + telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; + telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; + + telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; + telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; + telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; + + telemetry.mega_sensor.mag_x = packet->hmc5883.x; + telemetry.mega_sensor.mag_y = packet->hmc5883.y; + telemetry.mega_sensor.mag_z = packet->hmc5883.z; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static __pdata int8_t ao_telemetry_mega_data_max; +static __pdata int8_t ao_telemetry_mega_data_cur; + +/* Send mega data packet */ +static void +ao_send_mega_data(void) +{ + if (--ao_telemetry_mega_data_cur <= 0) { + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + uint8_t i; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_DATA; + + telemetry.mega_data.state = ao_flight_state; + telemetry.mega_data.v_batt = packet->adc.v_batt; + telemetry.mega_data.v_pyro = packet->adc.v_pbatt; + + /* XXX figure out right shift value; 4 might suffice */ + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + + telemetry.mega_data.ground_pres = ao_ground_pres; + telemetry.mega_data.ground_accel = ao_ground_accel; + telemetry.mega_data.accel_plus_g = ao_config.accel_plus_g; + telemetry.mega_data.accel_minus_g = ao_config.accel_minus_g; + + telemetry.mega_data.acceleration = ao_accel; + telemetry.mega_data.speed = ao_speed; + telemetry.mega_data.height = ao_height; + + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_mega_data_cur = ao_telemetry_mega_data_max; + } +} +#endif /* AO_SEND_MEGA */ #ifdef AO_SEND_ALL_BARO +static uint8_t ao_baro_sample; + static void ao_send_baro(void) { @@ -121,6 +180,9 @@ ao_send_baro(void) } #endif +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; + static void ao_send_configuration(void) { @@ -146,6 +208,10 @@ ao_send_configuration(void) } #if HAS_GPS + +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; + static void ao_send_location(void) { @@ -181,6 +247,10 @@ ao_send_satellite(void) #endif #if HAS_COMPANION + +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; + static void ao_send_companion(void) { @@ -223,7 +293,13 @@ ao_telemetry(void) #ifdef AO_SEND_ALL_BARO ao_send_baro(); #endif +#ifdef AO_SEND_MEGA + ao_send_mega_sensor(); + ao_send_mega_data(); +#else ao_send_sensor(); +#endif + #if HAS_COMPANION if (ao_companion_running) ao_send_companion(); @@ -257,31 +333,42 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { + uint8_t cur = 0; ao_telemetry_interval = interval; + +#if AO_SEND_MEGA + if (interval > 1) + ao_telemetry_mega_data_max = 1; + else + ao_telemetry_mega_data_max = 2; + if (ao_telemetry_mega_data_max > cur) + cur++; + ao_telemetry_mega_data_cur = cur; +#endif #if HAS_COMPANION if (!ao_companion_setup.update_period) ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); ao_telemetry_companion_max = ao_companion_setup.update_period / interval; - ao_telemetry_companion_cur = 1; + if (ao_telemetry_companion_max > cur) + cur++; + ao_telemetry_companion_cur = cur; #endif ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; #if HAS_COMPANION - ao_telemetry_config_cur = ao_telemetry_companion_cur; - if (ao_telemetry_config_max > ao_telemetry_config_cur) - ao_telemetry_config_cur++; -#else - ao_telemetry_config_cur = 1; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_config_cur = cur; #endif #if HAS_GPS - ao_telemetry_loc_cur = ao_telemetry_config_cur; - if (ao_telemetry_config_max > ao_telemetry_loc_cur) - ao_telemetry_loc_cur++; - ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max > ao_telemetry_sat_cur) - ao_telemetry_sat_cur++; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_loc_cur = cur; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_sat_cur = cur; #endif ao_wakeup(&telemetry); } diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 71299de9..ed1d20c9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -60,7 +60,7 @@ static void ao_adc_done(int index) #if HAS_MS5607 if (!ao_ms5607_valid) step = 0; - ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; #endif #if HAS_HMC5883 if (!ao_hmc5883_valid) -- cgit v1.2.3 From ff5b0ba90e73a83360a2e8a7e9969ed2c3ce1514 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:46:50 -0700 Subject: altos: Crank down STM SPI speed for MM The cc1120 is noisy enough to break SPI data transfers at 4MHz, so crank things down to 1MHz. It's "stable" now, but clearly needs a filter and shorter traces. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 8784d985..d3378648 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -282,7 +282,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_8 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 6f421818fd7062f03bfaf9e606d6a4cfdcb13b49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:50:18 -0700 Subject: altosui: Support MM telemetry packets Required restructuring the whole telemetry system to provide abstract interfaces to flight data. Signed-off-by: Keith Packard --- altoslib/AltosEepromIterable.java | 10 +- altoslib/AltosEepromMegaIterable.java | 32 ++-- altoslib/AltosLib.java | 20 +++ altoslib/AltosMs5607.java | 7 + altoslib/AltosRecord.java | 225 +++++++-------------------- altoslib/AltosRecordMM.java | 186 ++++++++++++++++++++++ altoslib/AltosRecordTM.java | 199 +++++++++++++++++++++++ altoslib/AltosTelemetry.java | 2 +- altoslib/AltosTelemetryIterable.java | 6 +- altoslib/AltosTelemetryRecord.java | 8 +- altoslib/AltosTelemetryRecordLegacy.java | 8 +- altoslib/AltosTelemetryRecordMegaData.java | 96 ++++++++++++ altoslib/AltosTelemetryRecordMegaSensor.java | 98 ++++++++++++ altoslib/AltosTelemetryRecordRaw.java | 6 +- altoslib/AltosTelemetryRecordSensor.java | 10 +- altoslib/Makefile.am | 4 + altosui/AltosCSV.java | 8 +- altosui/AltosIdleMonitorUI.java | 23 +-- 18 files changed, 735 insertions(+), 213 deletions(-) create mode 100644 altoslib/AltosRecordMM.java create mode 100644 altoslib/AltosRecordTM.java create mode 100644 altoslib/AltosTelemetryRecordMegaData.java create mode 100644 altoslib/AltosTelemetryRecordMegaSensor.java diff --git a/altoslib/AltosEepromIterable.java b/altoslib/AltosEepromIterable.java index a923d63b..f8acdc16 100644 --- a/altoslib/AltosEepromIterable.java +++ b/altoslib/AltosEepromIterable.java @@ -104,7 +104,7 @@ public class AltosEepromIterable extends AltosRecordIterable { } } - void update_state(AltosRecord state, AltosEepromRecord record, EepromState eeprom) { + void update_state(AltosRecordTM state, AltosEepromRecord record, EepromState eeprom) { state.tick = record.tick; switch (record.cmd) { case AltosLib.AO_LOG_FLIGHT: @@ -237,7 +237,7 @@ public class AltosEepromIterable extends AltosRecordIterable { LinkedList list = new LinkedList(); Iterator iterator = records.iterator(); AltosOrderedRecord record = null; - AltosRecord state = new AltosRecord(); + AltosRecordTM state = new AltosRecordTM(); boolean last_reported = false; EepromState eeprom = new EepromState(); @@ -254,13 +254,13 @@ public class AltosEepromIterable extends AltosRecordIterable { while (iterator.hasNext()) { record = iterator.next(); if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); + AltosRecordTM r = state.clone(); r.time = (r.tick - eeprom.boost_tick) / 100.0; list.add(r); } update_state(state, record, eeprom); } - AltosRecord r = new AltosRecord(state); + AltosRecordTM r = state.clone(); r.time = (r.tick - eeprom.boost_tick) / 100.0; list.add(r); return list; @@ -399,7 +399,7 @@ public class AltosEepromIterable extends AltosRecordIterable { try { for (;;) { - String line = AltosRecord.gets(input); + String line = AltosLib.gets(input); if (line == null) break; AltosOrderedRecord record = new AltosOrderedRecord(line, index++, prev_tick, prev_tick_valid); diff --git a/altoslib/AltosEepromMegaIterable.java b/altoslib/AltosEepromMegaIterable.java index 28a298b3..f62cc45b 100644 --- a/altoslib/AltosEepromMegaIterable.java +++ b/altoslib/AltosEepromMegaIterable.java @@ -108,7 +108,7 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { } } - void update_state(AltosRecord state, AltosEepromMega record, EepromState eeprom) { + void update_state(AltosRecordMM state, AltosEepromMega record, EepromState eeprom) { state.tick = record.tick; switch (record.cmd) { case AltosLib.AO_LOG_FLIGHT: @@ -122,7 +122,8 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { break; case AltosLib.AO_LOG_SENSOR: state.accel = record.accel(); - state.pres = baro.set(record.pres(), record.temp()); + baro.set(record.pres(), record.temp()); + state.pres = baro.pa; state.temp = baro.cc; state.imu = new AltosIMU(); state.imu.accel_x = record.accel_x(); @@ -161,15 +162,20 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { eeprom.seen |= seen_sensor; break; case AltosLib.AO_LOG_TEMP_VOLT: - state.batt = record.v_batt(); + state.v_batt = record.v_batt(); + state.v_pyro = record.v_pbatt(); + for (int i = 0; i < AltosRecordMM.num_sense; i++) + state.sense[i] = record.sense(i); eeprom.seen |= seen_temp_volt; break; - case AltosLib.AO_LOG_DEPLOY: - state.drogue = record.a; - state.main = record.b; - eeprom.seen |= seen_deploy; - has_ignite = true; - break; +// +// case AltosLib.AO_LOG_DEPLOY: +// state.drogue = record.a; +// state.main = record.b; +// eeprom.seen |= seen_deploy; +// has_ignite = true; +// break; + case AltosLib.AO_LOG_STATE: state.state = record.state(); break; @@ -278,7 +284,7 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { LinkedList list = new LinkedList(); Iterator iterator = records.iterator(); AltosOrderedMegaRecord record = null; - AltosRecord state = new AltosRecord(); + AltosRecordMM state = new AltosRecordMM(); boolean last_reported = false; EepromState eeprom = new EepromState(); @@ -295,13 +301,13 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { while (iterator.hasNext()) { record = iterator.next(); if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { - AltosRecord r = new AltosRecord(state); + AltosRecordMM r = state.clone(); r.time = (r.tick - eeprom.boost_tick) / 100.0; list.add(r); } update_state(state, record, eeprom); } - AltosRecord r = new AltosRecord(state); + AltosRecordMM r = state.clone(); r.time = (r.tick - eeprom.boost_tick) / 100.0; list.add(r); return list; @@ -442,7 +448,7 @@ public class AltosEepromMegaIterable extends AltosRecordIterable { try { for (;;) { - String line = AltosRecord.gets(input); + String line = AltosLib.gets(input); if (line == null) break; AltosOrderedMegaRecord record = new AltosOrderedMegaRecord(line, index++, prev_tick, prev_tick_valid); diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 4a779c55..2402331e 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -20,6 +20,7 @@ package org.altusmetrum.AltosLib; import java.awt.*; import java.util.*; import java.text.*; +import java.io.*; import java.nio.charset.Charset; public class AltosLib { @@ -304,6 +305,10 @@ public class AltosLib { (bytes[i+3] << 24); } + public static int int32(int[] bytes, int i) { + return (int) uint32(bytes, i); + } + public static final Charset unicode_set = Charset.forName("UTF-8"); public static String string(int[] bytes, int s, int l) { @@ -375,6 +380,21 @@ public class AltosLib { return v * sign; } + public static String gets(FileInputStream s) throws IOException { + int c; + String line = ""; + + while ((c = s.read()) != -1) { + if (c == '\r') + continue; + if (c == '\n') { + return line; + } + line = line + (char) c; + } + return null; + } + public static String replace_extension(String input, String extension) { int dot = input.lastIndexOf("."); if (dot > 0) diff --git a/altoslib/AltosMs5607.java b/altoslib/AltosMs5607.java index a7b902e2..5fd997d8 100644 --- a/altoslib/AltosMs5607.java +++ b/altoslib/AltosMs5607.java @@ -73,4 +73,11 @@ public class AltosMs5607 { convert(); return pa; } + + public AltosMs5607() { + raw_pres = AltosRecord.MISSING; + raw_temp = AltosRecord.MISSING; + pa = AltosRecord.MISSING; + cc = AltosRecord.MISSING; + } } diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index 10ef3061..e468f84b 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -22,8 +22,7 @@ import java.text.*; import java.util.HashMap; import java.io.*; -public class AltosRecord implements Comparable { - public final static int MISSING = 0x7fffffff; +public class AltosRecord implements Comparable , Cloneable { public static final int seen_flight = 1; public static final int seen_sensor = 2; @@ -33,8 +32,13 @@ public class AltosRecord implements Comparable { public static final int seen_gps_lat = 32; public static final int seen_gps_lon = 64; public static final int seen_companion = 128; - public int seen; + public int seen; + + public final static int MISSING = 0x7fffffff; + + /* Every AltosRecord implementation provides these fields */ + public int version; public String callsign; public int serial; @@ -44,31 +48,13 @@ public class AltosRecord implements Comparable { public int state; public int tick; - public int accel; - public int pres; - public int temp; - public int batt; - public int drogue; - public int main; - - public int ground_accel; - public int ground_pres; - public int accel_plus_g; - public int accel_minus_g; - - public double acceleration; - public double speed; - public double height; - - public int flight_accel; - public int flight_vel; - public int flight_pres; + /* Current flight dynamic state */ + public double acceleration; /* m/s² */ + public double speed; /* m/s */ + public double height; /* m */ public AltosGPS gps; - public boolean new_gps; - - public AltosIMU imu; - public AltosMag mag; + public boolean new_gps; public double time; /* seconds since boost */ @@ -83,45 +69,42 @@ public class AltosRecord implements Comparable { public AltosRecordCompanion companion; /* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: + * Abstract methods that convert record data + * to standard units: * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + * pressure: Pa + * voltage: V + * acceleration: m/s² + * speed: m/s + * height: m + * temperature: °C */ - public static final double counts_per_kPa = 27 * 2047 / 3300; - public static final double counts_at_101_3kPa = 1674.0; + public double raw_pressure() { return MISSING; } - public static double - barometer_to_pressure(double count) - { - return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; - } + public double filtered_pressure() { return MISSING; } - public double raw_pressure() { - if (pres == MISSING) - return MISSING; - return barometer_to_pressure(pres); - } + public double ground_pressure() { return MISSING; } - public double filtered_pressure() { - if (flight_pres == MISSING) - return MISSING; - return barometer_to_pressure(flight_pres); - } + public double battery_voltage() { return MISSING; } - public double ground_pressure() { - if (ground_pres == MISSING) - return MISSING; - return barometer_to_pressure(ground_pres); - } + public double main_voltage() { return MISSING; } + + public double drogue_voltage() { return MISSING; } + + public double temperature() { return MISSING; } + + public double acceleration() { return MISSING; } + + public double accel_speed() { return MISSING; } + + public AltosIMU imu() { return null; } + + public AltosMag mag() { return null; } + + /* + * Convert various pressure values to altitude + */ public double raw_altitude() { double p = raw_pressure(); @@ -138,8 +121,9 @@ public class AltosRecord implements Comparable { } public double filtered_altitude() { - if (height != MISSING && ground_pres != MISSING) - return height + ground_altitude(); + double ga = ground_altitude(); + if (height != MISSING && ga != MISSING) + return height + ga; double p = filtered_pressure(); if (p == MISSING) @@ -167,94 +151,17 @@ public class AltosRecord implements Comparable { return r - g; } - public double battery_voltage() { - if (batt == MISSING) - return MISSING; - return AltosConvert.cc_battery_to_voltage(batt); - } - - public double main_voltage() { - if (main == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(main); - } - - public double drogue_voltage() { - if (drogue == MISSING) - return MISSING; - return AltosConvert.cc_ignitor_to_voltage(drogue); - } - - /* Value for the CC1111 built-in temperature sensor - * Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - */ - - public static double - thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - - public double temperature() { - if (temp == MISSING) - return MISSING; - return thermometer_to_temperature(temp); - } - - public double accel_counts_per_mss() { - double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; - - return counts_per_g / 9.80665; - } - - public double acceleration() { - if (acceleration != MISSING) - return acceleration; - - if (ground_accel == MISSING || accel == MISSING) - return MISSING; - return (ground_accel - accel) / accel_counts_per_mss(); - } - - public double accel_speed() { - if (speed != MISSING) - return speed; - if (flight_vel == MISSING) - return MISSING; - return flight_vel / (accel_counts_per_mss() * 100.0); - } - public String state() { return AltosLib.state_name(state); } - public static String gets(FileInputStream s) throws IOException { - int c; - String line = ""; - - while ((c = s.read()) != -1) { - if (c == '\r') - continue; - if (c == '\n') { - return line; - } - line = line + (char) c; - } - return null; - } - public int compareTo(AltosRecord o) { return tick - o.tick; } - public AltosRecord(AltosRecord old) { - version = old.version; + public void copy(AltosRecord old) { seen = old.seen; + version = old.version; callsign = old.callsign; serial = old.serial; flight = old.flight; @@ -262,32 +169,27 @@ public class AltosRecord implements Comparable { status = old.status; state = old.state; tick = old.tick; - accel = old.accel; - pres = old.pres; - temp = old.temp; - batt = old.batt; - drogue = old.drogue; - main = old.main; - flight_accel = old.flight_accel; - ground_accel = old.ground_accel; - flight_vel = old.flight_vel; - flight_pres = old.flight_pres; - ground_pres = old.ground_pres; - accel_plus_g = old.accel_plus_g; - accel_minus_g = old.accel_minus_g; acceleration = old.acceleration; speed = old.speed; height = old.height; gps = new AltosGPS(old.gps); new_gps = false; companion = old.companion; - imu = old.imu; - mag = old.mag; + } + + public AltosRecord clone() { + try { + AltosRecord n = (AltosRecord) super.clone(); + n.copy(this); + return n; + } catch (CloneNotSupportedException e) { + return null; + } } public AltosRecord() { - version = 0; seen = 0; + version = 0; callsign = "N0CALL"; serial = 0; flight = 0; @@ -295,19 +197,6 @@ public class AltosRecord implements Comparable { status = 0; state = AltosLib.ao_flight_startup; tick = 0; - accel = MISSING; - pres = MISSING; - temp = MISSING; - batt = MISSING; - drogue = MISSING; - main = MISSING; - flight_accel = 0; - ground_accel = 0; - flight_vel = 0; - flight_pres = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; acceleration = MISSING; speed = MISSING; height = MISSING; diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java new file mode 100644 index 00000000..8b3d745a --- /dev/null +++ b/altoslib/AltosRecordMM.java @@ -0,0 +1,186 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosRecordMM extends AltosRecord { + + public int accel; + public int pres; + public int temp; + + public int v_batt; + public int v_pyro; + public int sense[]; + + public int ground_accel; + public int ground_pres; + public int accel_plus_g; + public int accel_minus_g; + + public int flight_accel; + public int flight_vel; + public int flight_pres; + + public final static int num_sense = 6; + + public AltosIMU imu; + public AltosMag mag; + + static double adc(int raw) { + return raw / 4095.0; + } + + public double raw_pressure() { + if (pres != MISSING) + return pres / 100.0; + return MISSING; + } + + public double filtered_pressure() { + return raw_pressure(); + } + + public double ground_pressure() { + if (ground_pres != MISSING) + return ground_pres / 100.0; + return MISSING; + } + + public double battery_voltage() { + if (v_batt != MISSING) + return 3.3 * adc(v_batt) * 27.0 / (15.0 + 27.0); + return MISSING; + } + + static double pyro(int raw) { + if (raw != MISSING) + return 3.3 * adc(raw) * 27.0 / (100.0 + 27.0); + return MISSING; + } + + public double main_voltage() { + return pyro(sense[1]); + } + + public double drogue_voltage() { + return pyro(sense[0]); + } + + public double temperature() { + if (temp != MISSING) + return temp / 100.0; + return MISSING; + } + + public AltosIMU imu() { return imu; } + + public AltosMag mag() { return mag; } + + double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + + public double acceleration() { + System.out.printf("MM record acceleration %g ground_accel %d accel %d accel_minus_g %d accel_plus_g %d\n", + acceleration, ground_accel, accel, accel_minus_g, accel_plus_g); + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; + + if (accel_minus_g == MISSING || accel_plus_g == MISSING) + return MISSING; + + return (ground_accel - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + return speed; + } + + public void copy (AltosRecordMM old) { + super.copy(old); + + accel = old.accel; + pres = old.pres; + temp = old.temp; + + v_batt = old.v_batt; + v_pyro = old.v_pyro; + sense = new int[num_sense]; + + for (int i = 0; i < num_sense; i++) + sense[i] = old.sense[i]; + + ground_accel = old.ground_accel; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + + flight_accel = old.flight_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + + imu = old.imu; + mag = old.mag; + } + + public AltosRecordMM clone() { + AltosRecordMM n = (AltosRecordMM) super.clone(); + n.copy(this); + return n; + } + + void make_missing() { + + accel = MISSING; + pres = MISSING; + temp = MISSING; + + v_batt = MISSING; + v_pyro = MISSING; + sense = new int[num_sense]; + for (int i = 0; i < num_sense; i++) + sense[i] = MISSING; + + ground_accel = MISSING; + ground_pres = MISSING; + accel_plus_g = MISSING; + accel_minus_g = MISSING; + + flight_accel = 0; + flight_vel = 0; + flight_pres = 0; + + imu = new AltosIMU(); + mag = new AltosMag(); + } + + public AltosRecordMM(AltosRecord old) { + super.copy(old); + make_missing(); + } + + public AltosRecordMM() { + super(); + make_missing(); + } +} diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java new file mode 100644 index 00000000..afb70790 --- /dev/null +++ b/altoslib/AltosRecordTM.java @@ -0,0 +1,199 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +public class AltosRecordTM extends AltosRecord { + public int accel; + public int pres; + public int temp; + public int batt; + public int drogue; + public int main; + + public int ground_accel; + public int ground_pres; + public int accel_plus_g; + public int accel_minus_g; + + public int flight_accel; + public int flight_vel; + public int flight_pres; + + /* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + + static final double counts_per_kPa = 27 * 2047 / 3300; + static final double counts_at_101_3kPa = 1674.0; + + static double + barometer_to_pressure(double count) + { + return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; + } + + public double raw_pressure() { + if (pres == MISSING) + return MISSING; + return barometer_to_pressure(pres); + } + + public double filtered_pressure() { + if (flight_pres == MISSING) + return MISSING; + return barometer_to_pressure(flight_pres); + } + + public double ground_pressure() { + if (ground_pres == MISSING) + return MISSING; + return barometer_to_pressure(ground_pres); + } + + public double battery_voltage() { + if (batt == MISSING) + return MISSING; + return AltosConvert.cc_battery_to_voltage(batt); + } + + public double main_voltage() { + if (main == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(main); + } + + public double drogue_voltage() { + if (drogue == MISSING) + return MISSING; + return AltosConvert.cc_ignitor_to_voltage(drogue); + } + + /* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + public double temperature() { + if (temp == MISSING) + return MISSING; + return thermometer_to_temperature(temp); + } + + double accel_counts_per_mss() { + double counts_per_g = Math.abs(accel_minus_g - accel_plus_g) / 2; + + return counts_per_g / 9.80665; + } + + public double acceleration() { + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; + return (ground_accel - accel) / accel_counts_per_mss(); + } + + public double accel_speed() { + if (speed != MISSING) + return speed; + if (flight_vel == MISSING) + return MISSING; + return flight_vel / (accel_counts_per_mss() * 100.0); + } + + public void copy(AltosRecordTM old) { + super.copy(old); + + version = old.version; + callsign = old.callsign; + serial = old.serial; + flight = old.flight; + rssi = old.rssi; + status = old.status; + state = old.state; + tick = old.tick; + accel = old.accel; + pres = old.pres; + temp = old.temp; + batt = old.batt; + drogue = old.drogue; + main = old.main; + flight_accel = old.flight_accel; + ground_accel = old.ground_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + ground_pres = old.ground_pres; + accel_plus_g = old.accel_plus_g; + accel_minus_g = old.accel_minus_g; + } + + public AltosRecordTM clone() { + AltosRecordTM n = (AltosRecordTM) super.clone(); + n.copy(this); + return n; + } + + void make_missing() { + accel = MISSING; + pres = MISSING; + temp = MISSING; + batt = MISSING; + drogue = MISSING; + main = MISSING; + + flight_accel = 0; + flight_vel = 0; + flight_pres = 0; + + ground_accel = 0; + ground_pres = 0; + accel_plus_g = 0; + accel_minus_g = 0; + } + + public AltosRecordTM(AltosRecord old) { + super.copy(old); + make_missing(); + } + + public AltosRecordTM() { + super(); + make_missing(); + } +} diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 04abb1f3..ee244824 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -84,7 +84,7 @@ import java.util.HashMap; * */ -public class AltosTelemetry extends AltosRecord { +public abstract class AltosTelemetry extends AltosRecord { /* * General header fields diff --git a/altoslib/AltosTelemetryIterable.java b/altoslib/AltosTelemetryIterable.java index f4b4029f..e95c15e0 100644 --- a/altoslib/AltosTelemetryIterable.java +++ b/altoslib/AltosTelemetryIterable.java @@ -45,7 +45,7 @@ public class AltosTelemetryIterable extends AltosRecordIterable { try { for (;;) { - String line = AltosRecord.gets(input); + String line = AltosLib.gets(input); if (line == null) { break; } @@ -67,11 +67,11 @@ public class AltosTelemetryIterable extends AltosRecordIterable { saw_boost = true; boost_tick = record.tick; } - if (record.accel != AltosRecord.MISSING) + if (record.acceleration() != AltosRecord.MISSING) has_accel = true; if (record.gps != null) has_gps = true; - if (record.main != AltosRecord.MISSING) + if (record.main_voltage() != AltosRecord.MISSING) has_ignite = true; if (previous != null && previous.tick != record.tick) records.add(previous); diff --git a/altoslib/AltosTelemetryRecord.java b/altoslib/AltosTelemetryRecord.java index 6b6a252d..6a8cfd35 100644 --- a/altoslib/AltosTelemetryRecord.java +++ b/altoslib/AltosTelemetryRecord.java @@ -43,6 +43,7 @@ public abstract class AltosTelemetryRecord { final static int packet_type_satellite = 0x06; final static int packet_type_companion = 0x07; final static int packet_type_MM_sensor = 0x08; + final static int packet_type_MM_data = 0x09; static AltosTelemetryRecord parse_hex(String hex) throws ParseException, AltosCRCException { AltosTelemetryRecord r; @@ -76,7 +77,6 @@ public abstract class AltosTelemetryRecord { case packet_type_TM_sensor: case packet_type_Tm_sensor: case packet_type_Tn_sensor: - case packet_type_MM_sensor: r = new AltosTelemetryRecordSensor(bytes, rssi); break; case packet_type_configuration: @@ -91,6 +91,12 @@ public abstract class AltosTelemetryRecord { case packet_type_companion: r = new AltosTelemetryRecordCompanion(bytes); break; + case packet_type_MM_sensor: + r = new AltosTelemetryRecordMegaSensor(bytes, rssi); + break; + case packet_type_MM_data: + r = new AltosTelemetryRecordMegaData(bytes); + break; default: r = new AltosTelemetryRecordRaw(bytes); break; diff --git a/altoslib/AltosTelemetryRecordLegacy.java b/altoslib/AltosTelemetryRecordLegacy.java index 85071d9c..3976a07a 100644 --- a/altoslib/AltosTelemetryRecordLegacy.java +++ b/altoslib/AltosTelemetryRecordLegacy.java @@ -232,7 +232,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { final static String AO_TELEM_SAT_SVID = "s_v"; final static String AO_TELEM_SAT_C_N_0 = "s_c"; - AltosRecord record; + AltosRecordTM record; private void parse_v4(String[] words, int i) throws ParseException { AltosTelemetryMap map = new AltosTelemetryMap(words, i); @@ -366,7 +366,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { String[] words = line.split("\\s+"); int i = 0; - record = new AltosRecord(); + record = new AltosRecordTM(); if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { i += 2; @@ -388,7 +388,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { } /* - * Given a hex dump of a legacy telemetry line, construct an AltosRecord from that + * Given a hex dump of a legacy telemetry line, construct an AltosRecordTM from that */ int[] bytes; @@ -422,7 +422,7 @@ public class AltosTelemetryRecordLegacy extends AltosTelemetryRecord { static final int AO_GPS_COURSE_VALID = (1 << 7); public AltosTelemetryRecordLegacy(int[] in_bytes, int in_rssi, int in_status) { - record = new AltosRecord(); + record = new AltosRecordTM(); bytes = in_bytes; record.version = 4; diff --git a/altoslib/AltosTelemetryRecordMegaData.java b/altoslib/AltosTelemetryRecordMegaData.java new file mode 100644 index 00000000..cc35cd83 --- /dev/null +++ b/altoslib/AltosTelemetryRecordMegaData.java @@ -0,0 +1,96 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + + +public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw { + + int state; + + int v_batt; + int v_pyro; + int sense[]; + + int ground_pres; + int ground_accel; + int accel_plus_g; + int accel_minus_g; + + int acceleration; + int speed; + int height; + + public AltosTelemetryRecordMegaData(int[] in_bytes) { + super(in_bytes); + + state = int8(5); + + v_batt = int16(6); + v_pyro = int16(8); + + sense = new int[6]; + + for (int i = 0; i < 6; i++) { + sense[i] = int8(10 + i) << 4; + sense[i] |= sense[i] >> 8; + } + + ground_pres = int32(16); + ground_accel = int16(20); + accel_plus_g = int16(22); + accel_minus_g = int16(24); + + acceleration = int16(26); + speed = int16(28); + height = int16(30); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord n = super.update_state(previous); + + AltosRecordMM next; + if (!(n instanceof AltosRecordMM)) { + System.out.printf("data making record MM\n"); + next = new AltosRecordMM(n); + } else { + System.out.printf ("data already has MM\n"); + next = (AltosRecordMM) n; + } + + next.state = state; + + next.v_batt = v_batt; + next.v_pyro = v_pyro; + + for (int i = 0; i < 6; i++) + next.sense[i] = sense[i]; + + next.ground_accel = ground_accel; + next.ground_pres = ground_pres; + next.accel_plus_g = accel_plus_g; + next.accel_minus_g = accel_minus_g; + + next.acceleration = acceleration / 16.0; + next.speed = speed / 16.0; + next.height = height; + + next.seen |= AltosRecord.seen_flight | AltosRecord.seen_temp_volt; + + return next; + } +} diff --git a/altoslib/AltosTelemetryRecordMegaSensor.java b/altoslib/AltosTelemetryRecordMegaSensor.java new file mode 100644 index 00000000..85a32d12 --- /dev/null +++ b/altoslib/AltosTelemetryRecordMegaSensor.java @@ -0,0 +1,98 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + + +public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { + int accel; + int pres; + int temp; + + int accel_x; + int accel_y; + int accel_z; + + int gyro_x; + int gyro_y; + int gyro_z; + + int mag_x; + int mag_y; + int mag_z; + + int rssi; + + public AltosTelemetryRecordMegaSensor(int[] in_bytes, int in_rssi) { + super(in_bytes); + + accel = int16(6); + pres = int32(8); + temp = int16(12); + + accel_x = int16(14); + accel_y = int16(16); + accel_z = int16(18); + + gyro_x = int16(20); + gyro_y = int16(22); + gyro_z = int16(24); + + mag_x = int16(26); + mag_y = int16(28); + mag_z = int16(30); + + rssi = in_rssi; + System.out.printf ("telem record accel: %d\n", accel); + } + + public AltosRecord update_state(AltosRecord previous) { + AltosRecord n = super.update_state(previous); + + AltosRecordMM next; + if (!(n instanceof AltosRecordMM)) { + System.out.printf("sensor making MM\n"); + next = new AltosRecordMM(n); + } else { + System.out.printf("sensor has MM\n"); + next = (AltosRecordMM) n; + } + + System.out.printf("telem update_state accel: %d\n", accel); + next.accel = accel; + next.pres = pres; + next.temp = temp; + + next.imu.accel_x = accel_x; + next.imu.accel_y = accel_y; + next.imu.accel_z = accel_z; + + next.imu.gyro_x = gyro_x; + next.imu.gyro_y = gyro_y; + next.imu.gyro_z = gyro_z; + + next.mag.x = mag_x; + next.mag.y = mag_y; + next.mag.z = mag_z; + + next.rssi = rssi; + + next.seen |= AltosRecord.seen_sensor; + + return next; + } +} diff --git a/altoslib/AltosTelemetryRecordRaw.java b/altoslib/AltosTelemetryRecordRaw.java index 43d0f17a..dc1b8947 100644 --- a/altoslib/AltosTelemetryRecordRaw.java +++ b/altoslib/AltosTelemetryRecordRaw.java @@ -49,6 +49,10 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { return AltosLib.uint32(bytes, off + 1); } + public int int32(int off) { + return AltosLib.int32(bytes, off + 1); + } + public String string(int off, int l) { return AltosLib.string(bytes, off + 1, l); } @@ -63,7 +67,7 @@ public class AltosTelemetryRecordRaw extends AltosTelemetryRecord { public AltosRecord update_state(AltosRecord previous) { AltosRecord next; if (previous != null) - next = new AltosRecord(previous); + next = previous.clone(); else next = new AltosRecord(); next.serial = serial; diff --git a/altoslib/AltosTelemetryRecordSensor.java b/altoslib/AltosTelemetryRecordSensor.java index cfaf90b0..319a91b3 100644 --- a/altoslib/AltosTelemetryRecordSensor.java +++ b/altoslib/AltosTelemetryRecordSensor.java @@ -61,8 +61,14 @@ public class AltosTelemetryRecordSensor extends AltosTelemetryRecordRaw { rssi = in_rssi; } - public AltosRecord update_state(AltosRecord previous) { - AltosRecord next = super.update_state(previous); + public AltosRecord update_state(AltosRecord prev) { + AltosRecord n = super.update_state(prev); + + AltosRecordTM next; + if (!(n instanceof AltosRecordTM)) + next = new AltosRecordTM(n); + else + next = (AltosRecordTM) n; next.state = state; if (type == packet_type_TM_sensor) diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index f644d46a..ac97c9cb 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -35,6 +35,8 @@ AltosLib_JAVA = \ $(SRC)/AltosRecordCompanion.java \ $(SRC)/AltosRecordIterable.java \ $(SRC)/AltosRecord.java \ + $(SRC)/AltosRecordTM.java \ + $(SRC)/AltosRecordMM.java \ $(SRC)/AltosReplayReader.java \ $(SRC)/AltosState.java \ $(SRC)/AltosTelemetry.java \ @@ -50,6 +52,8 @@ AltosLib_JAVA = \ $(SRC)/AltosTelemetryRecordRaw.java \ $(SRC)/AltosTelemetryRecordSatellite.java \ $(SRC)/AltosTelemetryRecordSensor.java \ + $(SRC)/AltosTelemetryRecordMegaSensor.java \ + $(SRC)/AltosTelemetryRecordMegaData.java \ $(SRC)/AltosMs5607.java \ $(SRC)/AltosIMU.java \ $(SRC)/AltosMag.java diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index be86a454..c876d9ca 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -146,8 +146,8 @@ public class AltosCSV implements AltosWriter { } void write_advanced(AltosRecord record) { - AltosIMU imu = record.imu; - AltosMag mag = record.mag; + AltosIMU imu = record.imu(); + AltosMag mag = record.mag(); if (imu == null) imu = new AltosIMU(); @@ -263,7 +263,7 @@ public class AltosCSV implements AltosWriter { write_general(record); out.printf(","); write_flight(record); out.printf(","); write_basic(record); out.printf(","); - if (record.imu != null || record.mag != null) + if (record.imu() != null || record.mag() != null) write_advanced(record); if (record.gps != null) { out.printf(","); @@ -287,7 +287,7 @@ public class AltosCSV implements AltosWriter { if (record.state == Altos.ao_flight_startup) return; if (!header_written) { - write_header(record.imu != null || record.mag != null, + write_header(record.imu() != null || record.mag() != null, record.gps != null, record.companion != null); header_written = true; } diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 2ee90937..949e3926 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -204,17 +204,18 @@ class AltosIdleMonitor extends Thread { record.state = Altos.ao_flight_idle; record.tick = adc.tick; - record.accel = adc.accel; - record.pres = adc.pres; - record.batt = adc.batt; - record.temp = adc.temp; - record.drogue = adc.drogue; - record.main = adc.main; - - record.ground_accel = record.accel; - record.ground_pres = record.pres; - record.accel_plus_g = config_data.accel_cal_plus; - record.accel_minus_g = config_data.accel_cal_minus; + +// record.accel = adc.accel; +// record.pres = adc.pres; +// record.batt = adc.batt; +// record.temp = adc.temp; +// record.drogue = adc.drogue; +// record.main = adc.main; + +// record.ground_accel = record.accel; +// record.ground_pres = record.pres; +// record.accel_plus_g = config_data.accel_cal_plus; +// record.accel_minus_g = config_data.accel_cal_minus; record.acceleration = 0; record.speed = 0; record.height = 0; -- cgit v1.2.3 From 0b5548d6ced67201311e1072d37fbedd3d9929c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:51:17 -0700 Subject: ao-tools: Support MM telemetry packets in ao-telem Parse the new packet formats Signed-off-by: Keith Packard --- ao-tools/ao-telem/ao-telem.c | 38 ++++++++++++++++++++++++++++++- ao-tools/lib/cc-telemetry.h | 54 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/ao-tools/ao-telem/ao-telem.c b/ao-tools/ao-telem/ao-telem.c index 384b2fc8..e7fc8e26 100644 --- a/ao-tools/ao-telem/ao-telem.c +++ b/ao-tools/ao-telem/ao-telem.c @@ -82,7 +82,6 @@ main (int argc, char **argv) case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: case AO_TELEMETRY_SENSOR_TELENANO: - case AO_TELEMETRY_SENSOR_MEGAMETRUM: printf ("state %1d accel %5d pres %5d ", telem.sensor.state, telem.sensor.accel, telem.sensor.pres); printf ("accel %6.2f speed %6.2f height %5d ", @@ -152,6 +151,43 @@ main (int argc, char **argv) telem.satellite.sats[c].c_n_1); } printf ("\n"); + break; + case AO_TELEMETRY_MEGA_SENSOR: + printf ("accel %5d pres %9d temp %5d accel_x %5d accel_y %5d accel_z %5d gyro_x %5d gyro_y %5d gyro_z %5d mag_x %5d mag_y %5d mag_z %5d\n", + telem.mega_sensor.accel, + telem.mega_sensor.pres, + telem.mega_sensor.temp, + telem.mega_sensor.accel_x, + telem.mega_sensor.accel_y, + telem.mega_sensor.accel_z, + telem.mega_sensor.gyro_x, + telem.mega_sensor.gyro_y, + telem.mega_sensor.gyro_z, + telem.mega_sensor.mag_x, + telem.mega_sensor.mag_y, + telem.mega_sensor.mag_z); + break; + case AO_TELEMETRY_MEGA_DATA: + printf ("state %1d v_batt %5d v_pyro %5d ", + telem.mega_data.state, + telem.mega_data.v_batt, + telem.mega_data.v_pyro); + for (c = 0; c < 6; c++) + printf ("s%1d %5d ", c, + telem.mega_data.sense[c] | + (telem.mega_data.sense[c] << 8)); + + printf ("ground_pres %5d ground_accel %5d accel_plus %5d accel_minus %5d ", + telem.mega_data.ground_pres, + telem.mega_data.ground_accel, + telem.mega_data.accel_plus_g, + telem.mega_data.accel_minus_g); + + printf ("accel %6.2f speed %6.2f height %5d\n", + telem.mega_data.acceleration / 16.0, + telem.mega_data.speed / 16.0, + telem.mega_data.height); + break; default: printf("\n"); diff --git a/ao-tools/lib/cc-telemetry.h b/ao-tools/lib/cc-telemetry.h index 4e064a97..e849cd3b 100644 --- a/ao-tools/lib/cc-telemetry.h +++ b/ao-tools/lib/cc-telemetry.h @@ -37,7 +37,6 @@ struct ao_telemetry_generic { #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 #define AO_TELEMETRY_SENSOR_TELEMINI 0x02 #define AO_TELEMETRY_SENSOR_TELENANO 0x03 -#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 struct ao_telemetry_sensor { uint16_t serial; /* 0 */ @@ -151,6 +150,57 @@ struct ao_telemetry_companion { /* 32 */ }; +#define AO_TELEMETRY_MEGA_SENSOR 0x08 + +struct ao_telemetry_mega_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t pad5; /* 5 */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t accel_x; /* 14 */ + int16_t accel_y; /* 16 */ + int16_t accel_z; /* 18 */ + + int16_t gyro_x; /* 20 */ + int16_t gyro_y; /* 22 */ + int16_t gyro_z; /* 24 */ + + int16_t mag_x; /* 26 */ + int16_t mag_y; /* 28 */ + int16_t mag_z; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_DATA 0x09 + +struct ao_telemetry_mega_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + + int16_t v_batt; /* 6 battery voltage */ + int16_t v_pyro; /* 8 pyro battery voltage */ + int8_t sense[6]; /* 10 continuity sense */ + + int32_t ground_pres; /* 16 average pres on pad */ + int16_t ground_accel; /* 20 average accel on pad */ + int16_t accel_plus_g; /* 22 accel calibration at +1g */ + int16_t accel_minus_g; /* 24 accel calibration at -1g */ + + int16_t acceleration; /* 26 m/s² * 16 */ + int16_t speed; /* 28 m/s * 16 */ + int16_t height; /* 30 m */ + /* 32 */ +}; + /* #define AO_SEND_ALL_BARO */ #define AO_TELEMETRY_BARO 0x80 @@ -182,6 +232,8 @@ union ao_telemetry_all { struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; struct ao_telemetry_companion companion; + struct ao_telemetry_mega_sensor mega_sensor; + struct ao_telemetry_mega_data mega_data; struct ao_telemetry_baro baro; }; -- cgit v1.2.3 From 75e4521ec42a368cebc67a07f8713d7a854ea265 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:52:37 -0700 Subject: altos: Move FEC code to core It's not a driver as it's not specific to the 1120 chip Signed-off-by: Keith Packard --- src/core/ao_fec.h | 60 ++++++++++++++++++++ src/core/ao_fec_tx.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_fec.h | 60 -------------------- src/drivers/ao_fec_tx.c | 139 ---------------------------------------------- 4 files changed, 204 insertions(+), 199 deletions(-) create mode 100644 src/core/ao_fec.h create mode 100644 src/core/ao_fec_tx.c delete mode 100644 src/drivers/ao_fec.h delete mode 100644 src/drivers/ao_fec_tx.c diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/core/ao_fec.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FEC_H_ +#define _AO_FEC_H_ + +#include + +#define AO_FEC_CRC_INIT 0xffff +#define AO_FEC_TRELLIS_TERMINATOR 0x0b +#define AO_FEC_PREPARE_EXTRA 4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c new file mode 100644 index 00000000..bf32c506 --- /dev/null +++ b/src/core/ao_fec_tx.c @@ -0,0 +1,144 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ + uint8_t i; + + printf ("%s (%d):", name, len); + for (i = 0; i < len; i++) { + if ((i & 7) == 0) + printf ("\n\t%02x:", i); + printf(" %02x", bytes[i]); + } + printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = crc_byte(*bytes++, crc); + return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t crc = ao_fec_crc (in, len); + uint8_t i; + uint8_t num_fec; + + /* Copy data */ + for (i = 0; i < len; i++) + out[i] = in[i]; + + /* Append CRC */ + out[i++] = crc >> 8; + out[i++] = crc; + + /* Append FEC -- 1 byte if odd, two bytes if even */ + num_fec = 2 - (i & 1); + while (num_fec--) + out[i++] = AO_FEC_TRELLIS_TERMINATOR; + return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ + const uint8_t *w = whiten; + + while (len--) + *out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t fec = 0, output; + uint8_t byte, bit; + + for (byte = 0; byte < len; byte++) { + fec = (fec & 0x700) | in[byte]; + output = 0; + for (bit = 0; bit < 8; bit++) { + output = output << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } + out[byte * 2] = output >> 8; + out[byte * 2 + 1] = output; + } + return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + out[i+0] = interleaved >> 24; + out[i+1] = interleaved >> 16; + out[i+2] = interleaved >> 8; + out[i+3] = interleaved; + } + return len; +} diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h deleted file mode 100644 index db5523a3..00000000 --- a/src/drivers/ao_fec.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_FEC_H_ -#define _AO_FEC_H_ - -#include - -#define AO_FEC_CRC_INIT 0xffff -#define AO_FEC_TRELLIS_TERMINATOR 0x0b -#define AO_FEC_PREPARE_EXTRA 4 - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Encode data. 'out' must be len*2 bytes long - */ -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - -#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c deleted file mode 100644 index b8933956..00000000 --- a/src/drivers/ao_fec_tx.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 -#include - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) -{ - uint8_t i; - - printf ("%s (%d):", name, len); - for (i = 0; i < len; i++) { - if ((i & 7) == 0) - printf ("\n\t%02x:", i); - printf(" %02x", bytes[i]); - } - printf ("\n"); -} - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) -{ - uint16_t crc = AO_FEC_CRC_INIT; - - while (len--) - crc = crc_byte(*bytes++, crc); - return crc; -} - -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t crc = ao_fec_crc (in, len); - uint8_t i; - uint8_t num_fec; - - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; - - /* Append FEC -- 1 byte if odd, two bytes if even */ - num_fec = 2 - (i & 1); - while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; - return i; -} - -static const uint8_t whiten[] = { -#include "ao_whiten.h" -}; - -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = whiten; - - while (len--) - *out++ = *in++ ^ *w++; -} - -static const uint8_t ao_fec_encode_table[16] = { - 0, 3, 1, 2, - 3, 0, 2, 1, - 3, 0, 2, 1, - 0, 3, 1, 2 -}; - -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; - } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} - -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; - } - return len; -} -- cgit v1.2.3 From cbf79a0f9cb859d04e8e03d627219cb2bf49611f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:12:02 -0700 Subject: altos: Add the simplest possible viterbi decoder I think I understand how it works now. It's not exactly speedy, and it uses a lot of memory. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 9 +++ src/core/ao_viterbi.c | 143 ++++++++++++++++++++++++++++++++++++++++ src/test/Makefile | 4 +- src/test/ao_fec_tx_test.c | 163 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 src/core/ao_viterbi.c diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index db5523a3..985352dd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -57,4 +57,13 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Decode data. 'in' is one byte per bit, soft decision + * 'out' must be len/8 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c new file mode 100644 index 00000000..2d441f4b --- /dev/null +++ b/src/core/ao_viterbi.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +/* + * 'input' is 8-bits per symbol soft decision data + * 'len' is output byte length + */ + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +struct ao_soft_sym { + uint8_t a, b; +}; + +struct ao_soft_sym +ao_soft_sym(uint8_t bits) +{ + struct ao_soft_sym s; + + s.a = ((bits & 2) >> 1) * 0xff; + s.b = (bits & 1) * 0xff; + return s; +} + +uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline abs(int x) { return x < 0 ? -x : x; } + +int +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return abs(a.a - b.a) + abs(a.b - b.b); +} + +uint8_t +ao_fec_decode(uint8_t *in, int len, uint8_t *out) +{ + int cost[len/2 + 1][8]; + uint8_t prev[len/2 + 1][8]; + int c; + int i, b; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + for (c = 0; c < 8; c++) + cost[0][c] = 10000; + cost[0][0] = 0; + + for (i = 0; i < len; i += 2) { + b = i/2; + struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + for (state = 0; state < 8; state++) + cost[b+1][state] = 10000; + + for (state = 0; state < 8; state++) { + struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); + struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); + uint8_t zero_state = ao_next_state(state, 0); + uint8_t one_state = ao_next_state(state, 1); + int zero_cost = ao_cost(s, zero); + int one_cost = ao_cost(s, one); + +#if 0 + printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", + s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); +#endif + zero_cost += cost[b][state]; + one_cost += cost[b][state]; + if (zero_cost < cost[b+1][zero_state]) { + prev[b+1][zero_state] = state; + cost[b+1][zero_state] = zero_cost; + } + + if (one_cost < cost[b+1][one_state]) { + prev[b+1][one_state] = state; + cost[b+1][one_state] = one_cost; + } + } + + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < 8; state++) { + printf (" %5d", cost[b+1][state]); + } + printf ("\n"); + } + + b = len / 2; + c = cost[b][0]; + min_state = 0; + for (state = 1; state < 8; state++) { + if (cost[b][state] < c) { + c = cost[b][state]; + min_state = state; + } + } + + for (b = len/2; b > 0; b--) { + bits[b-1] = min_state & 1; + min_state = prev[b][min_state]; + } + + for (i = 0; i < len/2; i += 8) { + uint8_t byte; + + byte = 0; + for (b = 0; b < 8; b++) + byte = (byte << 1) | bits[i + b]; + out[i/8] = byte; + } + return len/16; +} diff --git a/src/test/Makefile b/src/test/Makefile index 3e308dd7..024a54c1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c index b8dc9308..d01eadc5 100644 --- a/src/test/ao_fec_tx_test.c +++ b/src/test/ao_fec_tx_test.c @@ -18,21 +18,73 @@ #include #include #include +#include +#include -int -main(int argc, char **argv) +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) { - uint8_t input[4] = { 3, 1, 2, 3 }; - uint8_t prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; - uint8_t encode[sizeof(prepare) * 2]; - uint8_t interleave[sizeof(encode)]; + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) + +static int +ao_encode(uint8_t *input, int input_len, uint8_t *output) +{ + uint8_t prepare[PREPARE_LEN(input_len)]; + uint8_t encode[ENCODE_LEN(input_len)]; + uint8_t interleave[INTERLEAVE_LEN(input_len)]; uint8_t prepare_len; uint8_t encode_len; uint8_t interleave_len; - ao_fec_dump_bytes(input, sizeof(input), "Input"); + ao_fec_dump_bytes(input, input_len, "Input"); - prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + prepare_len = ao_fec_prepare(input, input_len, prepare); ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); @@ -40,8 +92,99 @@ main(int argc, char **argv) ao_fec_dump_bytes(encode, encode_len, "Encode"); - interleave_len = ao_fec_interleave(encode, encode_len, interleave); + interleave_len = ao_fec_interleave(encode, encode_len, output); + + ao_fec_dump_bytes(output, interleave_len, "Interleave"); + + return interleave_len; +} + +#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) + +static int +ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + uint8_t b, *bytes_orig = bytes; + uint8_t interleave[bits_len]; + int i, bit; + + ao_fec_interleave(bits, bits_len, interleave); + + ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); + + for (i = 0; i < bits_len; i++) { + b = interleave[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + return bits_len * 8; } +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + + printf ("Introduced %d errors\n", errors); + ao_fec_dump_bytes(out, in_len, "Fuzz"); + return in_len; +} + +static int +ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) +{ + int bits_len; + + bits_len = ao_fec_decode(bytes, bytes_len, bits); + + ao_fec_dump_bytes(bits, bits_len, "Decode"); +} + +int +main(int argc, char **argv) +{ + uint8_t original[4] = { 3, 1, 2, 3 }; + uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[RADIO_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[RADIO_LEN(sizeof(original))]; + int receive_len; + + uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; + int decode_len; + + encode_len = ao_encode(original, sizeof(original), encode); + + transmit_len = ao_radio(encode, encode_len, transmit); + + /* apply gaussian noise to test viterbi code against errors */ + receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80); + + decode_len = ao_decode(receive, receive_len, decode); +} + + -- cgit v1.2.3 From 047e95421c87c5d056038797b48f759bedabf245 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:31:11 -0700 Subject: altos: Start optimizing viterbi decoder Only need two cost arrays (previous and next). Create constant full-width decoder table instead of expanding bits into bytes for each decode step. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 2d441f4b..916c4d7c 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -23,22 +23,22 @@ * 'len' is output byte length */ -static const uint8_t ao_fec_encode_table[16] = { -/* next 0 1 state */ - 0, 3, /* 000 */ - 1, 2, /* 001 */ - 3, 0, /* 010 */ - 2, 1, /* 011 */ - 3, 0, /* 100 */ - 2, 1, /* 101 */ - 0, 3, /* 110 */ - 1, 2 /* 111 */ -}; - struct ao_soft_sym { uint8_t a, b; }; +static const struct ao_soft_sym ao_fec_decode_table[16] = { +/* next 0 1 state */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ + { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ + { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ +}; + struct ao_soft_sym ao_soft_sym(uint8_t bits) { @@ -57,71 +57,71 @@ ao_next_state(uint8_t state, uint8_t bit) static inline abs(int x) { return x < 0 ? -x : x; } -int +static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { return abs(a.a - b.a) + abs(a.b - b.b); } +#define NUM_STATE 8 + uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - int cost[len/2 + 1][8]; - uint8_t prev[len/2 + 1][8]; - int c; - int i, b; - uint8_t state = 0, min_state; - uint8_t bits[len/2]; - - for (c = 0; c < 8; c++) - cost[0][c] = 10000; + uint16_t cost[2][NUM_STATE]; + uint8_t prev[len/2 + 1][NUM_STATE]; + int c; + int i, b; + uint8_t p, n; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + p = 0; + for (c = 0; c < NUM_STATE; c++) + cost[0][c] = 0xffff; cost[0][0] = 0; for (i = 0; i < len; i += 2) { b = i/2; + n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; - for (state = 0; state < 8; state++) - cost[b+1][state] = 10000; + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + for (state = 0; state < NUM_STATE; state++) { + int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); + int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - for (state = 0; state < 8; state++) { - struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); - struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); uint8_t zero_state = ao_next_state(state, 0); uint8_t one_state = ao_next_state(state, 1); - int zero_cost = ao_cost(s, zero); - int one_cost = ao_cost(s, one); - -#if 0 - printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", - s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); -#endif - zero_cost += cost[b][state]; - one_cost += cost[b][state]; - if (zero_cost < cost[b+1][zero_state]) { + + zero_cost += cost[p][state]; + one_cost += cost[p][state]; + if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; - cost[b+1][zero_state] = zero_cost; + cost[n][zero_state] = zero_cost; } - if (one_cost < cost[b+1][one_state]) { + if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; - cost[b+1][one_state] = one_cost; + cost[n][one_state] = one_cost; } } printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < 8; state++) { - printf (" %5d", cost[b+1][state]); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d", cost[n][state]); } printf ("\n"); + p = n; } - b = len / 2; - c = cost[b][0]; + c = cost[p][0]; min_state = 0; - for (state = 1; state < 8; state++) { - if (cost[b][state] < c) { - c = cost[b][state]; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < c) { + c = cost[p][state]; min_state = state; } } -- cgit v1.2.3 From ff8de3af193839de4bacfd07ade7a5f9ac0bf5b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 00:54:42 -0700 Subject: altos: incremental viterbi decode Decode bits incrementally. Don't bother decoding the last byte; it's always a pad byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 70 +++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 916c4d7c..df95e979 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -49,18 +49,18 @@ ao_soft_sym(uint8_t bits) return s; } -uint8_t +static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { return ((state << 1) | bit) & 0x7; } -static inline abs(int x) { return x < 0 ? -x : x; } +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { - return abs(a.a - b.a) + abs(a.b - b.b); + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } #define NUM_STATE 8 @@ -68,19 +68,23 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - uint16_t cost[2][NUM_STATE]; + uint16_t cost[2][NUM_STATE], min_cost; uint8_t prev[len/2 + 1][NUM_STATE]; - int c; - int i, b; + uint16_t prev_bits[2][NUM_STATE]; + int i, b, dump; uint8_t p, n; uint8_t state = 0, min_state; - uint8_t bits[len/2]; p = 0; - for (c = 0; c < NUM_STATE; c++) - cost[0][c] = 0xffff; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + prev_bits[0][state] = 0; + } cost[0][0] = 0; + min_state = 0; + min_cost = 0; + dump = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; @@ -101,43 +105,49 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; cost[n][zero_state] = zero_cost; + prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); } if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; cost[n][one_state] = one_cost; + prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); } } +#if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d", cost[n][state]); + printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); } printf ("\n"); +#endif p = n; - } - c = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < c) { - c = cost[p][state]; - min_state = state; + b++; + if ((b - dump) > 16 || i + 2 >= len) { + uint8_t dist = b - (dump + 9); + uint8_t rev; + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + for (rev = 0; rev < dist; rev++) { + min_state = prev[b][min_state]; + b--; + } +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", + i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); +#endif + out[dump/8] = prev_bits[p][min_state] >> dist; + dump = b - 1; } - } - - for (b = len/2; b > 0; b--) { - bits[b-1] = min_state & 1; - min_state = prev[b][min_state]; - } - - for (i = 0; i < len/2; i += 8) { - uint8_t byte; - byte = 0; - for (b = 0; b < 8; b++) - byte = (byte << 1) | bits[i + b]; - out[i/8] = byte; } return len/16; } -- cgit v1.2.3 From f7bf07dfdad260c1f219064957ef08fb480bf20f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:12:58 -0700 Subject: altos: optimize Viterbi implementation Minimize data usage, make data arrays static Signed-off-by: Keith Packard --- src/core/ao_fec.h | 5 +- src/core/ao_fec_tx.c | 2 +- src/core/ao_viterbi.c | 149 ++++++++++++++++++++++++++++---------------------- 3 files changed, 86 insertions(+), 70 deletions(-) diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 985352dd..d4f64b74 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -42,7 +42,7 @@ ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); * must be 'len' bytes long. 'out' and 'in' can be * the same array */ -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* @@ -57,13 +57,12 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ uint8_t -ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index bf32c506..c5f410b8 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -83,7 +83,7 @@ static const uint8_t whiten[] = { #include "ao_whiten.h" }; -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { const uint8_t *w = whiten; diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index df95e979..1b1784b3 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,37 +18,26 @@ #include #include -/* - * 'input' is 8-bits per symbol soft decision data - * 'len' is output byte length - */ - struct ao_soft_sym { uint8_t a, b; }; -static const struct ao_soft_sym ao_fec_decode_table[16] = { +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ - { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ - { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ + { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ + { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ + { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ + { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ }; -struct ao_soft_sym -ao_soft_sym(uint8_t bits) -{ - struct ao_soft_sym s; - - s.a = ((bits & 2) >> 1) * 0xff; - s.b = (bits & 1) * 0xff; - return s; -} - static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { @@ -63,71 +52,93 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } -#define NUM_STATE 8 +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ uint8_t -ao_fec_decode(uint8_t *in, int len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) { - uint16_t cost[2][NUM_STATE], min_cost; - uint8_t prev[len/2 + 1][NUM_STATE]; - uint16_t prev_bits[2][NUM_STATE]; - int i, b, dump; - uint8_t p, n; - uint8_t state = 0, min_state; + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ p = 0; for (state = 0; state < NUM_STATE; state++) { cost[0][state] = 0xffff; - prev_bits[0][state] = 0; + bits[0][state] = 0; } cost[0][0] = 0; - min_state = 0; - min_cost = 0; - dump = 0; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ for (state = 0; state < NUM_STATE; state++) cost[n][state] = 0xffff; + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ for (state = 0; state < NUM_STATE; state++) { - int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); - int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - - uint8_t zero_state = ao_next_state(state, 0); - uint8_t one_state = ao_next_state(state, 1); - - zero_cost += cost[p][state]; - one_cost += cost[p][state]; - if (zero_cost < cost[n][zero_state]) { - prev[b+1][zero_state] = state; - cost[n][zero_state] = zero_cost; - prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); - } - - if (one_cost < cost[n][one_state]) { - prev[b+1][one_state] = state; - cost[n][one_state] = one_cost; - prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } } } #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); + printf (" %5d(%04x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif p = n; - b++; - if ((b - dump) > 16 || i + 2 >= len) { - uint8_t dist = b - (dump + 9); - uint8_t rev; + /* A loop is needed to handle the last output byte. It + * won't have a full NUM_HIST bits of future data to + * perform full error correction, but we might as well + * give the best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ min_cost = cost[p][0]; min_state = 0; for (state = 1; state < NUM_STATE; state++) { @@ -136,18 +147,24 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) min_state = state; } } - for (rev = 0; rev < dist; rev++) { - min_state = prev[b][min_state]; - b--; + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; } + #if 0 printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); #endif - out[dump/8] = prev_bits[p][min_state] >> dist; - dump = b - 1; + out[o >> 3] = bits[p][min_state] >> dist; + o += 8; } - } return len/16; } -- cgit v1.2.3 From 83549f8bde42c3fddbdc817540c869dc8aefd013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:13:52 -0700 Subject: altos: Make ao_fec_tx_test build cleanly with -Wall Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- src/test/ao_fec_tx_test.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/Makefile b/src/test/Makefile index 024a54c1..7bcf24e1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -4,7 +4,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall all: $(PROGS) diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c index d01eadc5..1b1fd56d 100644 --- a/src/test/ao_fec_tx_test.c +++ b/src/test/ao_fec_tx_test.c @@ -77,7 +77,6 @@ ao_encode(uint8_t *input, int input_len, uint8_t *output) { uint8_t prepare[PREPARE_LEN(input_len)]; uint8_t encode[ENCODE_LEN(input_len)]; - uint8_t interleave[INTERLEAVE_LEN(input_len)]; uint8_t prepare_len; uint8_t encode_len; uint8_t interleave_len; @@ -159,6 +158,7 @@ ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) bits_len = ao_fec_decode(bytes, bytes_len, bits); ao_fec_dump_bytes(bits, bits_len, "Decode"); + return bits_len; } int @@ -182,9 +182,11 @@ main(int argc, char **argv) transmit_len = ao_radio(encode, encode_len, transmit); /* apply gaussian noise to test viterbi code against errors */ - receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80); + receive_len = ao_fuzz(transmit, transmit_len, receive, 0x70); decode_len = ao_decode(receive, receive_len, decode); + + return decode_len >= sizeof(original); } -- cgit v1.2.3 From 566a0c277de01963922cabc80db8ec3a129923bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:23:08 -0700 Subject: altos: fix comment about decoding last byte of FEC data There aren't *any* forward bits to use when decoding the last byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 1b1784b3..17464cd1 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -120,9 +120,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) p = n; /* A loop is needed to handle the last output byte. It - * won't have a full NUM_HIST bits of future data to - * perform full error correction, but we might as well - * give the best possible answer anyways. + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. */ while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { -- cgit v1.2.3 From 74f6a1a8c8fa9d5bb8d74c99782310b431dd4727 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:24:30 -0700 Subject: altos: Add ao_viterbi.c to megametrum build It's not used yet, just wanted to see how big the resulting object file was (492 bytes). Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5c641e9a..857667b0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -48,6 +48,7 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_cc1120.c \ ao_fec_tx.c \ + ao_viterbi.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ -- cgit v1.2.3 From b292c14790fc225029cba3f80ce8ad6c5652bc4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 16:05:42 -0700 Subject: altos: improve FEC apis to reduce data copying Integrate interleaving and whitening into encode and decode steps. Add CRC checking function for receive. Make ao_fec_test program round-trip the data and verify correctness. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 26 ++++-- src/core/ao_fec_tx.c | 118 +++++++++++++++++---------- src/core/ao_viterbi.c | 46 ++++++++++- src/test/Makefile | 6 +- src/test/ao_fec_test.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ src/test/ao_fec_tx_test.c | 192 -------------------------------------------- 6 files changed, 337 insertions(+), 249 deletions(-) create mode 100644 src/test/ao_fec_test.c delete mode 100644 src/test/ao_fec_tx_test.c diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index d4f64b74..f3f55fa8 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -24,12 +24,22 @@ #define AO_FEC_TRELLIS_TERMINATOR 0x0b #define AO_FEC_PREPARE_EXTRA 4 +extern const uint8_t ao_fec_whiten_table[]; + void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); uint16_t ao_fec_crc(uint8_t *bytes, uint8_t len); +/* + * 'len' is the length of the original data; 'bytes' + * must be four bytes longer than that, and the first + * two after 'len' must be the received crc + */ +uint8_t +ao_fec_check_crc(uint8_t *bytes, uint8_t len); + /* * Append CRC and terminator bytes, returns resulting length. * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long @@ -46,17 +56,11 @@ void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* - * Encode data. 'out' must be len*2 bytes long + * Encode and interleave data. 'out' must be len*2 bytes long */ uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long @@ -65,4 +69,10 @@ ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +/* + * Interleave data packed in bytes. 'out' must be 'len' bytes long. + */ +uint16_t +ao_fec_interleave_bytes(uint8_t *in, uint16_t len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c5f410b8..c9c0a3d6 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -19,9 +19,9 @@ #include void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) { - uint8_t i; + uint16_t i; printf ("%s (%d):", name, len); for (i = 0; i < len; i++) { @@ -57,41 +57,76 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) return crc; } +/* + * len is the length of the data; the crc will be + * the fist two bytes after that + */ + uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_check_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t computed_crc = ao_fec_crc(bytes, len); + uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); + + return computed_crc == received_crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); - uint8_t i; + uint8_t i = 0; uint8_t num_fec; - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; + extra[i++] = crc >> 8; + extra[i++] = crc; /* Append FEC -- 1 byte if odd, two bytes if even */ num_fec = 2 - (i & 1); while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; + extra[i++] = AO_FEC_TRELLIS_TERMINATOR; return i; } -static const uint8_t whiten[] = { +const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; +#if 0 void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { - const uint8_t *w = whiten; + const uint8_t *w = ao_fec_whiten_table; while (len--) *out++ = *in++ ^ *w++; } +/* + * Unused as interleaving is now built in to ao_fec_encode + */ + +static void +ao_fec_interleave(uint8_t *d, uint8_t len) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + d[i+0] = interleaved >> 24; + d[i+1] = interleaved >> 16; + d[i+2] = interleaved >> 8; + d[i+3] = interleaved; + } +} +#endif + static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -107,38 +142,37 @@ static const uint8_t ao_fec_encode_table[16] = { uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) { - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; + uint8_t extra[AO_FEC_PREPARE_EXTRA]; + uint8_t extra_len; + uint32_t encode, interleave; + uint8_t pair, byte, bit; + uint16_t fec = 0; + const uint8_t *whiten = ao_fec_whiten_table; + + extra_len = ao_fec_prepare(in, len, extra); + for (pair = 0; pair < len + extra_len; pair += 2) { + encode = 0; + for (byte = 0; byte < 2; byte++) { + if (pair + byte == len) + in = extra; + fec |= *in++ ^ *whiten++; + for (bit = 0; bit < 8; bit++) { + encode = encode << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; + interleave = 0; + for (bit = 0; bit < 4 * 4; bit++) { + uint8_t byte_shift = (bit & 0x3) << 3; + uint8_t bit_shift = (bit & 0xc) >> 1; - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3); } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; + *out++ = interleave >> 24; + *out++ = interleave >> 16; + *out++ = interleave >> 8; + *out++ = interleave >> 0; } - return len; + return (len + extra_len) * 2; } diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 17464cd1..bb93bc83 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,6 +18,35 @@ #include #include +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + struct ao_soft_sym { uint8_t a, b; }; @@ -70,6 +99,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -82,7 +114,13 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; - struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this @@ -159,10 +197,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) } #if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - out[o >> 3] = bits[p][min_state] >> dist; + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; o += 8; } } diff --git a/src/test/Makefile b/src/test/Makefile index 7bcf24e1..cdcecd51 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test KALMAN=make-kalman @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c new file mode 100644 index 00000000..c7509728 --- /dev/null +++ b/src/test/ao_fec_test.c @@ -0,0 +1,198 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include +#include +#include +#include + +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) +{ + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) + +static int +ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + int i, bit; + uint8_t b; + + for (i = 0; i < bits_len; i++) { + b = bits[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + return bits_len * 8; +} + +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + return errors; +} + +static uint8_t +ao_random_data(uint8_t *out, uint8_t out_len) +{ + uint8_t len = random() % (out_len + 1); + uint8_t i; + + for (i = 0; i < len; i++) + out[i] = random(); + return len; +} + + +int +main(int argc, char **argv) +{ + int trial; + + uint8_t original[120]; + uint8_t original_len; + + uint8_t encode[ENCODE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[EXPAND_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[EXPAND_LEN(sizeof(original))]; + int receive_len, receive_errors; + + uint8_t decode[DECODE_LEN(sizeof(original))]; + int decode_len; + + int errors = 0; + int error; + + srandom(0); + for (trial = 0; trial < 10000; trial++) { + + /* Compute some random data */ + original_len = ao_random_data(original, sizeof(original)); + + /* Encode it */ + encode_len = ao_fec_encode(original, original_len, encode); + + /* Expand from 1-bit-per-symbol to 1-byte-per-symbol */ + transmit_len = ao_expand(encode, encode_len, transmit); + + /* Add gaussian noise to the signal */ + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_len = transmit_len; + + /* Decode it */ + decode_len = ao_fec_decode(receive, receive_len, decode); + + /* Check to see if we received the right data */ + error = 0; + + if (decode_len < original_len + 2) { + printf ("len mis-match\n"); + error++; + } + + if (!ao_fec_check_crc(decode, original_len)) { + printf ("crc mis-match\n"); + error++; + } + + if (memcmp(original, decode, original_len) != 0) { + printf ("data mis-match\n"); + error++; + } + if (error) { + printf ("Errors: %d\n", receive_errors); + ao_fec_dump_bytes(original, original_len, "Input"); + ao_fec_dump_bytes(decode, original_len, "Decode"); + errors += error; + } + } + return errors; +} + + diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c deleted file mode 100644 index 1b1fd56d..00000000 --- a/src/test/ao_fec_tx_test.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 -#include -#include -#include -#include - -#ifndef RANDOM_MAX -#define RANDOM_MAX 0x7fffffff -#endif - -static double -rand_real(void) { - return (double) random() / (double) RANDOM_MAX; -} - -static double -gaussian_random(double mean, double dev) -{ - static int save_x_valid = 0; - static double save_x; - double x; - - if (save_x_valid) - { - x = save_x; - save_x_valid = 0; - } - else - { - double w; - double normal_x1, normal_x2; - - do { - normal_x1 = 2 * rand_real () - 1; - normal_x2 = 2 * rand_real () - 1; - w = normal_x1*normal_x1 + normal_x2*normal_x2; - } while (w >= 1 || w < 1E-30); - - w = sqrt(log(w)*(-2./w)); - - /* - * normal_x1 and normal_x2 are independent normally - * distributed variates - */ - - x = normal_x1 * w; - /* save normal_x2 for next call */ - save_x = normal_x2 * w; - save_x_valid = 1; - } - return x * dev + mean; -} - -#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) -#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) -#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) - -static int -ao_encode(uint8_t *input, int input_len, uint8_t *output) -{ - uint8_t prepare[PREPARE_LEN(input_len)]; - uint8_t encode[ENCODE_LEN(input_len)]; - uint8_t prepare_len; - uint8_t encode_len; - uint8_t interleave_len; - - ao_fec_dump_bytes(input, input_len, "Input"); - - prepare_len = ao_fec_prepare(input, input_len, prepare); - - ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - - ao_fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, output); - - ao_fec_dump_bytes(output, interleave_len, "Interleave"); - - return interleave_len; -} - -#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) - -static int -ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) -{ - uint8_t b, *bytes_orig = bytes; - uint8_t interleave[bits_len]; - int i, bit; - - ao_fec_interleave(bits, bits_len, interleave); - - ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); - - for (i = 0; i < bits_len; i++) { - b = interleave[i]; - for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; - } - - ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - - return bits_len * 8; -} - -static int -ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) -{ - int i; - int errors = 0; - - for (i = 0; i < in_len; i++) { - double error = gaussian_random(0, dev); - uint8_t byte = in[i]; - - if (error > 0) { - if (error > 0xff) - error = 0xff; - if (error >= 0x80) - errors++; - if (byte < 0x80) - byte += error; - else - byte -= error; - } - out[i] = byte; - } - - printf ("Introduced %d errors\n", errors); - ao_fec_dump_bytes(out, in_len, "Fuzz"); - return in_len; -} - -static int -ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) -{ - int bits_len; - - bits_len = ao_fec_decode(bytes, bytes_len, bits); - - ao_fec_dump_bytes(bits, bits_len, "Decode"); - return bits_len; -} - -int -main(int argc, char **argv) -{ - uint8_t original[4] = { 3, 1, 2, 3 }; - uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; - int encode_len; - - uint8_t transmit[RADIO_LEN(sizeof(original))]; - int transmit_len; - - uint8_t receive[RADIO_LEN(sizeof(original))]; - int receive_len; - - uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; - int decode_len; - - encode_len = ao_encode(original, sizeof(original), encode); - - transmit_len = ao_radio(encode, encode_len, transmit); - - /* apply gaussian noise to test viterbi code against errors */ - receive_len = ao_fuzz(transmit, transmit_len, receive, 0x70); - - decode_len = ao_decode(receive, receive_len, decode); - - return decode_len >= sizeof(original); -} - - -- cgit v1.2.3 From 246174b32bb6cf827d240c32d6a51c3513a08c37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:16 -0700 Subject: altos: Forgot ao_telemetry.h Not much builds without this... Signed-off-by: Keith Packard --- src/core/ao_telemetry.h | 250 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/core/ao_telemetry.h diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h new file mode 100644 index 00000000..32a1668c --- /dev/null +++ b/src/core/ao_telemetry.h @@ -0,0 +1,250 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEMETRY_H_ +#define _AO_TELEMETRY_H_ + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#if LEGACY_MONITOR +#define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10â·) */ + int32_t longitude; /* 12 longitude (degrees * 10â·) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_SENSOR 0x08 + +struct ao_telemetry_mega_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t pad5; /* 5 */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t accel_x; /* 14 */ + int16_t accel_y; /* 16 */ + int16_t accel_z; /* 18 */ + + int16_t gyro_x; /* 20 */ + int16_t gyro_y; /* 22 */ + int16_t gyro_z; /* 24 */ + + int16_t mag_x; /* 26 */ + int16_t mag_y; /* 28 */ + int16_t mag_z; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_DATA 0x09 + +struct ao_telemetry_mega_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + + int16_t v_batt; /* 6 battery voltage */ + int16_t v_pyro; /* 8 pyro battery voltage */ + int8_t sense[6]; /* 10 continuity sense */ + + int32_t ground_pres; /* 16 average pres on pad */ + int16_t ground_accel; /* 20 average accel on pad */ + int16_t accel_plus_g; /* 22 accel calibration at +1g */ + int16_t accel_minus_g; /* 24 accel calibration at -1g */ + + int16_t acceleration; /* 26 m/s² * 16 */ + int16_t speed; /* 28 m/s * 16 */ + int16_t height; /* 30 m */ + /* 32 */ +}; + + +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; + struct ao_telemetry_mega_sensor mega_sensor; + struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_baro baro; +}; + +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + +#endif /* _AO_TELEMETRY_H_ */ -- cgit v1.2.3 From 70cf32e89df19bde5185339fc703532c8a5b8be6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:34 -0700 Subject: altos: Get cc1120 packet reception working Interrupt-per-bit, but it seems to work Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 19 ++-- src/drivers/ao_cc1120.c | 169 ++++++++++++++++++++++++++---------- src/megametrum-v0.1/ao_megametrum.c | 6 +- src/megametrum-v0.1/ao_pins.h | 2 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 5 ++ src/test/ao_fec_test.c | 151 ++++++++++++++++++++++++++++++++ 7 files changed, 299 insertions(+), 56 deletions(-) diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index bb93bc83..594c0d91 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -55,16 +55,19 @@ struct ao_soft_sym { #define NUM_HIST 8 #define MOD_HIST(b) ((b) & 7) +#define V_0 0xc0 +#define V_1 0x40 + static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ - { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ - { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ - { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ }; static inline uint8_t diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 67a36c5c..4378716d 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -19,6 +19,7 @@ #include #include #include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; @@ -102,6 +103,35 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) ao_radio_deselect(); } +static void +ao_radio_burst_read_start (uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); +} + +static void +ao_radio_burst_read_stop (void) +{ + ao_radio_deselect(); +} + + static uint8_t ao_radio_strobe(uint8_t addr) { @@ -247,10 +277,19 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + static void ao_radio_start_tx(void) { ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); } @@ -336,29 +375,13 @@ void ao_radio_send(void *d, uint8_t size) { uint8_t marc_status; - uint8_t prepare[size + AO_FEC_PREPARE_EXTRA]; - uint8_t prepare_len; - uint8_t encode[sizeof(prepare) * 2]; + uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; uint8_t encode_len; - uint8_t interleave[sizeof(encode)]; - uint8_t interleave_len; - fec_dump_bytes(d, size, "Input"); + encode_len = ao_fec_encode(d, size, encode); - prepare_len = ao_fec_prepare(d, size, prepare); - fec_dump_bytes(prepare, prepare_len, "Prepare"); - - ao_fec_whiten(prepare, prepare_len, prepare); - fec_dump_bytes(prepare, prepare_len, "Whiten"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, interleave); - fec_dump_bytes(interleave, interleave_len, "Interleave"); - - ao_radio_get(interleave_len); - ao_radio_fifo_write(interleave, interleave_len); + ao_radio_get(encode_len); + ao_radio_fifo_write(encode, encode_len); ao_radio_wake = 0; @@ -373,34 +396,92 @@ ao_radio_send(void *d, uint8_t size) ao_radio_put(); } +#define AO_RADIO_MAX_RECV 90 + +static uint8_t rx_data[2048]; +static uint16_t rx_data_count; +static uint16_t rx_data_cur; +static uint8_t rx_started; + +static void +ao_radio_rx_isr(void) +{ + if (rx_started) { + rx_data[rx_data_cur++] = stm_spi2.dr; + if (rx_data_cur >= rx_data_count) { + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); + } + } else { + (void) stm_spi2.dr; + rx_started = 1; + } + stm_spi2.dr = 0x00; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint16_t i; + + rx_data_count = sizeof (rx_data); + rx_data_cur = 0; + rx_started = 0; + + printf ("len %d rx_data_count %d\n", len, rx_data_count); /* configure interrupt pin */ - ao_radio_get(size); + ao_radio_get(len); ao_radio_wake = 0; + ao_radio_abort = 0; + + ao_radio_reg_write(CC1120_PKT_CFG2, + (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + + ao_radio_reg_write(CC1120_EXT_CTRL, 0); + + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + + stm_spi2.cr2 = 0; + + /* clear any RXNE */ + (void) stm_spi2.dr; + + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); - cli(); - for (;;) { - if (ao_radio_abort) - break; - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +#if 1 + cli(); + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); - if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) - ao_radio_fifo_read(d, size); + +#else + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); +#endif + ao_radio_burst_read_stop(); + + ao_radio_strobe(CC1120_SIDLE); + ao_radio_put(); - return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; + + printf ("Received data:"); + for (i = 0; i < rx_data_cur; i++) { + if ((i & 15) == 0) + printf ("\n"); + printf (" %02x", rx_data[i]); + } + printf ("\n"); + return 1; } /* @@ -477,13 +558,6 @@ static const uint16_t radio_setup[] = { static uint8_t ao_radio_configured = 0; -static void -ao_radio_isr(void) -{ - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); -} static void ao_radio_setup(void) @@ -745,6 +819,12 @@ static void ao_radio_packet(void) { ao_radio_send(packet, sizeof (packet)); } +void +ao_radio_test_recv() +{ + ao_radio_recv(0, 34); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { @@ -753,6 +833,7 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, #endif { 0, NULL } }; @@ -776,7 +857,7 @@ ao_radio_init(void) /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index dc9c0d19..a2ac186b 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -44,9 +44,9 @@ main(void) ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); +// ao_flight_init(); +// ao_log_init(); +// ao_report_init(); ao_telemetry_init(); ao_config_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5c5c5972..9d9113c8 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -255,7 +255,7 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) -#define HAS_HIGHG_ACCEL 1 +#define HAS_HIGHG_ACCEL 0 #define NUM_CMDS 16 diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 43eaa52f..87a072e7 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -26,6 +26,9 @@ void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()); + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 0fa24188..683a91b3 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -94,6 +94,11 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback stm_nvic_set_enable(irq); } +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { + ao_exti_callback[pin] = callback; +} + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { uint32_t mask = (1 << pin); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index c7509728..98067486 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -126,6 +126,156 @@ ao_random_data(uint8_t *out, uint8_t out_len) } +static uint8_t real_packet[] = { + 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, + 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, + 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, + 0xc9, 0xc6, 0x37, 0x3e, 0x3d, 0xc8, 0xc3, 0xc6, 0x38, 0x3d, 0xcf, 0x34, 0x3d, 0x3b, 0xcb, 0x31, + 0xca, 0x35, 0x38, 0xcb, 0x31, 0xcc, 0x31, 0x3b, 0xc7, 0xbf, 0xbe, 0xbe, 0xc3, 0x35, 0x38, 0xcb, + 0x2f, 0xc9, 0xc2, 0x34, 0x3c, 0xcc, 0x31, 0xca, 0xc1, 0xc0, 0xc3, 0x33, 0x3f, 0x3f, 0x3e, 0x3c, + 0xcc, 0x31, 0xcc, 0xc3, 0xc4, 0x32, 0xd1, 0x34, 0x3f, 0x3c, 0xcc, 0x31, 0xcc, 0xc3, 0x33, 0xd0, + 0x31, 0xd1, 0x35, 0x3f, 0x3e, 0x3c, 0xca, 0xc5, 0x34, 0xcc, 0xc2, 0xc3, 0xc3, 0xc5, 0x36, 0x40, + 0x3e, 0x41, 0x3e, 0x41, 0x3e, 0x3f, 0x41, 0x40, 0xce, 0xc5, 0x33, 0xcf, 0xc7, 0x36, 0xd2, 0x32, + 0xd1, 0xc5, 0xc6, 0x35, 0xd4, 0x32, 0xd1, 0xc6, 0x34, 0x41, 0xd2, 0x30, 0xd0, 0xc2, 0xc2, 0xc5, + 0x31, 0xd3, 0x31, 0xd1, 0xc7, 0x33, 0xd4, 0xc6, 0x34, 0x42, 0x40, 0x40, 0x40, 0x41, 0x41, 0xd2, + 0xc4, 0xc4, 0x39, 0x3e, 0xce, 0x35, 0x3c, 0xcd, 0x31, 0x3d, 0xc8, 0xc3, 0x32, 0x3d, 0xcc, 0x2f, + 0xce, 0x30, 0xd0, 0x2e, 0xcf, 0x30, 0x3d, 0x3c, 0x3c, 0x3a, 0xcb, 0xbf, 0xbf, 0xc1, 0x31, 0x3d, + 0x3d, 0x3c, 0x3c, 0x3c, 0x3d, 0x3b, 0xcf, 0x2e, 0xd2, 0x2e, 0xd0, 0x2c, 0x3b, 0xd1, 0x2a, 0xcf, + 0xbe, 0xc0, 0xc0, 0xbf, 0xc1, 0xc1, 0x2c, 0x3f, 0xd0, 0xc0, 0x2e, 0xd0, 0x31, 0xd2, 0xc2, 0x2f, + 0x3e, 0x3e, 0x3d, 0xcf, 0x31, 0xcb, 0xc3, 0x32, 0xd1, 0xc4, 0x37, 0x3f, 0xce, 0xc4, 0x35, 0xd0, + 0x33, 0x3f, 0xce, 0x31, 0x3c, 0x3b, 0xcc, 0x31, 0xcd, 0x2f, 0xd1, 0x32, 0x3a, 0x3b, 0xcb, 0xc1, + 0xc0, 0x32, 0x3e, 0x3e, 0x3c, 0x3d, 0x3d, 0xce, 0x2d, 0xcd, 0xc3, 0xc2, 0x30, 0x3d, 0xcf, 0xc1, + 0xc2, 0x30, 0xd0, 0xc4, 0x31, 0xd4, 0x30, 0x40, 0x3e, 0xd0, 0x2f, 0xd0, 0x2f, 0xd1, 0xc2, 0x2e, + 0xd4, 0x2e, 0x3f, 0xce, 0xc2, 0x34, 0x3e, 0x3f, 0xd0, 0x30, 0xcf, 0x31, 0x3d, 0x3d, 0xcc, 0x2d, + 0xcf, 0x2f, 0xcf, 0x2e, 0x3b, 0xcf, 0x2c, 0x3b, 0x3b, 0x3a, 0x3d, 0x38, 0xcc, 0x2d, 0x3b, 0xcc, + 0xbe, 0x2d, 0xd1, 0x2c, 0x3c, 0x3d, 0xce, 0xc0, 0x2d, 0xd1, 0x2f, 0x3f, 0x3f, 0x3c, 0x3f, 0x3e, + 0x3e, 0x3c, 0xd3, 0x2a, 0xd1, 0xc2, 0x2e, 0x3c, 0xd1, 0x2f, 0x3d, 0xd1, 0xbe, 0xc1, 0x2d, 0xd2, + 0x2d, 0x3d, 0x3d, 0x3b, 0xcd, 0x31, 0xcc, 0x31, 0xce, 0x2e, 0x3d, 0x3e, 0x3a, 0xcd, 0x2d, 0xcc, + 0xc1, 0xc1, 0xc3, 0x2e, 0x3f, 0x3f, 0x3c, 0xcf, 0xc0, 0x31, 0xd1, 0xc2, 0xc3, 0x33, 0xd2, 0xc7, + 0x32, 0x40, 0xd3, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd2, 0x2f, 0xd0, 0x2f, 0x3c, 0xd1, 0x2c, 0x3a, + 0x3d, 0xd0, 0x2a, 0xd0, 0x28, 0xcf, 0xc3, 0x2c, 0xd2, 0x2d, 0xd3, 0xc3, 0xc3, 0x2e, 0x3e, 0x41, + 0xd2, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc4, 0x32, 0xd2, 0x34, 0x3e, 0x3e, 0x3c, 0xd1, 0x30, 0x3d, + 0x3c, 0xce, 0x2e, 0x3b, 0x38, 0xcb, 0xbe, 0xc1, 0x2e, 0x3e, 0x3c, 0x3d, 0xd1, 0x2c, 0x3b, 0x3b, + 0xcd, 0xbf, 0x2d, 0xd0, 0x2f, 0xd0, 0x2d, 0xd1, 0x2d, 0x3d, 0xd0, 0x2b, 0x3b, 0xcf, 0x2b, 0x3a, + 0xcc, 0xbc, 0xc1, 0x2a, 0x3c, 0xce, 0x28, 0xd1, 0x2a, 0x3c, 0x3a, 0xcf, 0xbf, 0x2b, 0x3e, 0x3c, + 0xd2, 0x2b, 0x3d, 0x3a, 0x3a, 0xcf, 0x2c, 0xcc, 0xbe, 0xc1, 0xc0, 0xbf, 0xc1, 0x31, 0x3c, 0xce, + 0xc0, 0xc1, 0xc0, 0xc1, 0x31, 0x3c, 0xd1, 0xc2, 0x2e, 0xd1, 0xc3, 0xc4, 0x30, 0x3f, 0xd3, 0x2c, + 0xd3, 0xc2, 0x30, 0xd5, 0xc3, 0xc5, 0x30, 0xd5, 0xc4, 0xc5, 0xc5, 0x31, 0x41, 0xd4, 0xc4, 0x31, + 0x40, 0xd4, 0x2d, 0xd5, 0xc0, 0xc3, 0x2c, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, 0xd6, 0x2c, 0x3e, 0xd2, + 0x27, 0x37, 0xde, 0xc9, 0xe9, 0x2e, 0xc7, 0x3c, 0xd9, 0x07, 0xf3, 0x28, 0x8d, 0xa5, 0xc9, 0xca, + 0xe7, 0xcb, 0xfc, 0xb3, 0x3c, 0xd4, 0xd3, 0x9a, 0xe7, 0x2c, 0xc8, 0xf8, 0x44, 0xb3, 0xb0, 0xfa, + 0x1c, 0xbf, 0xc9, 0xff, 0xbb, 0x1d, 0x02, 0xdb, 0x45, 0xc1, 0x40, 0x1c, 0xec, 0x48, 0xda, 0x21, + 0x4c, 0xe3, 0x38, 0xdf, 0x34, 0xd8, 0x35, 0xd8, 0x31, 0xd7, 0x30, 0xd4, 0x2f, 0xd6, 0x2d, 0xd5, + 0x2b, 0xd5, 0x33, 0xce, 0x33, 0xce, 0x33, 0xd0, 0x34, 0xcf, 0x31, 0xcf, 0x30, 0xce, 0x30, 0xcf, + 0x30, 0x3d, 0xce, 0x2f, 0xcf, 0xc2, 0x30, 0x3f, 0x3d, 0xcf, 0xc1, 0x31, 0xd0, 0xc5, 0xc4, 0x33, + 0x41, 0x3e, 0xd1, 0x30, 0x3c, 0x3d, 0xce, 0x2f, 0xce, 0xc1, 0xc3, 0x2e, 0xd3, 0x30, 0x3e, 0x3e, + 0x3c, 0x3f, 0x3c, 0xd1, 0xc0, 0xc0, 0xc0, 0xc1, 0xc2, 0xc0, 0xc1, 0xc3, 0x2c, 0x3f, 0xd2, 0xbe, + 0xc1, 0x2e, 0xcf, 0xc4, 0x33, 0xd3, 0x34, 0xd0, 0x33, 0x3d, 0xcf, 0xc3, 0x32, 0xce, 0x33, 0xd2, + 0x32, 0xce, 0xc5, 0x34, 0x40, 0xce, 0xc5, 0x32, 0x3e, 0xd0, 0x31, 0xd0, 0x2f, 0xd2, 0x30, 0xce, + 0xc2, 0x33, 0x40, 0x3e, 0xd0, 0xc3, 0xc2, 0x2e, 0xd3, 0x31, 0xd0, 0xc7, 0x32, 0x40, 0x3e, 0xd3, + 0x2f, 0xd3, 0x2e, 0xd0, 0x2d, 0xd3, 0x2d, 0xd3, 0x2f, 0x3c, 0x3d, 0xd1, 0x2a, 0x3b, 0xd1, 0x28, + 0x3b, 0x3b, 0xc8, 0x31, 0x39, 0x3b, 0x38, 0xc6, 0xbf, 0x31, 0x3d, 0x3a, 0xca, 0xc0, 0x33, 0x3c, + 0xca, 0xc0, 0xc1, 0xc1, 0xc2, 0x35, 0x3e, 0x3c, 0x3d, 0x3f, 0xcc, 0xc0, 0xc3, 0x31, 0xce, 0xc5, + 0x33, 0xd0, 0xc4, 0x35, 0xd3, 0x33, 0xd3, 0x32, 0xd1, 0xc4, 0xc3, 0x35, 0xd3, 0xc6, 0xc4, 0x35, + 0xd2, 0xc6, 0x35, 0x41, 0x41, 0xd4, 0x33, 0xd1, 0xc4, 0x30, 0x41, 0xd2, 0x30, 0x3e, 0xce, 0xc1, + 0xc3, 0xc0, 0x31, 0xce, 0xc5, 0x34, 0x40, 0x3d, 0xd1, 0xc4, 0x32, 0x3e, 0xcf, 0xc2, 0xc3, 0x30, + 0xd4, 0x32, 0x3e, 0x3f, 0x3e, 0x3f, 0x3e, 0xd0, 0xc2, 0x31, 0x3e, 0x3f, 0x3f, 0xd1, 0xc2, 0x2f, + 0xd5, 0x2e, 0xd3, 0xc3, 0x2f, 0xd7, 0x30, 0x3e, 0xd2, 0x2c, 0x3e, 0x3c, 0xd0, 0xc1, 0xc1, 0xc3, + 0xc0, 0xc3, 0x2c, 0xd4, 0xc2, 0x2e, 0x40, 0xd2, 0xc3, 0x2d, 0xd5, 0xc3, 0x2f, 0x42, 0x40, 0xd6, + 0x2d, 0xd4, 0xc2, 0xc2, 0xc2, 0x32, 0xd4, 0xc3, 0xc5, 0xc4, 0x32, 0x40, 0xd3, 0x30, 0xd0, 0xc3, + 0xc4, 0x30, 0xd3, 0xc5, 0xc5, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd4, 0x2f, 0xd2, 0x2d, 0x3d, 0xd1, + 0xc1, 0xc2, 0x2c, 0xd4, 0x2e, 0xd4, 0x2d, 0x3d, 0xd3, 0xc1, 0xc1, 0xc1, 0x2d, 0xd5, 0xc2, 0xc2, + 0xc2, 0x2d, 0xd9, 0xc4, 0xc5, 0x2f, 0x43, 0x40, 0xd6, 0xd7, 0xd7, 0x2b, 0x3e, 0xd5, 0x29, 0x3d, + 0xd4, 0x24, 0x3b, 0x3a, 0x3b, 0xce, 0x2a, 0x3a, 0xcc, 0xbe, 0x2d, 0x3b, 0x3b, 0x3d, 0x3b, 0x3b, + 0xce, 0x2b, 0x3a, 0xcc, 0x2b, 0xd0, 0x2b, 0x3b, 0x3b, 0x39, 0xcf, 0xbf, 0x2a, 0xd1, 0xc0, 0x2f, + 0x3e, 0xd0, 0x2d, 0x3a, 0xd1, 0xbe, 0x2b, 0xd2, 0xc3, 0xc2, 0xc0, 0x2d, 0xd7, 0x2c, 0xd7, 0xc2, + 0xc3, 0x2f, 0x43, 0x41, 0x40, 0xd4, 0xc3, 0xc3, 0xc3, 0xc2, 0x2c, 0x40, 0xd7, 0x2a, 0x3d, 0xd3, + 0x26, 0xd5, 0x2f, 0x3a, 0x3c, 0xca, 0xc3, 0x2c, 0xd3, 0x2e, 0x3c, 0x3d, 0x3d, 0x3d, 0xd0, 0xc2, + 0x2e, 0xd3, 0x2e, 0xd1, 0xc5, 0x2e, 0x3f, 0xd3, 0x2e, 0x3c, 0xd1, 0xc0, 0xc2, 0x2a, 0xd2, 0xc2, + 0xc4, 0x2e, 0xd7, 0x2e, 0x3e, 0xd3, 0xc1, 0xc3, 0xc1, 0x2d, 0x3f, 0xd3, 0xc2, 0x2c, 0x3f, 0xd3, + 0x2b, 0x3b, 0xd1, 0xbf, 0xc1, 0xbe, 0x29, 0x3f, 0xd4, 0x29, 0xd5, 0xbf, 0x29, 0xd7, 0xc0, 0x2d, + 0xd8, 0xc2, 0x33, 0x41, 0xd3, 0x30, 0x3d, 0xd0, 0x2c, 0xcf, 0xc1, 0xc1, 0xc2, 0x2e, 0x3f, 0xd3, + 0x2b, 0xcf, 0xc3, 0x2f, 0x40, 0x3f, 0x3e, 0xd3, 0x2a, 0x3d, 0x3d, 0xce, 0xc1, 0x2b, 0x3d, 0xd0, + 0x2b, 0xd3, 0x2b, 0x3b, 0x3d, 0xce, 0x29, 0x3b, 0x3b, 0x3b, 0xd1, 0xbe, 0x2b, 0xd2, 0x29, 0x3d, + 0x3a, 0xd3, 0x29, 0x3a, 0x3b, 0x3b, 0xd2, 0x26, 0x3b, 0xd0, 0xbf, 0xbe, 0xbc, 0xbf, 0xbe, 0xbc, + 0x27, 0x3d, 0x3a, 0x3c, 0xce, 0xc1, 0x2c, 0xd2, 0xc2, 0xc2, 0x2f, 0x40, 0xd2, 0xc2, 0xc2, 0x2e, + 0x40, 0xd4, 0x2a, 0x3b, 0xcf, 0x2b, 0xd2, 0x2a, 0x3c, 0xd0, 0xc1, 0x2a, 0x3d, 0xd0, 0xc1, 0xc0, + 0xbe, 0x2b, 0x3f, 0x3e, 0xd2, 0xc1, 0xc0, 0xc1, 0xc0, 0xc2, 0x2a, 0xd6, 0xc2, 0xc3, 0xc3, 0xc3, + 0x2c, 0x3e, 0x41, 0xd6, 0xc0, 0xc3, 0xc2, 0xc2, 0x2a, 0xd9, 0x28, 0x3f, 0xd5, 0xc1, 0xc2, 0xc0, + 0xc3, 0x28, 0xd5, 0xc2, 0xc5, 0x30, 0xd6, 0xc4, 0xc5, 0xc5, 0x31, 0x43, 0xd4, 0xc3, 0xc5, 0xc2, + 0xc2, 0x2f, 0xd6, 0xc5, 0xc2, 0x2d, 0x41, 0x41, 0x43, 0x40, 0x41, 0xd8, 0x2a, 0x3f, 0x3f, 0x3e, + 0x2c, 0x0a, 0x0d, 0x2a, 0xbb, 0x91, 0x5e, 0x2a, 0xca, 0x23, 0xf0, 0x0f, 0xbe, 0xd6, 0xfb, 0xc0, + 0x2c, 0x34, 0x7f, 0xd1, 0xc9, 0xc1, 0x1c, 0x06, 0x97, 0x1f, 0x21, 0xa8, 0x04, 0x5d, 0x07, 0xb0, + 0x49, 0xaf, 0x10, 0x60, 0xd1, 0xf1, 0xf3, 0xcb, 0x72, 0x16, 0x24, 0xe9, 0xd4, 0x28, 0xb2, 0x8c, + 0xf3, 0x3b, 0xe8, 0x06, 0xeb, 0x09, 0xec, 0x0a, 0xec, 0x0b, 0xee, 0x0b, 0xee, 0x0b, 0xf0, 0x0b, + 0xf0, 0x0a, 0xf3, 0x0b, 0xf2, 0x0a, 0xf5, 0x08, 0xf5, 0x0a, 0xf4, 0x08, 0xf5, 0x08, 0xf5, 0x09, + 0xf4, 0x07, 0x3f, 0xf5, 0x05, 0xf6, 0xbf, 0x06, 0x3f, 0x3f, 0xf8, 0xbe, 0x07, 0xf8, 0xc3, 0xc3, + 0x06, 0x41, 0x40, 0xf0, 0x0f, 0x3c, 0x3d, 0xef, 0x0e, 0xee, 0xbe, 0xbf, 0x11, 0xf2, 0x0e, 0x3e, + 0x3c, 0x3f, 0x3e, 0x3e, 0xf0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc1, 0x0b, 0x3f, 0xf5, + 0xc0, 0xc0, 0x08, 0xf7, 0xc2, 0x0c, 0xf6, 0x0d, 0xf9, 0x0a, 0x3f, 0xf9, 0xc0, 0x0b, 0xf6, 0x06, + 0xf8, 0x06, 0xf9, 0xc3, 0x08, 0x40, 0xfa, 0xc2, 0x09, 0x3e, 0xf7, 0x05, 0xf6, 0x04, 0xf7, 0x05, + 0xf8, 0xc1, 0xc3, 0xc1, 0x0a, 0x3e, 0x41, 0xf6, 0x07, 0xf7, 0x08, 0xf6, 0x07, 0x3e, 0x3c, 0x3f, + 0xf4, 0xbf, 0xbe, 0x06, 0xf8, 0x07, 0xf8, 0x05, 0xfb, 0xc0, 0xc1, 0x02, 0x40, 0x40, 0x3e, 0xfb, + 0x02, 0x3e, 0x3e, 0xf6, 0x01, 0xf9, 0x00, 0x3f, 0xf8, 0xbd, 0x02, 0xfc, 0xc1, 0xc0, 0x03, 0xfe, + 0xc5, 0xc4, 0xc2, 0xc5, 0xc2, 0x02, 0x41, 0x40, 0x40, 0x41, 0x40, 0xff, 0xff, 0x40, 0xfd, 0xfd, + 0xfc, 0xfd, 0x3e, 0xfc, 0xbe, 0xbf, 0xfe, 0xfc, 0xc1, 0xc0, 0xc1, 0xc1, 0x00, 0x01, 0x01, 0x02, + 0xc0, 0x00, 0x02, 0xc3, 0xc5, 0x02, 0x07, 0xc4, 0xc6, 0xc4, 0x02, 0x06, 0xc3, 0x01, 0x43, 0x43, + 0x42, 0x05, 0xfc, 0x04, 0xfd, 0x41, 0x3e, 0x05, 0xbf, 0xfb, 0x41, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, + 0x02, 0xf9, 0x3e, 0x03, 0xbf, 0xbe, 0xf6, 0x3f, 0x05, 0xf6, 0x3c, 0x05, 0xbd, 0xbf, 0xbe, 0xf2, + 0x3f, 0x3c, 0x3d, 0x3e, 0x08, 0xee, 0x3d, 0x3b, 0x07, 0xbd, 0xf3, 0x0e, 0xc0, 0xc0, 0xf2, 0x0f, + 0xf2, 0x40, 0x0d, 0xef, 0x3f, 0x3e, 0x0a, 0xbf, 0xf0, 0x0e, 0xf1, 0x40, 0x0a, 0xef, 0x0e, 0xc1, + 0xc0, 0xc1, 0xc2, 0xc0, 0xee, 0x13, 0xc1, 0xee, 0x43, 0x10, 0xea, 0x15, 0xc0, 0xc0, 0xc0, 0xc3, + 0xc0, 0xec, 0x15, 0xc2, 0xf0, 0x16, 0xc2, 0xef, 0x1b, 0xc2, 0xf1, 0x44, 0x42, 0x19, 0xc2, 0xc3, + 0xed, 0x17, 0xe7, 0x21, 0xe4, 0x40, 0x3f, 0x20, 0xc0, 0xe2, 0x40, 0x3e, 0x1d, 0xc1, 0xc2, 0xc0, + 0xe2, 0x20, 0xe2, 0x3f, 0x3f, 0x3e, 0x1c, 0xdf, 0x3c, 0x3f, 0x1e, 0xbf, 0xc1, 0xbe, 0xdf, 0x3e, + 0x3d, 0x1f, 0xdc, 0x3c, 0x3b, 0x3d, 0x3a, 0x3d, 0x1f, 0xdb, 0x1e, 0xda, 0x20, 0xda, 0x21, 0xc1, + 0xc0, 0xc1, 0xdc, 0x3e, 0x23, 0xda, 0x3e, 0x20, 0xbf, 0xbd, 0xdb, 0x23, 0xbf, 0xdf, 0x26, 0xdc, + 0x26, 0xdc, 0x2e, 0xc2, 0xc3, 0xc3, 0xd4, 0x40, 0x2f, 0xc2, 0xd2, 0x3f, 0x3f, 0x3f, 0x2e, 0xd1, + 0x2d, 0xd3, 0x2c, 0xc3, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xd3, 0x3e, 0x31, 0xd0, 0x2d, 0xc3, 0xc0, + 0xc1, 0xd1, 0x2f, 0xd3, 0x3f, 0x3f, 0x31, 0xc1, 0xcf, 0x31, 0xd2, 0x3e, 0x3f, 0x3c, 0x41, 0x3e, + 0x3e, 0x3f, 0x31, 0xd1, 0x30, 0xc0, 0xcf, 0x33, 0xd1, 0x3d, 0x41, 0x32, 0xc0, 0xc3, 0xce, 0x3e, + 0x32, 0xc3, 0xc3, 0xc2, 0xc0, 0xc3, 0xca, 0x3c, 0x37, 0xc5, 0xc3, 0xca, 0x34, 0xcf, 0x35, 0xc6, + 0xca, 0x3c, 0x39, 0xce, 0x3c, 0x37, 0xc2, 0xc8, 0x3c, 0x36, 0xcc, 0x30, 0xcb, 0x33, 0xc6, 0xc3, + 0xc8, 0x34, 0xcc, 0x3d, 0x37, 0xc5, 0xc9, 0x38, 0xc6, 0xca, 0x3b, 0x40, 0x40, 0x40, 0x3a, 0xc5, + 0xc8, 0x3f, 0x3e, 0x3b, 0xce, 0x3a, 0x3e, 0x38, 0xca, 0x39, 0x3c, 0x3c, 0x36, 0xcb, 0x36, 0x3b, + 0x37, 0xc8, 0x35, 0x3a, 0x36, 0xc8, 0x2f, 0xc4, 0xc5, 0x36, 0x38, 0xc7, 0xc0, 0xc7, 0x33, 0xc8, + 0xc3, 0xc5, 0x39, 0x3b, 0xc9, 0xc7, 0x34, 0xd1, 0x34, 0xcf, 0x35, 0xca, 0xc9, 0x36, 0xd0, 0x36, + 0xcc, 0xc7, 0x39, 0x41, 0x42, 0x42, 0x3e, 0xca, 0xc1, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xc4, 0xc6, + 0x34, 0xd1, 0x35, 0xcf, 0x37, 0x3c, 0xce, 0x35, 0x3b, 0xcc, 0x30, 0xca, 0x33, 0x39, 0xc9, 0xbf, + 0xbf, 0xbf, 0xc3, 0x34, 0x3c, 0x3f, 0x3a, 0xcc, 0x2f, 0xcd, 0x32, 0x3c, 0x3a, 0xc8, 0xc2, 0x34, + 0x3a, 0xcb, 0xc0, 0xc0, 0x35, 0x3c, 0xce, 0x32, 0x3c, 0x3c, 0x3d, 0x3a, 0xcd, 0x2e, 0x3b, 0x39, + 0xc9, 0xbc, 0xbf, 0x30, 0xcc, 0xc0, 0xc3, 0x33, 0xce, 0xc5, 0xc2, 0xc4, 0x36, 0x3e, 0xd1, 0xc3, + 0xc2, 0xc3, 0xc5, 0x33, 0xd0, 0xc5, 0xc4, 0x35, 0x40, 0x40, 0x3e, 0x41, 0x3e, 0xd2, 0x30, 0x3f, + 0x3e, 0x3d, 0x21, 0xc8, 0x0d, 0x23, 0xec, 0xb1, 0x1a, 0xf0, 0xf3, 0x10, 0xc6, 0xbd, 0x5b, 0x0d, + 0xff, 0xe2, 0xe6, 0xd4, 0x72, 0xe2, 0xda, 0x0c, 0xf8, 0x1b, 0x04, 0x0b, 0xf7, 0xb4, 0xf0, 0x44, + 0xcd, 0xaf, 0x12, 0x1f, 0x11, 0xa1, 0x29, 0xb8, 0x1a, 0xdb, 0x09, 0x69, 0xf7, 0x20, 0xc4, 0x1c, + 0xc0, 0xc8, 0x1d, 0x45, 0xd9, 0x30, 0xd8, 0x2e, 0xd8, 0x2e, 0xd6, 0x2c, 0xd5, 0x2d, 0xd4, 0x2b, + 0xd5, 0x2b, 0xd1, 0x31, 0xd0, 0x32, 0xd2, 0x30, 0xd0, 0x31, 0xd0, 0x31, 0xce, 0x2f, 0xd3, 0x2e, + 0xce, 0x2f, 0xd1, 0x31, 0x3c, 0xd1, 0x2d, 0xd0, 0xc0, 0x2e, 0x3c, 0x3d, 0xd1, 0xc3, 0x2c, 0xd2, + 0xc3, 0xc5, 0x31, 0x40, 0x40, 0xd5, 0x2c, 0x3a, 0x3d, 0xd0, 0x2b, 0xd3, 0xc0, 0xc0, 0x2d, 0xd4, + 0x2c, 0x3f, 0x3e, 0x3c, 0x3f, 0x3c, 0xd2, 0xc1, 0xc2, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0x2a, +}; + + +void +ao_real_packet(void) +{ + uint8_t decode[64]; + uint8_t decode_len; + int off; + + for (off = 0; off < sizeof (real_packet) - 576; off++) { + decode_len = ao_fec_decode(real_packet+off, 576, decode); + + if (ao_fec_check_crc(decode, 32)) { + printf ("match at %d\n", off); + + ao_fec_dump_bytes(decode, decode_len, "Decode"); + } + } +} + int main(int argc, char **argv) { @@ -149,6 +299,7 @@ main(int argc, char **argv) int errors = 0; int error; + ao_real_packet(); exit(0); srandom(0); for (trial = 0; trial < 10000; trial++) { -- cgit v1.2.3 From 628076aa90e7bc9a894646e417dd8e1fe149b60d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:38:34 -0700 Subject: altos: decode cc1120 received packets Call the fec decode function, compute RSSI and check CRC Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_viterbi.c | 7 +++++-- src/drivers/ao_cc1120.c | 47 ++++++++++++++++++++++++++--------------------- 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f3f55fa8..e3c55d6e 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -67,7 +67,7 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 594c0d91..77681556 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -203,7 +203,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } o += 8; } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 4378716d..b42ca54c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -401,12 +401,12 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; static uint16_t rx_data_cur; -static uint8_t rx_started; +static uint8_t rx_ignore; static void ao_radio_rx_isr(void) { - if (rx_started) { + if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) { ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); @@ -415,7 +415,7 @@ ao_radio_rx_isr(void) } } else { (void) stm_spi2.dr; - rx_started = 1; + --rx_ignore; } stm_spi2.dr = 0x00; } @@ -423,12 +423,17 @@ ao_radio_rx_isr(void) uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint8_t len; uint16_t i; + uint8_t rssi; - rx_data_count = sizeof (rx_data); + size -= 2; /* status bytes */ + len = size + 2; /* CRC bytes */ + len += 1 + ~(len & 1); /* 1 or two pad bytes */ + len *= 2; /* 1/2 rate convolution */ + rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; - rx_started = 0; + rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -456,31 +461,31 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); -#if 1 cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); sei(); - -#else - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -#endif ao_radio_burst_read_stop(); + /* Convert from 'real' rssi to cc1111-style values */ + + rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + ao_radio_strobe(CC1120_SIDLE); ao_radio_put(); - printf ("Received data:"); - for (i = 0; i < rx_data_cur; i++) { - if ((i & 15) == 0) - printf ("\n"); - printf (" %02x", rx_data[i]); - } - printf ("\n"); + /* Construct final packet */ + + ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + + if (ao_fec_check_crc(d, size)) + ((uint8_t *) d)[size + 1] = 0x80; + else + ((uint8_t *) d)[size + 1] = 0x00; + + ((uint8_t *) d)[size] = (uint8_t) rssi; + return 1; } -- cgit v1.2.3 From 09761fe0f6ed40ff74317fbb47d6a74068fb4ce4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:51:36 -0700 Subject: altos: Incremental viterbi decode Decode radio input one interleave block at a time. This overlaps the decode computation with the packet reception, leading to lower latency in an attempt to keep up with the transmitter. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 4 +++- src/core/ao_viterbi.c | 14 +++++++++++++- src/drivers/ao_cc1120.c | 28 +++++++++++++++++++++------- src/test/ao_fec_test.c | 4 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index e3c55d6e..4fd398eb 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -66,8 +66,10 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); * 'out' must be len/8 bytes long */ +#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ + uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 77681556..69e9c1f5 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -105,6 +105,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -113,11 +114,22 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) } cost[0][0] = 0; + if (callback) + avail = 0; + else + avail = len; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; + if (!avail) { + avail = callback(); + if (!avail) + break; + } + /* Fetch one pair of input bytes, de-interleaving * the input. */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index b42ca54c..394cf7c5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -400,6 +400,7 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; +static uint16_t rx_data_consumed; static uint16_t rx_data_cur; static uint8_t rx_ignore; @@ -408,9 +409,9 @@ ao_radio_rx_isr(void) { if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; - if (rx_data_cur >= rx_data_count) { + if (rx_data_cur >= rx_data_count) ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; + if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { ao_wakeup(&ao_radio_wake); } } else { @@ -420,6 +421,19 @@ ao_radio_rx_isr(void) stm_spi2.dr = 0x00; } +static uint16_t +ao_radio_rx_wait(void) +{ + cli(); + while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && + !ao_radio_abort) + ao_sleep(&ao_radio_wake); + sei(); + if (ao_radio_abort) + return 0; + return AO_FEC_DECODE_BLOCK; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { @@ -433,6 +447,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) len *= 2; /* 1/2 rate convolution */ rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; + rx_data_consumed = 0; rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -461,10 +476,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); + + ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ao_radio_burst_read_stop(); /* Convert from 'real' rssi to cc1111-style values */ @@ -477,7 +491,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); if (ao_fec_check_crc(d, size)) ((uint8_t *) d)[size + 1] = 0x80; diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 98067486..e8d3d8b1 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -266,7 +266,7 @@ ao_real_packet(void) int off; for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode); + decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); if (ao_fec_check_crc(decode, 32)) { printf ("match at %d\n", off); @@ -317,7 +317,7 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode); + decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; -- cgit v1.2.3 From eab18714ed9eabbcef0ff81b07427da042a58ccc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:16:44 -0700 Subject: altos: rename ao_viterbi.c to ao_fec_rx.c Keep it parallel with ao_fec_tx.c Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 226 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_viterbi.c | 226 ------------------------------------------- src/megametrum-v0.1/Makefile | 2 +- src/test/Makefile | 4 +- 4 files changed, 229 insertions(+), 229 deletions(-) create mode 100644 src/core/ao_fec_rx.c delete mode 100644 src/core/ao_viterbi.c diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c new file mode 100644 index 00000000..69e9c1f5 --- /dev/null +++ b/src/core/ao_fec_rx.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + +struct ao_soft_sym { + uint8_t a, b; +}; + +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +#define V_0 0xc0 +#define V_1 0x40 + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { +/* next 0 1 state */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ +}; + +static inline uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } + +static inline uint16_t +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); +} + +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +{ + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; + + p = 0; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + bits[0][state] = 0; + } + cost[0][0] = 0; + + if (callback) + avail = 0; + else + avail = len; + + o = 0; + for (i = 0; i < len; i += 2) { + b = i/2; + n = p ^ 1; + + if (!avail) { + avail = callback(); + if (!avail) + break; + } + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; + + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ + for (state = 0; state < NUM_STATE; state++) { + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } + } + } + +#if 0 + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d(%04x)", cost[n][state], bits[n][state]); + } + printf ("\n"); +#endif + p = n; + + /* A loop is needed to handle the last output byte. It + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; + } + +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); +#endif + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } + o += 8; + } + } + return len/16; +} diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c deleted file mode 100644 index 69e9c1f5..00000000 --- a/src/core/ao_viterbi.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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 -#include - -/* - * byte order repeats through 3 2 1 0 - * - * bit-pair order repeats through - * - * 1/0 3/2 5/4 7/6 - * - * So, the over all order is: - * - * 3,1/0 2,1/0 1,1/0 0,1/0 - * 3,3/2 2,3/2 1,3/2 0,3/2 - * 3,5/4 2,5/4 1,5/4 0,5/4 - * 3,7/6 2,7/6 1,7/6 0,7/6 - * - * The raw bit order is thus - * - * 1e/1f 16/17 0e/0f 06/07 - * 1c/1d 14/15 0c/0d 04/05 - * 1a/1b 12/13 0a/0b 02/03 - * 18/19 10/11 08/09 00/01 - */ - -static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; -} - -struct ao_soft_sym { - uint8_t a, b; -}; - -#define NUM_STATE 8 -#define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ -}; - -static inline uint8_t -ao_next_state(uint8_t state, uint8_t bit) -{ - return ((state << 1) | bit) & 0x7; -} - -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - -/* - * 'in' is 8-bits per symbol soft decision data - * 'len' is input byte length. 'out' must be - * 'len'/16 bytes long - */ - -uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) -{ - static uint16_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ - uint16_t i; /* input byte index */ - uint16_t b; /* encoded symbol index (bytes/2) */ - uint16_t o; /* output bit index */ - uint8_t p; /* previous cost/bits index */ - uint8_t n; /* next cost/bits index */ - uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ - const uint8_t *whiten = ao_fec_whiten_table; - uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ - uint16_t avail; - - p = 0; - for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; - bits[0][state] = 0; - } - cost[0][0] = 0; - - if (callback) - avail = 0; - else - avail = len; - - o = 0; - for (i = 0; i < len; i += 2) { - b = i/2; - n = p ^ 1; - - if (!avail) { - avail = callback(); - if (!avail) - break; - } - - /* Fetch one pair of input bytes, de-interleaving - * the input. - */ - interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; - - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; - - /* Compute path costs and accumulate output bit path - * for each state and encoded bit value - */ - for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); - } - } - } - -#if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); - } - printf ("\n"); -#endif - p = n; - - /* A loop is needed to handle the last output byte. It - * won't have any bits of future data to perform full - * error correction, but we might as well give the - * best possible answer anyways. - */ - while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { - - /* Compute number of bits to the end of the - * last full byte of data. This is generally - * NUM_HIST, unless we've reached - * the end of the input, in which case - * it will be seven. - */ - int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ - uint8_t min_state; /* lowest cost state */ - - /* Find the best fit at the current point - * of the decode. - */ - min_cost = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < min_cost) { - min_cost = cost[p][state]; - min_state = state; - } - } - - /* The very last byte of data has the very last bit - * of data left in the state value; just smash the - * bits value in place and reset the 'dist' from - * -1 to 0 so that the full byte is read out - */ - if (dist < 0) { - bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); - dist = 0; - } - -#if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); -#endif - if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; - --out_len; - } - o += 8; - } - } - return len/16; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 857667b0..22a58ff4 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -48,7 +48,7 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_cc1120.c \ ao_fec_tx.c \ - ao_viterbi.c \ + ao_fec_rx.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index cdcecd51..4631fb78 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c + cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm -- cgit v1.2.3 From 9dcb4e2ab60ecf0cc7371c1b1a620be952fa8776 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:19:01 -0700 Subject: altosui: AltosSerial and AltosLink both tried to provide frequency setting AltosLink owns all of the device configuration, so remove that from AltosSerial and make sure that AltosLink provides the right function signatures (wasn't using the new direct frequency setting command). Signed-off-by: Keith Packard --- altoslib/AltosLink.java | 28 ++++++++----------------- altosui/AltosSerial.java | 53 ------------------------------------------------ 2 files changed, 9 insertions(+), 72 deletions(-) diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 77b400fc..a39204ac 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -166,6 +166,15 @@ public abstract class AltosLink { set_channel(AltosConvert.radio_frequency_to_channel(frequency)); } + public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { + frequency = in_frequency; + config_data(); + set_radio_frequency(frequency, + config_data.radio_frequency != 0, + config_data.radio_setting != 0, + config_data.radio_calibration); + } + public void set_telemetry(int in_telemetry) { telemetry = in_telemetry; if (monitor_mode) @@ -200,31 +209,12 @@ public abstract class AltosLink { flush_output(); } - public void set_radio_frequency(double frequency, - boolean has_setting, - int cal) { - if (debug) - System.out.printf("set_radio_frequency %7.3f %b %d\n", frequency, has_setting, cal); - if (has_setting) - set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); - else - set_channel(AltosConvert.radio_frequency_to_channel(frequency)); - } - public AltosConfigData config_data() throws InterruptedException, TimeoutException { if (config_data == null) config_data = new AltosConfigData(this); return config_data; } - public void set_radio_frequency(double in_frequency) throws InterruptedException, TimeoutException { - frequency = in_frequency; - config_data(); - set_radio_frequency(frequency, - config_data.radio_setting != 0, - config_data.radio_calibration); - } - public void set_callsign(String callsign) { printf ("c c %s\n", callsign); flush_output(); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 5768ba71..8b60dd54 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -264,59 +264,6 @@ public class AltosSerial extends AltosLink implements Runnable { flush_output(); } - private int telemetry_len() { - return Altos.telemetry_len(telemetry); - } - - private void set_channel(int channel) { - if (altos != null) { - if (monitor_mode) - printf("m 0\nc r %d\nm %x\n", - channel, telemetry_len()); - else - printf("c r %d\n", channel); - flush_output(); - } - } - - private void set_radio_setting(int setting) { - if (altos != null) { - if (monitor_mode) - printf("m 0\nc R %d\nm %x\n", - setting, telemetry_len()); - else - printf("c R %d\n", setting); - flush_output(); - } - } - - private void set_radio_freq(int frequency) { - if (altos != null) { - if (monitor_mode) - printf("m 0\nc F %d\nm %x\n", - frequency, telemetry_len()); - else - printf("c F %d\n", frequency); - flush_output(); - } - } - - public void set_radio_frequency(double frequency, - boolean has_frequency, - boolean has_setting, - int cal) { - if (debug) - System.out.printf("set_radio_frequency %7.3f (freq %b) (set %b) %d\n", frequency, has_frequency, has_setting, cal); - if (frequency == 0) - return; - if (has_frequency) - set_radio_freq((int) Math.floor (frequency * 1000)); - else if (has_setting) - set_radio_setting(AltosConvert.radio_frequency_to_setting(frequency, cal)); - else - set_channel(AltosConvert.radio_frequency_to_channel(frequency)); - } - public void set_frame(Frame in_frame) { frame = in_frame; } -- cgit v1.2.3 From f11f05c5d634de2a80c34d0d3dc93925980f52e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:20:50 -0700 Subject: altosui: Make libaltos recognise new USB ids libaltos has a small range of 'AltusMetrum' products to avoid opening other devices. We've got more IDs, so open up the range. Signed-off-by: Keith Packard --- altosui/libaltos/libaltos.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 48e00a44..1cc27cbe 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -23,12 +23,8 @@ #define USB_VENDOR_FSF 0xfffe #define USB_VENDOR_ALTUSMETRUM USB_VENDOR_FSF #define USB_PRODUCT_ALTUSMETRUM 0x000a -#define USB_PRODUCT_TELEMETRUM 0x000b -#define USB_PRODUCT_TELEDONGLE 0x000c -#define USB_PRODUCT_TELETERRA 0x000d -#define USB_PRODUCT_TELEBT 0x000e #define USB_PRODUCT_ALTUSMETRUM_MIN 0x000a -#define USB_PRODUCT_ALTUSMETRUM_MAX 0x0013 +#define USB_PRODUCT_ALTUSMETRUM_MAX 0x00ff #define USB_IS_ALTUSMETRUM(v,p) ((v) == USB_VENDOR_ALTUSMETRUM && \ (USB_PRODUCT_ALTUSMETRUM_MIN <= (p) && \ -- cgit v1.2.3 From 03dc80d15a2f8fe9d7340351226dadd8bc3cfdb9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:01:58 -0700 Subject: altos: Clean up usage of port parameters Make stm port parameters always be pointers; this avoids the confusion where some macros took '&port' and others took a bare 'port', and also unifies code to run on other processors in a consistent fashion. Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 24 ++++++--- src/cc1111/ao_pins.h | 27 +++++++--- src/drivers/ao_25lc1024.c | 11 ++--- src/drivers/ao_at45db161d.c | 4 +- src/drivers/ao_companion.c | 49 ++++++++++++------- src/drivers/ao_hmc5883.c | 6 +-- src/drivers/ao_ms5607.c | 14 +++--- src/megametrum-v0.1/ao_pins.h | 111 ++++++++++++++++++++++++++++++++++-------- src/stm-demo/ao_pins.h | 4 +- src/stm/ao_adc_stm.c | 30 ++++++------ src/stm/ao_arch_funcs.h | 36 ++++++++++---- src/stm/ao_led.c | 17 ++++--- 12 files changed, 230 insertions(+), 103 deletions(-) diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index d9f5955a..728f1f76 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -31,14 +31,14 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit,bus) do { \ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ +#define ao_spi_get_bit(reg,bit,pin,bus) do { \ + ao_mutex_get(&ao_spi_mutex); \ + pin = 0; \ } while (0) -#define ao_spi_put_bit(bit,bus) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_bit(reg,bit,pin,bus) do { \ + pin = 1; \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) @@ -65,3 +65,15 @@ ao_spi_init(void); SPI_CS_DIR |= mask; \ SPI_CS_SEL &= ~mask; \ } while (0) + +#define cc1111_enable_output(port,dir,sel,mask,v) do { \ + port = port & ~(mask) | v; \ + dir |= mask; \ + sel &= ~mask; \ +} while (0) + +#define disable_unreachable _Pragma("disable_warning 126") + +#define token_paster(x,y) x ## y +#define token_evaluator(x,y) token_paster(x,y) +#define ao_enable_output(port,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), 1 << pin, 1 << v) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 0923e75d..e28a7b65 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -41,8 +41,9 @@ #define HAS_COMPANION 1 #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -72,9 +73,9 @@ #define PACKET_HAS_SLAVE 1 #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -108,9 +109,9 @@ #define PACKET_HAS_SLAVE 1 #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -527,21 +528,31 @@ #endif /* HAS_ADC */ #if IGNITE_ON_P2 +#define AO_IGNITER_PORT P2 +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT #define AO_IGNITER_DROGUE P2_3 #define AO_IGNITER_MAIN P2_4 #define AO_IGNITER_DIR P2DIR #define AO_IGNITER_DROGUE_BIT (1 << 3) #define AO_IGNITER_MAIN_BIT (1 << 4) +#define AO_IGNITER_DROGUE_PIN 3 +#define AO_IGNITER_MAIN_PIN 4 #endif #if IGNITE_ON_P0 +#define AO_IGNITER_PORT P0 #define AO_IGNITER_DROGUE P0_5 #define AO_IGNITER_MAIN P0_4 #define AO_IGNITER_DIR P0DIR #define AO_IGNITER_DROGUE_BIT (1 << 5) #define AO_IGNITER_MAIN_BIT (1 << 4) +#define AO_IGNITER_DROGUE_PIN 5 +#define AO_IGNITER_MAIN_PIN 4 #endif +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT +#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT + /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 #define AO_IGNITER_CLOSED 7000 diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index f0fb13c9..b25d52c4 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -38,8 +38,9 @@ __pdata uint16_t ao_storage_unit; * Using SPI on USART 0, with P1_2 as the chip select */ +#define EE_CS_PORT P1 #define EE_CS P1_2 -#define EE_CS_INDEX 2 +#define EE_CS_PIN 2 static __xdata uint8_t ao_ee_mutex; @@ -49,9 +50,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) struct ao_ee_instruction { uint8_t instruction; @@ -235,7 +236,5 @@ void ao_storage_device_init(void) { /* set up CS */ - EE_CS = 1; - P1DIR |= (1 << EE_CS_INDEX); - P1SEL &= ~(1 << EE_CS_INDEX); + ao_enable_output(EE_CS_PORT, EE_CS_PIN,1); } diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index afe0080b..5eb25acf 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,9 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) struct ao_flash_instruction { uint8_t instruction; diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index fe88e998..a31cc2ea 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -15,20 +15,36 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) - -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS, AO_COMPANION_BUS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS, AO_COMPANION_BUS); } while (0) +#include +#include + +#ifndef ao_spi_slow +#define ao_spi_slow(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) +#endif + +#define COMPANION_SELECT() do { \ + ao_spi_get_bit(AO_COMPANION_CS_PORT, \ + AO_COMPANION_CS_PIN, \ + AO_COMPANION_CS, \ + AO_COMPANION_SPI_BUS); \ + ao_spi_slow(AO_COMPANION_SPI_BUS); \ + } while (0) + +#define COMPANION_DESELECT() do { \ + ao_spi_fast(AO_COMPANION_SPI_BUS); \ + ao_spi_put_bit(AO_COMPANION_CS_PORT, \ + AO_COMPANION_CS_PIN, \ + AO_COMPANION_CS, \ + AO_COMPANION_SPI_BUS); \ + } while (0) __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; @@ -123,10 +139,7 @@ static __xdata struct ao_task ao_companion_task; void ao_companion_init(void) { - COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ - COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ - COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ - + ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, 1); ao_cmd_register(&ao_companion_cmds[0]); ao_add_task(&ao_companion_task, ao_companion, "companion"); } diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 1bc914e6..64663ea6 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -58,7 +58,7 @@ static uint8_t ao_hmc5883_done; static void ao_hmc5883_isr(void) { - ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_exti_disable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_done = 1; ao_wakeup(&ao_hmc5883_done); } @@ -71,7 +71,7 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) uint8_t single = HMC5883_MODE_SINGLE; ao_hmc5883_done = 0; - ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); cli(); @@ -159,7 +159,7 @@ ao_hmc5883_init(void) ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); - ao_exti_setup(&AO_HMC5883_INT_PORT, + ao_exti_setup(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 0f0625d0..e08f4d40 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -25,12 +25,12 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { ao_spi_get(AO_MS5607_SPI_INDEX); - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); } static void ao_ms5607_stop(void) { - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); ao_spi_put(AO_MS5607_SPI_INDEX); } @@ -132,12 +132,12 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_exti_enable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); cli(); while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); - ao_exti_disable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); ao_ms5607_start(); @@ -203,7 +203,7 @@ ao_ms5607(void) ao_ms5607_setup(); for (;;) { - struct ao_ms5607_sample ao_ms5607_next; + static struct ao_ms5607_sample ao_ms5607_next; ao_ms5607_sample(&ao_ms5607_next); ao_arch_critical( ao_ms5607_current = ao_ms5607_next; @@ -260,7 +260,7 @@ ao_ms5607_init(void) * conversion is complete, the MS5607 will raise this * pin as a signal */ - ao_exti_setup(&AO_MS5607_MISO_GPIO, + ao_exti_setup(AO_MS5607_MISO_GPIO, AO_MS5607_MISO, AO_EXTI_MODE_RISING, ao_ms5607_isr); @@ -268,7 +268,7 @@ ao_ms5607_init(void) /* Reset the pin from INPUT to ALTERNATE so that SPI works * This needs an abstraction at some point... */ - stm_moder_set(&AO_MS5607_MISO_GPIO, + stm_moder_set(AO_MS5607_MISO_GPIO, AO_MS5607_MISO, STM_MODER_ALTERNATE); } diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 9d9113c8..f5bd3e0d 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -76,7 +76,7 @@ #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 #define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_GPIO stm_gpiob +#define SPI_2_GPIO (&stm_gpiob) #define SPI_2_SCK 13 #define SPI_2_MISO 14 #define SPI_2_MOSI 15 @@ -87,12 +87,13 @@ #define HAS_I2C_2 1 #define I2C_2_PB10_PB11 1 -#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_MASTER 0 -#define LOW_LEVEL_DEBUG 1 +#define LOW_LEVEL_DEBUG 0 #define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT stm_gpioc +#define LED_PORT (&stm_gpioc) #define LED_PIN_RED 8 #define LED_PIN_GREEN 9 #define AO_LED_RED (1 << LED_PIN_RED) @@ -107,6 +108,48 @@ #define HAS_ACCEL_REF 1 #define HAS_LOG 1 +/* + * Igniter + */ + +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_PORT_A (&stm_gpiod) +#define AO_IGNITER_PIN_A 6 + +#define AO_IGNITER_PORT_B (&stm_gpiod) +#define AO_IGNITER_PIN_B 7 + +#define AO_IGNITER_PORT_C (&stm_gpiob) +#define AO_IGNITER_PIN_C 5 + +#define AO_IGNITER_PORT_D (&stm_gpioe) +#define AO_IGNITER_PIN_D 4 + +#define AO_IGNITER_PORT_E (&stm_gpioe) +#define AO_IGNITER_PIN_E 6 + +#define AO_IGNITER_PORT_F (&stm_gpioe) +#define AO_IGNITER_PIN_F 5 + +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT_A +#define AO_IGNITER_DROGUE_PIN AO_IGNITER_PIN_A + +#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT_B +#define AO_IGNITER_MAIN_PIN AO_IGNITER_PIN_B + +#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) +#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) + +/* + * ADC + */ #define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 @@ -120,43 +163,43 @@ struct ao_adc { }; #define AO_ADC_SENSE_A 0 -#define AO_ADC_SENSE_A_PORT stm_gpioa +#define AO_ADC_SENSE_A_PORT (&stm_gpioa) #define AO_ADC_SENSE_A_PIN 0 #define AO_ADC_SENSE_B 1 -#define AO_ADC_SENSE_B_PORT stm_gpioa +#define AO_ADC_SENSE_B_PORT (&stm_gpioa) #define AO_ADC_SENSE_B_PIN 1 #define AO_ADC_SENSE_C 2 -#define AO_ADC_SENSE_C_PORT stm_gpioa +#define AO_ADC_SENSE_C_PORT (&stm_gpioa) #define AO_ADC_SENSE_C_PIN 2 #define AO_ADC_SENSE_D 3 -#define AO_ADC_SENSE_D_PORT stm_gpioa +#define AO_ADC_SENSE_D_PORT (&stm_gpioa) #define AO_ADC_SENSE_D_PIN 3 #define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT stm_gpioa +#define AO_ADC_SENSE_E_PORT (&stm_gpioa) #define AO_ADC_SENSE_E_PIN 4 #define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT stm_gpioe +#define AO_ADC_SENSE_F_PORT (&stm_gpioe) #define AO_ADC_SENSE_F_PIN 7 #define AO_ADC_V_BATT 8 -#define AO_ADC_V_BATT_PORT stm_gpiob +#define AO_ADC_V_BATT_PORT (&stm_gpiob) #define AO_ADC_V_BATT_PIN 0 #define AO_ADC_V_PBATT 9 -#define AO_ADC_V_PBATT_PORT stm_gpiob +#define AO_ADC_V_PBATT_PORT (&stm_gpiob) #define AO_ADC_V_PBATT_PIN 1 #define AO_ADC_ACCEL_REF 10 -#define AO_ADC_ACCEL_REF_PORT stm_gpioc +#define AO_ADC_ACCEL_REF_PORT (&stm_gpioc) #define AO_ADC_ACCEL_REF_PIN 0 #define AO_ADC_ACCEL 11 -#define AO_ADC_ACCEL_PORT stm_gpioc +#define AO_ADC_ACCEL_PORT (&stm_gpioc) #define AO_ADC_ACCEL_PIN 1 #define AO_ADC_TEMP 16 @@ -207,10 +250,10 @@ struct ao_adc { * Pressure sensor settings */ #define HAS_MS5607 1 -#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS_GPIO (&stm_gpioc) #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_GPIO stm_gpioa +#define AO_MS5607_MISO_GPIO (&stm_gpioa) #define AO_MS5607_MISO 6 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) @@ -220,7 +263,7 @@ struct ao_adc { */ #define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT stm_gpiod +#define AO_M25_SPI_CS_PORT (&stm_gpiod) #define AO_M25_SPI_CS_MASK (1 << 3) #define AO_M25_SPI_BUS STM_SPI_INDEX(2) @@ -228,21 +271,23 @@ struct ao_adc { * Radio (cc1120) */ -#define AO_CC1120_SPI_CS_PORT stm_gpioc +#define AO_FEC_DEBUG 1 +#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 #define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) -#define AO_CC1120_INT_PORT stm_gpioc +#define AO_CC1120_INT_PORT (&stm_gpioc) #define AO_CC1120_INT_PIN 14 #define AO_CC1120_INT_GPIO 2 +#define HAS_BOOT_RADIO 1 /* * Mag sensor (hmc5883) */ #define HAS_HMC5883 1 -#define AO_HMC5883_INT_PORT stm_gpioc +#define AO_HMC5883_INT_PORT (&stm_gpioc) #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) @@ -251,7 +296,7 @@ struct ao_adc { */ #define HAS_MPU6000 1 -#define AO_MPU6000_INT_PORT stm_gpioc +#define AO_MPU6000_INT_PORT (&stm_gpioc) #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) @@ -259,4 +304,28 @@ struct ao_adc { #define NUM_CMDS 16 +/* + * Companion + */ + +#define AO_COMPANION_CS_PORT (&stm_gpiod) +#define AO_COMPANION_CS_PIN (0) +#define AO_COMPANION_SPI_BUS STM_SPI_INDEX(2) + +/* + * Monitor + */ + +#define HAS_MONITOR 0 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED 0 +#define HAS_RSSI 0 + +/* + * Profiling Viterbi decoding + */ + +#define AO_PROFILE 0 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index d02c071c..7e222122 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -70,7 +70,7 @@ #define LOW_LEVEL_DEBUG 1 #define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN -#define LED_PORT stm_gpiob +#define LED_PORT (&stm_gpiob) #define LED_PIN_GREEN 7 #define LED_PIN_BLUE 6 #define AO_LED_GREEN (1 << LED_PIN_GREEN) @@ -147,7 +147,7 @@ struct ao_adc { }; #define AO_ADC_IDD 4 -#define AO_ADC_PIN0_PORT stm_gpioa +#define AO_ADC_PIN0_PORT (&stm_gpioa) #define AO_ADC_PIN0_PIN 4 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index ed1d20c9..7564c7fa 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -156,43 +156,43 @@ ao_adc_init(void) #endif #ifdef AO_ADC_PIN0_PORT - stm_moder_set(&AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN1_PORT - stm_moder_set(&AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN2_PORT - stm_moder_set(&AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN3_PORT - stm_moder_set(&AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN4_PORT - stm_moder_set(&AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN5_PORT - stm_moder_set(&AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN6_PORT - stm_moder_set(&AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN7_PORT - stm_moder_set(&AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN8_PORT - stm_moder_set(&AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN9_PORT - stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN10_PORT - stm_moder_set(&AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN11_PORT - stm_moder_set(&AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN12_PORT - stm_moder_set(&AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); #endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); @@ -281,8 +281,10 @@ ao_adc_init(void) #endif /* Clear any stale status bits */ stm_adc.sr = 0; - ao_adc_ready = 1; ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + ao_cmd_register(&ao_adc_cmds[0]); + + ao_adc_ready = 1; } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 447042dd..62b10063 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -40,36 +40,54 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); +#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 + +extern uint16_t ao_spi_speed[STM_NUM_SPI]; + +#define ao_spi_slow(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_200kHz) + +#define ao_spi_fast(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_FAST) + void ao_spi_init(void); #define ao_spi_get_mask(reg,mask,bus) do { \ ao_spi_get(bus); \ - (reg).bsrr = ((uint32_t) mask) << 16; \ + (reg)->bsrr = ((uint32_t) mask) << 16; \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ - (reg).bsrr = mask; \ + (reg)->bsrr = mask; \ ao_spi_put(bus); \ } while (0) +#define ao_spi_get_bit(reg,bit,pin,bus) ao_spi_get_mask(reg,(1<bsrr = (colors & ao_led_enable); } void ao_led_off(uint16_t colors) { - LED_PORT.odr &= ~(colors & ao_led_enable); + LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16; } void ao_led_set(uint16_t colors) { - LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); + uint16_t on = colors & ao_led_enable; + uint16_t off = ~colors & ao_led_enable; + + LED_PORT->bsrr = off << 16 | on; } void ao_led_toggle(uint16_t colors) { - LED_PORT.odr ^= (colors & ao_led_enable); + LED_PORT->odr ^= (colors & ao_led_enable); } void @@ -58,11 +61,11 @@ ao_led_init(uint16_t enable) stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); ao_led_enable = enable; - LED_PORT.odr &= ~enable; + LED_PORT->odr &= ~enable; for (bit = 0; bit < 16; bit++) { if (enable & (1 << bit)) { - stm_moder_set(&LED_PORT, bit, STM_MODER_OUTPUT); - stm_otyper_set(&LED_PORT, bit, STM_OTYPER_PUSH_PULL); + stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); } } } -- cgit v1.2.3 From 33f8f7add27a02d24b0671da353b59762224c1ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:05:42 -0700 Subject: altos: Make cc1111 radio control functions static No need to publish these; they're all private to cc1111 Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 8 +++++--- src/core/ao.h | 13 +------------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 51ed369b..2c4a661e 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -260,7 +260,7 @@ ao_radio_general_isr(void) __interrupt 16 } } -void +static void ao_radio_set_packet(void) { uint8_t i; @@ -268,7 +268,7 @@ ao_radio_set_packet(void) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; } -void +static void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -280,7 +280,9 @@ ao_radio_idle(void) } } -void +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void ao_radio_get(uint8_t len) { ao_config_get(); diff --git a/src/core/ao.h b/src/core/ao.h index 204c8530..c13029bf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,15 +505,7 @@ void ao_radio_general_isr(void) ao_arch_interrupt(16); void -ao_radio_get(uint8_t len); - -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) - -void -ao_radio_set_packet(void); - -void -ao_radio_send(__xdata void *d, uint8_t size) __reentrant; +ao_radio_send(const __xdata void *d, uint8_t size) __reentrant; uint8_t ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; @@ -537,9 +529,6 @@ ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); -void -ao_radio_idle(void); - void ao_radio_init(void); -- cgit v1.2.3 From 936ecad62596f34773afb7460b10f63df7d0896d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:07:38 -0700 Subject: altos: Add GPS logging code for MegaMetrum MM uses a different logging format with larger log blocks, so restructure the GPS logging code to fill them up Signed-off-by: Keith Packard --- src/core/ao.h | 10 +++++ src/core/ao_gps_report_mega.c | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/core/ao_gps_report_mega.c diff --git a/src/core/ao.h b/src/core/ao.h index c13029bf..62eb488e 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -396,6 +396,16 @@ ao_gps_report(void); void ao_gps_report_init(void); +/* + * ao_gps_report_mega.c + */ + +void +ao_gps_report_mega(void); + +void +ao_gps_report_mega_init(void); + /* * ao_telemetry_orig.c */ diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c new file mode 100644 index 00000000..47891cab --- /dev/null +++ b/src/core/ao_gps_report_mega.c @@ -0,0 +1,95 @@ +/* + * Copyright © 2009 Keith Packard + * + * 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" + +void +ao_gps_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; + + gps_log.u.gps.hour = gps_data.hour; + gps_log.u.gps.minute = gps_data.minute; + gps_log.u.gps.second = gps_data.second; + gps_log.u.gps.flags = gps_data.flags; + gps_log.u.gps.year = gps_data.year; + gps_log.u.gps.month = gps_data.month; + gps_log.u.gps.day = gps_data.day; + ao_log_mega(&gps_log); + } +} + +void +ao_gps_tracking_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n, i; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + gps_log.tick = ao_gps_tick; + i = 0; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; + } + gps_log.u.gps_sat.channels = i; + ao_log_mega(&gps_log); + } +} + +__xdata struct ao_task ao_gps_report_mega_task; +__xdata struct ao_task ao_gps_tracking_report_mega_task; + +void +ao_gps_report_mega_init(void) +{ + ao_add_task(&ao_gps_report_mega_task, + ao_gps_report_mega, + "gps_report"); + ao_add_task(&ao_gps_tracking_report_mega_task, + ao_gps_tracking_report_mega, + "gps_tracking_report"); +} -- cgit v1.2.3 From f1ae622eff60e05c1f5d8f822a3cf6a85750c6cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:11:10 -0700 Subject: altos: Optimize FEC encode and decode Integrate interleaving, CRC and padding within the decode/encode functions. Provide for ISR priorities so that the 1120 RX interrupt takes precedence over the other interrupts or we risk losing bits. Optimize the viterbi decoder a bit (goes from 10ms per packet to 7ms per packet). Signed-off-by: Keith Packard --- src/core/ao_fec.h | 46 ++-- src/core/ao_fec_rx.c | 145 ++++++++----- src/core/ao_fec_tx.c | 68 +----- src/drivers/ao_cc1120.c | 483 ++++++++++++++++++++++++++--------------- src/drivers/ao_cc1120.h | 9 + src/drivers/ao_cc1120_CC1120.h | 27 ++- src/stm/ao_arch.h | 23 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 73 ++++--- src/stm/ao_spi_stm.c | 6 +- src/stm/ao_timer.c | 2 +- src/test/ao_fec_test.c | 39 ++-- 12 files changed, 560 insertions(+), 364 deletions(-) diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 4fd398eb..f1192b62 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -26,11 +26,28 @@ extern const uint8_t ao_fec_whiten_table[]; +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name); +#endif + +static uint16_t inline +ao_fec_crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); +ao_fec_crc(const uint8_t *bytes, uint8_t len); /* * 'len' is the length of the original data; 'bytes' @@ -38,38 +55,23 @@ ao_fec_crc(uint8_t *bytes, uint8_t len); * two after 'len' must be the received crc */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_check_crc(const uint8_t *bytes, uint8_t len); /* - * Encode and interleave data. 'out' must be len*2 bytes long + * Compute CRC, whiten, convolve and interleave data. 'out' must be (len + 4) * 2 bytes long */ uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ -#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 69e9c1f5..0d400bb0 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -18,6 +18,16 @@ #include #include +#ifdef MEGAMETRUM +#include +#endif + +#if AO_PROFILE +#include + +uint32_t ao_fec_decode_start, ao_fec_decode_end; +#endif + /* * byte order repeats through 3 2 1 0 * @@ -40,34 +50,35 @@ * 18/19 10/11 08/09 00/01 */ +static const uint8_t ao_interleave_order[] = { + 0x1e, 0x16, 0x0e, 0x06, + 0x1c, 0x14, 0x0c, 0x04, + 0x1a, 0x12, 0x0a, 0x02, + 0x18, 0x10, 0x08, 0x00 +}; + static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; + return (i & ~0x1e) | ao_interleave_order[(i & 0x1e) >> 1]; } -struct ao_soft_sym { - uint8_t a, b; -}; - #define NUM_STATE 8 #define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ + +#define V_0 0xff +#define V_1 0x00 + +/* + * These are just the 'zero' states; the 'one' states mirror them + */ +static const uint8_t ao_fec_decode_table[NUM_STATE*2] = { + V_0, V_0, /* 000 */ + V_0, V_1, /* 001 */ + V_1, V_1, /* 010 */ + V_1, V_0, /* 011 */ + V_1, V_1, /* 100 */ + V_1, V_0, /* 101 */ + V_0, V_0, /* 110 */ + V_0, V_1 /* 111 */ }; static inline uint8_t @@ -76,14 +87,6 @@ ao_next_state(uint8_t state, uint8_t bit) return ((state << 1) | bit) & 0x7; } -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - /* * 'in' is 8-bits per symbol soft decision data * 'len' is input byte length. 'out' must be @@ -91,25 +94,29 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { - static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint32_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ uint16_t o; /* output bit index */ uint8_t p; /* previous cost/bits index */ uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ + uint8_t s0, s1; uint16_t avail; + uint16_t crc = AO_FEC_CRC_INIT; +#if AO_PROFILE + uint32_t start_tick; +#endif p = 0; for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; + cost[0][state] = 0x7fffffff; bits[0][state] = 0; } cost[0][0] = 0; @@ -119,6 +126,14 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t else avail = len; +#if AO_PROFILE + if (!avail) { + avail = callback(); + if (!avail) + return 0; + } + start_tick = ao_profile_tick(); +#endif o = 0; for (i = 0; i < len; i += 2) { b = i/2; @@ -127,44 +142,52 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t if (!avail) { avail = callback(); if (!avail) - break; + return 0; } /* Fetch one pair of input bytes, de-interleaving * the input. */ interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; + s0 = in[interleave]; + s1 = in[interleave+1]; + + avail -= 2; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this */ for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; + cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path * for each state and encoded bit value */ for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); + { + uint32_t cost0 = cost[p][state] + bitcost; + uint8_t state0 = ao_next_state(state, 0); + + if (cost0 < cost[n][state0]) { + cost[n][state0] = cost0; + bits[n][state0] = (bits[p][state] << 1) | (state & 1); + } + } + { + uint32_t cost1 = cost[p][state] + 510 - bitcost; + uint8_t state1 = ao_next_state(state, 1); + + if (cost1 < cost[n][state1]) { + cost[n][state1] = cost1; + bits[n][state1] = (bits[p][state] << 1) | (state & 1); } } } #if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { printf (" %5d(%04x)", cost[n][state], bits[n][state]); } @@ -186,7 +209,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t * it will be seven. */ int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ + uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ /* Find the best fit at the current point @@ -216,11 +239,23 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + + if (out_len > 2) { + crc = ao_fec_crc_byte(byte, crc); + *out++ = byte; + } else { + *out++ = byte ^ (crc >> 8); + crc <<= 8; + } --out_len; } o += 8; } } +#if AO_PROFILE + ao_fec_decode_start = start_tick; + ao_fec_decode_end = ao_profile_tick(); +#endif return len/16; } diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c9c0a3d6..4941d745 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -18,8 +18,9 @@ #include #include +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name) { uint16_t i; @@ -31,29 +32,15 @@ ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) } printf ("\n"); } - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} +#endif uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) +ao_fec_crc(const uint8_t *bytes, uint8_t len) { uint16_t crc = AO_FEC_CRC_INIT; while (len--) - crc = crc_byte(*bytes++, crc); + crc = ao_fec_crc_byte(*bytes++, crc); return crc; } @@ -63,7 +50,7 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len) +ao_fec_check_crc(const uint8_t *bytes, uint8_t len) { uint16_t computed_crc = ao_fec_crc(bytes, len); uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); @@ -71,8 +58,11 @@ ao_fec_check_crc(uint8_t *bytes, uint8_t len) return computed_crc == received_crc; } -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) +/* + * Compute CRC and trellis-terminator/interleave-pad bytes + */ +static uint8_t +ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); uint8_t i = 0; @@ -93,40 +83,6 @@ const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; -#if 0 -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = ao_fec_whiten_table; - - while (len--) - *out++ = *in++ ^ *w++; -} - -/* - * Unused as interleaving is now built in to ao_fec_encode - */ - -static void -ao_fec_interleave(uint8_t *d, uint8_t len) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - d[i+0] = interleaved >> 24; - d[i+1] = interleaved >> 16; - d[i+2] = interleaved >> 8; - d[i+3] = interleaved; - } -} -#endif - static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -140,7 +96,7 @@ static const uint8_t ao_fec_encode_table[16] = { }; uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out) { uint8_t extra[AO_FEC_PREPARE_EXTRA]; uint8_t extra_len; diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 394cf7c5..501b9370 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -24,8 +24,9 @@ uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; +uint8_t ao_radio_in_recv; -#define CC1120_DEBUG 1 +#define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 #if CC1120_TRACE @@ -34,7 +35,7 @@ uint8_t ao_radio_abort; #define fec_dump_bytes(b,l,n) #endif -uint32_t ao_radio_cal = 0x6ca333; +const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -194,6 +195,12 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) return status; } +static uint8_t +ao_radio_tx_fifo_space(void) +{ + return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); +} + static uint8_t ao_radio_status(void) { @@ -209,6 +216,97 @@ ao_radio_recv_abort(void) #define ao_radio_rdf_value 0x55 +static uint8_t +ao_radio_marc_status(void) +{ + return ao_radio_reg_read(CC1120_MARC_STATUS1); +} + +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + +static void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = ao_radio_strobe(CC1120_SIDLE); + if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + break; + } +} + +/* + * Packet deviation is 20.5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + */ + +#define PACKET_DEV_E 5 +#define PACKET_DEV_M 80 + +/* + * For our packet data, set the symbol rate to 38360 Baud + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * + * DATARATE_M = 239914 + * DATARATE_E = 9 + */ +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 + +static const uint16_t packet_setup[] = { + CC1120_DEVIATION_M, PACKET_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), +}; + +static const uint16_t packet_tx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG, +}; + +static const uint16_t packet_rx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT, +}; + /* * RDF deviation is 5kHz * @@ -259,50 +357,111 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -static uint8_t -ao_radio_marc_status(void) -{ - return ao_radio_reg_read(CC1120_MARC_STATUS1); -} +static uint8_t ao_radio_mode; -static uint8_t -ao_radio_tx_done(void) -{ - return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED; -} +#define AO_RADIO_MODE_BITS_PACKET 1 +#define AO_RADIO_MODE_BITS_PACKET_TX 2 +#define AO_RADIO_MODE_BITS_TX_BUF 4 +#define AO_RADIO_MODE_BITS_TX_FINISH 8 +#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RDF 32 -static uint8_t -ao_radio_rx_done(void) +#define AO_RADIO_MODE_NONE 0 +#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) + +static void +ao_radio_set_mode(uint8_t new_mode) { - return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; + uint8_t changes; + int i; + + if (new_mode == ao_radio_mode) + return; + + changes = new_mode & (~ao_radio_mode); + if (changes & AO_RADIO_MODE_BITS_PACKET) + for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2) + ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_PACKET_TX) + for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2) + ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_TX_BUF) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR); + + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + + if (changes & AO_RADIO_MODE_BITS_PACKET_RX) + for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2) + ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_RDF) + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); + ao_radio_mode = new_mode; } +static const uint16_t radio_setup[] = { +#include "ao_cc1120_CC1120.h" +}; + +static uint8_t ao_radio_configured = 0; + static void -ao_radio_tx_isr(void) +ao_radio_setup(void) { - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); + int i; + + ao_radio_strobe(CC1120_SRES); + + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) + ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + + ao_radio_mode = 0; + + ao_config_get(); + + ao_radio_configured = 1; } static void -ao_radio_start_tx(void) +ao_radio_get(uint8_t len) { - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); + static uint32_t last_radio_setting; + static uint8_t last_len; + + ao_mutex_get(&ao_radio_mutex); + if (!ao_radio_configured) + ao_radio_setup(); + if (ao_config.radio_setting != last_radio_setting) { + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); + last_radio_setting = ao_config.radio_setting; + } + if (len != last_len) { + ao_radio_reg_write(CC1120_PKT_LEN, len); + last_len = len; + } } +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + void ao_radio_rdf(uint8_t len) { int i; + ao_radio_abort = 0; ao_radio_get(len); + + ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); @@ -311,11 +470,9 @@ ao_radio_rdf(uint8_t len) cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) + if (!ao_radio_wake) ao_radio_idle(); - ao_radio_set_packet(); ao_radio_put(); } @@ -372,65 +529,113 @@ ao_radio_test(void) } void -ao_radio_send(void *d, uint8_t size) +ao_radio_send(const void *d, uint8_t size) { uint8_t marc_status; - uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; + static uint8_t encode[256]; + uint8_t *e = encode; uint8_t encode_len; + uint8_t this_len; + uint8_t started = 0; + uint8_t fifo_space; encode_len = ao_fec_encode(d, size, encode); ao_radio_get(encode_len); - ao_radio_fifo_write(encode, encode_len); - ao_radio_wake = 0; + started = 0; + fifo_space = CC1120_FIFO_SIZE; + while (encode_len) { + this_len = encode_len; - ao_radio_start_tx(); + if (this_len > fifo_space) { + this_len = fifo_space; + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF); + } else { + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH); + } - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) - ao_radio_idle(); + ao_radio_fifo_write(e, this_len); + e += this_len; + encode_len -= this_len; + + if (!started) { + ao_radio_start_tx(); + started = 1; + } else { + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + } + + do { + ao_radio_wake = 0; + cli(); + while (!ao_radio_wake) + ao_sleep(&ao_radio_wake); + sei(); + if (!encode_len) + break; + fifo_space = ao_radio_tx_fifo_space(); + } while (!fifo_space); + } ao_radio_put(); } #define AO_RADIO_MAX_RECV 90 -static uint8_t rx_data[2048]; -static uint16_t rx_data_count; -static uint16_t rx_data_consumed; -static uint16_t rx_data_cur; -static uint8_t rx_ignore; +uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; +uint16_t rx_data_count; +uint16_t rx_data_consumed; +uint16_t rx_data_cur; +uint8_t rx_ignore; +uint8_t rx_waiting; + +#if AO_PROFILE +static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; + +uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + +#include +#endif static void ao_radio_rx_isr(void) { + uint8_t d; + + d = stm_spi2.dr; + stm_spi2.dr = 0; if (rx_ignore == 0) { - rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + else + rx_data[rx_data_cur++] = d; + if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { +#if AO_PROFILE + if (rx_data_consumed == 0) + rx_packet_tick = ao_profile_tick(); +#endif + rx_waiting = 0; ao_wakeup(&ao_radio_wake); } } else { - (void) stm_spi2.dr; --rx_ignore; } - stm_spi2.dr = 0x00; } static uint16_t ao_radio_rx_wait(void) { cli(); + rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && - !ao_radio_abort) + !ao_radio_abort) { ao_sleep(&ao_radio_wake); + } + rx_waiting = 0; sei(); if (ao_radio_abort) return 0; + rx_data_consumed += AO_FEC_DECODE_BLOCK; return AO_FEC_DECODE_BLOCK; } @@ -440,8 +645,17 @@ ao_radio_recv(__xdata void *d, uint8_t size) uint8_t len; uint16_t i; uint8_t rssi; + uint8_t ret; + static int been_here = 0; size -= 2; /* status bytes */ + if (size > AO_RADIO_MAX_RECV) { + ao_delay(AO_SEC_TO_TICKS(1)); + return 0; + } +#if AO_PROFILE + rx_start_tick = ao_profile_tick(); +#endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ len *= 2; /* 1/2 rate convolution */ @@ -450,162 +664,65 @@ ao_radio_recv(__xdata void *d, uint8_t size) rx_data_consumed = 0; rx_ignore = 2; - printf ("len %d rx_data_count %d\n", len, rx_data_count); - + ao_radio_abort = 0; + ao_radio_in_recv = 1; /* configure interrupt pin */ ao_radio_get(len); - ao_radio_wake = 0; - ao_radio_abort = 0; - - ao_radio_reg_write(CC1120_PKT_CFG2, - (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); - ao_radio_reg_write(CC1120_EXT_CTRL, 0); - - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + ao_radio_wake = 0; stm_spi2.cr2 = 0; /* clear any RXNE */ (void) stm_spi2.dr; - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); ao_radio_burst_read_stop(); + ao_radio_strobe(CC1120_SIDLE); + /* Convert from 'real' rssi to cc1111-style values */ rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; - ao_radio_strobe(CC1120_SIDLE); - ao_radio_put(); /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); - - if (ao_fec_check_crc(d, size)) + if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) ((uint8_t *) d)[size + 1] = 0x80; else ((uint8_t *) d)[size + 1] = 0x00; ((uint8_t *) d)[size] = (uint8_t) rssi; - return 1; -} - -/* - * Packet deviation is 20.5kHz - * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e - * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz - */ - -#define PACKET_DEV_E 5 -#define PACKET_DEV_M 80 - -/* - * For our packet data, set the symbol rate to 38360 Baud - * - * (2**20 + DATARATE_M) * 2 ** DATARATE_E - * Rdata = -------------------------------------- * fosc - * 2 ** 39 - * - * - * DATARATE_M = 239914 - * DATARATE_E = 9 - */ -#define PACKET_DRATE_E 9 -#define PACKET_DRATE_M 239914 + ao_radio_in_recv = 0; -static const uint16_t packet_setup[] = { - CC1120_DEVIATION_M, PACKET_DEV_M, - CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | - (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | - (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), - CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | - (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), - CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), - CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), - CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | - (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | - (1 << CC1120_PKT_CFG1_APPEND_STATUS)), - CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | - (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1120_PKT_CFG0_UART_MODE_EN) | - (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), -}; - -void -ao_radio_set_packet(void) -{ - int i; - - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); -} - -void -ao_radio_idle(void) -{ - for (;;) { - uint8_t state = ao_radio_strobe(CC1120_SIDLE); - if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) - break; - } - ao_radio_strobe(CC1120_SFTX); - ao_radio_strobe(CC1120_SFRX); -} - -static const uint16_t radio_setup[] = { -#include "ao_cc1120_CC1120.h" -}; - -static uint8_t ao_radio_configured = 0; - - -static void -ao_radio_setup(void) -{ - int i; - - ao_radio_strobe(CC1120_SRES); - - for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) - ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + if (ao_radio_abort) + ao_delay(1); - ao_radio_set_packet(); +#if AO_PROFILE + rx_last_done_tick = rx_done_tick; + rx_done_tick = ao_profile_tick(); - ao_config_get(); + ao_rx_start_tick = rx_start_tick; + ao_rx_packet_tick = rx_packet_tick; + ao_rx_done_tick = rx_done_tick; + ao_rx_last_done_tick = rx_last_done_tick; +#endif - ao_radio_configured = 1; + return ret; } -void -ao_radio_get(uint8_t len) -{ - ao_mutex_get(&ao_radio_mutex); - if (!ao_radio_configured) - ao_radio_setup(); - ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); - ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); - ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); - ao_radio_reg_write(CC1120_PKT_LEN, len); -} #if CC1120_DEBUG static char *cc1120_state_name[] = { @@ -824,7 +941,7 @@ static void ao_radio_beep(void) { } static void ao_radio_packet(void) { - static uint8_t packet[] = { + static const uint8_t packet[] = { #if 1 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -841,7 +958,19 @@ static void ao_radio_packet(void) { void ao_radio_test_recv() { - ao_radio_recv(0, 34); + uint8_t bytes[34]; + uint8_t b; + + if (ao_radio_recv(bytes, 34)) { + if (bytes[33] & 0x80) + printf ("CRC OK"); + else + printf ("CRC BAD"); + printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + for (b = 0; b < 32; b++) + printf (" %02x", bytes[b]); + printf ("\n"); + } } #endif @@ -865,18 +994,20 @@ ao_radio_init(void) ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); - AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { - if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0) break; } - AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); + ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 5822a21a..60b9621e 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -181,6 +181,11 @@ #define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 #define CC1120_PREAMBLE_CFG0 0x0e +#define CC1120_PREAMBLE_CFG0_PQT_EN 5 +#define CC1120_PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4 +#define CC1120_PREAMBLE_CFG0_PQT 0 +#define CC1120_PREAMBLE_CFG0_PQT_MASK 0xf + #define CC1120_FREQ_IF_CFG 0x0f #define CC1120_IQIC 0x10 #define CC1120_CHAN_BW 0x11 @@ -215,6 +220,8 @@ #define CC1120_AGC_CFG1 0x1c #define CC1120_AGC_CFG0 0x1d #define CC1120_FIFO_CFG 0x1e +#define CC1120_FIFO_CFG_CRC_AUTOFLUSH 7 +#define CC1120_FIFO_CFG_FIFO_THR 0 #define CC1120_DEV_ADDR 0x1f #define CC1120_SETTLING_CFG 0x20 #define CC1120_SETTLING_CFG_FS_AUTOCAL 3 @@ -321,6 +328,8 @@ #define CC1120_DIRECT_FIFO 0x3e #define CC1120_FIFO 0x3f +#define CC1120_FIFO_SIZE 128 + /* Extended register space */ #define CC1120_EXTENDED_BIT 0x8000 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c0f35a23..5376afd5 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -26,7 +26,9 @@ CC1120_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ - CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ + CC1120_SYNC_CFG1, /* Sync Word Detection Configuration */ + (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) | + (0x07 << CC1120_SYNC_CFG1_SYNC_THR), CC1120_SYNC_CFG0, (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) | (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR), @@ -34,12 +36,21 @@ CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */ (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD), - CC1120_PREAMBLE_CFG0, 0x2a, /* */ + CC1120_PREAMBLE_CFG0, + (1 << CC1120_PREAMBLE_CFG0_PQT_EN) | + (0x6 << CC1120_PREAMBLE_CFG0_PQT), CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ - CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ + CC1120_MDMCFG1, /* General Modem Parameter Configuration */ + (0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) | + (1 << CC1120_MDMCFG1_FIFO_EN) | + (0 << CC1120_MDMCFG1_MANCHESTER_EN) | + (0 << CC1120_MDMCFG1_INVERT_DATA_EN) | + (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) | + (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) | + (0 << CC1120_MDMCFG1_SINGLE_ADC_EN), CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ @@ -49,7 +60,9 @@ CC1120_AGC_CFG2, 0x20, /* AGC Configuration */ CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ - CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1120_FIFO_CFG, /* FIFO Configuration */ + (0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) | + (0x40 << CC1120_FIFO_CFG_FIFO_THR), CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) | @@ -65,12 +78,12 @@ #if 0 CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ -#endif CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ +#endif CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ - CC1120_PA_CFG2, 0x23, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x04, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ @@ -80,7 +93,7 @@ CC1120_MARC_SPARE, 0x00, /* MARC Spare */ CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */ CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */ - CC1120_EXT_CTRL, 0x01, /* External Control Configuration */ + CC1120_EXT_CTRL, 0x00, /* External Control Configuration */ CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */ CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index bbd1b3b1..30cd9ea5 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 1024 +#define AO_STACK_SIZE 512 #define AO_LED_TYPE uint16_t @@ -111,14 +111,22 @@ extern const uint16_t ao_serial_number; uint32_t *sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ ao_cur_task->sp = (sp); \ - if ((uint8_t *) sp < ao_cur_task->stack) \ + if ((uint8_t *) sp < &ao_cur_task->stack[0]) \ ao_panic (AO_PANIC_STACK); \ } while (0) -#define ao_arch_isr_stack() /* nothing */ +#if 0 +#define ao_arch_isr_stack() do { \ + uint32_t *sp = (uint32_t *) 0x20004000; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + } while (0) +#else +#define ao_arch_isr_stack() +#endif + #define ao_arch_cpu_idle() do { \ - asm("wfi"); \ + asm("wfi"); \ } while (0) #define ao_arch_restore_stack() do { \ @@ -173,6 +181,11 @@ extern const uint16_t ao_serial_number; #define AO_TIM91011_CLK (2 * AO_PCLK2) #endif +#define AO_STM_NVIC_HIGH_PRIORITY 4 +#define AO_STM_NVIC_CLOCK_PRIORITY 6 +#define AO_STM_NVIC_MED_PRIORITY 8 +#define AO_STM_NVIC_LOW_PRIORITY 10 + void ao_lcd_stm_init(void); void ao_lcd_font_init(void); @@ -215,7 +228,7 @@ ao_serial3_pollchar(void); void ao_serial3_set_speed(uint8_t speed); -extern uint32_t ao_radio_cal; +extern const uint32_t ao_radio_cal; void ao_adc_init(); diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 87a072e7..b579ad9f 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -22,6 +22,9 @@ #define AO_EXTI_MODE_FALLING 2 #define AO_EXTI_MODE_PULL_UP 4 #define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 683a91b3..d54e6ee6 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -20,37 +20,50 @@ static void (*ao_exti_callback[16])(void); -static void -ao_exti_isr(void) { - uint32_t pending = stm_exti.pr; - uint8_t pin; +uint32_t ao_last_exti; + +static void ao_exti_one_isr(uint8_t pin) { + uint32_t pending = (ao_last_exti = stm_exti.pr) & (1 << pin); - /* Clear pending interrupts */ stm_exti.pr = pending; - for (pin = 0; pin < 16 && pending; pin++) { - uint32_t mask = (1 << pin); + if (pending && ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); +} - if (pending & mask) { - pending &= ~mask; - if (ao_exti_callback[pin]) - (*ao_exti_callback[pin])(); - } +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } } -void stm_exti0_isr(void) { ao_exti_isr(); } -void stm_exti1_isr(void) { ao_exti_isr(); } -void stm_exti2_isr(void) { ao_exti_isr(); } -void stm_exti3_isr(void) { ao_exti_isr(); } -void stm_exti4_isr(void) { ao_exti_isr(); } -void stm_exti9_5_isr(void) { ao_exti_isr(); } -void stm_exti15_10_isr(void) { ao_exti_isr(); } +void stm_exti0_isr(void) { ao_exti_one_isr(0); } +void stm_exti1_isr(void) { ao_exti_one_isr(1); } +void stm_exti2_isr(void) { ao_exti_one_isr(2); } +void stm_exti3_isr(void) { ao_exti_one_isr(3); } +void stm_exti4_isr(void) { ao_exti_one_isr(4); } +void stm_exti9_5_isr(void) { ao_exti_range_isr(5, 9, 0x3e0); } +void stm_exti15_10_isr(void) { ao_exti_range_isr(10, 15, 0xfc00); } void ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; + uint8_t prio; ao_exti_callback[pin] = callback; @@ -90,7 +103,15 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback irq = STM_ISR_EXTI9_5_POS; else irq = STM_ISR_EXTI15_10_POS; - stm_nvic_set_priority(irq, 10); + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); stm_nvic_set_enable(irq); } @@ -116,10 +137,10 @@ ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { void ao_exti_init(void) { - stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY); } diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index d3378648..26227086 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -23,7 +23,8 @@ struct ao_spi_stm_info { struct stm_spi *stm_spi; }; -uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint16_t ao_spi_speed[STM_NUM_SPI]; static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { { @@ -282,7 +283,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (ao_spi_speed[spi_index] << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); @@ -310,6 +311,7 @@ ao_spi_channel_init(uint8_t spi_index) (0 << STM_SPI_CR2_SSOE) | (0 << STM_SPI_CR2_TXDMAEN) | (0 << STM_SPI_CR2_RXDMAEN)); + ao_spi_speed[spi_index] = AO_SPI_SPEED_FAST; } void diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 0c44f352..936dc881 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -87,7 +87,7 @@ void ao_timer_init(void) { stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); /* Turn on timer 6 */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index e8d3d8b1..8ce532c8 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -74,6 +74,12 @@ gaussian_random(double mean, double dev) #define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) #define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) +static uint8_t ao_bit(uint8_t b) { + if (b) + return 0x00; + return 0xff; +} + static int ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) { @@ -83,7 +89,7 @@ ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) for (i = 0; i < bits_len; i++) { b = bits[i]; for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; + *bytes++ = ao_bit ((b >> bit) & 1); } return bits_len * 8; @@ -127,7 +133,7 @@ ao_random_data(uint8_t *out, uint8_t out_len) static uint8_t real_packet[] = { - 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, @@ -258,22 +264,24 @@ static uint8_t real_packet[] = { }; -void +int ao_real_packet(void) { uint8_t decode[64]; uint8_t decode_len; - int off; + int ok = 0; - for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); + decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (ao_fec_check_crc(decode, 32)) { - printf ("match at %d\n", off); + if (decode[32] == 0 && decode[33] == 0) { + printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - } + ao_fec_dump_bytes(decode, decode_len, "Decode"); + ok = 1; + } else { + printf ("actual packet crc error\n"); } + return ok; } int @@ -299,9 +307,11 @@ main(int argc, char **argv) int errors = 0; int error; - ao_real_packet(); exit(0); + if (!ao_real_packet()) + errors++; + srandom(0); - for (trial = 0; trial < 10000; trial++) { + for (trial = 0; trial < 100000; trial++) { /* Compute some random data */ original_len = ao_random_data(original, sizeof(original)); @@ -313,7 +323,7 @@ main(int argc, char **argv) transmit_len = ao_expand(encode, encode_len, transmit); /* Add gaussian noise to the signal */ - receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x38); receive_len = transmit_len; /* Decode it */ @@ -327,7 +337,7 @@ main(int argc, char **argv) error++; } - if (!ao_fec_check_crc(decode, original_len)) { + if (decode[original_len] != 0 || decode[original_len+1] != 0) { printf ("crc mis-match\n"); error++; } @@ -343,6 +353,7 @@ main(int argc, char **argv) errors += error; } } + printf ("%d packets coded\n", trial); return errors; } -- cgit v1.2.3 From b5f5fd92109ac6f4909a81303d52bc9220cc2520 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:13:14 -0700 Subject: altos: custom hex printer for telemetry packets Using printf is way too slow with pdclib; just hand-write hex byte output. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 4ca641b7..51d61425 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -103,6 +103,13 @@ ao_monitor_blink(void) #if HAS_MONITOR_PUT +static const char xdigit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +#define hex(c) do { putchar(xdigit[(c) >> 4]); putchar(xdigit[(c)&0xf]); } while (0) + void ao_monitor_put(void) { @@ -210,14 +217,27 @@ ao_monitor_put(void) break; #endif /* LEGACY_MONITOR */ default: - printf ("TELEM %02x", ao_monitoring + 2); +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n", ao_rx_done_tick - ao_fec_decode_end); + } +#endif + printf("TELEM "); + hex((uint8_t) (ao_monitoring + 2)); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { byte = recv_raw.packet[state]; sum += byte; - printf("%02x", byte); + hex(byte); } - printf("%02x\n", sum); + hex(sum); + putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; -- cgit v1.2.3 From c4036bf6e7997b618f89a05dd1214c16066ba2b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:14:13 -0700 Subject: altos: Turn radio-related bits of ao_flight_mm.c Now that MM has full radio functionality, we can make it work right. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 28b9869f..a0affc48 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -87,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL && 0 +#if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -105,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL && 0 +#if HAS_ACCEL && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO && 0 +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ -- cgit v1.2.3 From 1ae69a1c2ce7e45db9d9c175bc63867eff68ebe5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:15:54 -0700 Subject: altos: Make gcc happy with ao_telemetry_set_interval Using unsigned locals made GCC sad as it was compared with a signed value. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 9000a149..b3ce8ba9 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -333,7 +333,7 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { - uint8_t cur = 0; + int8_t cur = 0; ao_telemetry_interval = interval; #if AO_SEND_MEGA -- cgit v1.2.3 From 097b337eb9b7deff13d5dcdafddec9bec3868b93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:17:00 -0700 Subject: altos: Abort radio receive when using flash memory on megametrum Radio receive camps on the SPI bus, making it impossible to access flash memory. Abort any pending receive operation when trying to get to the flash part. Yes, this is a total hack. Signed-off-by: Keith Packard --- src/drivers/ao_m25.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index c807cd68..2983a405 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -99,7 +99,18 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) +#if HAS_BOOT_RADIO +extern uint8_t ao_radio_in_recv; + +static void ao_boot_radio(void) { + if (ao_radio_in_recv) + ao_radio_recv_abort(); +} +#else +#define ao_boot_radio() +#endif + +#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS); } while (0) #define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 -- cgit v1.2.3 From fb2b83fcd28199d8c686e676d46d6ecfbf706f37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:18:44 -0700 Subject: altos: Create a 32-bit 1MHz timer for use in profiling execution This provides a simple method for getting high-resolution timer data to use in performance tuning code. It's not used by default anywhere. Signed-off-by: Keith Packard --- src/stm/ao_profile.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_profile.h | 34 ++++++++++++++++ src/stm/stm32l.h | 10 +++-- 3 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 src/stm/ao_profile.c create mode 100644 src/stm/ao_profile.h diff --git a/src/stm/ao_profile.c b/src/stm/ao_profile.c new file mode 100644 index 00000000..149ca29f --- /dev/null +++ b/src/stm/ao_profile.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +static void ao_profile_test(void) +{ + uint8_t i; + uint32_t ticks[20]; + + for (i = 0; i < 20; i++) { + ticks[i] = ao_profile_tick(); + ao_delay(0); + } + for (i = 0; i < 19; i++) + printf ("%d\n", ticks[i+1] - ticks[i]); +} + +static const struct ao_cmds ao_profile_cmds[] = { + { ao_profile_test, "P\0Test profile counter" }, + { 0, NULL } +}; + +void ao_profile_init(void) +{ + /* Turn on timer 2 and 4 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM2EN) | + (1 << STM_RCC_APB1ENR_TIM4EN); + + /* disable timers */ + stm_tim4.cr1 = 0; + stm_tim2.cr1 = 0; + + /* tim4 is master */ + + + stm_tim4.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + stm_tim4.smcr = ((0 << STM_TIM234_SMCR_ETP) | + (0 << STM_TIM234_SMCR_ECE) | + (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) | + (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) | + (0 << STM_TIM234_SMCR_MSM) | + (STM_TIM234_SMCR_TS_ITR3 << STM_TIM234_SMCR_TS) | + (0 << STM_TIM234_SMCR_OCCS) | + (STM_TIM234_SMCR_SMS_DISABLE << STM_TIM234_SMCR_SMS)); + + stm_tim4.dier = 0; + stm_tim4.sr = 0; + + stm_tim4.psc = 31; + stm_tim4.cnt = 0; + stm_tim4.arr = 0xffff; + + /* tim2 is slaved to tim4 */ + + stm_tim2.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_ENABLE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + stm_tim2.smcr = ((0 << STM_TIM234_SMCR_ETP) | + (0 << STM_TIM234_SMCR_ECE) | + (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) | + (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) | + (0 << STM_TIM234_SMCR_MSM) | + (STM_TIM234_SMCR_TS_ITR3 << STM_TIM234_SMCR_TS) | + (0 << STM_TIM234_SMCR_OCCS) | + (STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK << STM_TIM234_SMCR_SMS)); + stm_tim2.dier = 0; + stm_tim2.sr = 0; + stm_tim2.psc = 0; + stm_tim2.cnt = 0; + stm_tim2.arr = 0xffff; + + /* Start your timers */ + + stm_tim2.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE | STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + stm_tim4.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE | STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (1 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + ao_cmd_register(&ao_profile_cmds[0]); +} diff --git a/src/stm/ao_profile.h b/src/stm/ao_profile.h new file mode 100644 index 00000000..f7dd029d --- /dev/null +++ b/src/stm/ao_profile.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PROFILE_H_ +#define _AO_PROFILE_H_ + +void ao_profile_init(); + +static uint32_t inline ao_profile_tick(void) { + uint16_t hi, lo, second_hi; + + do { + hi = stm_tim2.cnt; + lo = stm_tim4.cnt; + second_hi = stm_tim2.cnt; + } while (hi != second_hi); + return ((uint32_t) hi << 16) | lo; +} + +#endif diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index cb66df6c..60f0b6d0 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1331,6 +1331,8 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CR1_CMS_CENTER_3 3 #define STM_TIM234_CR1_CMS_MASK 3 #define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_DIR_UP 0 +#define STM_TIM234_CR1_DIR_DOWN 1 #define STM_TIM234_CR1_OPM 3 #define STM_TIM234_CR1_URS 2 #define STM_TIM234_CR1_UDIS 1 @@ -1377,10 +1379,10 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_SMCR_ETF_MASK 15 #define STM_TIM234_SMCR_MSM 7 #define STM_TIM234_SMCR_TS 4 -#define STM_TIM234_SMCR_TS_TR0 0 -#define STM_TIM234_SMCR_TS_TR1 1 -#define STM_TIM234_SMCR_TS_TR2 2 -#define STM_TIM234_SMCR_TS_TR3 3 +#define STM_TIM234_SMCR_TS_ITR0 0 +#define STM_TIM234_SMCR_TS_ITR1 1 +#define STM_TIM234_SMCR_TS_ITR2 2 +#define STM_TIM234_SMCR_TS_ITR3 3 #define STM_TIM234_SMCR_TS_TI1F_ED 4 #define STM_TIM234_SMCR_TS_TI1FP1 5 #define STM_TIM234_SMCR_TS_TI2FP2 6 -- cgit v1.2.3 From ebeac02a990da3fa6dd71487141d0bc6f78b42de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:20:17 -0700 Subject: altos: Enable full flight computer functionality in MegaMetrum This turns on everything that currently works Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 8 +++++++- src/megametrum-v0.1/ao_megametrum.c | 40 +++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 22a58ff4..07a339b9 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -19,6 +19,7 @@ INC = \ ao_hmc5883.h \ ao_mpu6000.h \ ao_cc1120_CC1120.h \ + ao_profile.h \ ao_whiten.h \ stm32l.h @@ -43,6 +44,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ + ao_gps_report_mega.c \ + ao_ignite.c \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ @@ -66,7 +69,10 @@ ALTOS_SRC = \ ao_sample_mm.c \ ao_kalman.c \ ao_flight_mm.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_packet_slave.c \ + ao_packet.c \ + ao_companion.c PRODUCT=MegaMetrum-v0.1 diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index a2ac186b..ed35efa4 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include int main(void) @@ -30,24 +33,35 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_GREEN); ao_timer_init(); - ao_cmd_init(); - ao_gps_init(); - ao_dma_init(); + + ao_i2c_init(); ao_spi_init(); - ao_ms5607_init(); - ao_beep_init(); - ao_adc_init(); - ao_storage_init(); - ao_usb_init(); + ao_dma_init(); ao_exti_init(); - ao_radio_init(); - ao_i2c_init(); + + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + + ao_ms5607_init(); ao_hmc5883_init(); ao_mpu6000_init(); -// ao_flight_init(); -// ao_log_init(); -// ao_report_init(); + + ao_storage_init(); + + ao_flight_init(); + ao_log_init(); + ao_report_init(); + + ao_usb_init(); + ao_gps_init(); + ao_gps_report_mega_init(); ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); + ao_igniter_init(); + ao_companion_init(); + ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 8efac8eb99a9aabb45d9fbf742e4be91e4b331a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:21:04 -0700 Subject: altos: Add debugging code to check for stack overflow Stack overflow often happens from interrupt handlers sitting on top of a task stack. Check for this during ao_wakeup as that is often called during interrupt processing. Signed-off-by: Keith Packard --- src/core/ao_task.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 910f1587..4011a36e 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include #define AO_NO_TASK_INDEX 0xff @@ -28,6 +28,20 @@ __xdata struct ao_task *__data ao_cur_task; ao_arch_task_globals #endif +#define AO_CHECK_STACK 0 + +#if AO_CHECK_STACK +static uint8_t in_yield; + +static inline void ao_check_stack(void) { + uint8_t q; + if (!in_yield && ao_cur_task && &q < &ao_cur_task->stack[0]) + ao_panic(AO_PANIC_STACK); +} +#else +#define ao_check_stack() +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -68,6 +82,9 @@ ao_yield(void) ao_arch_naked_define ao_arch_isr_stack(); +#if CHECK_STACK + in_yield = 1; +#endif /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ @@ -97,6 +114,10 @@ ao_yield(void) ao_arch_naked_define } } } +#if CHECK_STACK + cli(); + in_yield = 0; +#endif ao_arch_restore_stack(); } @@ -117,6 +138,7 @@ ao_wakeup(__xdata void *wchan) { uint8_t i; + ao_check_stack(); for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i]->wchan == wchan) ao_tasks[i]->wchan = NULL; -- cgit v1.2.3 From 4847595e0383e5ff9c5a373f3c7f2af8c210c50a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:25:00 -0700 Subject: altos: ao_ignite.c is no longer cc1111 specific Move it to core Signed-off-by: Keith Packard --- src/cc1111/ao_ignite.c | 193 --------------------------------------------- src/core/ao_ignite.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 193 deletions(-) delete mode 100644 src/cc1111/ao_ignite.c create mode 100644 src/core/ao_ignite.c diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c deleted file mode 100644 index cf07dfe8..00000000 --- a/src/cc1111/ao_ignite.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include - -__xdata struct ao_ignition ao_ignition[2]; - -void -ao_ignite(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); -} - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter) -{ - __xdata struct ao_data packet; - __pdata int16_t value; - __pdata uint8_t request, firing, fired; - - __critical { - ao_data_get(&packet); - request = ao_ignition[igniter].request; - fired = ao_ignition[igniter].fired; - firing = ao_ignition[igniter].firing; - } - if (firing || (request && !fired)) - return ao_igniter_active; - - value = (AO_IGNITER_CLOSED>>1); - switch (igniter) { - case ao_igniter_drogue: - value = packet.adc.sense_d; - break; - case ao_igniter_main: - value = packet.adc.sense_m; - break; - } - if (value < AO_IGNITER_OPEN) - return ao_igniter_open; - else if (value > AO_IGNITER_CLOSED) - return ao_igniter_ready; - else - return ao_igniter_unknown; -} - -void -ao_igniter_fire(enum ao_igniter igniter) __critical -{ - ao_mutex_get(&ao_radio_mutex); - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - } - ao_ignition[igniter].firing = 0; - ao_mutex_put(&ao_radio_mutex); -} - -void -ao_igniter(void) -{ - __xdata enum ao_ignter igniter; - - ao_config_get(); - for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; - } - } - } -} - -void -ao_ignite_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); - } -} - -static __code char * __code igniter_status_names[] = { - "unknown", "ready", "active", "open" -}; - -void -ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant -{ - enum ao_igniter_status status = ao_igniter_status(igniter); - printf("Igniter: %6s Status: %s\n", - name, - igniter_status_names[status]); -} - -void -ao_ignite_test(void) -{ - ao_ignite_print_status(ao_igniter_drogue, "drogue"); - ao_ignite_print_status(ao_igniter_main, "main"); -} - -__code struct ao_cmds ao_ignite_cmds[] = { - { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter" }, - { 0, NULL }, -}; - -__xdata struct ao_task ao_igniter_task; - -void -ao_ignite_set_pins(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; -} - -void -ao_igniter_init(void) -{ - ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); - ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); -} diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c new file mode 100644 index 00000000..561b5513 --- /dev/null +++ b/src/core/ao_ignite.c @@ -0,0 +1,210 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include + +__xdata struct ao_ignition ao_ignition[2]; + +void +ao_ignite(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].request = 1; + ao_wakeup(&ao_ignition); +} + +#ifndef AO_SENSE_DROGUE +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_d) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) +#endif + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + __xdata struct ao_data packet; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; + + __critical { + ao_data_get(&packet); + request = ao_ignition[igniter].request; + fired = ao_ignition[igniter].fired; + firing = ao_ignition[igniter].firing; + } + if (firing || (request && !fired)) + return ao_igniter_active; + + value = (AO_IGNITER_CLOSED>>1); + switch (igniter) { + case ao_igniter_drogue: + value = AO_SENSE_DROGUE(&packet); + break; + case ao_igniter_main: + value = AO_SENSE_MAIN(&packet); + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +#ifndef AO_IGNITER_SET_DROGUE +#define AO_IGNITER_SET_DROGUE(v) AO_IGNITER_DROGUE = (v) +#define AO_IGNITER_SET_MAIN(v) AO_IGNITER_MAIN = (v) +#endif + +#ifndef AO_IGNITER_FIRE_TIME +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#endif + +#ifndef AO_IGNITER_CHARGE_TIME +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +#endif + +void +ao_igniter_fire(enum ao_igniter igniter) __critical +{ + ao_mutex_get(&ao_radio_mutex); + ao_ignition[igniter].firing = 1; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + break; + case ao_igniter_main: + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + } + ao_ignition[igniter].firing = 0; + ao_mutex_put(&ao_radio_mutex); +} + +void +ao_igniter(void) +{ + __xdata enum ao_igniter igniter; + + ao_config_get(); + for (;;) { + ao_sleep(&ao_ignition); + for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { + if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + + ao_igniter_fire(igniter); + ao_delay(AO_IGNITER_CHARGE_TIME); + ao_ignition[igniter].fired = 1; + } + } + } +} + +void +ao_ignite_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + if (ao_cmd_lex_c == 'm') { + if(ao_match_word("main")) + ao_igniter_fire(ao_igniter_main); + } else { + if(ao_match_word("drogue")) + ao_igniter_fire(ao_igniter_drogue); + } +} + +static __code char * __code igniter_status_names[] = { + "unknown", "ready", "active", "open" +}; + +void +ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant +{ + enum ao_igniter_status status = ao_igniter_status(igniter); + printf("Igniter: %6s Status: %s\n", + name, + igniter_status_names[status]); +} + +void +ao_ignite_test(void) +{ + ao_ignite_print_status(ao_igniter_drogue, "drogue"); + ao_ignite_print_status(ao_igniter_main, "main"); +} + +__code struct ao_cmds ao_ignite_cmds[] = { + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter" }, + { 0, NULL }, +}; + +__xdata struct ao_task ao_igniter_task; + +void +ao_ignite_set_pins(void) +{ + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); + ao_cmd_register(&ao_ignite_cmds[0]); + ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +} -- cgit v1.2.3 From 0285696e5280fc64774b6c3a2fcdaa36bd36ae7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:17:51 -0700 Subject: altos: mpu6000 requires a delay during start I have no idea why this is required, but the mpu6000 will not come up and run if this isn't present. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index c205706d..12b9e8b4 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -136,6 +136,15 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +static inline void +ao_i2c_delay(void) +{ + uint8_t i; + + for (i = 0; i < 10; i++) + ao_arch_nop(); +} + #define I2C_DEBUG 0 #if I2C_DEBUG #define DBG(x...) printf(x) @@ -194,6 +203,7 @@ ao_i2c_start(uint8_t index, uint16_t addr) out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + ao_i2c_delay(); out_cr2("start", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); ao_alarm(1); @@ -429,4 +439,3 @@ ao_i2c_init(void) stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); #endif } - -- cgit v1.2.3 From 8fc643c9768f0db31a248331681af9490f5715af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:19:05 -0700 Subject: altos: stm i2c debug code was calling flush() even when disabled The fancy stm i2c debugging code had calls to flush() that were invoked outside of the conditionals leading to all kinds of fun -- flush() may re-enable interrupts, yield or do all kinds of wacky stuff, none of which is appropriate from the middle of a device driver Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 12b9e8b4..51631cb7 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -147,47 +147,47 @@ ao_i2c_delay(void) #define I2C_DEBUG 0 #if I2C_DEBUG -#define DBG(x...) printf(x) +#define DBG(x...) do { printf(x); flush(); } while (0) #else -#define DBG(x...) +#define DBG(x...) #endif static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { uint32_t sr1 = stm_i2c->sr1; - DBG("%s: sr1: %x\n", where, sr1); flush(); + DBG("%s: sr1: %x\n", where, sr1); return sr1; } static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { uint32_t sr2 = stm_i2c->sr2; - DBG("%s: sr2: %x\n", where, sr2); flush(); + DBG("%s: sr2: %x\n", where, sr2); return sr2; } static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - DBG("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); stm_i2c->cr1 = cr1; } static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { uint32_t cr1 = stm_i2c->cr1; - DBG("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); return cr1; } static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - DBG("%s: cr2: %x\n", where, cr2); flush(); + DBG("%s: cr2: %x\n", where, cr2); stm_i2c->cr2 = cr2; } static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { uint32_t dr = stm_i2c->dr; - DBG("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); return dr; } static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - DBG("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); stm_i2c->dr = dr; } @@ -236,8 +236,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t *b = block; uint32_t sr1; - int t; - uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ -- cgit v1.2.3 From a00aff5ee93ea9763b5c0466fcecc823cad135ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:20:43 -0700 Subject: altos: Don't try to grab radio while firing MM igniters If you're in idle mode, you stop forever as the packet mode receiver will own the radio mutex forever. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 561b5513..d4aef153 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,7 +81,9 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { +#ifndef MEGAMETRUM ao_mutex_get(&ao_radio_mutex); +#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -126,7 +128,9 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; +#ifndef MEGAMETRUM ao_mutex_put(&ao_radio_mutex); +#endif } void -- cgit v1.2.3 From b96eece8e42df0713fc92d47b6bb27604c0168a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:22:00 -0700 Subject: altos: Clean up cc1120 driver a bit Make some variables static, remove stale debug code Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 501b9370..cc9ebd30 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -29,12 +29,6 @@ uint8_t ao_radio_in_recv; #define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 -#if CC1120_TRACE -#define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n) -#else -#define fec_dump_bytes(b,l,n) -#endif - const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -582,12 +576,12 @@ ao_radio_send(const void *d, uint8_t size) #define AO_RADIO_MAX_RECV 90 -uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; -uint16_t rx_data_count; -uint16_t rx_data_consumed; -uint16_t rx_data_cur; -uint8_t rx_ignore; -uint8_t rx_waiting; +static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; +static uint16_t rx_data_count; +static uint16_t rx_data_consumed; +static uint16_t rx_data_cur; +static uint8_t rx_ignore; +static uint8_t rx_waiting; #if AO_PROFILE static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; -- cgit v1.2.3 From 9695a217e13f9d194b6dc40e2696017e5f8e8176 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:22:32 -0700 Subject: altos: disable FEC debug on MM Seems to work; we'll leave the code around in case something bad happens later. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f5bd3e0d..1d2051e1 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -271,7 +271,7 @@ struct ao_adc { * Radio (cc1120) */ -#define AO_FEC_DEBUG 1 +#define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 #define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) -- cgit v1.2.3 From 1a1d4a557a30e2e743936b828b654187ec562ca8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 02:46:27 -0700 Subject: altos: Wait for i2c START condition before setting interrupt bits This seems better than the random loop that it replaces, but I still have no idea why this is required; it doesn't coorespond to the docs at all... Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 128 ++++++++++++++++++--------------------------------- src/stm/stm32l.h | 2 +- 2 files changed, 45 insertions(+), 85 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 51631cb7..4d7d8d87 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -33,6 +33,22 @@ static uint8_t ao_i2c_state[STM_NUM_I2C]; static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; +#if AO_PCLK1 == 2000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_2_MHZ +#endif +#if AO_PCLK1 == 4000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_4_MHZ +#endif +#if AO_PCLK1 == 8000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_8_MHZ +#endif +#if AO_PCLK1 == 16000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_16_MHZ +#endif +#if AO_PCLK1 == 32000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_32_MHZ +#endif + #define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) | \ (0 << STM_I2C_CR1_ALERT) | \ (0 << STM_I2C_CR1_PEC) | \ @@ -53,7 +69,7 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; (0 << STM_I2C_CR2_ITBUFEN) | \ (0 << STM_I2C_CR2_ITEVTEN) | \ (0 << STM_I2C_CR2_ITERREN) | \ - (STM_I2C_CR2_FREQ_16_MHZ << STM_I2C_CR2_FREQ)) + (AO_STM_I2C_CR2_FREQ << STM_I2C_CR2_FREQ)) static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { { @@ -136,61 +152,6 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } -static inline void -ao_i2c_delay(void) -{ - uint8_t i; - - for (i = 0; i < 10; i++) - ao_arch_nop(); -} - -#define I2C_DEBUG 0 -#if I2C_DEBUG -#define DBG(x...) do { printf(x); flush(); } while (0) -#else -#define DBG(x...) -#endif - -static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { - uint32_t sr1 = stm_i2c->sr1; - DBG("%s: sr1: %x\n", where, sr1); - return sr1; -} - -static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { - uint32_t sr2 = stm_i2c->sr2; - DBG("%s: sr2: %x\n", where, sr2); - return sr2; -} - -static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - DBG("%s: cr1: %x\n", where, cr1); - stm_i2c->cr1 = cr1; -} - -static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { - uint32_t cr1 = stm_i2c->cr1; - DBG("%s: cr1: %x\n", where, cr1); - return cr1; -} - -static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - DBG("%s: cr2: %x\n", where, cr2); - stm_i2c->cr2 = cr2; -} - -static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { - uint32_t dr = stm_i2c->dr; - DBG("%s: dr: %x\n", where, dr); - return dr; -} - -static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - DBG("%s: dr: %x\n", where, dr); - stm_i2c->dr = dr; -} - uint8_t ao_i2c_start(uint8_t index, uint16_t addr) { @@ -200,13 +161,14 @@ ao_i2c_start(uint8_t index, uint16_t addr) ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - out_cr2("start", stm_i2c, AO_STM_I2C_CR2); - out_cr1("start", stm_i2c, - AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); - ao_i2c_delay(); - out_cr2("start", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - ao_alarm(1); + stm_i2c->cr2 = AO_STM_I2C_CR2; + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START))) + break; + } + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + ao_alarm(AO_MS_TO_TICKS(250)); cli(); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) @@ -223,7 +185,7 @@ ao_i2c_wait_stop(uint8_t index) int t; for (t = 0; t < I2C_TIMEOUT; t++) { - if (!(in_cr1("wait stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_STOP))) break; ao_yield(); } @@ -239,8 +201,8 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ - in_sr2("send clear addr", stm_i2c); - out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN)); + (void) stm_i2c->sr2; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -262,15 +224,14 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; ao_clear_alarm(); ao_dma_done_transfer(tx_dma_index); - out_cr2("send enable isr", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0) + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0) if (ao_sleep(&ao_i2c_state[index])) break; - out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); + stm_i2c->cr2 = AO_STM_I2C_CR2; sei(); if (stop) { - out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); } return TRUE; @@ -307,19 +268,18 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) if (len == 1) { ao_i2c_recv_data[index] = block; ao_i2c_recv_len[index] = 1; - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + stm_i2c->cr1 = AO_STM_I2C_CR1; /* Clear any pending ADDR bit */ - in_sr2("clear addr", stm_i2c); + stm_i2c->sr2; /* Enable interrupts to transfer the byte */ - out_cr2("setup recv 1", stm_i2c, - AO_STM_I2C_CR2 | - (1 << STM_I2C_CR2_ITEVTEN) | - (1 << STM_I2C_CR2_ITERREN) | - (1 << STM_I2C_CR2_ITBUFEN)); + stm_i2c->cr2 = (AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_ITEVTEN) | + (1 << STM_I2C_CR2_ITERREN) | + (1 << STM_I2C_CR2_ITBUFEN)); if (stop) - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_alarm(1); cli(); @@ -343,11 +303,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); - out_cr1("recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); - out_cr2("recv > 1", stm_i2c, AO_STM_I2C_CR2 | - (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK); + stm_i2c->cr2 = AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST); /* Clear any pending ADDR bit */ - in_sr2("clear addr", stm_i2c); + (void) stm_i2c->sr2; ao_dma_start(rx_dma_index); ao_alarm(len); @@ -359,7 +319,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_clear_alarm(); ret = ao_dma_done[rx_dma_index]; ao_dma_done_transfer(rx_dma_index); - out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); } if (stop) ao_i2c_wait_stop(index); diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 60f0b6d0..ff8dddff 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1255,7 +1255,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CR2_FREQ_8_MHZ 8 #define STM_I2C_CR2_FREQ_16_MHZ 16 #define STM_I2C_CR2_FREQ_32_MHZ 32 -#define STM_I2C_CR2_FREQ_MASK 0x3f; +#define STM_I2C_CR2_FREQ_MASK 0x3f #define STM_I2C_SR1_SMBALERT 15 #define STM_I2C_SR1_TIMEOUT 14 -- cgit v1.2.3 From 08a4ed8fe794a2b2b52147bd5535fe0954822e95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 14:34:53 -0700 Subject: altos: include targe SPI speed in get request STM needs it to be provided when enabling the SPI device, so just fix AVR and cc1111 to do the same. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 10 +++++----- src/cc1111/ao_arch_funcs.h | 19 +++++++++++++++---- src/drivers/ao_25lc1024.c | 2 +- src/drivers/ao_at45db161d.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_companion.c | 18 +++++------------- src/drivers/ao_m25.c | 2 +- src/drivers/ao_ms5607.c | 2 +- src/stm-demo/ao_demo.c | 4 ++-- src/stm/ao_arch_funcs.h | 19 ++++++++----------- src/stm/ao_spi_stm.c | 6 ++---- 11 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index 1eeca6cc..e400c98b 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -21,7 +21,7 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask,bus) do { \ +#define ao_spi_get_mask(reg,mask,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ (reg) &= ~(mask); \ } while (0) @@ -31,13 +31,13 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do { \ +#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ + (pin) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ +#define ao_spi_put_bit(reg,bit,pin,bus) do { \ + (pin) = 1; \ ao_mutex_put(&ao_spi_mutex); \ } while (0) diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 728f1f76..0a322961 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -21,9 +21,18 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask,bus) do { \ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ +#define AO_SPI_SPEED_FAST 17 +#define AO_SPI_SPEED_200kHz 13 + +#define ao_spi_set_speed(speed) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + ((speed) << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_get_mask(reg,mask,bus,speed) do { \ + ao_mutex_get(&ao_spi_mutex); \ + ao_spi_set_speed(speed); \ + (reg) &= ~(mask); \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ @@ -31,8 +40,10 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(reg,bit,pin,bus) do { \ + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ + ao_spi_set_speed(speed); \ pin = 0; \ } while (0) diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index b25d52c4..c5d811f7 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -50,7 +50,7 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS, AO_SPI_SPEED_FAST) #define ao_ee_cs_high() ao_spi_put_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index 5eb25acf..e7e74153 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,7 +43,7 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS, AO_SPI_SPEED_FAST) #define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index cc9ebd30..c974613e 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -33,7 +33,7 @@ const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_1MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index a31cc2ea..85d68c44 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -18,28 +18,20 @@ #include #include -#ifndef ao_spi_slow -#define ao_spi_slow(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) +#ifdef MEGAMETRUM +#define ao_spi_slow(b) +#define ao_spi_fast(b) #endif #define COMPANION_SELECT() do { \ ao_spi_get_bit(AO_COMPANION_CS_PORT, \ AO_COMPANION_CS_PIN, \ AO_COMPANION_CS, \ - AO_COMPANION_SPI_BUS); \ - ao_spi_slow(AO_COMPANION_SPI_BUS); \ + AO_COMPANION_SPI_BUS, \ + AO_SPI_SPEED_200kHz); \ } while (0) #define COMPANION_DESELECT() do { \ - ao_spi_fast(AO_COMPANION_SPI_BUS); \ ao_spi_put_bit(AO_COMPANION_CS_PORT, \ AO_COMPANION_CS_PIN, \ AO_COMPANION_CS, \ diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 2983a405..9603c1de 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -110,7 +110,7 @@ static void ao_boot_radio(void) { #define ao_boot_radio() #endif -#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS); } while (0) +#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS, AO_SPI_SPEED_FAST); } while (0) #define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index e08f4d40..e1d0507e 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -24,7 +24,7 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { - ao_spi_get(AO_MS5607_SPI_INDEX); + ao_spi_get(AO_MS5607_SPI_INDEX,AO_SPI_SPEED_FAST); stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); } diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 73ace558..9a581ff9 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -83,7 +83,7 @@ ao_spi_write(void) { int i; for (i = 0; i < 10; i++) { - ao_spi_get(0); + ao_spi_get(0, AO_SPI_SPEED_FAST); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_send(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); @@ -100,7 +100,7 @@ ao_spi_read(void) { int i; for (i = 0; i < 10; i++) { - ao_spi_get(0); + ao_spi_get(0, AO_SPI_SPEED_FAST); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_recv(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 62b10063..7820bf79 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -22,8 +22,12 @@ */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; +#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 + void -ao_spi_get(uint8_t spi_index); +ao_spi_get(uint8_t spi_index, uint32_t speed); void ao_spi_put(uint8_t spi_index); @@ -40,20 +44,13 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); -#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 - extern uint16_t ao_spi_speed[STM_NUM_SPI]; -#define ao_spi_slow(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_200kHz) - -#define ao_spi_fast(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_FAST) - void ao_spi_init(void); -#define ao_spi_get_mask(reg,mask,bus) do { \ - ao_spi_get(bus); \ +#define ao_spi_get_mask(reg,mask,bus, speed) do { \ + ao_spi_get(bus, speed); \ (reg)->bsrr = ((uint32_t) mask) << 16; \ } while (0) @@ -62,7 +59,7 @@ ao_spi_init(void); ao_spi_put(bus); \ } while (0) -#define ao_spi_get_bit(reg,bit,pin,bus) ao_spi_get_mask(reg,(1< Date: Wed, 27 Jun 2012 14:35:56 -0700 Subject: altos: reorder stm USB state stores to avoid races Must set ao_usb_in_pending before telling USB about new data or an interrupt could arrive at the wrong time to clear it. Same for ao_usb_in_flushed. Without these changes, I've seen the USB bus lock up on occasion, waiting for an IN packet to consume data, but with no IN data pending in the hardware. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index c093f526..4f37a7d9 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -792,10 +792,10 @@ static void ao_usb_in_send(void) { debug ("send %d\n", ao_usb_tx_count); + ao_usb_in_pending = 1; ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); - ao_usb_in_pending = 1; ao_usb_tx_count = 0; } @@ -848,12 +848,12 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_wait(); + ao_usb_in_flushed = 0; ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) ao_usb_in_send(); - ao_usb_in_flushed = 0; } static void -- cgit v1.2.3 From b0b7f5da2d29716959c6793d744e47a3d435c247 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 14:38:35 -0700 Subject: altos: get MPU6000 I2C link working reliably This slows the i2c bus to 100kHz (yuck), sets the rise time to spec (it was way off) and adds more delays during bus setup. I've run this for hours now without trouble. Will try to adjust things back to fast mode and see if I can make that work as 100kHz isn't fast enough to reliably get data at 100 samples/sec. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 4d7d8d87..c4a6c5a3 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -167,9 +167,10 @@ ao_i2c_start(uint8_t index, uint16_t addr) if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START))) break; } - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); ao_alarm(AO_MS_TO_TICKS(250)); cli(); + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + ao_i2c_ev_isr(index); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) break; @@ -192,6 +193,19 @@ ao_i2c_wait_stop(uint8_t index) ao_i2c_state[index] = I2C_IDLE; } +static void +ao_i2c_wait_addr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + int t; + + for (t = 0; t < I2C_TIMEOUT; t++) + if (!(stm_i2c->sr1 & (1 << STM_I2C_SR1_ADDR))) + break; + if (t) + printf ("wait_addr %d\n", t); +} + uint8_t ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) { @@ -199,9 +213,11 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint8_t *b = block; uint32_t sr1; uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + int t; /* Clear any pending ADDR bit */ (void) stm_i2c->sr2; + ao_i2c_wait_addr(index); stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, @@ -272,6 +288,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) /* Clear any pending ADDR bit */ stm_i2c->sr2; + ao_i2c_wait_addr(index); /* Enable interrupts to transfer the byte */ stm_i2c->cr2 = (AO_STM_I2C_CR2 | @@ -308,6 +325,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST); /* Clear any pending ADDR bit */ (void) stm_i2c->sr2; + ao_i2c_wait_addr(index); ao_dma_start(rx_dma_index); ao_alarm(len); @@ -346,10 +364,11 @@ ao_i2c_channel_init(uint8_t index) stm_i2c->sr1 = 0; stm_i2c->sr2 = 0; - stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) | + stm_i2c->ccr = ((0 << STM_I2C_CCR_FS) | (0 << STM_I2C_CCR_DUTY) | - (20 << STM_I2C_CCR_CCR)); - + (80 << STM_I2C_CCR_CCR)); + + stm_i2c->trise = 17; stm_i2c->cr1 = AO_STM_I2C_CR1; } -- cgit v1.2.3 From 84f9a525c64491afa9b7a565e3c10a4cee106e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:17:44 -0700 Subject: altos: Clean up radio CRC handling Make the FEC code just set the CRC_OK bit like the cc1111 radio does; eliminates a bunch of weird conventions across the FEC API. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++++ src/core/ao_fec.h | 2 ++ src/core/ao_fec_rx.c | 26 +++++++++++++++----------- src/drivers/ao_cc1120.c | 7 +------ src/drivers/ao_packet.c | 4 +--- src/test/ao_fec_test.c | 21 ++++++++++----------- 6 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index 62eb488e..861a0fd4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -511,6 +511,13 @@ extern __xdata uint8_t ao_radio_dma_done; extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; +#ifdef PKT_APPEND_STATUS_1_CRC_OK +#define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK +#else +#include +#define AO_RADIO_STATUS_CRC_OK AO_FEC_DECODE_CRC_OK +#endif + void ao_radio_general_isr(void) ao_arch_interrupt(16); diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f1192b62..771732bd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -70,6 +70,8 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ + uint8_t ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 0d400bb0..d4c98475 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -211,6 +211,7 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ + uint8_t byte; /* Find the best fit at the current point * of the decode. @@ -238,24 +239,27 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - if (out_len) { - uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + byte = (bits[p][min_state] >> dist) ^ *whiten++; + *out++ = byte; + if (out_len > 2) + crc = ao_fec_crc_byte(byte, crc); - if (out_len > 2) { - crc = ao_fec_crc_byte(byte, crc); - *out++ = byte; - } else { - *out++ = byte ^ (crc >> 8); - crc <<= 8; - } - --out_len; + if (!--out_len) { + if ((out[-2] == (uint8_t) (crc >> 8)) && + out[-1] == (uint8_t) crc) + out[-1] = AO_FEC_DECODE_CRC_OK; + else + out[-1] = 0; + out[-2] = 0; + goto done; } o += 8; } } +done: #if AO_PROFILE ao_fec_decode_start = start_tick; ao_fec_decode_end = ao_profile_tick(); #endif - return len/16; + return 1; } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index c974613e..30663042 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -690,12 +690,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_put(); - /* Construct final packet */ - - if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) - ((uint8_t *) d)[size + 1] = 0x80; - else - ((uint8_t *) d)[size + 1] = 0x00; + /* Store the received RSSI value; the crc-OK byte is already done */ ((uint8_t *) d)[size] = (uint8_t) rssi; diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 19fe0558..28a0c415 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -65,10 +65,8 @@ ao_packet_recv(void) /* Check to see if we got a valid packet */ if (!dma_done) return 0; -#ifdef PKT_APPEND_STATUS_1_CRC_OK - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; -#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 8ce532c8..671fcafc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -268,18 +268,17 @@ int ao_real_packet(void) { uint8_t decode[64]; - uint8_t decode_len; - int ok = 0; + int ok; - decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); + ok = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (decode[32] == 0 && decode[33] == 0) { + if (ok && decode[33] == AO_FEC_DECODE_CRC_OK) { printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - ok = 1; + ao_fec_dump_bytes(decode, 34, "Decode"); } else { printf ("actual packet crc error\n"); + ok = 0; } return ok; } @@ -302,7 +301,7 @@ main(int argc, char **argv) int receive_len, receive_errors; uint8_t decode[DECODE_LEN(sizeof(original))]; - int decode_len; + int decode_ok; int errors = 0; int error; @@ -327,17 +326,17 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); + decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; - if (decode_len < original_len + 2) { - printf ("len mis-match\n"); + if (!decode_ok) { + printf ("decode failed\n"); error++; } - if (decode[original_len] != 0 || decode[original_len+1] != 0) { + if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { printf ("crc mis-match\n"); error++; } -- cgit v1.2.3 From 4f258fe565dc3e58b83761bfa1a2276946012163 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:18:57 -0700 Subject: altos: Clean up STM I2C clock computations Fix both clock time and rise time. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 63 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index c4a6c5a3..b6dd7056 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -23,6 +23,8 @@ struct ao_i2c_stm_info { struct stm_i2c *stm_i2c; }; +#define I2C_FAST 1 + #define I2C_TIMEOUT 100 #define I2C_IDLE 0 @@ -33,6 +35,33 @@ static uint8_t ao_i2c_state[STM_NUM_I2C]; static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; +# define I2C_HIGH_SLOW 5000 /* ns, 100kHz clock */ +#ifdef MEGAMETRUM +# define I2C_HIGH_FAST 2000 /* ns, 167kHz clock */ +#else +# define I2C_HIGH_FAST 1000 /* ns, 333kHz clock */ +#endif + +# define I2C_RISE_SLOW 500 /* ns */ +# define I2C_RISE_FAST 100 /* ns */ + +/* Clock period in ns */ +#define CYCLES(period) (((period) * (AO_PCLK1 / 1000)) / 1000000) + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define I2C_CCR_HIGH_SLOW max(4,CYCLES(I2C_HIGH_SLOW)) +#define I2C_CCR_HIGH_FAST max(4,CYCLES(I2C_HIGH_FAST)) +#define I2C_TRISE_SLOW (CYCLES(I2C_RISE_SLOW) + 1) +#define I2C_TRISE_FAST (CYCLES(I2C_RISE_FAST) + 1) + +#if I2C_FAST +#define I2C_TRISE I2C_TRISE_FAST +#define I2C_CCR_HIGH I2C_CCR_HIGH_FAST +#else +#define I2C_TRISE I2C_TRISE_SLOW +#define I2C_CCR_HIGH I2C_CCR_HIGH_SLOW +#endif + #if AO_PCLK1 == 2000000 # define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_2_MHZ #endif @@ -364,15 +393,23 @@ ao_i2c_channel_init(uint8_t index) stm_i2c->sr1 = 0; stm_i2c->sr2 = 0; - stm_i2c->ccr = ((0 << STM_I2C_CCR_FS) | + stm_i2c->ccr = ((I2C_FAST << STM_I2C_CCR_FS) | (0 << STM_I2C_CCR_DUTY) | - (80 << STM_I2C_CCR_CCR)); + (I2C_CCR_HIGH << STM_I2C_CCR_CCR)); - stm_i2c->trise = 17; + stm_i2c->trise = I2C_TRISE; stm_i2c->cr1 = AO_STM_I2C_CR1; } +static inline void +i2c_pin_set(struct stm_gpio *gpio, int pin) +{ + stm_afr_set(gpio, pin, STM_AFR_AF4); + stm_ospeedr_set(gpio, pin, STM_OSPEEDR_400kHz); + stm_pupdr_set(gpio, pin, STM_PUPDR_PULL_UP); +} + void ao_i2c_init(void) { @@ -380,12 +417,12 @@ ao_i2c_init(void) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); #if HAS_I2C_1 # if I2C_1_PB6_PB7 - stm_afr_set(&stm_gpiob, 6, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 7, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 6); + i2c_pin_set(&stm_gpiob, 7); # else # if I2C_1_PB8_PB9 - stm_afr_set(&stm_gpiob, 8, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 9, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 8); + i2c_pin_set(&stm_gpiob, 9); # else # error "No I2C_1 port configuration specified" # endif @@ -395,15 +432,15 @@ ao_i2c_init(void) ao_i2c_channel_init(0); stm_nvic_set_enable(STM_ISR_I2C1_EV_POS); - stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, AO_STM_NVIC_MED_PRIORITY); stm_nvic_set_enable(STM_ISR_I2C1_ER_POS); - stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, AO_STM_NVIC_MED_PRIORITY); #endif #if HAS_I2C_2 # if I2C_2_PB10_PB11 - stm_afr_set(&stm_gpiob, 10, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 11, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 10); + i2c_pin_set(&stm_gpiob, 11); # else # error "No I2C_2 port configuration specified" # endif @@ -411,8 +448,8 @@ ao_i2c_init(void) ao_i2c_channel_init(1); stm_nvic_set_enable(STM_ISR_I2C2_EV_POS); - stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, AO_STM_NVIC_MED_PRIORITY); stm_nvic_set_enable(STM_ISR_I2C2_ER_POS); - stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, AO_STM_NVIC_MED_PRIORITY); #endif } -- cgit v1.2.3 From 407cefae9cb95c5910b3bd79851776c48729e06b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:45:22 -0700 Subject: altos: Unroll viterbi state loop for >30% performance boost 9.3ms vs 14.7ms, a clear win. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index d4c98475..c1a3918b 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -161,31 +161,43 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path - * for each state and encoded bit value + * for each state and encoded bit value. Unrolling + * this loop is worth about > 30% performance boost. + * Decoding 76-byte remote access packets is reduced + * from 14.700ms to 9.3ms */ - for (state = 0; state < NUM_STATE; state++) { - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); - { - uint32_t cost0 = cost[p][state] + bitcost; - uint8_t state0 = ao_next_state(state, 0); - - if (cost0 < cost[n][state0]) { - cost[n][state0] = cost0; - bits[n][state0] = (bits[p][state] << 1) | (state & 1); - } - } - { - uint32_t cost1 = cost[p][state] + 510 - bitcost; - uint8_t state1 = ao_next_state(state, 1); - - if (cost1 < cost[n][state1]) { - cost[n][state1] = cost1; - bits[n][state1] = (bits[p][state] << 1) | (state & 1); - } - } +#define DO_STATE(state) { \ + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ + { \ + uint32_t cost0 = cost[p][state] + bitcost; \ + uint8_t state0 = ao_next_state(state, 0); \ + \ + if (cost0 < cost[n][state0]) { \ + cost[n][state0] = cost0; \ + bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ + { \ + uint32_t cost1 = cost[p][state] + 510 - bitcost; \ + uint8_t state1 = ao_next_state(state, 1); \ + \ + if (cost1 < cost[n][state1]) { \ + cost[n][state1] = cost1; \ + bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ } + DO_STATE(0); + DO_STATE(1); + DO_STATE(2); + DO_STATE(3); + DO_STATE(4); + DO_STATE(5); + DO_STATE(6); + DO_STATE(7); + #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { -- cgit v1.2.3 From bd21c050fd8b96b33ab6859c942bf55cf2b91868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:47:52 -0700 Subject: altos: Make profiling Viterbi decoder more useful This blocks starting the decoder until all of the data have arrived so that the time spent in the decoder is easily computed. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 8 +++++++- src/drivers/ao_packet.c | 12 ++++++++++++ src/megametrum-v0.1/Makefile | 7 +++---- src/megametrum-v0.1/ao_megametrum.c | 3 +++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 30663042..1d28148b 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -605,8 +605,10 @@ ao_radio_rx_isr(void) rx_data[rx_data_cur++] = d; if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { #if AO_PROFILE - if (rx_data_consumed == 0) + if (!rx_packet_tick) rx_packet_tick = ao_profile_tick(); + if (rx_data_cur < rx_data_count) + return; #endif rx_waiting = 0; ao_wakeup(&ao_radio_wake); @@ -630,6 +632,9 @@ ao_radio_rx_wait(void) if (ao_radio_abort) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; +#if AO_PROFILE + return rx_data_cur - rx_data_consumed; +#endif return AO_FEC_DECODE_BLOCK; } @@ -649,6 +654,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) } #if AO_PROFILE rx_start_tick = ao_profile_tick(); + rx_packet_tick = 0; #endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 28a0c415..e020c003 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -61,6 +61,18 @@ ao_packet_recv(void) #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n\n", ao_rx_done_tick - ao_fec_decode_end); + flush(); + } +#endif /* Check to see if we got a valid packet */ if (!dma_done) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 07a339b9..06b5e2ae 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -27,8 +27,7 @@ INC = \ # Common AltOS sources # -# ao_packet.c \ -# ao_packet_slave.c \ +#PROFILE=ao_profile.c ALTOS_SRC = \ ao_interrupt.c \ @@ -72,8 +71,8 @@ ALTOS_SRC = \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ - ao_companion.c - + ao_companion.c \ + $(PROFILE) PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index ed35efa4..749f251d 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -63,6 +63,9 @@ main(void) ao_companion_init(); ao_config_init(); +#if AO_PROFILE + ao_profile_init(); +#endif ao_start_scheduler(); return 0; -- cgit v1.2.3 From dd623b21cb904238c6d903b6936ff2f8ebf6f339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:03:33 -0700 Subject: altos: Allow megametrum to be built without using the mag sensor I'm having trouble getting it working reliably, so we'll like disable it for now. This patch makes that possible. Signed-off-by: Keith Packard --- src/core/ao_log_mega.c | 8 +++++++- src/core/ao_telemetry.c | 4 ++++ src/megametrum-v0.1/ao_megametrum.c | 6 ++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index e7c2b0d9..ac1590db 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,18 +112,24 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; +#if HAS_MS5607 log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; +#endif +#if HAS_MPU6000 log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; +#endif +#if HAS_HMC5883 log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; - log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; +#endif + log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index b3ce8ba9..3c747520 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -104,6 +104,7 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); +#if HAS_MPU6000 telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; @@ -111,10 +112,13 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; +#endif +#if HAS_HMC5883 telemetry.mega_sensor.mag_x = packet->hmc5883.x; telemetry.mega_sensor.mag_y = packet->hmc5883.y; telemetry.mega_sensor.mag_z = packet->hmc5883.z; +#endif ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 749f251d..a6d93733 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -43,9 +43,15 @@ main(void) ao_beep_init(); ao_cmd_init(); +#if HAS_MS5607 ao_ms5607_init(); +#endif +#if HAS_HMC5883 ao_hmc5883_init(); +#endif +#if HAS_MPU6000 ao_mpu6000_init(); +#endif ao_storage_init(); -- cgit v1.2.3 From f9f65211c378849270a6138fda05ed2a166f7d82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:04:25 -0700 Subject: altos: Disable mag sensor for megametrum It doesn't work unless USB is connected or occasionally while the debug port is enabled. It's mystic. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- src/megametrum-v0.1/ao_pins.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 06b5e2ae..e789a0e8 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -29,6 +29,8 @@ INC = \ #PROFILE=ao_profile.c +# ao_hmc5883.c + ALTOS_SRC = \ ao_interrupt.c \ ao_product.c \ @@ -60,7 +62,6 @@ ALTOS_SRC = \ ao_exti_stm.c \ ao_report.c \ ao_i2c_stm.c \ - ao_hmc5883.c \ ao_mpu6000.c \ ao_convert_pa.c \ ao_log.c \ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 1d2051e1..dc3761ba 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -286,7 +286,7 @@ struct ao_adc { * Mag sensor (hmc5883) */ -#define HAS_HMC5883 1 +#define HAS_HMC5883 0 #define AO_HMC5883_INT_PORT (&stm_gpioc) #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) -- cgit v1.2.3 From aab7b31b71aa7c87c5a5003084e4b7773c30835f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:05:36 -0700 Subject: altos: panic if MPU6000 self test fails Don't try to fly if the board isn't working right. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 53 +++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 065ed221..a1c32d4d 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -102,16 +102,12 @@ ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) int16_t diff = test - normal; if (diff < MPU6000_ST_ACCEL(16) / 2) { - printf ("%s accel self test value too small (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } if (diff > MPU6000_ST_ACCEL(16) * 2) { - printf ("%s accel self test value too large (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } - return TRUE; + return 0; } static uint8_t @@ -122,23 +118,19 @@ ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) if (diff < 0) diff = -diff; if (diff < MPU6000_ST_GYRO(2000) / 2) { - printf ("%s gyro self test value too small (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } if (diff > MPU6000_ST_GYRO(2000) * 2) { - printf ("%s gyro self test value too large (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } - return TRUE; + return 0; } static void ao_mpu6000_setup(void) { struct ao_mpu6000_sample normal_mode, test_mode; - int t; + int errors =0; if (ao_mpu6000_configured) return; @@ -224,13 +216,16 @@ ao_mpu6000_setup(void) ao_delay(AO_MS_TO_TICKS(10)); ao_mpu6000_sample(&normal_mode); - ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); - ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); - ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); + errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); + errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); + errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); - ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); - ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); - ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + + if (errors) + ao_panic(AO_PANIC_SELF_TEST); /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ ao_mpu6000_reg_write(MPU6000_CONFIG, @@ -271,14 +266,16 @@ ao_mpu6000_show(void) { struct ao_mpu6000_sample sample; - sample = ao_mpu6000_current; + ao_arch_critical( + sample = ao_mpu6000_current; + ); printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", - ao_mpu6000_accel(sample.accel_x), - ao_mpu6000_accel(sample.accel_y), - ao_mpu6000_accel(sample.accel_z), - ao_mpu6000_gyro(sample.gyro_x), - ao_mpu6000_gyro(sample.gyro_y), - ao_mpu6000_gyro(sample.gyro_z)); + sample.accel_x, + sample.accel_y, + sample.accel_z, + sample.gyro_x, + sample.gyro_y, + sample.gyro_z); } static const struct ao_cmds ao_mpu6000_cmds[] = { -- cgit v1.2.3 From 79dbe1a5e46d7f0b8929400897631ab969cd2bc0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:09:16 -0700 Subject: altos: Increase default STM stack to 648 bytes 512 seems cozy given the printf implementation we're using and the extensive interrupts. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 30cd9ea5..baae1902 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 512 +#define AO_STACK_SIZE 700 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 572e1664938c7ce6c308b36779f6a412959e03f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:11:27 -0700 Subject: altos: Track missed HMC5883 interrupts When it fails to signal conversion complete to the CPU, keep track of that and report it with the rest of the current data. Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 64663ea6..dbeb66b8 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -63,6 +63,8 @@ ao_hmc5883_isr(void) ao_wakeup(&ao_hmc5883_done); } +static uint32_t ao_hmc5883_missed_irq; + void ao_hmc5883_sample(struct ao_hmc5883_sample *sample) { @@ -74,10 +76,13 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + ao_alarm(AO_MS_TO_TICKS(10)); cli(); while (!ao_hmc5883_done) - ao_sleep(&ao_hmc5883_done); + if (ao_sleep(&ao_hmc5883_done)) + ++ao_hmc5883_missed_irq; sei(); + ao_clear_alarm(); ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -144,7 +149,8 @@ ao_hmc5883_show(void) struct ao_hmc5883_sample sample; sample = ao_hmc5883_current; - printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); + printf ("X: %d Y: %d Z: %d missed irq: %lu\n", + sample.x, sample.y, sample.z, ao_hmc5883_missed_irq); } static const struct ao_cmds ao_hmc5883_cmds[] = { -- cgit v1.2.3 From ca1bc20735a170a77066f5f37e0ad728899a3989 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jun 2012 16:05:56 -0700 Subject: altos: Disable MS5607 interrupt in the handler Avoids having the interrupt re-raised multiple times until the reading task finally wakes up. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index e1d0507e..17fe853b 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -118,6 +118,7 @@ static uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { + ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_done = 1; ao_wakeup(&ao_ms5607_done); } @@ -137,7 +138,6 @@ ao_ms5607_get_sample(uint8_t cmd) { while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); - ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); ao_ms5607_start(); -- cgit v1.2.3 From ccf64117662fc800a07b3a25e52255b80f8b5eaf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jun 2012 16:42:59 -0700 Subject: Update version to 1.0.9.6 Signed-off-by: Keith Packard --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 170e0dfc..a3004811 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.5) +AC_INIT([altos], 1.0.9.6) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE -- cgit v1.2.3 From edbc5d27c8c2936b59ff5289276d9198b501ebc8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jun 2012 17:43:36 -0700 Subject: altos: Declare cc1111 accel_ref as unsigned so the math works If accel_ref is signed, then the careful shifting and dividing dance necessary to correct for changes in the relationship between the 5V and 3.3V supplies always generates zero. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index cece09eb..8d9e4952 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -206,7 +206,7 @@ struct ao_adc { int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ #if HAS_ACCEL_REF - int16_t accel_ref; /* acceleration reference */ + uint16_t accel_ref; /* acceleration reference */ #endif }; -- cgit v1.2.3 From f0ec8416f2e308e40e1b9f34a7c2549989fee5fb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 30 Jun 2012 13:00:33 -0600 Subject: conditionalize build of ARM binaries on presence of arm-none-eabi-gcc in PATH --- src/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3fca2ab2..1b0dabe4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,8 +15,6 @@ vpath matrix.5c kalman include Version SUBDIRS=\ - megametrum-v0.1 \ - stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ @@ -26,6 +24,10 @@ SUBDIRS=\ tidongle test telescience-v0.1 telepyro-v0.1 \ teleterra-v0.2 teleshield-v0.1 +ifneq ($(shell which arm-none-eabi-gcc),) + SUBDIRS += megametrum-v0.1 stm-bringup stm-demo +endif + all: all-local all-recursive RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive -- cgit v1.2.3 From 50b343d389039eae082e82b8ac0b76ae3e2b3ad4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 1 Jul 2012 23:24:20 -0600 Subject: extend cross-compiler availability logic to all target CPUs, not just ARM --- src/Makefile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 1b0dabe4..491618f6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,6 @@ # # AltOS build # -# vpath make-altitude util vpath make-altitude-pa util @@ -14,15 +13,20 @@ vpath matrix.5c kalman include Version -SUBDIRS=\ +ifneq ($(shell which sdcc),) + SUBDIRS+=\ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - telelaunch-v0.1 \ - tidongle test telescience-v0.1 telepyro-v0.1 \ + telelaunch-v0.1 tidongle test \ teleterra-v0.2 teleshield-v0.1 +endif + +ifneq ($(shell which avr-gcc),) + SUBDIRS += telescience-v0.1 telepyro-v0.1 +endif ifneq ($(shell which arm-none-eabi-gcc),) SUBDIRS += megametrum-v0.1 stm-bringup stm-demo -- cgit v1.2.3 From 933fc7e4c2f617e49e1cfdf45b83695290b51456 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jul 2012 23:44:10 -0700 Subject: altos: Do not block igniters on the radio mutex. Blocking igniters on the radio mutex fails when doing igniter testing over the RF link; the packet receiver task will never release the mutex and the CPU at the same time, causing the system to lock up. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 6 ------ src/telemetrum-v1.1/.sdcdbrc | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index d4aef153..e82de355 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,9 +81,6 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { -#ifndef MEGAMETRUM - ao_mutex_get(&ao_radio_mutex); -#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -128,9 +125,6 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; -#ifndef MEGAMETRUM - ao_mutex_put(&ao_radio_mutex); -#endif } void diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc index 710b4a2f..fbe9a599 100644 --- a/src/telemetrum-v1.1/.sdcdbrc +++ b/src/telemetrum-v1.1/.sdcdbrc @@ -1 +1 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. -- cgit v1.2.3 From ea957f9e6144f8411ac84ee2905700f55f5a6e8a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 00:29:43 -0700 Subject: altosui: Fix flight data download for TM. Look for MM flights when graphing A couple of minor fixes, the first to not force the log format so that TM/Tm data will be downloaded correctly and the second to expand the set of files to include '.mega' files when plotting data. Signed-off-by: Keith Packard --- altosui/AltosDataChooser.java | 2 +- altosui/AltosEepromDownload.java | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index 0d629b3c..4bd51c39 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -77,7 +77,7 @@ public class AltosDataChooser extends JFileChooser { frame = in_frame; setDialogTitle("Select Flight Record File"); setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom")); + "telem", "eeprom", "mega")); setCurrentDirectory(AltosUIPreferences.logdir()); } } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index d1e5fdf0..4a35c2f1 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -319,11 +319,9 @@ public class AltosEepromDownload implements Runnable { done = false; start = true; -// if (flights.config_data.serial == 0) -// throw new IOException("no serial number found"); + if (flights.config_data.serial == 0) + throw new IOException("no serial number found"); - log_format = 5; - System.out.printf ("log format: %d\n", log_format); /* Reset per-capture variables */ flight = 0; year = 0; -- cgit v1.2.3 From e8ab00cc45e48230e3b2018ce959114d3fedd228 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 20:59:35 -0700 Subject: altos: Viterbi performance improvments. Down to 5.7ms for command decode Stealing more of Phil's good ideas, decoding a command mode packet has been reduced from 9ms to 5.7ms. Lots more comments to help future-me figure out how this code works. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 105 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index c1a3918b..64426d72 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -62,7 +62,9 @@ static inline uint16_t ao_interleave_index(uint16_t i) { } #define NUM_STATE 8 -#define NUM_HIST 8 +#define NUM_HIST 24 + +typedef uint32_t bits_t; #define V_0 0xff #define V_1 0x00 @@ -97,7 +99,7 @@ uint8_t ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint32_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ @@ -154,54 +156,93 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui avail -= 2; - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0x7fffffff; - /* Compute path costs and accumulate output bit path * for each state and encoded bit value. Unrolling * this loop is worth about > 30% performance boost. * Decoding 76-byte remote access packets is reduced - * from 14.700ms to 9.3ms + * from 14.700ms to 9.3ms. Redoing the loop to + * directly compare the two pasts for each future state + * reduces this down to 5.7ms + */ + + /* Ok, of course this is tricky, it's optimized. + * + * First, it's important to realize that we have 8 + * states representing the combinations of the three + * most recent bits from the encoder. Flipping any + * of these three bits flips both output bits. + * + * 'state<<1' represents the target state for a new + * bit value of 0. '(state<<1)+1' represents the + * target state for a new bit value of 1. + * + * 'state' is the previous state with an oldest bit + * value of 0. 'state + 4' is the previous state with + * an oldest bit value of 1. These two states will + * either lead to 'state<<1' or '(state<<1)+1', depending + * on whether the next encoded bit was a zero or a one. + * + * m0 and m1 are the cost of coming to 'state<<1' from + * one of the two possible previous states 'state' and + * 'state + 4'. + * + * Because we know the expected values of each + * received bit are flipped between these two previous + * states: + * + * bitcost(state+4) = 510 - bitcost(state) + * + * With those two total costs in hand, we then pick + * the lower as the cost of the 'state<<1', and compute + * the path of bits leading to that state. + * + * Then, do the same for '(state<<1) + 1'. This time, + * instead of computing the m0 and m1 values from + * scratch, because the only difference is that we're + * expecting a one bit instead of a zero bit, we just + * flip the bitcost values around to match the + * expected transmitted bits with some tricky + * arithmetic which is equivalent to: + * + * m0 = cost[p][state] + (510 - bitcost); + * m1 = cost[p][state+4] + bitcost + * + * Then, the lowest cost and bit trace of the new state + * is saved. */ + #define DO_STATE(state) { \ - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ - { \ - uint32_t cost0 = cost[p][state] + bitcost; \ - uint8_t state0 = ao_next_state(state, 0); \ + uint32_t bitcost; \ + \ + uint32_t m0; \ + uint32_t m1; \ + uint32_t bit; \ + \ + bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)|1])); \ \ - if (cost0 < cost[n][state0]) { \ - cost[n][state0] = cost0; \ - bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ - { \ - uint32_t cost1 = cost[p][state] + 510 - bitcost; \ - uint8_t state1 = ao_next_state(state, 1); \ + m0 = cost[p][state] + bitcost; \ + m1 = cost[p][state+4] + (510 - bitcost); \ + bit = m0 > m1; \ + cost[n][state<<1] = bit ? m1 : m0; \ + bits[n][state<<1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ \ - if (cost1 < cost[n][state1]) { \ - cost[n][state1] = cost1; \ - bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ + m0 -= (bitcost+bitcost-510); \ + m1 += (bitcost+bitcost-510); \ + bit = m0 > m1; \ + cost[n][(state<<1)+1] = bit ? m1 : m0; \ + bits[n][(state<<1)+1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ } DO_STATE(0); DO_STATE(1); DO_STATE(2); DO_STATE(3); - DO_STATE(4); - DO_STATE(5); - DO_STATE(6); - DO_STATE(7); #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); + printf (" %8u(%08x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif -- cgit v1.2.3 From 939ad8bfd640ed55116703a58f87af06e75ef87e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 21:01:01 -0700 Subject: altos: Crank up the gaussian noise in the FEC test This lets us check to make sure our receive performance isn't degrading at all, instead of just making sure we can receive perfect packets well. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 54 +++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 671fcafc..b94b16dc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -283,6 +283,11 @@ ao_real_packet(void) return ok; } +#define EXPECT_DECODE_FAIL 0 +#define EXPECT_CRC_MISMATCH 6386 +#define EXPECT_DATA_MISMATCH 0 +#define NOISE_AMOUNT 0x50 + int main(int argc, char **argv) { @@ -298,13 +303,15 @@ main(int argc, char **argv) int transmit_len; uint8_t receive[EXPAND_LEN(sizeof(original))]; - int receive_len, receive_errors; + int receive_len; uint8_t decode[DECODE_LEN(sizeof(original))]; int decode_ok; int errors = 0; - int error; + int decode_fail = 0; + int crc_mismatch = 0; + int data_mismatch = 0; if (!ao_real_packet()) errors++; @@ -322,37 +329,38 @@ main(int argc, char **argv) transmit_len = ao_expand(encode, encode_len, transmit); /* Add gaussian noise to the signal */ - receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x38); + (void) ao_fuzz(transmit, transmit_len, receive, NOISE_AMOUNT); receive_len = transmit_len; /* Decode it */ decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ - error = 0; - if (!decode_ok) { - printf ("decode failed\n"); - error++; - } + if (!decode_ok) + decode_fail++; + else if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) + crc_mismatch++; + else if (memcmp(original, decode, original_len) != 0) + data_mismatch++; + } - if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { - printf ("crc mis-match\n"); - error++; - } - if (memcmp(original, decode, original_len) != 0) { - printf ("data mis-match\n"); - error++; - } - if (error) { - printf ("Errors: %d\n", receive_errors); - ao_fec_dump_bytes(original, original_len, "Input"); - ao_fec_dump_bytes(decode, original_len, "Decode"); - errors += error; - } - } printf ("%d packets coded\n", trial); + printf ("decode_fail %d crc_mismatch %d data_mismatch %d\n", + decode_fail, crc_mismatch, data_mismatch); + if (decode_fail != EXPECT_DECODE_FAIL) { + printf ("expected %d decode failures\n", EXPECT_DECODE_FAIL); + errors++; + } + if (crc_mismatch != EXPECT_CRC_MISMATCH) { + printf ("expected %d crc mismatch\n", EXPECT_CRC_MISMATCH); + errors++; + } + if (data_mismatch != EXPECT_DATA_MISMATCH) { + printf ("expected %d data mismatch\n", EXPECT_DATA_MISMATCH); + errors++; + } return errors; } -- cgit v1.2.3 From 31b05454ec8d90b89fa3039563ff0e86ae80b2a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 21:02:20 -0700 Subject: altos: Move profiling settings to Makefile Instead of splitting the changes across Makefile and ao_pins.h, put them both in Makefile to simplify enabling profiling. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- src/megametrum-v0.1/ao_pins.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index e789a0e8..6fc9324e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -28,6 +28,7 @@ INC = \ # #PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 # ao_hmc5883.c @@ -79,7 +80,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x0023 -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dc3761ba..34b75255 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -326,6 +326,8 @@ struct ao_adc { * Profiling Viterbi decoding */ +#ifndef AO_PROFILE #define AO_PROFILE 0 +#endif #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 702ca87983594880d7926d2317d63802af82746e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:07:34 -0700 Subject: altos: remove stale ao_flight.c and ao_sample.c The mega-metrum versions are now the official versions Signed-off-by: Keith Packard --- src/core/ao_flight.c | 350 --------------------------------------------------- src/core/ao_sample.c | 214 ------------------------------- 2 files changed, 564 deletions(-) delete mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_sample.c diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c deleted file mode 100644 index 494e656d..00000000 --- a/src/core/ao_flight.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); - - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { - ao_ignite(ao_igniter_main); - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c deleted file mode 100644 index 2bf9632f..00000000 --- a/src/core/ao_sample.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -/* - * Current sensor values - */ - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata int16_t ao_sample_pres; -__pdata int16_t ao_sample_alt; -__pdata int16_t ao_sample_height; -#if HAS_ACCEL -__pdata int16_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_adc; - -/* - * Sensor calibration values - */ - -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -__pdata int16_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - -uint8_t -ao_sample(void) -{ - ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_sample_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_sample_adc]; - ao_sample_tick = ao_adc->tick; - ao_sample_pres = ao_adc->pres; - ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; -#if HAS_ACCEL - ao_sample_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_sample_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_sample_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_sample_accel 32767 - * = ------------ * ------------ - * 32767 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_sample_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; -#else - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; - } -#endif -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_adc = ao_adc_ring_next(ao_sample_adc); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_adc = ao_adc_head; - ao_preflight = TRUE; -} -- cgit v1.2.3 From 1ae3f467a1d7be2fc3b1a45ba12568a3a25a0099 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:11:36 -0700 Subject: altos: Rename *_mm.c back to *.c Was just a temporary hack to keep cc1111 products building during MM development. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 418 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_flight_mm.c | 418 ---------------------------------------- src/core/ao_sample.c | 138 +++++++++++++ src/core/ao_sample_mm.c | 138 ------------- src/megametrum-v0.1/Makefile | 4 +- src/product/Makefile.telemetrum | 4 +- src/product/Makefile.telemini | 4 +- src/product/Makefile.telenano | 2 +- src/test/Makefile | 9 +- src/test/ao_flight_test.c | 35 ++-- 10 files changed, 591 insertions(+), 579 deletions(-) create mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_sample.c delete mode 100644 src/core/ao_sample_mm.c diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..a0affc48 --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,418 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB && HAS_RADIO + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_TELEMETRY + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_TELEMETRY + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_TELEMETRY + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ +#if HAS_ACCEL + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c deleted file mode 100644 index a0affc48..00000000 --- a/src/core/ao_flight_mm.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#include -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#ifndef HAS_TELEMETRY -#define HAS_TELEMETRY HAS_RADIO -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - -#if HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - -#if HAS_TELEMETRY - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); -#endif - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - -#if HAS_TELEMETRY - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); -#endif - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { -#if HAS_IGNITE - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); -#endif - -#if HAS_TELEMETRY - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); -#endif - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { -#if HAS_IGNITE - ao_ignite(ao_igniter_main); -#endif - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -#if !HAS_RADIO -static inline int int_part(int16_t i) { return i >> 4; } -static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } - -static void -ao_flight_dump(void) -{ -#if HAS_ACCEL - int16_t accel; - - accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; -#endif - - printf ("sample:\n"); - printf (" tick %d\n", ao_sample_tick); - printf (" raw pres %d\n", ao_sample_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); -#endif - printf (" ground pres %d\n", ao_ground_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); - printf (" groundaccel %d\n", ao_ground_accel); - printf (" accel_2g %d\n", ao_accel_2g); -#endif - - printf (" alt %d\n", ao_sample_alt); - printf (" height %d\n", ao_sample_height); -#if HAS_ACCEL - printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); -#endif - - - printf ("kalman:\n"); - printf (" height %d\n", ao_height); - printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); - printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); - printf (" max_height %d\n", ao_max_height); - printf (" avg_height %d\n", ao_avg_height); - printf (" error_h %d\n", ao_error_h); - printf (" error_avg %d\n", ao_error_h_sq_avg); -} - -__code struct ao_cmds ao_flight_cmds[] = { - { ao_flight_dump, "F\0Dump flight status" }, - { 0, NULL }, -}; -#endif - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; -#if !HAS_RADIO - ao_cmd_register(&ao_flight_cmds[0]); -#endif - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..ac11eef0 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,138 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; + +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_cook(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c deleted file mode 100644 index ac11eef0..00000000 --- a/src/core/ao_sample_mm.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#include -#endif - -/* - * Current sensor values - */ - -#ifndef PRES_TYPE -#define PRES_TYPE int32_t -#define ALT_TYPE int32_t -#define ACCEL_TYPE int16_t -#endif - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata pres_t ao_sample_pres; -__pdata alt_t ao_sample_alt; -__pdata alt_t ao_sample_height; -#if HAS_ACCEL -__pdata accel_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_data; - -/* - * Sensor calibration values - */ - -__pdata pres_t ao_ground_pres; /* startup pressure */ -__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata accel_t ao_ground_accel; /* startup acceleration */ -__pdata accel_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - - -uint8_t -ao_sample(void) -{ - ao_config_get(); - ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); - ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); - while (ao_sample_data != ao_data_head) { - __xdata struct ao_data *ao_data; - - /* Capture a sample */ - ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; - ao_sample_tick = ao_data->tick; - - ao_data_pres_cook(ao_data); - ao_sample_pres = ao_data_pres(ao_data); - ao_sample_alt = pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; - -#if HAS_ACCEL - ao_sample_accel = ao_data_accel_cook(ao_data); - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = ao_data_accel_invert(ao_sample_accel); - ao_data_set_accel(ao_data, ao_sample_accel); -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_data = ao_data_ring_next(ao_sample_data); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_data = ao_data_head; - ao_preflight = TRUE; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6fc9324e..13e46c97 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -67,9 +67,9 @@ ALTOS_SRC = \ ao_convert_pa.c \ ao_log.c \ ao_log_mega.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_kalman.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fba2c19a..57586c95 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -36,8 +36,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight_mm.c \ - ao_sample_mm.c \ + ao_flight.c \ + ao_sample.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index f0ab2b14..23aed1c7 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -24,14 +24,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index a55bcf95..ca719bbf 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -31,7 +31,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 4631fb78..963f4131 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -4,7 +4,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall +CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall all: $(PROGS) @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h @@ -42,3 +42,6 @@ ao_kalman.h: $(KALMAN) ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm + +check: ao_fec_test ao_flight_test ao_flight_test_baro run-tests + ./ao_fec_test && ./run-tests \ No newline at end of file diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index baf2ad1d..9bb03d68 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -141,7 +141,7 @@ struct ao_task { int dummy; }; -#define ao_add_task(t,f,n) +#define ao_add_task(t,f,n) ((void) (t)) #define ao_log_start() #define ao_log_stop() @@ -156,6 +156,7 @@ int ao_flight_debug; FILE *emulator_in; char *emulator_app; char *emulator_name; +char *emulator_info; double emulator_error_max = 4; double emulator_height_error_max = 20; /* noise in the baro sensor */ @@ -199,6 +200,7 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) #define HAS_FLIGHT 1 +#define HAS_IGNITE 1 #define HAS_ADC 1 #define HAS_USB 1 #define HAS_GPS 1 @@ -223,8 +225,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample_mm.c" -#include "ao_flight_mm.c" +#include "ao_sample.c" +#include "ao_flight.c" #define to_double(f) ((f) / 65536.0) @@ -259,10 +261,11 @@ ao_test_exit(void) main_error = fabs(ao_test_main_height_time - main_time); landed_error = fabs(ao_test_landed_height - landed_height); landed_time_error = ao_test_landed_time - landed_time; - if (drogue_error > emulator_error_max || main_error > emulator_error_max || - landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { printf ("%s %s\n", emulator_app, emulator_name); + if (emulator_info) + printf ("\t%s\n", emulator_info); printf ("\tApogee error %g\n", drogue_error); printf ("\tMain error %g\n", main_error); printf ("\tLanded height error %g\n", landed_error); @@ -477,10 +480,9 @@ void ao_sleep(void *wchan) { if (wchan == &ao_data_head) { - char type; - uint16_t tick; - uint16_t a, b; - int ret; + char type = 0; + uint16_t tick = 0; + uint16_t a = 0, b = 0; uint8_t bytes[1024]; union ao_telemetry_all telem; char line[1024]; @@ -676,13 +678,15 @@ ao_dump_state(void) static const struct option options[] = { { .name = "summary", .has_arg = 0, .val = 's' }, { .name = "debug", .has_arg = 0, .val = 'd' }, + { .name = "info", .has_arg = 1, .val = 'i' }, { 0, 0, 0, 0}, }; -void run_flight_fixed(char *name, FILE *f, int summary) +void run_flight_fixed(char *name, FILE *f, int summary, char *info) { emulator_name = name; emulator_in = f; + emulator_info = info; ao_summary = summary; ao_flight_init(); ao_flight(); @@ -694,13 +698,14 @@ main (int argc, char **argv) int summary = 0; int c; int i; + char *info = NULL; #if HAS_ACCEL emulator_app="full"; #else emulator_app="baro"; #endif - while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "sdi:", options, NULL)) != -1) { switch (c) { case 's': summary = 1; @@ -708,11 +713,14 @@ main (int argc, char **argv) case 'd': ao_flight_debug = 1; break; + case 'i': + info = optarg; + break; } } if (optind == argc) - run_flight_fixed("", stdin, summary); + run_flight_fixed("", stdin, summary, info); else for (i = optind; i < argc; i++) { FILE *f = fopen(argv[i], "r"); @@ -720,7 +728,8 @@ main (int argc, char **argv) perror(argv[i]); continue; } - run_flight_fixed(argv[i], f, summary); + run_flight_fixed(argv[i], f, summary, info); fclose(f); } + exit(0); } -- cgit v1.2.3 From 6694cedd560a7ea9520ef11472c2770b489187c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:13:18 -0700 Subject: altos: Eliminate compiler warnings when building ao_flight_test We turn on a pile of warnings for that. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 4 +++- src/core/ao_kalman.c | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index a0affc48..39084fd0 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -48,7 +48,9 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ static __data uint16_t ao_interval_end; static __data int16_t ao_interval_min_height; static __data int16_t ao_interval_max_height; +#if HAS_ACCEL static __data int16_t ao_coast_avg_accel; +#endif __pdata uint8_t ao_flight_force_idle; @@ -350,7 +352,7 @@ ao_flight(void) ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; - case ao_flight_landed: + default: break; } } diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 68725f69..59ffd8b2 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -172,6 +172,7 @@ ao_kalman_err_accel(void) ao_error_a = (accel - ao_k_accel) >> 16; } +#ifndef FORCE_ACCEL static void ao_kalman_correct_both(void) { @@ -242,7 +243,8 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_100 * ao_error_a; } -#ifdef FORCE_ACCEL +#else + static void ao_kalman_correct_accel(void) { @@ -258,7 +260,8 @@ ao_kalman_correct_accel(void) ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; } -#endif + +#endif /* else FORCE_ACCEL */ #endif /* HAS_ACCEL */ void -- cgit v1.2.3 From b89d37d357273b97050c00d7fe12022e32799fa8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:13:55 -0700 Subject: altos: add some (unused) test code for different soft-decision sizes This lets us experiment with hard-decision and other possible soft_decision bit depths. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index b94b16dc..216a4b79 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -100,6 +100,7 @@ ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) { int i; int errors = 0; + int s; for (i = 0; i < in_len; i++) { double error = gaussian_random(0, dev); @@ -115,6 +116,24 @@ ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) else byte -= error; } + + /* abcd efgh 8 + * abcd efga 7 + * abcd efab 6 + * abcd eabc 5 + * abcd abcd 4 + * abca bcab 3 + * abab abab 2 + * aaaa aaaa 1 + */ + +#define SAVE 8 +#define SAVE_MASK (((1 << SAVE) - 1) << (8 - SAVE)) + + byte &= SAVE_MASK; + for (s = SAVE; s < 8; s += SAVE) + byte |= byte >> s; + out[i] = byte; } return errors; -- cgit v1.2.3 From a60c5a728530e4659a6750d8d5b87000735d4531 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:15:00 -0700 Subject: altos: Improve ao_flight_test a bit Add -i flag to include flight description Have run-tests know how many failures to expect Add run_baro to plot a single flight using the baro-only mode Signed-off-by: Keith Packard --- src/test/run-baro | 31 +++++++++++++++++++++++++++++++ src/test/run-tests | 17 +++++++++++------ src/test/test-flights | 14 +++++++------- 3 files changed, 49 insertions(+), 13 deletions(-) create mode 100755 src/test/run-baro diff --git a/src/test/run-baro b/src/test/run-baro new file mode 100755 index 00000000..21bab9fb --- /dev/null +++ b/src/test/run-baro @@ -0,0 +1,31 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test_baro "$i" > run-out.baro + +#./ao_flight_test_accel "$i" > run-out.accel +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.baro" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.baro" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.baro" using 1:9 with lines lt 3 axes x1y1 title "baro height",\ +"run-out.baro" using 1:11 with lines lt 4 axes x1y2 title "baro speed",\ +"run-out.baro" using 1:13 with lines lt 5 axes x1y2 title "baro accel",\ +"run-out.baro" using 1:17 with lines lt 6 axes x1y1 title "baro drogue",\ +"run-out.baro" using 1:19 with lines lt 7 axes x1y1 title "baro main" +pause mouse close +EOF +done \ No newline at end of file diff --git a/src/test/run-tests b/src/test/run-tests index a8a8dc3f..4edecf1a 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -2,21 +2,26 @@ DIR=~/misc/rockets/flights +expect_baro=2 +expect_full=5 + bad_baro=0 bad_full=0 while read flight description; do - if ./ao_flight_test_baro -s $DIR/$flight; then + if ./ao_flight_test_baro -s -i "$description" $DIR/$flight; then : else : $((bad_baro++)) fi - if ./ao_flight_test -s $DIR/$flight; then + if ./ao_flight_test -s -i "$description" $DIR/$flight; then : else : $((bad_full++)) fi done < test-flights -echo baro errors $bad_baro -echo full errors $bad_full -: $((bad = bad_baro + bad_full)) -exit $bad \ No newline at end of file +echo baro errors $bad_baro expected $expect_baro +echo full errors $bad_full expected $expect_full +: $((miss_baro = bad_baro > expect_baro ? bad_baro - expect_baro : expect_baro - bad_baro)) +: $((miss_full = bad_full > expect_full ? bad_full - expect_full : expect_full - bad_full)) +: $((miss = miss_baro + miss_full)) +exit $miss \ No newline at end of file diff --git a/src/test/test-flights b/src/test/test-flights index f6b3b992..12f62ea9 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -29,7 +29,7 @@ 2010-02-28-serial-052-flight-004.eeprom LDDD Tillamook airport, 2010-02-28, I161 2010-03-06-serial-010-flight-004.eeprom Robert's Lil Nuke at Hudson Ranch on a CTI 108G57CL Pro29 2010-03-06-serial-013-flight-003.eeprom Trick-O-Treat at Hudson Ranch on a J595BS -2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W +2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W (apogee early, fools ao_flight_test_baro) 2010-03-06-serial-053-flight-004.eeprom Horizon Rebuilt at Hudson Ranch on a J530IM with MAWD as backup 2010-05-08-serial-229-flight-002.eeprom First customer flight on a sparky. 2010-05-28-serial-215-flight-002.eeprom Mike's L1 cert flight. Congrats! @@ -38,28 +38,28 @@ 2010-05-30-serial-010-flight-005.eeprom Robert's Lil Nuke on a 84G88 Smoky Sam at Mile High Mayhem 2010 Version 0.1 TeleMetrum with 5010 GPS board. 2010-05-30-serial-051-flight-004.eeprom Bdale's G-Spot on a CTI 298H159 Green3 at Mile High Mayhem 2010 2010-05-30-serial-224-flight-003.eeprom Bill Mott's L3 cert flight -2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee +2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee (fools full) 2010-05-31-serial-010-flight-006.eeprom Robert's Lil Nuke with a v0.1 TeleMetrum and 5010 GPS board flying on a 159G118 Blue Streak on the last day of Mile High Mayhem 2010 2010-05-31-serial-216-flight-001.eeprom Sharp Stick in the Sky on an "I something" EX motor from James Russell -2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. +2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. (accel noise fools full) 2010-05-31-serial-227-flight-003.eeprom Mike's Rocket on J285 for successful L2 cert at MHM 2010-06-05-serial-220-flight-001.eeprom Mini-mmuchness on 159G54RL, Sunday at MHM 2010 2010-06-26-serial-209-flight-003.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch -2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch (accel noise fools full) 2010-06-26-serial-220-flight-002.eeprom Mini Mmuchness on CTI H120CL to 1975m, OROC June 2010 2010-06-26-serial-226-flight-002.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch 2010-06-27-serial-221-flight-002.eeprom PSAS LV2c on N2000 at OROC june launch 2010-07-17-serial-230-flight-001.eeprom Mike Ward's Level 1 cert flight on H225 2010-07-18-serial-219-flight-002.eeprom MMuchness on M1230 for successful L3 cert flight 2010-08-07-serial-216-flight-003.eeprom Sharp stick on I300T at Metra's august launch. Main out at apogee. -2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. -2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 +2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. (fools full) +2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 (early apogee charge fools baro) 2010-08-21-serial-010-flight-007.eeprom Robert's Lil Nuke, flying on a CTI Pro29 2-grain 110G250 Vmax. Just awesome! PFND. 2010-08-21-serial-224-flight-004.eeprom Anthony Towns' LDDD clone, successful L1 cert on a CTI Pro38 2-grain 266H125 classic. Airframe was set up for apogee-only with motor based ejection. The BP charge was larger than necessary, caused nose cone to snap back against aft airframe. Minor damage to leading edge of aft airframe, big chunk of the nose cone skin cracked away. Same problem Bdale saw on Sharp Stick's nosecone, also from Performance Rocketry, where there was apparently an air bubble below the gel coat. Determination was that damage was cosmetic and would not affect cert... confirmed by successful L2 later in the day! 2010-08-21-serial-224-flight-005.eeprom Anthony Towns' LDDD clone, successful L2 cert on a CTI Pro38 5-grain 58J357 blue streak. Perfect drogueless dual deploy! 0.8-0.9 grams aft charge and about 1.0 grams forward. Flew without ground testing charges due to time pressure before waiver closed for the day. About as close to the waiver as you'd ever want to be on a cert flight, again demonstrating that OpenRocket under-estimates apogee ... approximately 6800 ft predicted... 2010-08-21-serial-233-flight-002.eeprom Tim van Milligan's 5.5" L2 airframe, flying on a CTI Pro38 6-grain 774J410 red, TM indicated a problem with the apogee igniter continuity, noticed during countdown, turned out to be a loose wire! Perfect dual deploy flight once that was fixed. 2010-09-03-serial-051-flight-005.eeprom G-spot on an old Aerotech H125-20W single use 29mm motor. It appears the ejection at apogee actually happened much later, perhaps as much as 10 seconds late! -2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. +2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. (accel noise fools full) 2010-09-24-serial-236-flight-006.eeprom LDDD on I236 in Sheridan on 2010-09-24 to 1216m 2010-09-25-serial-223-flight-001.eeprom Bdale's 10" Goblin, flying on a CTI Pro75 M1300 Imax dual thrust during Chili Blaster 2 at Hudson Ranch. First flight after rebuild to do dual deploy from one bay with ARRD and 15' surplus "+ sign" parachute. 2010-10-17-serial-215-flight-006.eeprom Horizon Rebuild on CTI J595BS at Tripoli Colorado launch site near Hartsel, CO -- cgit v1.2.3 From aafa8859ecb27383f697b98f6991643b44f4721a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:32:31 -0700 Subject: altos: Save some memory. A few minor space savings in ao_cmd.c and ao_config.c. Don't build unused conversion functions ao_altitude_to_pres and ao_temp_to_dC Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 24 +++++++++++++----------- src/core/ao_config.c | 26 ++++++++++++++------------ src/core/ao_convert.c | 4 ++++ src/core/ao_convert_test.c | 5 +++-- src/test/ao_flight_test.c | 1 + 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fbf0c347..05dbfb51 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -36,10 +36,16 @@ put_string(__code char *s) putchar(c); } +static void +backspace(void) +{ + put_string ("\010 \010"); +} + static void readline(void) { - __pdata char c; + char c; if (ao_echo()) put_string("> "); cmd_len = 0; @@ -50,7 +56,7 @@ readline(void) if (c == '\010' || c == '\177') { if (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -60,7 +66,7 @@ readline(void) if (c == '\025') { while (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -76,11 +82,8 @@ readline(void) break; } - if (cmd_len >= CMD_LEN - 2) { - if (ao_echo()) - putchar('\007'); + if (cmd_len >= CMD_LEN - 2) continue; - } cmd_line[cmd_len++] = c; if (ao_echo()) putchar(c); @@ -271,13 +274,12 @@ help(void) __pdata uint8_t cmds; __pdata uint8_t cmd; __code struct ao_cmds * __pdata cs; + const char *h; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + for (cmd = 0; (h = cs[cmd].help); cmd++) + printf("%-45s %s\n", h, h + 1 + strlen(h)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index cc580d66..e0dabcd9 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,6 +78,8 @@ ao_config_set_radio(void) static void _ao_config_get(void) { + uint8_t minor; + if (ao_config_loaded) return; #if HAS_EEPROM @@ -97,37 +99,37 @@ _ao_config_get(void) ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - ao_config_dirty = 1; } - if (ao_config.minor != AO_CONFIG_MINOR) { + minor = ao_config.minor; + if (minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ - if (ao_config.minor < 1) + if (minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; /* Fixups for minor version 2 */ - if (ao_config.minor < 2) { + if (minor < 2) { ao_config.accel_plus_g = 0; ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ #if HAS_RADIO - if (ao_config.minor < 3) + if (minor < 3) ao_config.radio_cal = ao_radio_cal; #endif /* Fixups for minor version 4 */ - if (ao_config.minor < 4) + if (minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; /* Fixupes for minor version 5 */ - if (ao_config.minor < 5) + if (minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - if (ao_config.minor < 6) + if (minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 8) + if (minor < 8) ao_config.radio_enable = TRUE; - if (ao_config.minor < 9) + if (minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); - if (ao_config.minor < 10) + if (minor < 10) ao_config.frequency = 434550; - if (ao_config.minor < 11) + if (minor < 11) ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c index 0969f107..aa9b5f48 100644 --- a/src/core/ao_convert.c +++ b/src/core/ao_convert.c @@ -41,6 +41,7 @@ ao_pres_to_altitude(int16_t pres) __reentrant (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } +#if AO_NEED_ALTITUDE_TO_PRES int16_t ao_altitude_to_pres(int16_t alt) __reentrant { @@ -66,7 +67,9 @@ ao_altitude_to_pres(int16_t alt) __reentrant pres = 0; return (int16_t) pres; } +#endif +#if 0 int16_t ao_temp_to_dC(int16_t temp) __reentrant { @@ -83,3 +86,4 @@ ao_temp_to_dC(int16_t temp) __reentrant ret = ((temp - 19791) * 1012L) >> 16; return ret; } +#endif diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c index e2c28b73..87e76841 100644 --- a/src/core/ao_convert_test.c +++ b/src/core/ao_convert_test.c @@ -17,14 +17,15 @@ #include #define AO_CONVERT_TEST +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_host.h" #include "ao_convert.c" #define STEP 1 -static inline i_abs(int i) { return i < 0 ? -i : i; } +static inline int i_abs(int i) { return i < 0 ? -i : i; } -main () +int main (int argc, char **argv) { int i; int16_t p_to_a, p_to_a_to_p; diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 9bb03d68..a4ef8dc0 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -180,6 +180,7 @@ struct ao_cmds { #define ao_xmemset(d,v,c) memset(d,v,c) #define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_convert.c" struct ao_config { -- cgit v1.2.3 From bca72b782a2909ecedef15ad589292647221ca56 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:34:02 -0700 Subject: altos: Add 'void' parameter to ao_fec_decode callback parameter This keeps the compiler from whinging about the lack of a prototype. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_fec_rx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 771732bd..eedea8f4 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -73,7 +73,7 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 64426d72..072a9e90 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -96,7 +96,7 @@ ao_next_state(uint8_t state, uint8_t bit) */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)) { static uint32_t cost[2][NUM_STATE]; /* path cost */ static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ -- cgit v1.2.3 From fb60d87b02c0fc83a0b4268212f0b6b740c984e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:35:19 -0700 Subject: altos: Signal continuity over radio in pad mode (trac #40) This is especially useful for telemini which has no beeper, allowing you to hear the continuity signal while at the pad over the air. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 89 ++++++++++++++++++++++++++++++++++++++++--------- src/core/ao.h | 25 ++++++++++++-- src/core/ao_report.c | 10 ++++-- src/core/ao_telemetry.c | 14 +++++--- src/drivers/ao_cc1120.c | 69 +++++++++++++++++++++++++++++--------- 5 files changed, 167 insertions(+), 40 deletions(-) diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2c4a661e..2071c47a 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -200,7 +200,7 @@ static __code uint8_t rdf_setup[] = { RF_MDMCFG3_OFF, (RDF_DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT), RF_MDMCFG2_OFF, (RF_MDMCFG2_DEM_DCFILT_OFF | RF_MDMCFG2_MOD_FORMAT_GFSK | - RF_MDMCFG2_SYNC_MODE_15_16_THRES), + RF_MDMCFG2_SYNC_MODE_NONE), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | RF_MDMCFG1_NUM_PREAMBLE_2 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -366,29 +366,22 @@ ao_radio_recv_abort(void) ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_value = 0x55; +__code ao_radio_rdf_value = 0x55; -void -ao_radio_rdf(uint8_t pkt_len) +static void +ao_radio_rdf_start(void) { uint8_t i; - ao_radio_abort = 0; - ao_radio_get(pkt_len); + ao_radio_get(AO_RADIO_RDF_LEN); ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; +} - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); +static void +ao_radio_rdf_run(void) +{ ao_dma_start(ao_radio_dma); RFST = RFST_STX; __critical while (!ao_radio_done && !ao_radio_abort) @@ -401,6 +394,70 @@ ao_radio_rdf(uint8_t pkt_len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_radio_rdf_start(); + + ao_dma_set_transfer(ao_radio_dma, + CODE_TO_XDATA(&ao_radio_rdf_value), + &RFDXADDR, + AO_RADIO_RDF_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + +#define PA 0x00 +#define BE 0x55 + +#define CONT_PAUSE_8 PA, PA, PA, PA, PA, PA, PA, PA +#define CONT_PAUSE_16 CONT_PAUSE_8, CONT_PAUSE_8 +#define CONT_PAUSE_24 CONT_PAUSE_16, CONT_PAUSE_8 + +#define CONT_BEEP_8 BE, BE, BE, BE, BE, BE, BE, BE + +#if AO_RADIO_CONT_PAUSE_LEN == 24 +#define CONT_PAUSE CONT_PAUSE_24 +#endif + +#if AO_RADIO_CONT_TONE_LEN == 8 +#define CONT_BEEP CONT_BEEP_8 +#define CONT_PAUSE_SHORT CONT_PAUSE_8 +#endif + +#define CONT_ADDR(c) CODE_TO_XDATA(&ao_radio_cont[(3-(c)) * (AO_RADIO_CONT_PAUSE_LEN + AO_RADIO_CONT_TONE_LEN)]) + +__code uint8_t ao_radio_cont[] = { + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, +}; + +void +ao_radio_continuity(uint8_t c) +{ + ao_radio_rdf_start(); + ao_dma_set_transfer(ao_radio_dma, + CONT_ADDR(c), + &RFDXADDR, + AO_RADIO_CONT_TOTAL_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + void ao_radio_rdf_abort(void) { diff --git a/src/core/ao.h b/src/core/ao.h index 861a0fd4..2e012f08 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -264,6 +264,26 @@ ao_cmd_filter(void); * ao_report.c */ +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 +#define AO_RDF_CONTINUITY_MS 32 +#define AO_RDF_CONTINUITY_PAUSE 96 +#define AO_RDF_CONTINUITY_TOTAL ((AO_RDF_CONTINUITY_PAUSE + AO_RDF_CONTINUITY_MS) * 3 + AO_RDF_CONTINUITY_PAUSE) + +/* This assumes that we're generating a 1kHz tone, which + * modulates the carrier at 2kbps, or 250kBps + */ +#define AO_MS_TO_RDF_LEN(ms) ((ms) / 4) + +#define AO_RADIO_RDF_LEN AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS) +#define AO_RADIO_CONT_TONE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_MS) +#define AO_RADIO_CONT_PAUSE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_PAUSE) +#define AO_RADIO_CONT_TOTAL_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_TOTAL) + +/* returns a value 0-3 to indicate igniter continuity */ +uint8_t +ao_report_igniter(void); + void ao_report_init(void); @@ -538,10 +558,11 @@ ao_radio_recv_abort(void); * 2 * ms bits, or ms / 4 bytes */ -#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) +void +ao_radio_rdf(void); void -ao_radio_rdf(uint8_t pkt_len); +ao_radio_continuity(uint8_t c); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_report.c b/src/core/ao_report.c index eb90a4f8..1104cd82 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -114,6 +114,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; } +uint8_t +ao_report_igniter(void) +{ + return (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); +} + static void ao_report_continuity(void) __reentrant { @@ -123,8 +130,7 @@ ao_report_continuity(void) __reentrant if (!ao_igniter_present) return; #endif - c = (ao_report_igniter_ready(ao_igniter_drogue) | - (ao_report_igniter_ready(ao_igniter_main) << 1)); + c = ao_report_igniter(); if (c) { while (c--) { high(AO_MS_TO_TICKS(25)); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 3c747520..583a6636 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -22,9 +22,6 @@ static __pdata uint16_t ao_telemetry_interval; static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - #if defined(MEGAMETRUM) #define AO_SEND_MEGA 1 #endif @@ -317,8 +314,16 @@ ao_telemetry(void) if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { +#if HAS_IGNITE_REPORT + uint8_t c; +#endif ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); +#if HAS_IGNITE_REPORT + if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter())) + ao_radio_continuity(c); + else +#endif + ao_radio_rdf(); } #endif time += ao_telemetry_interval; @@ -330,6 +335,7 @@ ao_telemetry(void) } else time = ao_time(); + bottom: ; } } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 1d28148b..a36d922c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -160,7 +160,7 @@ ao_radio_fifo_read(uint8_t *data, uint8_t len) } static uint8_t -ao_radio_fifo_write(uint8_t *data, uint8_t len) +ao_radio_fifo_write_start(void) { uint8_t addr = ((0 << CC1120_READ) | (1 << CC1120_BURST) | @@ -169,24 +169,28 @@ ao_radio_fifo_write(uint8_t *data, uint8_t len) ao_radio_select(); ao_radio_duplex(&addr, &status, 1); - ao_radio_spi_send(data, len); + return status; +} + +static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { ao_radio_deselect(); return status; } static uint8_t -ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +ao_radio_fifo_write(uint8_t *data, uint8_t len) { - uint8_t addr = ((0 << CC1120_READ) | - (1 << CC1120_BURST) | - CC1120_FIFO); - uint8_t status; + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send(data, len); + return ao_radio_fifo_write_stop(status); +} - ao_radio_select(); - ao_radio_duplex(&addr, &status, 1); +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); ao_radio_spi_send_fixed(data, len); - ao_radio_deselect(); - return status; + return ao_radio_fifo_write_stop(status); } static uint8_t @@ -446,19 +450,20 @@ ao_radio_get(uint8_t len) #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -void -ao_radio_rdf(uint8_t len) +static void +ao_rdf_start(uint8_t len) { - int i; - ao_radio_abort = 0; ao_radio_get(len); ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); +} +static void +ao_rdf_run(void) +{ ao_radio_start_tx(); cli(); @@ -470,6 +475,38 @@ ao_radio_rdf(uint8_t len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_rdf_start(AO_RADIO_RDF_LEN); + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + + ao_rdf_run(); +} + +void +ao_radio_continuity(uint8_t c) +{ + uint8_t i; + uint8_t status; + + ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + + status = ao_radio_fifo_write_start(); + for (i = 0; i < 3; i++) { + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + if (i < c) + ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + else + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + } + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + status = ao_radio_fifo_write_stop(status); + (void) status; + ao_rdf_run(); +} + void ao_radio_rdf_abort(void) { -- cgit v1.2.3 From 0b92164143aaf0d2aa3d5d742484391c16545289 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:08:28 -0700 Subject: altos: Set HAS_FLIGHT_DEBUG=1 to include the flight debugging commands This leaves USB enabled, and adds the 'F' command to dump internal flight state. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 39084fd0..c6786455 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -114,7 +114,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG /* Disable the USB controller in flight mode * to save power */ @@ -358,7 +358,7 @@ ao_flight(void) } } -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG static inline int int_part(int16_t i) { return i >> 4; } static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } @@ -378,6 +378,7 @@ ao_flight_dump(void) printf (" raw accel %d\n", ao_sample_accel); #endif printf (" ground pres %d\n", ao_ground_pres); + printf (" ground alt %d\n", ao_ground_height); #if HAS_ACCEL printf (" raw accel %d\n", ao_sample_accel); printf (" groundaccel %d\n", ao_ground_accel); @@ -413,7 +414,7 @@ void ao_flight_init(void) { ao_flight_state = ao_flight_startup; -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG ao_cmd_register(&ao_flight_cmds[0]); #endif ao_add_task(&flight_task, ao_flight, "flight"); -- cgit v1.2.3 From aa305da7e5dc182c99c09e422c053d85ed48d5d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:09:44 -0700 Subject: altos: Continuously update ground state while on pad (trac #42) Average data for 5 seconds, wait 5 seconds and if still in pad mode, replace the existing data with the new data. This should avoid averaging in boost data while still keeping things reasonably current. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 58 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index ac11eef0..6461def0 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -61,6 +61,29 @@ __pdata int32_t ao_sample_pres_sum; __pdata int32_t ao_sample_accel_sum; #endif +static void +ao_sample_preflight_add(void) +{ +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; +} + +static void +ao_sample_preflight_set(void) +{ +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_sample_accel_sum = 0; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + nsamples = 0; + ao_sample_pres_sum = 0; +} + static void ao_sample_preflight(void) { @@ -70,29 +93,38 @@ ao_sample_preflight(void) * data and average them to find the resting values */ if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; + ao_sample_preflight_add(); } else { - ao_config_get(); #if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_sample_preflight_set(); ao_preflight = FALSE; } } +/* + * While in pad mode, constantly update the ground state by + * re-averaging the data. This tracks changes in orientation, which + * might be caused by adjustments to the rocket on the pad and + * pressure, which might be caused by changes in the weather. + */ + +static void +ao_sample_preflight_update(void) +{ + if (nsamples < 512) + ao_sample_preflight_add(); + else if (nsamples < 1024) + ++nsamples; + else + ao_sample_preflight_set(); +} uint8_t ao_sample(void) { - ao_config_get(); ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); while (ao_sample_data != ao_data_head) { @@ -116,8 +148,11 @@ ao_sample(void) if (ao_preflight) ao_sample_preflight(); - else + else { + if (ao_flight_state < ao_flight_boost) + ao_sample_preflight_update(); ao_kalman(); + } ao_sample_data = ao_data_ring_next(ao_sample_data); } return !ao_preflight; @@ -126,6 +161,7 @@ ao_sample(void) void ao_sample_init(void) { + ao_config_get(); nsamples = 0; ao_sample_pres_sum = 0; ao_sample_pres = 0; -- cgit v1.2.3 From 46407f7f3e4d2b6e74b3a2e90b38736a792cfc54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:41:59 -0700 Subject: altos: Force 434.550Mhz by connecting debug gnd and clk (trac #41) Check for pin P2_2 low at startup and set the frequency to 434.550MHz. This value won't get written to flash, so rebooting again will restore the configured frequency. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao.h | 7 +++++++ src/core/ao_config.c | 4 ++++ src/product/ao_telemini.c | 13 +++++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index e28a7b65..fc6ed3ec 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -163,6 +163,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 + #define HAS_FORCE_FREQ 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 diff --git a/src/core/ao.h b/src/core/ao.h index 2e012f08..06daf48f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -682,6 +682,13 @@ ao_igniter_init(void); * ao_config.c */ +#if HAS_FORCE_FREQ +/* + * Set this to force the frequency to 434.550MHz + */ +extern __xdata uint8_t ao_force_freq; +#endif + #define AO_CONFIG_MAJOR 1 #define AO_CONFIG_MINOR 11 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e0dabcd9..ced8b1f2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -135,6 +135,10 @@ _ao_config_get(void) ao_config_dirty = 1; } #if HAS_RADIO +#if HAS_FORCE_FREQ + if (ao_force_freq) + ao_config.frequency = 434550; +#endif ao_config_set_radio(); #endif ao_config_loaded = 1; diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c index fa23de01..21551ee9 100644 --- a/src/product/ao_telemini.c +++ b/src/product/ao_telemini.c @@ -18,6 +18,8 @@ #include "ao.h" #include "ao_pins.h" +__xdata uint8_t ao_force_freq; + void main(void) { @@ -33,6 +35,17 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); + /* A hack -- look at the debug clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P2_2 == 0) { + ao_flight_force_idle = 1; + ao_force_freq = 1; + while (P2_2 == 0) + ; + } + ao_timer_init(); ao_adc_init(); ao_cmd_init(); -- cgit v1.2.3 From 675ccd41e3b668cd4e1d2dd282dd317a00d00151 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 00:35:21 -0700 Subject: Get AltOS version numbers into Mac 'about' dialog Generate Info.plist from Info.plist.in to correctly set the VERSION information. This also changes some strings around to make them look better Signed-off-by: Keith Packard --- altosui/AltosUI.app/Contents/Info.plist | 44 ------------------------------- altosui/Info.plist.in | 46 +++++++++++++++++++++++++++++++++ altosui/Makefile.am | 4 ++- configure.ac | 1 + 4 files changed, 50 insertions(+), 45 deletions(-) delete mode 100644 altosui/AltosUI.app/Contents/Info.plist create mode 100644 altosui/Info.plist.in diff --git a/altosui/AltosUI.app/Contents/Info.plist b/altosui/AltosUI.app/Contents/Info.plist deleted file mode 100644 index 60842804..00000000 --- a/altosui/AltosUI.app/Contents/Info.plist +++ /dev/null @@ -1,44 +0,0 @@ - - - - - CFBundleName - altosui - CFBundleVersion - 100.0 - CFBundleAllowMixedLocalizations - true - CFBundleExecutable - JavaApplicationStub - CFBundleDevelopmentRegion - English - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleGetInfoString - AltOS UI version 0.7 - CFBundleInfoDictionaryVersion - 6.0 - CFBundleIconFile - AltosUIIcon.icns - Java - - MainClass - altosui.AltosUI - JVMVersion - 1.5+ - ClassPath - - $JAVAROOT/altosui.jar - $JAVAROOT/freetts.jar - - VMOptions - - -Xms512M - -Xmx512M - -Dosgi.clean=true - - - - diff --git a/altosui/Info.plist.in b/altosui/Info.plist.in new file mode 100644 index 00000000..46dea171 --- /dev/null +++ b/altosui/Info.plist.in @@ -0,0 +1,46 @@ + + + + + CFBundleName + AltosUI + CFBundleVersion + @VERSION@ + CFBundleAllowMixedLocalizations + true + CFBundleExecutable + JavaApplicationStub + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleIdentifier + org.altusmetrum.altosui + CFBundleSignature + Altu + CFBundleGetInfoString + AltOS UI version @VERSION@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleIconFile + AltosUIIcon.icns + Java + + MainClass + altosui.AltosUI + JVMVersion + 1.5+ + ClassPath + + $JAVAROOT/altosui.jar + $JAVAROOT/freetts.jar + + VMOptions + + -Xms512M + -Xmx512M + -Dosgi.clean=true + + + + diff --git a/altosui/Makefile.am b/altosui/Makefile.am index feda00c7..b22405aa 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -165,7 +165,8 @@ FAT_FILES=$(FATJAR) $(ALTOSLIB_CLASS) $(FREETTS_CLASS) $(JFREECHART_CLASS) $(JCO LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) $(DOC) LINUX_EXTRA=altosui-fat -MACOSX_FILES=$(FAT_FILES) libaltos.dylib +MACOSX_INFO_PLIST=Info.plist +MACOSX_FILES=$(FAT_FILES) libaltos.dylib $(MACOSX_INFO_PLIST) MACOSX_EXTRA=$(FIRMWARE) WINDOWS_FILES=$(FAT_FILES) altos.dll altos64.dll $(top_srcdir)/telemetrum.inf $(WINDOWS_ICON) @@ -311,6 +312,7 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) -rm -rf macosx mkdir macosx cp -a AltosUI.app macosx/ + cp -p Info.plist macosx/AltosUI.app/Contents mkdir -p macosx/AltOS macosx/AltosUI.app/Contents/Resources/Java cp -p $(FATJAR) macosx/AltosUI.app/Contents/Resources/Java/altosui.jar cp -p libaltos.dylib macosx/AltosUI.app/Contents/Resources/Java diff --git a/configure.ac b/configure.ac index a3004811..e78f5873 100644 --- a/configure.ac +++ b/configure.ac @@ -141,6 +141,7 @@ Makefile altoslib/Makefile altosui/Makefile altosui/AltosVersion.java +altosui/Info.plist altosui/libaltos/Makefile altosdroid/Makefile altosdroid/local.properties -- cgit v1.2.3 From cc5d106f014f714a9a2d5f595a2de0da8f7da80a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:40:07 -0700 Subject: altos: Ignore megametrum built files Signed-off-by: Keith Packard --- src/megametrum-v0.1/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/megametrum-v0.1/.gitignore diff --git a/src/megametrum-v0.1/.gitignore b/src/megametrum-v0.1/.gitignore new file mode 100644 index 00000000..b04d3950 --- /dev/null +++ b/src/megametrum-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +megametrum-*.elf -- cgit v1.2.3 From 7be98836e69a222b2f9f4baacddcf12d168e2207 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:40:54 -0700 Subject: Add megametrum outline to doc dir And install it alongside telemetrum-outline Signed-off-by: Keith Packard --- altosui/Makefile.am | 2 +- altosui/altos-windows.nsi | 1 + debian/docs | 1 + doc/megametrum-outline.pdf | Bin 0 -> 4349 bytes doc/megametrum-outline.svg | 244 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 doc/megametrum-outline.pdf create mode 100644 doc/megametrum-outline.svg diff --git a/altosui/Makefile.am b/altosui/Makefile.am index b22405aa..1c8ea491 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -151,7 +151,7 @@ FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TELEMINI) $(FIRMWARE_TD) ALTUSMETRUM_DOC=$(top_srcdir)/doc/altusmetrum.pdf ALTOS_DOC=$(top_srcdir)/doc/altos.pdf TELEMETRY_DOC=$(top_srcdir)/doc/telemetry.pdf -TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf +TEMPLATE_DOC=$(top_srcdir)/doc/telemetrum-outline.pdf $(top_srcdir)/doc/megametrum-outline.pdf DOC=$(ALTUSMETRUM_DOC) $(ALTOS_DOC) $(TELEMETRY_DOC) $(TEMPLATE_DOC) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index e5e01d79..92c985a9 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -126,6 +126,7 @@ Section "Documentation" File "../doc/altos.pdf" File "../doc/telemetry.pdf" File "../doc/telemetrum-outline.pdf" + File "../doc/megametrum-outline.pdf" SectionEnd Section "Uninstaller" diff --git a/debian/docs b/debian/docs index 6652abf7..3ac75ad4 100644 --- a/debian/docs +++ b/debian/docs @@ -7,3 +7,4 @@ doc/telemetry.pdf doc/altos.html doc/altos.pdf doc/telemetrum-outline.pdf +doc/megametrum-outline.pdf diff --git a/doc/megametrum-outline.pdf b/doc/megametrum-outline.pdf new file mode 100644 index 00000000..f8fc26e2 Binary files /dev/null and b/doc/megametrum-outline.pdf differ diff --git a/doc/megametrum-outline.svg b/doc/megametrum-outline.svg new file mode 100644 index 00000000..e8d74d38 --- /dev/null +++ b/doc/megametrum-outline.svg @@ -0,0 +1,244 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UP + + -- cgit v1.2.3 From 726f47c8a07f060aed930e1d102a1e8b5a5c7aed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:47:25 -0700 Subject: altos: remove optimization for 'help' that confuses cc1111 compiler The cc1111 compiler gets this very wrong and prints piles of garbage Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 05dbfb51..1814cecf 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -278,8 +278,10 @@ help(void) for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; (h = cs[cmd].help); cmd++) + for (cmd = 0; cs[cmd].func; cmd++) { + h = cs[cmd].help; printf("%-45s %s\n", h, h + 1 + strlen(h)); + } } } -- cgit v1.2.3 From 18431c88c8a6cb267922b97192e8b7ddb88d0e7e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:49:26 -0700 Subject: altos: Have 'make clean' remove all programs, even old ones This makes sure that changing version numbers doesn't leave old compiled output lying around. Signed-off-by: Keith Packard --- src/cc1111/Makefile.cc1111 | 8 ++++++++ src/megametrum-v0.1/Makefile | 5 +++-- src/product/Makefile.telebt | 13 +++++-------- src/product/Makefile.teledongle | 9 +++------ src/product/Makefile.telelaunch | 9 +++------ src/product/Makefile.telemetrum | 9 +++------ src/product/Makefile.telemini | 9 +++------ src/product/Makefile.telenano | 9 +++------ src/stm-demo/Makefile | 2 +- src/teleballoon-v1.1/Makefile | 13 +++++-------- src/telescience-v0.1/Makefile | 2 +- src/teleshield-v0.1/Makefile | 9 +++------ src/teleterra-v0.2/Makefile | 9 +++------ src/test/Makefile | 2 +- src/tidongle/Makefile | 9 +++------ 15 files changed, 48 insertions(+), 69 deletions(-) diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index 8de4a9b2..f7ecce33 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -25,3 +25,11 @@ PAOM=$(PROG:.ihx=) %.rel : %.c $(INC) $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< + +all: + +clean-cc1111: + rm -f *.adb *.asm *.lnk *.lst *.rel *.rst *.sym + rm -f $(PROGNAME)-* + rm -f ao_product.h + rm -f ../$(PROGNAME)-* diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 13e46c97..59cfb64d 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -82,7 +82,8 @@ IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g -PROG=megametrum-v0.1-$(VERSION).elf +PROGNAME=megametrum-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) @@ -103,7 +104,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 90525d63..fd52cec4 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -60,7 +60,8 @@ SRC = \ $(PRODUCT_SRC) \ $(TELEBT_SRC) -PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx +PROGNAME = telebt-v$(TELEBT_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleBT-v$(TELEBT_VER) PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF) IDPRODUCT=0x000e @@ -78,9 +79,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ @@ -89,11 +90,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index fbf14a04..5105b567 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -60,7 +60,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teledongle-v$(TD_VER)-$(VERSION).ihx +PROGNAME = teledongle-v$(TD_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleDongle-v$(TD_VER) PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF) IDPRODUCT=0x000c @@ -89,11 +90,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 3753f3c9..1e55989c 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -62,7 +62,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx +PROGNAME = telelaunch-v$(TELELAUNCH_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) IDPRODUCT=0x000f @@ -92,11 +93,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 57586c95..5e3eed7f 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -75,7 +75,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemetrum-v$(TM_VER)-$(VERSION)$(TM_EXTRA).ihx +PROGNAME = telemetrum-v$(TM_VER)$(TM_EXTRA) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleMetrum-v$(TM_VER) PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) IDPRODUCT=0x000b @@ -104,11 +105,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 23aed1c7..ef8906ba 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -63,7 +63,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx +PROGNAME = telemini-v$(TELEMINI_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleMini-v$(TELEMINI_VER) PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) IDPRODUCT=0x000a @@ -93,11 +94,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index ca719bbf..67410ae0 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -62,7 +62,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx +PROGNAME = telenano-v$(TELENANO_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleNano-v$(TELENANO_VER) PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF) IDPRODUCT=0x000a @@ -92,11 +93,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index dd7e6e02..055a73af 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -61,7 +61,7 @@ $(OBJ): $(INC) distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROG) rm -f ao_product.h install: diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile index fb88787b..2eea996e 100644 --- a/src/teleballoon-v1.1/Makefile +++ b/src/teleballoon-v1.1/Makefile @@ -81,7 +81,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teleballoon-v$(TELEBALLOON_VER)-$(VERSION).ihx +PROGNAME = teleballoon-v$(TELEBALLOON_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleBalloon-v$(TELEBALLOON_VER) PRODUCT_DEF=-DTELEBALLOON_V_$(TELEBALLOON_DEF) IDPRODUCT=0x000b @@ -99,9 +100,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ @@ -110,11 +111,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 10e4a2a3..d24128ef 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -105,7 +105,7 @@ ao_product.o: ao_product.c ao_product.h distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROG) $(PROG).hex rm -f ao_product.h install: diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index c1f45f37..ab2a025f 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -72,7 +72,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teleshield-v$(TELESHIELD_VER)-$(VERSION).ihx +PROGNAME = teleshield-v$(TELESHIELD_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleShield-v$(TELESHIELD_VER) PRODUCT_DEF=-DTELESHIELD_V_$(TELESHIELD_DEF) IDPRODUCT=0x0013 @@ -102,11 +103,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 4967d187..65db57ce 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -66,7 +66,8 @@ SRC = \ TELETERRA_VER=0.2 TELETERRA_DEF=0_2 -PROG = teleterra-v$(TELETERRA_VER)-$(VERSION).ihx +PROGNAME = teleterra-v$(TELETERRA_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleTerra-v$(TELETERRA_VER) PRODUCT_DEF=-DTELETERRA_V_$(TELETERRA_DEF) IDPRODUCT=0x000d @@ -95,11 +96,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/test/Makefile b/src/test/Makefile index 963f4131..db3cc04b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -9,7 +9,7 @@ CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall all: $(PROGS) clean: - rm -f $(PROGS) + rm -f $(PROGS) run-out.baro run-out.full install: diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 0bb2ce32..1514c4df 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -53,7 +53,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = tidongle-$(VERSION).ihx +PROGNAME = tidongle +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TIDongle PRODUCT_DEF=-DTIDONGLE IDPRODUCT=0x000a @@ -82,11 +83,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: -- cgit v1.2.3 From fe70611c3c7d4b8cce3b5292f0ec549f3191bf86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:50:56 -0700 Subject: altos: Create macros to convert from/to radio RSSI representation AO_RSSI_FROM_RADIO and AO_RADIO_FROM_RSSI. Removes a bunch of open-coded versions of the same function. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/core/ao_monitor.c | 5 ++--- src/drivers/ao_cc1120.c | 4 ++-- src/product/ao_terraui.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/core/ao.h b/src/core/ao.h index 06daf48f..eb2d47cf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -487,6 +487,12 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method + * for reporting RSSI. So, now we use these values everywhere + */ +#define AO_RSSI_FROM_RADIO(radio) ((int16_t) ((int8_t) (radio) >> 1) - 74) +#define AO_RADIO_FROM_RSSI(rssi) (((int8_t) (rssi) + 74) << 1) + /* * ao_radio_recv tacks on rssi and status bytes */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 51d61425..d492e32a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -141,8 +141,7 @@ ao_monitor_put(void) case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + rssi = (int16_t) AO_RSSI_FROM_RADIO(recv_orig.rssi); ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; @@ -240,7 +239,7 @@ ao_monitor_put(void) putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { - rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]); ao_rssi_set(rssi); } #endif diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index a36d922c..569df3b7 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -729,7 +729,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Convert from 'real' rssi to cc1111-style values */ - rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1)); ao_radio_put(); @@ -998,7 +998,7 @@ ao_radio_test_recv() printf ("CRC OK"); else printf ("CRC BAD"); - printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); for (b = 0; b < 32; b++) printf (" %02x", bytes[b]); printf ("\n"); diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 963c7be4..1866eb0c 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -594,7 +594,7 @@ ao_terramonitor(void) continue; if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) continue; - ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + ao_tel_rssi = AO_RSSI_FROM_RADIO(ao_monitor_ring[monitor].all.rssi); switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: -- cgit v1.2.3 From cf44ea354c2d1780cee343132c6058e11e9eefa3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:52:32 -0700 Subject: altos: Fix gcc compiler warnings in GPS code unused variables and mis-matches in printf format codes. Signed-off-by: Keith Packard --- src/core/ao_gps_print.c | 4 ++-- src/drivers/ao_gps_skytraq.c | 2 +- src/test/ao_gps_test.c | 7 ++++++- src/test/ao_gps_test_skytraq.c | 12 +++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c index fcdedd30..47c945d7 100644 --- a/src/core/ao_gps_print.c +++ b/src/core/ao_gps_print.c @@ -40,8 +40,8 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant printf(AO_TELEM_GPS_LATITUDE " %ld " AO_TELEM_GPS_LONGITUDE " %ld " AO_TELEM_GPS_ALTITUDE " %d ", - gps_data->latitude, - gps_data->longitude, + (long) gps_data->latitude, + (long) gps_data->longitude, gps_data->altitude); if (gps_data->flags & AO_GPS_DATE_VALID) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 84616a05..d80da97c 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -480,7 +480,7 @@ gps_dump(void) __reentrant ao_mutex_get(&ao_gps_mutex); printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); printf ("Flags: 0x%x\n", ao_gps_data.flags); printf ("Sats: %d", ao_gps_tracking_data.channels); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 4d4012df..d75a12ec 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -220,6 +221,8 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -257,6 +260,7 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -368,10 +372,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 88bed305..846daa94 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -22,6 +22,7 @@ #include #include #include +#include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -87,6 +88,7 @@ ao_mutex_put(uint8_t *mutex) static int ao_gps_fd; +#if 0 static void ao_dbg_char(char c) { @@ -102,6 +104,7 @@ ao_dbg_char(char c) } write(1, line, strlen(line)); } +#endif #define QUEUE_LEN 4096 @@ -222,6 +225,8 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -259,6 +264,7 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -371,10 +377,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } @@ -422,8 +429,6 @@ ao_serial1_set_speed(uint8_t speed) void ao_dump_state(void *wchan) { - double lat, lon; - int i; if (wchan == &ao_gps_data) ao_gps_print(&ao_gps_data); else @@ -487,4 +492,5 @@ main (int argc, char **argv) exit (1); } ao_gps(); + return 0; } -- cgit v1.2.3 From 846a6298e4a8bfbe87bb24d7b0802c0bf6f233be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:53:30 -0700 Subject: Report RSSI values in monitor idle UI (trac #44) This adds a new 's' command to TeleDongle to report RSSI value from last received packet, and then has AltosUI request that value when closing the remote link. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 46 ++++++++++++++++++++++++++++------------- src/core/ao_packet.h | 2 ++ src/drivers/ao_packet.c | 11 ++++++---- src/drivers/ao_packet_master.c | 7 ++++++- 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 949e3926..eb6ec5e7 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -178,8 +178,23 @@ class AltosIdleMonitor extends Thread { AltosADC adc; AltosGPS gps; + int AltosRSSI() throws TimeoutException, InterruptedException { + serial.printf("s\n"); + String line = serial.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + void update_state() throws InterruptedException, TimeoutException { - AltosRecord record = new AltosRecord(); + AltosRecordTM record = new AltosRecordTM(); + int rssi; try { if (remote) { @@ -191,31 +206,34 @@ class AltosIdleMonitor extends Thread { adc = new AltosADC(serial); gps = new AltosGPSQuery(serial, config_data); } finally { - if (remote) + if (remote) { serial.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; } record.version = 0; record.callsign = config_data.callsign; record.serial = config_data.serial; record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = 0; + record.rssi = rssi; record.status = 0; record.state = Altos.ao_flight_idle; record.tick = adc.tick; -// record.accel = adc.accel; -// record.pres = adc.pres; -// record.batt = adc.batt; -// record.temp = adc.temp; -// record.drogue = adc.drogue; -// record.main = adc.main; - -// record.ground_accel = record.accel; -// record.ground_pres = record.pres; -// record.accel_plus_g = config_data.accel_cal_plus; -// record.accel_minus_g = config_data.accel_cal_minus; + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; record.acceleration = 0; record.speed = 0; record.height = 0; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 618ccda4..f232a878 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -67,6 +67,8 @@ ao_packet_pollchar(void) __critical; #if PACKET_HAS_MASTER /* ao_packet_master.c */ +extern __xdata uint8_t ao_packet_last_rssi; + void ao_packet_master_init(void); #endif diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index e020c003..d813b25f 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -27,7 +27,11 @@ static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; __xdata uint8_t ao_packet_enable; + +#if PACKET_HAS_MASTER __xdata uint8_t ao_packet_master_sleeping; +__xdata uint8_t ao_packet_last_rssi; +#endif void ao_packet_send(void) @@ -80,6 +84,9 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; +#if PACKET_HAS_MASTER + ao_packet_last_rssi = ao_rx_packet.rssi; +#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured */ @@ -130,10 +137,6 @@ ao_packet_recv(void) return 1; } -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - #if PACKET_HAS_MASTER void ao_packet_flush(void) diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 66f94288..e97a6648 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -137,10 +137,15 @@ ao_packet_forward(void) __reentrant #endif } - +static void +ao_packet_signal(void) +{ + printf ("RSSI: %d\n", AO_RSSI_FROM_RADIO(ao_packet_last_rssi)); +} __code struct ao_cmds ao_packet_master_cmds[] = { { ao_packet_forward, "p\0Remote packet link." }, + { ao_packet_signal, "s\0Report signal strength." }, { 0, NULL }, }; -- cgit v1.2.3 From f078a591cf2fafe89bb1bb883f49d80750129d44 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 14:28:53 -0700 Subject: altosui: Remove a bunch of debugging printfs These aren't useful at this point. Signed-off-by: Keith Packard --- altoslib/AltosLog.java | 1 - altoslib/AltosPreferences.java | 2 -- altoslib/AltosRecordMM.java | 2 -- altoslib/AltosTelemetryRecordMegaData.java | 2 -- altoslib/AltosTelemetryRecordMegaSensor.java | 4 ---- altosui/AltosBTDevice.java | 2 -- altosui/AltosBTDeviceIterator.java | 2 -- altosui/AltosBTKnown.java | 2 -- altosui/AltosBTManage.java | 3 --- altosui/AltosConfigTD.java | 7 ++----- altosui/AltosConfigureUI.java | 1 - altosui/AltosFlashUI.java | 7 ------- altosui/AltosLaunchUI.java | 1 - 13 files changed, 2 insertions(+), 34 deletions(-) diff --git a/altoslib/AltosLog.java b/altoslib/AltosLog.java index 08c45ca8..55a25bb4 100644 --- a/altoslib/AltosLog.java +++ b/altoslib/AltosLog.java @@ -62,7 +62,6 @@ class AltosLog implements Runnable { boolean open (AltosRecord telem) throws IOException { AltosFile a = new AltosFile(telem); - System.out.printf("open %s\n", a.toString()); log_file = new FileWriter(a, true); if (log_file != null) { while (!pending_queue.isEmpty()) { diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 43c7088d..9ab80cf5 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -306,7 +306,6 @@ public class AltosPreferences { public static void set_launcher_serial(int new_launcher_serial) { launcher_serial = new_launcher_serial; - System.out.printf("set launcher serial to %d\n", new_launcher_serial); synchronized (preferences) { preferences.putInt(launcherSerialPreference, launcher_serial); flush_preferences(); @@ -319,7 +318,6 @@ public class AltosPreferences { public static void set_launcher_channel(int new_launcher_channel) { launcher_channel = new_launcher_channel; - System.out.printf("set launcher channel to %d\n", new_launcher_channel); synchronized (preferences) { preferences.putInt(launcherChannelPreference, launcher_channel); flush_preferences(); diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java index 8b3d745a..055cf85f 100644 --- a/altoslib/AltosRecordMM.java +++ b/altoslib/AltosRecordMM.java @@ -98,8 +98,6 @@ public class AltosRecordMM extends AltosRecord { } public double acceleration() { - System.out.printf("MM record acceleration %g ground_accel %d accel %d accel_minus_g %d accel_plus_g %d\n", - acceleration, ground_accel, accel, accel_minus_g, accel_plus_g); if (acceleration != MISSING) return acceleration; diff --git a/altoslib/AltosTelemetryRecordMegaData.java b/altoslib/AltosTelemetryRecordMegaData.java index cc35cd83..8f55d238 100644 --- a/altoslib/AltosTelemetryRecordMegaData.java +++ b/altoslib/AltosTelemetryRecordMegaData.java @@ -65,10 +65,8 @@ public class AltosTelemetryRecordMegaData extends AltosTelemetryRecordRaw { AltosRecordMM next; if (!(n instanceof AltosRecordMM)) { - System.out.printf("data making record MM\n"); next = new AltosRecordMM(n); } else { - System.out.printf ("data already has MM\n"); next = (AltosRecordMM) n; } diff --git a/altoslib/AltosTelemetryRecordMegaSensor.java b/altoslib/AltosTelemetryRecordMegaSensor.java index 85a32d12..93c001de 100644 --- a/altoslib/AltosTelemetryRecordMegaSensor.java +++ b/altoslib/AltosTelemetryRecordMegaSensor.java @@ -57,7 +57,6 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { mag_z = int16(30); rssi = in_rssi; - System.out.printf ("telem record accel: %d\n", accel); } public AltosRecord update_state(AltosRecord previous) { @@ -65,14 +64,11 @@ public class AltosTelemetryRecordMegaSensor extends AltosTelemetryRecordRaw { AltosRecordMM next; if (!(n instanceof AltosRecordMM)) { - System.out.printf("sensor making MM\n"); next = new AltosRecordMM(n); } else { - System.out.printf("sensor has MM\n"); next = (AltosRecordMM) n; } - System.out.printf("telem update_state accel: %d\n", accel); next.accel = accel; next.pres = pres; next.temp = temp; diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java index f6926b10..5e353fdd 100644 --- a/altosui/AltosBTDevice.java +++ b/altosui/AltosBTDevice.java @@ -87,7 +87,6 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { public boolean matchProduct(int want_product) { - System.out.printf("matchProduct %s %d\n", toString(), want_product); // if (!isAltusMetrum()) // return false; @@ -107,7 +106,6 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice { if (!(o instanceof AltosBTDevice)) return false; AltosBTDevice other = (AltosBTDevice) o; - System.out.printf("AltosBTDevice equals %s == %s\n", toString(), other.toString()); return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); } diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java index 7c360705..58ed86d5 100644 --- a/altosui/AltosBTDeviceIterator.java +++ b/altosui/AltosBTDeviceIterator.java @@ -26,7 +26,6 @@ public class AltosBTDeviceIterator implements Iterator { SWIGTYPE_p_altos_bt_list list; public boolean hasNext() { - System.out.printf ("BT has next?\n"); if (list == null) return false; if (current != null) @@ -35,7 +34,6 @@ public class AltosBTDeviceIterator implements Iterator { return false; current = new AltosBTDevice(); while (libaltos.altos_bt_list_next(list, current) != 0) { - System.out.printf("Got BT device %s\n", current.toString()); // if (current.matchProduct(product)) return true; } diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java index 021e4d0b..6a8e53cb 100644 --- a/altosui/AltosBTKnown.java +++ b/altosui/AltosBTKnown.java @@ -31,7 +31,6 @@ public class AltosBTKnown implements Iterable { private void set_address(String name, String addr) { bt_pref.put(name, addr); - System.out.printf("saving known %s %s\n", name, addr); } private void remove(String name) { @@ -44,7 +43,6 @@ public class AltosBTKnown implements Iterable { for (int i = 0; i < names.length; i++) { String name = names[i]; String addr = get_address(name); - System.out.printf("Known device %s %s\n", name, addr); devices.add(new AltosBTDevice(name, addr)); } } catch (BackingStoreException be) { diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java index d2899d65..aeb964bb 100644 --- a/altosui/AltosBTManage.java +++ b/altosui/AltosBTManage.java @@ -126,7 +126,6 @@ public class AltosBTManage extends AltosDialog implements ActionListener, Iterab public void add_known() { for (AltosBTDevice device : visible_devices.selected_list()) { - System.out.printf("Add known %s\n", device.toString()); known_devices.add(device); visible_devices.remove(device); } @@ -134,7 +133,6 @@ public class AltosBTManage extends AltosDialog implements ActionListener, Iterab public void remove_known() { for (AltosBTDevice device : known_devices.selected_list()) { - System.out.printf("Remove known %s\n", device.toString()); known_devices.remove(device); visible_devices.add(device); } @@ -151,7 +149,6 @@ public class AltosBTManage extends AltosDialog implements ActionListener, Iterab public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); - System.out.printf("manage command %s\n", command); if ("ok".equals(command)) { bt_thread.interrupt(); commit(); diff --git a/altosui/AltosConfigTD.java b/altosui/AltosConfigTD.java index 4048166c..324a5988 100644 --- a/altosui/AltosConfigTD.java +++ b/altosui/AltosConfigTD.java @@ -144,10 +144,8 @@ public class AltosConfigTD implements ActionListener { get_string(line, "Config version", config_version); get_int(line, "serial-number", serial); get_int(line, "Radio channel:", radio_channel); - if (get_int(line, "Radio cal:", radio_calibration)) - System.out.printf("got radio cal %d\n", radio_calibration.get()); - if (get_int(line, "Frequency:", radio_frequency)) - System.out.printf("got radio freq %d\n", radio_frequency.get()); + get_int(line, "Radio cal:", radio_calibration); + get_int(line, "Frequency:", radio_frequency); get_int(line, "Radio setting:", radio_setting); get_string(line,"software-version", version); get_string(line,"product", product); @@ -205,7 +203,6 @@ public class AltosConfigTD implements ActionListener { break; } } - System.out.printf("config_version %s\n", config_version.get()); if (been_there) break; if (!config_version.get().equals("0.0")) diff --git a/altosui/AltosConfigureUI.java b/altosui/AltosConfigureUI.java index d0ed9325..ace245a0 100644 --- a/altosui/AltosConfigureUI.java +++ b/altosui/AltosConfigureUI.java @@ -291,7 +291,6 @@ public class AltosConfigureUI final UIManager.LookAndFeelInfo[] look_and_feels = UIManager.getInstalledLookAndFeels(); - System.out.printf("look_and_feels %d\n", look_and_feels.length); look_and_feel_value = new JComboBox(look_and_feels); DelegatingRenderer.install(look_and_feel_value); diff --git a/altosui/AltosFlashUI.java b/altosui/AltosFlashUI.java index 4ab73a6d..66991d10 100644 --- a/altosui/AltosFlashUI.java +++ b/altosui/AltosFlashUI.java @@ -235,22 +235,17 @@ public class AltosFlashUI public void run() { ui.flash = flash; ui.update_rom_config_info(current_config); - System.out.printf("Done updating rom config info\n"); await_rom_config.release(); } }); - System.out.printf("Waiting for rom configuration updates\n"); await_rom_config.acquire(); - System.out.printf("Got rom config update\n"); if (ui.rom_config != null) { - System.out.printf("rom_config not null\n"); flash.set_romconfig(ui.rom_config); flash.flash(); } } catch (InterruptedException ee) { final Exception e = ee; - System.out.printf("exception %s\n", e.toString()); SwingUtilities.invokeLater(new Runnable() { public void run() { ui.exception(e); @@ -258,7 +253,6 @@ public class AltosFlashUI }); } catch (IOException ee) { final Exception e = ee; - System.out.printf("exception %s\n", e.toString()); SwingUtilities.invokeLater(new Runnable() { public void run() { ui.exception(e); @@ -266,7 +260,6 @@ public class AltosFlashUI }); } catch (AltosSerialInUseException ee) { final Exception e = ee; - System.out.printf("exception %s\n", e.toString()); SwingUtilities.invokeLater(new Runnable() { public void run() { ui.exception(e); diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java index eb76243d..44481544 100644 --- a/altosui/AltosLaunchUI.java +++ b/altosui/AltosLaunchUI.java @@ -336,7 +336,6 @@ public class AltosLaunchUI public void actionPerformed(ActionEvent e) { String cmd = e.getActionCommand(); - System.out.printf("cmd %s\n", cmd); if (cmd.equals("armed") || cmd.equals("igniter")) { stop_arm_timer(); } -- cgit v1.2.3 From b5f6d4e5251a825395c93916afa3af659c678498 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 19:15:32 -0700 Subject: altosui: Abstract remote connection timeout stuff This moves some of the logic for managing when to present the 'cancel' dialog for remote operations to altoslib. Signed-off-by: Keith Packard --- altoslib/AltosLink.java | 69 +++++++++++++++++++++++++++++++---- altosui/AltosSerial.java | 95 ++++++++++++++---------------------------------- 2 files changed, 88 insertions(+), 76 deletions(-) diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index a39204ac..779c8496 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -60,16 +60,66 @@ public abstract class AltosLink { return null; } - public String get_reply(int timeout) throws InterruptedException { - try { - return get_reply_no_dialog(timeout); - } catch (TimeoutException te) { - return null; + public String get_reply() throws InterruptedException { + return get_reply(5000); + } + + + public abstract boolean can_cancel_reply(); + public abstract boolean show_reply_timeout(); + public abstract void hide_reply_timeout(); + + public boolean reply_abort; + public int in_reply; + + boolean reply_timeout_shown = false; + + private boolean check_reply_timeout() { + if (!reply_timeout_shown) + reply_timeout_shown = show_reply_timeout(); + return reply_abort; + } + + private void cleanup_reply_timeout() { + if (reply_timeout_shown) { + reply_timeout_shown = false; + hide_reply_timeout(); } } - public String get_reply() throws InterruptedException { - return get_reply(5000); + + public String get_reply(int timeout) throws InterruptedException { + boolean can_cancel = can_cancel_reply(); + String reply = null; + + if (!can_cancel && remote) + System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); + + if (remote && can_cancel) + timeout = 500; + try { + ++in_reply; + + flush_output(); + + reply_abort = false; + reply_timeout_shown = false; + for (;;) { + AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); + if (line != null) { + cleanup_reply_timeout(); + reply = line.line; + break; + } + if (!remote || !can_cancel || check_reply_timeout()) { + reply = null; + break; + } + } + } finally { + --in_reply; + } + return reply; } public void add_telem(AltosLine line) throws InterruptedException { @@ -124,7 +174,10 @@ public abstract class AltosLink { public void flush_input() throws InterruptedException { - flush_input(100); + if (remote) + flush_input(500); + else + flush_input(100); } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 8b60dd54..35704d40 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -102,21 +102,7 @@ public class AltosSerial extends AltosLink implements Runnable { } } - boolean abort; JDialog timeout_dialog; - boolean timeout_started = false; - - private void stop_timeout_dialog() { - if (timeout_started) { - timeout_started = false; - Runnable r = new Runnable() { - public void run() { - timeout_dialog.setVisible(false); - } - }; - SwingUtilities.invokeLater(r); - } - } private void start_timeout_dialog_internal() { @@ -135,69 +121,42 @@ public class AltosSerial extends AltosLink implements Runnable { if (o == null) return; if (options[0].equals(o)) - abort = true; + reply_abort = true; timeout_dialog.dispose(); timeout_dialog = null; } - private boolean check_timeout() { - if (!timeout_started && frame != null) { - if (!SwingUtilities.isEventDispatchThread()) { - timeout_started = true; - Runnable r = new Runnable() { - public void run() { - start_timeout_dialog_internal(); - } - }; - SwingUtilities.invokeLater(r); - } - } - return abort; - } + /* + * These are required by the AltosLink implementation + */ - public void flush_input() throws InterruptedException { - if (remote) - flush_input(500); - else - flush_input(100); + public boolean can_cancel_reply() { + /* + * Can cancel any replies not called from the dispatch thread + */ + return !SwingUtilities.isEventDispatchThread(); } - int in_reply; - - public String get_reply(int timeout) throws InterruptedException { - boolean can_cancel = true; - String reply = null; - - try { - ++in_reply; + public boolean show_reply_timeout() { + if (!SwingUtilities.isEventDispatchThread() && frame != null) { + Runnable r = new Runnable() { + public void run() { + start_timeout_dialog_internal(); + } + }; + SwingUtilities.invokeLater(r); + return true; + } + return false; + } - if (SwingUtilities.isEventDispatchThread()) { - can_cancel = false; - if (remote) - System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); - } - flush_output(); - if (remote && can_cancel) { - timeout = 500; - } - abort = false; - timeout_started = false; - for (;;) { - AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); - if (line != null) { - stop_timeout_dialog(); - reply = line.line; - break; + public void hide_reply_timeout() { + Runnable r = new Runnable() { + public void run() { + timeout_dialog.setVisible(false); } - if (!remote || !can_cancel || check_timeout()) { - reply = null; - break; - } - } - } finally { - --in_reply; - } - return reply; + }; + SwingUtilities.invokeLater(r); } public void close() { -- cgit v1.2.3 From 09633cac697e37d770b2b666ab20cab30628484f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:24:14 -0700 Subject: altos/stm: Force STM stack to start at the top of RAM Using a fixed size means crashing if there's not enough space for that, or wasting memory if there's too much. Signed-off-by: Keith Packard --- src/stm/altos-ram.ld | 4 +--- src/stm/altos.ld | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/stm/altos-ram.ld b/src/stm/altos-ram.ld index b8fffedc..1143a08b 100644 --- a/src/stm/altos-ram.ld +++ b/src/stm/altos-ram.ld @@ -19,8 +19,6 @@ MEMORY { ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } -C_STACK_SIZE = 512; - INCLUDE registers.ld SECTIONS { @@ -59,7 +57,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); } diff --git a/src/stm/altos.ld b/src/stm/altos.ld index 7fede558..f5a84f4c 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -23,7 +23,6 @@ MEMORY { INCLUDE registers.ld EXTERN (stm_interrupt_vector) -C_STACK_SIZE = 512; SECTIONS { . = ORIGIN(rom); @@ -62,7 +61,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); } -- cgit v1.2.3 From d90587535676f9492f0fde6b974353158104ef88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:26:38 -0700 Subject: altos: Add arbitrary pyro channel support Programmed by specifying a conjunction of flight conditions that trigger the igniter to fire. Signed-off-by: Keith Packard --- src/core/ao.h | 15 +- src/core/ao_config.c | 12 +- src/core/ao_flight.c | 6 + src/core/ao_flight.h | 4 + src/core/ao_pyro.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_pyro.h | 69 ++++++++++ 6 files changed, 481 insertions(+), 3 deletions(-) create mode 100644 src/core/ao_pyro.c create mode 100644 src/core/ao_pyro.h diff --git a/src/core/ao.h b/src/core/ao.h index eb2d47cf..d4be3be4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -688,6 +688,10 @@ ao_igniter_init(void); * ao_config.c */ +#if AO_PYRO_NUM +#include +#endif + #if HAS_FORCE_FREQ /* * Set this to force the frequency to 434.550MHz @@ -696,7 +700,7 @@ extern __xdata uint8_t ao_force_freq; #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 11 +#define AO_CONFIG_MINOR 12 #define AO_AES_LEN 16 @@ -718,6 +722,9 @@ struct ao_config { uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ uint16_t apogee_lockout; /* minor version 11 */ +#if AO_PYRO_NUM + struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 @@ -731,6 +738,12 @@ extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 +void +_ao_config_edit_start(void); + +void +_ao_config_edit_finish(void); + void ao_config_get(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ced8b1f2..88fcc12d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -131,6 +131,10 @@ _ao_config_get(void) ao_config.frequency = 434550; if (minor < 11) ao_config.apogee_lockout = 0; +#if AO_PYRO_NUM + if (minor < 12) + memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro)); +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -144,14 +148,14 @@ _ao_config_get(void) ao_config_loaded = 1; } -static void +void _ao_config_edit_start(void) { ao_mutex_get(&ao_config_mutex); _ao_config_get(); } -static void +void _ao_config_edit_finish(void) { ao_config_dirty = 1; @@ -537,6 +541,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if AO_PYRO_NUM + { "P \0Configure pyro channels", + ao_pyro_set, ao_pyro_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index c6786455..fc018f00 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,6 +40,9 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ +#if AO_PYRO_NUM +__pdata uint16_t ao_motor_number; /* number of motors burned so far */ +#endif /* * track min/max data over a long interval to detect @@ -214,6 +217,9 @@ ao_flight(void) ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; +#endif +#if AO_PYRO_NUM + ++ao_motor_number; #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index aa5ab60d..c5c8af46 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -37,6 +37,10 @@ enum ao_flight_state { }; extern __pdata enum ao_flight_state ao_flight_state; +extern __pdata uint16_t ao_boost_tick; +#if AO_PYRO_NUM +extern __pdata uint16_t ao_motor_number; +#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c new file mode 100644 index 00000000..c060a866 --- /dev/null +++ b/src/core/ao_pyro.c @@ -0,0 +1,378 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include +#include + +#define ao_lowbit(x) ((x) & (-x)) + +/* + * Given a pyro structure, figure out + * if the current flight state satisfies all + * of the requirements + */ +static uint8_t +ao_pyro_ready(struct ao_pyro *pyro) +{ + enum ao_pyro_flag flag, flags; + + flags = pyro->flags; + while (flags != ao_pyro_none) { + flag = ao_lowbit(flags); + flags &= ~flag; + switch (flag) { + + case ao_pyro_accel_less: + if (ao_accel <= pyro->accel_less) + continue; + break; + case ao_pyro_accel_greater: + if (ao_accel >= pyro->accel_greater) + continue; + break; + + + case ao_pyro_speed_less: + if (ao_speed <= pyro->speed_less) + continue; + break; + case ao_pyro_speed_greater: + if (ao_speed >= pyro->speed_greater) + continue; + break; + + case ao_pyro_height_less: + if (ao_height <= pyro->height_less) + continue; + break; + case ao_pyro_height_greater: + if (ao_height >= pyro->height_greater) + continue; + break; + + case ao_pyro_orient_less: +// if (ao_orient <= pyro->orient_less) + continue; + break; + case ao_pyro_orient_greater: +// if (ao_orient >= pyro->orient_greater) + continue; + break; + + case ao_pyro_time_less: + if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) + continue; + break; + case ao_pyro_time_greater: + if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater) + continue; + break; + + case ao_pyro_ascending: + if (ao_speed > 0) + continue; + break; + case ao_pyro_descending: + if (ao_speed < 0) + continue; + break; + + case ao_pyro_after_motor: + if (ao_motor_number == pyro->motor) + continue; + break; + + case ao_pyro_delay: + /* handled separately */ + continue; + + } + return FALSE; + } + return TRUE; +} + +#define ao_pyro_fire_port(port, pin) do { \ + ao_gpio_set(port, pin, 1); \ + ao_delay(AO_MS_TO_TICKS(50)); \ + ao_gpio_set(port, pin, 0); \ + } while (0) + + +static void +ao_pyro_fire(uint8_t p) +{ + switch (p) { +#if AO_PYRO_NUM > 0 + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; +#endif +#if AO_PYRO_NUM > 1 + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; +#endif +#if AO_PYRO_NUM > 2 + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; +#endif +#if AO_PYRO_NUM > 3 + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; +#endif +#if AO_PYRO_NUM > 4 + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; +#endif +#if AO_PYRO_NUM > 5 + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; +#endif +#if AO_PYRO_NUM > 6 + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; +#endif +#if AO_PYRO_NUM > 7 + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; +#endif + default: break; + } + ao_delay(AO_MS_TO_TICKS(50)); +} + +static void +ao_pyro(void) +{ + uint8_t p; + struct ao_pyro *pyro; + + ao_config_get(); + while (ao_flight_state < ao_flight_boost) + ao_sleep(&ao_flight_state); + + for (;;) { + ao_delay(AO_MS_TO_TICKS(100)); + for (p = 0; p < AO_PYRO_NUM; p++) { + pyro = &ao_config.pyro[p]; + + /* Ignore igniters which have already fired + */ + if (pyro->fired) + continue; + + /* Ignore disabled igniters + */ + if (!pyro->flags) + continue; + + /* Check pyro state to see if it shoule fire + */ + if (!pyro->delay_done) { + if (!ao_pyro_ready(pyro)) + continue; + + /* If there's a delay set, then remember when + * it expires + */ + if (pyro->flags & ao_pyro_delay) + pyro->delay_done = ao_time() + pyro->delay; + } + + /* Check to see if we're just waiting for + * the delay to expire + */ + if (pyro->delay_done) { + if ((int16_t) (ao_time() - pyro->delay_done) < 0) + continue; + } + + ao_pyro_fire(p); + } + } +} + +__xdata struct ao_task ao_pyro_task; + +#define NO_VALUE 0xff + +#define AO_PYRO_NAME_LEN 3 + +const struct { + char name[AO_PYRO_NAME_LEN]; + enum ao_pyro_flag flag; + uint8_t offset; + char *help; +} ao_pyro_values[] = { + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, + + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + + { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, + { "D", ao_pyro_descending, NO_VALUE, "descending" }, + + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, + { "", ao_pyro_none, NO_VALUE, NULL }, +}; + +static void +ao_pyro_print_name(uint8_t v) +{ + const char *s = ao_pyro_values[v].name; + printf ("%s%s", s, " " + strlen(s)); +} + +static void +ao_pyro_help(void) +{ + uint8_t v; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) + printf (" "); + else + printf (" "); + printf ("%s\n", ao_pyro_values[v].help); + } +} + +void +ao_pyro_show(void) +{ + uint8_t p; + uint8_t v; + struct ao_pyro *pyro; + + for (p = 0; p < AO_PYRO_NUM; p++) { + printf ("Pyro %2d: ", p); + pyro = &ao_config.pyro[p]; + if (!pyro->flags) { + printf ("\n"); + continue; + } + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!(pyro->flags & ao_pyro_values[v].flag)) + continue; + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) { + int16_t value; + + value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset)); + printf ("%6d ", value); + } else { + printf (" "); + } + } + printf ("\n"); + } +} + +void +ao_pyro_set(void) +{ + uint8_t p; + struct ao_pyro *pyro; + struct ao_pyro pyro_tmp; + char name[AO_PYRO_NAME_LEN]; + uint8_t c; + uint8_t v; + + ao_cmd_white(); + switch (ao_cmd_lex_c) { + case '?': + ao_pyro_help(); + return; + } + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + p = ao_cmd_lex_i; + if (p < 0 || AO_PYRO_NUM <= p) { + printf ("invalid pyro channel %d\n", p); + return; + } + pyro_tmp.flags = 0; + for (;;) { + ao_cmd_white(); + if (ao_cmd_lex_c == '\n') + break; + + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { + if (ao_cmd_is_white()) + break; + name[c] = ao_cmd_lex_c; + ao_cmd_lex(); + } + name[c] = '\0'; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!strcmp (ao_pyro_values[v].name, name)) + break; + } + if (ao_pyro_values[v].flag == ao_pyro_none) { + printf ("invalid pyro field %s\n", name); + ao_cmd_status = ao_cmd_syntax_error; + return; + } + pyro_tmp.flags |= ao_pyro_values[v].flag; + if (ao_pyro_values[v].offset != NO_VALUE) { + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i; + } + } + _ao_config_edit_start(); + ao_config.pyro[p] = pyro_tmp; + _ao_config_edit_finish(); +} + +void +ao_pyro_init(void) +{ +#if AO_PYRO_NUM > 0 + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); +#endif +#if AO_PYRO_NUM > 1 + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); +#endif +#if AO_PYRO_NUM > 2 + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); +#endif +#if AO_PYRO_NUM > 3 + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); +#endif +#if AO_PYRO_NUM > 4 + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); +#endif +#if AO_PYRO_NUM > 5 + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); +#endif +#if AO_PYRO_NUM > 6 + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); +#endif +#if AO_PYRO_NUM > 7 + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); +#endif + ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); +} diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h new file mode 100644 index 00000000..1989a9e5 --- /dev/null +++ b/src/core/ao_pyro.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PYRO_H_ +#define _AO_PYRO_H_ + +enum ao_pyro_flag { + ao_pyro_none = 0x00000000, + + ao_pyro_accel_less = 0x00000001, + ao_pyro_accel_greater = 0x00000002, + + ao_pyro_speed_less = 0x00000004, + ao_pyro_speed_greater = 0x00000008, + + ao_pyro_height_less = 0x00000010, + ao_pyro_height_greater = 0x00000020, + + ao_pyro_orient_less = 0x00000040, + ao_pyro_orient_greater = 0x00000080, + + ao_pyro_time_less = 0x00000100, + ao_pyro_time_greater = 0x00000200, + + ao_pyro_ascending = 0x00000400, + ao_pyro_descending = 0x00000800, + + ao_pyro_after_motor = 0x00001000, + + ao_pyro_delay = 0x00002000, +}; + +struct ao_pyro { + enum ao_pyro_flag flags; + int16_t accel_less, accel_greater; + int16_t speed_less, speed_greater; + int16_t height_less, height_greater; + int16_t orient_less, orient_greater; + int16_t time_less, time_greater; + int16_t delay; + int16_t motor; + uint16_t delay_done; + uint8_t fired; +}; + +void +ao_pyro_set(void); + +void +ao_pyro_show(void); + +void +ao_pyro_init(void); + +#endif -- cgit v1.2.3 From 726e0f2c547b6bae1f1e640e2c1155c0b9631a9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:28:31 -0700 Subject: stm: running out of memory in MM -- reduce stack to 668 bytes Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index baae1902..d8fa3e89 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 700 +#define AO_STACK_SIZE 668 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 82b50fc1b7f2c6af7264fbad2c35508abc15e81e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:28:55 -0700 Subject: altos/stm: Expose ao_gpio_set which sets a specific GPIO pin Will need versions for other architectures Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 7820bf79..4416bbab 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -76,9 +76,11 @@ ao_spi_init(void); } while (0) +#define ao_gpio_set(port, pin, v) stm_gpio_set(port, pin, v) + #define ao_enable_output(port,pin,v) do { \ ao_enable_port(port); \ - stm_gpio_set(port, pin, v); \ + ao_gpio_set(port, pin, v); \ stm_moder_set(port, pin, STM_MODER_OUTPUT); \ } while (0) -- cgit v1.2.3 From 37032e4b0cbac4c823e3dd18e60ad8900e9ceff1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:29:50 -0700 Subject: altos/megametrum: Support the four additional pyro channels These use the new pyro code to allow for some flexibility in programming. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + src/megametrum-v0.1/ao_megametrum.c | 2 ++ src/megametrum-v0.1/ao_pins.h | 31 ++++++++++++++----------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 59cfb64d..d415b59b 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -74,6 +74,7 @@ ALTOS_SRC = \ ao_packet_slave.c \ ao_packet.c \ ao_companion.c \ + ao_pyro.c \ $(PROFILE) PRODUCT=MegaMetrum-v0.1 diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index a6d93733..55324514 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -23,6 +23,7 @@ #include #include #include +#include int main(void) @@ -67,6 +68,7 @@ main(void) ao_packet_slave_init(FALSE); ao_igniter_init(); ao_companion_init(); + ao_pyro_init(); ao_config_init(); #if AO_PROFILE diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 34b75255..2c438f6c 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -120,29 +120,26 @@ #define AO_IGNITER_CLOSED 400 #define AO_IGNITER_OPEN 60 -#define AO_IGNITER_PORT_A (&stm_gpiod) -#define AO_IGNITER_PIN_A 6 +#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) +#define AO_IGNITER_DROGUE_PIN 6 -#define AO_IGNITER_PORT_B (&stm_gpiod) -#define AO_IGNITER_PIN_B 7 +#define AO_IGNITER_MAIN_PORT (&stm_gpiod) +#define AO_IGNITER_MAIN_PIN 7 -#define AO_IGNITER_PORT_C (&stm_gpiob) -#define AO_IGNITER_PIN_C 5 +#define AO_PYRO_PORT_0 (&stm_gpiob) +#define AO_PYRO_PIN_0 5 -#define AO_IGNITER_PORT_D (&stm_gpioe) -#define AO_IGNITER_PIN_D 4 +#define AO_PYRO_PORT_1 (&stm_gpioe) +#define AO_PYRO_PIN_1 4 -#define AO_IGNITER_PORT_E (&stm_gpioe) -#define AO_IGNITER_PIN_E 6 +#define AO_PYRO_PORT_2 (&stm_gpioe) +#define AO_PYRO_PIN_2 6 -#define AO_IGNITER_PORT_F (&stm_gpioe) -#define AO_IGNITER_PIN_F 5 +#define AO_PYRO_PORT_3 (&stm_gpioe) +#define AO_PYRO_PIN_3 5 -#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT_A -#define AO_IGNITER_DROGUE_PIN AO_IGNITER_PIN_A - -#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT_B -#define AO_IGNITER_MAIN_PIN AO_IGNITER_PIN_B +/* Number of general purpose pyro channels available */ +#define AO_PYRO_NUM 4 #define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) #define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) -- cgit v1.2.3 From 0cfd22baa6af44e053428c30c1a95cf5551b68af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 02:44:17 -0700 Subject: src: Add explicit 'pin' argument to ao_enable_output This lets the cc1111 use the atomic bit operation instead of a mask, which is immune to interrupt issues as well as being a shorter code sequence. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 17 +++++++++++++++++ src/cc1111/ao_arch_funcs.h | 12 ++++++------ src/core/ao_ignite.c | 4 ++-- src/core/ao_pyro.c | 41 +++++++++++++++++++++-------------------- src/drivers/ao_25lc1024.c | 2 +- src/drivers/ao_companion.c | 2 +- src/stm/ao_arch_funcs.h | 8 ++++---- 7 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index e400c98b..792ff744 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -41,12 +41,29 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) + +#define ao_gpio_token_paster(x,y) x ## y +#define ao_gpio_token_evaluator(x,y) ao_gpio_token_paster(x,y) + +#define ao_gpio_set(port, bit, pin, v) do { \ + if (v) \ + (ao_gpio_token_evaluator(PORT,port)) |= (1 << bit); \ + else \ + (ao_gpio_token_evaluator(PORT,port)) &= ~(1 << bit); \ + } while (0) + /* * The SPI mutex must be held to call either of these * functions -- this mutex covers the entire SPI operation, * from chip select low to chip select high */ +#define ao_enable_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + ao_gpio_token_evaluator(DDR,port) |= (1 << bit); \ + } while (0) + + void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 0a322961..0737e7ab 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -77,14 +77,14 @@ ao_spi_init(void); SPI_CS_SEL &= ~mask; \ } while (0) -#define cc1111_enable_output(port,dir,sel,mask,v) do { \ - port = port & ~(mask) | v; \ - dir |= mask; \ - sel &= ~mask; \ -} while (0) +#define cc1111_enable_output(port,dir,sel,pin,bit,v) do { \ + pin = v; \ + dir |= (1 << bit); \ + sel &= ~(1 << bit); \ + } while (0) #define disable_unreachable _Pragma("disable_warning 126") #define token_paster(x,y) x ## y #define token_evaluator(x,y) token_paster(x,y) -#define ao_enable_output(port,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), 1 << pin, 1 << v) +#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index e82de355..c7829fc3 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -195,8 +195,8 @@ __xdata struct ao_task ao_igniter_task; void ao_ignite_set_pins(void) { - ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); - ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0); } void diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index c060a866..943413e6 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -102,16 +102,18 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; + case ao_pyro_none: + break; } return FALSE; } return TRUE; } -#define ao_pyro_fire_port(port, pin) do { \ - ao_gpio_set(port, pin, 1); \ +#define ao_pyro_fire_port(port, bit, pin) do { \ + ao_gpio_set(port, bit, pin, 1); \ ao_delay(AO_MS_TO_TICKS(50)); \ - ao_gpio_set(port, pin, 0); \ + ao_gpio_set(port, bit, pin, 0); \ } while (0) @@ -120,28 +122,28 @@ ao_pyro_fire(uint8_t p) { switch (p) { #if AO_PYRO_NUM > 0 - case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0); break; #endif #if AO_PYRO_NUM > 1 - case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1); break; #endif #if AO_PYRO_NUM > 2 - case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2); break; #endif #if AO_PYRO_NUM > 3 - case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3); break; #endif #if AO_PYRO_NUM > 4 - case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4); break; #endif #if AO_PYRO_NUM > 5 - case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5); break; #endif #if AO_PYRO_NUM > 6 - case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6); break; #endif #if AO_PYRO_NUM > 7 - case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7); break; #endif default: break; } @@ -291,7 +293,6 @@ void ao_pyro_set(void) { uint8_t p; - struct ao_pyro *pyro; struct ao_pyro pyro_tmp; char name[AO_PYRO_NAME_LEN]; uint8_t c; @@ -351,28 +352,28 @@ void ao_pyro_init(void) { #if AO_PYRO_NUM > 0 - ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0, 0); #endif #if AO_PYRO_NUM > 1 - ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1, 0); #endif #if AO_PYRO_NUM > 2 - ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2, 0); #endif #if AO_PYRO_NUM > 3 - ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3, 0); #endif #if AO_PYRO_NUM > 4 - ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4, 0); #endif #if AO_PYRO_NUM > 5 - ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5, 0); #endif #if AO_PYRO_NUM > 6 - ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6, 0); #endif #if AO_PYRO_NUM > 7 - ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index c5d811f7..fac0a430 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -236,5 +236,5 @@ void ao_storage_device_init(void) { /* set up CS */ - ao_enable_output(EE_CS_PORT, EE_CS_PIN,1); + ao_enable_output(EE_CS_PORT, EE_CS_PIN, EE_CS, 1); } diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 85d68c44..a3167956 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -131,7 +131,7 @@ static __xdata struct ao_task ao_companion_task; void ao_companion_init(void) { - ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, 1); + ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, AO_COMPANION_CS, 1); ao_cmd_register(&ao_companion_cmds[0]); ao_add_task(&ao_companion_task, ao_companion, "companion"); } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 4416bbab..d2c973f5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -76,12 +76,12 @@ ao_spi_init(void); } while (0) -#define ao_gpio_set(port, pin, v) stm_gpio_set(port, pin, v) +#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) -#define ao_enable_output(port,pin,v) do { \ +#define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ - ao_gpio_set(port, pin, v); \ - stm_moder_set(port, pin, STM_MODER_OUTPUT); \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) #define ao_enable_cs(port,bit) do { \ -- cgit v1.2.3 From 42a51becf4b76f23dbd4f5f80f8879ce696aa543 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:36:51 -0700 Subject: altos/avr: Remove debugging printf in avr stdio startup Signed-off-by: Keith Packard --- src/avr/ao_avr_stdio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index ba562dbf..2765853a 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -48,5 +48,4 @@ ao_avr_stdio_init(void) { stdout = &mystdout; stdin = &mystdin; - printf("%d stdios registered\n", ao_num_stdios); } -- cgit v1.2.3 From 81b7b58c9df01847fa47747deeff8c3c91304ad1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:37:58 -0700 Subject: altos/avr: Remove debugging command from USB driver Signed-off-by: Keith Packard --- src/avr/ao_usb_avr.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 23a27c73..9ba407af 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -658,18 +658,6 @@ ao_usb_echo(void) } #endif -static void -ao_usb_irq(void) -{ - printf ("control: %d out: %d in: %d\n", - control_count, out_count, in_count); -} - -__code struct ao_cmds ao_usb_cmds[] = { - { ao_usb_irq, "i\0Show USB interrupt counts" }, - { 0, NULL } -}; - void ao_usb_init(void) { @@ -680,6 +668,5 @@ ao_usb_init(void) #if USB_DEBUG ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif - ao_cmd_register(&ao_usb_cmds[0]); ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } -- cgit v1.2.3 From 366217e86a4c353012b5102322ee6927f7b27a21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:39:05 -0700 Subject: altos: Remove unused 'func' from ao_config_set Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 88fcc12d..e2095e65 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -562,12 +562,10 @@ ao_config_set(void) { char c; uint8_t cmd; - void (*__xdata func)(void) __reentrant; ao_cmd_white(); c = ao_cmd_lex_c; ao_cmd_lex(); - func = 0; for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].str[0] == c) { (*ao_config_vars[cmd].set)(); -- cgit v1.2.3 From 2a23030031c31267fc4f14accd9220f285c03b61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:40:49 -0700 Subject: altos: No space for pyro help on TP v0.1 AVR doesn't have enough ram to hold the help messages, and we can't use them in flash. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 943413e6..b0d45162 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -207,34 +207,48 @@ __xdata struct ao_task ao_pyro_task; #define AO_PYRO_NAME_LEN 3 +#if !DISABLE_HELP +#define ENABLE_HELP 1 +#endif + +#if ENABLE_HELP +#define HELP(s) (s) +#else +#define HELP(s) +#endif + const struct { char name[AO_PYRO_NAME_LEN]; enum ao_pyro_flag flag; uint8_t offset; +#if ENABLE_HELP char *help; +#endif } ao_pyro_values[] = { - { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, - { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), HELP("accel less (m/ss * 16)") }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), HELP("accel greater (m/ss * 16)") }, - { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, - { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), HELP("speed less (m/s * 16)") }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), HELP("speed greater (m/s * 16)") }, - { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, - { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, - { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, - { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, +#if 0 + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, +#endif - { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, - { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)") }, - { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, - { "D", ao_pyro_descending, NO_VALUE, "descending" }, + { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, + { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, - { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, - { "", ao_pyro_none, NO_VALUE, NULL }, + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, + { "", ao_pyro_none, NO_VALUE, HELP(NULL) }, }; static void @@ -244,6 +258,7 @@ ao_pyro_print_name(uint8_t v) printf ("%s%s", s, " " + strlen(s)); } +#if ENABLE_HELP static void ao_pyro_help(void) { @@ -257,6 +272,7 @@ ao_pyro_help(void) printf ("%s\n", ao_pyro_values[v].help); } } +#endif void ao_pyro_show(void) @@ -299,11 +315,14 @@ ao_pyro_set(void) uint8_t v; ao_cmd_white(); + +#if ENABLE_HELP switch (ao_cmd_lex_c) { case '?': ao_pyro_help(); return; } +#endif ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) -- cgit v1.2.3 From 84d5e00d417af4924594908d19346bb965089cdd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:44:40 -0700 Subject: src: Add driver for AVR internal eeprom. Use for telepyro config. Signed-off-by: Keith Packard --- src/avr/ao_eeprom_avr.c | 133 +++++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_pins.h | 6 ++ src/telepyro-v0.1/Makefile | 16 +++--- 3 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 src/avr/ao_eeprom_avr.c diff --git a/src/avr/ao_eeprom_avr.c b/src/avr/ao_eeprom_avr.c new file mode 100644 index 00000000..2451fa8a --- /dev/null +++ b/src/avr/ao_eeprom_avr.c @@ -0,0 +1,133 @@ +/* + * Copyright © 2012 Keith Packard + * Copyright © 2011 Anthony Towns + * + * 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 +#include + +/* Total bytes of available storage */ +__pdata ao_pos_t ao_storage_total = 1024; + +/* Block size - device is erased in these units. */ +__pdata ao_pos_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata ao_pos_t ao_storage_config = 0; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__pdata uint16_t ao_storage_unit = 1024; + +/* + * The internal flash chip is arranged in 8 byte sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(ao_pos_t pos) __reentrant +{ + /* Not necessary */ + return 1; +} + +#define ao_intflash_wait_idle() do { \ + /* Wait for any outstanding writes to complete */ \ + while (EECR & (1 << EEPE)) \ + ; \ + } while (0) \ + +static void +ao_intflash_write(uint16_t pos, uint8_t d) +{ + ao_intflash_wait_idle(); + EEAR = pos; + EEDR = d; + ao_arch_critical( + EECR |= (1 << EEMPE); + EECR |= (1 << EEPE); + ); +} + +static uint8_t +ao_intflash_read(uint16_t pos) +{ + ao_intflash_wait_idle(); + EEAR = pos; + + EECR |= (1 << EERE); + return EEDR; +} +/* + * Write to flash + */ + +uint8_t +ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + while (len--) + ao_intflash_write(pos++, *d++); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant +{ + uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len--) + *d++ = ao_intflash_read(pos++); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash\n"); +} + +void +ao_storage_device_init(void) +{ +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 850a08ec..3c9010a8 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -72,6 +72,12 @@ #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define DISABLE_HELP 1 + #define HAS_STORAGE_DEBUG 0 + #define IS_COMPANION 1 + #define ao_storage_pos_t uint16_t #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2ac7e747..bc57b9d7 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -22,7 +22,8 @@ INC = \ ao.h \ ao_usb.h \ ao_pins.h \ - altitude.h + ao_arch.h \ + ao_arch_funcs.h ALTOS_SRC = \ ao_clock.c \ @@ -39,14 +40,18 @@ ALTOS_SRC = \ ao_usb_avr.c \ ao_adc_avr.c \ ao_pyro_slave.c \ - ao_spi_slave.c + ao_spi_slave.c \ + ao_eeprom_avr.c \ + ao_storage.c \ + ao_config.c \ + ao_pyro.c PRODUCT=TelePyro-v0.1 MCU=atmega32u4 PRODUCT_DEF=-DTELEPYRO IDPRODUCT=0x0011 CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. -CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR +CFLAGS += -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR NICKLE=nickle @@ -79,9 +84,6 @@ $(PROG).hex: $(PROG) load: $(PROG).hex $(LOADCMD) $(LOADARG)$(PROG).hex -../altitude.h: make-altitude - nickle $< > $@ - ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ @@ -100,4 +102,4 @@ install: uninstall: -$(OBJ): ao.h ao_product.h ao_usb.h +$(OBJ): $(INC) -- cgit v1.2.3 From 4de789331098abc24abcb9390a35aef889a41784 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:47:53 -0700 Subject: altos: Make storage addresses datatype configurable No sense using 32 bits for tiny hardware Signed-off-by: Keith Packard --- src/core/ao_storage.c | 8 ++++---- src/core/ao_storage.h | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 66394e01..b2dd435b 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -18,7 +18,7 @@ #include uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -48,7 +48,7 @@ ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -161,8 +161,8 @@ void ao_storage_info(void) __reentrant { ao_storage_setup(); - printf("Storage size: %ld\n", ao_storage_total); - printf("Storage erase unit: %ld\n", ao_storage_block); + printf("Storage size: %ld\n", (long) ao_storage_total); + printf("Storage erase unit: %ld\n", (long) ao_storage_block); ao_storage_device_info(); } diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h index 873fe097..ea946399 100644 --- a/src/core/ao_storage.h +++ b/src/core/ao_storage.h @@ -23,14 +23,20 @@ * drivers */ +#ifndef ao_storage_pos_t +#define ao_storage_pos_t uint32_t +#endif + +typedef ao_storage_pos_t ao_pos_t; + /* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; +extern __pdata ao_pos_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; +extern __pdata ao_pos_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; +extern __pdata ao_pos_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ extern __pdata uint16_t ao_storage_unit; @@ -43,15 +49,15 @@ ao_storage_setup(void) __reentrant; /* Write data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Read data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_storage_erase(uint32_t pos) __reentrant; +ao_storage_erase(ao_pos_t pos) __reentrant; /* Flush any pending writes to stable storage */ void @@ -67,11 +73,11 @@ ao_storage_init(void); /* Read data within a storage unit */ uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Write data within a storage unit */ uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Initialize low-level device bits */ void -- cgit v1.2.3 From e7ca3a7849b3cbbb38143d35fe86972290bd4e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:18:12 -0700 Subject: altos: Make sure telepyro ao_product.h is built before .o files Signed-off-by: Keith Packard --- src/telepyro-v0.1/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index bc57b9d7..2ccd565f 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -2,7 +2,7 @@ # AltOS build # # -vpath % ..:../core:../product:../drivers:../avr +vpath % .:..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util MCU=atmega32u4 @@ -23,7 +23,8 @@ INC = \ ao_usb.h \ ao_pins.h \ ao_arch.h \ - ao_arch_funcs.h + ao_arch_funcs.h \ + ao_product.h ALTOS_SRC = \ ao_clock.c \ -- cgit v1.2.3 From 184e2ff4790974733df57facdeeb96bfe692ab54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:21:21 -0700 Subject: altos: Remove some debug code from avr ADC driver Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 928cd3e1..3a262977 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,42 +125,21 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_data packet; uint8_t i; ao_data_get(&packet); -#ifdef TELEPYRO - printf("ADMUX: %02x\n", ADMUX); - printf("ADCSRA: %02x\n", ADCSRA); - printf("ADCSRB: %02x\n", ADCSRB); - printf("DIDR0: %02x\n", DIDR0); - printf("DIDR2: %02x\n", DIDR2); - printf("PORTF: %02x\n", PORTF); - printf("DDRF: %02x\n", DDRF); - printf("PINF: %02x\n", PINF); -#endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc.adc[i]); printf("\n"); - - -#ifdef TELEPYRO - ADMUX = 0x60; - ADCSRB = 0x00; - ADCSRA = 0xc6; - while (ADCSRA & 0x40) - ; - printf ("ADCL: %02x\n", ADCL); - printf ("ADCH: %02x\n", ADCH); - printf ("\n"); -#endif } __code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Display current ADC values" }, + { ao_adc_dump, "a\0ADC" }, { 0, NULL }, }; void ao_adc_init(void) { + PRR0 &= ~(1 << PRADC); DIDR0 = 0xf3; DIDR2 = 0x3f; ADCSRB = ADCSRB_INIT; -- cgit v1.2.3 From 90507d4f7ef77b0870a032b1d9809898c2924721 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:24:21 -0700 Subject: altos: Make ao_tick_count visible Necessary to fetch it when interrupts are already disabled as we can't call ao_time then. Signed-off-by: Keith Packard --- src/avr/ao_timer.c | 2 +- src/cc1111/ao_timer.c | 2 +- src/core/ao.h | 2 ++ src/stm/ao_timer.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index eef14345..cd81b163 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index aadee71e..602f98c8 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) __critical { diff --git a/src/core/ao.h b/src/core/ao.h index d4be3be4..65b9eb18 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -125,6 +125,8 @@ ao_panic(uint8_t reason); * ao_timer.c */ +extern volatile __data uint16_t ao_tick_count; + /* Our timer runs at 100Hz */ #define AO_HERTZ 100 #define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 936dc881..ebe75366 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { -- cgit v1.2.3 From 1887ca3d7d4a0259686f8c1e68d1e47c47b4ab84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:25:47 -0700 Subject: altos: Pass flight dynamics to companion boards Necessary for TelePyro Signed-off-by: Keith Packard --- src/core/ao_companion.h | 4 ++++ src/core/ao_flight.c | 4 ---- src/core/ao_flight.h | 2 -- src/drivers/ao_companion.c | 4 ++++ 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h index 47e0acf5..035325a3 100644 --- a/src/core/ao_companion.h +++ b/src/core/ao_companion.h @@ -30,6 +30,10 @@ struct ao_companion_command { uint16_t tick; uint16_t serial; uint16_t flight; + int16_t accel; + int16_t speed; + int16_t height; + int16_t motor_number; }; struct ao_companion_setup { diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index fc018f00..aa4f6961 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,7 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ -#if AO_PYRO_NUM __pdata uint16_t ao_motor_number; /* number of motors burned so far */ -#endif /* * track min/max data over a long interval to detect @@ -218,9 +216,7 @@ ao_flight(void) #else ao_flight_state = ao_flight_coast; #endif -#if AO_PYRO_NUM ++ao_motor_number; -#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index c5c8af46..b80202f0 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -38,9 +38,7 @@ enum ao_flight_state { extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_boost_tick; -#if AO_PYRO_NUM extern __pdata uint16_t ao_motor_number; -#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index a3167956..6e0bd2ec 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -53,6 +53,10 @@ ao_companion_send_command(uint8_t command) ao_companion_command.tick = ao_time(); ao_companion_command.serial = ao_serial_number; ao_companion_command.flight = ao_flight_number; + ao_companion_command.accel = ao_accel; + ao_companion_command.speed = ao_speed; + ao_companion_command.height = ao_height; + ao_companion_command.motor_number = ao_motor_number; ao_spi_send(&ao_companion_command, sizeof (ao_companion_command), AO_COMPANION_SPI_BUS); } -- cgit v1.2.3 From 6581eefbdbd8d3e94f615bdf11652a000d131c8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:27:58 -0700 Subject: altos: Use 'HAS_ORIENT' to enable orientation selection in pyro code Don't expose orientation options when no orientation data is available Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index b0d45162..162f5e1e 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -66,14 +66,16 @@ ao_pyro_ready(struct ao_pyro *pyro) continue; break; +#if HAS_ORIENT case ao_pyro_orient_less: -// if (ao_orient <= pyro->orient_less) + if (ao_orient <= pyro->orient_less) continue; break; case ao_pyro_orient_greater: -// if (ao_orient >= pyro->orient_greater) + if (ao_orient >= pyro->orient_greater) continue; break; +#endif case ao_pyro_time_less: if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) @@ -102,8 +104,8 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; - case ao_pyro_none: - break; + default: + continue; } return FALSE; } @@ -234,7 +236,7 @@ const struct { { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, -#if 0 +#if HAS_ORIENT { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, #endif @@ -281,6 +283,7 @@ ao_pyro_show(void) uint8_t v; struct ao_pyro *pyro; + printf ("Pyro-count: %d\n", AO_PYRO_NUM); for (p = 0; p < AO_PYRO_NUM; p++) { printf ("Pyro %2d: ", p); pyro = &ao_config.pyro[p]; -- cgit v1.2.3 From 3ce645a79b54e22d7835c6e390a22a5ad501a339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:30:29 -0700 Subject: altos: Add manual firing command for extra pyro channels In parallel with the existing igniter commands, this tests the programmable pyro channels Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 162f5e1e..a1377d21 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -103,7 +103,7 @@ ao_pyro_ready(struct ao_pyro *pyro) case ao_pyro_delay: /* handled separately */ continue; - + default: continue; } @@ -117,7 +117,7 @@ ao_pyro_ready(struct ao_pyro *pyro) ao_delay(AO_MS_TO_TICKS(50)); \ ao_gpio_set(port, bit, pin, 0); \ } while (0) - + static void ao_pyro_fire(uint8_t p) @@ -246,7 +246,7 @@ const struct { { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, @@ -275,7 +275,7 @@ ao_pyro_help(void) } } #endif - + void ao_pyro_show(void) { @@ -340,7 +340,7 @@ ao_pyro_set(void) ao_cmd_white(); if (ao_cmd_lex_c == '\n') break; - + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { if (ao_cmd_is_white()) break; @@ -370,6 +370,25 @@ ao_pyro_set(void) _ao_config_edit_finish(); } +static void +ao_pyro_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_cmd_decimal(); + if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i) + return; + ao_pyro_fire(ao_cmd_lex_i); + +} + +const struct ao_cmds ao_pyro_cmds[] = { + { ao_pyro_manual, "P DoIt \0Fire igniter" }, + { 0, NULL } +}; + void ao_pyro_init(void) { @@ -397,5 +416,6 @@ ao_pyro_init(void) #if AO_PYRO_NUM > 7 ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif + ao_cmd_register(&ao_pyro_cmds[0]); ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } -- cgit v1.2.3 From 5860f75677ee20fcf35ab89a6b62f3e14a1c32f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:32:26 -0700 Subject: altos: Enable pyro channel control in telepyro This should make the board actually work now. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 30 ++++++++++++++++++++++++++++++ src/core/ao_pyro.c | 15 ++++++++++++++- src/core/ao_pyro.h | 2 ++ src/drivers/ao_pyro_slave.c | 11 +++++++++++ src/product/ao_telepyro.c | 3 +++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 3c9010a8..bc423ff7 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -59,6 +59,8 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define IS_COMPANION 1 #endif #ifdef TELEPYRO @@ -77,6 +79,7 @@ #define DISABLE_HELP 1 #define HAS_STORAGE_DEBUG 0 #define IS_COMPANION 1 + #define HAS_ORIENT 0 #define ao_storage_pos_t uint16_t #define AVR_VCC_5V 0 @@ -89,6 +92,33 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define AO_PYRO_NUM 8 + + #define AO_PYRO_PORT_0 B + #define AO_PYRO_PIN_0 5 + + #define AO_PYRO_PORT_1 B + #define AO_PYRO_PIN_1 6 + + #define AO_PYRO_PORT_2 B + #define AO_PYRO_PIN_2 7 + + #define AO_PYRO_PORT_3 C + #define AO_PYRO_PIN_3 6 + + #define AO_PYRO_PORT_4 C + #define AO_PYRO_PIN_4 7 + + #define AO_PYRO_PORT_5 D + #define AO_PYRO_PIN_5 5 + + #define AO_PYRO_PORT_6 D + #define AO_PYRO_PIN_6 3 + + #define AO_PYRO_PORT_7 D + #define AO_PYRO_PIN_7 2 + #endif #define AO_M25_SPI_CS_PORT SPI_CS_PORT diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index a1377d21..4f37e979 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -20,6 +20,15 @@ #include #include +#if IS_COMPANION +#include +#define ao_accel ao_companion_command.accel +#define ao_speed ao_companion_command.speed +#define ao_height ao_companion_command.height +#define ao_flight_state ao_companion_command.flight_state +#define ao_motor_number ao_companion_command.motor_number +#endif + #define ao_lowbit(x) ((x) & (-x)) /* @@ -152,6 +161,8 @@ ao_pyro_fire(uint8_t p) ao_delay(AO_MS_TO_TICKS(50)); } +uint8_t ao_pyro_wakeup; + static void ao_pyro(void) { @@ -163,7 +174,9 @@ ao_pyro(void) ao_sleep(&ao_flight_state); for (;;) { - ao_delay(AO_MS_TO_TICKS(100)); + ao_alarm(AO_MS_TO_TICKS(100)); + ao_sleep(&ao_pyro_wakeup); + ao_clear_alarm(); for (p = 0; p < AO_PYRO_NUM; p++) { pyro = &ao_config.pyro[p]; diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 1989a9e5..5deb69d0 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -57,6 +57,8 @@ struct ao_pyro { uint8_t fired; }; +extern uint8_t ao_pyro_wakeup; + void ao_pyro_set(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 70206a00..f07c2cba 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include struct ao_companion_command ao_companion_command; @@ -28,6 +30,11 @@ static const struct ao_companion_setup ao_telepyro_setup = { .channels = AO_TELEPYRO_NUM_ADC, }; +struct ao_config ao_config; + +extern volatile __data uint16_t ao_tick_count; +uint16_t ao_boost_tick; + void ao_spi_slave(void) { if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, @@ -45,6 +52,10 @@ void ao_spi_slave(void) AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: + /* Can't use ao_time because we have interrupts suspended */ + if (ao_companion_command.flight_state < ao_flight_boost && ao_companion_command.flight_state >= ao_flight_boost) + ao_boost_tick = ao_tick_count; + ao_wakeup(&ao_pyro_wakeup); break; default: return; diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c index a2b8f83c..79454fb7 100644 --- a/src/product/ao_telepyro.c +++ b/src/product/ao_telepyro.c @@ -31,6 +31,9 @@ main(void) ao_spi_slave_init(); ao_usb_init(); ao_adc_init(); + ao_storage_init(); + ao_config_init(); + ao_pyro_init(); ao_start_scheduler(); return 0; } -- cgit v1.2.3 From 0edb5616a70fd480317acc99ec3c28c662aa8556 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:34:01 -0700 Subject: altos: megametrum depends on ao_companion.h Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index d415b59b..a519609e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -9,6 +9,7 @@ INC = \ ao.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_companion.h \ ao_data.h \ ao_sample.h \ ao_pins.h \ -- cgit v1.2.3 From 52196975c447851f14619213c1de5101d334eebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:35:11 -0700 Subject: altosui: Move serial datastream parser to altoslib instead of having it in altosui Signed-off-by: Keith Packard --- altoslib/AltosLink.java | 47 +++++++++++++++++++++++++++++++++++++++++++++++ altosui/AltosSerial.java | 42 ++---------------------------------------- 2 files changed, 49 insertions(+), 40 deletions(-) diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 779c8496..d59e73ba 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -24,6 +24,11 @@ import java.util.*; import java.text.*; public abstract class AltosLink { + + public final static int ERROR = -1; + public final static int TIMEOUT = -2; + + public abstract int getchar(); public abstract void print(String data); public abstract void close(); @@ -88,6 +93,48 @@ public abstract class AltosLink { } + public void run () { + int c; + byte[] line_bytes = null; + int line_count = 0; + + try { + for (;;) { + c = getchar(); + if (Thread.interrupted()) + break; + if (c == ERROR) { + add_telem (new AltosLine()); + add_reply (new AltosLine()); + break; + } + if (c == TIMEOUT) + continue; + if (c == '\r') + continue; + synchronized(this) { + if (c == '\n') { + if (line_count != 0) { + add_bytes(line_bytes, line_count); + line_count = 0; + } + } else { + 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++; + } + } + } + } catch (InterruptedException e) { + } + } + public String get_reply(int timeout) throws InterruptedException { boolean can_cancel = can_cancel_reply(); String reply = null; diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index 35704d40..c4e9c697 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -53,46 +53,8 @@ public class AltosSerial extends AltosLink implements Runnable { int line_count; Frame frame; - public void run () { - int c; - byte[] line_bytes = null; - int line_count = 0; - - try { - for (;;) { - c = libaltos.altos_getchar(altos, 0); - if (Thread.interrupted()) - break; - if (c == libaltosConstants.LIBALTOS_ERROR) { - add_telem (new AltosLine()); - add_reply (new AltosLine()); - break; - } - if (c == libaltosConstants.LIBALTOS_TIMEOUT) - continue; - if (c == '\r') - continue; - synchronized(this) { - if (c == '\n') { - if (line_count != 0) { - add_bytes(line_bytes, line_count); - line_count = 0; - } - } else { - 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++; - } - } - } - } catch (InterruptedException e) { - } + public int getchar() { + return libaltos.altos_getchar(altos, 0); } public void flush_output() { -- cgit v1.2.3 From eda636c5f309b85282b4142118ee65673d28d137 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:36:20 -0700 Subject: altosui: Skip unknown data when parsing ADC for idle monitoring This resolves an infinite loop when talking to megametrum. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index eb6ec5e7..ce608d2b 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -84,6 +84,7 @@ class AltosADC { i += 2; continue; } + i++; } break; } -- cgit v1.2.3 From 20877ae9de8bb5d3a29e2a96024e53afbd396f55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 01:18:45 -0700 Subject: Add ao-stmload tool This loads an ELF image through the STlink programming interface using the stlink utility library Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-stmload/Makefile.am | 14 + ao-tools/ao-stmload/ao-stmload.1 | 61 ++++ ao-tools/ao-stmload/ao-stmload.c | 591 +++++++++++++++++++++++++++++++++++++++ configure.ac | 1 + 5 files changed, 668 insertions(+), 1 deletion(-) create mode 100644 ao-tools/ao-stmload/Makefile.am create mode 100644 ao-tools/ao-stmload/ao-stmload.1 create mode 100644 ao-tools/ao-stmload/ao-stmload.c diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 611bb7dc..6c315dd1 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am new file mode 100644 index 00000000..77979daf --- /dev/null +++ b/ao-tools/ao-stmload/Makefile.am @@ -0,0 +1,14 @@ +bin_PROGRAMS=ao-stmload + +LIBSTLINKDIR=/local/src/stlink + +AM_CFLAGS=-I$(LIBSTLINKDIR)/src $(LIBUSB_CFLAGS) -I../lib + +AO_STMLOAD_LIBS=$(LIBSTLINKDIR)/libstlink.a +ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS) + +ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBUSB_LIBS) -lelf + +ao_stmload_SOURCES=ao-stmload.c + +man_MANS = ao-stmload.1 diff --git a/ao-tools/ao-stmload/ao-stmload.1 b/ao-tools/ao-stmload/ao-stmload.1 new file mode 100644 index 00000000..38e9c177 --- /dev/null +++ b/ao-tools/ao-stmload/ao-stmload.1 @@ -0,0 +1,61 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, but +.\" WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +.\" General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License along +.\" with this program; if not, write to the Free Software Foundation, Inc., +.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +.\" +.\" +.TH AO-LOAD 1 "ao-stmload" "" +.SH NAME +ao-stmload \- flash a program to an STM32-based AltOS device +.SH SYNOPSIS +.B "ao-stmload" +[\-D \fI/dev/sgX\fP] +[\--device \fI/dev/sgX\fP] +[\--cal \fIradio-calibration\fP] +[\--serial \fserial-number\fP] +\fIfile.elf\fP +.SH DESCRIPTION +.I ao-stmload +loads the specified .elf file into the target device flash memory, +using either existing serial number and radio calibration values or +taking either of those from the command line. +.SH OPTIONS +.TP +\-D /dev/sgX | --device /dev/sgX +This targets an STlinkV1 connection rather than STlinkV2 +.TP +\-s serial-number | --serial serial-number +This programs the device serial number into the image. If no serial +number is specified, then the existing serial number, if any, will be +read from the device. +.TP +\-c radio-calibration | --cal radio-calibration This programs the +radio calibration value into the image for hardware which doesn't have +any eeprom storage for this value. If no calibration value is +specified, an existing calibration value will be used. The value here +can be computed given the current radio calibration value, the +measured frequency and the desired frequency: +.IP + cal' = cal * (desired/measured) +.IP +The default calibration value is 7119667. +.SH USAGE +.I ao-stmload +reads the specified .elf file into memory, edits the image to +customize it using the specified serial number and radio calibration +values. It then connects to the debug dongle and writes the program to +the target device flash memory. +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-stmload/ao-stmload.c b/ao-tools/ao-stmload/ao-stmload.c new file mode 100644 index 00000000..e689539b --- /dev/null +++ b/ao-tools/ao-stmload/ao-stmload.c @@ -0,0 +1,591 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "stlink-common.h" + +#define AO_USB_DESC_STRING 3 + +struct sym { + unsigned addr; + char *name; + int required; +} ao_symbols[] = { + + { 0, "ao_romconfig_version", 1 }, +#define AO_ROMCONFIG_VERSION (ao_symbols[0].addr) + + { 0, "ao_romconfig_check", 1 }, +#define AO_ROMCONFIG_CHECK (ao_symbols[1].addr) + + { 0, "ao_serial_number", 1 }, +#define AO_SERIAL_NUMBER (ao_symbols[2].addr) + + { 0, "ao_usb_descriptors", 0 }, +#define AO_USB_DESCRIPTORS (ao_symbols[3].addr) + + { 0, "ao_radio_cal", 0 }, +#define AO_RADIO_CAL (ao_symbols[4].addr) +}; + +#define NUM_SYMBOLS 5 +#define NUM_REQUIRED_SYMBOLS 3 + +/* + * Look through the Elf file for the AltOS symbols + * that can be adjusted before the image is written + * to the device + */ +static int +find_symbols (Elf *e) +{ + Elf_Scn *scn; + Elf_Data *symbol_data = NULL; + GElf_Shdr shdr; + GElf_Sym sym; + int i, symbol_count, s; + int required = 0; + char *symbol_name; + + /* + * Find the symbols + */ + + scn = NULL; + while ((scn = elf_nextscn(e, scn)) != NULL) { + if (gelf_getshdr(scn, &shdr) != &shdr) + return 0; + + if (shdr.sh_type == SHT_SYMTAB) { + symbol_data = elf_getdata(scn, NULL); + symbol_count = shdr.sh_size / shdr.sh_entsize; + break; + } + } + + if (!symbol_data) + return 0; + + for (i = 0; i < symbol_count; i++) { + gelf_getsym(symbol_data, i, &sym); + + symbol_name = elf_strptr(e, shdr.sh_link, sym.st_name); + + for (s = 0; s < NUM_SYMBOLS; s++) + if (!strcmp (ao_symbols[s].name, symbol_name)) { + int t; + ao_symbols[s].addr = sym.st_value; + if (ao_symbols[s].required) + ++required; + } + } + + return required >= NUM_REQUIRED_SYMBOLS; +} + +struct load { + uint32_t addr; + uint32_t len; + uint8_t buf[0]; +}; + +struct load * +new_load (uint32_t addr, uint32_t len) +{ + struct load *new = calloc (1, sizeof (struct load) + len); + if (!new) + abort(); + + new->addr = addr; + new->len = len; + return new; +} + +void +load_paste(struct load *into, struct load *from) +{ + if (from->addr < into->addr || into->addr + into->len < from->addr + from->len) + abort(); + + memcpy(into->buf + from->addr - into->addr, from->buf, from->len); +} + +/* + * Make a new load structure large enough to hold the old one and + * the new data + */ +struct load * +expand_load(struct load *from, uint32_t addr, uint32_t len) +{ + struct load *new; + + if (from) { + uint32_t from_last = from->addr + from->len; + uint32_t last = addr + len; + + if (addr > from->addr) + addr = from->addr; + if (last < from_last) + last = from_last; + + len = last - addr; + + if (addr == from->addr && len == from->len) + return from; + } + new = new_load(addr, len); + if (from) { + load_paste(new, from); + free (from); + } + return new; +} + +/* + * Create a new load structure with data from the existing one + * and the new data + */ +struct load * +load_write(struct load *from, uint32_t addr, uint32_t len, void *data) +{ + struct load *new; + + new = expand_load(from, addr, len); + memcpy(new->buf + addr - new->addr, data, len); + return new; +} + +/* + * Construct a large in-memory block for all + * of the loaded sections of the program + */ +static struct load * +get_load(Elf *e) +{ + Elf_Scn *scn; + size_t shstrndx; + GElf_Shdr shdr; + Elf_Data *data; + uint8_t *buf; + char *got_name; + size_t nphdr; + int p; + GElf_Phdr phdr; + struct load *load = NULL; + + if (elf_getshdrstrndx(e, &shstrndx) < 0) + return 0; + + if (elf_getphdrnum(e, &nphdr) < 0) + return 0; + + /* + * As far as I can tell, all of the phdr sections should + * be flashed to memory + */ + for (p = 0; p < nphdr; p++) { + + /* Find this phdr */ + gelf_getphdr(e, p, &phdr); + + /* Get the associated file section */ + scn = gelf_offscn(e, phdr.p_offset); + + if (gelf_getshdr(scn, &shdr) != &shdr) + abort(); + + data = elf_getdata(scn, NULL); + + /* Write the section data into the memory block */ + load = load_write(load, phdr.p_paddr, phdr.p_filesz, data->d_buf); + } + return load; +} + +/* + * Edit the to-be-written memory block + */ +static int +rewrite(struct load *load, unsigned addr, uint8_t *data, int len) +{ + int i; + + if (addr < load->addr || load->addr + load->len < addr + len) + return 0; + + printf("rewrite %04x:", addr); + for (i = 0; i < len; i++) + printf (" %02x", load->buf[addr - load->addr + i]); + printf(" ->"); + for (i = 0; i < len; i++) + printf (" %02x", data[i]); + printf("\n"); + memcpy(load->buf + addr - load->addr, data, len); +} + +/* + * Open the specified ELF file and + * check for the symbols we need + */ + +Elf * +ao_open_elf(char *name) +{ + int fd; + Elf *e; + Elf_Scn *scn; + Elf_Data *symbol_data = NULL; + GElf_Shdr shdr; + GElf_Sym sym; + size_t n, shstrndx, sz; + int i, symbol_count, s; + int required = 0; + + if (elf_version(EV_CURRENT) == EV_NONE) + return NULL; + + fd = open(name, O_RDONLY, 0); + + if (fd < 0) + return NULL; + + e = elf_begin(fd, ELF_C_READ, NULL); + + if (!e) + return NULL; + + if (elf_kind(e) != ELF_K_ELF) + return NULL; + + if (elf_getshdrstrndx(e, &shstrndx) != 0) + return NULL; + + if (!find_symbols(e)) { + fprintf (stderr, "Cannot find required symbols\n"); + return NULL; + } + + return e; +} + +/* + * Read a 32-bit value from the target device with arbitrary + * alignment + */ +static uint32_t +get_uint32(stlink_t *sl, uint32_t addr) +{ + const uint8_t *data = sl->q_buf; + uint32_t actual_addr; + int off; + uint32_t result; + + sl->q_len = 0; + + printf ("read 0x%x\n", addr); + + actual_addr = addr & ~3; + + stlink_read_mem32(sl, actual_addr, 8); + + if (sl->q_len != 8) + abort(); + + off = addr & 3; + result = data[off] | (data[off + 1] << 8) | (data[off+2] << 16) | (data[off+3] << 24); + printf ("read 0x%08x = 0x%08x\n", addr, result); + return result; +} + +/* + * Read a 16-bit value from the target device with arbitrary + * alignment + */ +static uint16_t +get_uint16(stlink_t *sl, uint32_t addr) +{ + const uint8_t *data = sl->q_buf; + uint32_t actual_addr; + int off; + uint16_t result; + + sl->q_len = 0; + + + actual_addr = addr & ~3; + + stlink_read_mem32(sl, actual_addr, 8); + + if (sl->q_len != 8) + abort(); + + off = addr & 3; + result = data[off] | (data[off + 1] << 8); + printf ("read 0x%08x = 0x%04x\n", addr, result); + return result; +} + +/* + * Check to see if the target device has been + * flashed with a similar firmware image before + * + * This is done by looking for the same romconfig version, + * which should be at the same location as the linker script + * places this at 0x100 from the start of the rom section + */ +static int +check_flashed(stlink_t *sl) +{ + uint16_t romconfig_version = get_uint16(sl, AO_ROMCONFIG_VERSION); + uint16_t romconfig_check = get_uint16(sl, AO_ROMCONFIG_CHECK); + + if (romconfig_version != (uint16_t) ~romconfig_check) { + fprintf (stderr, "Device has not been flashed before\n"); + return 0; + } + return 1; +} + +static const struct option options[] = { + { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "cal", .has_arg = 1, .val = 'c' }, + { .name = "serial", .has_arg = 1, .val = 's' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--cal=] [--serial=] file.elf\n", program); + exit(1); +} + +void +done(stlink_t *sl, int code) +{ + if (sl) { + stlink_reset(sl); + stlink_run(sl); + stlink_exit_debug_mode(sl); + stlink_close(sl); + } + exit (code); +} + +int +main (int argc, char **argv) +{ + char *device = NULL; + char *filename; + Elf *e; + char *serial_end; + unsigned int serial = 0; + char *serial_ucs2; + int serial_ucs2_len; + char serial_int[2]; + unsigned int s; + int i; + int string_num; + uint32_t cal = 0; + char cal_int[4]; + char *cal_end; + int c; + stlink_t *sl; + int was_flashed = 0; + struct load *load; + + while ((c = getopt_long(argc, argv, "D:c:s:", options, NULL)) != -1) { + switch (c) { + case 'D': + device = optarg; + break; + case 'c': + cal = strtoul(optarg, &cal_end, 10); + if (cal_end == optarg || *cal_end != '\0') + usage(argv[0]); + break; + case 's': + serial = strtoul(optarg, &serial_end, 10); + if (serial_end == optarg || *serial_end != '\0') + usage(argv[0]); + break; + default: + usage(argv[0]); + break; + } + } + + filename = argv[optind]; + if (filename == NULL) + usage(argv[0]); + + /* + * Open the source file and load the symbols and + * flash data + */ + + e = ao_open_elf(filename); + if (!e) { + fprintf(stderr, "Cannot open file \"%s\"\n", filename); + exit(1); + } + + if (!find_symbols(e)) { + fprintf(stderr, "Cannot find symbols in \"%s\"\n", filename); + exit(1); + } + + if (!(load = get_load(e))) { + fprintf(stderr, "Cannot find program data in \"%s\"\n", filename); + exit(1); + } + + /* Connect to the programming dongle + */ + + if (device) { + sl = stlink_v1_open(50); + } else { + sl = stlink_open_usb(50); + + } + if (!sl) { + fprintf (stderr, "No STLink devices present\n"); + done (sl, 1); + } + + sl->verbose = 50; + + /* Verify that the loaded image fits entirely within device flash + */ + if (load->addr < sl->flash_base || + sl->flash_base + sl->flash_size < load->addr + load->len) { + fprintf (stderr, "\%s\": Invalid memory range 0x%08x - 0x%08x\n", filename, + load->addr, load->addr + load->len); + done(sl, 1); + } + + /* Enter debugging mode + */ + if (stlink_current_mode(sl) == STLINK_DEV_DFU_MODE) + stlink_exit_dfu_mode(sl); + + if (stlink_current_mode(sl) != STLINK_DEV_DEBUG_MODE) + stlink_enter_swd_mode(sl); + + /* Go fetch existing config values + * if available + */ + was_flashed = check_flashed(sl); + + if (!serial) { + if (!was_flashed) { + fprintf (stderr, "Must provide serial number\n"); + done(sl, 1); + } + serial = get_uint16(sl, AO_SERIAL_NUMBER); + if (!serial || serial == 0xffff) { + fprintf (stderr, "Invalid existing serial %d\n", serial); + done(sl, 1); + } + } + + if (!cal && AO_RADIO_CAL && was_flashed) { + cal = get_uint32(sl, AO_RADIO_CAL); + if (!cal || cal == 0xffffffff) { + fprintf (stderr, "Invalid existing rf cal %d\n", cal); + done(sl, 1); + } + } + + /* Write the config values into the flash image + */ + + serial_int[0] = serial & 0xff; + serial_int[1] = (serial >> 8) & 0xff; + + if (!rewrite(load, AO_SERIAL_NUMBER, serial_int, sizeof (serial_int))) { + fprintf(stderr, "Cannot rewrite serial integer at %08x\n", + AO_SERIAL_NUMBER); + done(sl, 1); + } + + if (AO_USB_DESCRIPTORS) { + unsigned usb_descriptors; + usb_descriptors = AO_USB_DESCRIPTORS - load->addr; + string_num = 0; + + while (load->buf[usb_descriptors] != 0 && usb_descriptors < load->len) { + if (load->buf[usb_descriptors+1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + usb_descriptors += load->buf[usb_descriptors]; + } + if (usb_descriptors >= load->len || load->buf[usb_descriptors] == 0 ) { + fprintf(stderr, "Cannot rewrite serial string at %08x\n", AO_USB_DESCRIPTORS); + done(sl, 1); + } + + serial_ucs2_len = load->buf[usb_descriptors] - 2; + serial_ucs2 = malloc(serial_ucs2_len); + if (!serial_ucs2) { + fprintf(stderr, "Malloc(%d) failed\n", serial_ucs2_len); + done(sl, 1); + } + s = serial; + for (i = serial_ucs2_len / 2; i; i--) { + serial_ucs2[i * 2 - 1] = 0; + serial_ucs2[i * 2 - 2] = (s % 10) + '0'; + s /= 10; + } + if (!rewrite(load, usb_descriptors + 2 + load->addr, serial_ucs2, serial_ucs2_len)) { + fprintf (stderr, "Cannot rewrite USB descriptor at %08x\n", AO_USB_DESCRIPTORS); + done(sl, 1); + } + } + + if (cal && AO_RADIO_CAL) { + cal_int[0] = cal & 0xff; + cal_int[1] = (cal >> 8) & 0xff; + cal_int[2] = (cal >> 16) & 0xff; + cal_int[3] = (cal >> 24) & 0xff; + + if (!rewrite(load, AO_RADIO_CAL, cal_int, sizeof (cal_int))) { + fprintf(stderr, "Cannot rewrite radio calibration at %08x\n", AO_RADIO_CAL); + exit(1); + } + } + + /* And flash the resulting image to the device + */ + if (stlink_write_flash(sl, load->addr, load->buf, load->len) < 0) { + fprintf (stderr, "\"%s\": Write failed\n", filename); + done(sl, 1); + } + + done(sl, 0); +} diff --git a/configure.ac b/configure.ac index e78f5873..10bf9abf 100644 --- a/configure.ac +++ b/configure.ac @@ -154,6 +154,7 @@ ao-tools/ao-eeprom/Makefile ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile ao-tools/ao-telem/Makefile +ao-tools/ao-stmload/Makefile ao-utils/Makefile src/Version ]) -- cgit v1.2.3 From a5d873d47b3b16ca32559b4de668bf07b25eddb0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 01:24:52 -0700 Subject: altos: Place STM config values at fixed addresses for re-use Just like cc1111, stick the serial number and radio calibration values at known fixed addresses so that when re-flashing the board, we can go find the existing values. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 2 +- src/avr/ao_arch.h | 6 +++++- src/avr/ao_romconfig.c | 2 +- src/cc1111/ao_arch.h | 10 ++++++---- src/core/ao_product.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_companion.c | 4 +++- src/megametrum-v0.1/Makefile | 2 +- src/megametrum-v0.1/ao_pins.h | 4 ++++ src/stm-bringup/Makefile | 4 ++-- src/stm/altos.ld | 21 +++++++++++---------- src/stm/ao_arch.h | 12 ++++++++++++ src/stm/ao_romconfig.c | 7 ++++++- 13 files changed, 54 insertions(+), 24 deletions(-) diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 1b729d39..e3cef4a5 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -197,7 +197,7 @@ main (int argc, char **argv) serial = strtoul(serial_string, NULL, 0); if (!serial) -(argv[0]); + usage(argv[0]); serial_int[0] = serial & 0xff; serial_int[1] = (serial >> 8) & 0xff; diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c775dab6..a14d0ade 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -67,7 +67,11 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); -extern const uint16_t ao_serial_number; +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) const + +extern AO_ROMCONFIG_SYMBOL(0) uint16_t ao_serial_number; #define AVR_PUSH8(stack, val) (*((stack)--) = (val)) diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c index bbb677e2..ecc19c76 100644 --- a/src/avr/ao_romconfig.c +++ b/src/avr/ao_romconfig.c @@ -17,4 +17,4 @@ #include "ao.h" -const uint16_t ao_serial_number = 0; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8d9e4952..06b04b93 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -59,10 +59,12 @@ #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; +#define AO_ROMCONFIG_SYMBOL(a) __code __at(a) + +extern AO_ROMCONFIG_SYMBOL(0x00a0) uint16_t ao_romconfig_version; +extern AO_ROMCONFIG_SYMBOL(0x00a2) uint16_t ao_romconfig_check; +extern AO_ROMCONFIG_SYMBOL(0x00a4) uint16_t ao_serial_number; +extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #ifndef HAS_USB #error Please define HAS_USB diff --git a/src/core/ao_product.c b/src/core/ao_product.c index 67ec6793..ec91b978 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -29,7 +29,7 @@ const char ao_product[] = AO_iProduct_STRING; #if HAS_USB #include "ao_usb.h" /* USB descriptors in one giant block of bytes */ -__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = { /* Device descriptor */ 0x12, diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 569df3b7..97a434d8 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -29,7 +29,7 @@ uint8_t ao_radio_in_recv; #define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 -const uint32_t ao_radio_cal = 0x6ca333; +extern const uint32_t ao_radio_cal; #define FOSC 32000000 diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 6e0bd2ec..c749adea 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -68,7 +68,7 @@ ao_companion_get_setup(void) ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup), AO_COMPANION_SPI_BUS); COMPANION_DESELECT(); return (ao_companion_setup.board_id == - ~ao_companion_setup.board_id_inverse); + (uint16_t) ~ao_companion_setup.board_id_inverse); } static void @@ -116,6 +116,8 @@ ao_companion_status(void) __reentrant { uint8_t i; printf("Companion running: %d\n", ao_companion_running); + if (!ao_companion_running) + return; printf("device: %d\n", ao_companion_setup.board_id); printf("update period: %d\n", ao_companion_setup.update_period); printf("channels: %d\n", ao_companion_setup.channels); diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a519609e..4a4c983a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -92,7 +92,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -$(PROG): Makefile $(OBJ) +$(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ../altitude.h: make-altitude diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2c438f6c..6b0f9832 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -268,6 +268,10 @@ struct ao_adc { * Radio (cc1120) */ +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + #define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 01c80614..d45e836d 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -16,7 +16,7 @@ DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld -LD_FLAGS=-L../stm -Wl,-Taltos.ld +LD_FLAGS=-L../stm -Wl,-Tbringup.ld CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY @@ -28,7 +28,7 @@ all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJ) $(C_LIB) altos.ld +bringup.elf: $(OBJ) $(C_LIB) bringup.ld $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld diff --git a/src/stm/altos.ld b/src/stm/altos.ld index f5a84f4c..f78a45d6 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -25,18 +25,22 @@ INCLUDE registers.ld EXTERN (stm_interrupt_vector) SECTIONS { - . = ORIGIN(rom); - /* * Rom contents */ - __text_start__ = .; - - .text : { + .text ORIGIN(rom) : { + __text_start__ = .; *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text*) /* Executable code */ *(.rodata*) /* Constants */ + } > rom .ARM.exidx : { @@ -44,12 +48,10 @@ SECTIONS { __text_end__ = .; } > rom - . = ORIGIN(ram); - __data_start__ = .; - /* Data -- relocated to RAM, but written to ROM */ - .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; __bss_start__ = .; @@ -63,7 +65,6 @@ SECTIONS { PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); - } ENTRY(start); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index d8fa3e89..484ce89e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -59,7 +59,19 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const + +extern const uint16_t ao_romconfig_version; +extern const uint16_t ao_romconfig_check; extern const uint16_t ao_serial_number; +extern const uint32_t ao_radio_cal; #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index 84317458..cbb922ec 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -17,4 +17,9 @@ #include "ao.h" -const uint16_t ao_serial_number = 58; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; +#ifdef AO_RADIO_CAL_DEFAULT +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; +#endif -- cgit v1.2.3 From e93c6bcc799d76d4ff425815e2601a25e6796229 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Tue, 17 Jul 2012 13:23:48 -0600 Subject: first work on PWM input to TeleScience, 'p' command displays timer 1 --- src/avr/ao_pwmin.c | 54 +++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_pwmin.h | 18 +++++++++++++++ src/product/ao_telescience.c | 2 ++ src/telescience-v0.1/Makefile | 1 + 4 files changed, 75 insertions(+) create mode 100644 src/avr/ao_pwmin.c create mode 100644 src/avr/ao_pwmin.h diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c new file mode 100644 index 00000000..4d96404d --- /dev/null +++ b/src/avr/ao_pwmin.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwmin.h" + +/* + * This code implements a PWM input using ICP3. + * + * The initial use is to measure wind speed in the ULA/Ball summer intern + * project payload developed at Challenger Middle School. + */ + +static void +ao_pwmin_display(void) __reentrant +{ + uint8_t lo = TCNT1L; + uint8_t hi = TCNT1H; + uint16_t value = (hi <<8) | lo; + + /* now display the value we read */ + printf("timer 1: %5u", value); + +} + +__code struct ao_cmds ao_pwmin_cmds[] = { + { ao_pwmin_display, "p\0PWM input" }, + { 0, NULL }, +}; + +void +ao_pwmin_init(void) +{ + /* do hardware setup here */ + /* set the spike filter bit in the TCCR3B register */ + + ao_cmd_register(&ao_pwmin_cmds[0]); +} + + diff --git a/src/avr/ao_pwmin.h b/src/avr/ao_pwmin.h new file mode 100644 index 00000000..bbab4ddc --- /dev/null +++ b/src/avr/ao_pwmin.h @@ -0,0 +1,18 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * 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. + */ + +void ao_pwmin_init(void); diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 45b6d40e..2d594d7f 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pwmin.h" int main(void) @@ -34,6 +35,7 @@ main(void) ao_usb_init(); ao_adc_init(); ao_log_single_init(); + ao_pwmin_init(); ao_start_scheduler(); return 0; } diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index d24128ef..5542913d 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -53,6 +53,7 @@ ALTOS_SRC = \ ao_adc_avr.c \ ao_science_slave.c \ ao_spi_slave.c \ + ao_pwmin.c \ $(TELESCIENCE_STORAGE)\ $(TELESCIENCE_LOG) -- cgit v1.2.3 From 99b7eaf8d1b312443b842d078fb8464032b3a39b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 20:42:42 -0700 Subject: altoslib: Fix MM conversion functions Pressure is already reported in Pa, no need to convert that. Voltage divider computations were backwards. Signed-off-by: Keith Packard --- altoslib/AltosRecordMM.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/altoslib/AltosRecordMM.java b/altoslib/AltosRecordMM.java index 055cf85f..5f952f7a 100644 --- a/altoslib/AltosRecordMM.java +++ b/altoslib/AltosRecordMM.java @@ -47,7 +47,7 @@ public class AltosRecordMM extends AltosRecord { public double raw_pressure() { if (pres != MISSING) - return pres / 100.0; + return pres; return MISSING; } @@ -57,19 +57,19 @@ public class AltosRecordMM extends AltosRecord { public double ground_pressure() { if (ground_pres != MISSING) - return ground_pres / 100.0; + return ground_pres; return MISSING; } public double battery_voltage() { if (v_batt != MISSING) - return 3.3 * adc(v_batt) * 27.0 / (15.0 + 27.0); + return 3.3 * adc(v_batt) * (15.0 + 27.0) / 27.0; return MISSING; } static double pyro(int raw) { if (raw != MISSING) - return 3.3 * adc(raw) * 27.0 / (100.0 + 27.0); + return 3.3 * adc(raw) * (100.0 + 27.0) / 27.0; return MISSING; } -- cgit v1.2.3 From 97c1cfee929a35dd1596dc02ce519b80132f3c5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 20:43:31 -0700 Subject: altoslib: Don't use MISSING values in max computations Early telemetry state may be missing critical data, don't use MISSING values in computing max ranges. Signed-off-by: Keith Packard --- altoslib/AltosState.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index 68c7611f..e20ec9a7 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -160,7 +160,8 @@ public class AltosState { } ngps++; } - } + } else + pad_alt = ground_altitude; gps_waiting = MIN_PAD_SAMPLES - npad; if (gps_waiting < 0) @@ -173,14 +174,14 @@ public class AltosState { boost = (AltosLib.ao_flight_boost == state); /* Only look at accelerometer data under boost */ - if (boost && acceleration > max_acceleration) + if (boost && acceleration > max_acceleration && acceleration != AltosRecord.MISSING) max_acceleration = acceleration; - if (boost && speed > max_speed) + if (boost && speed > max_speed && speed != AltosRecord.MISSING) max_speed = speed; - if (boost && baro_speed > max_baro_speed) + if (boost && baro_speed > max_baro_speed && baro_speed != AltosRecord.MISSING) max_baro_speed = baro_speed; - if (height > max_height) + if (height > max_height && height != AltosRecord.MISSING) max_height = height; if (data.gps != null) { if (gps == null || !gps.locked || data.gps.locked) -- cgit v1.2.3 From b4be63627e146c7c868b5b3468d34880a561cfba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 20:44:55 -0700 Subject: altos: Megametrum ADC values are 12 bits, discard low 4 for telemetry We've only got space for 8 bits for the ADC values for pyro channels, discard the low 4 bits instead of the low 8 bits. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 583a6636..52ac9489 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -138,9 +138,9 @@ ao_send_mega_data(void) telemetry.mega_data.v_batt = packet->adc.v_batt; telemetry.mega_data.v_pyro = packet->adc.v_pbatt; - /* XXX figure out right shift value; 4 might suffice */ + /* ADC range is 0-4095, so shift by four to save the high 8 bits */ for (i = 0; i < AO_ADC_NUM_SENSE; i++) - telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 4; telemetry.mega_data.ground_pres = ao_ground_pres; telemetry.mega_data.ground_accel = ao_ground_accel; -- cgit v1.2.3 From f6921c9040b1f1fc4408d163532b0695a3611195 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 21:04:23 -0700 Subject: altoslib: Move idle monitor managing code to altoslib More stuff to be shared (potentially) Signed-off-by: Keith Packard --- altoslib/AltosIdleMonitor.java | 445 +++++++++++++++++++++++++++++++++ altoslib/AltosIdleMonitorListener.java | 28 +++ altoslib/AltosIdleRecordTM.java | 268 ++++++++++++++++++++ altoslib/Makefile.am | 2 + altosui/AltosIdleMonitorUI.java | 266 +------------------- 5 files changed, 752 insertions(+), 257 deletions(-) create mode 100644 altoslib/AltosIdleMonitor.java create mode 100644 altoslib/AltosIdleMonitorListener.java create mode 100644 altoslib/AltosIdleRecordTM.java diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java new file mode 100644 index 00000000..cd518c28 --- /dev/null +++ b/altoslib/AltosIdleMonitor.java @@ -0,0 +1,445 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class AltosSensorTM { + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + + public AltosSensorTM(AltosLink link) throws InterruptedException, TimeoutException { + link.printf("a\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("accel:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("pres:")) { + pres = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("temp:")) { + temp = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("drogue:")) { + drogue = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + break; + } + } +} + +class AltosSensorMM { + int tick; + int sense[]; + int v_batt; + int v_pyro; + int accel; + int accel_ref; + + public AltosSensorMM(AltosLink link) throws InterruptedException, TimeoutException { + link.printf("a\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + sense = new int[6]; + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("0:")) { + sense[0] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("1:")) { + sense[1] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("2:")) { + sense[2] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("3:")) { + sense[3] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("4:")) { + sense[4] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("5:")) { + sense[5] = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("6:")) { + v_batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("7:")) { + v_pyro = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("8:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("9:")) { + accel_ref = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + for (int i = 0; i < sense.length; i++) + System.out.printf("sense[%d]: %d\n", i, sense[i]); + break; + } + } +} + +class AltosIMUQuery extends AltosIMU { + + public AltosIMUQuery (AltosLink link) throws InterruptedException, TimeoutException { + link.printf("I\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("Accel:")) + continue; + String[] items = line.split("\\s+"); + if (items.length >= 8) { + accel_x = Integer.parseInt(items[1]); + accel_y = Integer.parseInt(items[2]); + accel_z = Integer.parseInt(items[3]); + gyro_x = Integer.parseInt(items[5]); + gyro_y = Integer.parseInt(items[6]); + gyro_z = Integer.parseInt(items[7]); + } + break; + } + } +} + +class AltosMs5607Query extends AltosMs5607 { + public AltosMs5607Query (AltosLink link) throws InterruptedException, TimeoutException { + link.printf("v\nB\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + String[] items = line.split("\\s+"); + if (line.startsWith("Pressure:")) { + if (items.length >= 2) + raw_pres = Integer.parseInt(items[1]); + } else if (line.startsWith("Temperature:")) { + if (items.length >= 2) + raw_temp = Integer.parseInt(items[1]); + } else if (line.startsWith("ms5607 reserved:")) { + if (items.length >= 3) + reserved = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 sens:")) { + if (items.length >= 3) + sens = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 off:")) { + if (items.length >= 3) + off = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tcs:")) { + if (items.length >= 3) + tcs = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tco:")) { + if (items.length >= 3) + tco = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tref:")) { + if (items.length >= 3) + tref = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 tempsens:")) { + if (items.length >= 3) + tempsens = Integer.parseInt(items[2]); + } else if (line.startsWith("ms5607 crc:")) { + if (items.length >= 3) + crc = Integer.parseInt(items[2]); + } else if (line.startsWith("Altitude")) + break; + } + convert(); + } +} + +class AltosGPSQuery extends AltosGPS { + public AltosGPSQuery (AltosLink link, AltosConfigData config_data) + throws TimeoutException, InterruptedException { + boolean says_done = config_data.compare_version("1.0") >= 0; + link.printf("g\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] bits = line.split("\\s+"); + if (bits.length == 0) + continue; + if (line.startsWith("Date:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split(":"); + if (d.length < 3) + continue; + year = Integer.parseInt(d[0]) + 2000; + month = Integer.parseInt(d[1]); + day = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Time:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split("/"); + if (d.length < 3) + continue; + hour = Integer.parseInt(d[0]); + minute = Integer.parseInt(d[1]); + second = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Lat/Lon:")) { + if (bits.length < 3) + continue; + lat = Integer.parseInt(bits[1]) * 1.0e-7; + lon = Integer.parseInt(bits[2]) * 1.0e-7; + continue; + } + if (line.startsWith("Alt:")) { + if (bits.length < 2) + continue; + alt = Integer.parseInt(bits[1]); + continue; + } + if (line.startsWith("Flags:")) { + if (bits.length < 2) + continue; + int status = Integer.decode(bits[1]); + connected = (status & AltosLib.AO_GPS_RUNNING) != 0; + locked = (status & AltosLib.AO_GPS_VALID) != 0; + if (!says_done) + break; + continue; + } + if (line.startsWith("Sats:")) { + if (bits.length < 2) + continue; + nsat = Integer.parseInt(bits[1]); + cc_gps_sat = new AltosGPSSat[nsat]; + for (int i = 0; i < nsat; i++) { + int svid = Integer.parseInt(bits[2+i*2]); + int cc_n0 = Integer.parseInt(bits[3+i*2]); + cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0); + } + } + if (line.startsWith("done")) + break; + if (line.startsWith("Syntax error")) + break; + } + } +} + +public class AltosIdleMonitor extends Thread { + AltosLink link; + AltosIdleMonitorListener listener; + AltosState state; + boolean remote; + double frequency; + AltosState previous_state; + AltosConfigData config_data; + AltosGPS gps; + + int AltosRSSI() throws TimeoutException, InterruptedException { + link.printf("s\n"); + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + + void update_state() throws InterruptedException, TimeoutException { + AltosRecord record; + int rssi; + + try { + if (remote) { + link.set_radio_frequency(frequency); + link.start_remote(); + } else + link.flush_input(); + config_data = new AltosConfigData(link); + if (config_data.product.startsWith("TeleMetrum")) { + AltosRecordTM record_tm = new AltosRecordTM(); + AltosSensorTM sensor = new AltosSensorTM(link); + record_tm.accel = sensor.accel; + record_tm.pres = sensor.pres; + record_tm.batt = sensor.batt; + record_tm.temp = sensor.temp; + record_tm.drogue = sensor.drogue; + record_tm.main = sensor.main; + record_tm.ground_accel = record_tm.accel; + record_tm.ground_pres = record_tm.pres; + record_tm.accel_plus_g = config_data.accel_cal_plus; + record_tm.accel_minus_g = config_data.accel_cal_minus; + record_tm.tick = sensor.tick; + record = record_tm; + } else if (config_data.product.startsWith("MegaMetrum")) { + AltosRecordMM record_mm = new AltosRecordMM(); + AltosSensorMM sensor = new AltosSensorMM(link); + AltosMs5607 ms5607 = new AltosMs5607Query(link); + AltosIMU imu = new AltosIMUQuery(link); + + record_mm.accel_plus_g = config_data.accel_cal_plus; + record_mm.accel_minus_g = config_data.accel_cal_minus; + + record_mm.ground_accel = sensor.accel; + record_mm.accel = sensor.accel; + record_mm.ground_pres = ms5607.pa; + record_mm.pres = ms5607.pa; + record_mm.temp = ms5607.cc; + + record_mm.v_batt = sensor.v_batt; + record_mm.v_pyro = sensor.v_pyro; + record_mm.sense = sensor.sense; + + record_mm.imu = imu; + + record = record_mm; + } else + record = new AltosRecord(); + + gps = new AltosGPSQuery(link, config_data); + } finally { + if (remote) { + link.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; + } + + record.version = 0; + record.callsign = config_data.callsign; + record.serial = config_data.serial; + record.flight = config_data.log_available() > 0 ? 255 : 0; + record.rssi = rssi; + record.status = 0; + record.state = AltosLib.ao_flight_idle; + + record.gps = gps; + state = new AltosState (record, state); + } + + public void set_frequency(double in_frequency) { + frequency = in_frequency; + } + + public void post_state() { + listener.update(state); + } + + public void run() { + try { + for (;;) { + try { + update_state(); + post_state(); + } catch (TimeoutException te) { + } + Thread.sleep(1000); + } + } catch (InterruptedException ie) { + link.close(); + } + } + + public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) + throws FileNotFoundException, InterruptedException, TimeoutException { + listener = in_listener; + link = in_link; + remote = in_remote; + state = null; + } +} diff --git a/altoslib/AltosIdleMonitorListener.java b/altoslib/AltosIdleMonitorListener.java new file mode 100644 index 00000000..3c18bfaa --- /dev/null +++ b/altoslib/AltosIdleMonitorListener.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +public interface AltosIdleMonitorListener { + public void update(AltosState state); +} \ No newline at end of file diff --git a/altoslib/AltosIdleRecordTM.java b/altoslib/AltosIdleRecordTM.java new file mode 100644 index 00000000..112b847e --- /dev/null +++ b/altoslib/AltosIdleRecordTM.java @@ -0,0 +1,268 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class AltosADCTM { + int tick; + int accel; + int pres; + int temp; + int batt; + int drogue; + int main; + + public AltosADCTM(AltosLink link) throws InterruptedException, TimeoutException { + link.printf("a\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) { + throw new TimeoutException(); + } + if (!line.startsWith("tick:")) + continue; + String[] items = line.split("\\s+"); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("accel:")) { + accel = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("pres:")) { + pres = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("temp:")) { + temp = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("drogue:")) { + drogue = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + break; + } + } +} + +class AltosGPSQuery extends AltosGPS { + public AltosGPSQuery (AltosLink link, AltosConfigData config_data) + throws TimeoutException, InterruptedException { + boolean says_done = config_data.compare_version("1.0") >= 0; + link.printf("g\n"); + for (;;) { + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] bits = line.split("\\s+"); + if (bits.length == 0) + continue; + if (line.startsWith("Date:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split(":"); + if (d.length < 3) + continue; + year = Integer.parseInt(d[0]) + 2000; + month = Integer.parseInt(d[1]); + day = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Time:")) { + if (bits.length < 2) + continue; + String[] d = bits[1].split("/"); + if (d.length < 3) + continue; + hour = Integer.parseInt(d[0]); + minute = Integer.parseInt(d[1]); + second = Integer.parseInt(d[2]); + continue; + } + if (line.startsWith("Lat/Lon:")) { + if (bits.length < 3) + continue; + lat = Integer.parseInt(bits[1]) * 1.0e-7; + lon = Integer.parseInt(bits[2]) * 1.0e-7; + continue; + } + if (line.startsWith("Alt:")) { + if (bits.length < 2) + continue; + alt = Integer.parseInt(bits[1]); + continue; + } + if (line.startsWith("Flags:")) { + if (bits.length < 2) + continue; + int status = Integer.decode(bits[1]); + connected = (status & AltosLib.AO_GPS_RUNNING) != 0; + locked = (status & AltosLib.AO_GPS_VALID) != 0; + if (!says_done) + break; + continue; + } + if (line.startsWith("Sats:")) { + if (bits.length < 2) + continue; + nsat = Integer.parseInt(bits[1]); + cc_gps_sat = new AltosGPSSat[nsat]; + for (int i = 0; i < nsat; i++) { + int svid = Integer.parseInt(bits[2+i*2]); + int cc_n0 = Integer.parseInt(bits[3+i*2]); + cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0); + } + } + if (line.startsWith("done")) + break; + if (line.startsWith("Syntax error")) + break; + } + } +} + +public class AltosIdleMonitor extends Thread { + AltosLink link; + AltosIdleMonitorListener listener; + AltosState state; + boolean remote; + double frequency; + AltosState previous_state; + AltosConfigData config_data; + AltosADC adc; + AltosGPS gps; + + int AltosRSSI() throws TimeoutException, InterruptedException { + link.printf("s\n"); + String line = link.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + + void update_state() throws InterruptedException, TimeoutException { + AltosRecordTM record = new AltosRecordTM(); + int rssi; + + try { + if (remote) { + link.set_radio_frequency(frequency); + link.start_remote(); + } else + link.flush_input(); + config_data = new AltosConfigData(link); + adc = new AltosADC(link); + gps = new AltosGPSQuery(link, config_data); + } finally { + if (remote) { + link.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; + } + + record.version = 0; + record.callsign = config_data.callsign; + record.serial = config_data.serial; + record.flight = config_data.log_available() > 0 ? 255 : 0; + record.rssi = rssi; + record.status = 0; + record.state = AltosLib.ao_flight_idle; + + record.tick = adc.tick; + + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; + record.acceleration = 0; + record.speed = 0; + record.height = 0; + record.gps = gps; + state = new AltosState (record, state); + } + + public void set_frequency(double in_frequency) { + frequency = in_frequency; + } + + public void post_state() { + listener.update(state); + } + + public void run() { + try { + for (;;) { + try { + update_state(); + post_state(); + } catch (TimeoutException te) { + } + Thread.sleep(1000); + } + } catch (InterruptedException ie) { + link.close(); + } + } + + public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) + throws FileNotFoundException, InterruptedException, TimeoutException { + listener = in_listener; + link = in_link; + remote = in_remote; + state = null; + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index ac97c9cb..a39623ee 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -27,6 +27,8 @@ AltosLib_JAVA = \ $(SRC)/AltosGPS.java \ $(SRC)/AltosGPSSat.java \ $(SRC)/AltosGreatCircle.java \ + $(SRC)/AltosIdleMonitor.java \ + $(SRC)/AltosIdleMonitorListener.java \ $(SRC)/AltosLine.java \ $(SRC)/AltosLink.java \ $(SRC)/AltosLog.java \ diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index ce608d2b..46ca3e5d 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -29,260 +29,7 @@ import java.util.prefs.*; import java.util.concurrent.*; import org.altusmetrum.AltosLib.*; -class AltosADC { - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; - - public AltosADC(AltosSerial serial) throws InterruptedException, TimeoutException { - serial.printf("a\n"); - for (;;) { - String line = serial.get_reply_no_dialog(5000); - if (line == null) { - throw new TimeoutException(); - } - if (!line.startsWith("tick:")) - continue; - String[] items = line.split("\\s+"); - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("accel:")) { - accel = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("pres:")) { - pres = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("temp:")) { - temp = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("batt:")) { - batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("drogue:")) { - drogue = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("main:")) { - main = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; - } - break; - } - } -} - -class AltosGPSQuery extends AltosGPS { - public AltosGPSQuery (AltosSerial serial, AltosConfigData config_data) - throws TimeoutException, InterruptedException { - boolean says_done = config_data.compare_version("1.0") >= 0; - serial.printf("g\n"); - for (;;) { - String line = serial.get_reply_no_dialog(5000); - if (line == null) - throw new TimeoutException(); - String[] bits = line.split("\\s+"); - if (bits.length == 0) - continue; - if (line.startsWith("Date:")) { - if (bits.length < 2) - continue; - String[] d = bits[1].split(":"); - if (d.length < 3) - continue; - year = Integer.parseInt(d[0]) + 2000; - month = Integer.parseInt(d[1]); - day = Integer.parseInt(d[2]); - continue; - } - if (line.startsWith("Time:")) { - if (bits.length < 2) - continue; - String[] d = bits[1].split("/"); - if (d.length < 3) - continue; - hour = Integer.parseInt(d[0]); - minute = Integer.parseInt(d[1]); - second = Integer.parseInt(d[2]); - continue; - } - if (line.startsWith("Lat/Lon:")) { - if (bits.length < 3) - continue; - lat = Integer.parseInt(bits[1]) * 1.0e-7; - lon = Integer.parseInt(bits[2]) * 1.0e-7; - continue; - } - if (line.startsWith("Alt:")) { - if (bits.length < 2) - continue; - alt = Integer.parseInt(bits[1]); - continue; - } - if (line.startsWith("Flags:")) { - if (bits.length < 2) - continue; - int status = Integer.decode(bits[1]); - connected = (status & Altos.AO_GPS_RUNNING) != 0; - locked = (status & Altos.AO_GPS_VALID) != 0; - if (!says_done) - break; - continue; - } - if (line.startsWith("Sats:")) { - if (bits.length < 2) - continue; - nsat = Integer.parseInt(bits[1]); - cc_gps_sat = new AltosGPSSat[nsat]; - for (int i = 0; i < nsat; i++) { - int svid = Integer.parseInt(bits[2+i*2]); - int cc_n0 = Integer.parseInt(bits[3+i*2]); - cc_gps_sat[i] = new AltosGPSSat(svid, cc_n0); - } - } - if (line.startsWith("done")) - break; - if (line.startsWith("Syntax error")) - break; - } - } -} - -class AltosIdleMonitor extends Thread { - AltosDevice device; - AltosSerial serial; - AltosIdleMonitorUI ui; - AltosState state; - boolean remote; - double frequency; - AltosState previous_state; - AltosConfigData config_data; - AltosADC adc; - AltosGPS gps; - - int AltosRSSI() throws TimeoutException, InterruptedException { - serial.printf("s\n"); - String line = serial.get_reply_no_dialog(5000); - if (line == null) - throw new TimeoutException(); - String[] items = line.split("\\s+"); - if (items.length < 2) - return 0; - if (!items[0].equals("RSSI:")) - return 0; - int rssi = Integer.parseInt(items[1]); - return rssi; - } - - void update_state() throws InterruptedException, TimeoutException { - AltosRecordTM record = new AltosRecordTM(); - int rssi; - - try { - if (remote) { - serial.set_radio_frequency(frequency); - serial.start_remote(); - } else - serial.flush_input(); - config_data = new AltosConfigData(serial); - adc = new AltosADC(serial); - gps = new AltosGPSQuery(serial, config_data); - } finally { - if (remote) { - serial.stop_remote(); - rssi = AltosRSSI(); - } else - rssi = 0; - } - - record.version = 0; - record.callsign = config_data.callsign; - record.serial = config_data.serial; - record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = rssi; - record.status = 0; - record.state = Altos.ao_flight_idle; - - record.tick = adc.tick; - - record.accel = adc.accel; - record.pres = adc.pres; - record.batt = adc.batt; - record.temp = adc.temp; - record.drogue = adc.drogue; - record.main = adc.main; - - record.ground_accel = record.accel; - record.ground_pres = record.pres; - record.accel_plus_g = config_data.accel_cal_plus; - record.accel_minus_g = config_data.accel_cal_minus; - record.acceleration = 0; - record.speed = 0; - record.height = 0; - record.gps = gps; - state = new AltosState (record, state); - } - - void set_frequency(double in_frequency) { - frequency = in_frequency; - } - - public void post_state() { - Runnable r = new Runnable() { - public void run() { - ui.update(state); - } - }; - SwingUtilities.invokeLater(r); - } - - public void run() { - try { - for (;;) { - try { - update_state(); - post_state(); - } catch (TimeoutException te) { - if (AltosSerial.debug) - System.out.printf ("monitor idle data timeout\n"); - } - Thread.sleep(1000); - } - } catch (InterruptedException ie) { - serial.close(); - } - } - - public AltosIdleMonitor(AltosIdleMonitorUI in_ui, AltosDevice in_device, boolean in_remote) - throws FileNotFoundException, AltosSerialInUseException, InterruptedException, TimeoutException { - device = in_device; - ui = in_ui; - serial = new AltosSerial(device); - remote = in_remote; - state = null; - } -} - -public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener { +public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay, AltosFontListener, AltosIdleMonitorListener { AltosDevice device; JTabbedPane pane; AltosPad pad; @@ -333,8 +80,13 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay } } - public void update(AltosState state) { - show (state, 0); + public void update(final AltosState state) { + Runnable r = new Runnable() { + public void run() { + show(state, 0); + } + }; + SwingUtilities.invokeLater(r); } Container bag; @@ -427,7 +179,7 @@ public class AltosIdleMonitorUI extends AltosFrame implements AltosFlightDisplay pack(); setVisible(true); - thread = new AltosIdleMonitor(this, device, remote); + thread = new AltosIdleMonitor((AltosIdleMonitorListener) this, (AltosLink) new AltosSerial (device), (boolean) remote); status_update = new AltosFlightStatusUpdate(flightStatus); -- cgit v1.2.3 From 700818c8ff0518e79bff2f0e80b2cc3cb3b48bf0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 21:04:58 -0700 Subject: altosui: Accept variations in spacing for igniter status reply Megametrum uses different white space; just deal with it here. Signed-off-by: Keith Packard --- altosui/AltosIgnite.java | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java index 45d37d16..f84db0b9 100644 --- a/altosui/AltosIgnite.java +++ b/altosui/AltosIgnite.java @@ -110,12 +110,23 @@ public class AltosIgnite { String line = serial.get_reply(5000); if (line == null) throw new TimeoutException(); - if (get_string(line, "Igniter: drogue Status: ", status_name)) + String[] items = line.split("\\s+"); + + if (items.length < 4) + continue; + + if (!items[0].equals("Igniter:")) + continue; + + if (!items[2].equals("Status:")) + continue; + + if (items[1].equals("drogue")) { if (igniter == Apogee) - status = status(status_name.get()); - if (get_string(line, "Igniter: main Status: ", status_name)) { + status = status(items[3]); + } else if (items[1].equals("main")) { if (igniter == Main) - status = status(status_name.get()); + status = status(items[3]); break; } } -- cgit v1.2.3 From 9fd5e3c28fb0fd6da8641e7dd18b9912866d1b75 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 21:06:07 -0700 Subject: altos: With debug cables disconnected, CC1120 seems happy at +16dBm Let's see how it goes... Signed-off-by: Keith Packard --- src/drivers/ao_cc1120_CC1120.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 5376afd5..44cca938 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -83,7 +83,7 @@ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ - CC1120_PA_CFG2, 0x04, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ -- cgit v1.2.3 From a698cd68968fc0be5f96b1729cdea2f65d2ccbf6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 23:59:13 -0700 Subject: altos: Toggling telemetry monitoring would replay the telem queue Using the 'm' command to turn telem off and back on would end up going around the whole telemetry queue replaying everything there as the wait loop would exit when disabling monitoring even if the ring was empty. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index d492e32a..5876bef7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -132,6 +132,8 @@ ao_monitor_put(void) ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (!ao_external_monitoring) + continue; m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { -- cgit v1.2.3 From f164e48cbeff521d45737794e2046a08322951d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 18 Jul 2012 00:01:51 -0700 Subject: altosui: Make scan UI handle incremental telem data The new telem format doesn't send everything in each telem packet, so we need to handle updating information incrementally in the scan results. This involved clearing old scan data when switching frequencies and then updating existing entries with new data as it arrives. Signed-off-by: Keith Packard --- altoslib/AltosIdleMonitor.java | 2 -- altoslib/AltosTelemetryReader.java | 5 +++++ altosui/AltosScanUI.java | 42 +++++++++++++++++++++++++++++--------- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index cd518c28..57c4da71 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -162,8 +162,6 @@ class AltosSensorMM { } i++; } - for (int i = 0; i < sense.length; i++) - System.out.printf("sense[%d]: %d\n", i, sense[i]); break; } } diff --git a/altoslib/AltosTelemetryReader.java b/altoslib/AltosTelemetryReader.java index 911a099a..bdb44eef 100644 --- a/altoslib/AltosTelemetryReader.java +++ b/altoslib/AltosTelemetryReader.java @@ -44,6 +44,11 @@ public class AltosTelemetryReader extends AltosFlightReader { telem.clear(); } + public void reset() { + previous = null; + flush(); + } + public void close(boolean interrupted) { link.remove_monitor(telem); log.close(); diff --git a/altosui/AltosScanUI.java b/altosui/AltosScanUI.java index 44eeda6d..ef6389b6 100644 --- a/altosui/AltosScanUI.java +++ b/altosui/AltosScanUI.java @@ -59,29 +59,50 @@ class AltosScanResult { } public boolean equals(AltosScanResult other) { - return (callsign.equals(other.callsign) && - serial == other.serial && - flight == other.flight && + return (serial == other.serial && frequency.frequency == other.frequency.frequency && telemetry == other.telemetry); } + + public boolean up_to_date(AltosScanResult other) { + if (flight == 0 && other.flight != 0) { + flight = other.flight; + return false; + } + if (callsign.equals("N0CALL") && !other.callsign.equals("N0CALL")) { + callsign = other.callsign; + return false; + } + return true; + } } class AltosScanResults extends LinkedList implements ListModel { LinkedList listeners = new LinkedList(); + void changed(ListDataEvent de) { + for (ListDataListener l : listeners) + l.contentsChanged(de); + } + public boolean add(AltosScanResult r) { - for (AltosScanResult old : this) - if (old.equals(r)) + int i = 0; + for (AltosScanResult old : this) { + if (old.equals(r)) { + if (!old.up_to_date(r)) + changed (new ListDataEvent(this, + ListDataEvent.CONTENTS_CHANGED, + i, i)); return true; + } + i++; + } super.add(r); - ListDataEvent de = new ListDataEvent(this, - ListDataEvent.INTERVAL_ADDED, - this.size() - 2, this.size() - 1); - for (ListDataListener l : listeners) - l.contentsChanged(de); + changed(new ListDataEvent(this, + ListDataEvent.INTERVAL_ADDED, + this.size() - 2, this.size() - 1)); return true; } @@ -205,6 +226,7 @@ public class AltosScanUI void set_frequency() throws InterruptedException, TimeoutException { reader.set_frequency(frequencies[frequency_index].frequency); + reader.reset(); } void next() throws InterruptedException, TimeoutException { -- cgit v1.2.3 From b242f2756a8d9419a9bdba890b9e6b73560bdc19 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 18 Jul 2012 00:03:54 -0700 Subject: altosdroid: Start adding an AltosLink subclass for android Will talks over bluetooth while providing an AltosLink APi Signed-off-by: Keith Packard --- .../org/altusmetrum/AltosDroid/AltosBluetooth.java | 191 +++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java new file mode 100644 index 00000000..45438a6c --- /dev/null +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -0,0 +1,191 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosDroid; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothSocket; +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.util.Log; + +import org.altusmetrum.AltosLib.*; + +public class AltosBluetooth extends AltosLink { + + // Debugging + private static final String TAG = "AltosBluetooth"; + private static final boolean D = true; + + /** + * This thread runs while attempting to make an outgoing connection + * with a device. It runs straight through; the connection either + * succeeds or fails. + */ + + private BluetoothAdapter adapter; + private ConnectThread connect_thread; + private BluetoothSocket socket; + private InputStream input; + private OutputStream output; + + private class ConnectThread extends Thread { + private final BluetoothDevice mmDevice; + private String mSocketType; + BluetoothSocket tmp_socket; + + public ConnectThread(BluetoothDevice device, boolean secure) { + mmDevice = device; + mSocketType = secure ? "Secure" : "Insecure"; + + // Get a BluetoothSocket for a connection with the + // given BluetoothDevice + try { + if (secure) { + Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); + tmp_socket = (BluetoothSocket) m.invoke(device, 2); + // tmp = device.createRfcommSocket(2); + } else { + Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class}); + tmp_socket = (BluetoothSocket) m.invoke(device, 2); + // tmp = device.createInsecureRfcommSocket(2); + } + } catch (Exception e) { + Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e); + e.printStackTrace(); + } + } + + public void run() { + Log.i(TAG, "BEGIN connect_thread SocketType:" + mSocketType); + setName("ConnectThread" + mSocketType); + + // Always cancel discovery because it will slow down a connection + adapter.cancelDiscovery(); + + // Make a connection to the BluetoothSocket + try { + // This is a blocking call and will only return on a + // successful connection or an exception + tmp_socket.connect(); + } catch (IOException e) { + // Close the socket + try { + tmp_socket.close(); + } catch (IOException e2) { + Log.e(TAG, "unable to close() " + mSocketType + + " socket during connection failure", e2); + } + connection_failed(); + return; + } + + try { + synchronized (AltosBluetooth.this) { + input = tmp_socket.getInputStream(); + output = tmp_socket.getOutputStream(); + socket = tmp_socket; + // Reset the ConnectThread because we're done + AltosBluetooth.this.notify(); + connect_thread = null; + } + } catch (Exception e) { + Log.e(TAG, "Failed to finish connection", e); + e.printStackTrace(); + } + } + + public void cancel() { + try { + if (tmp_socket != null) + tmp_socket.close(); + } catch (IOException e) { + Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e); + } + } + } + + private synchronized void wait_connected() throws InterruptedException { + if (input == null) { + wait(); + } + } + + private void connection_failed() { + } + + public void print(String data) { + byte[] bytes = data.getBytes(); + try { + wait_connected(); + output.write(bytes); + } catch (IOException e) { + connection_failed(); + } catch (InterruptedException e) { + connection_failed(); + } + } + + public int getchar() { + try { + wait_connected(); + return input.read(); + } catch (IOException e) { + connection_failed(); + } catch (java.lang.InterruptedException e) { + connection_failed(); + } + return AltosLink.ERROR; + } + + public void close() { + synchronized(this) { + if (connect_thread != null) { + connect_thread.cancel(); + connect_thread = null; + } + } + } + + public void flush_output() { + super.flush_output(); + /* any local work needed to flush bluetooth? */ + } + + public boolean can_cancel_reply() { + return false; + } + public boolean show_reply_timeout() { + return true; + } + + public void hide_reply_timeout() { + } + + public AltosBluetooth(BluetoothDevice device) { + adapter = BluetoothAdapter.getDefaultAdapter(); + connect_thread = new ConnectThread(device, true); + connect_thread.start(); + } +} \ No newline at end of file -- cgit v1.2.3 From 49b1ff4c614d24977b33cd17b583acc87acff476 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 13:41:27 -0600 Subject: Timer 3 working with slower clock and all 16 bits. --- src/avr/ao_pwmin.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 4d96404d..edcb1636 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,6 +25,8 @@ * project payload developed at Challenger Middle School. */ +volatile __data uint16_t ao_tick3_count; + static void ao_pwmin_display(void) __reentrant { @@ -32,10 +34,19 @@ ao_pwmin_display(void) __reentrant uint8_t hi = TCNT1H; uint16_t value = (hi <<8) | lo; + uint8_t lo3 = TCNT3L; + uint8_t hi3 = TCNT3H; + uint16_t value3 = (hi3 <<8) | lo3; + /* now display the value we read */ - printf("timer 1: %5u", value); + printf("timer 1: %5u %2x %2x\n", value, hi, lo); + printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); } +ISR(TIMER3_COMPA_vect) +{ + ++ao_tick3_count; +} __code struct ao_cmds ao_pwmin_cmds[] = { { ao_pwmin_display, "p\0PWM input" }, @@ -46,6 +57,18 @@ void ao_pwmin_init(void) { /* do hardware setup here */ + TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ + (0 << WGM30)); /* normal mode, OCR3A */ + TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ + (0 << ICES3) | /* input capture on falling edge (don't care) */ + (0 << WGM33) | /* normal mode, OCR3A */ + (0 << WGM32) | /* normal mode, OCR3A */ + (4 << CS30)); /* clk/256 from prescaler */ + + OCR3A = 1250; /* 8MHz clock */ + + TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ + /* set the spike filter bit in the TCCR3B register */ ao_cmd_register(&ao_pwmin_cmds[0]); -- cgit v1.2.3 From 75d6aa6f798606f1a6c5a46542065dda81e63b2a Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 14:24:05 -0600 Subject: ICP3 working --- src/avr/ao_pwmin.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index edcb1636..73a153b2 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,27 +25,20 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_tick3_count; +volatile __data uint16_t ao_icp3_count; static void ao_pwmin_display(void) __reentrant { - uint8_t lo = TCNT1L; - uint8_t hi = TCNT1H; - uint16_t value = (hi <<8) | lo; - - uint8_t lo3 = TCNT3L; - uint8_t hi3 = TCNT3H; - uint16_t value3 = (hi3 <<8) | lo3; - - /* now display the value we read */ - printf("timer 1: %5u %2x %2x\n", value, hi, lo); - printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); + /* display the most recent value */ + printf("icp 3: %5u\n", ao_icp3_count); } -ISR(TIMER3_COMPA_vect) +ISR(TIMER3_CAPT_vect) { - ++ao_tick3_count; + uint8_t lo = ICR3L; + uint8_t hi = ICR3H; + ao_icp3_count = (hi <<8) | lo; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -59,15 +52,15 @@ ao_pwmin_init(void) /* do hardware setup here */ TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ (0 << WGM30)); /* normal mode, OCR3A */ - TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ + TCCR3B = ((1 << ICNC3) | /* input capture noise canceler on */ (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ (4 << CS30)); /* clk/256 from prescaler */ - OCR3A = 1250; /* 8MHz clock */ + - TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ + TIMSK3 = (1 << ICIE3); /* Interrupt on input compare */ /* set the spike filter bit in the TCCR3B register */ -- cgit v1.2.3 From ada6f2dfc045e77cb9499f20cdec1b4a54ef0db1 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 18:41:00 -0600 Subject: telescience: correctly calculating rate values with higher resolution --- src/avr/ao_pwmin.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 73a153b2..84397357 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,20 +25,40 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_icp3_count; +volatile __data uint16_t ao_icp3_count = 0; +volatile __data uint16_t ao_icp3_last = 0; + +uint16_t ao_icp3(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_icp3_count; + ); + return v; +} static void ao_pwmin_display(void) __reentrant { /* display the most recent value */ - printf("icp 3: %5u\n", ao_icp3_count); + printf("icp 3: %5u\n", ao_icp3()); } + + ISR(TIMER3_CAPT_vect) { + uint8_t lo = ICR3L; uint8_t hi = ICR3H; - ao_icp3_count = (hi <<8) | lo; + uint16_t ao_icp3_this = (hi <<8) | lo; + + /* handling counter rollovers */ + if (ao_icp3_this >= ao_icp3_last) + ao_icp3_count = ao_icp3_this - ao_icp3_last; + else + ao_icp3_count = ao_icp3_this + (65536 - ao_icp3_last); + ao_icp3_last = ao_icp3_this; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -56,7 +76,7 @@ ao_pwmin_init(void) (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ - (4 << CS30)); /* clk/256 from prescaler */ + (3 << CS30)); /* clk/64 from prescaler */ -- cgit v1.2.3 From 15ebd9c75aa57572040e3b1ee41e6f3eb8cf92ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 19 Jul 2012 09:46:20 -0700 Subject: altosui: Delay starting KML output for flight and GPS coords Don't start outputing KML data until the telem record containing flight number and GPS coordinates are present. Signed-off-by: Keith Packard --- altosui/AltosKML.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/altosui/AltosKML.java b/altosui/AltosKML.java index 2993607b..ff0734b8 100644 --- a/altosui/AltosKML.java +++ b/altosui/AltosKML.java @@ -133,6 +133,12 @@ public class AltosKML implements AltosWriter { if (gps == null) return; + if ((record.seen & (AltosRecord.seen_flight)) == 0) + return; + if ((record.seen & (AltosRecord.seen_gps_lat)) == 0) + return; + if ((record.seen & (AltosRecord.seen_gps_lon)) == 0) + return; if (!started) { start(record); started = true; -- cgit v1.2.3 From e033a72d3f420e18ed24354c7dfc7e1317a03fb6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jul 2012 11:08:22 -0700 Subject: Add stlink pinout Signed-off-by: Keith Packard --- src/megametrum-v0.1/stlink-pins | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/megametrum-v0.1/stlink-pins diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins new file mode 100644 index 00000000..71042acc --- /dev/null +++ b/src/megametrum-v0.1/stlink-pins @@ -0,0 +1,41 @@ + ST discovery card pins + +1 AIN-1 +2 JTCK +3 GND +4 JTMS +5 NRST +6 SWO + +MM misc connector + +1 GND +2 reset_n +3 boot0 +4 tx1 +5 rx1 +6 +3.3V +7 GND +8 jtms +9 jtck +10 jtdi +11 jtdo +12 jntrst +13 sda2 +14 scl2 +15 pe1 +16 pe0 + +For debugging: + + ST MM +JTCK 2 9 +GND 3 7 +JTMS 4 8 +NRST 5 2 + +MegaAccel: + +Jumpers +PC0 (pin15) (blue) PE0 (pin97) accel_ref (debug 16) +PC1 (pin16) (green) PE1 (pin98) accel (debug 15) -- cgit v1.2.3 From 38f66a31174dd367e39d717c527f555add60a9d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jul 2012 12:04:17 -0700 Subject: tools: Use pkgconfig to find stlink for ao-stmload Signed-off-by: Keith Packard --- ao-tools/ao-stmload/Makefile.am | 7 ++----- configure.ac | 5 +++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am index 77979daf..375896ea 100644 --- a/ao-tools/ao-stmload/Makefile.am +++ b/ao-tools/ao-stmload/Makefile.am @@ -2,12 +2,9 @@ bin_PROGRAMS=ao-stmload LIBSTLINKDIR=/local/src/stlink -AM_CFLAGS=-I$(LIBSTLINKDIR)/src $(LIBUSB_CFLAGS) -I../lib +AM_CFLAGS=$(LIBSTLINK_CFLAGS) $(LIBUSB_CFLAGS) -I../lib -AO_STMLOAD_LIBS=$(LIBSTLINKDIR)/libstlink.a -ao_stmload_DEPENDENCIES = $(AO_STMLOAD_LIBS) - -ao_stmload_LDADD=$(AO_STMLOAD_LIBS) $(LIBUSB_LIBS) -lelf +ao_stmload_LDADD=$(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf ao_stmload_SOURCES=ao-stmload.c diff --git a/configure.ac b/configure.ac index 10bf9abf..bcd2dcac 100644 --- a/configure.ac +++ b/configure.ac @@ -136,6 +136,11 @@ AC_CHECK_LIB(readline, readline) PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) +AC_CHECK_HEADERS(libelf.h libelf/libelf.h, [break]) +AC_CHECK_HEADERS(gelf.h libelf/gelf.h, [break]) + +PKG_CHECK_MODULES([LIBSTLINK], [stlink]) + AC_OUTPUT([ Makefile altoslib/Makefile -- cgit v1.2.3 From 233ab58df8ac8e1fdeab8d4c2f6c8c9d3f6e7be1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Jul 2012 11:53:44 -0700 Subject: altosui: Move AltosIgnite.java to altoslib To be shared with altosdroid eventually Signed-off-by: Keith Packard --- altoslib/AltosIgnite.java | 180 +++++++++++++++++++++++++++++++++++++++++ altoslib/Makefile.am | 1 + altosui/AltosIgnite.java | 195 --------------------------------------------- altosui/AltosIgniteUI.java | 7 +- altosui/Makefile.am | 1 - 5 files changed, 186 insertions(+), 198 deletions(-) create mode 100644 altoslib/AltosIgnite.java delete mode 100644 altosui/AltosIgnite.java diff --git a/altoslib/AltosIgnite.java b/altoslib/AltosIgnite.java new file mode 100644 index 00000000..cc814337 --- /dev/null +++ b/altoslib/AltosIgnite.java @@ -0,0 +1,180 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.AltosLib; + +import java.io.*; +import java.util.concurrent.*; + +public class AltosIgnite { + AltosLink link; + boolean remote; + boolean link_started; + + public final static int None = 0; + public final static int Apogee = 1; + public final static int Main = 2; + + public final static int Unknown = 0; + public final static int Ready = 1; + public final static int Active = 2; + public final static int Open = 3; + + private void start_link() throws InterruptedException, TimeoutException { + link_started = true; + if (remote) + link.start_remote(); + } + + private void stop_link() throws InterruptedException { + if (!link_started) + return; + link_started = false; + if (link == null) + return; + if (remote) + link.stop_remote(); + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + private int status(String status_name) { + if (status_name.equals("unknown")) + return Unknown; + if (status_name.equals("ready")) + return Ready; + if (status_name.equals("active")) + return Active; + if (status_name.equals("open")) + return Open; + return Unknown; + } + + public int status(int igniter) throws InterruptedException, TimeoutException { + int status = Unknown; + if (link == null) + return status; + string_ref status_name = new string_ref(); + try { + start_link(); + link.printf("t\n"); + for (;;) { + String line = link.get_reply(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + + if (items.length < 4) + continue; + + if (!items[0].equals("Igniter:")) + continue; + + if (!items[2].equals("Status:")) + continue; + + if (items[1].equals("drogue")) { + if (igniter == Apogee) + status = status(items[3]); + } else if (items[1].equals("main")) { + if (igniter == Main) + status = status(items[3]); + break; + } + } + } finally { + stop_link(); + } + return status; + } + + public static String status_string(int status) { + switch (status) { + case Unknown: return "Unknown"; + case Ready: return "Ready"; + case Active: return "Active"; + case Open: return "Open"; + default: return "Unknown"; + } + } + + public void fire(int igniter) { + if (link == null) + return; + try { + start_link(); + switch (igniter) { + case Main: + link.printf("i DoIt main\n"); + break; + case Apogee: + link.printf("i DoIt drogue\n"); + break; + } + } catch (InterruptedException ie) { + } catch (TimeoutException te) { + } finally { + try { + stop_link(); + } catch (InterruptedException ie) { + } + } + } + + public void close() { + try { + stop_link(); + } catch (InterruptedException ie) { + } + link.close(); + link = null; + } + + public AltosIgnite(AltosLink in_link, boolean in_remote) + throws FileNotFoundException, TimeoutException, InterruptedException { + + link = in_link; + remote = in_remote; + } +} \ No newline at end of file diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index a39623ee..1f42140b 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -29,6 +29,7 @@ AltosLib_JAVA = \ $(SRC)/AltosGreatCircle.java \ $(SRC)/AltosIdleMonitor.java \ $(SRC)/AltosIdleMonitorListener.java \ + $(SRC)/AltosIgnite.java \ $(SRC)/AltosLine.java \ $(SRC)/AltosLink.java \ $(SRC)/AltosLog.java \ diff --git a/altosui/AltosIgnite.java b/altosui/AltosIgnite.java deleted file mode 100644 index f84db0b9..00000000 --- a/altosui/AltosIgnite.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 java.util.concurrent.*; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.filechooser.FileNameExtensionFilter; -import javax.swing.table.*; -import javax.swing.event.*; -import org.altusmetrum.AltosLib.*; - -public class AltosIgnite { - AltosDevice device; - AltosSerial serial; - boolean remote; - boolean serial_started; - final static int None = 0; - final static int Apogee = 1; - final static int Main = 2; - - final static int Unknown = 0; - final static int Ready = 1; - final static int Active = 2; - final static int Open = 3; - - private void start_serial() throws InterruptedException, TimeoutException { - serial_started = true; - if (remote) - serial.start_remote(); - } - - private void stop_serial() throws InterruptedException { - if (!serial_started) - return; - serial_started = false; - if (serial == null) - return; - if (remote) - serial.stop_remote(); - } - - class string_ref { - String value; - - public String get() { - return value; - } - public void set(String i) { - value = i; - } - public string_ref() { - value = null; - } - } - - private boolean get_string(String line, String label, string_ref s) { - if (line.startsWith(label)) { - String quoted = line.substring(label.length()).trim(); - - if (quoted.startsWith("\"")) - quoted = quoted.substring(1); - if (quoted.endsWith("\"")) - quoted = quoted.substring(0,quoted.length()-1); - s.set(quoted); - return true; - } else { - return false; - } - } - - private int status(String status_name) { - if (status_name.equals("unknown")) - return Unknown; - if (status_name.equals("ready")) - return Ready; - if (status_name.equals("active")) - return Active; - if (status_name.equals("open")) - return Open; - return Unknown; - } - - public int status(int igniter) throws InterruptedException, TimeoutException { - int status = Unknown; - if (serial == null) - return status; - string_ref status_name = new string_ref(); - try { - start_serial(); - serial.printf("t\n"); - for (;;) { - String line = serial.get_reply(5000); - if (line == null) - throw new TimeoutException(); - String[] items = line.split("\\s+"); - - if (items.length < 4) - continue; - - if (!items[0].equals("Igniter:")) - continue; - - if (!items[2].equals("Status:")) - continue; - - if (items[1].equals("drogue")) { - if (igniter == Apogee) - status = status(items[3]); - } else if (items[1].equals("main")) { - if (igniter == Main) - status = status(items[3]); - break; - } - } - } finally { - stop_serial(); - } - return status; - } - - public static String status_string(int status) { - switch (status) { - case Unknown: return "Unknown"; - case Ready: return "Ready"; - case Active: return "Active"; - case Open: return "Open"; - default: return "Unknown"; - } - } - - public void fire(int igniter) { - if (serial == null) - return; - try { - start_serial(); - switch (igniter) { - case Main: - serial.printf("i DoIt main\n"); - break; - case Apogee: - serial.printf("i DoIt drogue\n"); - break; - } - } catch (InterruptedException ie) { - } catch (TimeoutException te) { - } finally { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - } - } - - public void close() { - try { - stop_serial(); - } catch (InterruptedException ie) { - } - serial.close(); - serial = null; - } - - public void set_frame(Frame frame) { - serial.set_frame(frame); - } - - public AltosIgnite(AltosDevice in_device) - throws FileNotFoundException, AltosSerialInUseException, TimeoutException, InterruptedException { - - device = in_device; - serial = new AltosSerial(device); - remote = false; - - if (!device.matchProduct(Altos.product_altimeter)) - remote = true; - } -} \ No newline at end of file diff --git a/altosui/AltosIgniteUI.java b/altosui/AltosIgniteUI.java index 076d99b2..78eba8e6 100644 --- a/altosui/AltosIgniteUI.java +++ b/altosui/AltosIgniteUI.java @@ -72,12 +72,15 @@ public class AltosIgniteUI public void run () { try { - ignite = new AltosIgnite(device); + AltosSerial serial = new AltosSerial(device); + serial.set_frame(owner); + ignite = new AltosIgnite(serial, + !device.matchProduct(Altos.product_altimeter)); + } catch (Exception e) { send_exception(e); return; } - ignite.set_frame(owner); for (;;) { Runnable r; diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 1c8ea491..19db6698 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -55,7 +55,6 @@ altosui_JAVA = \ AltosHexfile.java \ Altos.java \ AltosIdleMonitorUI.java \ - AltosIgnite.java \ AltosIgniteUI.java \ AltosLaunch.java \ AltosLaunchUI.java \ -- cgit v1.2.3 From 52e920bc7a98edf5c6f2ad0bd59d581011dcd5c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Jul 2012 15:18:27 -0700 Subject: altos: Move ao_radio_cmac.c to core (it doesn't depend on hardware) Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 406 ----------------------------------------------- src/core/ao_radio_cmac.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+), 406 deletions(-) delete mode 100644 src/ao_radio_cmac.c create mode 100644 src/core/ao_radio_cmac.c diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c deleted file mode 100644 index e263f0db..00000000 --- a/src/ao_radio_cmac.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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" - -#define AO_CMAC_KEY_LEN AO_AES_LEN -#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) - -static __xdata uint8_t ao_radio_cmac_mutex; -__pdata int16_t ao_radio_cmac_rssi; -static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; -static __pdata uint8_t ao_radio_cmac_len; - -static uint8_t -getnibble(void) -{ - int8_t b; - - b = ao_cmd_hexchar(getchar()); - if (b < 0) { - ao_cmd_status = ao_cmd_lex_error; - return 0; - } - return (uint8_t) b; -} - -static uint8_t -getbyte(void) -{ - uint8_t b; - b = getnibble() << 4; - b |= getnibble(); - return b; -} - -static uint8_t -round_len(uint8_t len) -{ - uint8_t rem; - - /* Make sure we transfer at least one packet, and - * then make sure every packet is full. Note that - * there is no length encoded, and that the receiver - * must deal with any extra bytes in the packet - */ - if (len < AO_CMAC_KEY_LEN) - len = AO_CMAC_KEY_LEN; - rem = len % AO_CMAC_KEY_LEN; - if (rem != 0) - len += (AO_CMAC_KEY_LEN - rem); - return len; -} - -/* - * Sign and deliver the data sitting in the cmac buffer - */ -static void -radio_cmac_send(uint8_t len) __reentrant -{ - uint8_t i; - - len = round_len(len); - /* Make sure the AES key is loaded */ - ao_config_get(); - -#if HAS_MONITOR - ao_monitor_set(0); -#endif - - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(ao_config.aes_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len]); - } - ao_mutex_put(&ao_aes_mutex); - - ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); -} - -/* - * Receive and validate an incoming packet - */ - -static int8_t -radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant -{ - uint8_t i; - - len = round_len(len); -#if HAS_MONITOR - ao_monitor_set(0); -#endif - if (timeout) - ao_alarm(timeout); - - i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); - ao_clear_alarm(); - - if (!i) { - ao_radio_cmac_rssi = 0; - return AO_RADIO_CMAC_TIMEOUT; - } - - ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) - return AO_RADIO_CMAC_CRC_ERROR; - - ao_config_get(); - - /* Compute the packet signature - */ - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(ao_config.aes_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); - } - ao_mutex_put(&ao_aes_mutex); - - /* Check the packet signature against the signature provided - * over the link - */ - - if (memcmp(&cmac_data[len], - &cmac_data[len + AO_CMAC_KEY_LEN + 2], - AO_CMAC_KEY_LEN) != 0) { - return AO_RADIO_CMAC_MAC_ERROR; - } - - return AO_RADIO_CMAC_OK; -} - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant -{ - if (len > AO_CMAC_MAX_LEN) - return AO_RADIO_CMAC_LEN_ERROR; - ao_mutex_get(&ao_radio_cmac_mutex); - memcpy(cmac_data, packet, len); - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); - return AO_RADIO_CMAC_OK; -} - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant -{ - uint8_t i; - if (len > AO_CMAC_MAX_LEN) - return AO_RADIO_CMAC_LEN_ERROR; - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) - memcpy(packet, cmac_data, len); - ao_mutex_put(&ao_radio_cmac_mutex); - return i; -} - -static void -radio_cmac_send_cmd(void) __reentrant -{ - uint8_t i; - uint8_t len; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - if (len > AO_CMAC_MAX_LEN) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - flush(); - ao_mutex_get(&ao_radio_cmac_mutex); - len = ao_cmd_lex_i; - for (i = 0; i < len; i++) { - cmac_data[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; - } - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static void -radio_cmac_recv_cmd(void) __reentrant -{ - uint8_t len, i; - uint16_t timeout; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) { - printf ("PACKET "); - for (i = 0; i < len; i++) - printf("%02x", cmac_data[i]); - printf (" %d\n", ao_radio_cmac_rssi); - } else - printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static pdata uint16_t launch_serial; -static pdata uint8_t launch_channel; -static pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_radio_cmac_init(void) -{ - ao_cmd_register(&ao_radio_cmac_cmds[0]); -} diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c new file mode 100644 index 00000000..e263f0db --- /dev/null +++ b/src/core/ao_radio_cmac.c @@ -0,0 +1,406 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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" + +#define AO_CMAC_KEY_LEN AO_AES_LEN +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t ao_radio_cmac_mutex; +__pdata int16_t ao_radio_cmac_rssi; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; +static __pdata uint8_t ao_radio_cmac_len; + +static uint8_t +getnibble(void) +{ + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; +} + +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + +static uint8_t +round_len(uint8_t len) +{ + uint8_t rem; + + /* Make sure we transfer at least one packet, and + * then make sure every packet is full. Note that + * there is no length encoded, and that the receiver + * must deal with any extra bytes in the packet + */ + if (len < AO_CMAC_KEY_LEN) + len = AO_CMAC_KEY_LEN; + rem = len % AO_CMAC_KEY_LEN; + if (rem != 0) + len += (AO_CMAC_KEY_LEN - rem); + return len; +} + +/* + * Sign and deliver the data sitting in the cmac buffer + */ +static void +radio_cmac_send(uint8_t len) __reentrant +{ + uint8_t i; + + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_monitor_set(0); +#endif + + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len]); + } + ao_mutex_put(&ao_aes_mutex); + + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); +} + +/* + * Receive and validate an incoming packet + */ + +static int8_t +radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + + len = round_len(len); +#if HAS_MONITOR + ao_monitor_set(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) { + ao_radio_cmac_rssi = 0; + return AO_RADIO_CMAC_TIMEOUT; + } + + ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + return AO_RADIO_CMAC_CRC_ERROR; + + ao_config_get(); + + /* Compute the packet signature + */ + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + ao_mutex_put(&ao_aes_mutex); + + /* Check the packet signature against the signature provided + * over the link + */ + + if (memcmp(&cmac_data[len], + &cmac_data[len + AO_CMAC_KEY_LEN + 2], + AO_CMAC_KEY_LEN) != 0) { + return AO_RADIO_CMAC_MAC_ERROR; + } + + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; +} + +static void +radio_cmac_send_cmd(void) __reentrant +{ + uint8_t i; + uint8_t len; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + flush(); + ao_mutex_get(&ao_radio_cmac_mutex); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); + if (ao_cmd_status != ao_cmd_success) + return; + } + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static void +radio_cmac_recv_cmd(void) __reentrant +{ + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf (" %d\n", ao_radio_cmac_rssi); + } else + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static pdata uint16_t launch_serial; +static pdata uint8_t launch_channel; +static pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); +} -- cgit v1.2.3 From 59588ba34159b27c02e1a886b46497ecfa0cf4d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 16:22:23 -0700 Subject: Add ability to re-play telemetry through TeleDongle This adds a new command to TeleDongle to send arbitrary data, and then creates a new tool, 'ao-send-telem' that replays existing telemetry files through TeleDongle. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-send-telem/Makefile.am | 12 ++ ao-tools/ao-send-telem/ao-send-telem.1 | 64 +++++++++ ao-tools/ao-send-telem/ao-send-telem.c | 238 +++++++++++++++++++++++++++++++++ configure.ac | 1 + src/core/ao_send_packet.c | 74 ++++++++++ src/core/ao_send_packet.h | 24 ++++ src/product/Makefile.teledongle | 1 + src/product/ao_teledongle.c | 2 + 9 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 ao-tools/ao-send-telem/Makefile.am create mode 100644 ao-tools/ao-send-telem/ao-send-telem.1 create mode 100644 ao-tools/ao-send-telem/ao-send-telem.c create mode 100644 src/core/ao_send_packet.c create mode 100644 src/core/ao_send_packet.h diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 6c315dd1..257fdaec 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload ao-send-telem diff --git a/ao-tools/ao-send-telem/Makefile.am b/ao-tools/ao-send-telem/Makefile.am new file mode 100644 index 00000000..bfddf131 --- /dev/null +++ b/ao-tools/ao-send-telem/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-send-telem + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_send_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_send_telem_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) + +ao_send_telem_SOURCES = ao-send-telem.c + +man_MANS = ao-send-telem.1 diff --git a/ao-tools/ao-send-telem/ao-send-telem.1 b/ao-tools/ao-send-telem/ao-send-telem.1 new file mode 100644 index 00000000..fbdb2fe9 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.1 @@ -0,0 +1,64 @@ +.\" +.\" Copyright © 2009 Keith Packard +.\" +.\" 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-SEND-TELEM 1 "ao-send-telem" "" +.SH NAME +ao-send-telem \- Re-transmit stored telemetry file +.SH SYNOPSIS +.B "ao-send-telem" +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] +[\-F \fIfrequency (kHz)\fP] +[\--frequency \fIfrequency (kHz)\fP] +[\-R] +[\--realtime] + +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device ao-dumplog uses to communicate with +the target device. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleDongle:2 +.br +TeleDongle +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. +.TP +\-F kHz | --frequency kHz +This selects which frequency to send the specified packets on. +.TP +\-R | --realtime +This makes the program delay between packets in pad mode. Normally, +pad mode packets are sent as quickly as possible. +.SH DESCRIPTION +.I ao-send-telem +reads the specified flight telemetry log and re-transmits it via the +specified ground station device +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c new file mode 100644 index 00000000..c4c354e0 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.c @@ -0,0 +1,238 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cc.h" +#include "cc-usb.h" + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "frequency", .has_arg = 1, .val = 'F' }, + { .name = "realtime", .has_arg = 0, .val = 'R' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ] [--device ] [--frequency ] [--realtime] file.telem ...\n", program); + exit(1); +} + +#define bool(b) ((b) ? "true" : "false") + +struct ao_telem_list { + struct ao_telem_list *next; + union ao_telemetry_all telem; +}; + +static struct ao_telem_list *telem_list, **telem_last; + +static void +trim_telem(uint16_t time) +{ + while (telem_list && (int16_t) (time - telem_list->telem.generic.tick) > 0) { + struct ao_telem_list *next = telem_list->next; + free(telem_list); + telem_list = next; + } + if (!telem_list) + telem_last = &telem_list; +} + +static void +add_telem(union ao_telemetry_all *telem) +{ + struct ao_telem_list *new = malloc (sizeof (struct ao_telem_list)); + trim_telem((uint16_t) (telem->generic.tick - 20 * 100)); + new->telem = *telem; + new->next = 0; + *telem_last = new; + telem_last = &new->next; +} + +static enum ao_flight_state cur_state = ao_flight_invalid; +static enum ao_flight_state last_state = ao_flight_invalid; + +static enum ao_flight_state +packet_state(union ao_telemetry_all *telem) +{ + switch (telem->generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + cur_state = telem->sensor.state; + break; + case AO_TELEMETRY_MEGA_DATA: + cur_state = telem->mega_data.state; + break; + } + return cur_state; +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static void +send_telem(struct cc_usb *cc, union ao_telemetry_all *telem) +{ + int rssi = (int8_t) telem->generic.rssi / 2 - 74; + int i; + uint8_t *b; + + packet_state(telem); + if (cur_state != last_state) { + if (0 <= cur_state && cur_state < sizeof(state_names) / sizeof (state_names[0])) + printf ("%s\n", state_names[cur_state]); + last_state = cur_state; + } + cc_usb_printf(cc, "S 20\n"); + b = (uint8_t *) telem; + for (i = 0; i < 0x20; i++) + cc_usb_printf(cc, "%02x", b[i]); + cc_usb_sync(cc); +} + +static void +do_delay(uint16_t now, uint16_t then) +{ + int16_t delay = (int16_t) (now - then); + + if (delay > 0 && delay < 1000) + usleep(delay * 10 * 1000); +} + +static uint16_t +send_queued(struct cc_usb *cc, int pause) +{ + struct ao_telem_list *next; + uint16_t tick = 0; + int started = 0; + + while (telem_list) { + if (started && pause) + do_delay(telem_list->telem.generic.tick, tick); + tick = telem_list->telem.generic.tick; + started = 1; + send_telem(cc, &telem_list->telem); + + next = telem_list->next; + free(telem_list); + telem_list = next; + } + return tick; +} + +int +main (int argc, char **argv) +{ + struct cc_usb *cc; + char *tty = NULL; + char *device = NULL; + char line[80]; + int c, i, ret = 0; + int freq = 434550; + char *s; + FILE *file; + int serial; + uint16_t last_tick; + int started; + int realtime = 0; + + + while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + case 'D': + device = optarg; + break; + case 'F': + freq = atoi(optarg); + break; + case 'R': + realtime = 1; + default: + usage(argv[0]); + break; + } + } + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TeleDongle"); + if (!tty) + tty = getenv("ALTOS_TTY"); + if (!tty) + tty="/dev/ttyACM0"; + cc = cc_usb_open(tty); + if (!cc) + exit (1); + + cc_usb_printf(cc, "m 0\n"); + cc_usb_printf(cc, "F %d\n", freq); + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + perror(argv[i]); + ret++; + continue; + } + started = 0; + last_tick = 0; + while (fgets(line, sizeof (line), file)) { + union ao_telemetry_all telem; + + if (cc_telemetry_parse(line, &telem)) { + /* + * Skip packets with CRC errors. + */ + if ((telem.generic.status & (1 << 7)) == 0) + continue; + + if (started) { + do_delay(telem.generic.tick, last_tick); + last_tick = telem.generic.tick; + send_telem(cc, &telem); + } else { + add_telem(&telem); + if (packet_state(&telem) > ao_flight_pad) { + started = 1; + last_tick = send_queued(cc, realtime); + } + } + } + } + fclose (file); + + } + return ret; +} diff --git a/configure.ac b/configure.ac index bcd2dcac..c59261af 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,7 @@ ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile ao-tools/ao-telem/Makefile ao-tools/ao-stmload/Makefile +ao-tools/ao-send-telem/Makefile ao-utils/Makefile src/Version ]) diff --git a/src/core/ao_send_packet.c b/src/core/ao_send_packet.c new file mode 100644 index 00000000..1a8e74de --- /dev/null +++ b/src/core/ao_send_packet.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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" + +#define AO_MAX_SEND 128 + +static __xdata uint8_t ao_send[AO_MAX_SEND]; + +static uint8_t +getnibble(void) +{ + char c; + + c = getchar(); + 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); + ao_cmd_status = ao_cmd_lex_error; + return 0; +} + +static void +ao_send_packet(void) +{ + __pdata uint16_t count; + uint8_t b; + __pdata uint8_t i; + + ao_cmd_hex(); + count = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + if (count > AO_MAX_SEND - 2) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < count; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_send[i] = b; + } + ao_radio_send(ao_send, count); +} + +static __code struct ao_cmds ao_send_packet_cmds[] = { + { ao_send_packet, "S \0Send packet. Data on next line" }, + { 0, NULL } +}; + +void +ao_send_packet_init(void) +{ + ao_cmd_register(&ao_send_packet_cmds[0]); +} diff --git a/src/core/ao_send_packet.h b/src/core/ao_send_packet.h new file mode 100644 index 00000000..526f7b55 --- /dev/null +++ b/src/core/ao_send_packet.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SEND_PACKET_H_ +#define _AO_SEND_PACKET_H_ + +void +ao_send_packet_init(void); + +#endif /* _AO_SEND_PACKET_H_ */ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 5105b567..3101b777 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_send_packet.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 0c829e97..25ebe73e 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include void main(void) @@ -32,6 +33,7 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); + ao_send_packet_init(); #if HAS_DBG ao_dbg_init(); #endif -- cgit v1.2.3 From 0bf21399d3d47d58410df4c6ce89fc20fcd42c89 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:34:00 -0700 Subject: altosui: Handle Monitor Idle errors better Deal with missing data by checking for MISSING in more places. Handle serial communication failures during send by reporting back from libaltos. Signed-off-by: Keith Packard --- altoslib/AltosIdleMonitor.java | 67 +++++++++++++++++------------------------- altoslib/AltosLink.java | 20 +++++++++++-- altoslib/AltosRecord.java | 2 +- altoslib/AltosRecordTM.java | 16 +++++----- altoslib/AltosState.java | 2 ++ altosui/AltosSerial.java | 14 +++++++-- altosui/libaltos/libaltos.c | 4 +-- 7 files changed, 70 insertions(+), 55 deletions(-) diff --git a/altoslib/AltosIdleMonitor.java b/altoslib/AltosIdleMonitor.java index 57c4da71..27ea3a2b 100644 --- a/altoslib/AltosIdleMonitor.java +++ b/altoslib/AltosIdleMonitor.java @@ -23,16 +23,10 @@ import java.text.*; import java.util.prefs.*; import java.util.concurrent.*; -class AltosSensorTM { - int tick; - int accel; - int pres; - int temp; - int batt; - int drogue; - int main; +class AltosSensorTM extends AltosRecordTM { - public AltosSensorTM(AltosLink link) throws InterruptedException, TimeoutException { + public AltosSensorTM(AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException { + super(); link.printf("a\n"); for (;;) { String line = link.get_reply_no_dialog(5000); @@ -82,6 +76,10 @@ class AltosSensorTM { } break; } + ground_accel = config_data.accel_cal_plus; + ground_pres = pres; + accel_plus_g = config_data.accel_cal_plus; + accel_minus_g = config_data.accel_cal_minus; } } @@ -253,7 +251,7 @@ class AltosGPSQuery extends AltosGPS { if (line.startsWith("Date:")) { if (bits.length < 2) continue; - String[] d = bits[1].split(":"); + String[] d = bits[1].split("/"); if (d.length < 3) continue; year = Integer.parseInt(d[0]) + 2000; @@ -264,7 +262,7 @@ class AltosGPSQuery extends AltosGPS { if (line.startsWith("Time:")) { if (bits.length < 2) continue; - String[] d = bits[1].split("/"); + String[] d = bits[1].split(":"); if (d.length < 3) continue; hour = Integer.parseInt(d[0]); @@ -339,8 +337,7 @@ public class AltosIdleMonitor extends Thread { } void update_state() throws InterruptedException, TimeoutException { - AltosRecord record; - int rssi; + AltosRecord record = null; try { if (remote) { @@ -350,20 +347,7 @@ public class AltosIdleMonitor extends Thread { link.flush_input(); config_data = new AltosConfigData(link); if (config_data.product.startsWith("TeleMetrum")) { - AltosRecordTM record_tm = new AltosRecordTM(); - AltosSensorTM sensor = new AltosSensorTM(link); - record_tm.accel = sensor.accel; - record_tm.pres = sensor.pres; - record_tm.batt = sensor.batt; - record_tm.temp = sensor.temp; - record_tm.drogue = sensor.drogue; - record_tm.main = sensor.main; - record_tm.ground_accel = record_tm.accel; - record_tm.ground_pres = record_tm.pres; - record_tm.accel_plus_g = config_data.accel_cal_plus; - record_tm.accel_minus_g = config_data.accel_cal_minus; - record_tm.tick = sensor.tick; - record = record_tm; + record = new AltosSensorTM(link, config_data); } else if (config_data.product.startsWith("MegaMetrum")) { AltosRecordMM record_mm = new AltosRecordMM(); AltosSensorMM sensor = new AltosSensorMM(link); @@ -390,24 +374,27 @@ public class AltosIdleMonitor extends Thread { record = new AltosRecord(); gps = new AltosGPSQuery(link, config_data); + + record.version = 0; + record.callsign = config_data.callsign; + record.serial = config_data.serial; + record.flight = config_data.log_available() > 0 ? 255 : 0; + record.status = 0; + record.state = AltosLib.ao_flight_idle; + record.gps = gps; + record.new_gps = true; + state = new AltosState (record, state); } finally { if (remote) { link.stop_remote(); - rssi = AltosRSSI(); - } else - rssi = 0; + if (record != null) + record.rssi = AltosRSSI(); + } else { + if (record != null) + record.rssi = 0; + } } - record.version = 0; - record.callsign = config_data.callsign; - record.serial = config_data.serial; - record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = rssi; - record.status = 0; - record.state = AltosLib.ao_flight_idle; - - record.gps = gps; - state = new AltosState (record, state); } public void set_frequency(double in_frequency) { diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index d59e73ba..fd5db7e9 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -101,15 +101,23 @@ public abstract class AltosLink { try { for (;;) { c = getchar(); - if (Thread.interrupted()) + if (Thread.interrupted()) { + if (debug) + System.out.printf("INTERRUPTED\n"); break; + } if (c == ERROR) { + if (debug) + System.out.printf("ERROR\n"); add_telem (new AltosLine()); add_reply (new AltosLine()); break; } - if (c == TIMEOUT) + if (c == TIMEOUT) { + if (debug) + System.out.printf("TIMEOUT\n"); continue; + } if (c == '\r') continue; synchronized(this) { @@ -180,6 +188,14 @@ public abstract class AltosLink { reply_queue.put (line); } + public void abort_reply() { + try { + add_telem (new AltosLine()); + add_reply (new AltosLine()); + } catch (InterruptedException e) { + } + } + public void add_string(String line) throws InterruptedException { if (line.startsWith("TELEM") || line.startsWith("VERSION") || line.startsWith("CRC")) { add_telem(new AltosLine(line)); diff --git a/altoslib/AltosRecord.java b/altoslib/AltosRecord.java index e468f84b..8722bc05 100644 --- a/altoslib/AltosRecord.java +++ b/altoslib/AltosRecord.java @@ -127,7 +127,7 @@ public class AltosRecord implements Comparable , Cloneable { double p = filtered_pressure(); if (p == MISSING) - return MISSING; + return raw_altitude(); return AltosConvert.pressure_to_altitude(p); } diff --git a/altoslib/AltosRecordTM.java b/altoslib/AltosRecordTM.java index afb70790..37accef6 100644 --- a/altoslib/AltosRecordTM.java +++ b/altoslib/AltosRecordTM.java @@ -177,14 +177,14 @@ public class AltosRecordTM extends AltosRecord { drogue = MISSING; main = MISSING; - flight_accel = 0; - flight_vel = 0; - flight_pres = 0; - - ground_accel = 0; - ground_pres = 0; - accel_plus_g = 0; - accel_minus_g = 0; + flight_accel = MISSING; + flight_vel = MISSING; + flight_pres = MISSING; + + ground_accel = MISSING; + ground_pres = MISSING; + accel_plus_g = MISSING; + accel_minus_g = MISSING; } public AltosRecordTM(AltosRecord old) { diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index e20ec9a7..3b37a3d4 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -38,6 +38,7 @@ public class AltosState { public boolean boost; /* under power */ public double ground_altitude; + public double altitude; public double height; public double speed; public double acceleration; @@ -82,6 +83,7 @@ public class AltosState { data = cur; ground_altitude = data.ground_altitude(); + altitude = data.raw_altitude(); height = data.filtered_height(); report_time = System.currentTimeMillis(); diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index c4e9c697..8b692fa9 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -54,13 +54,19 @@ public class AltosSerial extends AltosLink implements Runnable { Frame frame; public int getchar() { + if (altos == null) + return ERROR; return libaltos.altos_getchar(altos, 0); } public void flush_output() { super.flush_output(); if (altos != null) { - libaltos.altos_flush(altos); + if (libaltos.altos_flush(altos) != 0) { + libaltos.altos_close(altos); + altos = null; + abort_reply(); + } } } @@ -155,7 +161,11 @@ public class AltosSerial extends AltosLink implements Runnable { private void putc(char c) { if (altos != null) - libaltos.altos_putchar(altos, c); + if (libaltos.altos_putchar(altos, c) != 0) { + libaltos.altos_close(altos); + altos = null; + abort_reply(); + } } public void print(String data) { diff --git a/altosui/libaltos/libaltos.c b/altosui/libaltos/libaltos.c index 1cc27cbe..515432f9 100644 --- a/altosui/libaltos/libaltos.c +++ b/altosui/libaltos/libaltos.c @@ -221,7 +221,7 @@ altos_flush(struct altos_file *file) #endif if (ret < 0) { altos_set_last_posix_error(); - return -errno; + return -last_error.code; } if (ret) { memmove(file->out_data, file->out_data + ret, @@ -247,7 +247,7 @@ altos_putchar(struct altos_file *file, char c) ret = 0; if (file->out_used == USB_BUF_SIZE) ret = altos_flush(file); - return 0; + return ret; } #ifdef USE_POLL -- cgit v1.2.3 From 743dca54012758d3ae54312d542b34afa88495cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:35:15 -0700 Subject: altosui: Remove duplicate values from info table. Add altitude No need to have state/call/serial/flight data, those are all in the header. Having altitude makes Monitor Idle slightly more useful. Signed-off-by: Keith Packard --- altosui/AltosInfoTable.java | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index aa6a6d4e..c1400976 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -40,18 +40,38 @@ public class AltosInfoTable extends JTable { return (infoValueMetrics.getHeight() + infoValueMetrics.getLeading()) * 18 / 10; } + int text_width(String t) { + FontMetrics infoValueMetrics = getFontMetrics(Altos.table_value_font); + + return infoValueMetrics.stringWidth(t); + } + + void set_layout() { + setRowHeight(desired_row_height()); + for (int i = 0; i < info_columns * 2; i++) + { + TableColumn column = getColumnModel().getColumn(i); + + if ((i & 1) == 0) + column.setPreferredWidth(text_width(" Satellites Visible ")); + else + column.setPreferredWidth(text_width(" 179°59.99999' ")); + } + } + public AltosInfoTable() { super(new AltosFlightInfoTableModel(info_rows, info_columns)); model = (AltosFlightInfoTableModel) getModel(); setFont(Altos.table_value_font); setAutoResizeMode(AUTO_RESIZE_ALL_COLUMNS); setShowGrid(true); - setRowHeight(desired_row_height()); + set_layout(); doLayout(); } public void set_font() { setFont(Altos.table_value_font); + set_layout(); doLayout(); } @@ -95,13 +115,8 @@ public class AltosInfoTable extends JTable { if (state == null) return; info_reset(); - 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, "Altitude", "%6.0f m", state.altitude); + info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); 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); @@ -114,7 +129,8 @@ public class AltosInfoTable extends JTable { info_add_row(0, "Drogue", "%9.2f V", state.drogue_sense); if (state.main_sense != AltosRecord.MISSING) info_add_row(0, "Main", "%9.2f V", state.main_sense); - info_add_row(0, "Pad altitude", "%6.0f m", state.ground_altitude); + info_add_row(0, "CRC Errors", "%6d", crc_errors); + if (state.gps == null || !state.gps.connected) { info_add_row(1, "GPS", "not available"); } else { -- cgit v1.2.3 From 21e39811bd234c6f66ab7644864fcc1b8c316998 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:36:50 -0700 Subject: altos/cc1111: Fix serial 0 option 2 pins definitions tx/rx are 4/5, rts/cts are 2/3 Signed-off-by: Keith Packard --- src/cc1111/Makefile.cc1111 | 2 +- src/cc1111/ao_serial.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index f7ecce33..bfd444dd 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -2,7 +2,7 @@ CC=sdcc CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) -CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product +CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../drivers -I../product CODESIZE ?= 0x8000 diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 00c85ff3..d90103b0 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -236,9 +236,9 @@ ao_serial_init(void) (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW P1SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 3) | (1 << 2); #endif #endif -- cgit v1.2.3 From e4d244eefa4c779cd9c8a91389bf998c54705b72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:42:53 -0700 Subject: altos: Add software AES implementation This is untested Signed-off-by: Keith Packard --- src/aes/ao_aes.c | 390 ++++++++++++++++++++++++ src/aes/ao_aes_int.h | 64 ++++ src/aes/ao_aes_tables.c | 768 +++++++++++++++++++++++++++++++++++++++++++++++ src/aes/ao_aes_tables.h | 10 + src/core/ao_aes.h | 2 + src/core/ao_radio_cmac.c | 8 +- src/stm/Makefile.defs | 2 +- 7 files changed, 1239 insertions(+), 5 deletions(-) create mode 100644 src/aes/ao_aes.c create mode 100644 src/aes/ao_aes_int.h create mode 100644 src/aes/ao_aes_tables.c create mode 100644 src/aes/ao_aes_tables.h diff --git a/src/aes/ao_aes.c b/src/aes/ao_aes.c new file mode 100644 index 00000000..4977aaf8 --- /dev/null +++ b/src/aes/ao_aes.c @@ -0,0 +1,390 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.c - optimized version of the Rijndeal cipher */ +/* $Id: rijndael.c 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#include +#include +#include "ao_aes_int.h" + +static const int xshifts[3][2][4] = { + {{0, 1, 2, 3}, + {0, 3, 2, 1}}, + + {{0, 1, 2, 3}, + {0, 5, 4, 3}}, + + {{0, 1, 3, 4}, + {0, 7, 5, 4}}, +}; + +/* Exor corresponding text input and round key input bytes */ +/* the result is written to res, which can be the same as a */ +static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + + for (j = 0; j < BC; j++) { + res[j] = a[j] ^ rk[j]; + } +} + +#if 0 /* code included for reference */ + +/* shift rows a, return result in res. This avoids having to copy a + tmp array back to a. res must not be a. */ +static inline void xShiftRow(word32 res[MAXBC], word32 a[MAXBC], int shift[4], + int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + int i, j; + int s; + + for (j = 0; j < BC; j++) { + res8[j][0] = a8[j][0]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC; j++) { + res8[j][i] = a8[(j + s) % BC][i]; + } + } +} + +static inline void xSubstitution(word32 a[MAXBC], word8 box[256], int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < BC; j++) { + a8[j][i] = box[a[j][i]]; + } + } +} + +#endif /* code included for reference */ + +/* profiling shows that the ccrypt program spends about 50% of its + time in the function xShiftSubst. Splitting the inner "for" + statement into two parts - versus using the expensive "%" modulo + operation, makes this function about 44% faster, thereby making the + entire program about 28% faster. With -O3 optimization, the time + savings are even more dramatic - ccrypt runs between 55% and 65% + faster on most platforms. */ + +/* do ShiftRow and Substitution together. res must not be a. */ +static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC], + int shift[4], int BC, const word8 box[256]) +{ + int i, j; + int s; + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + for (j = 0; j < BC; j++) { + res8[j][0] = box[a8[j][0]]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC - s; j++) { + res8[j][i] = box[a8[(j + s)][i]]; + } + for (j = BC - s; j < BC; j++) { + res8[j][i] = box[a8[(j + s) - BC][i]]; + } + } +} + +#if 0 /* code included for reference */ + +/* Mix the four bytes of every column in a linear way */ +/* the result is written to res, which may equal a */ +static inline void xMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +/* do MixColumn and KeyAddition together */ +static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + b ^= rk[j]; + res[j] = b; + } +} + +/* Mix the four bytes of every column in a linear way + * This is the opposite operation of xMixColumn */ +/* the result is written to res, which may equal a */ +static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#if 0 /* code included for reference */ + +/* do KeyAddition and InvMixColumn together */ +static inline void xAddInvMix(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + a[j] = a[j] ^ rk[j]; + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk) +{ + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + word8 (*k8)[4] = (word8 (*)[4]) key; + + switch (keyBits) { + case 128: + KC = 4; + break; + case 192: + KC = 6; + break; + case 256: + KC = 8; + break; + default: + return -1; + } + + switch (blockBits) { + case 128: + BC = 4; + break; + case 192: + BC = 6; + break; + case 256: + BC = 8; + break; + default: + return -2; + } + + ROUNDS = KC > BC ? KC + 6 : BC + 6; + + t = 0; + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) + rkk->rk[t] = key[j]; + + while (t < (ROUNDS + 1) * BC) { /* while not enough round key material */ + /* calculate new values */ + for (i = 0; i < 4; i++) { + k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]]; + } + k8[0][0] ^= xrcon[rconpointer++]; + + if (KC != 8) { + for (j = 1; j < KC; j++) { + key[j] ^= key[j - 1]; + } + } else { + for (j = 1; j < 4; j++) { + key[j] ^= key[j - 1]; + } + for (i = 0; i < 4; i++) { + k8[4][i] ^= xS[k8[3][i]]; + } + for (j = 5; j < 8; j++) { + key[j] ^= key[j - 1]; + } + } + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) { + rkk->rk[t] = key[j]; + } + } + + /* make roundkey structure */ + rkk->BC = BC; + rkk->KC = KC; + rkk->ROUNDS = ROUNDS; + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j]; + } + } + + return 0; +} + +/* Encryption of one block. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[0]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk; + + /* begin with a key addition */ + xKeyAddition(block, block, rp, BC); + rp += BC; + + /* ROUNDS-1 ordinary rounds */ + for (r = 1; r < ROUNDS; r++) { + xShiftSubst(block2, block, shift, BC, xS); + xMixAdd(block, block2, rp, BC); + rp += BC; + } + + /* Last round is special: there is no xMixColumn */ + xShiftSubst(block2, block, shift, BC, xS); + xKeyAddition(block, block2, rp, BC); +} + +void xrijndaelDecrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[1]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk + ROUNDS * BC; + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (xKeyAddition is an involution: it's equal to its inverse) + * (the inverse of xSubstitution with table S is xSubstitution with the + * inverse table of S) + * (the inverse of xShiftRow is xShiftRow over a suitable distance) + */ + + /* First the special round: + * without xInvMixColumn + * with extra xKeyAddition + */ + xKeyAddition(block2, block, rp, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + + /* ROUNDS-1 ordinary rounds + */ + for (r = ROUNDS - 1; r > 0; r--) { + xKeyAddition(block, block, rp, BC); + xInvMixColumn(block2, block, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + } + + /* End with the extra key addition + */ + + xKeyAddition(block, block, rp, BC); +} + +uint8_t ao_aes_mutex; +static roundkey rkk; + +static uint8_t iv[16]; + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + /* we only do CBC_MAC anyways... */ +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + xrijndaelKeySched((word32 *) in, 128, 128, &rkk); +} + +void +ao_aes_zero_iv(void) +{ + memset(iv, '\0', sizeof (iv)); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t i; + + for (i = 0; i < 16; i++) + iv[i] ^= in[i]; + xrijndaelEncrypt((word32 *) iv, &rkk); + if (out) + memcpy(out, iv, 16); +} + +void +ao_aes_init(void) +{ +} diff --git a/src/aes/ao_aes_int.h b/src/aes/ao_aes_int.h new file mode 100644 index 00000000..7990a2e1 --- /dev/null +++ b/src/aes/ao_aes_int.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.h */ +/* $Id: rijndael.h 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#include + +typedef uint8_t word8; +typedef uint32_t word32; + +/* a type to hold 32 bits accessible as 1 integer or 4 bytes */ +union word8x4_u { + word8 w8[4]; + word32 w32; +}; +typedef union word8x4_u word8x4; + +#include "ao_aes_tables.h" + +#define MAXBC (256/32) +#define MAXKC (256/32) +#define MAXROUNDS 14 +#define MAXRK ((MAXROUNDS+1)*MAXBC) + +typedef struct { + int BC; + int KC; + int ROUNDS; + int shift[2][4]; + word32 rk[MAXRK]; +} roundkey; + +/* keys and blocks are externally treated as word32 arrays, to + make sure they are aligned on 4-byte boundaries on architectures + that require it. */ + +/* make a roundkey rkk from key. key must have appropriate size given + by keyBits. keyBits and blockBits may only be 128, 196, or + 256. Returns non-zero if arguments are invalid. */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk); + +/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must + have been created with xrijndaelKeySched. Size of block, in bits, + must be equal to blockBits parameter that was used to make rkk. In + all other cases, behavior is undefined - for reasons of speed, no + check for error conditions is done. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk); +void xrijndaelDecrypt(word32 block[], roundkey *rkk); + +#endif /* __RIJNDAEL_H */ diff --git a/src/aes/ao_aes_tables.c b/src/aes/ao_aes_tables.c new file mode 100644 index 00000000..1bca227c --- /dev/null +++ b/src/aes/ao_aes_tables.c @@ -0,0 +1,768 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* generated by maketables.c */ + +#include "ao_aes_int.h" + +const word8x4 M0[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 2, 1, 1, 3}}, {{ 4, 2, 2, 6}}, + {{ 6, 3, 3, 5}}, {{ 8, 4, 4, 12}}, {{ 10, 5, 5, 15}}, + {{ 12, 6, 6, 10}}, {{ 14, 7, 7, 9}}, {{ 16, 8, 8, 24}}, + {{ 18, 9, 9, 27}}, {{ 20, 10, 10, 30}}, {{ 22, 11, 11, 29}}, + {{ 24, 12, 12, 20}}, {{ 26, 13, 13, 23}}, {{ 28, 14, 14, 18}}, + {{ 30, 15, 15, 17}}, {{ 32, 16, 16, 48}}, {{ 34, 17, 17, 51}}, + {{ 36, 18, 18, 54}}, {{ 38, 19, 19, 53}}, {{ 40, 20, 20, 60}}, + {{ 42, 21, 21, 63}}, {{ 44, 22, 22, 58}}, {{ 46, 23, 23, 57}}, + {{ 48, 24, 24, 40}}, {{ 50, 25, 25, 43}}, {{ 52, 26, 26, 46}}, + {{ 54, 27, 27, 45}}, {{ 56, 28, 28, 36}}, {{ 58, 29, 29, 39}}, + {{ 60, 30, 30, 34}}, {{ 62, 31, 31, 33}}, {{ 64, 32, 32, 96}}, + {{ 66, 33, 33, 99}}, {{ 68, 34, 34, 102}}, {{ 70, 35, 35, 101}}, + {{ 72, 36, 36, 108}}, {{ 74, 37, 37, 111}}, {{ 76, 38, 38, 106}}, + {{ 78, 39, 39, 105}}, {{ 80, 40, 40, 120}}, {{ 82, 41, 41, 123}}, + {{ 84, 42, 42, 126}}, {{ 86, 43, 43, 125}}, {{ 88, 44, 44, 116}}, + {{ 90, 45, 45, 119}}, {{ 92, 46, 46, 114}}, {{ 94, 47, 47, 113}}, + {{ 96, 48, 48, 80}}, {{ 98, 49, 49, 83}}, {{100, 50, 50, 86}}, + {{102, 51, 51, 85}}, {{104, 52, 52, 92}}, {{106, 53, 53, 95}}, + {{108, 54, 54, 90}}, {{110, 55, 55, 89}}, {{112, 56, 56, 72}}, + {{114, 57, 57, 75}}, {{116, 58, 58, 78}}, {{118, 59, 59, 77}}, + {{120, 60, 60, 68}}, {{122, 61, 61, 71}}, {{124, 62, 62, 66}}, + {{126, 63, 63, 65}}, {{128, 64, 64, 192}}, {{130, 65, 65, 195}}, + {{132, 66, 66, 198}}, {{134, 67, 67, 197}}, {{136, 68, 68, 204}}, + {{138, 69, 69, 207}}, {{140, 70, 70, 202}}, {{142, 71, 71, 201}}, + {{144, 72, 72, 216}}, {{146, 73, 73, 219}}, {{148, 74, 74, 222}}, + {{150, 75, 75, 221}}, {{152, 76, 76, 212}}, {{154, 77, 77, 215}}, + {{156, 78, 78, 210}}, {{158, 79, 79, 209}}, {{160, 80, 80, 240}}, + {{162, 81, 81, 243}}, {{164, 82, 82, 246}}, {{166, 83, 83, 245}}, + {{168, 84, 84, 252}}, {{170, 85, 85, 255}}, {{172, 86, 86, 250}}, + {{174, 87, 87, 249}}, {{176, 88, 88, 232}}, {{178, 89, 89, 235}}, + {{180, 90, 90, 238}}, {{182, 91, 91, 237}}, {{184, 92, 92, 228}}, + {{186, 93, 93, 231}}, {{188, 94, 94, 226}}, {{190, 95, 95, 225}}, + {{192, 96, 96, 160}}, {{194, 97, 97, 163}}, {{196, 98, 98, 166}}, + {{198, 99, 99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, + {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, + {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, + {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, + {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, + {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, + {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, + {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, + {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, + {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, + {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, + {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, + {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{ 9, 137, 137, 128}}, + {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{ 3, 140, 140, 143}}, + {{ 1, 141, 141, 140}}, {{ 7, 142, 142, 137}}, {{ 5, 143, 143, 138}}, + {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, + {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, + {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, + {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, + {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, + {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, + {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, + {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, + {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, + {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, + {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, + {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, + {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, + {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, + {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, + {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, + {{155, 192, 192, 91}}, {{153, 193, 193, 88}}, {{159, 194, 194, 93}}, + {{157, 195, 195, 94}}, {{147, 196, 196, 87}}, {{145, 197, 197, 84}}, + {{151, 198, 198, 81}}, {{149, 199, 199, 82}}, {{139, 200, 200, 67}}, + {{137, 201, 201, 64}}, {{143, 202, 202, 69}}, {{141, 203, 203, 70}}, + {{131, 204, 204, 79}}, {{129, 205, 205, 76}}, {{135, 206, 206, 73}}, + {{133, 207, 207, 74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, + {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, + {{177, 213, 213, 100}}, {{183, 214, 214, 97}}, {{181, 215, 215, 98}}, + {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, + {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, + {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224, 59}}, + {{217, 225, 225, 56}}, {{223, 226, 226, 61}}, {{221, 227, 227, 62}}, + {{211, 228, 228, 55}}, {{209, 229, 229, 52}}, {{215, 230, 230, 49}}, + {{213, 231, 231, 50}}, {{203, 232, 232, 35}}, {{201, 233, 233, 32}}, + {{207, 234, 234, 37}}, {{205, 235, 235, 38}}, {{195, 236, 236, 47}}, + {{193, 237, 237, 44}}, {{199, 238, 238, 41}}, {{197, 239, 239, 42}}, + {{251, 240, 240, 11}}, {{249, 241, 241, 8}}, {{255, 242, 242, 13}}, + {{253, 243, 243, 14}}, {{243, 244, 244, 7}}, {{241, 245, 245, 4}}, + {{247, 246, 246, 1}}, {{245, 247, 247, 2}}, {{235, 248, 248, 19}}, + {{233, 249, 249, 16}}, {{239, 250, 250, 21}}, {{237, 251, 251, 22}}, + {{227, 252, 252, 31}}, {{225, 253, 253, 28}}, {{231, 254, 254, 25}}, + {{229, 255, 255, 26}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 3, 2, 1, 1}}, {{ 6, 4, 2, 2}}, + {{ 5, 6, 3, 3}}, {{ 12, 8, 4, 4}}, {{ 15, 10, 5, 5}}, + {{ 10, 12, 6, 6}}, {{ 9, 14, 7, 7}}, {{ 24, 16, 8, 8}}, + {{ 27, 18, 9, 9}}, {{ 30, 20, 10, 10}}, {{ 29, 22, 11, 11}}, + {{ 20, 24, 12, 12}}, {{ 23, 26, 13, 13}}, {{ 18, 28, 14, 14}}, + {{ 17, 30, 15, 15}}, {{ 48, 32, 16, 16}}, {{ 51, 34, 17, 17}}, + {{ 54, 36, 18, 18}}, {{ 53, 38, 19, 19}}, {{ 60, 40, 20, 20}}, + {{ 63, 42, 21, 21}}, {{ 58, 44, 22, 22}}, {{ 57, 46, 23, 23}}, + {{ 40, 48, 24, 24}}, {{ 43, 50, 25, 25}}, {{ 46, 52, 26, 26}}, + {{ 45, 54, 27, 27}}, {{ 36, 56, 28, 28}}, {{ 39, 58, 29, 29}}, + {{ 34, 60, 30, 30}}, {{ 33, 62, 31, 31}}, {{ 96, 64, 32, 32}}, + {{ 99, 66, 33, 33}}, {{102, 68, 34, 34}}, {{101, 70, 35, 35}}, + {{108, 72, 36, 36}}, {{111, 74, 37, 37}}, {{106, 76, 38, 38}}, + {{105, 78, 39, 39}}, {{120, 80, 40, 40}}, {{123, 82, 41, 41}}, + {{126, 84, 42, 42}}, {{125, 86, 43, 43}}, {{116, 88, 44, 44}}, + {{119, 90, 45, 45}}, {{114, 92, 46, 46}}, {{113, 94, 47, 47}}, + {{ 80, 96, 48, 48}}, {{ 83, 98, 49, 49}}, {{ 86, 100, 50, 50}}, + {{ 85, 102, 51, 51}}, {{ 92, 104, 52, 52}}, {{ 95, 106, 53, 53}}, + {{ 90, 108, 54, 54}}, {{ 89, 110, 55, 55}}, {{ 72, 112, 56, 56}}, + {{ 75, 114, 57, 57}}, {{ 78, 116, 58, 58}}, {{ 77, 118, 59, 59}}, + {{ 68, 120, 60, 60}}, {{ 71, 122, 61, 61}}, {{ 66, 124, 62, 62}}, + {{ 65, 126, 63, 63}}, {{192, 128, 64, 64}}, {{195, 130, 65, 65}}, + {{198, 132, 66, 66}}, {{197, 134, 67, 67}}, {{204, 136, 68, 68}}, + {{207, 138, 69, 69}}, {{202, 140, 70, 70}}, {{201, 142, 71, 71}}, + {{216, 144, 72, 72}}, {{219, 146, 73, 73}}, {{222, 148, 74, 74}}, + {{221, 150, 75, 75}}, {{212, 152, 76, 76}}, {{215, 154, 77, 77}}, + {{210, 156, 78, 78}}, {{209, 158, 79, 79}}, {{240, 160, 80, 80}}, + {{243, 162, 81, 81}}, {{246, 164, 82, 82}}, {{245, 166, 83, 83}}, + {{252, 168, 84, 84}}, {{255, 170, 85, 85}}, {{250, 172, 86, 86}}, + {{249, 174, 87, 87}}, {{232, 176, 88, 88}}, {{235, 178, 89, 89}}, + {{238, 180, 90, 90}}, {{237, 182, 91, 91}}, {{228, 184, 92, 92}}, + {{231, 186, 93, 93}}, {{226, 188, 94, 94}}, {{225, 190, 95, 95}}, + {{160, 192, 96, 96}}, {{163, 194, 97, 97}}, {{166, 196, 98, 98}}, + {{165, 198, 99, 99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, + {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, + {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, + {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, + {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, + {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, + {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, + {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, + {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, + {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155, 27, 128, 128}}, + {{152, 25, 129, 129}}, {{157, 31, 130, 130}}, {{158, 29, 131, 131}}, + {{151, 19, 132, 132}}, {{148, 17, 133, 133}}, {{145, 23, 134, 134}}, + {{146, 21, 135, 135}}, {{131, 11, 136, 136}}, {{128, 9, 137, 137}}, + {{133, 15, 138, 138}}, {{134, 13, 139, 139}}, {{143, 3, 140, 140}}, + {{140, 1, 141, 141}}, {{137, 7, 142, 142}}, {{138, 5, 143, 143}}, + {{171, 59, 144, 144}}, {{168, 57, 145, 145}}, {{173, 63, 146, 146}}, + {{174, 61, 147, 147}}, {{167, 51, 148, 148}}, {{164, 49, 149, 149}}, + {{161, 55, 150, 150}}, {{162, 53, 151, 151}}, {{179, 43, 152, 152}}, + {{176, 41, 153, 153}}, {{181, 47, 154, 154}}, {{182, 45, 155, 155}}, + {{191, 35, 156, 156}}, {{188, 33, 157, 157}}, {{185, 39, 158, 158}}, + {{186, 37, 159, 159}}, {{251, 91, 160, 160}}, {{248, 89, 161, 161}}, + {{253, 95, 162, 162}}, {{254, 93, 163, 163}}, {{247, 83, 164, 164}}, + {{244, 81, 165, 165}}, {{241, 87, 166, 166}}, {{242, 85, 167, 167}}, + {{227, 75, 168, 168}}, {{224, 73, 169, 169}}, {{229, 79, 170, 170}}, + {{230, 77, 171, 171}}, {{239, 67, 172, 172}}, {{236, 65, 173, 173}}, + {{233, 71, 174, 174}}, {{234, 69, 175, 175}}, {{203, 123, 176, 176}}, + {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, + {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, + {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, + {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223, 99, 188, 188}}, + {{220, 97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, + {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, + {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, + {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, + {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, + {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, + {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, + {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, + {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, + {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, + {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, + {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, + {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, + {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, + {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, + {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, + {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, + {{ 11, 251, 240, 240}}, {{ 8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, + {{ 14, 253, 243, 243}}, {{ 7, 243, 244, 244}}, {{ 4, 241, 245, 245}}, + {{ 1, 247, 246, 246}}, {{ 2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, + {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, + {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, + {{ 26, 229, 255, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 3, 2, 1}}, {{ 2, 6, 4, 2}}, + {{ 3, 5, 6, 3}}, {{ 4, 12, 8, 4}}, {{ 5, 15, 10, 5}}, + {{ 6, 10, 12, 6}}, {{ 7, 9, 14, 7}}, {{ 8, 24, 16, 8}}, + {{ 9, 27, 18, 9}}, {{ 10, 30, 20, 10}}, {{ 11, 29, 22, 11}}, + {{ 12, 20, 24, 12}}, {{ 13, 23, 26, 13}}, {{ 14, 18, 28, 14}}, + {{ 15, 17, 30, 15}}, {{ 16, 48, 32, 16}}, {{ 17, 51, 34, 17}}, + {{ 18, 54, 36, 18}}, {{ 19, 53, 38, 19}}, {{ 20, 60, 40, 20}}, + {{ 21, 63, 42, 21}}, {{ 22, 58, 44, 22}}, {{ 23, 57, 46, 23}}, + {{ 24, 40, 48, 24}}, {{ 25, 43, 50, 25}}, {{ 26, 46, 52, 26}}, + {{ 27, 45, 54, 27}}, {{ 28, 36, 56, 28}}, {{ 29, 39, 58, 29}}, + {{ 30, 34, 60, 30}}, {{ 31, 33, 62, 31}}, {{ 32, 96, 64, 32}}, + {{ 33, 99, 66, 33}}, {{ 34, 102, 68, 34}}, {{ 35, 101, 70, 35}}, + {{ 36, 108, 72, 36}}, {{ 37, 111, 74, 37}}, {{ 38, 106, 76, 38}}, + {{ 39, 105, 78, 39}}, {{ 40, 120, 80, 40}}, {{ 41, 123, 82, 41}}, + {{ 42, 126, 84, 42}}, {{ 43, 125, 86, 43}}, {{ 44, 116, 88, 44}}, + {{ 45, 119, 90, 45}}, {{ 46, 114, 92, 46}}, {{ 47, 113, 94, 47}}, + {{ 48, 80, 96, 48}}, {{ 49, 83, 98, 49}}, {{ 50, 86, 100, 50}}, + {{ 51, 85, 102, 51}}, {{ 52, 92, 104, 52}}, {{ 53, 95, 106, 53}}, + {{ 54, 90, 108, 54}}, {{ 55, 89, 110, 55}}, {{ 56, 72, 112, 56}}, + {{ 57, 75, 114, 57}}, {{ 58, 78, 116, 58}}, {{ 59, 77, 118, 59}}, + {{ 60, 68, 120, 60}}, {{ 61, 71, 122, 61}}, {{ 62, 66, 124, 62}}, + {{ 63, 65, 126, 63}}, {{ 64, 192, 128, 64}}, {{ 65, 195, 130, 65}}, + {{ 66, 198, 132, 66}}, {{ 67, 197, 134, 67}}, {{ 68, 204, 136, 68}}, + {{ 69, 207, 138, 69}}, {{ 70, 202, 140, 70}}, {{ 71, 201, 142, 71}}, + {{ 72, 216, 144, 72}}, {{ 73, 219, 146, 73}}, {{ 74, 222, 148, 74}}, + {{ 75, 221, 150, 75}}, {{ 76, 212, 152, 76}}, {{ 77, 215, 154, 77}}, + {{ 78, 210, 156, 78}}, {{ 79, 209, 158, 79}}, {{ 80, 240, 160, 80}}, + {{ 81, 243, 162, 81}}, {{ 82, 246, 164, 82}}, {{ 83, 245, 166, 83}}, + {{ 84, 252, 168, 84}}, {{ 85, 255, 170, 85}}, {{ 86, 250, 172, 86}}, + {{ 87, 249, 174, 87}}, {{ 88, 232, 176, 88}}, {{ 89, 235, 178, 89}}, + {{ 90, 238, 180, 90}}, {{ 91, 237, 182, 91}}, {{ 92, 228, 184, 92}}, + {{ 93, 231, 186, 93}}, {{ 94, 226, 188, 94}}, {{ 95, 225, 190, 95}}, + {{ 96, 160, 192, 96}}, {{ 97, 163, 194, 97}}, {{ 98, 166, 196, 98}}, + {{ 99, 165, 198, 99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, + {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, + {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, + {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, + {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, + {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, + {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, + {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, + {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, + {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155, 27, 128}}, + {{129, 152, 25, 129}}, {{130, 157, 31, 130}}, {{131, 158, 29, 131}}, + {{132, 151, 19, 132}}, {{133, 148, 17, 133}}, {{134, 145, 23, 134}}, + {{135, 146, 21, 135}}, {{136, 131, 11, 136}}, {{137, 128, 9, 137}}, + {{138, 133, 15, 138}}, {{139, 134, 13, 139}}, {{140, 143, 3, 140}}, + {{141, 140, 1, 141}}, {{142, 137, 7, 142}}, {{143, 138, 5, 143}}, + {{144, 171, 59, 144}}, {{145, 168, 57, 145}}, {{146, 173, 63, 146}}, + {{147, 174, 61, 147}}, {{148, 167, 51, 148}}, {{149, 164, 49, 149}}, + {{150, 161, 55, 150}}, {{151, 162, 53, 151}}, {{152, 179, 43, 152}}, + {{153, 176, 41, 153}}, {{154, 181, 47, 154}}, {{155, 182, 45, 155}}, + {{156, 191, 35, 156}}, {{157, 188, 33, 157}}, {{158, 185, 39, 158}}, + {{159, 186, 37, 159}}, {{160, 251, 91, 160}}, {{161, 248, 89, 161}}, + {{162, 253, 95, 162}}, {{163, 254, 93, 163}}, {{164, 247, 83, 164}}, + {{165, 244, 81, 165}}, {{166, 241, 87, 166}}, {{167, 242, 85, 167}}, + {{168, 227, 75, 168}}, {{169, 224, 73, 169}}, {{170, 229, 79, 170}}, + {{171, 230, 77, 171}}, {{172, 239, 67, 172}}, {{173, 236, 65, 173}}, + {{174, 233, 71, 174}}, {{175, 234, 69, 175}}, {{176, 203, 123, 176}}, + {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, + {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, + {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, + {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223, 99, 188}}, + {{189, 220, 97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, + {{192, 91, 155, 192}}, {{193, 88, 153, 193}}, {{194, 93, 159, 194}}, + {{195, 94, 157, 195}}, {{196, 87, 147, 196}}, {{197, 84, 145, 197}}, + {{198, 81, 151, 198}}, {{199, 82, 149, 199}}, {{200, 67, 139, 200}}, + {{201, 64, 137, 201}}, {{202, 69, 143, 202}}, {{203, 70, 141, 203}}, + {{204, 79, 131, 204}}, {{205, 76, 129, 205}}, {{206, 73, 135, 206}}, + {{207, 74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, + {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, + {{213, 100, 177, 213}}, {{214, 97, 183, 214}}, {{215, 98, 181, 215}}, + {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, + {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, + {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224, 59, 219, 224}}, + {{225, 56, 217, 225}}, {{226, 61, 223, 226}}, {{227, 62, 221, 227}}, + {{228, 55, 211, 228}}, {{229, 52, 209, 229}}, {{230, 49, 215, 230}}, + {{231, 50, 213, 231}}, {{232, 35, 203, 232}}, {{233, 32, 201, 233}}, + {{234, 37, 207, 234}}, {{235, 38, 205, 235}}, {{236, 47, 195, 236}}, + {{237, 44, 193, 237}}, {{238, 41, 199, 238}}, {{239, 42, 197, 239}}, + {{240, 11, 251, 240}}, {{241, 8, 249, 241}}, {{242, 13, 255, 242}}, + {{243, 14, 253, 243}}, {{244, 7, 243, 244}}, {{245, 4, 241, 245}}, + {{246, 1, 247, 246}}, {{247, 2, 245, 247}}, {{248, 19, 235, 248}}, + {{249, 16, 233, 249}}, {{250, 21, 239, 250}}, {{251, 22, 237, 251}}, + {{252, 31, 227, 252}}, {{253, 28, 225, 253}}, {{254, 25, 231, 254}}, + {{255, 26, 229, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 1, 3, 2}}, {{ 2, 2, 6, 4}}, + {{ 3, 3, 5, 6}}, {{ 4, 4, 12, 8}}, {{ 5, 5, 15, 10}}, + {{ 6, 6, 10, 12}}, {{ 7, 7, 9, 14}}, {{ 8, 8, 24, 16}}, + {{ 9, 9, 27, 18}}, {{ 10, 10, 30, 20}}, {{ 11, 11, 29, 22}}, + {{ 12, 12, 20, 24}}, {{ 13, 13, 23, 26}}, {{ 14, 14, 18, 28}}, + {{ 15, 15, 17, 30}}, {{ 16, 16, 48, 32}}, {{ 17, 17, 51, 34}}, + {{ 18, 18, 54, 36}}, {{ 19, 19, 53, 38}}, {{ 20, 20, 60, 40}}, + {{ 21, 21, 63, 42}}, {{ 22, 22, 58, 44}}, {{ 23, 23, 57, 46}}, + {{ 24, 24, 40, 48}}, {{ 25, 25, 43, 50}}, {{ 26, 26, 46, 52}}, + {{ 27, 27, 45, 54}}, {{ 28, 28, 36, 56}}, {{ 29, 29, 39, 58}}, + {{ 30, 30, 34, 60}}, {{ 31, 31, 33, 62}}, {{ 32, 32, 96, 64}}, + {{ 33, 33, 99, 66}}, {{ 34, 34, 102, 68}}, {{ 35, 35, 101, 70}}, + {{ 36, 36, 108, 72}}, {{ 37, 37, 111, 74}}, {{ 38, 38, 106, 76}}, + {{ 39, 39, 105, 78}}, {{ 40, 40, 120, 80}}, {{ 41, 41, 123, 82}}, + {{ 42, 42, 126, 84}}, {{ 43, 43, 125, 86}}, {{ 44, 44, 116, 88}}, + {{ 45, 45, 119, 90}}, {{ 46, 46, 114, 92}}, {{ 47, 47, 113, 94}}, + {{ 48, 48, 80, 96}}, {{ 49, 49, 83, 98}}, {{ 50, 50, 86, 100}}, + {{ 51, 51, 85, 102}}, {{ 52, 52, 92, 104}}, {{ 53, 53, 95, 106}}, + {{ 54, 54, 90, 108}}, {{ 55, 55, 89, 110}}, {{ 56, 56, 72, 112}}, + {{ 57, 57, 75, 114}}, {{ 58, 58, 78, 116}}, {{ 59, 59, 77, 118}}, + {{ 60, 60, 68, 120}}, {{ 61, 61, 71, 122}}, {{ 62, 62, 66, 124}}, + {{ 63, 63, 65, 126}}, {{ 64, 64, 192, 128}}, {{ 65, 65, 195, 130}}, + {{ 66, 66, 198, 132}}, {{ 67, 67, 197, 134}}, {{ 68, 68, 204, 136}}, + {{ 69, 69, 207, 138}}, {{ 70, 70, 202, 140}}, {{ 71, 71, 201, 142}}, + {{ 72, 72, 216, 144}}, {{ 73, 73, 219, 146}}, {{ 74, 74, 222, 148}}, + {{ 75, 75, 221, 150}}, {{ 76, 76, 212, 152}}, {{ 77, 77, 215, 154}}, + {{ 78, 78, 210, 156}}, {{ 79, 79, 209, 158}}, {{ 80, 80, 240, 160}}, + {{ 81, 81, 243, 162}}, {{ 82, 82, 246, 164}}, {{ 83, 83, 245, 166}}, + {{ 84, 84, 252, 168}}, {{ 85, 85, 255, 170}}, {{ 86, 86, 250, 172}}, + {{ 87, 87, 249, 174}}, {{ 88, 88, 232, 176}}, {{ 89, 89, 235, 178}}, + {{ 90, 90, 238, 180}}, {{ 91, 91, 237, 182}}, {{ 92, 92, 228, 184}}, + {{ 93, 93, 231, 186}}, {{ 94, 94, 226, 188}}, {{ 95, 95, 225, 190}}, + {{ 96, 96, 160, 192}}, {{ 97, 97, 163, 194}}, {{ 98, 98, 166, 196}}, + {{ 99, 99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, + {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, + {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, + {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, + {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, + {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, + {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, + {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, + {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, + {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155, 27}}, + {{129, 129, 152, 25}}, {{130, 130, 157, 31}}, {{131, 131, 158, 29}}, + {{132, 132, 151, 19}}, {{133, 133, 148, 17}}, {{134, 134, 145, 23}}, + {{135, 135, 146, 21}}, {{136, 136, 131, 11}}, {{137, 137, 128, 9}}, + {{138, 138, 133, 15}}, {{139, 139, 134, 13}}, {{140, 140, 143, 3}}, + {{141, 141, 140, 1}}, {{142, 142, 137, 7}}, {{143, 143, 138, 5}}, + {{144, 144, 171, 59}}, {{145, 145, 168, 57}}, {{146, 146, 173, 63}}, + {{147, 147, 174, 61}}, {{148, 148, 167, 51}}, {{149, 149, 164, 49}}, + {{150, 150, 161, 55}}, {{151, 151, 162, 53}}, {{152, 152, 179, 43}}, + {{153, 153, 176, 41}}, {{154, 154, 181, 47}}, {{155, 155, 182, 45}}, + {{156, 156, 191, 35}}, {{157, 157, 188, 33}}, {{158, 158, 185, 39}}, + {{159, 159, 186, 37}}, {{160, 160, 251, 91}}, {{161, 161, 248, 89}}, + {{162, 162, 253, 95}}, {{163, 163, 254, 93}}, {{164, 164, 247, 83}}, + {{165, 165, 244, 81}}, {{166, 166, 241, 87}}, {{167, 167, 242, 85}}, + {{168, 168, 227, 75}}, {{169, 169, 224, 73}}, {{170, 170, 229, 79}}, + {{171, 171, 230, 77}}, {{172, 172, 239, 67}}, {{173, 173, 236, 65}}, + {{174, 174, 233, 71}}, {{175, 175, 234, 69}}, {{176, 176, 203, 123}}, + {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, + {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, + {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, + {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223, 99}}, + {{189, 189, 220, 97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, + {{192, 192, 91, 155}}, {{193, 193, 88, 153}}, {{194, 194, 93, 159}}, + {{195, 195, 94, 157}}, {{196, 196, 87, 147}}, {{197, 197, 84, 145}}, + {{198, 198, 81, 151}}, {{199, 199, 82, 149}}, {{200, 200, 67, 139}}, + {{201, 201, 64, 137}}, {{202, 202, 69, 143}}, {{203, 203, 70, 141}}, + {{204, 204, 79, 131}}, {{205, 205, 76, 129}}, {{206, 206, 73, 135}}, + {{207, 207, 74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, + {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, + {{213, 213, 100, 177}}, {{214, 214, 97, 183}}, {{215, 215, 98, 181}}, + {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, + {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, + {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224, 59, 219}}, + {{225, 225, 56, 217}}, {{226, 226, 61, 223}}, {{227, 227, 62, 221}}, + {{228, 228, 55, 211}}, {{229, 229, 52, 209}}, {{230, 230, 49, 215}}, + {{231, 231, 50, 213}}, {{232, 232, 35, 203}}, {{233, 233, 32, 201}}, + {{234, 234, 37, 207}}, {{235, 235, 38, 205}}, {{236, 236, 47, 195}}, + {{237, 237, 44, 193}}, {{238, 238, 41, 199}}, {{239, 239, 42, 197}}, + {{240, 240, 11, 251}}, {{241, 241, 8, 249}}, {{242, 242, 13, 255}}, + {{243, 243, 14, 253}}, {{244, 244, 7, 243}}, {{245, 245, 4, 241}}, + {{246, 246, 1, 247}}, {{247, 247, 2, 245}}, {{248, 248, 19, 235}}, + {{249, 249, 16, 233}}, {{250, 250, 21, 239}}, {{251, 251, 22, 237}}, + {{252, 252, 31, 227}}, {{253, 253, 28, 225}}, {{254, 254, 25, 231}}, + {{255, 255, 26, 229}}, + }, +}; + +const word8x4 M1[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 14, 9, 13, 11}}, {{ 28, 18, 26, 22}}, + {{ 18, 27, 23, 29}}, {{ 56, 36, 52, 44}}, {{ 54, 45, 57, 39}}, + {{ 36, 54, 46, 58}}, {{ 42, 63, 35, 49}}, {{112, 72, 104, 88}}, + {{126, 65, 101, 83}}, {{108, 90, 114, 78}}, {{ 98, 83, 127, 69}}, + {{ 72, 108, 92, 116}}, {{ 70, 101, 81, 127}}, {{ 84, 126, 70, 98}}, + {{ 90, 119, 75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, + {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, + {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, + {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, + {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, + {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219, 59, 187, 123}}, + {{213, 50, 182, 112}}, {{199, 41, 161, 109}}, {{201, 32, 172, 102}}, + {{227, 31, 143, 87}}, {{237, 22, 130, 92}}, {{255, 13, 149, 65}}, + {{241, 4, 152, 74}}, {{171, 115, 211, 35}}, {{165, 122, 222, 40}}, + {{183, 97, 201, 53}}, {{185, 104, 196, 62}}, {{147, 87, 231, 15}}, + {{157, 94, 234, 4}}, {{143, 69, 253, 25}}, {{129, 76, 240, 18}}, + {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, + {{ 41, 176, 124, 214}}, {{ 3, 143, 95, 231}}, {{ 13, 134, 82, 236}}, + {{ 31, 157, 69, 241}}, {{ 17, 148, 72, 250}}, {{ 75, 227, 3, 147}}, + {{ 69, 234, 14, 152}}, {{ 87, 241, 25, 133}}, {{ 89, 248, 20, 142}}, + {{115, 199, 55, 191}}, {{125, 206, 58, 180}}, {{111, 213, 45, 169}}, + {{ 97, 220, 32, 162}}, {{173, 118, 109, 246}}, {{163, 127, 96, 253}}, + {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149, 82, 89, 218}}, + {{155, 91, 84, 209}}, {{137, 64, 67, 204}}, {{135, 73, 78, 199}}, + {{221, 62, 5, 174}}, {{211, 55, 8, 165}}, {{193, 44, 31, 184}}, + {{207, 37, 18, 179}}, {{229, 26, 49, 130}}, {{235, 19, 60, 137}}, + {{249, 8, 43, 148}}, {{247, 1, 38, 159}}, {{ 77, 230, 189, 70}}, + {{ 67, 239, 176, 77}}, {{ 81, 244, 167, 80}}, {{ 95, 253, 170, 91}}, + {{117, 194, 137, 106}}, {{123, 203, 132, 97}}, {{105, 208, 147, 124}}, + {{103, 217, 158, 119}}, {{ 61, 174, 213, 30}}, {{ 51, 167, 216, 21}}, + {{ 33, 188, 207, 8}}, {{ 47, 181, 194, 3}}, {{ 5, 138, 225, 50}}, + {{ 11, 131, 236, 57}}, {{ 25, 152, 251, 36}}, {{ 23, 145, 246, 47}}, + {{118, 77, 214, 141}}, {{120, 68, 219, 134}}, {{106, 95, 204, 155}}, + {{100, 86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64, 96, 239, 170}}, + {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{ 6, 5, 190, 213}}, + {{ 8, 12, 179, 222}}, {{ 26, 23, 164, 195}}, {{ 20, 30, 169, 200}}, + {{ 62, 33, 138, 249}}, {{ 48, 40, 135, 242}}, {{ 34, 51, 144, 239}}, + {{ 44, 58, 157, 228}}, {{150, 221, 6, 61}}, {{152, 212, 11, 54}}, + {{138, 207, 28, 43}}, {{132, 198, 17, 32}}, {{174, 249, 50, 17}}, + {{160, 240, 63, 26}}, {{178, 235, 40, 7}}, {{188, 226, 37, 12}}, + {{230, 149, 110, 101}}, {{232, 156, 99, 110}}, {{250, 135, 116, 115}}, + {{244, 142, 121, 120}}, {{222, 177, 90, 73}}, {{208, 184, 87, 66}}, + {{194, 163, 64, 95}}, {{204, 170, 77, 84}}, {{ 65, 236, 218, 247}}, + {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, + {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, + {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, + {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{ 9, 128, 134, 131}}, + {{ 7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, + {{161, 124, 10, 71}}, {{175, 117, 7, 76}}, {{189, 110, 16, 81}}, + {{179, 103, 29, 90}}, {{153, 88, 62, 107}}, {{151, 81, 51, 96}}, + {{133, 74, 36, 125}}, {{139, 67, 41, 118}}, {{209, 52, 98, 31}}, + {{223, 61, 111, 20}}, {{205, 38, 120, 9}}, {{195, 47, 117, 2}}, + {{233, 16, 86, 51}}, {{231, 25, 91, 56}}, {{245, 2, 76, 37}}, + {{251, 11, 65, 46}}, {{154, 215, 97, 140}}, {{148, 222, 108, 135}}, + {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243, 85, 160}}, + {{172, 250, 88, 171}}, {{190, 225, 79, 182}}, {{176, 232, 66, 189}}, + {{234, 159, 9, 212}}, {{228, 150, 4, 223}}, {{246, 141, 19, 194}}, + {{248, 132, 30, 201}}, {{210, 187, 61, 248}}, {{220, 178, 48, 243}}, + {{206, 169, 39, 238}}, {{192, 160, 42, 229}}, {{122, 71, 177, 60}}, + {{116, 78, 188, 55}}, {{102, 85, 171, 42}}, {{104, 92, 166, 33}}, + {{ 66, 99, 133, 16}}, {{ 76, 106, 136, 27}}, {{ 94, 113, 159, 6}}, + {{ 80, 120, 146, 13}}, {{ 10, 15, 217, 100}}, {{ 4, 6, 212, 111}}, + {{ 22, 29, 195, 114}}, {{ 24, 20, 206, 121}}, {{ 50, 43, 237, 72}}, + {{ 60, 34, 224, 67}}, {{ 46, 57, 247, 94}}, {{ 32, 48, 250, 85}}, + {{236, 154, 183, 1}}, {{226, 147, 186, 10}}, {{240, 136, 173, 23}}, + {{254, 129, 160, 28}}, {{212, 190, 131, 45}}, {{218, 183, 142, 38}}, + {{200, 172, 153, 59}}, {{198, 165, 148, 48}}, {{156, 210, 223, 89}}, + {{146, 219, 210, 82}}, {{128, 192, 197, 79}}, {{142, 201, 200, 68}}, + {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241, 99}}, + {{182, 237, 252, 104}}, {{ 12, 10, 103, 177}}, {{ 2, 3, 106, 186}}, + {{ 16, 24, 125, 167}}, {{ 30, 17, 112, 172}}, {{ 52, 46, 83, 157}}, + {{ 58, 39, 94, 150}}, {{ 40, 60, 73, 139}}, {{ 38, 53, 68, 128}}, + {{124, 66, 15, 233}}, {{114, 75, 2, 226}}, {{ 96, 80, 21, 255}}, + {{110, 89, 24, 244}}, {{ 68, 102, 59, 197}}, {{ 74, 111, 54, 206}}, + {{ 88, 116, 33, 211}}, {{ 86, 125, 44, 216}}, {{ 55, 161, 12, 122}}, + {{ 57, 168, 1, 113}}, {{ 43, 179, 22, 108}}, {{ 37, 186, 27, 103}}, + {{ 15, 133, 56, 86}}, {{ 1, 140, 53, 93}}, {{ 19, 151, 34, 64}}, + {{ 29, 158, 47, 75}}, {{ 71, 233, 100, 34}}, {{ 73, 224, 105, 41}}, + {{ 91, 251, 126, 52}}, {{ 85, 242, 115, 63}}, {{127, 205, 80, 14}}, + {{113, 196, 93, 5}}, {{ 99, 223, 74, 24}}, {{109, 214, 71, 19}}, + {{215, 49, 220, 202}}, {{217, 56, 209, 193}}, {{203, 35, 198, 220}}, + {{197, 42, 203, 215}}, {{239, 21, 232, 230}}, {{225, 28, 229, 237}}, + {{243, 7, 242, 240}}, {{253, 14, 255, 251}}, {{167, 121, 180, 146}}, + {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181, 98, 163, 143}}, + {{159, 93, 128, 190}}, {{145, 84, 141, 181}}, {{131, 79, 154, 168}}, + {{141, 70, 151, 163}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 11, 14, 9, 13}}, {{ 22, 28, 18, 26}}, + {{ 29, 18, 27, 23}}, {{ 44, 56, 36, 52}}, {{ 39, 54, 45, 57}}, + {{ 58, 36, 54, 46}}, {{ 49, 42, 63, 35}}, {{ 88, 112, 72, 104}}, + {{ 83, 126, 65, 101}}, {{ 78, 108, 90, 114}}, {{ 69, 98, 83, 127}}, + {{116, 72, 108, 92}}, {{127, 70, 101, 81}}, {{ 98, 84, 126, 70}}, + {{105, 90, 119, 75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, + {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, + {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, + {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, + {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, + {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219, 59, 187}}, + {{112, 213, 50, 182}}, {{109, 199, 41, 161}}, {{102, 201, 32, 172}}, + {{ 87, 227, 31, 143}}, {{ 92, 237, 22, 130}}, {{ 65, 255, 13, 149}}, + {{ 74, 241, 4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, + {{ 53, 183, 97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147, 87, 231}}, + {{ 4, 157, 94, 234}}, {{ 25, 143, 69, 253}}, {{ 18, 129, 76, 240}}, + {{203, 59, 171, 107}}, {{192, 53, 162, 102}}, {{221, 39, 185, 113}}, + {{214, 41, 176, 124}}, {{231, 3, 143, 95}}, {{236, 13, 134, 82}}, + {{241, 31, 157, 69}}, {{250, 17, 148, 72}}, {{147, 75, 227, 3}}, + {{152, 69, 234, 14}}, {{133, 87, 241, 25}}, {{142, 89, 248, 20}}, + {{191, 115, 199, 55}}, {{180, 125, 206, 58}}, {{169, 111, 213, 45}}, + {{162, 97, 220, 32}}, {{246, 173, 118, 109}}, {{253, 163, 127, 96}}, + {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149, 82, 89}}, + {{209, 155, 91, 84}}, {{204, 137, 64, 67}}, {{199, 135, 73, 78}}, + {{174, 221, 62, 5}}, {{165, 211, 55, 8}}, {{184, 193, 44, 31}}, + {{179, 207, 37, 18}}, {{130, 229, 26, 49}}, {{137, 235, 19, 60}}, + {{148, 249, 8, 43}}, {{159, 247, 1, 38}}, {{ 70, 77, 230, 189}}, + {{ 77, 67, 239, 176}}, {{ 80, 81, 244, 167}}, {{ 91, 95, 253, 170}}, + {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, + {{119, 103, 217, 158}}, {{ 30, 61, 174, 213}}, {{ 21, 51, 167, 216}}, + {{ 8, 33, 188, 207}}, {{ 3, 47, 181, 194}}, {{ 50, 5, 138, 225}}, + {{ 57, 11, 131, 236}}, {{ 36, 25, 152, 251}}, {{ 47, 23, 145, 246}}, + {{141, 118, 77, 214}}, {{134, 120, 68, 219}}, {{155, 106, 95, 204}}, + {{144, 100, 86, 193}}, {{161, 78, 105, 226}}, {{170, 64, 96, 239}}, + {{183, 82, 123, 248}}, {{188, 92, 114, 245}}, {{213, 6, 5, 190}}, + {{222, 8, 12, 179}}, {{195, 26, 23, 164}}, {{200, 20, 30, 169}}, + {{249, 62, 33, 138}}, {{242, 48, 40, 135}}, {{239, 34, 51, 144}}, + {{228, 44, 58, 157}}, {{ 61, 150, 221, 6}}, {{ 54, 152, 212, 11}}, + {{ 43, 138, 207, 28}}, {{ 32, 132, 198, 17}}, {{ 17, 174, 249, 50}}, + {{ 26, 160, 240, 63}}, {{ 7, 178, 235, 40}}, {{ 12, 188, 226, 37}}, + {{101, 230, 149, 110}}, {{110, 232, 156, 99}}, {{115, 250, 135, 116}}, + {{120, 244, 142, 121}}, {{ 73, 222, 177, 90}}, {{ 66, 208, 184, 87}}, + {{ 95, 194, 163, 64}}, {{ 84, 204, 170, 77}}, {{247, 65, 236, 218}}, + {{252, 79, 229, 215}}, {{225, 93, 254, 192}}, {{234, 83, 247, 205}}, + {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, + {{198, 107, 211, 249}}, {{175, 49, 164, 178}}, {{164, 63, 173, 191}}, + {{185, 45, 182, 168}}, {{178, 35, 191, 165}}, {{131, 9, 128, 134}}, + {{136, 7, 137, 139}}, {{149, 21, 146, 156}}, {{158, 27, 155, 145}}, + {{ 71, 161, 124, 10}}, {{ 76, 175, 117, 7}}, {{ 81, 189, 110, 16}}, + {{ 90, 179, 103, 29}}, {{107, 153, 88, 62}}, {{ 96, 151, 81, 51}}, + {{125, 133, 74, 36}}, {{118, 139, 67, 41}}, {{ 31, 209, 52, 98}}, + {{ 20, 223, 61, 111}}, {{ 9, 205, 38, 120}}, {{ 2, 195, 47, 117}}, + {{ 51, 233, 16, 86}}, {{ 56, 231, 25, 91}}, {{ 37, 245, 2, 76}}, + {{ 46, 251, 11, 65}}, {{140, 154, 215, 97}}, {{135, 148, 222, 108}}, + {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243, 85}}, + {{171, 172, 250, 88}}, {{182, 190, 225, 79}}, {{189, 176, 232, 66}}, + {{212, 234, 159, 9}}, {{223, 228, 150, 4}}, {{194, 246, 141, 19}}, + {{201, 248, 132, 30}}, {{248, 210, 187, 61}}, {{243, 220, 178, 48}}, + {{238, 206, 169, 39}}, {{229, 192, 160, 42}}, {{ 60, 122, 71, 177}}, + {{ 55, 116, 78, 188}}, {{ 42, 102, 85, 171}}, {{ 33, 104, 92, 166}}, + {{ 16, 66, 99, 133}}, {{ 27, 76, 106, 136}}, {{ 6, 94, 113, 159}}, + {{ 13, 80, 120, 146}}, {{100, 10, 15, 217}}, {{111, 4, 6, 212}}, + {{114, 22, 29, 195}}, {{121, 24, 20, 206}}, {{ 72, 50, 43, 237}}, + {{ 67, 60, 34, 224}}, {{ 94, 46, 57, 247}}, {{ 85, 32, 48, 250}}, + {{ 1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, + {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, + {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, + {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, + {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, + {{104, 182, 237, 252}}, {{177, 12, 10, 103}}, {{186, 2, 3, 106}}, + {{167, 16, 24, 125}}, {{172, 30, 17, 112}}, {{157, 52, 46, 83}}, + {{150, 58, 39, 94}}, {{139, 40, 60, 73}}, {{128, 38, 53, 68}}, + {{233, 124, 66, 15}}, {{226, 114, 75, 2}}, {{255, 96, 80, 21}}, + {{244, 110, 89, 24}}, {{197, 68, 102, 59}}, {{206, 74, 111, 54}}, + {{211, 88, 116, 33}}, {{216, 86, 125, 44}}, {{122, 55, 161, 12}}, + {{113, 57, 168, 1}}, {{108, 43, 179, 22}}, {{103, 37, 186, 27}}, + {{ 86, 15, 133, 56}}, {{ 93, 1, 140, 53}}, {{ 64, 19, 151, 34}}, + {{ 75, 29, 158, 47}}, {{ 34, 71, 233, 100}}, {{ 41, 73, 224, 105}}, + {{ 52, 91, 251, 126}}, {{ 63, 85, 242, 115}}, {{ 14, 127, 205, 80}}, + {{ 5, 113, 196, 93}}, {{ 24, 99, 223, 74}}, {{ 19, 109, 214, 71}}, + {{202, 215, 49, 220}}, {{193, 217, 56, 209}}, {{220, 203, 35, 198}}, + {{215, 197, 42, 203}}, {{230, 239, 21, 232}}, {{237, 225, 28, 229}}, + {{240, 243, 7, 242}}, {{251, 253, 14, 255}}, {{146, 167, 121, 180}}, + {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181, 98, 163}}, + {{190, 159, 93, 128}}, {{181, 145, 84, 141}}, {{168, 131, 79, 154}}, + {{163, 141, 70, 151}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 13, 11, 14, 9}}, {{ 26, 22, 28, 18}}, + {{ 23, 29, 18, 27}}, {{ 52, 44, 56, 36}}, {{ 57, 39, 54, 45}}, + {{ 46, 58, 36, 54}}, {{ 35, 49, 42, 63}}, {{104, 88, 112, 72}}, + {{101, 83, 126, 65}}, {{114, 78, 108, 90}}, {{127, 69, 98, 83}}, + {{ 92, 116, 72, 108}}, {{ 81, 127, 70, 101}}, {{ 70, 98, 84, 126}}, + {{ 75, 105, 90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, + {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, + {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, + {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, + {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, + {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219, 59}}, + {{182, 112, 213, 50}}, {{161, 109, 199, 41}}, {{172, 102, 201, 32}}, + {{143, 87, 227, 31}}, {{130, 92, 237, 22}}, {{149, 65, 255, 13}}, + {{152, 74, 241, 4}}, {{211, 35, 171, 115}}, {{222, 40, 165, 122}}, + {{201, 53, 183, 97}}, {{196, 62, 185, 104}}, {{231, 15, 147, 87}}, + {{234, 4, 157, 94}}, {{253, 25, 143, 69}}, {{240, 18, 129, 76}}, + {{107, 203, 59, 171}}, {{102, 192, 53, 162}}, {{113, 221, 39, 185}}, + {{124, 214, 41, 176}}, {{ 95, 231, 3, 143}}, {{ 82, 236, 13, 134}}, + {{ 69, 241, 31, 157}}, {{ 72, 250, 17, 148}}, {{ 3, 147, 75, 227}}, + {{ 14, 152, 69, 234}}, {{ 25, 133, 87, 241}}, {{ 20, 142, 89, 248}}, + {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, + {{ 32, 162, 97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, + {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149, 82}}, + {{ 84, 209, 155, 91}}, {{ 67, 204, 137, 64}}, {{ 78, 199, 135, 73}}, + {{ 5, 174, 221, 62}}, {{ 8, 165, 211, 55}}, {{ 31, 184, 193, 44}}, + {{ 18, 179, 207, 37}}, {{ 49, 130, 229, 26}}, {{ 60, 137, 235, 19}}, + {{ 43, 148, 249, 8}}, {{ 38, 159, 247, 1}}, {{189, 70, 77, 230}}, + {{176, 77, 67, 239}}, {{167, 80, 81, 244}}, {{170, 91, 95, 253}}, + {{137, 106, 117, 194}}, {{132, 97, 123, 203}}, {{147, 124, 105, 208}}, + {{158, 119, 103, 217}}, {{213, 30, 61, 174}}, {{216, 21, 51, 167}}, + {{207, 8, 33, 188}}, {{194, 3, 47, 181}}, {{225, 50, 5, 138}}, + {{236, 57, 11, 131}}, {{251, 36, 25, 152}}, {{246, 47, 23, 145}}, + {{214, 141, 118, 77}}, {{219, 134, 120, 68}}, {{204, 155, 106, 95}}, + {{193, 144, 100, 86}}, {{226, 161, 78, 105}}, {{239, 170, 64, 96}}, + {{248, 183, 82, 123}}, {{245, 188, 92, 114}}, {{190, 213, 6, 5}}, + {{179, 222, 8, 12}}, {{164, 195, 26, 23}}, {{169, 200, 20, 30}}, + {{138, 249, 62, 33}}, {{135, 242, 48, 40}}, {{144, 239, 34, 51}}, + {{157, 228, 44, 58}}, {{ 6, 61, 150, 221}}, {{ 11, 54, 152, 212}}, + {{ 28, 43, 138, 207}}, {{ 17, 32, 132, 198}}, {{ 50, 17, 174, 249}}, + {{ 63, 26, 160, 240}}, {{ 40, 7, 178, 235}}, {{ 37, 12, 188, 226}}, + {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, + {{121, 120, 244, 142}}, {{ 90, 73, 222, 177}}, {{ 87, 66, 208, 184}}, + {{ 64, 95, 194, 163}}, {{ 77, 84, 204, 170}}, {{218, 247, 65, 236}}, + {{215, 252, 79, 229}}, {{192, 225, 93, 254}}, {{205, 234, 83, 247}}, + {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, + {{249, 198, 107, 211}}, {{178, 175, 49, 164}}, {{191, 164, 63, 173}}, + {{168, 185, 45, 182}}, {{165, 178, 35, 191}}, {{134, 131, 9, 128}}, + {{139, 136, 7, 137}}, {{156, 149, 21, 146}}, {{145, 158, 27, 155}}, + {{ 10, 71, 161, 124}}, {{ 7, 76, 175, 117}}, {{ 16, 81, 189, 110}}, + {{ 29, 90, 179, 103}}, {{ 62, 107, 153, 88}}, {{ 51, 96, 151, 81}}, + {{ 36, 125, 133, 74}}, {{ 41, 118, 139, 67}}, {{ 98, 31, 209, 52}}, + {{111, 20, 223, 61}}, {{120, 9, 205, 38}}, {{117, 2, 195, 47}}, + {{ 86, 51, 233, 16}}, {{ 91, 56, 231, 25}}, {{ 76, 37, 245, 2}}, + {{ 65, 46, 251, 11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, + {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, + {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, + {{ 9, 212, 234, 159}}, {{ 4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, + {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, + {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177, 60, 122, 71}}, + {{188, 55, 116, 78}}, {{171, 42, 102, 85}}, {{166, 33, 104, 92}}, + {{133, 16, 66, 99}}, {{136, 27, 76, 106}}, {{159, 6, 94, 113}}, + {{146, 13, 80, 120}}, {{217, 100, 10, 15}}, {{212, 111, 4, 6}}, + {{195, 114, 22, 29}}, {{206, 121, 24, 20}}, {{237, 72, 50, 43}}, + {{224, 67, 60, 34}}, {{247, 94, 46, 57}}, {{250, 85, 32, 48}}, + {{183, 1, 236, 154}}, {{186, 10, 226, 147}}, {{173, 23, 240, 136}}, + {{160, 28, 254, 129}}, {{131, 45, 212, 190}}, {{142, 38, 218, 183}}, + {{153, 59, 200, 172}}, {{148, 48, 198, 165}}, {{223, 89, 156, 210}}, + {{210, 82, 146, 219}}, {{197, 79, 128, 192}}, {{200, 68, 142, 201}}, + {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241, 99, 184, 228}}, + {{252, 104, 182, 237}}, {{103, 177, 12, 10}}, {{106, 186, 2, 3}}, + {{125, 167, 16, 24}}, {{112, 172, 30, 17}}, {{ 83, 157, 52, 46}}, + {{ 94, 150, 58, 39}}, {{ 73, 139, 40, 60}}, {{ 68, 128, 38, 53}}, + {{ 15, 233, 124, 66}}, {{ 2, 226, 114, 75}}, {{ 21, 255, 96, 80}}, + {{ 24, 244, 110, 89}}, {{ 59, 197, 68, 102}}, {{ 54, 206, 74, 111}}, + {{ 33, 211, 88, 116}}, {{ 44, 216, 86, 125}}, {{ 12, 122, 55, 161}}, + {{ 1, 113, 57, 168}}, {{ 22, 108, 43, 179}}, {{ 27, 103, 37, 186}}, + {{ 56, 86, 15, 133}}, {{ 53, 93, 1, 140}}, {{ 34, 64, 19, 151}}, + {{ 47, 75, 29, 158}}, {{100, 34, 71, 233}}, {{105, 41, 73, 224}}, + {{126, 52, 91, 251}}, {{115, 63, 85, 242}}, {{ 80, 14, 127, 205}}, + {{ 93, 5, 113, 196}}, {{ 74, 24, 99, 223}}, {{ 71, 19, 109, 214}}, + {{220, 202, 215, 49}}, {{209, 193, 217, 56}}, {{198, 220, 203, 35}}, + {{203, 215, 197, 42}}, {{232, 230, 239, 21}}, {{229, 237, 225, 28}}, + {{242, 240, 243, 7}}, {{255, 251, 253, 14}}, {{180, 146, 167, 121}}, + {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181, 98}}, + {{128, 190, 159, 93}}, {{141, 181, 145, 84}}, {{154, 168, 131, 79}}, + {{151, 163, 141, 70}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 9, 13, 11, 14}}, {{ 18, 26, 22, 28}}, + {{ 27, 23, 29, 18}}, {{ 36, 52, 44, 56}}, {{ 45, 57, 39, 54}}, + {{ 54, 46, 58, 36}}, {{ 63, 35, 49, 42}}, {{ 72, 104, 88, 112}}, + {{ 65, 101, 83, 126}}, {{ 90, 114, 78, 108}}, {{ 83, 127, 69, 98}}, + {{108, 92, 116, 72}}, {{101, 81, 127, 70}}, {{126, 70, 98, 84}}, + {{119, 75, 105, 90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, + {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, + {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, + {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, + {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, + {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, + {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, + {{ 31, 143, 87, 227}}, {{ 22, 130, 92, 237}}, {{ 13, 149, 65, 255}}, + {{ 4, 152, 74, 241}}, {{115, 211, 35, 171}}, {{122, 222, 40, 165}}, + {{ 97, 201, 53, 183}}, {{104, 196, 62, 185}}, {{ 87, 231, 15, 147}}, + {{ 94, 234, 4, 157}}, {{ 69, 253, 25, 143}}, {{ 76, 240, 18, 129}}, + {{171, 107, 203, 59}}, {{162, 102, 192, 53}}, {{185, 113, 221, 39}}, + {{176, 124, 214, 41}}, {{143, 95, 231, 3}}, {{134, 82, 236, 13}}, + {{157, 69, 241, 31}}, {{148, 72, 250, 17}}, {{227, 3, 147, 75}}, + {{234, 14, 152, 69}}, {{241, 25, 133, 87}}, {{248, 20, 142, 89}}, + {{199, 55, 191, 115}}, {{206, 58, 180, 125}}, {{213, 45, 169, 111}}, + {{220, 32, 162, 97}}, {{118, 109, 246, 173}}, {{127, 96, 253, 163}}, + {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82, 89, 218, 149}}, + {{ 91, 84, 209, 155}}, {{ 64, 67, 204, 137}}, {{ 73, 78, 199, 135}}, + {{ 62, 5, 174, 221}}, {{ 55, 8, 165, 211}}, {{ 44, 31, 184, 193}}, + {{ 37, 18, 179, 207}}, {{ 26, 49, 130, 229}}, {{ 19, 60, 137, 235}}, + {{ 8, 43, 148, 249}}, {{ 1, 38, 159, 247}}, {{230, 189, 70, 77}}, + {{239, 176, 77, 67}}, {{244, 167, 80, 81}}, {{253, 170, 91, 95}}, + {{194, 137, 106, 117}}, {{203, 132, 97, 123}}, {{208, 147, 124, 105}}, + {{217, 158, 119, 103}}, {{174, 213, 30, 61}}, {{167, 216, 21, 51}}, + {{188, 207, 8, 33}}, {{181, 194, 3, 47}}, {{138, 225, 50, 5}}, + {{131, 236, 57, 11}}, {{152, 251, 36, 25}}, {{145, 246, 47, 23}}, + {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, + {{ 86, 193, 144, 100}}, {{105, 226, 161, 78}}, {{ 96, 239, 170, 64}}, + {{123, 248, 183, 82}}, {{114, 245, 188, 92}}, {{ 5, 190, 213, 6}}, + {{ 12, 179, 222, 8}}, {{ 23, 164, 195, 26}}, {{ 30, 169, 200, 20}}, + {{ 33, 138, 249, 62}}, {{ 40, 135, 242, 48}}, {{ 51, 144, 239, 34}}, + {{ 58, 157, 228, 44}}, {{221, 6, 61, 150}}, {{212, 11, 54, 152}}, + {{207, 28, 43, 138}}, {{198, 17, 32, 132}}, {{249, 50, 17, 174}}, + {{240, 63, 26, 160}}, {{235, 40, 7, 178}}, {{226, 37, 12, 188}}, + {{149, 110, 101, 230}}, {{156, 99, 110, 232}}, {{135, 116, 115, 250}}, + {{142, 121, 120, 244}}, {{177, 90, 73, 222}}, {{184, 87, 66, 208}}, + {{163, 64, 95, 194}}, {{170, 77, 84, 204}}, {{236, 218, 247, 65}}, + {{229, 215, 252, 79}}, {{254, 192, 225, 93}}, {{247, 205, 234, 83}}, + {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, + {{211, 249, 198, 107}}, {{164, 178, 175, 49}}, {{173, 191, 164, 63}}, + {{182, 168, 185, 45}}, {{191, 165, 178, 35}}, {{128, 134, 131, 9}}, + {{137, 139, 136, 7}}, {{146, 156, 149, 21}}, {{155, 145, 158, 27}}, + {{124, 10, 71, 161}}, {{117, 7, 76, 175}}, {{110, 16, 81, 189}}, + {{103, 29, 90, 179}}, {{ 88, 62, 107, 153}}, {{ 81, 51, 96, 151}}, + {{ 74, 36, 125, 133}}, {{ 67, 41, 118, 139}}, {{ 52, 98, 31, 209}}, + {{ 61, 111, 20, 223}}, {{ 38, 120, 9, 205}}, {{ 47, 117, 2, 195}}, + {{ 16, 86, 51, 233}}, {{ 25, 91, 56, 231}}, {{ 2, 76, 37, 245}}, + {{ 11, 65, 46, 251}}, {{215, 97, 140, 154}}, {{222, 108, 135, 148}}, + {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243, 85, 160, 162}}, + {{250, 88, 171, 172}}, {{225, 79, 182, 190}}, {{232, 66, 189, 176}}, + {{159, 9, 212, 234}}, {{150, 4, 223, 228}}, {{141, 19, 194, 246}}, + {{132, 30, 201, 248}}, {{187, 61, 248, 210}}, {{178, 48, 243, 220}}, + {{169, 39, 238, 206}}, {{160, 42, 229, 192}}, {{ 71, 177, 60, 122}}, + {{ 78, 188, 55, 116}}, {{ 85, 171, 42, 102}}, {{ 92, 166, 33, 104}}, + {{ 99, 133, 16, 66}}, {{106, 136, 27, 76}}, {{113, 159, 6, 94}}, + {{120, 146, 13, 80}}, {{ 15, 217, 100, 10}}, {{ 6, 212, 111, 4}}, + {{ 29, 195, 114, 22}}, {{ 20, 206, 121, 24}}, {{ 43, 237, 72, 50}}, + {{ 34, 224, 67, 60}}, {{ 57, 247, 94, 46}}, {{ 48, 250, 85, 32}}, + {{154, 183, 1, 236}}, {{147, 186, 10, 226}}, {{136, 173, 23, 240}}, + {{129, 160, 28, 254}}, {{190, 131, 45, 212}}, {{183, 142, 38, 218}}, + {{172, 153, 59, 200}}, {{165, 148, 48, 198}}, {{210, 223, 89, 156}}, + {{219, 210, 82, 146}}, {{192, 197, 79, 128}}, {{201, 200, 68, 142}}, + {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241, 99, 184}}, + {{237, 252, 104, 182}}, {{ 10, 103, 177, 12}}, {{ 3, 106, 186, 2}}, + {{ 24, 125, 167, 16}}, {{ 17, 112, 172, 30}}, {{ 46, 83, 157, 52}}, + {{ 39, 94, 150, 58}}, {{ 60, 73, 139, 40}}, {{ 53, 68, 128, 38}}, + {{ 66, 15, 233, 124}}, {{ 75, 2, 226, 114}}, {{ 80, 21, 255, 96}}, + {{ 89, 24, 244, 110}}, {{102, 59, 197, 68}}, {{111, 54, 206, 74}}, + {{116, 33, 211, 88}}, {{125, 44, 216, 86}}, {{161, 12, 122, 55}}, + {{168, 1, 113, 57}}, {{179, 22, 108, 43}}, {{186, 27, 103, 37}}, + {{133, 56, 86, 15}}, {{140, 53, 93, 1}}, {{151, 34, 64, 19}}, + {{158, 47, 75, 29}}, {{233, 100, 34, 71}}, {{224, 105, 41, 73}}, + {{251, 126, 52, 91}}, {{242, 115, 63, 85}}, {{205, 80, 14, 127}}, + {{196, 93, 5, 113}}, {{223, 74, 24, 99}}, {{214, 71, 19, 109}}, + {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, + {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, + {{ 7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, + {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, + {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, + {{ 70, 151, 163, 141}}, + }, +}; + +const int xrcon[30] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, +}; + +const word8 xS[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, + 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, + 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, + 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, + 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, + 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, + 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, + 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, + 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, + 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, + 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, + 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, + 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, + 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, + 176, 84, 187, 22, +}; + +const word8 xSi[256] = { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, + 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, + 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, + 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, + 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, + 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, + 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, + 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, + 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, + 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, + 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, + 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, + 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, + 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, + 85, 33, 12, 125, +}; + diff --git a/src/aes/ao_aes_tables.h b/src/aes/ao_aes_tables.h new file mode 100644 index 00000000..73bcf3fb --- /dev/null +++ b/src/aes/ao_aes_tables.h @@ -0,0 +1,10 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +extern const word8x4 M0[4][256]; +extern const word8x4 M1[4][256]; +extern const int xrcon[30]; +extern const word8 xS[256]; +extern const word8 xSi[256]; + diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index 7f67374d..ab3e367e 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -29,9 +29,11 @@ enum ao_aes_mode { }; #if HAS_AES +#ifdef SDCC void ao_aes_isr(void) __interrupt 4; #endif +#endif void ao_aes_set_mode(enum ao_aes_mode mode); diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index e263f0db..7a377002 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -121,7 +121,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant } ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; ao_config_get(); @@ -233,9 +233,9 @@ radio_cmac_recv_cmd(void) __reentrant static __xdata struct ao_launch_command command; static __xdata struct ao_launch_query query; -static pdata uint16_t launch_serial; -static pdata uint8_t launch_channel; -static pdata uint16_t tick_offset; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; static void launch_args(void) __reentrant diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 3edfa41d..04404cdc 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -1,4 +1,4 @@ -vpath % ../stm:../product:../drivers:../core:../util:../kalman:.. +vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:.. vpath make-altitude ../util vpath make-kalman ../util vpath kalman.5c ../kalman -- cgit v1.2.3 From 843fcab46d633e5bb6959286adeb68e41a4c30a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:44:56 -0700 Subject: altos: Add telefire-v0.1 Signed-off-by: Keith Packard --- src/Makefile | 3 +- src/cc1111/ao_adc.c | 20 ++++ src/cc1111/ao_arch.h | 12 --- src/cc1111/ao_pins.h | 12 +++ src/core/ao.h | 7 ++ src/core/ao_config.c | 3 + src/core/ao_storage.c | 1 + src/drivers/ao_74hc497.c | 40 +++++++ src/drivers/ao_74hc497.h | 27 +++++ src/drivers/ao_pad.c | 227 ++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_pad.h | 67 ++++++++++++ src/drivers/ao_pca9922.c | 78 ++++++++++++++ src/telefire-v0.1/Makefile | 101 ++++++++++++++++++ src/telefire-v0.1/ao_pins.h | 94 +++++++++++++++++ src/telefire-v0.1/ao_telefire.c | 41 ++++++++ 15 files changed, 720 insertions(+), 13 deletions(-) create mode 100644 src/drivers/ao_74hc497.c create mode 100644 src/drivers/ao_74hc497.h create mode 100644 src/drivers/ao_pad.c create mode 100644 src/drivers/ao_pad.h create mode 100644 src/drivers/ao_pca9922.c create mode 100644 src/telefire-v0.1/Makefile create mode 100644 src/telefire-v0.1/ao_pins.h create mode 100644 src/telefire-v0.1/ao_telefire.c diff --git a/src/Makefile b/src/Makefile index 491618f6..99ea8f85 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,8 @@ ifneq ($(shell which sdcc),) telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 tidongle test \ - teleterra-v0.2 teleshield-v0.1 + teleterra-v0.2 teleshield-v0.1 \ + telefire-v0.1 endif ifneq ($(shell which avr-gcc),) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ce827e25..f7b52281 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -140,6 +140,15 @@ ao_adc_isr(void) __interrupt 1 } #endif /* telemini || telenano */ +#ifdef TELEFIRE_V_0_1 + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence); + a[0] = ADCL; + a[1] = ADCH; + if (sequence < 5) + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); +#define GOT_ADC +#endif /* TELEFIRE_V_0_1 */ + #ifndef GOT_ADC #error No known ADC configuration set #endif @@ -157,9 +166,13 @@ ao_adc_dump(void) __reentrant { static __xdata struct ao_data packet; ao_data_get(&packet); +#ifndef AO_ADC_DUMP printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); +#else + AO_ADC_DUMP(&packet); +#endif } __code struct ao_cmds ao_adc_cmds[] = { @@ -170,6 +183,11 @@ __code struct ao_cmds ao_adc_cmds[] = { void ao_adc_init(void) { +#ifdef AO_ADC_PINS + ADCCFG = AO_ADC_PINS; + +#else + #if IGNITE_ON_P2 /* TeleMetrum configuration */ ADCCFG = ((1 << 0) | /* acceleration */ @@ -190,6 +208,8 @@ ao_adc_init(void) (1 << 3)); /* battery voltage */ #endif +#endif /* else AO_ADC_PINS */ + /* enable interrupts */ ADCIF = 0; IEN0 |= IEN0_ADCIE; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 06b04b93..a97515a7 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -200,18 +200,6 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } -struct ao_adc { - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -#if HAS_ACCEL_REF - uint16_t accel_ref; /* acceleration reference */ -#endif -}; - #define AO_DATA_RING 32 /* ao_button.c */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index fc6ed3ec..2f0e2884 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -560,4 +560,16 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +struct ao_adc { + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +#if HAS_ACCEL_REF + uint16_t accel_ref; /* acceleration reference */ +#endif +}; + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 65b9eb18..1032dd33 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -432,6 +432,7 @@ ao_gps_report_mega_init(void); * ao_telemetry_orig.c */ +#if LEGACY_MONITOR struct ao_adc_orig { uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ @@ -489,6 +490,8 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +#endif /* LEGACY_MONITOR */ + /* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method * for reporting RSSI. So, now we use these values everywhere */ @@ -582,6 +585,8 @@ ao_radio_init(void); * ao_monitor.c */ +#if HAS_MONITOR + extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 @@ -618,6 +623,8 @@ ao_monitor_enable(void); void ao_monitor_init(void) __reentrant; +#endif + /* * ao_stdio.c */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e2095e65..f19dd9cd 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -17,8 +17,11 @@ #include "ao.h" #include "ao_log.h" +#include +#if HAS_FLIGHT #include #include +#endif __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index b2dd435b..adf7e4d4 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -16,6 +16,7 @@ */ #include +#include uint8_t ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c new file mode 100644 index 00000000..93c544c3 --- /dev/null +++ b/src/drivers/ao_74hc497.c @@ -0,0 +1,40 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +/* + * 74HC597 driver. + * Reads a single byte from the shift register + */ + +#include +#include + +uint8_t +ao_74hc497_read(void) +{ + static __xdata state; + ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&state, 1, AO_74HC497_SPI_BUS); + ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS); + return state; +} + +void +ao_74hc497_init(void) +{ + ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1); +} diff --git a/src/drivers/ao_74hc497.h b/src/drivers/ao_74hc497.h new file mode 100644 index 00000000..6df7bcae --- /dev/null +++ b/src/drivers/ao_74hc497.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_74HC497_H_ +#define _AO_74HC497_H_ + +uint8_t +ao_74hc497_read(void); + +void +ao_74hc497_init(void); + +#endif /* _AO_74HC497_H_ */ diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c new file mode 100644 index 00000000..21aa788d --- /dev/null +++ b/src/drivers/ao_pad.c @@ -0,0 +1,227 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include +#include + +__xdata uint8_t ao_pad_ignite; + +#define ao_pad_igniter_status(c) AO_PAD_IGNITER_STATUS_UNKNOWN +#define ao_pad_arm_status() AO_PAD_ARM_STATUS_UNKNOWN + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +static void +ao_pad_run(void) +{ + for (;;) { + while (!ao_pad_ignite) + ao_sleep(&ao_pad_ignite); + /* + * Actually set the pad bits + */ + AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | ao_pad_ignite; + while (ao_pad_ignite) { + ao_pad_ignite = 0; + ao_delay(AO_PAD_FIRE_TIME); + } + AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); + } +} + +static void +ao_pad_status(void) +{ + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); +#if 0 + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } +#endif + } +} + +static __pdata uint8_t ao_pad_armed; +static __pdata uint16_t ao_pad_arm_time; +static __pdata uint8_t ao_pad_box; + +static void +ao_pad(void) +{ + static __xdata struct ao_pad_command command; + static __xdata struct ao_pad_query query; + int16_t time_difference; + uint8_t c; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_pad_box = ao_74hc497_read(); + for (;;) { + flush(); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + PRINTD ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + switch (command.cmd) { + case AO_LAUNCH_ARM: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + if (command.channels & ~(AO_PAD_ALL_PINS)) + break; + + time_difference = command.tick - ao_time(); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time difference too large %d\n", time_difference); + break; + } + PRINTD ("armed\n"); + ao_pad_armed = command.channels; + ao_pad_arm_time = ao_time(); + + /* fall through ... */ + + case AO_LAUNCH_QUERY: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + query.tick = ao_time(); + query.box = ao_pad_box; + query.channels = AO_PAD_ALL_PINS; + query.armed = ao_pad_armed; + query.arm_status = ao_pad_arm_status(); + for (c = 0; c < AO_PAD_NUM; c++) + query.igniter_status[c] = ao_pad_igniter_status(c); + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); + break; + case AO_LAUNCH_FIRE: + if (!ao_pad_armed) { + PRINTD ("not armed\n"); + break; + } + if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late pad arm_time %d time %d\n", + ao_pad_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time different too large %d\n", time_difference); + break; + } + PRINTD ("ignite\n"); + ao_pad_ignite = ao_pad_armed; + ao_wakeup(&ao_pad_ignite); + break; + } + } +} + +void +ao_pad_test(void) +{ +#if 0 + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +#endif +} + +void +ao_pad_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_pad_ignite = 1; + ao_wakeup(&ao_pad_ignite); +} + +static __xdata struct ao_task ao_pad_task; +static __xdata struct ao_task ao_pad_ignite_task; +static __xdata struct ao_task ao_pad_status_task; + +__code struct ao_cmds ao_pad_cmds[] = { + { ao_pad_test, "t\0Test pad continuity" }, + { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; + +void +ao_pad_init(void) +{ +#if AO_PAD_NUM > 0 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); +#endif +#if AO_PAD_NUM > 1 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); +#endif +#if AO_PAD_NUM > 2 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); +#endif +#if AO_PAD_NUM > 3 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif + ao_cmd_register(&ao_pad_cmds[0]); + ao_add_task(&ao_pad_task, ao_pad, "pad listener"); + ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter"); + ao_add_task(&ao_pad_status_task, ao_pad_status, "pad status"); +} diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h new file mode 100644 index 00000000..9ea016ff --- /dev/null +++ b/src/drivers/ao_pad.h @@ -0,0 +1,67 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PAD_H_ +#define _AO_PAD_H_ + +#define AO_PAD_MAX_CHANNELS 8 + +struct ao_pad_command { + uint16_t tick; + uint16_t box; + uint8_t cmd; + uint8_t channels; +}; + +/* Report current telefire status. + */ + +#define AO_PAD_QUERY 1 + +struct ao_pad_query { + uint16_t tick; /* telefire tick */ + uint16_t box; /* telefire box number */ + uint8_t channels; /* which chanels are present */ + uint8_t armed; /* which channels are armed */ + uint8_t arm_status; /* status of arming switch */ + uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */ +}; + +/* Set current armed pads, report back status + */ + +#define AO_PAD_ARM 2 + +/* Fire current armed pads for 200ms, no report + */ +#define AO_PAD_FIRE 3 + +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) + +#define AO_PAD_ARM_STATUS_DISARMED 0 +#define AO_PAD_ARM_STATUS_ARMED 1 +#define AO_PAD_ARM_STATUS_UNKNOWN 2 + +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN 0 +#define AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN 1 +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED 2 +#define AO_PAD_IGNITER_STATUS_UNKNOWN 3 + +void +ao_pad_init(void); + +#endif /* _AO_PAD_H_ */ diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c new file mode 100644 index 00000000..dc006f55 --- /dev/null +++ b/src/drivers/ao_pca9922.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +/* + * PCA9922 LED driver. This uses SPI to send a single byte to the device to + * set the current state of the LEDs using the existing LED interface + */ + +#include + +static __xdata uint8_t ao_led_state; + +static void +ao_led_apply(void) +{ + /* Don't try the SPI bus during initialization */ + if (!ao_cur_task) + return; + ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS); + ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS); +} + +void +ao_led_on(uint8_t colors) +{ + ao_led_state |= colors; + ao_led_apply(); +} + +void +ao_led_off(uint8_t colors) +{ + ao_led_state &= ~colors; + ao_led_apply(); +} + +void +ao_led_set(uint8_t colors) +{ + ao_led_state = colors; + ao_led_apply(); +} + +void +ao_led_toggle(uint8_t colors) +{ + ao_led_state ^= colors; + ao_led_apply(); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1); +} diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile new file mode 100644 index 00000000..09cb88fb --- /dev/null +++ b/src/telefire-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# TeleFire build file +# + +TELEFIRE_VER=0.1 +TELEFIRE_DEF=0_1 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_freq.c + +CC1111_SRC = \ + ao_adc.c \ + ao_aes.c \ + ao_beep.c \ + ao_dma.c \ + ao_intflash.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_pca9922.c \ + ao_74hc497.c \ + ao_pad.c + +PRODUCT_SRC = \ + ao_telefire.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telefire-v$(TELEFIRE_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleFire-v$(TELEFIRE_VER) +PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_DEF) +IDPRODUCT=0x000f +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h new file mode 100644 index 00000000..4cf523fc --- /dev/null +++ b/src/telefire-v0.1/ao_pins.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define USE_INTERNAL_FLASH 1 +#define DBG_ON_P1 0 +#define IGNITE_ON_P2 0 +#define IGNITE_ON_P1 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_LED_RED 2 +#define AO_LED_GREEN 1 +#define LEDS_AVAILABLE (0xff) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define AO_74HC497_CS_PORT P1 +#define AO_74HC497_CS_PIN 4 +#define AO_74HC497_CS P1_4 + +#define AO_PCA9922_CS_PORT P1 +#define AO_PCA9922_CS_PIN 4 +#define AO_PCA9922_CS P1_4 + +#define AO_PAD_NUM 4 +#define AO_PAD_PORT P1 +#define AO_PAD_DIR P1DIR +#define AO_PAD_PIN_0 0 +#define AO_PAD_0 P1_0 +#define AO_PAD_PIN_1 1 +#define AO_PAD_1 P1_1 +#define AO_PAD_PIN_2 2 +#define AO_PAD_2 P1_2 +#define AO_PAD_PIN_3 3 +#define AO_PAD_3 P1_3 +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +struct ao_adc { + int16_t sense[4]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.sense[2], \ + (p)->adc.sense[3], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c new file mode 100644 index 00000000..96413a63 --- /dev/null +++ b/src/telefire-v0.1/ao_telefire.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_aes_init(); + ao_radio_cmac_init(); + ao_pad_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 2e7e304e67bc1e094282c8668fa8cccf09f9c9b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:48:08 -0700 Subject: altos: Add driver for STM internal flash Signed-off-by: Keith Packard --- src/stm/ao_eeprom_stm.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 24 ++++++ 2 files changed, 215 insertions(+) create mode 100644 src/stm/ao_eeprom_stm.c diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c new file mode 100644 index 00000000..1e51b417 --- /dev/null +++ b/src/stm/ao_eeprom_stm.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 +#include + +/* Total bytes of available storage */ +ao_pos_t ao_storage_total = 4096; + +/* Block size - device is erased in these units. */ +ao_pos_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +ao_pos_t ao_storage_config = 0; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +uint16_t ao_storage_unit = 1024; + +/* Location of eeprom in address space */ +#define stm_eeprom ((uint8_t *) 0x08080000) + +/* + * The internal flash chip is arranged in 8 byte sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(ao_pos_t pos) __reentrant +{ + /* Not necessary */ + return 1; +} + +static void +ao_intflash_unlock(void) +{ + /* Unlock Data EEPROM and FLASH_PECR register */ + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; + + /* Configure the FTDW bit (FLASH_PECR[8]) to execute + * word write, whatever the previous value of the word + * being written to + */ + stm_flash.pecr = ((0 << STM_FLASH_PECR_OBL_LAUNCH) | + (0 << STM_FLASH_PECR_ERRIE) | + (0 << STM_FLASH_PECR_EOPIE) | + (0 << STM_FLASH_PECR_FPRG) | + (0 << STM_FLASH_PECR_ERASE) | + (0 << STM_FLASH_PECR_FTDW) | + (1 << STM_FLASH_PECR_DATA) | + (0 << STM_FLASH_PECR_PROG) | + (0 << STM_FLASH_PECR_OPTLOCK) | + (0 << STM_FLASH_PECR_PRGLOCK) | + (0 << STM_FLASH_PECR_PELOCK)); +} + +static void +ao_intflash_lock(void) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK); +} + +static void +ao_intflash_write32(uint16_t pos, uint32_t w) +{ + uint32_t *addr; + + addr = (uint32_t *) (stm_eeprom + pos); + + /* Write a word to a valid address in the data EEPROM */ + *addr = w; + + /* Wait for the flash unit to go idle */ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +static void +ao_intflash_write8(uint16_t pos, uint8_t d) +{ + uint32_t w, *addr, mask; + uint8_t shift; + + addr = (uint32_t *) (stm_eeprom + (pos & ~3)); + + /* Compute word to be written */ + shift = (pos & 3) << 3; + mask = 0xff << shift; + w = (*addr & ~mask) | (d << shift); + + ao_intflash_write32(pos & ~3, w); +} + +static uint8_t +ao_intflash_read(uint16_t pos) +{ + return stm_eeprom[pos]; +} + +/* + * Write to flash + */ + +uint8_t +ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_intflash_unlock(); + while (len) { + if ((pos & 3) == 0 && len >= 4) { + uint32_t w; + + w = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); + ao_intflash_write32(pos, w); + pos += 4; + d += 4; + len -= 4; + } else { + ao_intflash_write8(pos, *d); + pos += 1; + d += 1; + len -= 1; + } + } + ao_intflash_lock(); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant +{ + uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len--) + *d++ = ao_intflash_read(pos++); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash\n"); +} + +void +ao_storage_device_init(void) +{ +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index ff8dddff..4d665e8b 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -281,6 +281,30 @@ extern struct stm_flash stm_flash; #define STM_FLASH_ACR_PRFEN (1) #define STM_FLASH_ACR_LATENCY (0) +#define STM_FLASH_PECR_OBL_LAUNCH 18 +#define STM_FLASH_PECR_ERRIE 17 +#define STM_FLASH_PECR_EOPIE 16 +#define STM_FLASH_PECR_FPRG 10 +#define STM_FLASH_PECR_ERASE 9 +#define STM_FLASH_PECR_FTDW 8 +#define STM_FLASH_PECR_DATA 4 +#define STM_FLASH_PECR_PROG 3 +#define STM_FLASH_PECR_OPTLOCK 2 +#define STM_FLASH_PECR_PRGLOCK 1 +#define STM_FLASH_PECR_PELOCK 0 + +#define STM_FLASH_SR_OPTVERR 11 +#define STM_FLASH_SR_SIZERR 10 +#define STM_FLASH_SR_PGAERR 9 +#define STM_FLASH_SR_WRPERR 8 +#define STM_FLASH_SR_READY 3 +#define STM_FLASH_SR_ENDHV 2 +#define STM_FLASH_SR_EOP 1 +#define STM_FLASH_SR_BSY 0 + +#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF +#define STM_FLASH_PEKEYR_PEKEY2 0x02030405 + struct stm_rcc { vuint32_t cr; vuint32_t icscr; -- cgit v1.2.3 From fb79f8fb358f8df25674336cd558fc3998cb7d9e Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Tue, 31 Jul 2012 20:04:34 +1200 Subject: Don't build ao-stmload if stlink is not available. Signed-off-by: Mike Beattie --- ao-tools/ao-stmload/Makefile.am | 4 ++++ configure.ac | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ao-tools/ao-stmload/Makefile.am b/ao-tools/ao-stmload/Makefile.am index 375896ea..5aea7db4 100644 --- a/ao-tools/ao-stmload/Makefile.am +++ b/ao-tools/ao-stmload/Makefile.am @@ -1,3 +1,5 @@ +if LIBSTLINK + bin_PROGRAMS=ao-stmload LIBSTLINKDIR=/local/src/stlink @@ -9,3 +11,5 @@ ao_stmload_LDADD=$(LIBSTLINK_LIBS) $(LIBUSB_LIBS) -lelf ao_stmload_SOURCES=ao-stmload.c man_MANS = ao-stmload.1 + +endif diff --git a/configure.ac b/configure.ac index c59261af..a54ef626 100644 --- a/configure.ac +++ b/configure.ac @@ -139,7 +139,9 @@ PKG_CHECK_MODULES([LIBUSB], [libusb-1.0]) AC_CHECK_HEADERS(libelf.h libelf/libelf.h, [break]) AC_CHECK_HEADERS(gelf.h libelf/gelf.h, [break]) -PKG_CHECK_MODULES([LIBSTLINK], [stlink]) +PKG_CHECK_MODULES([LIBSTLINK], [stlink], [HAVE_STLINK=yes], [HAVE_STLINK=no]) + +AM_CONDITIONAL([LIBSTLINK], [test x$HAVE_STLINK != xno]) AC_OUTPUT([ Makefile -- cgit v1.2.3 From c56dead72f65e7468017656347dba531ab2ca480 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Tue, 31 Jul 2012 20:05:35 +1200 Subject: Ignore autogenerated file: altosui/Info.plist Signed-off-by: Mike Beattie --- altosui/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/altosui/.gitignore b/altosui/.gitignore index 6d65611f..6d2d8c23 100644 --- a/altosui/.gitignore +++ b/altosui/.gitignore @@ -5,6 +5,7 @@ fat/ Manifest.txt Manifest-fat.txt AltosVersion.java +Info.plist libaltosJNI classes altosui -- cgit v1.2.3 From 599e28b2242c79bdd0960ef16e580e51a2fa3795 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 2 Aug 2012 21:16:54 +1200 Subject: Re-work external lib support for newer Android SDK * Remove older *.properties methods of locating lib dir * clean up Eclipse classpath file * adjust Makefile.am to link AltosLib.jar into libs/ Signed-off-by: Mike Beattie --- altosdroid/.classpath | 4 ++-- altosdroid/.gitignore | 1 - altosdroid/Makefile.am | 13 ++++++++----- altosdroid/build.properties | 1 - altosdroid/libs/.gitignore | 1 + altosdroid/local.properties.in | 1 - 6 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 altosdroid/build.properties create mode 100644 altosdroid/libs/.gitignore diff --git a/altosdroid/.classpath b/altosdroid/.classpath index d260cafa..0ca188f9 100644 --- a/altosdroid/.classpath +++ b/altosdroid/.classpath @@ -1,8 +1,8 @@ - - + + diff --git a/altosdroid/.gitignore b/altosdroid/.gitignore index 44f249ee..c0bb8dd4 100644 --- a/altosdroid/.gitignore +++ b/altosdroid/.gitignore @@ -1,4 +1,3 @@ local.properties bin gen -local.properties diff --git a/altosdroid/Makefile.am b/altosdroid/Makefile.am index 0732087b..6ee984c2 100644 --- a/altosdroid/Makefile.am +++ b/altosdroid/Makefile.am @@ -15,6 +15,11 @@ APKBUILDER=$(SDK)/tools/apkbuilder ZIPALIGN=$(SDK)/tools/zipalign SRC_DIR=src/org/altusmetrum/AltosDroid +EXT_LIBDIR=libs +ALTOSLIB_SRCDIR=../altoslib +ALTOSLIB_JAR=AltosLib.jar + +ALTOSLIB=$(EXT_LIBDIR)/$(ALTOSLIB_JAR) SRC=\ $(SRC_DIR)/AltosDroid.java \ @@ -25,11 +30,9 @@ SRC=\ all: $(all_target) -ALTOSLIB=bin/classes/AltosLib.jar - -$(ALTOSLIB): - mkdir -p bin/classes - cd bin/classes && ln -s ../../../altoslib/AltosLib.jar . +$(ALTOSLIB): $(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) + mkdir -p $(EXT_LIBDIR) + cd $(EXT_LIBDIR) && ln -s $(shell echo $(EXT_LIBDIR) | sed 's|[^/]\+|..|g')/$(ALTOSLIB_SRCDIR)/$(ALTOSLIB_JAR) . if ANDROID install-release: bin/AltosDroid-release.apk diff --git a/altosdroid/build.properties b/altosdroid/build.properties deleted file mode 100644 index 63d080cc..00000000 --- a/altosdroid/build.properties +++ /dev/null @@ -1 +0,0 @@ -jar.libs.dir=../altoslib \ No newline at end of file diff --git a/altosdroid/libs/.gitignore b/altosdroid/libs/.gitignore new file mode 100644 index 00000000..b4e68f63 --- /dev/null +++ b/altosdroid/libs/.gitignore @@ -0,0 +1 @@ +AltosLib.jar diff --git a/altosdroid/local.properties.in b/altosdroid/local.properties.in index 543ce208..14df0494 100644 --- a/altosdroid/local.properties.in +++ b/altosdroid/local.properties.in @@ -8,4 +8,3 @@ # For customization when using a Version Control System, please read the # header note. sdk.dir=@ANDROID_SDK@ -extensible.libs.classpath=../altoslib -- cgit v1.2.3 From c5304ac976dd44344a0b70ae3622e1f2d112a147 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 2 Aug 2012 21:20:23 +1200 Subject: Fix min/target SDK versions Signed-off-by: Mike Beattie --- altosdroid/AndroidManifest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosdroid/AndroidManifest.xml b/altosdroid/AndroidManifest.xml index 1d55737d..96fe5ac7 100644 --- a/altosdroid/AndroidManifest.xml +++ b/altosdroid/AndroidManifest.xml @@ -17,7 +17,7 @@ package="org.altusmetrum.AltosDroid" android:versionCode="1" android:versionName="1.0"> - + -- cgit v1.2.3 From 359d7353fd7b7d4d537db04c5e89724502333ff8 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Thu, 2 Aug 2012 22:09:24 +1200 Subject: AltosDroid: Begin re-working Bluetooth code * Move to using explicit 'magic' UUID, rather than java reflection * Re-work UI to make it more useful for testing * Use Insecure RFCOMM only, and remove code that differentiates. Signed-off-by: Mike Beattie --- altosdroid/res/layout/main.xml | 24 +++-- altosdroid/res/menu/option_menu.xml | 12 +-- altosdroid/res/values/strings.xml | 14 +-- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 111 ++++++++------------- .../AltosDroid/BluetoothChatService.java | 54 ++++------ 5 files changed, 83 insertions(+), 132 deletions(-) diff --git a/altosdroid/res/layout/main.xml b/altosdroid/res/layout/main.xml index 17025f6b..f2e6640c 100644 --- a/altosdroid/res/layout/main.xml +++ b/altosdroid/res/layout/main.xml @@ -19,24 +19,30 @@ android:layout_width="match_parent" android:layout_height="match_parent" > - + android:gravity="bottom" + android:scrollbars="vertical" + android:typeface="monospace" /> + - + android:layout_weight="1" + android:inputType="text|textNoSuggestions" /> + - - - - - diff --git a/altosdroid/res/layout/telemetry_service_controller.xml b/altosdroid/res/layout/telemetry_service_controller.xml deleted file mode 100644 index 189d2f6c..00000000 --- a/altosdroid/res/layout/telemetry_service_controller.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/altosdroid/res/menu/option_menu.xml b/altosdroid/res/menu/option_menu.xml index feb5668e..6946e298 100644 --- a/altosdroid/res/menu/option_menu.xml +++ b/altosdroid/res/menu/option_menu.xml @@ -17,10 +17,4 @@ - -

diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 72a4ddec..e3234fc7 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -36,31 +36,11 @@ Connect a device - Control Service - (Un)Bind Service - - AltosDroid Telemetry Service Telemetry Service Started Telemetry Service Stopped - - Telemetry Service Controller - Use the following buttons to start and stop the Telemetry - service. - Start Service - Stop Service - - Telemetry Service Binding - This demonstrates how you can connect with a persistent - service. Notice how it automatically starts for you, and play around with the - interaction between this and Local Service Controller. - Bind Service - Unbind Service - - Connected to local service - Disconnected from local service diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 29d72d95..92ba5587 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -321,14 +321,6 @@ public class AltosDroid extends Activity { public boolean onOptionsItemSelected(MenuItem item) { Intent serverIntent = null; switch (item.getItemId()) { - case R.id.telemetry_service_control: - serverIntent = new Intent(this, TelemetryServiceActivities.Controller.class); - startActivity(serverIntent); - return true; - case R.id.telemetry_service_bind: - serverIntent = new Intent(this, TelemetryServiceActivities.Binding.class); - startActivity(serverIntent); - return true; case R.id.connect_scan: // Launch the DeviceListActivity to see devices and do scan serverIntent = new Intent(this, DeviceListActivity.class); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index a1c5fede..95b655c2 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -67,7 +67,7 @@ public class TelemetryService extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, TelemetryServiceActivities.Controller.class), 0); + new Intent(this, AltosDroid.class), 0); // Set the info for the views that show in the notification panel. notification.setLatestEventInfo(this, getText(R.string.telemetry_service_label), text, contentIntent); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java deleted file mode 100644 index 5191cfa9..00000000 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryServiceActivities.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.altusmetrum.AltosDroid; - -import org.altusmetrum.AltosDroid.R; - -import android.app.Activity; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Bundle; -import android.os.IBinder; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.Toast; - -public class TelemetryServiceActivities { - /** - *

Example of explicitly starting and stopping the local service. - * This demonstrates the implementation of a service that runs in the same - * process as the rest of the application, which is explicitly started and stopped - * as desired.

- * - *

Note that this is implemented as an inner class only keep the sample - * all together; typically this code would appear in some separate class. - */ - public static class Controller extends Activity { - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.telemetry_service_controller); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.start); - button.setOnClickListener(mStartListener); - button = (Button)findViewById(R.id.stop); - button.setOnClickListener(mStopListener); - } - - private OnClickListener mStartListener = new OnClickListener() { - public void onClick(View v) { - // Make sure the service is started. It will continue running - // until someone calls stopService(). The Intent we use to find - // the service explicitly specifies our service component, because - // we want it running in our own process and don't want other - // applications to replace it. - startService(new Intent(Controller.this, - TelemetryService.class)); - } - }; - - private OnClickListener mStopListener = new OnClickListener() { - public void onClick(View v) { - // Cancel a previous call to startService(). Note that the - // service will not actually stop at this point if there are - // still bound clients. - stopService(new Intent(Controller.this, - TelemetryService.class)); - } - }; - } - - // ---------------------------------------------------------------------- - - /** - * Example of binding and unbinding to the local service. - * This demonstrates the implementation of a service which the client will - * bind to, receiving an object through which it can communicate with the service.

- * - *

Note that this is implemented as an inner class only keep the sample - * all together; typically this code would appear in some separate class. - */ - public static class Binding extends Activity { - private boolean mIsBound; - - - private TelemetryService mBoundService; - - private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - // This is called when the connection with the service has been - // established, giving us the service object we can use to - // interact with the service. Because we have bound to a explicit - // service that we know is running in our own process, we can - // cast its IBinder to a concrete class and directly access it. - mBoundService = ((TelemetryService.TelemetryBinder)service).getService(); - - // Tell the user about this for our demo. - Toast.makeText(Binding.this, R.string.telemetry_service_connected, - Toast.LENGTH_SHORT).show(); - } - - public void onServiceDisconnected(ComponentName className) { - // This is called when the connection with the service has been - // unexpectedly disconnected -- that is, its process crashed. - // Because it is running in our same process, we should never - // see this happen. - mBoundService = null; - Toast.makeText(Binding.this, R.string.telemetry_service_disconnected, - Toast.LENGTH_SHORT).show(); - } - }; - - void doBindService() { - // Establish a connection with the service. We use an explicit - // class name because we want a specific service implementation that - // we know will be running in our own process (and thus won't be - // supporting component replacement by other applications). - bindService(new Intent(Binding.this, - TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - - void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - doUnbindService(); - } - - - private OnClickListener mBindListener = new OnClickListener() { - public void onClick(View v) { - doBindService(); - } - }; - - private OnClickListener mUnbindListener = new OnClickListener() { - public void onClick(View v) { - doUnbindService(); - } - }; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setContentView(R.layout.telemetry_service_binding); - - // Watch for button clicks. - Button button = (Button)findViewById(R.id.bind); - button.setOnClickListener(mBindListener); - button = (Button)findViewById(R.id.unbind); - button.setOnClickListener(mUnbindListener); - } - } -} -- cgit v1.2.3 From 80bf63702175322053f2b38c4fff56b653ab7c70 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 14:52:30 +1200 Subject: altosdroid: excise BluetoothChatService example code Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 75 +---- .../AltosDroid/BluetoothChatService.java | 354 --------------------- 2 files changed, 11 insertions(+), 418 deletions(-) delete mode 100644 altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 92ba5587..521588fb 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -64,10 +64,6 @@ public class AltosDroid extends Activity { private EditText mOutEditText; private Button mSendButton; - // String buffer for outgoing messages - private StringBuffer mOutStringBuffer; - // Member object for the chat services - private BluetoothChatService mChatService = null; // Intent request codes private static final int REQUEST_CONNECT_DEVICE = 1; private static final int REQUEST_ENABLE_BT = 2; @@ -115,7 +111,7 @@ public class AltosDroid extends Activity { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableIntent, REQUEST_ENABLE_BT); } else { - if (mChatService == null) setupChat(); + //if (mChatService == null) setupChat(); } } @@ -127,13 +123,13 @@ public class AltosDroid extends Activity { // Performing this check in onResume() covers the case in which BT was // not enabled during onStart(), so we were paused to enable it... // onResume() will be called when ACTION_REQUEST_ENABLE activity returns. - if (mChatService != null) { - // Only if the state is STATE_NONE, do we know that we haven't started already - if (mChatService.getState() == BluetoothChatService.STATE_NONE) { - // Start the Bluetooth chat services - mChatService.start(); - } - } + //if (mChatService != null) { + // Only if the state is STATE_NONE, do we know that we haven't started already + //if (mChatService.getState() == BluetoothChatService.STATE_NONE) { + // Start the Bluetooth chat services + //mChatService.start(); + //} + //} } @Override @@ -151,13 +147,12 @@ public class AltosDroid extends Activity { @Override public void onDestroy() { super.onDestroy(); - // Stop the Bluetooth chat services - if (mChatService != null) mChatService.stop(); if(D) Log.e(TAG, "--- ON DESTROY ---"); } +/* private void setupChat() { Log.d(TAG, "setupChat()"); @@ -187,6 +182,7 @@ public class AltosDroid extends Activity { // Initialize the buffer for outgoing messages mOutStringBuffer = new StringBuffer(""); } +*/ /** * Sends a message. @@ -228,54 +224,6 @@ public class AltosDroid extends Activity { }; */ - // The Handler that gets information back from the BluetoothChatService - private final Handler mHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_STATE_CHANGE: - if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1); - switch (msg.arg1) { - case BluetoothChatService.STATE_CONNECTED: - mTitle.setText(R.string.title_connected_to); - mTitle.append(mConnectedDeviceName); - mSerialView.setText(""); - break; - case BluetoothChatService.STATE_CONNECTING: - mTitle.setText(R.string.title_connecting); - break; - case BluetoothChatService.STATE_READY: - case BluetoothChatService.STATE_NONE: - mTitle.setText(R.string.title_not_connected); - break; - } - break; - case MESSAGE_WRITE: - byte[] writeBuf = (byte[]) msg.obj; - // construct a string from the buffer - String writeMessage = new String(writeBuf); - mSerialView.append(writeMessage + '\n'); - break; - case MESSAGE_READ: - byte[] readBuf = (byte[]) msg.obj; - // construct a string from the valid bytes in the buffer - String readMessage = new String(readBuf, 0, msg.arg1); - mSerialView.append(readMessage); - break; - case MESSAGE_DEVICE_NAME: - // save the connected device's name - mConnectedDeviceName = msg.getData().getString(DEVICE_NAME); - Toast.makeText(getApplicationContext(), "Connected to " - + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); - break; - case MESSAGE_TOAST: - Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST), - Toast.LENGTH_SHORT).show(); - break; - } - } - }; - public void onActivityResult(int requestCode, int resultCode, Intent data) { if(D) Log.d(TAG, "onActivityResult " + resultCode); switch (requestCode) { @@ -289,7 +237,7 @@ public class AltosDroid extends Activity { // When the request to enable Bluetooth returns if (resultCode == Activity.RESULT_OK) { // Bluetooth is now enabled, so set up a chat session - setupChat(); + //setupChat(); } else { // User did not enable Bluetooth or an error occured Log.d(TAG, "BT not enabled"); @@ -306,7 +254,6 @@ public class AltosDroid extends Activity { // Get the BLuetoothDevice object BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device - mChatService.connect(device); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java b/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java deleted file mode 100644 index a93c08d6..00000000 --- a/altosdroid/src/org/altusmetrum/AltosDroid/BluetoothChatService.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.altusmetrum.AltosDroid; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.UUID; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothSocket; -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.util.Log; - -/** - * This class does all the work for setting up and managing Bluetooth - * connections with other devices. It has a thread that listens for - * incoming connections, a thread for connecting with a device, and a - * thread for performing data transmissions when connected. - */ -public class BluetoothChatService { - // Debugging - private static final String TAG = "BluetoothChatService"; - private static final boolean D = true; - - // Member fields - private final BluetoothAdapter mAdapter; - private final Handler mHandler; - private ConnectThread mConnectThread; - private ConnectedThread mConnectedThread; - private int mState; - - // Constants that indicate the current connection state - public static final int STATE_NONE = 0; // we're doing nothing - public static final int STATE_READY = 1; - public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection - public static final int STATE_CONNECTED = 3; // now connected to a remote device - - /** - * Constructor. Prepares a new BluetoothChat session. - * @param context The UI Activity Context - * @param handler A Handler to send messages back to the UI Activity - */ - public BluetoothChatService(Context context, Handler handler) { - mAdapter = BluetoothAdapter.getDefaultAdapter(); - mState = STATE_NONE; - mHandler = handler; - } - - /** - * Set the current state of the chat connection - * @param state An integer defining the current connection state - */ - private synchronized void setState(int state) { - if (D) Log.d(TAG, "setState() " + mState + " -> " + state); - mState = state; - - // Give the new state to the Handler so the UI Activity can update - mHandler.obtainMessage(AltosDroid.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); - } - - /** - * Return the current connection state. */ - public synchronized int getState() { - return mState; - } - - /** - * Start the chat service. Specifically start AcceptThread to begin a - * session in listening (server) mode. Called by the Activity onResume() */ - public synchronized void start() { - if (D) Log.d(TAG, "start"); - - // Cancel any thread attempting to make a connection - if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} - - // Cancel any thread currently running a connection - if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} - - setState(STATE_READY); - - } - - /** - * Start the ConnectThread to initiate a connection to a remote device. - * @param device The BluetoothDevice to connect - */ - public synchronized void connect(BluetoothDevice device) { - if (D) Log.d(TAG, "connect to: " + device); - - // Cancel any thread attempting to make a connection - if (mState == STATE_CONNECTING) { - if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} - } - - // Cancel any thread currently running a connection - if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} - - // Start the thread to connect with the given device - mConnectThread = new ConnectThread(device); - mConnectThread.start(); - setState(STATE_CONNECTING); - } - - /** - * Start the ConnectedThread to begin managing a Bluetooth connection - * @param socket The BluetoothSocket on which the connection was made - * @param device The BluetoothDevice that has been connected - */ - public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) { - if (D) Log.d(TAG, "connected"); - - // Cancel the thread that completed the connection - if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} - - // Cancel any thread currently running a connection - if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} - - // Start the thread to manage the connection and perform transmissions - mConnectedThread = new ConnectedThread(socket); - mConnectedThread.start(); - - // Send the name of the connected device back to the UI Activity - Message msg = mHandler.obtainMessage(AltosDroid.MESSAGE_DEVICE_NAME); - Bundle bundle = new Bundle(); - bundle.putString(AltosDroid.DEVICE_NAME, device.getName()); - msg.setData(bundle); - mHandler.sendMessage(msg); - - setState(STATE_CONNECTED); - } - - /** - * Stop all threads - */ - public synchronized void stop() { - if (D) Log.d(TAG, "stop"); - - if (mConnectThread != null) { - mConnectThread.cancel(); - mConnectThread = null; - } - - if (mConnectedThread != null) { - mConnectedThread.cancel(); - mConnectedThread = null; - } - - setState(STATE_NONE); - } - - /** - * Write to the ConnectedThread in an unsynchronized manner - * @param out The bytes to write - * @see ConnectedThread#write(byte[]) - */ - public void write(byte[] out) { - // Create temporary object - ConnectedThread r; - // Synchronize a copy of the ConnectedThread - synchronized (this) { - if (mState != STATE_CONNECTED) return; - r = mConnectedThread; - } - // Perform the write unsynchronized - r.write(out); - } - - /** - * Indicate that the connection attempt failed and notify the UI Activity. - */ - private void connectionFailed() { - // Send a failure message back to the Activity - Message msg = mHandler.obtainMessage(AltosDroid.MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(AltosDroid.TOAST, "Unable to connect device"); - msg.setData(bundle); - mHandler.sendMessage(msg); - - // Start the service over to restart listening mode - BluetoothChatService.this.start(); - } - - /** - * Indicate that the connection was lost and notify the UI Activity. - */ - private void connectionLost() { - // Send a failure message back to the Activity - Message msg = mHandler.obtainMessage(AltosDroid.MESSAGE_TOAST); - Bundle bundle = new Bundle(); - bundle.putString(AltosDroid.TOAST, "Device connection was lost"); - msg.setData(bundle); - mHandler.sendMessage(msg); - - // Start the service over to restart listening mode - BluetoothChatService.this.start(); - } - - - /** - * This thread runs while attempting to make an outgoing connection - * with a device. It runs straight through; the connection either - * succeeds or fails. - */ - private class ConnectThread extends Thread { - private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - private final BluetoothSocket mmSocket; - private final BluetoothDevice mmDevice; - - public ConnectThread(BluetoothDevice device) { - mmDevice = device; - BluetoothSocket tmp = null; - - try { - tmp = mmDevice.createInsecureRfcommSocketToServiceRecord(SPP_UUID); - } catch (IOException e) { - e.printStackTrace(); - } - mmSocket = tmp; - } - - public void run() { - Log.i(TAG, "BEGIN mConnectThread"); - setName("ConnectThread"); - - // Always cancel discovery because it will slow down a connection - mAdapter.cancelDiscovery(); - - // Make a connection to the BluetoothSocket - try { - // This is a blocking call and will only return on a - // successful connection or an exception - mmSocket.connect(); - } catch (IOException e) { - // Close the socket - try { - mmSocket.close(); - } catch (IOException e2) { - Log.e(TAG, "unable to close() socket during connection failure", e2); - } - connectionFailed(); - return; - } - - // Reset the ConnectThread because we're done - synchronized (BluetoothChatService.this) { - mConnectThread = null; - } - - // Start the connected thread - connected(mmSocket, mmDevice); - } - - public void cancel() { - try { - mmSocket.close(); - } catch (IOException e) { - Log.e(TAG, "close() of connect socket failed", e); - } - } - } - - /** - * This thread runs during a connection with a remote device. - * It handles all incoming and outgoing transmissions. - */ - private class ConnectedThread extends Thread { - private final BluetoothSocket mmSocket; - private final InputStream mmInStream; - private final OutputStream mmOutStream; - - public ConnectedThread(BluetoothSocket socket) { - Log.d(TAG, "create ConnectedThread"); - mmSocket = socket; - InputStream tmpIn = null; - OutputStream tmpOut = null; - - // Get the BluetoothSocket input and output streams - try { - tmpIn = socket.getInputStream(); - tmpOut = socket.getOutputStream(); - } catch (IOException e) { - Log.e(TAG, "temp sockets not created", e); - } - - mmInStream = tmpIn; - mmOutStream = tmpOut; - } - - public void run() { - Log.i(TAG, "BEGIN mConnectedThread"); - byte[] buffer = new byte[1024]; - int bytes; - - // Keep listening to the InputStream while connected - while (true) { - try { - // Read from the InputStream - bytes = mmInStream.read(buffer); - - // Send the obtained bytes to the UI Activity - mHandler.obtainMessage(AltosDroid.MESSAGE_READ, bytes, -1, buffer.clone()) - .sendToTarget(); - } catch (IOException e) { - Log.e(TAG, "disconnected", e); - connectionLost(); - break; - } - } - } - - /** - * Write to the connected OutStream. - * @param buffer The bytes to write - */ - public void write(byte[] buffer) { - try { - mmOutStream.write(buffer); - mmOutStream.write('\n'); - - // Share the sent message back to the UI Activity - mHandler.obtainMessage(AltosDroid.MESSAGE_WRITE, -1, -1, buffer) - .sendToTarget(); - } catch (IOException e) { - Log.e(TAG, "Exception during write", e); - } - } - - public void cancel() { - try { - mmSocket.close(); - } catch (IOException e) { - Log.e(TAG, "close() of connect socket failed", e); - } - } - } -} -- cgit v1.2.3 From 917f519a4e876087590a3a260fbbccf4c0ac3e31 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 14:54:06 +1200 Subject: altosdroid: remove UI components/imports no longer used Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 521588fb..a39dfa5d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -26,16 +26,16 @@ import android.os.Handler; import android.os.Message; import android.text.method.ScrollingMovementMethod; import android.util.Log; -import android.view.KeyEvent; +//import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; +//import android.view.View; import android.view.Window; -import android.view.View.OnClickListener; -import android.view.inputmethod.EditorInfo; -import android.widget.Button; -import android.widget.EditText; +//import android.view.View.OnClickListener; +//import android.view.inputmethod.EditorInfo; +//import android.widget.Button; +//import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import org.altusmetrum.AltosDroid.R; @@ -61,8 +61,6 @@ public class AltosDroid extends Activity { public static final String TOAST = "toast"; - private EditText mOutEditText; - private Button mSendButton; // Intent request codes private static final int REQUEST_CONNECT_DEVICE = 1; @@ -71,6 +69,8 @@ public class AltosDroid extends Activity { // Layout Views private TextView mTitle; private TextView mSerialView; + //private EditText mOutEditText; + //private Button mSendButton; // Name of the connected device private String mConnectedDeviceName = null; // Local Bluetooth adapter -- cgit v1.2.3 From 3f3da6626ef41b2cab116d6299d2a89cbf7718a9 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 14:54:54 +1200 Subject: altosdroid: Re-locate TextView initialisation Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index a39dfa5d..c18a73f8 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -93,6 +93,11 @@ public class AltosDroid extends Activity { mTitle.setText(R.string.app_name); mTitle = (TextView) findViewById(R.id.title_right_text); + mSerialView = (TextView) findViewById(R.id.in); + mSerialView.setMovementMethod(new ScrollingMovementMethod()); + mSerialView.setClickable(false); + mSerialView.setLongClickable(false); + // If the adapter is null, then Bluetooth is not supported if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); @@ -156,11 +161,6 @@ public class AltosDroid extends Activity { private void setupChat() { Log.d(TAG, "setupChat()"); - mSerialView = (TextView) findViewById(R.id.in); - mSerialView.setMovementMethod(new ScrollingMovementMethod()); - mSerialView.setClickable(false); - mSerialView.setLongClickable(false); - // Initialize the compose field with a listener for the return key mOutEditText = (EditText) findViewById(R.id.edit_text_out); mOutEditText.setOnEditorActionListener(mWriteListener); -- cgit v1.2.3 From cfe93315fc0e4b01a95b8e59f24aca96b5a66daf Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 14:55:19 +1200 Subject: altosdroid: whitespace Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index c18a73f8..5b48d571 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -86,8 +86,6 @@ public class AltosDroid extends Activity { setContentView(R.layout.main); getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title); - // Get local Bluetooth adapter - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // Set up the custom title mTitle = (TextView) findViewById(R.id.title_left_text); mTitle.setText(R.string.app_name); @@ -98,6 +96,9 @@ public class AltosDroid extends Activity { mSerialView.setClickable(false); mSerialView.setLongClickable(false); + // Get local Bluetooth adapter + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + // If the adapter is null, then Bluetooth is not supported if (mBluetoothAdapter == null) { Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show(); -- cgit v1.2.3 From 95a34caa8343997bcf7d8969ee8ae3124efcb573 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 14:57:04 +1200 Subject: altosdroid: Remove AltosLib import from main thread --- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 5b48d571..8abc8a7b 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -39,7 +39,6 @@ import android.view.Window; import android.widget.TextView; import android.widget.Toast; import org.altusmetrum.AltosDroid.R; -import org.altusmetrum.AltosLib.*; /** * This is the main Activity that displays the current chat session. -- cgit v1.2.3 From ffdfc08c317f503e30604d058749b24c3ca7bafa Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:00:23 +1200 Subject: altosdroid: Add service start/bind/unbind to AltosDroid Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 8abc8a7b..54b61c67 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -21,9 +21,15 @@ import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Intent; +import android.content.Context; +import android.content.ComponentName; +import android.content.ServiceConnection; +import android.os.IBinder; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.os.Messenger; +import android.os.RemoteException; import android.text.method.ScrollingMovementMethod; import android.util.Log; //import android.view.KeyEvent; @@ -70,11 +76,30 @@ public class AltosDroid extends Activity { private TextView mSerialView; //private EditText mOutEditText; //private Button mSendButton; + + private boolean mIsBound; + Messenger mService = null; + // Name of the connected device private String mConnectedDeviceName = null; // Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; + }; + + + private ServiceConnection mConnection = new ServiceConnection() { + public void onServiceConnected(ComponentName className, IBinder service) { + mService = new Messenger(service); + } + + public void onServiceDisconnected(ComponentName className) { + // This is called when the connection with the service has been unexpectedly disconnected - process crashed. + mService = null; + } + }; + + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -105,6 +130,10 @@ public class AltosDroid extends Activity { return; } + // Start Telemetry Service + startService(new Intent(AltosDroid.this, TelemetryService.class)); + + doBindService(); } @Override @@ -152,6 +181,9 @@ public class AltosDroid extends Activity { @Override public void onDestroy() { super.onDestroy(); + + doUnbindService(); + if(D) Log.e(TAG, "--- ON DESTROY ---"); } @@ -277,4 +309,19 @@ public class AltosDroid extends Activity { return false; } + + void doBindService() { + bindService(new Intent(this, TelemetryService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } + + void doUnbindService() { + if (mIsBound) { + // If we have received the service, and hence registered with it, then now is the time to unregister. + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } + } + } -- cgit v1.2.3 From c9689a3ef65ea9da5a7009834add789737ffb6a9 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:03:54 +1200 Subject: altosdroid: Clean up imports in TelemetryService * Begin adding AltosLib usage Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/TelemetryService.java | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 95b655c2..7d0f7a70 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -29,12 +29,15 @@ import android.widget.Toast; // Need the following import to get access to the app resources, since this // class is in a sub-package. -import org.altusmetrum.AltosDroid.R; - +//import org.altusmetrum.AltosDroid.R; +import org.altusmetrum.AltosLib.*; public class TelemetryService extends Service { + private static final String TAG = "TelemetryService"; + private static final boolean D = true; + /** * Class for clients to access. Because we know this service always * runs in the same process as its clients, we don't need to deal with @@ -50,6 +53,13 @@ public class TelemetryService extends Service { private int NOTIFICATION = R.string.telemetry_service_label; private NotificationManager mNM; + + // Name of the connected device + private String mConnectedDeviceName = null; + private AltosBluetooth mAltosBluetooth = null; + + LinkedBlockingQueue telem; + @Override public void onCreate() { // Create a reference to the NotificationManager so that we can update our notifcation text later -- cgit v1.2.3 From bad155538c4630c62ade80afd20830aad37c287e Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:10:15 +1200 Subject: altosdroid: AltosBluetooth.java * Clean up imports * Convert from reflection to using Well Known UUID for SPP. * clean up local variables * Add debug conditionals to logging * remove references to socket type Signed-off-by: Mike Beattie --- .../org/altusmetrum/AltosDroid/AltosBluetooth.java | 58 ++++++++-------------- 1 file changed, 21 insertions(+), 37 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 390dccdb..1f094679 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -21,14 +21,11 @@ package org.altusmetrum.AltosDroid; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.lang.reflect.Method; +import java.util.UUID; + import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; -import android.content.Context; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; import android.util.Log; import org.altusmetrum.AltosLib.*; @@ -52,35 +49,22 @@ public class AltosBluetooth extends AltosLink { private OutputStream output; private class ConnectThread extends Thread { - private final BluetoothDevice mmDevice; - private String mSocketType; - BluetoothSocket tmp_socket; + private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); - public ConnectThread(BluetoothDevice device, boolean secure) { - mmDevice = device; - mSocketType = secure ? "Secure" : "Insecure"; + public ConnectThread(BluetoothDevice device) { + BluetoothSocket tmp_socket = null; - // Get a BluetoothSocket for a connection with the - // given BluetoothDevice try { - if (secure) { - Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); - tmp_socket = (BluetoothSocket) m.invoke(device, 2); - // tmp = device.createRfcommSocket(2); - } else { - Method m = device.getClass().getMethod("createInsecureRfcommSocket", new Class[] {int.class}); - tmp_socket = (BluetoothSocket) m.invoke(device, 2); - // tmp = device.createInsecureRfcommSocket(2); - } - } catch (Exception e) { - Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e); + tmp_socket = device.createInsecureRfcommSocketToServiceRecord(SPP_UUID); + } catch (IOException e) { e.printStackTrace(); } + socket = tmp_socket; } public void run() { - Log.i(TAG, "BEGIN connect_thread SocketType:" + mSocketType); - setName("ConnectThread" + mSocketType); + if (D) Log.i(TAG, "BEGIN ConnectThread"); + setName("ConnectThread"); // Always cancel discovery because it will slow down a connection adapter.cancelDiscovery(); @@ -89,14 +73,13 @@ public class AltosBluetooth extends AltosLink { try { // This is a blocking call and will only return on a // successful connection or an exception - tmp_socket.connect(); + socket.connect(); } catch (IOException e) { // Close the socket try { - tmp_socket.close(); + socket.close(); } catch (IOException e2) { - Log.e(TAG, "unable to close() " + mSocketType + - " socket during connection failure", e2); + if (D) Log.e(TAG, "unable to close() socket during connection failure", e2); } connection_failed(); return; @@ -104,25 +87,26 @@ public class AltosBluetooth extends AltosLink { try { synchronized (AltosBluetooth.this) { - input = tmp_socket.getInputStream(); - output = tmp_socket.getOutputStream(); - socket = tmp_socket; + input = socket.getInputStream(); + output = socket.getOutputStream(); + // Reset the ConnectThread because we're done AltosBluetooth.this.notify(); connect_thread = null; + if (D) Log.i(TAG, "Completed connect"); } } catch (Exception e) { - Log.e(TAG, "Failed to finish connection", e); + if (D) Log.e(TAG, "Failed to finish connection", e); e.printStackTrace(); } } public void cancel() { try { - if (tmp_socket != null) - tmp_socket.close(); + if (socket != null) + socket.close(); } catch (IOException e) { - Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e); + if (D) Log.e(TAG, "close() of connect socket failed", e); } } } -- cgit v1.2.3 From d184638be79dafd6fb43df21040eb52402f54ea5 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:11:12 +1200 Subject: altosdroid: AltosBluetooth.java * clean up variables/comments Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 1f094679..4c1f09a2 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -36,17 +36,13 @@ public class AltosBluetooth extends AltosLink { private static final String TAG = "AltosBluetooth"; private static final boolean D = true; - /** - * This thread runs while attempting to make an outgoing connection - * with a device. It runs straight through; the connection either - * succeeds or fails. - */ - - private BluetoothAdapter adapter; - private ConnectThread connect_thread; - private BluetoothSocket socket; - private InputStream input; - private OutputStream output; + private ConnectThread connect_thread = null; + + private BluetoothAdapter adapter; + private BluetoothDevice device; + private BluetoothSocket socket; + private InputStream input; + private OutputStream output; private class ConnectThread extends Thread { private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); -- cgit v1.2.3 From b59e7d0b201290f2cb0fd494ef28c1402e11ba3b Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:18:44 +1200 Subject: altosdroid: clean up stub functions in AltosBluetooth.java Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 4c1f09a2..79e31e89 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -149,20 +149,12 @@ public class AltosBluetooth extends AltosLink { } } - public void flush_output() { - super.flush_output(); - /* any local work needed to flush bluetooth? */ - } - public boolean can_cancel_reply() { - return false; - } - public boolean show_reply_timeout() { - return true; - } - - public void hide_reply_timeout() { - } + //public void flush_output() { super.flush_output(); } + + public boolean can_cancel_reply() { return false; } + public boolean show_reply_timeout() { return true; } + public void hide_reply_timeout() { } public AltosBluetooth(BluetoothDevice device) { adapter = BluetoothAdapter.getDefaultAdapter(); -- cgit v1.2.3 From 5ce132b3366cd120499fcbe22b5fbe96d21b8584 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:20:42 +1200 Subject: altosdroid: Move constructor for AltosBluetooth Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 79e31e89..32140b3c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -44,6 +44,15 @@ public class AltosBluetooth extends AltosLink { private InputStream input; private OutputStream output; + // Constructor + public AltosBluetooth(BluetoothDevice in_device) { + adapter = BluetoothAdapter.getDefaultAdapter(); + + + connect_thread = new ConnectThread(device); + connect_thread.start(); + } + private class ConnectThread extends Thread { private final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); @@ -156,9 +165,4 @@ public class AltosBluetooth extends AltosLink { public boolean show_reply_timeout() { return true; } public void hide_reply_timeout() { } - public AltosBluetooth(BluetoothDevice device) { - adapter = BluetoothAdapter.getDefaultAdapter(); - connect_thread = new ConnectThread(device, true); - connect_thread.start(); - } -} \ No newline at end of file +} -- cgit v1.2.3 From fb8cd14cca61ca59b95c23e71505607b4509d4ed Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:21:36 +1200 Subject: altosdroid: Add input thread for reading from TBT Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 32140b3c..4c3f979d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -37,6 +37,7 @@ public class AltosBluetooth extends AltosLink { private static final boolean D = true; private ConnectThread connect_thread = null; + private Thread input_thread = null; private BluetoothAdapter adapter; private BluetoothDevice device; @@ -51,6 +52,9 @@ public class AltosBluetooth extends AltosLink { connect_thread = new ConnectThread(device); connect_thread.start(); + + input_thread = new Thread(this); + input_thread.start(); } private class ConnectThread extends Thread { @@ -155,6 +159,13 @@ public class AltosBluetooth extends AltosLink { connect_thread.cancel(); connect_thread = null; } + if (input_thread != null) { + try { + input_thread.interrupt(); + input_thread.join(); + } catch (Exception e) {} + input_thread = null; + } } } -- cgit v1.2.3 From ef29a197ce3318404f37e8a0b24d235e8b024a1f Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:21:57 +1200 Subject: altosdroid: Add debugging statements to AltosBluetooth Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 4c3f979d..db63b342 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -127,13 +127,16 @@ public class AltosBluetooth extends AltosLink { } private void connection_failed() { + if (D) Log.i(TAG, "Bluetooth Connection failed!"); } public void print(String data) { byte[] bytes = data.getBytes(); try { + if (D) Log.i(TAG, "Entering print();"); wait_connected(); output.write(bytes); + if (D) Log.i(TAG, "Writing bytes: '" + data + "'"); } catch (IOException e) { connection_failed(); } catch (InterruptedException e) { -- cgit v1.2.3 From bcd53483ccf4bbb2f163a011faae6d19a7bbed0d Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:22:23 +1200 Subject: altosdroid: Add TBT initialisation to AltosBluetooth Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index db63b342..6b86a153 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -99,6 +99,10 @@ public class AltosBluetooth extends AltosLink { input = socket.getInputStream(); output = socket.getOutputStream(); + // Configure the newly connected device for telemetry + print("~\nE 0\n"); + set_monitor(false); + // Reset the ConnectThread because we're done AltosBluetooth.this.notify(); connect_thread = null; -- cgit v1.2.3 From b69796991c1da6baf245349fcc4392668b9b5570 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:23:17 +1200 Subject: altosdroid: begin adding IPC to main thread Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 87 +++++++++++++++++++--- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index 54b61c67..c1b9c654 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -54,18 +54,15 @@ public class AltosDroid extends Activity { private static final String TAG = "AltosDroid"; private static final boolean D = true; - // Message types sent from the BluetoothChatService Handler - public static final int MESSAGE_STATE_CHANGE = 1; - public static final int MESSAGE_READ = 2; - public static final int MESSAGE_WRITE = 3; - public static final int MESSAGE_DEVICE_NAME = 4; - public static final int MESSAGE_TOAST = 5; - - // Key names received from the BluetoothChatService Handler - public static final String DEVICE_NAME = "device_name"; - public static final String TOAST = "toast"; - + // Message types sent from the TelemetryService Handler + public static final int MSG_STATE_CHANGE = 1; + public static final int MSG_DEVNAME = 2; + public static final int MSG_INCOMING_TELEM = 3; + public static final int MSG_TOAST = 4; + // Key names received from the TelemetryService Handler + public static final String KEY_DEVNAME = "key_devname"; + public static final String KEY_TOAST = "key_toast"; // Intent request codes private static final int REQUEST_CONNECT_DEVICE = 1; @@ -79,18 +76,69 @@ public class AltosDroid extends Activity { private boolean mIsBound; Messenger mService = null; + final Messenger mMessenger = new Messenger(new IncomingHandler()); // Name of the connected device private String mConnectedDeviceName = null; // Local Bluetooth adapter private BluetoothAdapter mBluetoothAdapter = null; + + // The Handler that gets information back from the Telemetry Service + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_STATE_CHANGE: + if(D) Log.i(TAG, "MSG_STATE_CHANGE: " + msg.arg1); + switch (msg.arg1) { + case TelemetryService.STATE_CONNECTED: + mTitle.setText(R.string.title_connected_to); + mTitle.append(mConnectedDeviceName); + mSerialView.setText(""); + break; + case TelemetryService.STATE_CONNECTING: + mTitle.setText(R.string.title_connecting); + break; + case TelemetryService.STATE_READY: + case TelemetryService.STATE_NONE: + mTitle.setText(R.string.title_not_connected); + break; + } + break; + case MSG_INCOMING_TELEM: + byte[] buf = (byte[]) msg.obj; + // construct a string from the buffer + String telem = new String(buf); + mSerialView.append(telem); + break; + case MSG_DEVNAME: + // save the connected device's name + mConnectedDeviceName = msg.getData().getString(KEY_DEVNAME); + Toast.makeText(getApplicationContext(), "Connected to " + + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); + break; + case MSG_TOAST: + Toast.makeText( + getApplicationContext(), + msg.getData().getString(KEY_TOAST), + Toast.LENGTH_SHORT).show(); + break; + } + } }; private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mService = new Messenger(service); + try { + Message msg = Message.obtain(null, TelemetryService.MSG_REGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + } catch (RemoteException e) { + // In this case the service has crashed before we could even do anything with it + } } public void onServiceDisconnected(ComponentName className) { @@ -286,6 +334,14 @@ public class AltosDroid extends Activity { // Get the BLuetoothDevice object BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); // Attempt to connect to the device + try { + //Message msg = Message.obtain(null, TelemetryService.MSG_CONNECT_TELEBT); + //msg.obj = device; + //mService.send(msg); + mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT_TELEBT, device)); + } catch (RemoteException e) { + e.printStackTrace(); + } } @@ -318,6 +374,15 @@ public class AltosDroid extends Activity { void doUnbindService() { if (mIsBound) { // If we have received the service, and hence registered with it, then now is the time to unregister. + if (mService != null) { + try { + Message msg = Message.obtain(null, TelemetryService.MSG_UNREGISTER_CLIENT); + msg.replyTo = mMessenger; + mService.send(msg); + } catch (RemoteException e) { + // There is nothing special we need to do if the service has crashed. + } + } // Detach our existing connection. unbindService(mConnection); mIsBound = false; -- cgit v1.2.3 From a33333b97e810f50db36f345aab71a3200feccc3 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:24:19 +1200 Subject: altosdroid: remove old Binder from TelemetryService Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/TelemetryService.java | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 7d0f7a70..15293b9e 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -22,7 +22,7 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; -import android.os.Binder; +//import android.os.Binder; import android.os.IBinder; import android.util.Log; import android.widget.Toast; @@ -38,16 +38,6 @@ public class TelemetryService extends Service { private static final String TAG = "TelemetryService"; private static final boolean D = true; - /** - * Class for clients to access. Because we know this service always - * runs in the same process as its clients, we don't need to deal with - * IPC. - */ - public class TelemetryBinder extends Binder { - TelemetryService getService() { - return TelemetryService.this; - } - } // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. private int NOTIFICATION = R.string.telemetry_service_label; @@ -106,11 +96,7 @@ public class TelemetryService extends Service { @Override public IBinder onBind(Intent intent) { - return mBinder; } - // This is the object that receives interactions from clients. See - // RemoteService for a more complete example. - private final IBinder mBinder = new TelemetryBinder(); } -- cgit v1.2.3 From 6ffcc82d8d18d3f05d4f5881e50dda298b43c114 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:28:09 +1200 Subject: altosdroid: begin adding IPC to TelemetryService * And add imports for LinkedBlockingQueue... oops! Signed-off-by: Mike Beattie --- .../altusmetrum/AltosDroid/TelemetryService.java | 53 ++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 15293b9e..337aece1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -17,13 +17,20 @@ package org.altusmetrum.AltosDroid; +import java.util.ArrayList; +import java.util.concurrent.LinkedBlockingQueue; + import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; +import android.bluetooth.BluetoothDevice; import android.content.Intent; //import android.os.Binder; import android.os.IBinder; +import android.os.Handler; +import android.os.Message; +import android.os.Messenger; import android.util.Log; import android.widget.Toast; @@ -38,11 +45,17 @@ public class TelemetryService extends Service { private static final String TAG = "TelemetryService"; private static final boolean D = true; + static final int MSG_REGISTER_CLIENT = 1; + static final int MSG_UNREGISTER_CLIENT = 2; + static final int MSG_CONNECT_TELEBT = 3; + // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. private int NOTIFICATION = R.string.telemetry_service_label; private NotificationManager mNM; + ArrayList mClients = new ArrayList(); // Keeps track of all current registered clients. + final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler. // Name of the connected device private String mConnectedDeviceName = null; @@ -50,6 +63,43 @@ public class TelemetryService extends Service { LinkedBlockingQueue telem; + // Handler of incoming messages from clients. + class IncomingHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_REGISTER_CLIENT: + mClients.add(msg.replyTo); + if (D) Log.d(TAG, "Client bound to service"); + break; + case MSG_UNREGISTER_CLIENT: + mClients.remove(msg.replyTo); + if (D) Log.d(TAG, "Client unbound from service"); + break; + case MSG_CONNECT_TELEBT: + if (D) Log.d(TAG, "Connect command received"); + TeleBT_stop(); + TeleBT_start((BluetoothDevice) msg.obj); + break; + default: + super.handleMessage(msg); + } + } + } + + private void TeleBT_stop() { + if (mAltosBluetooth != null) { + mAltosBluetooth.close(); + mAltosBluetooth = null; + } + telem.clear(); + } + + private void TeleBT_start(BluetoothDevice d) { + mAltosBluetooth = new AltosBluetooth(d); + mAltosBluetooth.add_monitor(telem); + } + @Override public void onCreate() { // Create a reference to the NotificationManager so that we can update our notifcation text later @@ -86,6 +136,8 @@ public class TelemetryService extends Service { @Override public void onDestroy() { + // Stop the bluetooth Comms threads + TeleBT_stop(); // Demote us from the foreground, and cancel the persistent notification. stopForeground(true); @@ -96,6 +148,7 @@ public class TelemetryService extends Service { @Override public IBinder onBind(Intent intent) { + return mMessenger.getBinder(); } -- cgit v1.2.3 From 5f4c47389a3d0d10d659a2e00fc74a150b5fed88 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:28:36 +1200 Subject: altosdroid: Add State constants for future usage Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 337aece1..9059ca79 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -49,6 +49,11 @@ public class TelemetryService extends Service { static final int MSG_UNREGISTER_CLIENT = 2; static final int MSG_CONNECT_TELEBT = 3; + public static final int STATE_NONE = 0; + public static final int STATE_READY = 1; + public static final int STATE_CONNECTING = 2; + public static final int STATE_CONNECTED = 3; + // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. private int NOTIFICATION = R.string.telemetry_service_label; -- cgit v1.2.3 From bf7def1a7b93867dfe16fe6499ee028747634c41 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 15:28:58 +1200 Subject: altosdroid: Remove Binder import from TelemetryService Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 9059ca79..2ee7fe58 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -26,7 +26,6 @@ import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothDevice; import android.content.Intent; -//import android.os.Binder; import android.os.IBinder; import android.os.Handler; import android.os.Message; -- cgit v1.2.3 From 54baecc208a40606e3242b2cbd5e66567053646f Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:12:48 +1200 Subject: altosdroid: Convert handlers to use weakreferences * Also renamed bluetooth start/stop methods Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 27 +++++++++++++--------- .../altusmetrum/AltosDroid/TelemetryService.java | 20 +++++++++------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index c1b9c654..d23d504f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -17,6 +17,7 @@ package org.altusmetrum.AltosDroid; +import java.lang.ref.WeakReference; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -85,24 +86,28 @@ public class AltosDroid extends Activity { // The Handler that gets information back from the Telemetry Service - class IncomingHandler extends Handler { + static class IncomingHandler extends Handler { + private final WeakReference mAltosDroid; + IncomingHandler(AltosDroid ad) { mAltosDroid = new WeakReference(ad); } + @Override public void handleMessage(Message msg) { + AltosDroid ad = mAltosDroid.get(); switch (msg.what) { case MSG_STATE_CHANGE: if(D) Log.i(TAG, "MSG_STATE_CHANGE: " + msg.arg1); switch (msg.arg1) { case TelemetryService.STATE_CONNECTED: - mTitle.setText(R.string.title_connected_to); - mTitle.append(mConnectedDeviceName); - mSerialView.setText(""); + ad.mTitle.setText(R.string.title_connected_to); + ad.mTitle.append(ad.mConnectedDeviceName); + ad.mSerialView.setText(""); break; case TelemetryService.STATE_CONNECTING: - mTitle.setText(R.string.title_connecting); + ad.mTitle.setText(R.string.title_connecting); break; case TelemetryService.STATE_READY: case TelemetryService.STATE_NONE: - mTitle.setText(R.string.title_not_connected); + ad.mTitle.setText(R.string.title_not_connected); break; } break; @@ -110,17 +115,17 @@ public class AltosDroid extends Activity { byte[] buf = (byte[]) msg.obj; // construct a string from the buffer String telem = new String(buf); - mSerialView.append(telem); + ad.mSerialView.append(telem); break; case MSG_DEVNAME: // save the connected device's name - mConnectedDeviceName = msg.getData().getString(KEY_DEVNAME); - Toast.makeText(getApplicationContext(), "Connected to " - + mConnectedDeviceName, Toast.LENGTH_SHORT).show(); + ad.mConnectedDeviceName = msg.getData().getString(KEY_DEVNAME); + Toast.makeText(ad.getApplicationContext(), "Connected to " + + ad.mConnectedDeviceName, Toast.LENGTH_SHORT).show(); break; case MSG_TOAST: Toast.makeText( - getApplicationContext(), + ad.getApplicationContext(), msg.getData().getString(KEY_TOAST), Toast.LENGTH_SHORT).show(); break; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 2ee7fe58..1c0e94b3 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -17,6 +17,7 @@ package org.altusmetrum.AltosDroid; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.concurrent.LinkedBlockingQueue; @@ -68,22 +69,25 @@ public class TelemetryService extends Service { LinkedBlockingQueue telem; // Handler of incoming messages from clients. - class IncomingHandler extends Handler { + static class IncomingHandler extends Handler { + private final WeakReference service; + IncomingHandler(TelemetryService s) { service = new WeakReference(s); } + @Override public void handleMessage(Message msg) { + TelemetryService s = service.get(); switch (msg.what) { case MSG_REGISTER_CLIENT: - mClients.add(msg.replyTo); + s.mClients.add(msg.replyTo); if (D) Log.d(TAG, "Client bound to service"); break; case MSG_UNREGISTER_CLIENT: - mClients.remove(msg.replyTo); + s.mClients.remove(msg.replyTo); if (D) Log.d(TAG, "Client unbound from service"); break; case MSG_CONNECT_TELEBT: if (D) Log.d(TAG, "Connect command received"); - TeleBT_stop(); - TeleBT_start((BluetoothDevice) msg.obj); + s.startAltosBluetooth((BluetoothDevice) msg.obj); break; default: super.handleMessage(msg); @@ -91,7 +95,7 @@ public class TelemetryService extends Service { } } - private void TeleBT_stop() { + private void stopAltosBluetooth() { if (mAltosBluetooth != null) { mAltosBluetooth.close(); mAltosBluetooth = null; @@ -99,7 +103,7 @@ public class TelemetryService extends Service { telem.clear(); } - private void TeleBT_start(BluetoothDevice d) { + private void startAltosBluetooth(BluetoothDevice d) { mAltosBluetooth = new AltosBluetooth(d); mAltosBluetooth.add_monitor(telem); } @@ -141,7 +145,7 @@ public class TelemetryService extends Service { public void onDestroy() { // Stop the bluetooth Comms threads - TeleBT_stop(); + stopAltosBluetooth(); // Demote us from the foreground, and cancel the persistent notification. stopForeground(true); -- cgit v1.2.3 From 21359f600354e8ee840e839e61ef97d30f3586fc Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:13:33 +1200 Subject: altosdroid: disable NotificationManager stuff for now Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 1c0e94b3..60500a2c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.concurrent.LinkedBlockingQueue; import android.app.Notification; -import android.app.NotificationManager; +//import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.bluetooth.BluetoothDevice; @@ -57,7 +57,7 @@ public class TelemetryService extends Service { // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. private int NOTIFICATION = R.string.telemetry_service_label; - private NotificationManager mNM; + //private NotificationManager mNM; ArrayList mClients = new ArrayList(); // Keeps track of all current registered clients. final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler. @@ -111,7 +111,7 @@ public class TelemetryService extends Service { @Override public void onCreate() { // Create a reference to the NotificationManager so that we can update our notifcation text later - mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); } @Override -- cgit v1.2.3 From a6373e84393312ed0fbf22285c704819c2011588 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:14:09 +1200 Subject: altosdroid: init telem blocking list.. oops! Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 60500a2c..89c45d6c 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -112,6 +112,8 @@ public class TelemetryService extends Service { public void onCreate() { // Create a reference to the NotificationManager so that we can update our notifcation text later //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + + telem = new LinkedBlockingQueue(); } @Override -- cgit v1.2.3 From 2c5513c51b187ad26a59b193b401f38c35141d27 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:16:04 +1200 Subject: altosdroid: Rename Connect message, add connected message Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 89c45d6c..cf7ae6da 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -47,7 +47,8 @@ public class TelemetryService extends Service { static final int MSG_REGISTER_CLIENT = 1; static final int MSG_UNREGISTER_CLIENT = 2; - static final int MSG_CONNECT_TELEBT = 3; + static final int MSG_CONNECT = 3; + static final int MSG_CONNECTED = 4; public static final int STATE_NONE = 0; public static final int STATE_READY = 1; @@ -85,10 +86,13 @@ public class TelemetryService extends Service { s.mClients.remove(msg.replyTo); if (D) Log.d(TAG, "Client unbound from service"); break; - case MSG_CONNECT_TELEBT: + case MSG_CONNECT: if (D) Log.d(TAG, "Connect command received"); s.startAltosBluetooth((BluetoothDevice) msg.obj); break; + case MSG_CONNECTED: + if (D) Log.d(TAG, "Connected to device"); + break; default: super.handleMessage(msg); } -- cgit v1.2.3 From fe6680dd3b4c31b3d4edc3f06a142f02bcb879df Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:16:49 +1200 Subject: altosdroid: init device variable... oops! Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 6b86a153..c16e3cf5 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -48,7 +48,7 @@ public class AltosBluetooth extends AltosLink { // Constructor public AltosBluetooth(BluetoothDevice in_device) { adapter = BluetoothAdapter.getDefaultAdapter(); - + device = in_device; connect_thread = new ConnectThread(device); connect_thread.start(); -- cgit v1.2.3 From 215d78f06093bd8a8b08a85cae0f1f34aee2a6ec Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:19:06 +1200 Subject: altosdroid: begin adding state support Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/TelemetryService.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index cf7ae6da..6a23dca3 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -66,7 +66,7 @@ public class TelemetryService extends Service { // Name of the connected device private String mConnectedDeviceName = null; private AltosBluetooth mAltosBluetooth = null; - + private int state = STATE_NONE; LinkedBlockingQueue telem; // Handler of incoming messages from clients. @@ -92,6 +92,7 @@ public class TelemetryService extends Service { break; case MSG_CONNECTED: if (D) Log.d(TAG, "Connected to device"); + s.setState(STATE_CONNECTED); break; default: super.handleMessage(msg); @@ -100,6 +101,7 @@ public class TelemetryService extends Service { } private void stopAltosBluetooth() { + setState(STATE_READY); if (mAltosBluetooth != null) { mAltosBluetooth.close(); mAltosBluetooth = null; @@ -110,6 +112,14 @@ public class TelemetryService extends Service { private void startAltosBluetooth(BluetoothDevice d) { mAltosBluetooth = new AltosBluetooth(d); mAltosBluetooth.add_monitor(telem); + setState(STATE_CONNECTING); + } + + private synchronized void setState(int s) { + if (D) Log.d(TAG, "setState() " + state + " -> " + s); + state = s; + + sendMessageToClients(Message.obtain(null, AltosDroid.MSG_STATE_CHANGE, state, -1)); } @Override @@ -118,6 +128,7 @@ public class TelemetryService extends Service { //mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); telem = new LinkedBlockingQueue(); + setState(STATE_READY); } @Override -- cgit v1.2.3 From d7173e814c49826f39bba1ff6b024819c555860c Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:20:01 +1200 Subject: altosdroid: reflect change in message name Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java index d23d504f..b8ddd574 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroid.java @@ -343,7 +343,7 @@ public class AltosDroid extends Activity { //Message msg = Message.obtain(null, TelemetryService.MSG_CONNECT_TELEBT); //msg.obj = device; //mService.send(msg); - mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT_TELEBT, device)); + mService.send(Message.obtain(null, TelemetryService.MSG_CONNECT, device)); } catch (RemoteException e) { e.printStackTrace(); } -- cgit v1.2.3 From a9ec3c96288b7ea4e40586321a0a98edf0c8fee5 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:23:33 +1200 Subject: altosdroid: Need access to handler inside AltosBluetooth * Also move add_monitor() call Signed-off-by: Mike Beattie --- altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java | 6 +++++- altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index c16e3cf5..3bfa3488 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -26,6 +26,7 @@ import java.util.UUID; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; +import android.os.Handler; import android.util.Log; import org.altusmetrum.AltosLib.*; @@ -39,6 +40,8 @@ public class AltosBluetooth extends AltosLink { private ConnectThread connect_thread = null; private Thread input_thread = null; + private Handler handler; + private BluetoothAdapter adapter; private BluetoothDevice device; private BluetoothSocket socket; @@ -46,9 +49,10 @@ public class AltosBluetooth extends AltosLink { private OutputStream output; // Constructor - public AltosBluetooth(BluetoothDevice in_device) { + public AltosBluetooth(BluetoothDevice in_device, Handler in_handler) { adapter = BluetoothAdapter.getDefaultAdapter(); device = in_device; + handler = in_handler; connect_thread = new ConnectThread(device); connect_thread.start(); diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 6a23dca3..1903cc1d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -61,7 +61,8 @@ public class TelemetryService extends Service { //private NotificationManager mNM; ArrayList mClients = new ArrayList(); // Keeps track of all current registered clients. - final Messenger mMessenger = new Messenger(new IncomingHandler()); // Target we publish for clients to send messages to IncomingHandler. + final Handler mHandler = new IncomingHandler(this); + final Messenger mMessenger = new Messenger(mHandler); // Target we publish for clients to send messages to IncomingHandler. // Name of the connected device private String mConnectedDeviceName = null; @@ -93,6 +94,7 @@ public class TelemetryService extends Service { case MSG_CONNECTED: if (D) Log.d(TAG, "Connected to device"); s.setState(STATE_CONNECTED); + s.mAltosBluetooth.add_monitor(s.telem); break; default: super.handleMessage(msg); @@ -110,8 +112,7 @@ public class TelemetryService extends Service { } private void startAltosBluetooth(BluetoothDevice d) { - mAltosBluetooth = new AltosBluetooth(d); - mAltosBluetooth.add_monitor(telem); + mAltosBluetooth = new AltosBluetooth(d, mHandler); setState(STATE_CONNECTING); } -- cgit v1.2.3 From 31bffa435cec2098c7ab5c42c829ba6e1578b5d2 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:24:13 +1200 Subject: altosdroid: need sendMessageToClients() for setState().. oops! Signed-off-by: Mike Beattie --- .../src/org/altusmetrum/AltosDroid/TelemetryService.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 1903cc1d..9c2fde97 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -102,6 +102,16 @@ public class TelemetryService extends Service { } } + private void sendMessageToClients(Message m) { + for (int i=mClients.size()-1; i>=0; i--) { + try { + mClients.get(i).send(m); + } catch (RemoteException e) { + mClients.remove(i); + } + } + } + private void stopAltosBluetooth() { setState(STATE_READY); if (mAltosBluetooth != null) { -- cgit v1.2.3 From 3d6fc5fe462531e05ca4b9be1a421490e067a28b Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:26:58 +1200 Subject: altosdroid: lots of debugging statements Signed-off-by: Mike Beattie --- .../org/altusmetrum/AltosDroid/AltosBluetooth.java | 22 +++++++++++++++++----- .../altusmetrum/AltosDroid/TelemetryService.java | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java index 3bfa3488..3071c8f1 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosBluetooth.java @@ -76,7 +76,7 @@ public class AltosBluetooth extends AltosLink { } public void run() { - if (D) Log.i(TAG, "BEGIN ConnectThread"); + if (D) Log.i(TAG, "ConnectThread: BEGIN"); setName("ConnectThread"); // Always cancel discovery because it will slow down a connection @@ -123,28 +123,31 @@ public class AltosBluetooth extends AltosLink { if (socket != null) socket.close(); } catch (IOException e) { - if (D) Log.e(TAG, "close() of connect socket failed", e); + if (D) Log.e(TAG, "ConnectThread: close() of connect socket failed", e); } } } private synchronized void wait_connected() throws InterruptedException { + if (D) Log.i(TAG, "wait_connected(): begin"); if (input == null) { + if (D) Log.i(TAG, "wait_connected(): waiting"); wait(); + if (D) Log.i(TAG, "wait_connected(): wait ended.."); } } private void connection_failed() { - if (D) Log.i(TAG, "Bluetooth Connection failed!"); + if (D) Log.e(TAG, "Bluetooth Socket IO failed!"); } public void print(String data) { byte[] bytes = data.getBytes(); + if (D) Log.i(TAG, "print(): begin"); try { - if (D) Log.i(TAG, "Entering print();"); wait_connected(); output.write(bytes); - if (D) Log.i(TAG, "Writing bytes: '" + data + "'"); + if (D) Log.i(TAG, "print(): Wrote bytes: '" + data.replace('\n', '\\') + "'"); } catch (IOException e) { connection_failed(); } catch (InterruptedException e) { @@ -153,8 +156,10 @@ public class AltosBluetooth extends AltosLink { } public int getchar() { + if (D) Log.i(TAG, "getchar(): begin"); try { wait_connected(); + if (D) Log.i(TAG, "getchar(): proceeding"); return input.read(); } catch (IOException e) { connection_failed(); @@ -165,14 +170,21 @@ public class AltosBluetooth extends AltosLink { } public void close() { + if (D) Log.i(TAG, "close(): begin"); synchronized(this) { + if (D) Log.i(TAG, "close(): synched"); + if (connect_thread != null) { + if (D) Log.i(TAG, "close(): stopping connect_thread"); connect_thread.cancel(); connect_thread = null; } if (input_thread != null) { + if (D) Log.i(TAG, "close(): stopping input_thread"); try { + if (D) Log.i(TAG, "close(): input_thread.interrupt()....."); input_thread.interrupt(); + if (D) Log.i(TAG, "close(): input_thread.join()....."); input_thread.join(); } catch (Exception e) {} input_thread = null; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java index 9c2fde97..a61a1eda 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/TelemetryService.java @@ -113,8 +113,10 @@ public class TelemetryService extends Service { } private void stopAltosBluetooth() { + if (D) Log.i(TAG, "Stopping BT"); setState(STATE_READY); if (mAltosBluetooth != null) { + if (D) Log.i(TAG, "Closing AltosBluetooth"); mAltosBluetooth.close(); mAltosBluetooth = null; } @@ -122,6 +124,7 @@ public class TelemetryService extends Service { } private void startAltosBluetooth(BluetoothDevice d) { + if (D) Log.i(TAG, "Connecting to " + d.getName()); mAltosBluetooth = new AltosBluetooth(d, mHandler); setState(STATE_CONNECTING); } -- cgit v1.2.3 From d40f96fcc961cfbf6af67fc84591d2660d065ca0 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 26 Aug 2012 23:28:26 +1200 Subject: altosdroid: Strings and Layout changes Signed-off-by: Mike Beattie --- altosdroid/res/layout/main.xml | 22 +--------------------- altosdroid/res/values/strings.xml | 12 +++++------- .../src/org/altusmetrum/AltosDroid/AltosDroid.java | 2 +- 3 files changed, 7 insertions(+), 29 deletions(-) diff --git a/altosdroid/res/layout/main.xml b/altosdroid/res/layout/main.xml index 070928a5..00ca63c8 100644 --- a/altosdroid/res/layout/main.xml +++ b/altosdroid/res/layout/main.xml @@ -23,31 +23,11 @@ - - - - -